openpond 0.0.31 → 0.0.32

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (115) hide show
  1. package/dist/chunks/{app-layer-53U5JVE7.js → app-layer-CUQQUVJS.js} +3 -3
  2. package/dist/chunks/{apps-MJ47WJNC.js → apps-TAYMUCWX.js} +3 -3
  3. package/dist/chunks/{chunk-DZUJ6XJC.js → chunk-3UOLQG6N.js} +1 -1
  4. package/dist/chunks/{chunk-4GLUNJLZ.js → chunk-3ZJIEA5F.js} +1 -1
  5. package/dist/chunks/{chunk-WQ2GF7XT.js → chunk-4HQURM3N.js} +1 -1
  6. package/dist/chunks/{chunk-ZIKHE5AY.js → chunk-4M4WAORL.js} +874 -798
  7. package/dist/chunks/{chunk-7KYOO25A.js → chunk-5RHZKQRK.js} +14 -76
  8. package/dist/chunks/{chunk-NC2GQQOT.js → chunk-D264OHTR.js} +4 -5
  9. package/dist/chunks/{chunk-XMW3PSI5.js → chunk-DCNAXREU.js} +179 -160
  10. package/dist/chunks/chunk-E5RVRUJB.js +1222 -0
  11. package/dist/chunks/{chunk-5X47XJC4.js → chunk-EONKWOLU.js} +2 -2
  12. package/dist/chunks/{chunk-VQX33YAG.js → chunk-FQW3AQVJ.js} +689 -121
  13. package/dist/chunks/{chunk-TQRWG54R.js → chunk-GYZYZGKS.js} +238 -69
  14. package/dist/chunks/{chunk-7HZBKUUB.js → chunk-OXQG773T.js} +33 -33
  15. package/dist/chunks/{chunk-BX4XSB2J.js → chunk-PJXJ2HRT.js} +1816 -1113
  16. package/dist/chunks/chunk-Q5MZCRJA.js +70 -0
  17. package/dist/chunks/{chunk-ETBF62DB.js → chunk-W2DJR3FA.js} +1 -1
  18. package/dist/chunks/{chunk-JWL5HCO5.js → chunk-XADW35CL.js} +3 -3
  19. package/dist/chunks/{chunk-IUTUUNAX.js → chunk-Y4F4XD5V.js} +1 -1
  20. package/dist/chunks/{cli-EP473A53.js → cli-WW5BVN5Z.js} +4 -3
  21. package/dist/chunks/{cli-H7PQLPKG.js → cli-ZOCP7X5M.js} +6 -6
  22. package/dist/chunks/{core-commands-KI53GSJF.js → core-commands-SYGK7K57.js} +4 -4
  23. package/dist/chunks/{extend-F4R3AI2G.js → extend-Q5HZ7TMA.js} +11 -11
  24. package/dist/chunks/fileFromPath-DHCRY3BD.js +2151 -0
  25. package/dist/chunks/{harness-WADDUNGU.js → harness-ZPBPQVAS.js} +3 -3
  26. package/dist/chunks/{help-TIEOIVOA.js → help-3V3TRQNX.js} +1 -1
  27. package/dist/chunks/{opchat-VYKKXDBO.js → opchat-OUPMEFE5.js} +5 -5
  28. package/dist/chunks/{organizations-LAACUOYE.js → organizations-5CSLBDAW.js} +4 -4
  29. package/dist/chunks/{profile-A75O7EZ4.js → profile-OQYSXHOG.js} +206 -166
  30. package/dist/chunks/{project-agent-JOZ6NRTW.js → project-agent-TBTWOUJF.js} +6 -7
  31. package/dist/chunks/{sandbox-command-Q72CAVQ7.js → sandbox-command-HCHPY7KW.js} +4 -4
  32. package/dist/chunks/{sandbox-template-KWCE3OJV.js → sandbox-template-PNTOZ6W3.js} +5 -6
  33. package/dist/chunks/{src-CBPRIWG5.js → src-C6MXLDYQ.js} +22 -6
  34. package/dist/chunks/{src-J4262EAE.js → src-GZT4UX6I.js} +81183 -53344
  35. package/dist/chunks/{teams-bot-KNY5OEXB.js → teams-bot-CQ76XI6T.js} +3 -3
  36. package/dist/chunks/workspaces-DHVVOTVR.js +93 -0
  37. package/dist/cli.js +10 -10
  38. package/dist/config.d.ts +0 -2
  39. package/dist/index.js +273 -69
  40. package/dist/profile/local-profile-types.d.ts +8 -2
  41. package/dist/profile/local-profile.d.ts +3 -1
  42. package/dist/sandbox/types/org-project-agent.d.ts +1 -2
  43. package/dist/web/assets/{AppsView-Bu-Nc3Ew.js → AppsView-CF2g-7FH.js} +1 -1
  44. package/dist/web/assets/{BrowserSidebar-CCguQ-DR.js → BrowserSidebar-lUsLUl20.js} +1 -1
  45. package/dist/web/assets/CloudWorkView-BnfGW4OV.js +1 -0
  46. package/dist/web/assets/{CommandMenu-CnodJFHD.js → CommandMenu-BsS4Bgb6.js} +1 -1
  47. package/dist/web/assets/{CommunityView-CIbjNUZr.js → CommunityView-C8qVOwlp.js} +1 -1
  48. package/dist/web/assets/ComposerCreateImproveStrip-C_LIpfSq.js +1 -0
  49. package/dist/web/assets/GetStartedView-Du533wOh.js +1 -0
  50. package/dist/web/assets/LabsRoute-CgKtVYTP.css +1 -0
  51. package/dist/web/assets/LabsRoute-yk8lNMQc.js +3 -0
  52. package/dist/web/assets/{NewProjectDialog-CaKiCoVS.js → NewProjectDialog-DH7wA1z9.js} +1 -1
  53. package/dist/web/assets/ProfileSettingsSection-CqnfjiCl.css +1 -0
  54. package/dist/web/assets/ProfileSettingsSection-D7JvMZdW.js +1 -0
  55. package/dist/web/assets/SettingsView-C9TgCaWG.js +63 -0
  56. package/dist/web/assets/TeamChatView-D_CE7br9.js +3 -0
  57. package/dist/web/assets/{TerminalOverlay-C1iP4OS1.js → TerminalOverlay-CC-VDSlp.js} +1 -1
  58. package/dist/web/assets/TrainingCreationPanel-NFCoaBUI.js +1 -0
  59. package/dist/web/assets/TrainingDraftPanel-BWEmVFjM.js +1 -0
  60. package/dist/web/assets/WorkspaceDiffPanel-SlLlGZM1.js +14 -0
  61. package/dist/web/assets/{WorkspaceEnvironmentMenu-B8JJbwIz.js → WorkspaceEnvironmentMenu-BAoMBTVD.js} +1 -1
  62. package/dist/web/assets/{WorkspaceGitDialogs-B4sp9BGn.js → WorkspaceGitDialogs-CVIFrzyl.js} +1 -1
  63. package/dist/web/assets/{WorkspaceMonacoEditor-BBqimG5X.js → WorkspaceMonacoEditor-0trp0-TI.js} +3 -3
  64. package/dist/web/assets/{boxes-DAaDUabq.js → boxes-CFihgX2z.js} +1 -1
  65. package/dist/web/assets/create-pipeline-request-AJWLMTyw.js +4 -0
  66. package/dist/web/assets/{cssMode-CBF1mieJ.js → cssMode-HvqfCFyP.js} +1 -1
  67. package/dist/web/assets/{git-commit-horizontal-CAickXpN.js → git-commit-horizontal-C5mUmACv.js} +1 -1
  68. package/dist/web/assets/{htmlMode-2u8OHtWO.js → htmlMode-C8btgUt-.js} +1 -1
  69. package/dist/web/assets/index-8H-GDlM5.css +1 -0
  70. package/dist/web/assets/index-D7Vr3zcV.js +192 -0
  71. package/dist/web/assets/index-DUqAiF57.js +1 -0
  72. package/dist/web/assets/{info-CQNTh78o.js → info-D0xuy5IB.js} +1 -1
  73. package/dist/web/assets/{jsonMode-C4CWXViX.js → jsonMode-5zVz9G0X.js} +1 -1
  74. package/dist/web/assets/{lspLanguageFeatures-CBs_BOlB.js → lspLanguageFeatures-DxlSSL7c.js} +1 -1
  75. package/dist/web/assets/{monaco.contribution-lOXpG2xQ.js → monaco.contribution-B1pWWwqT.js} +2 -2
  76. package/dist/web/assets/{monaco.contribution-sd3cFkcN.js → monaco.contribution-BKpVvKK9.js} +2 -2
  77. package/dist/web/assets/{monaco.contribution-C1LUxAKf.js → monaco.contribution-BXdXsSWI.js} +2 -2
  78. package/dist/web/assets/{monaco.contribution-Cpf6dWsh.js → monaco.contribution-CIjjzpUR.js} +2 -2
  79. package/dist/web/assets/{monitor-DsIswrMV.js → monitor-B4-9Shtp.js} +1 -1
  80. package/dist/web/assets/{play-CeRw21NV.js → play-BJdhBqQE.js} +1 -1
  81. package/dist/web/assets/{python-CXYq3BUl.js → python-CEK8J4w_.js} +1 -1
  82. package/dist/web/assets/{refresh-cw-N5b_6AP5.js → refresh-cw-DE0u_nmZ.js} +1 -1
  83. package/dist/web/assets/{reply-BSKjZrJg.js → reply-2MfLJ93n.js} +1 -1
  84. package/dist/web/assets/{save-D0oHH1a3.js → save-CBIVKaf8.js} +1 -1
  85. package/dist/web/assets/{toggleHighContrast-DRjlcwes.js → toggleHighContrast-CC73mtvA.js} +1 -1
  86. package/dist/web/assets/training-BY8siNUK.css +1 -0
  87. package/dist/web/assets/training-model-data-BXUCzS0p.js +1 -0
  88. package/dist/web/assets/{tsMode-x-1A7ZcB.js → tsMode-Bhn9wr_1.js} +1 -1
  89. package/dist/web/assets/{wifi-off-Dt52ofzh.js → wifi-off-BKTqnqj0.js} +1 -1
  90. package/dist/web/assets/{workers-Ciff6Dzi.js → workers-C_adgrEg.js} +1 -1
  91. package/dist/web/assets/{yaml-CB67Kxnz.js → yaml-DDRAcADU.js} +1 -1
  92. package/dist/web/index.html +2 -2
  93. package/package.json +1 -1
  94. package/dist/chunks/chunk-OG75GMVO.js +0 -1
  95. package/dist/web/assets/CloudWorkView-Dr3xqLE5.js +0 -1
  96. package/dist/web/assets/GetStartedView-C8nyH_PT.js +0 -1
  97. package/dist/web/assets/LabsExtensions-GtJzxDnK.js +0 -1
  98. package/dist/web/assets/LabsProfile-DG7rWYur.js +0 -1
  99. package/dist/web/assets/LabsRoute-D6MDHBzq.js +0 -2
  100. package/dist/web/assets/LabsRoute-TEt9j1vB.css +0 -1
  101. package/dist/web/assets/LabsSignals-BfsDN86w.js +0 -1
  102. package/dist/web/assets/LabsSignals-D6iA6Ryl.css +0 -1
  103. package/dist/web/assets/ProfileSettingsSection-DTQS2DVL.css +0 -1
  104. package/dist/web/assets/ProfileSettingsSection-DxEzoF3K.js +0 -1
  105. package/dist/web/assets/ProfileView-CEscW7Ru.js +0 -1
  106. package/dist/web/assets/SettingsView-JIRR_FO4.js +0 -63
  107. package/dist/web/assets/TeamChatView-B5M1ThhJ.js +0 -3
  108. package/dist/web/assets/TrainingSettingsSection-BDYvI2te.js +0 -1
  109. package/dist/web/assets/TrainingView-CoCFK6W3.js +0 -5
  110. package/dist/web/assets/WorkspaceDiffPanel-CMxKQeo7.js +0 -14
  111. package/dist/web/assets/index-BdY6A-YN.css +0 -1
  112. package/dist/web/assets/index-CU2qhUYV.js +0 -195
  113. package/dist/web/assets/index-Dz2B3-4C.js +0 -1
  114. package/dist/web/assets/settings-lists-BEg6LMcy.css +0 -1
  115. package/dist/web/assets/training-model-data-BPrc68VG.js +0 -1
