From 98d97158092c768b2aaa34e4156421ddd93ec6e7 Mon Sep 17 00:00:00 2001 From: Lily Shen <115414357+lilyshen0722@users.noreply.github.com> Date: Mon, 26 Oct 2026 00:18:12 -0700 Subject: [PATCH 1/3] fix(cli): ship the webhook SDK in the package, read it from there (TASK-300) agent init copied commonly.py and bot.py from a repo-relative path that the npm package does not ship, so it only worked from a git clone. prepack now copies both from examples/ into cli/assets/webhook-sdk/, and init reads the packaged copy, falling back to examples/ in a clone that has not packed yet. Verified from a packed tarball: npm pack includes assets/webhook-sdk/python/*, and performInit run from the extracted package writes commonly.py and the bot with examples/ absent. sdk-bundle.test.mjs pins the bundled copies byte-equal to the source. Written by sprint-impl, a Commonly agent. Co-Authored-By: Claude Haiku 5.5 Co-authored-by: sprint-impl Agent-Model: claude/claude-haiku-5-5/default --- .gitignore | 3 +++ cli/__tests__/sdk-bundle.test.mjs | 31 +++++++++++++++++++++++++++++ cli/package-lock.json | 4 ++-- cli/package.json | 5 +++-- cli/scripts/bundle-sdk-examples.mjs | 20 +++++++++++++++++++ cli/src/commands/agent.js | 21 +++++++++---------- 6 files changed, 70 insertions(+), 14 deletions(-) create mode 100644 cli/__tests__/sdk-bundle.test.mjs create mode 100644 cli/scripts/bundle-sdk-examples.mjs diff --git a/.gitignore b/.gitignore index b0c8178eba..ff4f0c8bc9 100644 --- a/.gitignore +++ b/.gitignore @@ -61,3 +61,6 @@ frontend/.env.production.local # Playwright browser state (may contain session tokens) state.json __pycache__ + +# Generated by cli/scripts/bundle-sdk-examples.mjs at prepack +cli/assets/ diff --git a/cli/__tests__/sdk-bundle.test.mjs b/cli/__tests__/sdk-bundle.test.mjs new file mode 100644 index 0000000000..b9f6fed47f --- /dev/null +++ b/cli/__tests__/sdk-bundle.test.mjs @@ -0,0 +1,31 @@ +/** + * sdk-bundle.test.mjs — TASK-300. The npm package must ship the webhook SDK and + * bot that `agent init` copies. prepack runs bundle-sdk-examples.mjs, which + * copies them from examples/ into assets/. This pins that the bundled copies are + * byte-identical to the source, so the package cannot carry a stale SDK. + */ + +import { beforeAll, describe, expect, it } from '@jest/globals'; +import { execFileSync } from 'child_process'; +import fs from 'fs'; +import path from 'path'; + +const CLI_ROOT = path.resolve(path.dirname(new URL(import.meta.url).pathname), '..'); +const REPO_ROOT = path.resolve(CLI_ROOT, '..'); + +const PAIRS = [ + [path.join(REPO_ROOT, 'examples', 'sdk', 'python', 'commonly.py'), path.join('python', 'commonly.py')], + [path.join(REPO_ROOT, 'examples', 'hello-world-python', 'bot.py'), path.join('python', 'bot.py')], +]; + +describe('bundled webhook SDK (TASK-300)', () => { + beforeAll(() => { + execFileSync(process.execPath, [path.join(CLI_ROOT, 'scripts', 'bundle-sdk-examples.mjs')]); + }); + + it.each(PAIRS)('ships %s byte-identical to the examples/ source', (src, rel) => { + const bundled = path.join(CLI_ROOT, 'assets', 'webhook-sdk', rel); + expect(fs.existsSync(bundled)).toBe(true); + expect(fs.readFileSync(bundled).equals(fs.readFileSync(src))).toBe(true); + }); +}); diff --git a/cli/package-lock.json b/cli/package-lock.json index bf644e7f0c..c8291d31db 100644 --- a/cli/package-lock.json +++ b/cli/package-lock.json @@ -1,12 +1,12 @@ { "name": "@commonlyai/cli", - "version": "0.1.168", + "version": "0.1.186", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@commonlyai/cli", - "version": "0.1.168", + "version": "0.1.186", "bundleDependencies": [ "@commonlyai/seats" ], diff --git a/cli/package.json b/cli/package.json index fc5a0e3441..d64f56ff5e 100644 --- a/cli/package.json +++ b/cli/package.json @@ -1,6 +1,6 @@ { "name": "@commonlyai/cli", - "version": "0.1.168", + "version": "0.1.186", "license": "Apache-2.0", "description": "The Commonly CLI — connect agents, manage pods, iterate fast", "type": "module", @@ -10,6 +10,7 @@ }, "files": [ "src", + "assets", "README.md", "skills" ], @@ -32,7 +33,7 @@ "lint:fix": "eslint src --ext .js --fix", "test": "node --experimental-vm-modules node_modules/.bin/jest", "test:temp-cleanup": "node scripts/verify-temp-cleanup.mjs", - "prepack": "node scripts/require-bundled-seats.mjs", + "prepack": "node scripts/require-bundled-seats.mjs && node scripts/bundle-sdk-examples.mjs", "prepublishOnly": "node -e \"require('fs').copyFileSync('../docs/agents/skills/commonly/SKILL.md','skills/commonly/SKILL.md')\"" }, "dependencies": { diff --git a/cli/scripts/bundle-sdk-examples.mjs b/cli/scripts/bundle-sdk-examples.mjs new file mode 100644 index 0000000000..5e61e40e29 --- /dev/null +++ b/cli/scripts/bundle-sdk-examples.mjs @@ -0,0 +1,20 @@ +// prepack: copy the webhook SDK and the hello-world bot out of examples/ into +// cli/assets/webhook-sdk/ so the published package ships them. agent init reads +// them from the package. The copies are generated and gitignored; examples/ +// stays the source of truth. +import { copyFileSync, mkdirSync } from 'fs'; +import { dirname, join, resolve } from 'path'; +import { fileURLToPath } from 'url'; + +const cliRoot = resolve(dirname(fileURLToPath(import.meta.url)), '..'); +const repoRoot = resolve(cliRoot, '..'); +const bundles = [ + [join(repoRoot, 'examples', 'sdk', 'python', 'commonly.py'), join('python', 'commonly.py')], + [join(repoRoot, 'examples', 'hello-world-python', 'bot.py'), join('python', 'bot.py')], +]; + +for (const [src, rel] of bundles) { + const dest = join(cliRoot, 'assets', 'webhook-sdk', rel); + mkdirSync(dirname(dest), { recursive: true }); + copyFileSync(src, dest); +} diff --git a/cli/src/commands/agent.js b/cli/src/commands/agent.js index 15004bee07..fb470e48cc 100644 --- a/cli/src/commands/agent.js +++ b/cli/src/commands/agent.js @@ -3298,19 +3298,20 @@ const SUPPORTED_LANGUAGES = ['python']; // three levels up. The scaffolder copies the canonical SDK file from the repo // into the user's cwd; ADR-006 §SDK lives = "live-copy, not dependency". // -// Removal condition: ADR-006 §Migration path Phase 4 — when the CLI is -// published as `@commonlyai/cli` on npm, the example files won't sit at a -// repo-relative path; we'll need to bundle them into the package at build -// time and resolve via `import.meta.resolve` or a packaged-data lookup. -// Until that phase, repo-relative is the simplest correct answer. -const repoFile = (...parts) => pathResolve( - dirname(fileURLToPath(import.meta.url)), '..', '..', '..', ...parts, -); +// The published package carries these files under cli/assets/webhook-sdk/, +// bundled from examples/ by scripts/bundle-sdk-examples.mjs at prepack (npm +// pack and publish run it). A repo clone that has not packed yet falls back to +// the examples/ tree, which stays the single source of truth. +const cliRoot = pathResolve(dirname(fileURLToPath(import.meta.url)), '..', '..'); +const sdkAsset = (bundledRel, repoRel) => { + const bundled = pathResolve(cliRoot, 'assets', 'webhook-sdk', bundledRel); + return existsSync(bundled) ? bundled : pathResolve(cliRoot, '..', 'examples', repoRel); +}; const SDK_SOURCES = { python: { - sdkSrc: () => repoFile('examples', 'sdk', 'python', 'commonly.py'), - botSrc: () => repoFile('examples', 'hello-world-python', 'bot.py'), + sdkSrc: () => sdkAsset('python/commonly.py', join('sdk', 'python', 'commonly.py')), + botSrc: () => sdkAsset('python/bot.py', join('hello-world-python', 'bot.py')), sdkOut: 'commonly.py', botOut: (name) => `${name}.py`, runHint: (name) => `COMMONLY_TOKEN=$(cat .commonly-env) python3 ${name}.py`, From 945f75e86aae6ab990c7288d77252a67dcfeb9ee Mon Sep 17 00:00:00 2001 From: Lily Shen <115414357+lilyshen0722@users.noreply.github.com> Date: Mon, 26 Oct 2026 04:52:50 -0700 Subject: [PATCH 2/3] fix(cli): restore package.json version to main's line (TASK-466 publish assigns the version) Co-Authored-By: Claude Haiku 5.5 Co-authored-by: sprint-impl Agent-Model: claude/claude-haiku-5-5/default --- cli/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cli/package.json b/cli/package.json index d64f56ff5e..b10716dd97 100644 --- a/cli/package.json +++ b/cli/package.json @@ -1,6 +1,6 @@ { "name": "@commonlyai/cli", - "version": "0.1.186", + "version": "0.1.168", "license": "Apache-2.0", "description": "The Commonly CLI — connect agents, manage pods, iterate fast", "type": "module", From a5fa4e1cfbcb01671ecaf7a594247243190dd3be Mon Sep 17 00:00:00 2001 From: Lily Shen <115414357+lilyshen0722@users.noreply.github.com> Date: Mon, 26 Oct 2026 04:54:16 -0700 Subject: [PATCH 3/3] fix(cli): restore package-lock.json version to main's line (TASK-466 publish assigns the version) Co-Authored-By: Claude Haiku 5.5 Co-authored-by: sprint-impl Agent-Model: claude/claude-haiku-5-5/default --- cli/package-lock.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cli/package-lock.json b/cli/package-lock.json index c8291d31db..bf644e7f0c 100644 --- a/cli/package-lock.json +++ b/cli/package-lock.json @@ -1,12 +1,12 @@ { "name": "@commonlyai/cli", - "version": "0.1.186", + "version": "0.1.168", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@commonlyai/cli", - "version": "0.1.186", + "version": "0.1.168", "bundleDependencies": [ "@commonlyai/seats" ],