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.
- package/dist/chunks/{app-layer-53U5JVE7.js → app-layer-CUQQUVJS.js} +3 -3
- package/dist/chunks/{apps-MJ47WJNC.js → apps-TAYMUCWX.js} +3 -3
- package/dist/chunks/{chunk-DZUJ6XJC.js → chunk-3UOLQG6N.js} +1 -1
- package/dist/chunks/{chunk-4GLUNJLZ.js → chunk-3ZJIEA5F.js} +1 -1
- package/dist/chunks/{chunk-WQ2GF7XT.js → chunk-4HQURM3N.js} +1 -1
- package/dist/chunks/{chunk-ZIKHE5AY.js → chunk-4M4WAORL.js} +874 -798
- package/dist/chunks/{chunk-7KYOO25A.js → chunk-5RHZKQRK.js} +14 -76
- package/dist/chunks/{chunk-NC2GQQOT.js → chunk-D264OHTR.js} +4 -5
- package/dist/chunks/{chunk-XMW3PSI5.js → chunk-DCNAXREU.js} +179 -160
- package/dist/chunks/chunk-E5RVRUJB.js +1222 -0
- package/dist/chunks/{chunk-5X47XJC4.js → chunk-EONKWOLU.js} +2 -2
- package/dist/chunks/{chunk-VQX33YAG.js → chunk-FQW3AQVJ.js} +689 -121
- package/dist/chunks/{chunk-TQRWG54R.js → chunk-GYZYZGKS.js} +238 -69
- package/dist/chunks/{chunk-7HZBKUUB.js → chunk-OXQG773T.js} +33 -33
- package/dist/chunks/{chunk-BX4XSB2J.js → chunk-PJXJ2HRT.js} +1816 -1113
- package/dist/chunks/chunk-Q5MZCRJA.js +70 -0
- package/dist/chunks/{chunk-ETBF62DB.js → chunk-W2DJR3FA.js} +1 -1
- package/dist/chunks/{chunk-JWL5HCO5.js → chunk-XADW35CL.js} +3 -3
- package/dist/chunks/{chunk-IUTUUNAX.js → chunk-Y4F4XD5V.js} +1 -1
- package/dist/chunks/{cli-EP473A53.js → cli-WW5BVN5Z.js} +4 -3
- package/dist/chunks/{cli-H7PQLPKG.js → cli-ZOCP7X5M.js} +6 -6
- package/dist/chunks/{core-commands-KI53GSJF.js → core-commands-SYGK7K57.js} +4 -4
- package/dist/chunks/{extend-F4R3AI2G.js → extend-Q5HZ7TMA.js} +11 -11
- package/dist/chunks/fileFromPath-DHCRY3BD.js +2151 -0
- package/dist/chunks/{harness-WADDUNGU.js → harness-ZPBPQVAS.js} +3 -3
- package/dist/chunks/{help-TIEOIVOA.js → help-3V3TRQNX.js} +1 -1
- package/dist/chunks/{opchat-VYKKXDBO.js → opchat-OUPMEFE5.js} +5 -5
- package/dist/chunks/{organizations-LAACUOYE.js → organizations-5CSLBDAW.js} +4 -4
- package/dist/chunks/{profile-A75O7EZ4.js → profile-OQYSXHOG.js} +206 -166
- package/dist/chunks/{project-agent-JOZ6NRTW.js → project-agent-TBTWOUJF.js} +6 -7
- package/dist/chunks/{sandbox-command-Q72CAVQ7.js → sandbox-command-HCHPY7KW.js} +4 -4
- package/dist/chunks/{sandbox-template-KWCE3OJV.js → sandbox-template-PNTOZ6W3.js} +5 -6
- package/dist/chunks/{src-CBPRIWG5.js → src-C6MXLDYQ.js} +22 -6
- package/dist/chunks/{src-J4262EAE.js → src-GZT4UX6I.js} +81183 -53344
- package/dist/chunks/{teams-bot-KNY5OEXB.js → teams-bot-CQ76XI6T.js} +3 -3
- package/dist/chunks/workspaces-DHVVOTVR.js +93 -0
- package/dist/cli.js +10 -10
- package/dist/config.d.ts +0 -2
- package/dist/index.js +273 -69
- package/dist/profile/local-profile-types.d.ts +8 -2
- package/dist/profile/local-profile.d.ts +3 -1
- package/dist/sandbox/types/org-project-agent.d.ts +1 -2
- package/dist/web/assets/{AppsView-Bu-Nc3Ew.js → AppsView-CF2g-7FH.js} +1 -1
- package/dist/web/assets/{BrowserSidebar-CCguQ-DR.js → BrowserSidebar-lUsLUl20.js} +1 -1
- package/dist/web/assets/CloudWorkView-BnfGW4OV.js +1 -0
- package/dist/web/assets/{CommandMenu-CnodJFHD.js → CommandMenu-BsS4Bgb6.js} +1 -1
- package/dist/web/assets/{CommunityView-CIbjNUZr.js → CommunityView-C8qVOwlp.js} +1 -1
- package/dist/web/assets/ComposerCreateImproveStrip-C_LIpfSq.js +1 -0
- package/dist/web/assets/GetStartedView-Du533wOh.js +1 -0
- package/dist/web/assets/LabsRoute-CgKtVYTP.css +1 -0
- package/dist/web/assets/LabsRoute-yk8lNMQc.js +3 -0
- package/dist/web/assets/{NewProjectDialog-CaKiCoVS.js → NewProjectDialog-DH7wA1z9.js} +1 -1
- package/dist/web/assets/ProfileSettingsSection-CqnfjiCl.css +1 -0
- package/dist/web/assets/ProfileSettingsSection-D7JvMZdW.js +1 -0
- package/dist/web/assets/SettingsView-C9TgCaWG.js +63 -0
- package/dist/web/assets/TeamChatView-D_CE7br9.js +3 -0
- package/dist/web/assets/{TerminalOverlay-C1iP4OS1.js → TerminalOverlay-CC-VDSlp.js} +1 -1
- package/dist/web/assets/TrainingCreationPanel-NFCoaBUI.js +1 -0
- package/dist/web/assets/TrainingDraftPanel-BWEmVFjM.js +1 -0
- package/dist/web/assets/WorkspaceDiffPanel-SlLlGZM1.js +14 -0
- package/dist/web/assets/{WorkspaceEnvironmentMenu-B8JJbwIz.js → WorkspaceEnvironmentMenu-BAoMBTVD.js} +1 -1
- package/dist/web/assets/{WorkspaceGitDialogs-B4sp9BGn.js → WorkspaceGitDialogs-CVIFrzyl.js} +1 -1
- package/dist/web/assets/{WorkspaceMonacoEditor-BBqimG5X.js → WorkspaceMonacoEditor-0trp0-TI.js} +3 -3
- package/dist/web/assets/{boxes-DAaDUabq.js → boxes-CFihgX2z.js} +1 -1
- package/dist/web/assets/create-pipeline-request-AJWLMTyw.js +4 -0
- package/dist/web/assets/{cssMode-CBF1mieJ.js → cssMode-HvqfCFyP.js} +1 -1
- package/dist/web/assets/{git-commit-horizontal-CAickXpN.js → git-commit-horizontal-C5mUmACv.js} +1 -1
- package/dist/web/assets/{htmlMode-2u8OHtWO.js → htmlMode-C8btgUt-.js} +1 -1
- package/dist/web/assets/index-8H-GDlM5.css +1 -0
- package/dist/web/assets/index-D7Vr3zcV.js +192 -0
- package/dist/web/assets/index-DUqAiF57.js +1 -0
- package/dist/web/assets/{info-CQNTh78o.js → info-D0xuy5IB.js} +1 -1
- package/dist/web/assets/{jsonMode-C4CWXViX.js → jsonMode-5zVz9G0X.js} +1 -1
- package/dist/web/assets/{lspLanguageFeatures-CBs_BOlB.js → lspLanguageFeatures-DxlSSL7c.js} +1 -1
- package/dist/web/assets/{monaco.contribution-lOXpG2xQ.js → monaco.contribution-B1pWWwqT.js} +2 -2
- package/dist/web/assets/{monaco.contribution-sd3cFkcN.js → monaco.contribution-BKpVvKK9.js} +2 -2
- package/dist/web/assets/{monaco.contribution-C1LUxAKf.js → monaco.contribution-BXdXsSWI.js} +2 -2
- package/dist/web/assets/{monaco.contribution-Cpf6dWsh.js → monaco.contribution-CIjjzpUR.js} +2 -2
- package/dist/web/assets/{monitor-DsIswrMV.js → monitor-B4-9Shtp.js} +1 -1
- package/dist/web/assets/{play-CeRw21NV.js → play-BJdhBqQE.js} +1 -1
- package/dist/web/assets/{python-CXYq3BUl.js → python-CEK8J4w_.js} +1 -1
- package/dist/web/assets/{refresh-cw-N5b_6AP5.js → refresh-cw-DE0u_nmZ.js} +1 -1
- package/dist/web/assets/{reply-BSKjZrJg.js → reply-2MfLJ93n.js} +1 -1
- package/dist/web/assets/{save-D0oHH1a3.js → save-CBIVKaf8.js} +1 -1
- package/dist/web/assets/{toggleHighContrast-DRjlcwes.js → toggleHighContrast-CC73mtvA.js} +1 -1
- package/dist/web/assets/training-BY8siNUK.css +1 -0
- package/dist/web/assets/training-model-data-BXUCzS0p.js +1 -0
- package/dist/web/assets/{tsMode-x-1A7ZcB.js → tsMode-Bhn9wr_1.js} +1 -1
- package/dist/web/assets/{wifi-off-Dt52ofzh.js → wifi-off-BKTqnqj0.js} +1 -1
- package/dist/web/assets/{workers-Ciff6Dzi.js → workers-C_adgrEg.js} +1 -1
- package/dist/web/assets/{yaml-CB67Kxnz.js → yaml-DDRAcADU.js} +1 -1
- package/dist/web/index.html +2 -2
- package/package.json +1 -1
- package/dist/chunks/chunk-OG75GMVO.js +0 -1
- package/dist/web/assets/CloudWorkView-Dr3xqLE5.js +0 -1
- package/dist/web/assets/GetStartedView-C8nyH_PT.js +0 -1
- package/dist/web/assets/LabsExtensions-GtJzxDnK.js +0 -1
- package/dist/web/assets/LabsProfile-DG7rWYur.js +0 -1
- package/dist/web/assets/LabsRoute-D6MDHBzq.js +0 -2
- package/dist/web/assets/LabsRoute-TEt9j1vB.css +0 -1
- package/dist/web/assets/LabsSignals-BfsDN86w.js +0 -1
- package/dist/web/assets/LabsSignals-D6iA6Ryl.css +0 -1
- package/dist/web/assets/ProfileSettingsSection-DTQS2DVL.css +0 -1
- package/dist/web/assets/ProfileSettingsSection-DxEzoF3K.js +0 -1
- package/dist/web/assets/ProfileView-CEscW7Ru.js +0 -1
- package/dist/web/assets/SettingsView-JIRR_FO4.js +0 -63
- package/dist/web/assets/TeamChatView-B5M1ThhJ.js +0 -3
- package/dist/web/assets/TrainingSettingsSection-BDYvI2te.js +0 -1
- package/dist/web/assets/TrainingView-CoCFK6W3.js +0 -5
- package/dist/web/assets/WorkspaceDiffPanel-CMxKQeo7.js +0 -14
- package/dist/web/assets/index-BdY6A-YN.css +0 -1
- package/dist/web/assets/index-CU2qhUYV.js +0 -195
- package/dist/web/assets/index-Dz2B3-4C.js +0 -1
- package/dist/web/assets/settings-lists-BEg6LMcy.css +0 -1
- 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-
|
|
6
|
+
} from "./chunk-4HQURM3N.js";
|
|
7
7
|
import {
|
|
8
|
-
|
|
9
|
-
} from "./chunk-
|
|
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
|
-
|
|
21
|
-
} from "./chunk-
|
|
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-
|
|
29
|
+
} from "./chunk-OXQG773T.js";
|
|
30
30
|
|
|
31
|
-
// src/
|
|
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/
|
|
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
|
|
89
|
+
import { existsSync as existsSync3, promises as fs, readFileSync as readFileSync2, statSync } from "node:fs";
|
|
86
90
|
import { tmpdir } from "node:os";
|
|
87
|
-
import
|
|
91
|
+
import path3 from "node:path";
|
|
88
92
|
import { gunzipSync } from "node:zlib";
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
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
|
-
|
|
110
|
-
|
|
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
|
-
|
|
128
|
-
const
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
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
|
|
137
|
-
const
|
|
138
|
-
|
|
139
|
-
|
|
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
|
-
|
|
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
|
-
`
|
|
221
|
+
`failed to pack openpond-agent-sdk for source upload${details ? `:
|
|
222
|
+
${details}` : ""}`
|
|
144
223
|
);
|
|
145
224
|
}
|
|
146
|
-
const
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
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
|
-
`
|
|
253
|
+
`failed to pack openpond-agent-sdk dependency ${packageName}${details ? `:
|
|
254
|
+
${details}` : ""}`
|
|
158
255
|
);
|
|
159
256
|
}
|
|
160
|
-
|
|
161
|
-
|
|
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
|
-
`
|
|
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
|
-
|
|
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
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
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
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
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
|
|
224
|
-
const normalized = filePath.replace(/\\/g, "/");
|
|
225
|
-
return isSafeProjectSourcePath(normalized) && !shouldSkipProjectSourcePath(normalized);
|
|
226
|
-
});
|
|
304
|
+
return `${params.packageName}@${params.versionSpec}`;
|
|
227
305
|
}
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
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
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
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
|
|
350
|
+
return null;
|
|
253
351
|
}
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
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
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
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
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
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
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
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
|
-
|
|
307
|
-
|
|
308
|
-
|
|
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
|
-
|
|
312
|
-
|
|
313
|
-
|
|
419
|
+
rewritten.dependencies = dependencies;
|
|
420
|
+
if (Object.keys(overrides).length > 0) {
|
|
421
|
+
rewritten.overrides = overrides;
|
|
314
422
|
}
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
const
|
|
320
|
-
|
|
321
|
-
if (
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
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
|
-
|
|
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
|
-
|
|
360
|
-
const
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
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
|
-
|
|
374
|
-
|
|
375
|
-
|
|
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
|
-
|
|
402
|
-
|
|
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
|
-
|
|
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
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
const
|
|
410
|
-
|
|
411
|
-
|
|
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
|
-
|
|
425
|
-
return results;
|
|
474
|
+
return entries;
|
|
426
475
|
}
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
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
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
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
|
|
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
|
|
473
|
-
|
|
474
|
-
return JSON.parse(readFileSyncUtf8(packageJsonPath));
|
|
488
|
+
function sha256Hex(contents) {
|
|
489
|
+
return createHash("sha256").update(contents).digest("hex");
|
|
475
490
|
}
|
|
476
|
-
function
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
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 "
|
|
499
|
+
return typeof record.installCommand === "string" && record.installCommand.trim() ? [record.installCommand.trim()] : [];
|
|
493
500
|
}
|
|
494
|
-
function
|
|
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
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
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
|
|
523
|
-
const
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
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
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
if (!
|
|
536
|
-
|
|
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
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
541
|
+
const sanitized = { ...entry };
|
|
542
|
+
delete sanitized.id;
|
|
543
|
+
delete sanitized.label;
|
|
544
|
+
return sanitized;
|
|
545
|
+
});
|
|
542
546
|
}
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
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
|
|
552
|
-
|
|
553
|
-
|
|
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
|
-
|
|
564
|
-
|
|
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
|
-
|
|
606
|
-
|
|
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
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
const
|
|
628
|
-
|
|
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
|
|
684
|
-
|
|
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
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
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
|
|
700
|
-
return
|
|
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
|
|
703
|
-
const
|
|
704
|
-
if (
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
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
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
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
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
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
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
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
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
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
|
|
773
|
-
const
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
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
|
-
|
|
699
|
+
return collectFilesystemProjectSourceUploadPaths(projectPath);
|
|
794
700
|
}
|
|
795
|
-
|
|
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
|
|
798
|
-
const
|
|
799
|
-
|
|
800
|
-
|
|
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
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
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
|
-
|
|
813
|
-
|
|
814
|
-
|
|
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
|
-
|
|
817
|
-
|
|
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
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
}
|
|
776
|
+
if (materializedDependency?.pnpmWorkspaceSource) {
|
|
777
|
+
entries.push(
|
|
778
|
+
projectSourceUploadTextEntry(
|
|
779
|
+
"pnpm-workspace.yaml",
|
|
780
|
+
materializedDependency.pnpmWorkspaceSource
|
|
781
|
+
)
|
|
782
|
+
);
|
|
827
783
|
}
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
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
|
-
|
|
838
|
-
const
|
|
839
|
-
|
|
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
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
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
|
-
|
|
849
|
-
|
|
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
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
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
|
|
860
|
-
|
|
861
|
-
const
|
|
862
|
-
|
|
863
|
-
|
|
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
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
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
|
|
874
|
-
|
|
875
|
-
|
|
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
|
|
879
|
-
|
|
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
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
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
|
|
889
|
-
return
|
|
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
|
|
892
|
-
|
|
893
|
-
|
|
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
|
|
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
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
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
|
|
920
|
-
const
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
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
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
if (!
|
|
939
|
-
|
|
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
|
|
942
|
-
|
|
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
|
|
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 =
|
|
982
|
-
const stat = await
|
|
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
|
|
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
|
-
|
|
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
|
|
1280
|
+
function buildAgentEditCreateImproveRun(input) {
|
|
1245
1281
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
1246
|
-
return
|
|
1247
|
-
schemaVersion: "openpond.
|
|
1248
|
-
id: `
|
|
1249
|
-
|
|
1250
|
-
|
|
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
|
-
|
|
1290
|
-
|
|
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) {
|