@@ -3,10 +3,10 @@ import {
3
3
  materializeSourceUploadFile,
4
4
  readSourceUploadCache,
5
5
  writeSourceUploadCache
6
- } from "./chunk-WQ2GF7XT.js";
6
+ } from "./chunk-4HQURM3N.js";
7
7
  import {
8
- CreatePipelineRequestSchema
9
- } from "./chunk-VQX33YAG.js";
8
+ CreateImproveRunSchema
9
+ } from "./chunk-FQW3AQVJ.js";
10
10
  import {
11
11
  formatSandboxTemplateDiagnostics,
12
12
  validateSandboxTemplateYaml
@@ -17,8 +17,8 @@ import {
17
17
  import {
18
18
  parseSandboxRuntimePromotionPolicyOption,
19
19
  parseSandboxWorkflowModeOption,
20
- runCommand
21
- } from "./chunk-NC2GQQOT.js";
20
+ runProcessCommand
21
+ } from "./chunk-D264OHTR.js";
22
22
  import {
23
23
  optionString,
24
24
  optionalJsonObject,
@@ -26,9 +26,9 @@ import {
26
26
  parseCsvOption,
27
27
  parseIntegerOption,
28
28
  requiredTeamId
29
- } from "./chunk-7HZBKUUB.js";
29
+ } from "./chunk-OXQG773T.js";
30
30
 
31
- // src/cli/agent-sdk-command.ts
31
+ // ../../packages/cloud/src/profile/agent-sdk-command.ts
32
32
  import { existsSync, readFileSync } from "node:fs";
33
33
  import { createRequire } from "node:module";
34
34
  import path from "node:path";
@@ -79,890 +79,926 @@ function nodeTypescriptCommand(packageRoot, sourceCli) {
79
79
  return { command: process.execPath, args: [tsxCli, sourceCli] };
80
80
  }
81
81
 
82
- // src/cli/project-source-upload.ts
82
+ // ../../packages/cloud/src/profile/project-source-upload.ts
83
83
  import { Buffer } from "node:buffer";
84
+ import { existsSync as existsSync4, promises as fs2 } from "node:fs";
85
+ import path4 from "node:path";
86
+
87
+ // ../../packages/cloud/src/profile/project-source-upload-agent-sdk.ts
84
88
  import { createHash } from "node:crypto";
85
- import { existsSync as existsSync2, promises as fs, readFileSync as readFileSync2, statSync } from "node:fs";
89
+ import { existsSync as existsSync3, promises as fs, readFileSync as readFileSync2, statSync } from "node:fs";
86
90
  import { tmpdir } from "node:os";
87
- import path2 from "node:path";
91
+ import path3 from "node:path";
88
92
  import { gunzipSync } from "node:zlib";
89
- var PROJECT_SOURCE_UPLOAD_MAX_FILES = 1500;
90
- var PROJECT_SOURCE_UPLOAD_MAX_FILE_BYTES = 8 * 1024 * 1024;
91
- var PROJECT_SOURCE_UPLOAD_MAX_BYTES = 100 * 1024 * 1024;
92
- var PROJECT_SOURCE_UPLOAD_CONCURRENCY = 8;
93
- var PROJECT_SOURCE_UPLOAD_LIMITS = {
94
- maxFiles: PROJECT_SOURCE_UPLOAD_MAX_FILES,
95
- maxFileBytes: PROJECT_SOURCE_UPLOAD_MAX_FILE_BYTES,
96
- maxTotalBytes: PROJECT_SOURCE_UPLOAD_MAX_BYTES,
97
- concurrency: PROJECT_SOURCE_UPLOAD_CONCURRENCY
98
- };
99
- var PROJECT_SOURCE_UPLOAD_TRANSPORT = {
100
- mode: "single_json_payload",
101
- chunkingSupported: false
102
- };
93
+
94
+ // ../../packages/cloud/src/profile/project-source-upload-bun-compat.ts
95
+ import { existsSync as existsSync2 } from "node:fs";
96
+ import path2 from "node:path";
97
+ function detectAgentSdkPackageManager(projectPath, packageJson) {
98
+ const packageManager = packageJson.packageManager;
99
+ if (typeof packageManager === "string") {
100
+ const name = packageManager.split("@")[0];
101
+ if (name === "bun" || name === "npm" || name === "pnpm" || name === "yarn") {
102
+ return name;
103
+ }
104
+ }
105
+ if (existsSync2(path2.join(projectPath, "bun.lock")) || existsSync2(path2.join(projectPath, "bun.lockb"))) {
106
+ return "bun";
107
+ }
108
+ if (existsSync2(path2.join(projectPath, "pnpm-lock.yaml"))) return "pnpm";
109
+ if (existsSync2(path2.join(projectPath, "yarn.lock"))) return "yarn";
110
+ if (existsSync2(path2.join(projectPath, "package-lock.json")) || existsSync2(path2.join(projectPath, "npm-shrinkwrap.json"))) {
111
+ return "npm";
112
+ }
113
+ return "unknown";
114
+ }
115
+ function agentSdkDependencyInstallCommand(packageManager) {
116
+ if (packageManager === "npm") return "npm install --offline";
117
+ if (packageManager === "pnpm") return "pnpm install --offline";
118
+ if (packageManager === "yarn") return "yarn install --offline";
119
+ if (packageManager === "bun") return "bun install --offline";
120
+ return "pnpm install --offline";
121
+ }
122
+ function agentSdkRunScriptCommand(packageManager, scriptName) {
123
+ if (packageManager === "pnpm") return `pnpm run ${scriptName}`;
124
+ if (packageManager === "yarn") return `yarn ${scriptName}`;
125
+ if (packageManager === "npm") return `npm run ${scriptName}`;
126
+ if (packageManager === "bun") return `bun run ${scriptName}`;
127
+ return `pnpm run ${scriptName}`;
128
+ }
129
+
130
+ // ../../packages/cloud/src/profile/project-source-upload-agent-sdk.ts
103
131
  var OPENPOND_PNPM_PACKAGE_MANAGER = "pnpm@11.13.0";
104
- var AGENT_SDK_SOURCE_UPLOAD_METADATA_PATH = ".openpond/source-upload-metadata.json";
105
132
  var AGENT_SDK_VENDOR_TARBALL_PATH = ".openpond/vendor/openpond-agent-sdk.tgz";
106
133
  var AGENT_SDK_VENDOR_NPM_DEPENDENCY_DIR = ".openpond/vendor/npm";
107
134
  var AGENT_SDK_MATERIALIZED_DEPENDENCY_SPEC = `file:${AGENT_SDK_VENDOR_TARBALL_PATH}`;
108
135
  var AGENT_SDK_SYNTHESIZED_OPENPOND_YAML_SENTINEL = "# openpond-agent-sdk-source-upload: synthesized-openpond-yaml";
109
- var AGENT_SDK_GENERATED_SKILLS_DIR = ".openpond/skills";
110
- var AGENT_SDK_GENERATED_ARTIFACTS = [
111
- ".openpond/agent-inspect.json",
112
- ".openpond/agent-manifest.json",
113
- ".openpond/action-registry.json",
114
- ".openpond/openpond-manifest.preview.yaml",
115
- ".openpond/runtime-bridge.mjs",
116
- ".openpond/validator-report.md"
117
- ];
118
- function isSafeProjectSourcePath(filePath) {
119
- return filePath.length > 0 && !filePath.includes("\0") && !path2.isAbsolute(filePath) && !filePath.split(/[\\/]+/).some((part) => !part || part === "." || part === "..");
120
- }
121
- function shouldSkipProjectSourcePath(filePath) {
122
- return filePath.split(/[\\/]+/).some((segment) => {
123
- const lower = segment.toLowerCase();
124
- return lower === ".git" || lower === ".openpond" || lower === "node_modules" || lower === ".next" || lower === ".turbo" || lower.startsWith(".env");
125
- });
136
+ async function runCommand(command, args, options = {}) {
137
+ return runProcessCommand(command, args, { cwd: options.cwd });
126
138
  }
127
- async function resolveProjectSourceUploadBranch(projectPath, options) {
128
- const explicit = optionString(options, "branch");
129
- if (explicit) return explicit;
130
- const branch = await runCommand("git", ["branch", "--show-current"], {
131
- cwd: projectPath
132
- });
133
- if (branch.code !== 0) return null;
134
- return branch.stdout.trim() || null;
139
+ function readOpenPondAgentSdkVersionSpec(packageJson) {
140
+ for (const key of ["dependencies", "devDependencies", "peerDependencies"]) {
141
+ const dependencies = packageJson[key];
142
+ if (!dependencies || typeof dependencies !== "object" || Array.isArray(dependencies)) {
143
+ continue;
144
+ }
145
+ const value = dependencies["openpond-agent-sdk"];
146
+ if (typeof value === "string" && value.trim()) return value.trim();
147
+ }
148
+ return null;
135
149
  }
136
- async function collectProjectSourceUploadEntries(projectPath) {
137
- const sourcePaths = await collectProjectSourceUploadPaths(projectPath);
138
- if (sourcePaths.length === 0) {
139
- throw new Error("no source files found to upload");
150
+ async function buildAgentSdkMaterializedDependency(projectPath, packageJson) {
151
+ const sdkSource = resolveLocalOpenPondAgentSdkMaterializationSource(
152
+ projectPath,
153
+ packageJson
154
+ );
155
+ if (!sdkSource) return null;
156
+ const tempDir = await fs.mkdtemp(path3.join(tmpdir(), "openpond-agent-sdk-pack-"));
157
+ try {
158
+ const sdkContents = sdkSource.kind === "package_root" ? await packOpenPondAgentSdkPackageRoot(sdkSource.packageRoot, tempDir) : sdkSource.tarballContents;
159
+ const sdkDependencyTarballs = await packAgentSdkRuntimeDependencyTarballs({
160
+ sdkPackageJson: sdkSource.packageJson,
161
+ dependencyBaseDir: sdkSource.dependencyBaseDir,
162
+ tempDir
163
+ });
164
+ const packageManager = detectAgentSdkPackageManager(projectPath, packageJson);
165
+ const rewrittenPackageJson = rewriteAgentSdkPackageJsonForMaterialization(
166
+ packageJson,
167
+ sdkDependencyTarballs,
168
+ packageManager
169
+ );
170
+ const pnpmWorkspaceSource = packageManager === "pnpm" || packageManager === "unknown" ? buildAgentSdkPnpmWorkspaceSource(projectPath, sdkDependencyTarballs) : null;
171
+ const installCommand = agentSdkDependencyInstallCommand(packageManager);
172
+ const sdkPackage = {
173
+ packageName: "openpond-agent-sdk",
174
+ source: "uploaded_tarball",
175
+ path: AGENT_SDK_VENDOR_TARBALL_PATH,
176
+ sha256: sha256Hex(sdkContents),
177
+ sizeBytes: sdkContents.byteLength
178
+ };
179
+ return {
180
+ rewrittenPackageJson,
181
+ pnpmWorkspaceSource,
182
+ tarballs: [
183
+ {
184
+ ...sdkPackage,
185
+ contents: sdkContents
186
+ },
187
+ ...sdkDependencyTarballs
188
+ ],
189
+ dependencySetup: {
190
+ required: true,
191
+ packageManager,
192
+ installCommand,
193
+ commands: [installCommand],
194
+ packageJsonPath: "package.json",
195
+ expectedBinaryPath: "node_modules/.bin/openpond-agent",
196
+ generatedArtifactDirectory: ".openpond",
197
+ sdkPackage,
198
+ dependencyPackages: sdkDependencyTarballs.map((tarball) => ({
199
+ packageName: tarball.packageName,
200
+ source: tarball.source,
201
+ versionSpec: tarball.versionSpec,
202
+ path: tarball.path,
203
+ sha256: tarball.sha256,
204
+ sizeBytes: tarball.sizeBytes
205
+ }))
206
+ }
207
+ };
208
+ } finally {
209
+ await fs.rm(tempDir, { recursive: true, force: true });
140
210
  }
141
- if (sourcePaths.length > PROJECT_SOURCE_UPLOAD_MAX_FILES) {
211
+ }
212
+ async function packOpenPondAgentSdkPackageRoot(sdkPackageRoot, tempDir) {
213
+ const pack = await runCommand(
214
+ "npm",
215
+ ["pack", "--silent", "--pack-destination", tempDir, sdkPackageRoot],
216
+ { cwd: sdkPackageRoot }
217
+ );
218
+ if (pack.code !== 0) {
219
+ const details = [pack.stderr.trim(), pack.stdout.trim()].filter(Boolean).join("\n");
142
220
  throw new Error(
143
- `too many source files to upload: ${sourcePaths.length} > ${PROJECT_SOURCE_UPLOAD_MAX_FILES}`
221
+ `failed to pack openpond-agent-sdk for source upload${details ? `:
222
+ ${details}` : ""}`
144
223
  );
145
224
  }
146
- const sortedSourcePaths = sourcePaths.sort();
147
- const filesToUpload = (await mapWithConcurrency(sortedSourcePaths, PROJECT_SOURCE_UPLOAD_CONCURRENCY, async (sourcePath) => {
148
- const absolutePath = path2.resolve(projectPath, sourcePath);
149
- const relative = path2.relative(projectPath, absolutePath);
150
- if (relative.startsWith("..") || path2.isAbsolute(relative)) {
151
- throw new Error(`source path escapes project: ${sourcePath}`);
152
- }
153
- const stat = await fs.stat(absolutePath);
154
- if (!stat.isFile()) return null;
155
- if (stat.size > PROJECT_SOURCE_UPLOAD_MAX_FILE_BYTES) {
225
+ const tarballName = pack.stdout.trim().split(/\r?\n/).filter(Boolean).pop();
226
+ if (!tarballName) {
227
+ throw new Error("failed to pack openpond-agent-sdk for source upload: npm pack did not return a tarball name");
228
+ }
229
+ return fs.readFile(path3.join(tempDir, tarballName));
230
+ }
231
+ async function packAgentSdkRuntimeDependencyTarballs(params) {
232
+ const dependencies = recordStringMap(params.sdkPackageJson.dependencies);
233
+ const pending = Object.entries(dependencies).sort(([left], [right]) => left.localeCompare(right)).map(([packageName, versionSpec]) => ({ packageName, versionSpec }));
234
+ const seen = /* @__PURE__ */ new Set();
235
+ const tarballs = [];
236
+ while (pending.length > 0) {
237
+ const { packageName, versionSpec } = pending.shift();
238
+ if (seen.has(packageName)) continue;
239
+ seen.add(packageName);
240
+ const packTarget = npmPackTargetForDependency({
241
+ packageName,
242
+ versionSpec,
243
+ dependencyBaseDir: params.dependencyBaseDir
244
+ });
245
+ const pack = await runCommand(
246
+ "npm",
247
+ ["pack", "--silent", "--pack-destination", params.tempDir, packTarget],
248
+ { cwd: params.dependencyBaseDir }
249
+ );
250
+ if (pack.code !== 0) {
251
+ const details = [pack.stderr.trim(), pack.stdout.trim()].filter(Boolean).join("\n");
156
252
  throw new Error(
157
- `source file is too large: ${sourcePath} (${stat.size} bytes)`
253
+ `failed to pack openpond-agent-sdk dependency ${packageName}${details ? `:
254
+ ${details}` : ""}`
158
255
  );
159
256
  }
160
- return {
161
- path: sourcePath.replace(/\\/g, "/"),
162
- absolutePath,
163
- size: stat.size,
164
- mtimeMs: Math.trunc(stat.mtimeMs),
165
- ctimeMs: Math.trunc(stat.ctimeMs)
166
- };
167
- })).filter((file) => file !== null);
168
- let totalBytes = 0;
169
- for (const file of filesToUpload) {
170
- totalBytes += file.size;
171
- if (totalBytes > PROJECT_SOURCE_UPLOAD_MAX_BYTES) {
257
+ const tarballName = pack.stdout.trim().split(/\r?\n/).filter(Boolean).pop();
258
+ if (!tarballName) {
172
259
  throw new Error(
173
- `source upload is too large: ${totalBytes} > ${PROJECT_SOURCE_UPLOAD_MAX_BYTES}`
260
+ `failed to pack openpond-agent-sdk dependency ${packageName}: npm pack did not return a tarball name`
174
261
  );
175
262
  }
263
+ const contents = await fs.readFile(path3.join(params.tempDir, tarballName));
264
+ const packedPackageJson = readPackageJsonFromNpmTarball(contents);
265
+ tarballs.push({
266
+ packageName,
267
+ source: "npm_dependency_tarball",
268
+ versionSpec,
269
+ path: `${AGENT_SDK_VENDOR_NPM_DEPENDENCY_DIR}/${sanitizeNpmPackageNameForVendor(
270
+ packageName
271
+ )}.tgz`,
272
+ contents,
273
+ sha256: sha256Hex(contents),
274
+ sizeBytes: contents.byteLength
275
+ });
276
+ for (const [dependencyName, dependencySpec] of Object.entries(
277
+ recordStringMap(packedPackageJson.dependencies)
278
+ )) {
279
+ pending.push({ packageName: dependencyName, versionSpec: dependencySpec });
280
+ }
281
+ for (const [dependencyName, dependencySpec] of Object.entries(
282
+ recordStringMap(packedPackageJson.optionalDependencies)
283
+ )) {
284
+ if (!isSupportedSandboxOptionalDependency(dependencyName)) continue;
285
+ pending.push({ packageName: dependencyName, versionSpec: dependencySpec });
286
+ }
176
287
  }
177
- const cache = await readSourceUploadCache(projectPath);
178
- const materialized = await mapWithConcurrency(
179
- filesToUpload,
180
- PROJECT_SOURCE_UPLOAD_CONCURRENCY,
181
- async (file) => materializeSourceUploadFile(file, cache)
182
- );
183
- await writeSourceUploadCache(projectPath, materialized).catch(() => {
184
- });
185
- const entries = materialized.map((item) => item.entry);
186
- return {
187
- entries,
188
- fileCount: entries.length,
189
- totalBytes,
190
- limits: PROJECT_SOURCE_UPLOAD_LIMITS,
191
- transport: PROJECT_SOURCE_UPLOAD_TRANSPORT
192
- };
288
+ return tarballs.sort((left, right) => left.packageName.localeCompare(right.packageName));
193
289
  }
194
- async function mapWithConcurrency(items, concurrency, mapper) {
195
- const results = new Array(items.length);
196
- let nextIndex = 0;
197
- const workerCount = Math.max(1, Math.min(concurrency, items.length));
198
- await Promise.all(
199
- Array.from({ length: workerCount }, async () => {
200
- while (nextIndex < items.length) {
201
- const index = nextIndex;
202
- nextIndex += 1;
203
- results[index] = await mapper(items[index], index);
204
- }
205
- })
206
- );
207
- return results;
290
+ function isSupportedSandboxOptionalDependency(packageName) {
291
+ if (packageName === "fsevents") return false;
292
+ if (packageName.startsWith("@esbuild/")) {
293
+ return packageName === "@esbuild/linux-x64" || packageName === "@esbuild/linux-arm64";
294
+ }
295
+ return true;
208
296
  }
209
- async function collectProjectSourceUploadPaths(projectPath) {
210
- const files = await runCommand(
211
- "git",
212
- ["ls-files", "-z", "--cached", "--others", "--exclude-standard"],
213
- { cwd: projectPath }
214
- );
215
- if (files.code !== 0) {
216
- if (existsSync2(path2.join(projectPath, ".git"))) {
217
- throw new Error(
218
- `git ls-files failed: ${files.stderr.trim() || files.stdout.trim() || "unknown error"}`
219
- );
220
- }
221
- return collectFilesystemProjectSourceUploadPaths(projectPath);
297
+ function npmPackTargetForDependency(params) {
298
+ if (params.versionSpec.startsWith("file:")) {
299
+ return path3.resolve(
300
+ params.dependencyBaseDir,
301
+ params.versionSpec.slice("file:".length)
302
+ );
222
303
  }
223
- return files.stdout.split("\0").map((filePath) => filePath.trim()).filter(Boolean).filter((filePath) => {
224
- const normalized = filePath.replace(/\\/g, "/");
225
- return isSafeProjectSourcePath(normalized) && !shouldSkipProjectSourcePath(normalized);
226
- });
304
+ return `${params.packageName}@${params.versionSpec}`;
227
305
  }
228
- async function collectFilesystemProjectSourceUploadPaths(projectPath) {
229
- const sourcePaths = [];
230
- async function visit(relativeDir) {
231
- const absoluteDir = path2.join(projectPath, relativeDir);
232
- const entries = await fs.readdir(absoluteDir, { withFileTypes: true });
233
- for (const entry of entries) {
234
- const relativePath = path2.join(relativeDir, entry.name).replace(/\\/g, "/");
235
- if (!isSafeProjectSourcePath(relativePath) || shouldSkipProjectSourcePath(relativePath)) {
236
- continue;
237
- }
238
- if (entry.isDirectory()) {
239
- await visit(relativePath);
240
- continue;
306
+ function sanitizeNpmPackageNameForVendor(packageName) {
307
+ return packageName.replace(/^@/, "").replace(/[\/\\]/g, "__").replace(/[^a-zA-Z0-9._-]/g, "_");
308
+ }
309
+ function resolveLocalOpenPondAgentSdkMaterializationSource(projectPath, packageJson) {
310
+ const versionSpec = readOpenPondAgentSdkVersionSpec(packageJson);
311
+ if (versionSpec?.startsWith("file:")) {
312
+ const candidate = path3.resolve(projectPath, versionSpec.slice("file:".length));
313
+ if (isOpenPondAgentSdkPackageRoot(candidate)) {
314
+ return {
315
+ kind: "package_root",
316
+ packageRoot: candidate,
317
+ dependencyBaseDir: candidate,
318
+ packageJson: JSON.parse(
319
+ readFileSyncUtf8(path3.join(candidate, "package.json"))
320
+ )
321
+ };
322
+ }
323
+ if (isLocalNpmTarball(candidate)) {
324
+ const tarballContents = readFileSync2(candidate);
325
+ const tarballPackageJson = readPackageJsonFromNpmTarball(tarballContents);
326
+ if (tarballPackageJson.name === "openpond-agent-sdk") {
327
+ return {
328
+ kind: "tarball",
329
+ tarballPath: candidate,
330
+ tarballContents,
331
+ dependencyBaseDir: path3.dirname(candidate),
332
+ packageJson: tarballPackageJson
333
+ };
241
334
  }
242
- if (entry.isFile()) sourcePaths.push(relativePath);
243
335
  }
244
336
  }
245
- try {
246
- await visit("");
247
- } catch (error) {
248
- throw new Error(
249
- `filesystem source scan failed: ${error instanceof Error ? error.message : String(error)}`
250
- );
337
+ if (versionSpec?.startsWith("workspace:")) {
338
+ const candidate = findOpenPondAgentSdkPackageRootInAncestors(projectPath);
339
+ if (candidate) {
340
+ return {
341
+ kind: "package_root",
342
+ packageRoot: candidate,
343
+ dependencyBaseDir: candidate,
344
+ packageJson: JSON.parse(
345
+ readFileSyncUtf8(path3.join(candidate, "package.json"))
346
+ )
347
+ };
348
+ }
251
349
  }
252
- return sourcePaths;
350
+ return null;
253
351
  }
254
- async function collectAgentSdkProjectSourceUploadEntries(projectPath, existingEntries) {
255
- if (!isAgentSdkProject(projectPath)) {
256
- return {
257
- entries: [],
258
- generatedManifestPath: null,
259
- synthesizedOpenPondYaml: false,
260
- uploadMetadataPath: null,
261
- uploadMetadata: null,
262
- uploadMetadataHash: null
263
- };
352
+ function findOpenPondAgentSdkPackageRootInAncestors(projectPath) {
353
+ let current = path3.resolve(projectPath);
354
+ while (true) {
355
+ if (isOpenPondAgentSdkPackageRoot(current)) return current;
356
+ const parent = path3.dirname(current);
357
+ if (parent === current) return null;
358
+ current = parent;
264
359
  }
265
- await runAgentSdkProjectCheck(projectPath, "build");
266
- await runAgentSdkProjectCheck(projectPath, "validate");
267
- await runAgentSdkProjectCheck(projectPath, "eval");
268
- const packageJson = readAgentSdkProjectPackageJson(projectPath);
269
- const materializedDependency = await buildAgentSdkMaterializedDependency(
270
- projectPath,
271
- packageJson
272
- );
273
- const manifestPath = ".openpond/openpond-manifest.preview.yaml";
274
- const manifestSource = await fs.readFile(path2.join(projectPath, manifestPath), "utf8");
275
- const openPondYamlSource = sanitizeAgentSdkRuntimeManifestForOpenPondYaml(
276
- manifestSource,
277
- materializedDependency?.dependencySetup ?? null
278
- );
279
- const manifestResult = validateSandboxTemplateYaml(openPondYamlSource);
280
- if (!manifestResult.ok) {
281
- throw new Error(
282
- `generated ${manifestPath} failed sandbox-template validation after openpond.yaml sanitization:
283
- ${formatSandboxTemplateDiagnostics(
284
- manifestResult.diagnostics
285
- )}`
286
- );
360
+ }
361
+ function isOpenPondAgentSdkPackageRoot(candidate) {
362
+ const packageJsonPath = path3.join(candidate, "package.json");
363
+ if (!existsSync3(packageJsonPath)) return false;
364
+ try {
365
+ const parsed = JSON.parse(readFileSyncUtf8(packageJsonPath));
366
+ return parsed.name === "openpond-agent-sdk";
367
+ } catch {
368
+ return false;
287
369
  }
288
- const entries = [];
289
- if (materializedDependency?.rewrittenPackageJson) {
290
- entries.push(
291
- projectSourceUploadTextEntry(
292
- "package.json",
293
- `${JSON.stringify(materializedDependency.rewrittenPackageJson, null, 2)}
294
- `
295
- )
296
- );
370
+ }
371
+ function isLocalNpmTarball(candidate) {
372
+ if (!existsSync3(candidate)) return false;
373
+ try {
374
+ return statSync(candidate).isFile() && (candidate.endsWith(".tgz") || candidate.endsWith(".tar.gz"));
375
+ } catch {
376
+ return false;
297
377
  }
298
- if (materializedDependency?.pnpmWorkspaceSource) {
299
- entries.push(
300
- projectSourceUploadTextEntry(
301
- "pnpm-workspace.yaml",
302
- materializedDependency.pnpmWorkspaceSource
303
- )
304
- );
378
+ }
379
+ function readPackageJsonFromNpmTarball(tarballContents) {
380
+ const tarContents = gunzipSync(tarballContents);
381
+ let offset = 0;
382
+ while (offset + 512 <= tarContents.length) {
383
+ const header = tarContents.subarray(offset, offset + 512);
384
+ if (header.every((byte) => byte === 0)) break;
385
+ const name = readTarString(header, 0, 100);
386
+ const prefix = readTarString(header, 345, 155);
387
+ const entryPath = prefix ? `${prefix}/${name}` : name;
388
+ const sizeText = readTarString(header, 124, 12).trim();
389
+ const size = Number.parseInt(sizeText || "0", 8);
390
+ if (!Number.isFinite(size) || size < 0) {
391
+ throw new Error("failed to read openpond-agent-sdk tarball: invalid entry size");
392
+ }
393
+ const dataStart = offset + 512;
394
+ const dataEnd = dataStart + size;
395
+ if (entryPath === "package/package.json") {
396
+ return JSON.parse(
397
+ tarContents.subarray(dataStart, dataEnd).toString("utf8")
398
+ );
399
+ }
400
+ offset = dataStart + Math.ceil(size / 512) * 512;
305
401
  }
306
- for (const tarball of materializedDependency?.tarballs ?? []) {
307
- entries.push(
308
- projectSourceUploadBufferEntry(tarball.path, tarball.contents)
309
- );
402
+ throw new Error("failed to read openpond-agent-sdk tarball: missing package.json");
403
+ }
404
+ function readTarString(header, start, length) {
405
+ const field = header.subarray(start, start + length);
406
+ const nullIndex = field.indexOf(0);
407
+ return field.subarray(0, nullIndex === -1 ? field.length : nullIndex).toString("utf8");
408
+ }
409
+ function rewriteAgentSdkPackageJsonForMaterialization(packageJson, dependencyTarballs, packageManager) {
410
+ const rewritten = { ...packageJson };
411
+ const dependencies = recordCopy(rewritten.dependencies);
412
+ const overrides = recordCopy(rewritten.overrides);
413
+ dependencies["openpond-agent-sdk"] = AGENT_SDK_MATERIALIZED_DEPENDENCY_SPEC;
414
+ for (const tarball of dependencyTarballs) {
415
+ const dependencySpec = `file:${tarball.path}`;
416
+ dependencies[tarball.packageName] = dependencySpec;
417
+ overrides[tarball.packageName] = dependencySpec;
310
418
  }
311
- const generatedArtifactPaths = await collectAgentSdkGeneratedArtifactPaths(projectPath);
312
- for (const artifactPath of generatedArtifactPaths) {
313
- entries.push(await projectSourceUploadFileEntry(projectPath, artifactPath));
419
+ rewritten.dependencies = dependencies;
420
+ if (Object.keys(overrides).length > 0) {
421
+ rewritten.overrides = overrides;
314
422
  }
315
- const hasAuthoredOpenPondYaml = existingEntries.some((entry) => entry.path === "openpond.yaml") || existsSync2(path2.join(projectPath, "openpond.yaml"));
316
- if (!hasAuthoredOpenPondYaml) {
317
- entries.push(projectSourceUploadTextEntry("openpond.yaml", openPondYamlSource));
318
- } else {
319
- const authoredSource = await fs.readFile(path2.join(projectPath, "openpond.yaml"), "utf8");
320
- const authoredResult = validateSandboxTemplateYaml(authoredSource);
321
- if (!authoredResult.ok) {
322
- throw new Error(
323
- `authored openpond.yaml failed sandbox-template validation:
324
- ${formatSandboxTemplateDiagnostics(
325
- authoredResult.diagnostics
326
- )}`
327
- );
423
+ if (packageManager === "unknown") {
424
+ rewritten.packageManager = OPENPOND_PNPM_PACKAGE_MANAGER;
425
+ }
426
+ for (const key of ["devDependencies", "peerDependencies"]) {
427
+ const entries = recordCopy(rewritten[key]);
428
+ delete entries["openpond-agent-sdk"];
429
+ if (Object.keys(entries).length > 0) {
430
+ rewritten[key] = entries;
431
+ } else {
432
+ delete rewritten[key];
328
433
  }
329
434
  }
330
- const uploadMetadata = await buildAgentSdkSourceUploadMetadata(projectPath, {
331
- packageJson,
332
- generatedManifestPath: manifestPath,
333
- generatedArtifactPaths,
334
- synthesizedOpenPondYaml: !hasAuthoredOpenPondYaml,
335
- openPondYamlSource,
336
- dependencySetup: materializedDependency?.dependencySetup ?? null
337
- });
338
- const uploadMetadataSource = `${JSON.stringify(uploadMetadata, null, 2)}
339
- `;
340
- const uploadMetadataHash = {
341
- sha256: sha256Hex(Buffer.from(uploadMetadataSource, "utf8")),
342
- sizeBytes: Buffer.byteLength(uploadMetadataSource, "utf8")
343
- };
344
- entries.push(
345
- projectSourceUploadTextEntry(
346
- AGENT_SDK_SOURCE_UPLOAD_METADATA_PATH,
347
- uploadMetadataSource
348
- )
349
- );
350
- return {
351
- entries,
352
- generatedManifestPath: manifestPath,
353
- synthesizedOpenPondYaml: !hasAuthoredOpenPondYaml,
354
- uploadMetadataPath: AGENT_SDK_SOURCE_UPLOAD_METADATA_PATH,
355
- uploadMetadata,
356
- uploadMetadataHash
357
- };
435
+ return rewritten;
358
436
  }
359
- async function buildAgentSdkSourceUploadMetadata(projectPath, params) {
360
- const packageManager = detectAgentSdkPackageManager(projectPath, params.packageJson);
361
- const commandHints = buildAgentSdkCommandHints(params.packageJson, packageManager);
362
- const setupRequirements = await collectAgentSdkSourceSetupRequirements(projectPath);
363
- const artifactHashes = {};
364
- for (const artifactPath of params.generatedArtifactPaths) {
365
- const absolutePath = path2.join(projectPath, artifactPath);
366
- if (!existsSync2(absolutePath)) continue;
367
- const contents = await fs.readFile(absolutePath);
368
- artifactHashes[artifactPath] = {
369
- sha256: sha256Hex(contents),
370
- sizeBytes: contents.byteLength
371
- };
437
+ function buildAgentSdkPnpmWorkspaceSource(projectPath, dependencyTarballs) {
438
+ const workspacePath = path3.join(projectPath, "pnpm-workspace.yaml");
439
+ let workspace = {};
440
+ if (existsSync3(workspacePath)) {
441
+ const parsed = yaml.load(readFileSyncUtf8(workspacePath));
442
+ workspace = parsed && typeof parsed === "object" && !Array.isArray(parsed) ? { ...parsed } : {};
372
443
  }
373
- artifactHashes["openpond.yaml"] = {
374
- sha256: sha256Hex(Buffer.from(params.openPondYamlSource, "utf8")),
375
- sizeBytes: Buffer.byteLength(params.openPondYamlSource, "utf8")
376
- };
377
- return {
378
- schema: "openpond.agent.source_upload.v1",
379
- sourceTreeMode: "typescript_agent_sdk",
380
- packageManager,
381
- sdk: {
382
- packageName: "openpond-agent-sdk",
383
- versionSpec: readOpenPondAgentSdkVersionSpec(params.packageJson)
384
- },
385
- commands: commandHints,
386
- ...params.dependencySetup ? { dependencySetup: params.dependencySetup } : {},
387
- ...setupRequirements.length > 0 ? { setupRequirements } : {},
388
- generatedManifestPath: params.generatedManifestPath,
389
- synthesizedOpenPondYaml: params.synthesizedOpenPondYaml,
390
- openPondYamlMode: params.synthesizedOpenPondYaml ? "synthesized" : "authored",
391
- artifactHashes
392
- };
393
- }
394
- async function collectAgentSdkGeneratedArtifactPaths(projectPath) {
395
- const generatedArtifacts = /* @__PURE__ */ new Set();
396
- for (const artifactPath of AGENT_SDK_GENERATED_ARTIFACTS) {
397
- if (existsSync2(path2.join(projectPath, artifactPath))) {
398
- generatedArtifacts.add(artifactPath);
399
- }
444
+ if (!Array.isArray(workspace.packages)) workspace.packages = [];
445
+ const overrides = recordCopy(workspace.overrides);
446
+ for (const tarball of dependencyTarballs) {
447
+ overrides[tarball.packageName] = `file:${tarball.path}`;
400
448
  }
401
- for (const skillArtifactPath of await collectAgentSdkGeneratedSkillArtifactPaths(projectPath)) {
402
- generatedArtifacts.add(skillArtifactPath);
449
+ workspace.overrides = overrides;
450
+ const allowBuilds = recordCopy(workspace.allowBuilds);
451
+ allowBuilds.esbuild = true;
452
+ const vendoredEsbuild = dependencyTarballs.find(
453
+ (tarball) => tarball.packageName === "esbuild"
454
+ );
455
+ if (vendoredEsbuild) {
456
+ allowBuilds[`esbuild@file:${vendoredEsbuild.path}`] = true;
403
457
  }
404
- return Array.from(generatedArtifacts).sort((left, right) => left.localeCompare(right));
458
+ workspace.allowBuilds = allowBuilds;
459
+ workspace.supportedArchitectures = {
460
+ os: ["linux"],
461
+ cpu: ["x64", "arm64"],
462
+ libc: ["glibc", "musl"]
463
+ };
464
+ return yaml.dump(workspace, { lineWidth: 120, noRefs: true });
405
465
  }
406
- async function collectAgentSdkGeneratedSkillArtifactPaths(projectPath) {
407
- const skillsRoot = path2.join(projectPath, AGENT_SDK_GENERATED_SKILLS_DIR);
408
- if (!existsSync2(skillsRoot)) return [];
409
- const results = [];
410
- async function visit(relativeDir) {
411
- const absoluteDir = path2.join(projectPath, relativeDir);
412
- const entries = await fs.readdir(absoluteDir, { withFileTypes: true });
413
- entries.sort((left, right) => left.name.localeCompare(right.name));
414
- for (const entry of entries) {
415
- const relativePath = path2.join(relativeDir, entry.name).replace(/\\/g, "/");
416
- if (!isSafeProjectSourcePath(relativePath)) continue;
417
- if (entry.isDirectory()) {
418
- await visit(relativePath);
419
- continue;
420
- }
421
- if (entry.isFile()) results.push(relativePath);
466
+ function recordStringMap(value) {
467
+ if (!value || typeof value !== "object" || Array.isArray(value)) return {};
468
+ const entries = {};
469
+ for (const [key, entryValue] of Object.entries(value)) {
470
+ if (typeof entryValue === "string" && entryValue.trim()) {
471
+ entries[key] = entryValue.trim();
422
472
  }
423
473
  }
424
- await visit(AGENT_SDK_GENERATED_SKILLS_DIR);
425
- return results;
474
+ return entries;
426
475
  }
427
- async function collectAgentSdkSourceSetupRequirements(projectPath) {
428
- const requirements = [];
429
- const seen = /* @__PURE__ */ new Set();
430
- for (const relativePath of [
431
- ".openpond/action-registry.json",
432
- ".openpond/agent-manifest.json"
433
- ]) {
434
- const payload = await readJsonFileIfExists(path2.join(projectPath, relativePath));
435
- if (!payload) continue;
436
- for (const actionRecord of [
437
- ...recordArray(payload.actions),
438
- ...recordArray(payload.actionCatalog)
439
- ]) {
440
- const actionId = text(actionRecord.id) ?? text(actionRecord.name);
441
- const actionName = text(actionRecord.name) ?? actionId;
442
- if (!actionId && !actionName) continue;
443
- for (const setupRecord of recordArray(actionRecord.setupRequirements)) {
444
- const setupRequirement = { ...setupRecord };
445
- if (actionId) setupRequirement.actionId = actionId;
446
- if (actionName && actionName !== actionId) setupRequirement.actionName = actionName;
447
- const key = setupRequirementIdentity(setupRequirement);
448
- if (seen.has(key)) continue;
449
- seen.add(key);
450
- requirements.push(setupRequirement);
451
- }
452
- }
453
- }
454
- return requirements;
476
+ function recordCopy(value) {
477
+ if (!value || typeof value !== "object" || Array.isArray(value)) return {};
478
+ return { ...value };
455
479
  }
456
- async function readJsonFileIfExists(filePath) {
457
- try {
458
- const parsed = JSON.parse(await fs.readFile(filePath, "utf8"));
459
- return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : null;
460
- } catch {
461
- return null;
462
- }
480
+ function recordArray(value) {
481
+ return Array.isArray(value) ? value.filter(
482
+ (item) => Boolean(item) && typeof item === "object" && !Array.isArray(item)
483
+ ) : [];
463
484
  }
464
- function setupRequirementIdentity(record) {
465
- return [
466
- text(record.actionId) ?? "",
467
- text(record.actionName) ?? "",
468
- text(record.kind) ?? text(record.type) ?? "",
469
- text(record.label) ?? text(record.name) ?? text(record.key) ?? text(record.provider) ?? text(record.tool) ?? text(record.command) ?? text(record.packageName) ?? ""
470
- ].join(":");
485
+ function text(value) {
486
+ return typeof value === "string" && value.trim() ? value.trim() : null;
471
487
  }
472
- function readAgentSdkProjectPackageJson(projectPath) {
473
- const packageJsonPath = path2.join(projectPath, "package.json");
474
- return JSON.parse(readFileSyncUtf8(packageJsonPath));
488
+ function sha256Hex(contents) {
489
+ return createHash("sha256").update(contents).digest("hex");
475
490
  }
476
- function detectAgentSdkPackageManager(projectPath, packageJson) {
477
- const packageManager = packageJson.packageManager;
478
- if (typeof packageManager === "string") {
479
- const name = packageManager.split("@")[0];
480
- if (name === "bun" || name === "npm" || name === "pnpm" || name === "yarn") {
481
- return name;
482
- }
483
- }
484
- if (existsSync2(path2.join(projectPath, "bun.lock")) || existsSync2(path2.join(projectPath, "bun.lockb"))) {
485
- return "bun";
486
- }
487
- if (existsSync2(path2.join(projectPath, "pnpm-lock.yaml"))) return "pnpm";
488
- if (existsSync2(path2.join(projectPath, "yarn.lock"))) return "yarn";
489
- if (existsSync2(path2.join(projectPath, "package-lock.json")) || existsSync2(path2.join(projectPath, "npm-shrinkwrap.json"))) {
490
- return "npm";
491
+ function dependencySetupCommands(value) {
492
+ if (!value || typeof value !== "object" || Array.isArray(value)) return [];
493
+ const record = value;
494
+ if (Array.isArray(record.commands)) {
495
+ return record.commands.filter(
496
+ (command) => typeof command === "string" && command.trim() !== ""
497
+ );
491
498
  }
492
- return "unknown";
499
+ return typeof record.installCommand === "string" && record.installCommand.trim() ? [record.installCommand.trim()] : [];
493
500
  }
494
- function buildAgentSdkCommandHints(packageJson, packageManager) {
501
+ function mergeManifestSetupCommands(manifest, commands) {
502
+ if (commands.length === 0) return manifest;
503
+ const setup = manifest.setup && typeof manifest.setup === "object" && !Array.isArray(manifest.setup) ? recordCopy(manifest.setup) : {};
504
+ const existingCommands = Array.isArray(setup.commands) ? setup.commands.filter(
505
+ (command) => typeof command === "string" && command.trim() !== ""
506
+ ) : [];
507
+ const mergedCommands = [...commands];
508
+ for (const command of existingCommands) {
509
+ if (!mergedCommands.includes(command)) mergedCommands.push(command);
510
+ }
495
511
  return {
496
- inspect: buildAgentSdkCommandHint(
497
- packageJson,
498
- packageManager,
499
- "agent:inspect",
500
- "openpond-agent inspect --json"
501
- ),
502
- build: buildAgentSdkCommandHint(
503
- packageJson,
504
- packageManager,
505
- "agent:build",
506
- "openpond-agent build"
507
- ),
508
- validate: buildAgentSdkCommandHint(
509
- packageJson,
510
- packageManager,
511
- "agent:validate",
512
- "openpond-agent validate"
513
- ),
514
- eval: buildAgentSdkCommandHint(
515
- packageJson,
516
- packageManager,
517
- "agent:eval",
518
- "openpond-agent eval"
519
- )
512
+ ...manifest,
513
+ setup: {
514
+ ...setup,
515
+ commands: mergedCommands
516
+ }
520
517
  };
521
518
  }
522
- function buildAgentSdkCommandHint(packageJson, packageManager, scriptName, fallback) {
523
- const scripts = packageJson.scripts;
524
- const hasScript = scripts && typeof scripts === "object" && !Array.isArray(scripts) && typeof scripts[scriptName] === "string";
525
- if (!hasScript) return fallback;
526
- if (packageManager === "pnpm") return `pnpm run ${scriptName}`;
527
- if (packageManager === "yarn") return `yarn ${scriptName}`;
528
- if (packageManager === "npm") return `npm run ${scriptName}`;
529
- if (packageManager === "bun") return `bun run ${scriptName}`;
530
- return `pnpm run ${scriptName}`;
519
+ function sanitizeAgentSdkRuntimeManifestForOpenPondYaml(source, dependencySetup) {
520
+ const parsed = yaml.load(source);
521
+ if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
522
+ return `${AGENT_SDK_SYNTHESIZED_OPENPOND_YAML_SENTINEL}
523
+ ${source}`;
524
+ }
525
+ const manifest = mergeManifestSetupCommands(
526
+ { ...parsed },
527
+ dependencySetupCommands(dependencySetup)
528
+ );
529
+ delete manifest.schema;
530
+ sanitizeGeneratedManifestNamedCommands(manifest, "actions");
531
+ sanitizeGeneratedManifestNamedCommands(manifest, "services");
532
+ return `${AGENT_SDK_SYNTHESIZED_OPENPOND_YAML_SENTINEL}
533
+ ${yaml.dump(manifest, { lineWidth: -1, noRefs: true })}`;
531
534
  }
532
- function readOpenPondAgentSdkVersionSpec(packageJson) {
533
- for (const key of ["dependencies", "devDependencies", "peerDependencies"]) {
534
- const dependencies = packageJson[key];
535
- if (!dependencies || typeof dependencies !== "object" || Array.isArray(dependencies)) {
536
- continue;
535
+ function sanitizeGeneratedManifestNamedCommands(manifest, key) {
536
+ if (!Array.isArray(manifest[key])) return;
537
+ manifest[key] = manifest[key].map((entry) => {
538
+ if (!entry || typeof entry !== "object" || Array.isArray(entry)) {
539
+ return entry;
537
540
  }
538
- const value = dependencies["openpond-agent-sdk"];
539
- if (typeof value === "string" && value.trim()) return value.trim();
540
- }
541
- return null;
541
+ const sanitized = { ...entry };
542
+ delete sanitized.id;
543
+ delete sanitized.label;
544
+ return sanitized;
545
+ });
542
546
  }
543
- async function buildAgentSdkMaterializedDependency(projectPath, packageJson) {
544
- const sdkSource = resolveLocalOpenPondAgentSdkMaterializationSource(
545
- projectPath,
546
- packageJson
547
- );
548
- if (!sdkSource) return null;
549
- const tempDir = await fs.mkdtemp(path2.join(tmpdir(), "openpond-agent-sdk-pack-"));
547
+ function isAgentSdkProject(projectPath) {
548
+ if (!existsSync3(path3.join(projectPath, "agent", "agent.ts"))) return false;
549
+ const packageJsonPath = path3.join(projectPath, "package.json");
550
+ if (!existsSync3(packageJsonPath)) return false;
550
551
  try {
551
- const sdkContents = sdkSource.kind === "package_root" ? await packOpenPondAgentSdkPackageRoot(sdkSource.packageRoot, tempDir) : sdkSource.tarballContents;
552
- const sdkDependencyTarballs = await packAgentSdkRuntimeDependencyTarballs({
553
- sdkPackageJson: sdkSource.packageJson,
554
- dependencyBaseDir: sdkSource.dependencyBaseDir,
555
- tempDir
556
- });
557
- const packageManager = detectAgentSdkPackageManager(projectPath, packageJson);
558
- const rewrittenPackageJson = rewriteAgentSdkPackageJsonForMaterialization(
559
- packageJson,
560
- sdkDependencyTarballs,
561
- packageManager
552
+ const parsed = JSON.parse(readFileSyncUtf8(packageJsonPath));
553
+ return Boolean(
554
+ parsed.dependencies?.["openpond-agent-sdk"] || parsed.devDependencies?.["openpond-agent-sdk"] || parsed.peerDependencies?.["openpond-agent-sdk"]
562
555
  );
563
- const pnpmWorkspaceSource = packageManager === "pnpm" || packageManager === "unknown" ? buildAgentSdkPnpmWorkspaceSource(projectPath, sdkDependencyTarballs) : null;
564
- const installCommand = agentSdkDependencyInstallCommand(packageManager);
565
- const sdkPackage = {
566
- packageName: "openpond-agent-sdk",
567
- source: "uploaded_tarball",
568
- path: AGENT_SDK_VENDOR_TARBALL_PATH,
569
- sha256: sha256Hex(sdkContents),
570
- sizeBytes: sdkContents.byteLength
571
- };
572
- return {
573
- rewrittenPackageJson,
574
- pnpmWorkspaceSource,
575
- tarballs: [
576
- {
577
- ...sdkPackage,
578
- contents: sdkContents
579
- },
580
- ...sdkDependencyTarballs
581
- ],
582
- dependencySetup: {
583
- required: true,
584
- packageManager,
585
- installCommand,
586
- commands: [installCommand],
587
- packageJsonPath: "package.json",
588
- expectedBinaryPath: "node_modules/.bin/openpond-agent",
589
- generatedArtifactDirectory: ".openpond",
590
- sdkPackage,
591
- dependencyPackages: sdkDependencyTarballs.map((tarball) => ({
592
- packageName: tarball.packageName,
593
- source: tarball.source,
594
- versionSpec: tarball.versionSpec,
595
- path: tarball.path,
596
- sha256: tarball.sha256,
597
- sizeBytes: tarball.sizeBytes
598
- }))
599
- }
600
- };
601
- } finally {
602
- await fs.rm(tempDir, { recursive: true, force: true });
556
+ } catch {
557
+ return false;
603
558
  }
604
559
  }
605
- async function packOpenPondAgentSdkPackageRoot(sdkPackageRoot, tempDir) {
606
- const pack = await runCommand(
607
- "npm",
608
- ["pack", "--silent", "--pack-destination", tempDir, sdkPackageRoot],
609
- { cwd: sdkPackageRoot }
610
- );
611
- if (pack.code !== 0) {
612
- const details = [pack.stderr.trim(), pack.stdout.trim()].filter(Boolean).join("\n");
613
- throw new Error(
614
- `failed to pack openpond-agent-sdk for source upload${details ? `:
615
- ${details}` : ""}`
616
- );
617
- }
618
- const tarballName = pack.stdout.trim().split(/\r?\n/).filter(Boolean).pop();
619
- if (!tarballName) {
620
- throw new Error("failed to pack openpond-agent-sdk for source upload: npm pack did not return a tarball name");
621
- }
622
- return fs.readFile(path2.join(tempDir, tarballName));
560
+ function readFileSyncUtf8(filePath) {
561
+ return readFileSync2(filePath, "utf8");
623
562
  }
624
- async function packAgentSdkRuntimeDependencyTarballs(params) {
625
- const dependencies = recordStringMap(params.sdkPackageJson.dependencies);
626
- const pending = Object.entries(dependencies).sort(([left], [right]) => left.localeCompare(right)).map(([packageName, versionSpec]) => ({ packageName, versionSpec }));
627
- const seen = /* @__PURE__ */ new Set();
628
- const tarballs = [];
629
- while (pending.length > 0) {
630
- const { packageName, versionSpec } = pending.shift();
631
- if (seen.has(packageName)) continue;
632
- seen.add(packageName);
633
- const packTarget = npmPackTargetForDependency({
634
- packageName,
635
- versionSpec,
636
- dependencyBaseDir: params.dependencyBaseDir
637
- });
638
- const pack = await runCommand(
639
- "npm",
640
- ["pack", "--silent", "--pack-destination", params.tempDir, packTarget],
641
- { cwd: params.dependencyBaseDir }
642
- );
643
- if (pack.code !== 0) {
644
- const details = [pack.stderr.trim(), pack.stdout.trim()].filter(Boolean).join("\n");
645
- throw new Error(
646
- `failed to pack openpond-agent-sdk dependency ${packageName}${details ? `:
647
- ${details}` : ""}`
648
- );
649
- }
650
- const tarballName = pack.stdout.trim().split(/\r?\n/).filter(Boolean).pop();
651
- if (!tarballName) {
652
- throw new Error(
653
- `failed to pack openpond-agent-sdk dependency ${packageName}: npm pack did not return a tarball name`
654
- );
655
- }
656
- const contents = await fs.readFile(path2.join(params.tempDir, tarballName));
657
- const packedPackageJson = readPackageJsonFromNpmTarball(contents);
658
- tarballs.push({
659
- packageName,
660
- source: "npm_dependency_tarball",
661
- versionSpec,
662
- path: `${AGENT_SDK_VENDOR_NPM_DEPENDENCY_DIR}/${sanitizeNpmPackageNameForVendor(
663
- packageName
664
- )}.tgz`,
665
- contents,
666
- sha256: sha256Hex(contents),
667
- sizeBytes: contents.byteLength
668
- });
669
- for (const [dependencyName, dependencySpec] of Object.entries(
670
- recordStringMap(packedPackageJson.dependencies)
671
- )) {
672
- pending.push({ packageName: dependencyName, versionSpec: dependencySpec });
673
- }
674
- for (const [dependencyName, dependencySpec] of Object.entries(
675
- recordStringMap(packedPackageJson.optionalDependencies)
676
- )) {
677
- if (!isSupportedSandboxOptionalDependency(dependencyName)) continue;
678
- pending.push({ packageName: dependencyName, versionSpec: dependencySpec });
679
- }
680
- }
681
- return tarballs.sort((left, right) => left.packageName.localeCompare(right.packageName));
563
+
564
+ // ../../packages/cloud/src/profile/project-source-upload.ts
565
+ function optionString2(options, key) {
566
+ const value = options[key];
567
+ return typeof value === "string" ? value.trim() : "";
682
568
  }
683
- function isSupportedSandboxOptionalDependency(packageName) {
684
- if (packageName === "fsevents") return false;
685
- if (packageName.startsWith("@esbuild/")) {
686
- return packageName === "@esbuild/linux-x64" || packageName === "@esbuild/linux-arm64";
687
- }
688
- return true;
569
+ async function runCommand2(command, args, options = {}) {
570
+ return runProcessCommand(command, args, { cwd: options.cwd });
689
571
  }
690
- function npmPackTargetForDependency(params) {
691
- if (params.versionSpec.startsWith("file:")) {
692
- return path2.resolve(
693
- params.dependencyBaseDir,
694
- params.versionSpec.slice("file:".length)
695
- );
696
- }
697
- return `${params.packageName}@${params.versionSpec}`;
572
+ var PROJECT_SOURCE_UPLOAD_MAX_FILES = 1500;
573
+ var PROJECT_SOURCE_UPLOAD_MAX_FILE_BYTES = 8 * 1024 * 1024;
574
+ var PROJECT_SOURCE_UPLOAD_MAX_BYTES = 100 * 1024 * 1024;
575
+ var PROJECT_SOURCE_UPLOAD_CONCURRENCY = 8;
576
+ var PROJECT_SOURCE_UPLOAD_LIMITS = {
577
+ maxFiles: PROJECT_SOURCE_UPLOAD_MAX_FILES,
578
+ maxFileBytes: PROJECT_SOURCE_UPLOAD_MAX_FILE_BYTES,
579
+ maxTotalBytes: PROJECT_SOURCE_UPLOAD_MAX_BYTES,
580
+ concurrency: PROJECT_SOURCE_UPLOAD_CONCURRENCY
581
+ };
582
+ var PROJECT_SOURCE_UPLOAD_TRANSPORT = {
583
+ mode: "single_json_payload",
584
+ chunkingSupported: false
585
+ };
586
+ var AGENT_SDK_SOURCE_UPLOAD_METADATA_PATH = ".openpond/source-upload-metadata.json";
587
+ var AGENT_SDK_GENERATED_SKILLS_DIR = ".openpond/skills";
588
+ var AGENT_SDK_GENERATED_ARTIFACTS = [
589
+ ".openpond/agent-inspect.json",
590
+ ".openpond/agent-manifest.json",
591
+ ".openpond/action-registry.json",
592
+ ".openpond/openpond-manifest.preview.yaml",
593
+ ".openpond/runtime-bridge.mjs",
594
+ ".openpond/validator-report.md"
595
+ ];
596
+ function isSafeProjectSourcePath(filePath) {
597
+ return filePath.length > 0 && !filePath.includes("\0") && !path4.isAbsolute(filePath) && !filePath.split(/[\\/]+/).some((part) => !part || part === "." || part === "..");
698
598
  }
699
- function sanitizeNpmPackageNameForVendor(packageName) {
700
- return packageName.replace(/^@/, "").replace(/[\/\\]/g, "__").replace(/[^a-zA-Z0-9._-]/g, "_");
599
+ function shouldSkipProjectSourcePath(filePath) {
600
+ return filePath.split(/[\\/]+/).some((segment) => {
601
+ const lower = segment.toLowerCase();
602
+ return lower === ".git" || lower === ".openpond" || lower === "node_modules" || lower === ".next" || lower === ".turbo" || lower.startsWith(".env");
603
+ });
701
604
  }
702
- function resolveLocalOpenPondAgentSdkMaterializationSource(projectPath, packageJson) {
703
- const versionSpec = readOpenPondAgentSdkVersionSpec(packageJson);
704
- if (versionSpec?.startsWith("file:")) {
705
- const candidate = path2.resolve(projectPath, versionSpec.slice("file:".length));
706
- if (isOpenPondAgentSdkPackageRoot(candidate)) {
707
- return {
708
- kind: "package_root",
709
- packageRoot: candidate,
710
- dependencyBaseDir: candidate,
711
- packageJson: JSON.parse(
712
- readFileSyncUtf8(path2.join(candidate, "package.json"))
713
- )
714
- };
605
+ async function resolveProjectSourceUploadBranch(projectPath, options) {
606
+ const explicit = optionString2(options, "branch");
607
+ if (explicit) return explicit;
608
+ const branch = await runCommand2("git", ["branch", "--show-current"], {
609
+ cwd: projectPath
610
+ });
611
+ if (branch.code !== 0) return null;
612
+ return branch.stdout.trim() || null;
613
+ }
614
+ async function collectProjectSourceUploadEntries(projectPath) {
615
+ const sourcePaths = await collectProjectSourceUploadPaths(projectPath);
616
+ if (sourcePaths.length === 0) {
617
+ throw new Error("no source files found to upload");
618
+ }
619
+ if (sourcePaths.length > PROJECT_SOURCE_UPLOAD_MAX_FILES) {
620
+ throw new Error(
621
+ `too many source files to upload: ${sourcePaths.length} > ${PROJECT_SOURCE_UPLOAD_MAX_FILES}`
622
+ );
623
+ }
624
+ const sortedSourcePaths = sourcePaths.sort();
625
+ const filesToUpload = (await mapWithConcurrency(sortedSourcePaths, PROJECT_SOURCE_UPLOAD_CONCURRENCY, async (sourcePath) => {
626
+ const absolutePath = path4.resolve(projectPath, sourcePath);
627
+ const relative = path4.relative(projectPath, absolutePath);
628
+ if (relative.startsWith("..") || path4.isAbsolute(relative)) {
629
+ throw new Error(`source path escapes project: ${sourcePath}`);
715
630
  }
716
- if (isLocalNpmTarball(candidate)) {
717
- const tarballContents = readFileSync2(candidate);
718
- const tarballPackageJson = readPackageJsonFromNpmTarball(tarballContents);
719
- if (tarballPackageJson.name === "openpond-agent-sdk") {
720
- return {
721
- kind: "tarball",
722
- tarballPath: candidate,
723
- tarballContents,
724
- dependencyBaseDir: path2.dirname(candidate),
725
- packageJson: tarballPackageJson
726
- };
727
- }
631
+ const stat = await fs2.stat(absolutePath);
632
+ if (!stat.isFile()) return null;
633
+ if (stat.size > PROJECT_SOURCE_UPLOAD_MAX_FILE_BYTES) {
634
+ throw new Error(
635
+ `source file is too large: ${sourcePath} (${stat.size} bytes)`
636
+ );
728
637
  }
729
- }
730
- if (versionSpec?.startsWith("workspace:")) {
731
- const candidate = findOpenPondAgentSdkPackageRootInAncestors(projectPath);
732
- if (candidate) {
733
- return {
734
- kind: "package_root",
735
- packageRoot: candidate,
736
- dependencyBaseDir: candidate,
737
- packageJson: JSON.parse(
738
- readFileSyncUtf8(path2.join(candidate, "package.json"))
739
- )
740
- };
638
+ return {
639
+ path: sourcePath.replace(/\\/g, "/"),
640
+ absolutePath,
641
+ size: stat.size,
642
+ mtimeMs: Math.trunc(stat.mtimeMs),
643
+ ctimeMs: Math.trunc(stat.ctimeMs)
644
+ };
645
+ })).filter((file) => file !== null);
646
+ let totalBytes = 0;
647
+ for (const file of filesToUpload) {
648
+ totalBytes += file.size;
649
+ if (totalBytes > PROJECT_SOURCE_UPLOAD_MAX_BYTES) {
650
+ throw new Error(
651
+ `source upload is too large: ${totalBytes} > ${PROJECT_SOURCE_UPLOAD_MAX_BYTES}`
652
+ );
741
653
  }
742
654
  }
743
- return null;
744
- }
745
- function findOpenPondAgentSdkPackageRootInAncestors(projectPath) {
746
- let current = path2.resolve(projectPath);
747
- while (true) {
748
- if (isOpenPondAgentSdkPackageRoot(current)) return current;
749
- const parent = path2.dirname(current);
750
- if (parent === current) return null;
751
- current = parent;
752
- }
753
- }
754
- function isOpenPondAgentSdkPackageRoot(candidate) {
755
- const packageJsonPath = path2.join(candidate, "package.json");
756
- if (!existsSync2(packageJsonPath)) return false;
757
- try {
758
- const parsed = JSON.parse(readFileSyncUtf8(packageJsonPath));
759
- return parsed.name === "openpond-agent-sdk";
760
- } catch {
761
- return false;
762
- }
655
+ const cache = await readSourceUploadCache(projectPath);
656
+ const materialized = await mapWithConcurrency(
657
+ filesToUpload,
658
+ PROJECT_SOURCE_UPLOAD_CONCURRENCY,
659
+ async (file) => materializeSourceUploadFile(file, cache)
660
+ );
661
+ await writeSourceUploadCache(projectPath, materialized).catch(() => {
662
+ });
663
+ const entries = materialized.map((item) => item.entry);
664
+ return {
665
+ entries,
666
+ fileCount: entries.length,
667
+ totalBytes,
668
+ limits: PROJECT_SOURCE_UPLOAD_LIMITS,
669
+ transport: PROJECT_SOURCE_UPLOAD_TRANSPORT
670
+ };
763
671
  }
764
- function isLocalNpmTarball(candidate) {
765
- if (!existsSync2(candidate)) return false;
766
- try {
767
- return statSync(candidate).isFile() && (candidate.endsWith(".tgz") || candidate.endsWith(".tar.gz"));
768
- } catch {
769
- return false;
770
- }
672
+ async function mapWithConcurrency(items, concurrency, mapper) {
673
+ const results = new Array(items.length);
674
+ let nextIndex = 0;
675
+ const workerCount = Math.max(1, Math.min(concurrency, items.length));
676
+ await Promise.all(
677
+ Array.from({ length: workerCount }, async () => {
678
+ while (nextIndex < items.length) {
679
+ const index = nextIndex;
680
+ nextIndex += 1;
681
+ results[index] = await mapper(items[index], index);
682
+ }
683
+ })
684
+ );
685
+ return results;
771
686
  }
772
- function readPackageJsonFromNpmTarball(tarballContents) {
773
- const tarContents = gunzipSync(tarballContents);
774
- let offset = 0;
775
- while (offset + 512 <= tarContents.length) {
776
- const header = tarContents.subarray(offset, offset + 512);
777
- if (header.every((byte) => byte === 0)) break;
778
- const name = readTarString(header, 0, 100);
779
- const prefix = readTarString(header, 345, 155);
780
- const entryPath = prefix ? `${prefix}/${name}` : name;
781
- const sizeText = readTarString(header, 124, 12).trim();
782
- const size = Number.parseInt(sizeText || "0", 8);
783
- if (!Number.isFinite(size) || size < 0) {
784
- throw new Error("failed to read openpond-agent-sdk tarball: invalid entry size");
785
- }
786
- const dataStart = offset + 512;
787
- const dataEnd = dataStart + size;
788
- if (entryPath === "package/package.json") {
789
- return JSON.parse(
790
- tarContents.subarray(dataStart, dataEnd).toString("utf8")
687
+ async function collectProjectSourceUploadPaths(projectPath) {
688
+ const files = await runCommand2(
689
+ "git",
690
+ ["ls-files", "-z", "--cached", "--others", "--exclude-standard"],
691
+ { cwd: projectPath }
692
+ );
693
+ if (files.code !== 0) {
694
+ if (existsSync4(path4.join(projectPath, ".git"))) {
695
+ throw new Error(
696
+ `git ls-files failed: ${files.stderr.trim() || files.stdout.trim() || "unknown error"}`
791
697
  );
792
698
  }
793
- offset = dataStart + Math.ceil(size / 512) * 512;
699
+ return collectFilesystemProjectSourceUploadPaths(projectPath);
794
700
  }
795
- throw new Error("failed to read openpond-agent-sdk tarball: missing package.json");
701
+ return files.stdout.split("\0").map((filePath) => filePath.trim()).filter(Boolean).filter((filePath) => {
702
+ const normalized = filePath.replace(/\\/g, "/");
703
+ return isSafeProjectSourcePath(normalized) && !shouldSkipProjectSourcePath(normalized);
704
+ });
796
705
  }
797
- function readTarString(header, start, length) {
798
- const field = header.subarray(start, start + length);
799
- const nullIndex = field.indexOf(0);
800
- return field.subarray(0, nullIndex === -1 ? field.length : nullIndex).toString("utf8");
706
+ async function collectFilesystemProjectSourceUploadPaths(projectPath) {
707
+ const sourcePaths = [];
708
+ async function visit(relativeDir) {
709
+ const absoluteDir = path4.join(projectPath, relativeDir);
710
+ const entries = await fs2.readdir(absoluteDir, { withFileTypes: true });
711
+ for (const entry of entries) {
712
+ const relativePath = path4.join(relativeDir, entry.name).replace(/\\/g, "/");
713
+ if (!isSafeProjectSourcePath(relativePath) || shouldSkipProjectSourcePath(relativePath)) {
714
+ continue;
715
+ }
716
+ if (entry.isDirectory()) {
717
+ await visit(relativePath);
718
+ continue;
719
+ }
720
+ if (entry.isFile()) sourcePaths.push(relativePath);
721
+ }
722
+ }
723
+ try {
724
+ await visit("");
725
+ } catch (error) {
726
+ throw new Error(
727
+ `filesystem source scan failed: ${error instanceof Error ? error.message : String(error)}`
728
+ );
729
+ }
730
+ return sourcePaths;
801
731
  }
802
- function rewriteAgentSdkPackageJsonForMaterialization(packageJson, dependencyTarballs, packageManager) {
803
- const rewritten = { ...packageJson };
804
- const dependencies = recordCopy(rewritten.dependencies);
805
- const overrides = recordCopy(rewritten.overrides);
806
- dependencies["openpond-agent-sdk"] = AGENT_SDK_MATERIALIZED_DEPENDENCY_SPEC;
807
- for (const tarball of dependencyTarballs) {
808
- const dependencySpec = `file:${tarball.path}`;
809
- dependencies[tarball.packageName] = dependencySpec;
810
- overrides[tarball.packageName] = dependencySpec;
732
+ async function collectAgentSdkProjectSourceUploadEntries(projectPath, existingEntries) {
733
+ if (!isAgentSdkProject(projectPath)) {
734
+ return {
735
+ entries: [],
736
+ generatedManifestPath: null,
737
+ synthesizedOpenPondYaml: false,
738
+ uploadMetadataPath: null,
739
+ uploadMetadata: null,
740
+ uploadMetadataHash: null
741
+ };
811
742
  }
812
- rewritten.dependencies = dependencies;
813
- if (Object.keys(overrides).length > 0) {
814
- rewritten.overrides = overrides;
743
+ await runAgentSdkProjectCheck(projectPath, "build");
744
+ await runAgentSdkProjectCheck(projectPath, "validate");
745
+ await runAgentSdkProjectCheck(projectPath, "eval");
746
+ const packageJson = readAgentSdkProjectPackageJson(projectPath);
747
+ const materializedDependency = await buildAgentSdkMaterializedDependency(
748
+ projectPath,
749
+ packageJson
750
+ );
751
+ const manifestPath = ".openpond/openpond-manifest.preview.yaml";
752
+ const manifestSource = await fs2.readFile(path4.join(projectPath, manifestPath), "utf8");
753
+ const openPondYamlSource = sanitizeAgentSdkRuntimeManifestForOpenPondYaml(
754
+ manifestSource,
755
+ materializedDependency?.dependencySetup ?? null
756
+ );
757
+ const manifestResult = validateSandboxTemplateYaml(openPondYamlSource);
758
+ if (!manifestResult.ok) {
759
+ throw new Error(
760
+ `generated ${manifestPath} failed sandbox-template validation after openpond.yaml sanitization:
761
+ ${formatSandboxTemplateDiagnostics(
762
+ manifestResult.diagnostics
763
+ )}`
764
+ );
815
765
  }
816
- if (packageManager === "unknown") {
817
- rewritten.packageManager = OPENPOND_PNPM_PACKAGE_MANAGER;
766
+ const entries = [];
767
+ if (materializedDependency?.rewrittenPackageJson) {
768
+ entries.push(
769
+ projectSourceUploadTextEntry(
770
+ "package.json",
771
+ `${JSON.stringify(materializedDependency.rewrittenPackageJson, null, 2)}
772
+ `
773
+ )
774
+ );
818
775
  }
819
- for (const key of ["devDependencies", "peerDependencies"]) {
820
- const entries = recordCopy(rewritten[key]);
821
- delete entries["openpond-agent-sdk"];
822
- if (Object.keys(entries).length > 0) {
823
- rewritten[key] = entries;
824
- } else {
825
- delete rewritten[key];
826
- }
776
+ if (materializedDependency?.pnpmWorkspaceSource) {
777
+ entries.push(
778
+ projectSourceUploadTextEntry(
779
+ "pnpm-workspace.yaml",
780
+ materializedDependency.pnpmWorkspaceSource
781
+ )
782
+ );
827
783
  }
828
- return rewritten;
829
- }
830
- function buildAgentSdkPnpmWorkspaceSource(projectPath, dependencyTarballs) {
831
- const workspacePath = path2.join(projectPath, "pnpm-workspace.yaml");
832
- let workspace = {};
833
- if (existsSync2(workspacePath)) {
834
- const parsed = yaml.load(readFileSyncUtf8(workspacePath));
835
- workspace = parsed && typeof parsed === "object" && !Array.isArray(parsed) ? { ...parsed } : {};
784
+ for (const tarball of materializedDependency?.tarballs ?? []) {
785
+ entries.push(
786
+ projectSourceUploadBufferEntry(tarball.path, tarball.contents)
787
+ );
836
788
  }
837
- if (!Array.isArray(workspace.packages)) workspace.packages = [];
838
- const overrides = recordCopy(workspace.overrides);
839
- for (const tarball of dependencyTarballs) {
840
- overrides[tarball.packageName] = `file:${tarball.path}`;
789
+ const generatedArtifactPaths = await collectAgentSdkGeneratedArtifactPaths(projectPath);
790
+ for (const artifactPath of generatedArtifactPaths) {
791
+ entries.push(await projectSourceUploadFileEntry(projectPath, artifactPath));
841
792
  }
842
- workspace.overrides = overrides;
843
- const allowBuilds = recordCopy(workspace.allowBuilds);
844
- allowBuilds.esbuild = true;
845
- const vendoredEsbuild = dependencyTarballs.find(
846
- (tarball) => tarball.packageName === "esbuild"
793
+ const hasAuthoredOpenPondYaml = existingEntries.some((entry) => entry.path === "openpond.yaml") || existsSync4(path4.join(projectPath, "openpond.yaml"));
794
+ if (!hasAuthoredOpenPondYaml) {
795
+ entries.push(projectSourceUploadTextEntry("openpond.yaml", openPondYamlSource));
796
+ } else {
797
+ const authoredSource = await fs2.readFile(path4.join(projectPath, "openpond.yaml"), "utf8");
798
+ const authoredResult = validateSandboxTemplateYaml(authoredSource);
799
+ if (!authoredResult.ok) {
800
+ throw new Error(
801
+ `authored openpond.yaml failed sandbox-template validation:
802
+ ${formatSandboxTemplateDiagnostics(
803
+ authoredResult.diagnostics
804
+ )}`
805
+ );
806
+ }
807
+ }
808
+ const uploadMetadata = await buildAgentSdkSourceUploadMetadata(projectPath, {
809
+ packageJson,
810
+ generatedManifestPath: manifestPath,
811
+ generatedArtifactPaths,
812
+ synthesizedOpenPondYaml: !hasAuthoredOpenPondYaml,
813
+ openPondYamlSource,
814
+ dependencySetup: materializedDependency?.dependencySetup ?? null
815
+ });
816
+ const uploadMetadataSource = `${JSON.stringify(uploadMetadata, null, 2)}
817
+ `;
818
+ const uploadMetadataHash = {
819
+ sha256: sha256Hex(Buffer.from(uploadMetadataSource, "utf8")),
820
+ sizeBytes: Buffer.byteLength(uploadMetadataSource, "utf8")
821
+ };
822
+ entries.push(
823
+ projectSourceUploadTextEntry(
824
+ AGENT_SDK_SOURCE_UPLOAD_METADATA_PATH,
825
+ uploadMetadataSource
826
+ )
847
827
  );
848
- if (vendoredEsbuild) {
849
- allowBuilds[`esbuild@file:${vendoredEsbuild.path}`] = true;
828
+ return {
829
+ entries,
830
+ generatedManifestPath: manifestPath,
831
+ synthesizedOpenPondYaml: !hasAuthoredOpenPondYaml,
832
+ uploadMetadataPath: AGENT_SDK_SOURCE_UPLOAD_METADATA_PATH,
833
+ uploadMetadata,
834
+ uploadMetadataHash
835
+ };
836
+ }
837
+ async function buildAgentSdkSourceUploadMetadata(projectPath, params) {
838
+ const packageManager = detectAgentSdkPackageManager(projectPath, params.packageJson);
839
+ const commandHints = buildAgentSdkCommandHints(params.packageJson, packageManager);
840
+ const setupRequirements = await collectAgentSdkSourceSetupRequirements(projectPath);
841
+ const artifactHashes = {};
842
+ for (const artifactPath of params.generatedArtifactPaths) {
843
+ const absolutePath = path4.join(projectPath, artifactPath);
844
+ if (!existsSync4(absolutePath)) continue;
845
+ const contents = await fs2.readFile(absolutePath);
846
+ artifactHashes[artifactPath] = {
847
+ sha256: sha256Hex(contents),
848
+ sizeBytes: contents.byteLength
849
+ };
850
850
  }
851
- workspace.allowBuilds = allowBuilds;
852
- workspace.supportedArchitectures = {
853
- os: ["linux"],
854
- cpu: ["x64", "arm64"],
855
- libc: ["glibc", "musl"]
851
+ artifactHashes["openpond.yaml"] = {
852
+ sha256: sha256Hex(Buffer.from(params.openPondYamlSource, "utf8")),
853
+ sizeBytes: Buffer.byteLength(params.openPondYamlSource, "utf8")
854
+ };
855
+ return {
856
+ schema: "openpond.agent.source_upload.v1",
857
+ sourceTreeMode: "typescript_agent_sdk",
858
+ packageManager,
859
+ sdk: {
860
+ packageName: "openpond-agent-sdk",
861
+ versionSpec: readOpenPondAgentSdkVersionSpec2(params.packageJson)
862
+ },
863
+ commands: commandHints,
864
+ ...params.dependencySetup ? { dependencySetup: params.dependencySetup } : {},
865
+ ...setupRequirements.length > 0 ? { setupRequirements } : {},
866
+ generatedManifestPath: params.generatedManifestPath,
867
+ synthesizedOpenPondYaml: params.synthesizedOpenPondYaml,
868
+ openPondYamlMode: params.synthesizedOpenPondYaml ? "synthesized" : "authored",
869
+ artifactHashes
856
870
  };
857
- return yaml.dump(workspace, { lineWidth: 120, noRefs: true });
858
871
  }
859
- function recordStringMap(value) {
860
- if (!value || typeof value !== "object" || Array.isArray(value)) return {};
861
- const entries = {};
862
- for (const [key, entryValue] of Object.entries(value)) {
863
- if (typeof entryValue === "string" && entryValue.trim()) {
864
- entries[key] = entryValue.trim();
872
+ async function collectAgentSdkGeneratedArtifactPaths(projectPath) {
873
+ const generatedArtifacts = /* @__PURE__ */ new Set();
874
+ for (const artifactPath of AGENT_SDK_GENERATED_ARTIFACTS) {
875
+ if (existsSync4(path4.join(projectPath, artifactPath))) {
876
+ generatedArtifacts.add(artifactPath);
865
877
  }
866
878
  }
867
- return entries;
868
- }
869
- function recordCopy(value) {
870
- if (!value || typeof value !== "object" || Array.isArray(value)) return {};
871
- return { ...value };
879
+ for (const skillArtifactPath of await collectAgentSdkGeneratedSkillArtifactPaths(projectPath)) {
880
+ generatedArtifacts.add(skillArtifactPath);
881
+ }
882
+ return Array.from(generatedArtifacts).sort((left, right) => left.localeCompare(right));
872
883
  }
873
- function recordArray(value) {
874
- return Array.isArray(value) ? value.filter(
875
- (item) => Boolean(item) && typeof item === "object" && !Array.isArray(item)
876
- ) : [];
884
+ async function collectAgentSdkGeneratedSkillArtifactPaths(projectPath) {
885
+ const skillsRoot = path4.join(projectPath, AGENT_SDK_GENERATED_SKILLS_DIR);
886
+ if (!existsSync4(skillsRoot)) return [];
887
+ const results = [];
888
+ async function visit(relativeDir) {
889
+ const absoluteDir = path4.join(projectPath, relativeDir);
890
+ const entries = await fs2.readdir(absoluteDir, { withFileTypes: true });
891
+ entries.sort((left, right) => left.name.localeCompare(right.name));
892
+ for (const entry of entries) {
893
+ const relativePath = path4.join(relativeDir, entry.name).replace(/\\/g, "/");
894
+ if (!isSafeProjectSourcePath(relativePath)) continue;
895
+ if (entry.isDirectory()) {
896
+ await visit(relativePath);
897
+ continue;
898
+ }
899
+ if (entry.isFile()) results.push(relativePath);
900
+ }
901
+ }
902
+ await visit(AGENT_SDK_GENERATED_SKILLS_DIR);
903
+ return results;
877
904
  }
878
- function text(value) {
879
- return typeof value === "string" && value.trim() ? value.trim() : null;
905
+ async function collectAgentSdkSourceSetupRequirements(projectPath) {
906
+ const requirements = [];
907
+ const seen = /* @__PURE__ */ new Set();
908
+ for (const relativePath of [
909
+ ".openpond/action-registry.json",
910
+ ".openpond/agent-manifest.json"
911
+ ]) {
912
+ const payload = await readJsonFileIfExists(path4.join(projectPath, relativePath));
913
+ if (!payload) continue;
914
+ for (const actionRecord of [
915
+ ...recordArray(payload.actions),
916
+ ...recordArray(payload.actionCatalog)
917
+ ]) {
918
+ const actionId = text(actionRecord.id) ?? text(actionRecord.name);
919
+ const actionName = text(actionRecord.name) ?? actionId;
920
+ if (!actionId && !actionName) continue;
921
+ for (const setupRecord of recordArray(actionRecord.setupRequirements)) {
922
+ const setupRequirement = { ...setupRecord };
923
+ if (actionId) setupRequirement.actionId = actionId;
924
+ if (actionName && actionName !== actionId) setupRequirement.actionName = actionName;
925
+ const key = setupRequirementIdentity(setupRequirement);
926
+ if (seen.has(key)) continue;
927
+ seen.add(key);
928
+ requirements.push(setupRequirement);
929
+ }
930
+ }
931
+ }
932
+ return requirements;
880
933
  }
881
- function agentSdkDependencyInstallCommand(packageManager) {
882
- if (packageManager === "npm") return "npm install --offline";
883
- if (packageManager === "pnpm") return "pnpm install --offline";
884
- if (packageManager === "yarn") return "yarn install --offline";
885
- if (packageManager === "bun") return "bun install --offline";
886
- return "pnpm install --offline";
934
+ async function readJsonFileIfExists(filePath) {
935
+ try {
936
+ const parsed = JSON.parse(await fs2.readFile(filePath, "utf8"));
937
+ return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : null;
938
+ } catch {
939
+ return null;
940
+ }
887
941
  }
888
- function sha256Hex(contents) {
889
- return createHash("sha256").update(contents).digest("hex");
942
+ function setupRequirementIdentity(record) {
943
+ return [
944
+ text(record.actionId) ?? "",
945
+ text(record.actionName) ?? "",
946
+ text(record.kind) ?? text(record.type) ?? "",
947
+ text(record.label) ?? text(record.name) ?? text(record.key) ?? text(record.provider) ?? text(record.tool) ?? text(record.command) ?? text(record.packageName) ?? ""
948
+ ].join(":");
890
949
  }
891
- function dependencySetupCommands(value) {
892
- if (!value || typeof value !== "object" || Array.isArray(value)) return [];
893
- const record = value;
894
- if (Array.isArray(record.commands)) {
895
- return record.commands.filter(
896
- (command) => typeof command === "string" && command.trim() !== ""
897
- );
898
- }
899
- return typeof record.installCommand === "string" && record.installCommand.trim() ? [record.installCommand.trim()] : [];
950
+ function readAgentSdkProjectPackageJson(projectPath) {
951
+ const packageJsonPath = path4.join(projectPath, "package.json");
952
+ return JSON.parse(readFileSyncUtf8(packageJsonPath));
900
953
  }
901
- function mergeManifestSetupCommands(manifest, commands) {
902
- if (commands.length === 0) return manifest;
903
- const setup = manifest.setup && typeof manifest.setup === "object" && !Array.isArray(manifest.setup) ? recordCopy(manifest.setup) : {};
904
- const existingCommands = Array.isArray(setup.commands) ? setup.commands.filter(
905
- (command) => typeof command === "string" && command.trim() !== ""
906
- ) : [];
907
- const mergedCommands = [...commands];
908
- for (const command of existingCommands) {
909
- if (!mergedCommands.includes(command)) mergedCommands.push(command);
910
- }
954
+ function buildAgentSdkCommandHints(packageJson, packageManager) {
911
955
  return {
912
- ...manifest,
913
- setup: {
914
- ...setup,
915
- commands: mergedCommands
916
- }
956
+ inspect: buildAgentSdkCommandHint(
957
+ packageJson,
958
+ packageManager,
959
+ "agent:inspect",
960
+ "openpond-agent inspect --json"
961
+ ),
962
+ build: buildAgentSdkCommandHint(
963
+ packageJson,
964
+ packageManager,
965
+ "agent:build",
966
+ "openpond-agent build"
967
+ ),
968
+ validate: buildAgentSdkCommandHint(
969
+ packageJson,
970
+ packageManager,
971
+ "agent:validate",
972
+ "openpond-agent validate"
973
+ ),
974
+ eval: buildAgentSdkCommandHint(
975
+ packageJson,
976
+ packageManager,
977
+ "agent:eval",
978
+ "openpond-agent eval"
979
+ )
917
980
  };
918
981
  }
919
- function sanitizeAgentSdkRuntimeManifestForOpenPondYaml(source, dependencySetup) {
920
- const parsed = yaml.load(source);
921
- if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
922
- return `${AGENT_SDK_SYNTHESIZED_OPENPOND_YAML_SENTINEL}
923
- ${source}`;
924
- }
925
- const manifest = mergeManifestSetupCommands(
926
- { ...parsed },
927
- dependencySetupCommands(dependencySetup)
928
- );
929
- delete manifest.schema;
930
- sanitizeGeneratedManifestNamedCommands(manifest, "actions");
931
- sanitizeGeneratedManifestNamedCommands(manifest, "services");
932
- return `${AGENT_SDK_SYNTHESIZED_OPENPOND_YAML_SENTINEL}
933
- ${yaml.dump(manifest, { lineWidth: -1, noRefs: true })}`;
982
+ function buildAgentSdkCommandHint(packageJson, packageManager, scriptName, fallback) {
983
+ const scripts = packageJson.scripts;
984
+ const hasScript = scripts && typeof scripts === "object" && !Array.isArray(scripts) && typeof scripts[scriptName] === "string";
985
+ if (!hasScript) return fallback;
986
+ return agentSdkRunScriptCommand(packageManager, scriptName);
934
987
  }
935
- function sanitizeGeneratedManifestNamedCommands(manifest, key) {
936
- if (!Array.isArray(manifest[key])) return;
937
- manifest[key] = manifest[key].map((entry) => {
938
- if (!entry || typeof entry !== "object" || Array.isArray(entry)) {
939
- return entry;
988
+ function readOpenPondAgentSdkVersionSpec2(packageJson) {
989
+ for (const key of ["dependencies", "devDependencies", "peerDependencies"]) {
990
+ const dependencies = packageJson[key];
991
+ if (!dependencies || typeof dependencies !== "object" || Array.isArray(dependencies)) {
992
+ continue;
940
993
  }
941
- const sanitized = { ...entry };
942
- delete sanitized.id;
943
- delete sanitized.label;
944
- return sanitized;
945
- });
946
- }
947
- function isAgentSdkProject(projectPath) {
948
- if (!existsSync2(path2.join(projectPath, "agent", "agent.ts"))) return false;
949
- const packageJsonPath = path2.join(projectPath, "package.json");
950
- if (!existsSync2(packageJsonPath)) return false;
951
- try {
952
- const parsed = JSON.parse(readFileSyncUtf8(packageJsonPath));
953
- return Boolean(
954
- parsed.dependencies?.["openpond-agent-sdk"] || parsed.devDependencies?.["openpond-agent-sdk"] || parsed.peerDependencies?.["openpond-agent-sdk"]
955
- );
956
- } catch {
957
- return false;
994
+ const value = dependencies["openpond-agent-sdk"];
995
+ if (typeof value === "string" && value.trim()) return value.trim();
958
996
  }
959
- }
960
- function readFileSyncUtf8(filePath) {
961
- return readFileSync2(filePath, "utf8");
997
+ return null;
962
998
  }
963
999
  async function runAgentSdkProjectCheck(projectPath, commandName) {
964
1000
  const command = resolveLocalAgentSdkCommand(projectPath);
965
- const result = await runCommand(command.command, [...command.args, commandName, "--cwd", projectPath], {
1001
+ const result = await runCommand2(command.command, [...command.args, commandName, "--cwd", projectPath], {
966
1002
  cwd: projectPath
967
1003
  });
968
1004
  if (result.code !== 0) {
@@ -978,8 +1014,8 @@ async function projectSourceUploadFileEntry(projectPath, relativePath) {
978
1014
  if (!isSafeProjectSourcePath(normalized) || normalized.startsWith(".env")) {
979
1015
  throw new Error(`unsafe generated source path: ${relativePath}`);
980
1016
  }
981
- const absolutePath = path2.join(projectPath, normalized);
982
- const stat = await fs.stat(absolutePath);
1017
+ const absolutePath = path4.join(projectPath, normalized);
1018
+ const stat = await fs2.stat(absolutePath);
983
1019
  if (!stat.isFile()) {
984
1020
  throw new Error(`generated source path is not a file: ${relativePath}`);
985
1021
  }
@@ -989,7 +1025,7 @@ async function projectSourceUploadFileEntry(projectPath, relativePath) {
989
1025
  return {
990
1026
  path: normalized,
991
1027
  type: "file",
992
- contentsBase64: Buffer.from(await fs.readFile(absolutePath)).toString("base64")
1028
+ contentsBase64: Buffer.from(await fs2.readFile(absolutePath)).toString("base64")
993
1029
  };
994
1030
  }
995
1031
  function projectSourceUploadTextEntry(relativePath, contents) {
@@ -1230,7 +1266,7 @@ function buildAgentEditOpenInput(agentId, teamId, options) {
1230
1266
  ...initialMessage ? { initialMessage } : {},
1231
1267
  ...sourceRef ? { sourceRef } : {},
1232
1268
  ...baseSha ? { baseSha } : {},
1233
- createPipelineRequest: buildAgentEditCreatePipelineRequest({
1269
+ createImproveRun: buildAgentEditCreateImproveRun({
1234
1270
  agentId,
1235
1271
  teamId,
1236
1272
  projectId,
@@ -1241,15 +1277,17 @@ function buildAgentEditOpenInput(agentId, teamId, options) {
1241
1277
  })
1242
1278
  };
1243
1279
  }
1244
- function buildAgentEditCreatePipelineRequest(input) {
1280
+ function buildAgentEditCreateImproveRun(input) {
1245
1281
  const now = (/* @__PURE__ */ new Date()).toISOString();
1246
- return CreatePipelineRequestSchema.parse({
1247
- schemaVersion: "openpond.createPipeline.request.v1",
1248
- id: `create_request_${randomUUID()}`,
1249
- operation: "edit",
1250
- surface: "hosted_edit",
1282
+ return CreateImproveRunSchema.parse({
1283
+ schemaVersion: "openpond.createImprove.run.v1",
1284
+ id: `create_improve_${randomUUID()}`,
1285
+ revision: 0,
1286
+ operation: "improve",
1287
+ surface: "hosted_improve",
1251
1288
  command: "/edit",
1252
1289
  objective: input.objective,
1290
+ state: "planning",
1253
1291
  adapter: {
1254
1292
  kind: "hosted",
1255
1293
  sourceAuthority: "hosted_profile",
@@ -1267,7 +1305,9 @@ function buildAgentEditCreatePipelineRequest(input) {
1267
1305
  label: null
1268
1306
  },
1269
1307
  scope: {
1308
+ profileId: input.activeProfile,
1270
1309
  conversationId: null,
1310
+ originTurnId: null,
1271
1311
  workItemId: null,
1272
1312
  projectId: input.projectId,
1273
1313
  targetProject: {
@@ -1284,18 +1324,54 @@ function buildAgentEditCreatePipelineRequest(input) {
1284
1324
  attachments: [],
1285
1325
  apps: [],
1286
1326
  tools: [],
1327
+ signalRefs: [],
1328
+ evalRefs: [],
1287
1329
  targetRepoAssumptions: [`cloud project: ${input.projectId}`]
1288
1330
  },
1289
- targetAgent: {
1290
- agentId: input.agentId,
1331
+ target: {
1332
+ kind: "agent",
1333
+ id: input.agentId,
1291
1334
  displayName: null,
1292
1335
  defaultActionKey: `${input.agentId}.chat`
1293
1336
  },
1337
+ plan: null,
1338
+ workflowCapture: null,
1339
+ executionPolicy: {
1340
+ mode: "background",
1341
+ pauseAllowed: true,
1342
+ cancellationAllowed: true
1343
+ },
1344
+ iterationPolicy: {
1345
+ mode: "single",
1346
+ maximumAttempts: 1,
1347
+ currentAttempt: 0
1348
+ },
1349
+ approvalIds: [],
1350
+ questionIds: [],
1351
+ questions: [],
1352
+ candidates: [],
1353
+ evaluationReceipts: [],
1354
+ checkRefs: [],
1355
+ sourceRefs: [],
1356
+ externalExecutionRefs: [],
1357
+ localProfileCommit: null,
1358
+ hostedSourceCommit: input.baseSha,
1359
+ hostedSourceRef: input.sourceRef,
1360
+ releaseOutcome: {
1361
+ status: "not_requested",
1362
+ profileCommit: null,
1363
+ profileTag: null,
1364
+ releaseReceiptRef: null,
1365
+ updatedAt: null
1366
+ },
1367
+ blockedReason: null,
1368
+ appliedActionIds: [],
1294
1369
  metadata: {
1295
1370
  source: "cli_agent_edit_open",
1296
1371
  selectedCommand: "/edit"
1297
1372
  },
1298
- createdAt: now
1373
+ createdAt: now,
1374
+ updatedAt: now
1299
1375
  });
1300
1376
  }
1301
1377
  function buildCodingWorkItemChatInput(teamId, options) {