openpond 0.0.36 → 0.0.38
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/README.md +4 -3
- package/dist/api/types.d.ts +0 -50
- package/dist/api.d.ts +2 -8
- package/dist/chunks/{app-layer-4AA4YYGK.js → app-layer-DPUJRNO2.js} +6 -3
- package/dist/chunks/{apps-V2JTB5MD.js → apps-AKBI6AS7.js} +16 -132
- package/dist/chunks/chunk-275WCETC.js +668 -0
- package/dist/chunks/{chunk-3DOOLZZM.js → chunk-43YI36NA.js} +1 -1
- package/dist/chunks/{chunk-NWQTF6O4.js → chunk-AHNFNWUN.js} +28 -3
- package/dist/chunks/{chunk-3JJBNVNX.js → chunk-AHPQTEIJ.js} +23 -19
- package/dist/chunks/chunk-FWLOFUPU.js +864 -0
- package/dist/chunks/{chunk-JAS6QZ2W.js → chunk-GB6VUZUA.js} +1 -1
- package/dist/chunks/{chunk-NVTC3XOA.js → chunk-GDZYDLEL.js} +8 -10
- package/dist/chunks/{chunk-G6WW2656.js → chunk-HLCTINEP.js} +1 -1
- package/dist/chunks/{chunk-MJT7EW5Q.js → chunk-HS2AGRDV.js} +1 -1
- package/dist/chunks/{chunk-CJSD5ADV.js → chunk-JWF37O5E.js} +2 -2
- package/dist/chunks/chunk-KSRWKXRB.js +12 -0
- package/dist/chunks/{chunk-7IPF4X3K.js → chunk-LZZM3IHS.js} +1004 -89
- package/dist/chunks/{chunk-TYYR7KWY.js → chunk-MPGSHXGF.js} +7 -5
- package/dist/chunks/chunk-MUMPWI4O.js +92 -0
- package/dist/chunks/{chunk-MSX2J653.js → chunk-QRM7XMAO.js} +5 -36
- package/dist/chunks/{chunk-65BVQIHR.js → chunk-SLMP353Q.js} +6 -6
- package/dist/chunks/chunk-T4QXKU5Y.js +1 -0
- package/dist/chunks/{chunk-GALAW74P.js → chunk-V35STJF4.js} +30 -11
- package/dist/chunks/{chunk-YLULZMWE.js → chunk-XCATKTK3.js} +51 -139
- package/dist/chunks/{chunk-LHYK6QO2.js → chunk-XEJ7XXUQ.js} +1 -0
- package/dist/chunks/{chunk-YRFQKUZD.js → chunk-XERQHYBO.js} +89 -27
- package/dist/chunks/{chunk-6L5WJF7T.js → chunk-YTJL6XPU.js} +2 -2
- package/dist/chunks/{chunk-NWVIUBJ3.js → chunk-ZI4GDAUB.js} +573 -1217
- package/dist/chunks/cli-2KBVNDRY.js +23 -0
- package/dist/chunks/{cli-RJHEE4FA.js → cli-7BKDWFNU.js} +5 -5
- package/dist/chunks/{core-commands-CQSPCVC4.js → core-commands-YN4RMWA3.js} +7 -4
- package/dist/chunks/{extend-4MZ75SHV.js → extend-REGNTBK3.js} +18 -13
- package/dist/chunks/extension-7K77DAVL.js +121 -0
- package/dist/chunks/{harness-YVZU42S7.js → harness-BHQRMXJR.js} +6 -3
- package/dist/chunks/{help-6SULYXVS.js → help-VREQNA4I.js} +2 -1
- package/dist/chunks/{opchat-XGS4AXHA.js → opchat-D63YTNSX.js} +12 -7
- package/dist/chunks/{organizations-4GFQ3NT2.js → organizations-I46KG7TC.js} +8 -5
- package/dist/chunks/{profile-VWMBIHIE.js → profile-WKZJHEPG.js} +11 -8
- package/dist/chunks/{project-agent-SQ6ODALG.js → project-agent-ZUC3YMCT.js} +10 -7
- package/dist/chunks/{sandbox-command-34S2V7BN.js → sandbox-command-AAOPFTI5.js} +7 -4
- package/dist/chunks/{sandbox-template-VP5HMGQI.js → sandbox-template-GKNVR4C5.js} +11 -7
- package/dist/chunks/{src-X3R3XIJT.js → src-MWDIK56B.js} +1997 -1247
- package/dist/chunks/{src-YHUMH6W6.js → src-RPW5TOPI.js} +3 -3
- package/dist/chunks/{teams-bot-EIVRNO5S.js → teams-bot-PSL3ZO6Z.js} +6 -3
- package/dist/chunks/{workspaces-2N52V3BI.js → workspaces-BPXC2DHT.js} +6 -2
- package/dist/cli.js +14 -11
- package/dist/client-types.d.ts +1 -9
- package/dist/client.d.ts +3 -3
- package/dist/index.js +27 -55
- package/dist/profile/local-profile-types.d.ts +1 -0
- package/dist/profile/profile-skills.d.ts +2 -0
- package/dist/web/assets/{AppDialog-j4N-gIi3.js → AppDialog-DrwJb_wG.js} +1 -1
- package/dist/web/assets/{AppsView-YiK3pqNb.js → AppsView-DPagLMsc.js} +1 -1
- package/dist/web/assets/{BrowserSidebar-BWFLEQ8j.js → BrowserSidebar-DMn2V8RV.js} +1 -1
- package/dist/web/assets/{CloudWorkView-3sS_1bhN.js → CloudWorkView-Cl_7mM3c.js} +1 -1
- package/dist/web/assets/{CommandMenu-B11OrTCq.js → CommandMenu-CHMQLez_.js} +1 -1
- package/dist/web/assets/{CommunityView-DXyXTWhP.js → CommunityView-DcHVDUk0.js} +1 -1
- package/dist/web/assets/{ComposerCreateImproveStrip-3NoRiJJq.js → ComposerCreateImproveStrip-BZ3Dgzmo.js} +1 -1
- package/dist/web/assets/{GetStartedView-CPV5lgVH.js → GetStartedView-DTRotFqz.js} +1 -1
- package/dist/web/assets/LabSkillSidebar-CVxtS9pd.css +1 -0
- package/dist/web/assets/LabSkillSidebar-D-PqFe1T.js +1 -0
- package/dist/web/assets/LabsRoute-BrJkBNig.css +1 -0
- package/dist/web/assets/LabsRoute-Dew1BwK5.js +3 -0
- package/dist/web/assets/MainChatThread-BaPxxzrw.js +2 -0
- package/dist/web/assets/{MakeAgentTutorialLearningPanel-C6F-kJQd.js → MakeAgentTutorialLearningPanel-CBsfnONQ.js} +2 -2
- package/dist/web/assets/{MarkdownText-CkVkr3P1.js → MarkdownText-DGLfAM_Z.js} +4 -4
- package/dist/web/assets/Messages-CIX9uTjX.js +10 -0
- package/dist/web/assets/NativeSkillSidebar-AP_uHn6g.js +1 -0
- package/dist/web/assets/{NewProjectDialog-DBMhkTvD.js → NewProjectDialog-C6lHkafU.js} +1 -1
- package/dist/web/assets/{PostTrainingLearningPanel-B1Rp7iIL.js → PostTrainingLearningPanel-CZEgPc8O.js} +2 -2
- package/dist/web/assets/{PostTrainingStatusPill-BGZ9h5eW.js → PostTrainingStatusPill-CeEpwUDB.js} +1 -1
- package/dist/web/assets/{ProfileSettingsSection-2NOHEz2b.js → ProfileSettingsSection-EumMLlEp.js} +1 -1
- package/dist/web/assets/RightChatPanelStack-MXBcx3zO.js +1 -0
- package/dist/web/assets/{SettingsView-uHhQnazW.css → SettingsView-Caljbns2.css} +1 -1
- package/dist/web/assets/SettingsView-DyURG_Uh.js +6 -0
- package/dist/web/assets/{TeamChatView-qVscSedQ.js → TeamChatView-D3v6aqJ3.js} +1 -1
- package/dist/web/assets/{TerminalOverlay-Bkw7XqMy.js → TerminalOverlay-BKl0p8pa.js} +1 -1
- package/dist/web/assets/{TrainingCreationPanel-COg1wvw8.js → TrainingCreationPanel-CfZQTuT5.js} +1 -1
- package/dist/web/assets/{TrainingDraftPanel-BNK2znmI.js → TrainingDraftPanel-DslRPSDW.js} +1 -1
- package/dist/web/assets/{UsageSettingsSection-CUxBaohC.js → UsageSettingsSection-zDAwzTGl.js} +1 -1
- package/dist/web/assets/WorkspaceDiffPanel-C_MZPPlL.js +14 -0
- package/dist/web/assets/{WorkspaceEnvironmentMenu-C0-mH7oF.js → WorkspaceEnvironmentMenu-BUAnn80j.js} +1 -1
- package/dist/web/assets/{WorkspaceGitDialogs-VvC2px0X.js → WorkspaceGitDialogs-Drbf4ujA.js} +1 -1
- package/dist/web/assets/{WorkspaceMonacoEditor-CUIwoHv1.js → WorkspaceMonacoEditor-DPGcG8fy.js} +3 -3
- package/dist/web/assets/{activity-BhqHgkfJ.js → activity-Dnr3jqb3.js} +1 -1
- package/dist/web/assets/{boxes-BpqUKFIm.js → boxes-BinC8UPn.js} +1 -1
- package/dist/web/assets/{chevron-up-BTn9DVRP.js → chevron-up-Bjp_-_Cb.js} +1 -1
- package/dist/web/assets/{circle-x-B9Qa8o5a.js → circle-x-ubnvEYuE.js} +1 -1
- package/dist/web/assets/{copy-BsYs6wBI.js → copy-B_ZCCUMz.js} +1 -1
- package/dist/web/assets/{create-pipeline-request-vxgKoAvv.js → create-pipeline-request-D6uLUxe9.js} +3 -3
- package/dist/web/assets/{cssMode-mw8RI2fR.js → cssMode-CKN9CcfG.js} +1 -1
- package/dist/web/assets/file-8HAMlTmQ.js +1 -0
- package/dist/web/assets/{git-branch-C7qQYFIs.js → git-branch-l2Zih3Bv.js} +1 -1
- package/dist/web/assets/{git-commit-horizontal-CbX4pTOA.js → git-commit-horizontal-Bxi8YPep.js} +1 -1
- package/dist/web/assets/{htmlMode-Cc4Czh_M.js → htmlMode-CeUcNhBZ.js} +1 -1
- package/dist/web/assets/index-BMFyOFRU.css +1 -0
- package/dist/web/assets/index-BzwcDzbT.js +1 -0
- package/dist/web/assets/index-KoQSSt_f.js +177 -0
- package/dist/web/assets/{info-BNGbwgtq.js → info-JTbDQxHx.js} +1 -1
- package/dist/web/assets/{jsonMode-CbqbqGVz.js → jsonMode-97z0Yz9u.js} +1 -1
- package/dist/web/assets/{lspLanguageFeatures-DKiKr5tH.js → lspLanguageFeatures-D4Tp-JmI.js} +1 -1
- package/dist/web/assets/{make-agent-tutorial-KKauJpB9.js → make-agent-tutorial-D6nBCgv-.js} +1 -1
- package/dist/web/assets/{monaco.contribution-Dxc4IxFM.js → monaco.contribution-B3j6oown.js} +2 -2
- package/dist/web/assets/{monaco.contribution-CNgwz_pw.js → monaco.contribution-BXHxPPWL.js} +2 -2
- package/dist/web/assets/{monaco.contribution-D_-wu578.js → monaco.contribution-C2P5zIzh.js} +2 -2
- package/dist/web/assets/{monaco.contribution-CdUAX47Q.js → monaco.contribution-C8c6OtGi.js} +2 -2
- package/dist/web/assets/{monitor-CNdx_GTg.js → monitor-kzHtxHnA.js} +1 -1
- package/dist/web/assets/{play-BLRANWaV.js → play-C-37dnR1.js} +1 -1
- package/dist/web/assets/{python-DYgDMu2R.js → python-CGpDXY7_.js} +1 -1
- package/dist/web/assets/{refresh-cw-BFjjwYNf.js → refresh-cw-BAaaPCXl.js} +1 -1
- package/dist/web/assets/{reply-D012cuZl.js → reply-9rehU13k.js} +1 -1
- package/dist/web/assets/{rotate-cw-CTfjlR4G.js → rotate-cw-C1Z_Xs23.js} +1 -1
- package/dist/web/assets/{save-B1zYlRyN.js → save-Cvxs3XyC.js} +1 -1
- package/dist/web/assets/{toggleHighContrast-D9XFH7EA.js → toggleHighContrast-CD42jH4g.js} +1 -1
- package/dist/web/assets/{tsMode-BU-tuKsY.js → tsMode-ZROIxEjv.js} +1 -1
- package/dist/web/assets/{upload-DU_81jvL.js → upload-DvCSGERK.js} +1 -1
- package/dist/web/assets/{wifi-off-TPsBnbGW.js → wifi-off-BIb94PkS.js} +1 -1
- package/dist/web/assets/{workers-NhWySRdT.js → workers-oYqbrVYG.js} +1 -1
- package/dist/web/assets/{yaml-DWXa_3ZL.js → yaml-WqBjNgOO.js} +1 -1
- package/dist/web/index.html +2 -2
- package/docs/command-reference.md +16 -1
- package/package.json +1 -1
- package/dist/chunks/cli-4JA3SIDE.js +0 -19
- package/dist/web/assets/LabsRoute-B_nsEZXy.js +0 -3
- package/dist/web/assets/LabsRoute-dNN-odU0.css +0 -1
- package/dist/web/assets/MainChatThread-Dg7p3R2O.js +0 -2
- package/dist/web/assets/Messages-C7uHGoFw.js +0 -10
- package/dist/web/assets/NativeSkillSidebar-BPpoHjEW.js +0 -1
- package/dist/web/assets/RightChatPanelStack-CLK7_zKe.js +0 -1
- package/dist/web/assets/SettingsView-BAqea_KX.js +0 -6
- package/dist/web/assets/WorkspaceDiffPanel-qfFj8IRq.js +0 -14
- package/dist/web/assets/credit-card-BCePAwMI.js +0 -1
- package/dist/web/assets/index-9tbdqUau.css +0 -1
- package/dist/web/assets/index-B_3z_lxq.js +0 -1
- package/dist/web/assets/index-Cr_RZ7GD.js +0 -177
- package/dist/web/tokens/eth.svg +0 -1
- package/dist/web/tokens/usdc.svg +0 -1
|
@@ -5,7 +5,7 @@ import {
|
|
|
5
5
|
SandboxTemplateManifestSchema,
|
|
6
6
|
SandboxTemplateValidationDiagnosticSchema,
|
|
7
7
|
validateConnectedAppToolCallRequest
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-XEJ7XXUQ.js";
|
|
9
9
|
import {
|
|
10
10
|
external_exports,
|
|
11
11
|
yaml
|
|
@@ -113,7 +113,9 @@ async function readProfileSkill(input) {
|
|
|
113
113
|
path: skill.path,
|
|
114
114
|
sourcePath: skill.sourcePath,
|
|
115
115
|
sourceHash: skill.sourceHash,
|
|
116
|
-
charCount: skill.charCount
|
|
116
|
+
charCount: skill.charCount,
|
|
117
|
+
packagePath: path.dirname(absolutePath),
|
|
118
|
+
resourceFiles: skill.resourceFiles
|
|
117
119
|
};
|
|
118
120
|
}
|
|
119
121
|
function emptyProfileSkillCatalogState(input = {}) {
|
|
@@ -128,12 +130,8 @@ async function loadProfileSkillDirectory(profileSourcePath2, directoryName) {
|
|
|
128
130
|
const relativePath = path.join(PROFILE_SKILLS_DIR, directoryName, PROFILE_SKILL_FILE).replace(/\\/g, "/");
|
|
129
131
|
const absolutePath = path.join(profileSourcePath2, relativePath);
|
|
130
132
|
const messages = [];
|
|
131
|
-
const
|
|
132
|
-
|
|
133
|
-
if (entry.name === PROFILE_SKILL_FILE && entry.isFile())
|
|
134
|
-
continue;
|
|
135
|
-
messages.push(`Profile skills only support ${PROFILE_SKILL_FILE}; unsupported entry: ${entry.name}`);
|
|
136
|
-
}
|
|
133
|
+
const packageRoot = path.join(profileSourcePath2, PROFILE_SKILLS_DIR, directoryName);
|
|
134
|
+
const packageFiles = await listPackageFiles(packageRoot);
|
|
137
135
|
let contents = "";
|
|
138
136
|
if (!existsSync(absolutePath)) {
|
|
139
137
|
messages.push(`Missing ${PROFILE_SKILL_FILE}.`);
|
|
@@ -163,9 +161,26 @@ async function loadProfileSkillDirectory(profileSourcePath2, directoryName) {
|
|
|
163
161
|
charCount: contents.length,
|
|
164
162
|
sourceHash: sha256Hex(contents),
|
|
165
163
|
validationStatus: messages.length > 0 ? "error" : "valid",
|
|
166
|
-
validationMessages: messages
|
|
164
|
+
validationMessages: messages,
|
|
165
|
+
resourceFiles: packageFiles.filter((file) => file !== PROFILE_SKILL_FILE)
|
|
167
166
|
};
|
|
168
167
|
}
|
|
168
|
+
async function listPackageFiles(root) {
|
|
169
|
+
const files = [];
|
|
170
|
+
async function visit(directory, prefix) {
|
|
171
|
+
const entries = await readdir(directory, { withFileTypes: true });
|
|
172
|
+
await Promise.all(entries.map(async (entry) => {
|
|
173
|
+
const relativePath = prefix ? `${prefix}/${entry.name}` : entry.name;
|
|
174
|
+
if (entry.isDirectory()) {
|
|
175
|
+
await visit(path.join(directory, entry.name), relativePath);
|
|
176
|
+
} else if (entry.isFile()) {
|
|
177
|
+
files.push(relativePath);
|
|
178
|
+
}
|
|
179
|
+
}));
|
|
180
|
+
}
|
|
181
|
+
await visit(root, "");
|
|
182
|
+
return files.sort();
|
|
183
|
+
}
|
|
169
184
|
function markDuplicateSkillNames(skills) {
|
|
170
185
|
const counts = /* @__PURE__ */ new Map();
|
|
171
186
|
for (const skill of skills) {
|
|
@@ -185,10 +200,14 @@ function markDuplicateSkillNames(skills) {
|
|
|
185
200
|
async function latestSkillMtime(profileSourcePath2, skills) {
|
|
186
201
|
let latest = 0;
|
|
187
202
|
for (const skill of skills) {
|
|
188
|
-
const
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
203
|
+
const packageRoot = path.dirname(path.join(profileSourcePath2, skill.path));
|
|
204
|
+
const packageFiles = [PROFILE_SKILL_FILE, ...skill.resourceFiles];
|
|
205
|
+
for (const file of packageFiles) {
|
|
206
|
+
const fileStat = await stat(path.join(packageRoot, file)).catch(() => null);
|
|
207
|
+
if (!fileStat?.isFile())
|
|
208
|
+
continue;
|
|
209
|
+
latest = Math.max(latest, fileStat.mtimeMs);
|
|
210
|
+
}
|
|
192
211
|
}
|
|
193
212
|
return latest > 0 ? new Date(latest).toISOString() : null;
|
|
194
213
|
}
|
|
@@ -2899,11 +2918,11 @@ function parseProfileSkillCommand(prompt) {
|
|
|
2899
2918
|
if (subcommand === "create") {
|
|
2900
2919
|
if (!args)
|
|
2901
2920
|
return { action: "help" };
|
|
2902
|
-
const
|
|
2921
|
+
const named2 = splitOptionalSkillName(args);
|
|
2903
2922
|
return {
|
|
2904
2923
|
action: "create",
|
|
2905
|
-
objective:
|
|
2906
|
-
requestedName:
|
|
2924
|
+
objective: named2.objective,
|
|
2925
|
+
requestedName: named2.name
|
|
2907
2926
|
};
|
|
2908
2927
|
}
|
|
2909
2928
|
if (subcommand === "edit") {
|
|
@@ -2914,7 +2933,12 @@ function parseProfileSkillCommand(prompt) {
|
|
|
2914
2933
|
return { action: "help" };
|
|
2915
2934
|
return { action: "edit", name, changeRequest };
|
|
2916
2935
|
}
|
|
2917
|
-
|
|
2936
|
+
const named = splitOptionalSkillName(rest);
|
|
2937
|
+
return {
|
|
2938
|
+
action: "create",
|
|
2939
|
+
objective: named.objective,
|
|
2940
|
+
requestedName: named.name
|
|
2941
|
+
};
|
|
2918
2942
|
}
|
|
2919
2943
|
return null;
|
|
2920
2944
|
}
|
|
@@ -2931,7 +2955,7 @@ function profileSkillHelp(profile) {
|
|
|
2931
2955
|
"- /skill create --name <skill-name> <what the skill should help with>",
|
|
2932
2956
|
"- /skill edit <skill-name> <change request>",
|
|
2933
2957
|
"",
|
|
2934
|
-
"Create/edit starts a profile-skill goal in the active profile repo. Skills
|
|
2958
|
+
"Create/edit starts a profile-skill goal in the active profile repo. Skills may include SKILL.md plus focused scripts, references, and assets. Use an agent when the workflow needs durable autonomy, schedules, identity, or its own model loop."
|
|
2935
2959
|
].join("\n")
|
|
2936
2960
|
};
|
|
2937
2961
|
}
|
|
@@ -3053,10 +3077,11 @@ function profileSkillGoalPrompt(goal) {
|
|
|
3053
3077
|
"",
|
|
3054
3078
|
"Rules:",
|
|
3055
3079
|
modeLine,
|
|
3056
|
-
"- Keep the
|
|
3080
|
+
"- Keep SKILL.md as the required entry point. Add only scripts, references, assets, or agents/openai.yaml that directly support the workflow.",
|
|
3057
3081
|
"- SKILL.md must include YAML frontmatter with required name and description fields, followed by a markdown body.",
|
|
3058
3082
|
"- The body should describe the reusable workflow clearly enough for future chats to apply it.",
|
|
3059
|
-
"-
|
|
3083
|
+
"- Use scripts for deterministic repeated operations, references for detailed knowledge, and assets for files consumed by outputs.",
|
|
3084
|
+
"- Do not add README, changelog, installation guide, or other auxiliary documentation.",
|
|
3060
3085
|
"- Validate the resulting file by reading it back and checking name, description, body, and path consistency.",
|
|
3061
3086
|
"- Report the final skill name, path, validation status, and explicit invocation such as $skill-name only after the file is written or updated.",
|
|
3062
3087
|
"- Ask only for missing details that materially change the skill.",
|
|
@@ -3297,16 +3322,6 @@ async function getOpenPondAccount(baseUrl, token) {
|
|
|
3297
3322
|
}
|
|
3298
3323
|
return await response.json();
|
|
3299
3324
|
}
|
|
3300
|
-
async function getOpenPondAccountBalance(baseUrl, token) {
|
|
3301
|
-
const response = await apiFetch(baseUrl, token, "/account/balance", {
|
|
3302
|
-
method: "GET"
|
|
3303
|
-
});
|
|
3304
|
-
if (!response.ok) {
|
|
3305
|
-
const text5 = await response.text().catch(() => "");
|
|
3306
|
-
throw new Error(`Account balance lookup failed: ${response.status} ${text5}`);
|
|
3307
|
-
}
|
|
3308
|
-
return await response.json();
|
|
3309
|
-
}
|
|
3310
3325
|
async function checkOpenPondApiHealth(baseUrl, token) {
|
|
3311
3326
|
const checkedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
3312
3327
|
const started = Date.now();
|
|
@@ -3543,13 +3558,13 @@ function createSandboxRuntimeHandle(client, runtimeId, initial = null) {
|
|
|
3543
3558
|
keepAlive,
|
|
3544
3559
|
checkpoint: (input) => client.checkpointSandboxRuntime(runtimeId, input),
|
|
3545
3560
|
files: {
|
|
3546
|
-
write: async (
|
|
3547
|
-
read: async (
|
|
3561
|
+
write: async (path13, contents) => client.uploadFile((await resume()).id, path13, contents),
|
|
3562
|
+
read: async (path13) => client.downloadFile((await resume()).id, path13),
|
|
3548
3563
|
readResponse: async (input) => client.downloadFileResponse((await resume()).id, input),
|
|
3549
3564
|
list: async (input = {}) => client.listFiles((await resume()).id, input),
|
|
3550
|
-
delete: async (
|
|
3565
|
+
delete: async (path13, input = {}) => client.deleteFile((await resume()).id, path13, input),
|
|
3551
3566
|
search: async (input) => client.searchFiles((await resume()).id, input),
|
|
3552
|
-
stat: async (
|
|
3567
|
+
stat: async (path13) => client.statFile((await resume()).id, path13),
|
|
3553
3568
|
mkdir: async (input) => client.mkdir((await resume()).id, input),
|
|
3554
3569
|
move: async (input) => client.moveFile((await resume()).id, input)
|
|
3555
3570
|
},
|
|
@@ -4053,20 +4068,20 @@ var OpenPondSandboxInstanceClient = class {
|
|
|
4053
4068
|
path: `/${encodeURIComponent(sandboxId)}/pty/${encodeURIComponent(ptyId)}/stream${query.size > 0 ? `?${query.toString()}` : ""}`
|
|
4054
4069
|
});
|
|
4055
4070
|
}
|
|
4056
|
-
uploadFile(sandboxId,
|
|
4057
|
-
return this.uploadFileBase64(sandboxId,
|
|
4071
|
+
uploadFile(sandboxId, path13, contents) {
|
|
4072
|
+
return this.uploadFileBase64(sandboxId, path13, Buffer.from(contents, "utf-8").toString("base64"));
|
|
4058
4073
|
}
|
|
4059
|
-
uploadFileBase64(sandboxId,
|
|
4074
|
+
uploadFileBase64(sandboxId, path13, contentsBase64) {
|
|
4060
4075
|
return this.request(`/${encodeURIComponent(sandboxId)}/files`, {
|
|
4061
4076
|
method: "POST",
|
|
4062
4077
|
body: JSON.stringify({
|
|
4063
|
-
path:
|
|
4078
|
+
path: path13,
|
|
4064
4079
|
contentsBase64
|
|
4065
4080
|
})
|
|
4066
4081
|
});
|
|
4067
4082
|
}
|
|
4068
|
-
async downloadFile(sandboxId,
|
|
4069
|
-
const payload = await this.downloadFileResponse(sandboxId,
|
|
4083
|
+
async downloadFile(sandboxId, path13) {
|
|
4084
|
+
const payload = await this.downloadFileResponse(sandboxId, path13);
|
|
4070
4085
|
return Buffer.from(payload.file.contentsBase64, "base64").toString("utf-8");
|
|
4071
4086
|
}
|
|
4072
4087
|
downloadFileResponse(sandboxId, input) {
|
|
@@ -4090,16 +4105,16 @@ var OpenPondSandboxInstanceClient = class {
|
|
|
4090
4105
|
query.set("maxEntries", String(input.maxEntries));
|
|
4091
4106
|
return this.request(`/${encodeURIComponent(sandboxId)}/files?${query.toString()}`);
|
|
4092
4107
|
}
|
|
4093
|
-
deleteFile(sandboxId,
|
|
4094
|
-
const query = new URLSearchParams({ path:
|
|
4108
|
+
deleteFile(sandboxId, path13, input = {}) {
|
|
4109
|
+
const query = new URLSearchParams({ path: path13 });
|
|
4095
4110
|
if (input.recursive !== void 0)
|
|
4096
4111
|
query.set("recursive", String(input.recursive));
|
|
4097
4112
|
return this.request(`/${encodeURIComponent(sandboxId)}/files?${query.toString()}`, {
|
|
4098
4113
|
method: "DELETE"
|
|
4099
4114
|
});
|
|
4100
4115
|
}
|
|
4101
|
-
statFile(sandboxId,
|
|
4102
|
-
const query = new URLSearchParams({ stat: "1", path:
|
|
4116
|
+
statFile(sandboxId, path13) {
|
|
4117
|
+
const query = new URLSearchParams({ stat: "1", path: path13 });
|
|
4103
4118
|
return this.request(`/${encodeURIComponent(sandboxId)}/files?${query.toString()}`);
|
|
4104
4119
|
}
|
|
4105
4120
|
mkdir(sandboxId, input) {
|
|
@@ -4275,12 +4290,12 @@ var OpenPondSandboxInstanceClient = class {
|
|
|
4275
4290
|
body: JSON.stringify({ leaseId })
|
|
4276
4291
|
});
|
|
4277
4292
|
}
|
|
4278
|
-
async request(
|
|
4279
|
-
const response = await apiFetch(this.sandboxApiUrl, this.apiKey,
|
|
4293
|
+
async request(path13, init = {}) {
|
|
4294
|
+
const response = await apiFetch(this.sandboxApiUrl, this.apiKey, path13, init);
|
|
4280
4295
|
return readApiJson(response, "Sandbox request");
|
|
4281
4296
|
}
|
|
4282
|
-
async requestApiRoot(
|
|
4283
|
-
const response = await apiFetch(this.apiRootUrl, this.apiKey,
|
|
4297
|
+
async requestApiRoot(path13, init = {}) {
|
|
4298
|
+
const response = await apiFetch(this.apiRootUrl, this.apiKey, path13, init);
|
|
4284
4299
|
return readApiJson(response, "OpenPond API request");
|
|
4285
4300
|
}
|
|
4286
4301
|
};
|
|
@@ -5019,8 +5034,841 @@ function responsePayloadData(payload) {
|
|
|
5019
5034
|
return null;
|
|
5020
5035
|
}
|
|
5021
5036
|
|
|
5037
|
+
// ../../packages/cloud/dist/extensions/types.js
|
|
5038
|
+
var GithubExtensionError = class extends Error {
|
|
5039
|
+
code;
|
|
5040
|
+
status;
|
|
5041
|
+
constructor(message, options) {
|
|
5042
|
+
super(message);
|
|
5043
|
+
this.name = "GithubExtensionError";
|
|
5044
|
+
this.code = options.code;
|
|
5045
|
+
this.status = options.status ?? 400;
|
|
5046
|
+
}
|
|
5047
|
+
};
|
|
5048
|
+
|
|
5049
|
+
// ../../packages/cloud/dist/extensions/github-source.js
|
|
5050
|
+
import { createHash as createHash3 } from "node:crypto";
|
|
5051
|
+
import path10 from "node:path";
|
|
5052
|
+
var DEFAULT_REF = "HEAD";
|
|
5053
|
+
var MAX_EXTENSION_SKILLS = 64;
|
|
5054
|
+
var MAX_EXTENSION_FILES = 512;
|
|
5055
|
+
var MAX_EXTENSION_BYTES = 20 * 1024 * 1024;
|
|
5056
|
+
var MAX_EXTENSION_FILE_BYTES = 5 * 1024 * 1024;
|
|
5057
|
+
var DOWNLOAD_CONCURRENCY = 8;
|
|
5058
|
+
var SKILL_NAME_PATTERN = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
|
|
5059
|
+
var GITHUB_REPOSITORY_PATTERN = /^[A-Za-z0-9_.-]+$/;
|
|
5060
|
+
var ROOT_SKILL_RESOURCE_DIRECTORIES = /* @__PURE__ */ new Set(["agents", "assets", "references", "scripts"]);
|
|
5061
|
+
function createGithubSourceClient(options = {}) {
|
|
5062
|
+
const fetchImpl = options.fetch ?? fetch;
|
|
5063
|
+
const githubToken = options.githubToken?.trim() || process.env.GITHUB_TOKEN?.trim() || process.env.GH_TOKEN?.trim() || null;
|
|
5064
|
+
return {
|
|
5065
|
+
async resolve(request) {
|
|
5066
|
+
const source = await resolveSource(request, fetchImpl, githubToken);
|
|
5067
|
+
const preview = await buildPreview(source, fetchImpl, githubToken);
|
|
5068
|
+
return {
|
|
5069
|
+
preview,
|
|
5070
|
+
files: filesToDownload(source)
|
|
5071
|
+
};
|
|
5072
|
+
},
|
|
5073
|
+
async download(resolution, writeFile5) {
|
|
5074
|
+
await downloadFiles({
|
|
5075
|
+
resolution,
|
|
5076
|
+
fetchImpl,
|
|
5077
|
+
githubToken,
|
|
5078
|
+
writeFile: writeFile5
|
|
5079
|
+
});
|
|
5080
|
+
}
|
|
5081
|
+
};
|
|
5082
|
+
}
|
|
5083
|
+
function parseGithubExtensionSource(source) {
|
|
5084
|
+
const trimmed = source.trim();
|
|
5085
|
+
let owner = "";
|
|
5086
|
+
let repo = "";
|
|
5087
|
+
if (/^(?:https?:\/\/)?github\.com\//i.test(trimmed)) {
|
|
5088
|
+
const url = new URL(trimmed.startsWith("http") ? trimmed : `https://${trimmed}`);
|
|
5089
|
+
if (url.hostname.toLowerCase() !== "github.com") {
|
|
5090
|
+
throw invalidSource(source);
|
|
5091
|
+
}
|
|
5092
|
+
const segments = url.pathname.replace(/^\/+|\/+$/g, "").split("/");
|
|
5093
|
+
if (segments.length !== 2)
|
|
5094
|
+
throw invalidSource(source);
|
|
5095
|
+
[owner = "", repo = ""] = segments;
|
|
5096
|
+
} else {
|
|
5097
|
+
const normalized = trimmed.replace(/^github:/i, "").replace(/^\/+|\/+$/g, "");
|
|
5098
|
+
const segments = normalized.split("/");
|
|
5099
|
+
if (segments.length !== 2)
|
|
5100
|
+
throw invalidSource(source);
|
|
5101
|
+
[owner = "", repo = ""] = segments;
|
|
5102
|
+
}
|
|
5103
|
+
repo = repo.replace(/\.git$/i, "");
|
|
5104
|
+
if (!GITHUB_REPOSITORY_PATTERN.test(owner) || !GITHUB_REPOSITORY_PATTERN.test(repo)) {
|
|
5105
|
+
throw invalidSource(source);
|
|
5106
|
+
}
|
|
5107
|
+
const normalizedOwner = owner.toLowerCase();
|
|
5108
|
+
const normalizedRepo = repo.toLowerCase();
|
|
5109
|
+
return {
|
|
5110
|
+
id: `github:${normalizedOwner}/${normalizedRepo}`,
|
|
5111
|
+
owner: normalizedOwner,
|
|
5112
|
+
repo: normalizedRepo,
|
|
5113
|
+
repositoryUrl: `https://github.com/${normalizedOwner}/${normalizedRepo}`
|
|
5114
|
+
};
|
|
5115
|
+
}
|
|
5116
|
+
async function resolveSource(request, fetchImpl, githubToken) {
|
|
5117
|
+
const identity = parseGithubExtensionSource(request.source);
|
|
5118
|
+
const requestedRef = request.ref?.trim() || DEFAULT_REF;
|
|
5119
|
+
const repository = await githubJson(fetchImpl, githubToken, `/repos/${identity.owner}/${identity.repo}`);
|
|
5120
|
+
const resolvedRef = requestedRef === DEFAULT_REF ? repository.default_branch?.trim() || "main" : requestedRef;
|
|
5121
|
+
const commit = await githubJson(fetchImpl, githubToken, `/repos/${identity.owner}/${identity.repo}/commits/${encodeURIComponent(resolvedRef)}`);
|
|
5122
|
+
const resolvedCommit = commit.sha?.trim();
|
|
5123
|
+
const treeSha = commit.commit?.tree?.sha?.trim();
|
|
5124
|
+
if (!resolvedCommit || !treeSha) {
|
|
5125
|
+
throw new GithubExtensionError("GitHub returned an incomplete commit response.", {
|
|
5126
|
+
code: "github_invalid_commit",
|
|
5127
|
+
status: 502
|
|
5128
|
+
});
|
|
5129
|
+
}
|
|
5130
|
+
const treePayload = await githubJson(fetchImpl, githubToken, `/repos/${identity.owner}/${identity.repo}/git/trees/${treeSha}?recursive=1`);
|
|
5131
|
+
if (treePayload.truncated) {
|
|
5132
|
+
throw new GithubExtensionError("The GitHub repository tree is too large to install safely.", {
|
|
5133
|
+
code: "github_tree_truncated"
|
|
5134
|
+
});
|
|
5135
|
+
}
|
|
5136
|
+
const tree = (treePayload.tree ?? []).filter(validTreeEntry);
|
|
5137
|
+
const skillPackages = discoverSkillPackages(tree);
|
|
5138
|
+
if (skillPackages.length === 0) {
|
|
5139
|
+
throw new GithubExtensionError("No skills found. Add SKILL.md at the repository root or use a standard agent skills directory.", { code: "extension_no_skills" });
|
|
5140
|
+
}
|
|
5141
|
+
if (skillPackages.length > MAX_EXTENSION_SKILLS) {
|
|
5142
|
+
throw new GithubExtensionError(`Extension contains more than ${MAX_EXTENSION_SKILLS} skills.`, {
|
|
5143
|
+
code: "extension_too_many_skills"
|
|
5144
|
+
});
|
|
5145
|
+
}
|
|
5146
|
+
validateDownloadLimits(skillPackages);
|
|
5147
|
+
const readme = tree.find((entry) => entry.type === "blob" && /^readme(?:\.[^/]+)?$/i.test(entry.path)) ?? null;
|
|
5148
|
+
return { identity, requestedRef, resolvedCommit, tree, skillPackages, readme };
|
|
5149
|
+
}
|
|
5150
|
+
async function buildPreview(source, fetchImpl, githubToken) {
|
|
5151
|
+
const skills = await mapConcurrent(source.skillPackages, DOWNLOAD_CONCURRENCY, async (skillPackage) => {
|
|
5152
|
+
const contents = await downloadText(source, skillPackage.entry, fetchImpl, githubToken);
|
|
5153
|
+
return previewSkill(skillPackage, contents);
|
|
5154
|
+
});
|
|
5155
|
+
const duplicateNames = duplicateValues(skills.map((skill) => skill.name));
|
|
5156
|
+
for (const skill of skills) {
|
|
5157
|
+
if (!duplicateNames.has(skill.name))
|
|
5158
|
+
continue;
|
|
5159
|
+
skill.validationStatus = "error";
|
|
5160
|
+
skill.validationMessages = [...skill.validationMessages, `Duplicate skill name: ${skill.name}`];
|
|
5161
|
+
}
|
|
5162
|
+
const validationMessages = skills.flatMap((skill) => skill.validationMessages.map((message) => `${skill.relativePath}: ${message}`));
|
|
5163
|
+
const packageFiles = filesToDownload(source);
|
|
5164
|
+
return {
|
|
5165
|
+
...source.identity,
|
|
5166
|
+
source: "github",
|
|
5167
|
+
requestedRef: source.requestedRef,
|
|
5168
|
+
resolvedCommit: source.resolvedCommit,
|
|
5169
|
+
sourcePath: null,
|
|
5170
|
+
readmePath: source.readme?.path ?? null,
|
|
5171
|
+
packageHash: hashTree(packageFiles),
|
|
5172
|
+
skills: skills.sort((left, right) => left.name.localeCompare(right.name)),
|
|
5173
|
+
validationStatus: validationMessages.length === 0 ? "valid" : "error",
|
|
5174
|
+
validationMessages
|
|
5175
|
+
};
|
|
5176
|
+
}
|
|
5177
|
+
function previewSkill(skillPackage, contents) {
|
|
5178
|
+
const parsed = parseProfileSkillMarkdown(contents);
|
|
5179
|
+
const directoryName = skillPackage.root === "." ? null : path10.posix.basename(skillPackage.root);
|
|
5180
|
+
const name = parsed.name ?? directoryName ?? "invalid-skill";
|
|
5181
|
+
const messages = [...parsed.messages];
|
|
5182
|
+
if (!SKILL_NAME_PATTERN.test(name))
|
|
5183
|
+
messages.push("Skill name must be lowercase kebab-case.");
|
|
5184
|
+
if (directoryName && name !== directoryName) {
|
|
5185
|
+
messages.push(`Skill name must match its directory name (${directoryName}).`);
|
|
5186
|
+
}
|
|
5187
|
+
const resourceFiles = skillPackage.files.filter((file) => file.path !== skillPackage.entry.path).map((file) => relativeSkillPath(skillPackage.root, file.path)).sort();
|
|
5188
|
+
return {
|
|
5189
|
+
name,
|
|
5190
|
+
description: parsed.description ?? "",
|
|
5191
|
+
relativePath: skillPackage.root === "." ? "SKILL.md" : `${skillPackage.root}/SKILL.md`,
|
|
5192
|
+
sourcePath: "",
|
|
5193
|
+
charCount: contents.length,
|
|
5194
|
+
sourceHash: createHash3("sha256").update(contents).digest("hex"),
|
|
5195
|
+
resourceFiles,
|
|
5196
|
+
validationStatus: messages.length === 0 ? "valid" : "error",
|
|
5197
|
+
validationMessages: [...new Set(messages)]
|
|
5198
|
+
};
|
|
5199
|
+
}
|
|
5200
|
+
function discoverSkillPackages(tree) {
|
|
5201
|
+
const entries = [];
|
|
5202
|
+
const rootEntry = tree.find((entry) => entry.type === "blob" && entry.path === "SKILL.md");
|
|
5203
|
+
if (rootEntry)
|
|
5204
|
+
entries.push({ root: ".", entry: rootEntry });
|
|
5205
|
+
const skillEntries = tree.filter((entry) => entry.type === "blob" && entry.path.endsWith("/SKILL.md"));
|
|
5206
|
+
const standardEntries = skillEntries.filter((entry) => isStandardAgentSkillsPath(entry.path));
|
|
5207
|
+
const discoveredEntries = standardEntries.length > 0 ? standardEntries : skillEntries;
|
|
5208
|
+
const roots = new Set(discoveredEntries.map((entry) => path10.posix.dirname(entry.path)));
|
|
5209
|
+
for (const entry of discoveredEntries) {
|
|
5210
|
+
const root = path10.posix.dirname(entry.path);
|
|
5211
|
+
if ([...roots].some((candidate) => candidate !== root && root.startsWith(`${candidate}/`)))
|
|
5212
|
+
continue;
|
|
5213
|
+
entries.push({ root, entry });
|
|
5214
|
+
}
|
|
5215
|
+
return entries.map(({ root, entry }) => {
|
|
5216
|
+
const files = tree.filter((candidate) => {
|
|
5217
|
+
if (candidate.type !== "blob")
|
|
5218
|
+
return false;
|
|
5219
|
+
if (root !== ".")
|
|
5220
|
+
return candidate.path.startsWith(`${root}/`);
|
|
5221
|
+
if (candidate.path === "SKILL.md")
|
|
5222
|
+
return true;
|
|
5223
|
+
const firstSegment = candidate.path.split("/", 1)[0] ?? "";
|
|
5224
|
+
return ROOT_SKILL_RESOURCE_DIRECTORIES.has(firstSegment);
|
|
5225
|
+
});
|
|
5226
|
+
const unsafe = tree.find((candidate) => candidate.type !== "blob" && candidate.type !== "tree" && (root === "." ? candidate.path === "SKILL.md" || ROOT_SKILL_RESOURCE_DIRECTORIES.has(candidate.path.split("/", 1)[0] ?? "") : candidate.path.startsWith(`${root}/`)));
|
|
5227
|
+
const symlink2 = files.find((candidate) => candidate.mode === "120000");
|
|
5228
|
+
if (unsafe || symlink2) {
|
|
5229
|
+
throw new GithubExtensionError(`Skill package ${root} contains a symlink or submodule.`, {
|
|
5230
|
+
code: "extension_unsafe_entry"
|
|
5231
|
+
});
|
|
5232
|
+
}
|
|
5233
|
+
return { root, entry, files };
|
|
5234
|
+
});
|
|
5235
|
+
}
|
|
5236
|
+
function isStandardAgentSkillsPath(skillPath) {
|
|
5237
|
+
const segments = skillPath.split("/");
|
|
5238
|
+
if (segments.at(-1) !== "SKILL.md")
|
|
5239
|
+
return false;
|
|
5240
|
+
const skillDirectorySegments = segments.slice(0, -1);
|
|
5241
|
+
if (skillDirectorySegments.length < 2)
|
|
5242
|
+
return false;
|
|
5243
|
+
const skillsIndex = skillDirectorySegments.lastIndexOf("skills");
|
|
5244
|
+
if (skillsIndex < 0 || skillsIndex > 2)
|
|
5245
|
+
return false;
|
|
5246
|
+
const containerPrefix = skillDirectorySegments.slice(0, skillsIndex);
|
|
5247
|
+
const nestedSkillPath = skillDirectorySegments.slice(skillsIndex + 1);
|
|
5248
|
+
if (nestedSkillPath.length < 1 || nestedSkillPath.length > 2)
|
|
5249
|
+
return false;
|
|
5250
|
+
if (skillsIndex === 0)
|
|
5251
|
+
return true;
|
|
5252
|
+
const first = containerPrefix[0] ?? "";
|
|
5253
|
+
return first.startsWith(".") || first === "agent" || first === "data";
|
|
5254
|
+
}
|
|
5255
|
+
function filesToDownload(source) {
|
|
5256
|
+
const byPath = /* @__PURE__ */ new Map();
|
|
5257
|
+
if (source.readme)
|
|
5258
|
+
byPath.set(source.readme.path, source.readme);
|
|
5259
|
+
for (const skillPackage of source.skillPackages) {
|
|
5260
|
+
for (const file of skillPackage.files)
|
|
5261
|
+
byPath.set(file.path, file);
|
|
5262
|
+
}
|
|
5263
|
+
return [...byPath.values()].sort((left, right) => left.path.localeCompare(right.path));
|
|
5264
|
+
}
|
|
5265
|
+
async function downloadFiles(input) {
|
|
5266
|
+
let downloadedBytes = 0;
|
|
5267
|
+
await mapConcurrent(input.resolution.files, DOWNLOAD_CONCURRENCY, async (file) => {
|
|
5268
|
+
const bytes = await downloadBytes({
|
|
5269
|
+
owner: input.resolution.preview.owner,
|
|
5270
|
+
repo: input.resolution.preview.repo,
|
|
5271
|
+
commit: input.resolution.preview.resolvedCommit,
|
|
5272
|
+
file,
|
|
5273
|
+
fetchImpl: input.fetchImpl,
|
|
5274
|
+
githubToken: input.githubToken
|
|
5275
|
+
});
|
|
5276
|
+
downloadedBytes += bytes.byteLength;
|
|
5277
|
+
if (downloadedBytes > MAX_EXTENSION_BYTES) {
|
|
5278
|
+
throw new GithubExtensionError("Extension download exceeds the maximum allowed size.", {
|
|
5279
|
+
code: "extension_too_large"
|
|
5280
|
+
});
|
|
5281
|
+
}
|
|
5282
|
+
await input.writeFile(file.path, bytes, file.mode === "100755");
|
|
5283
|
+
});
|
|
5284
|
+
}
|
|
5285
|
+
async function downloadText(source, file, fetchImpl, githubToken) {
|
|
5286
|
+
const bytes = await downloadBytes({
|
|
5287
|
+
owner: source.identity.owner,
|
|
5288
|
+
repo: source.identity.repo,
|
|
5289
|
+
commit: source.resolvedCommit,
|
|
5290
|
+
file,
|
|
5291
|
+
fetchImpl,
|
|
5292
|
+
githubToken
|
|
5293
|
+
});
|
|
5294
|
+
return new TextDecoder("utf-8", { fatal: true }).decode(bytes);
|
|
5295
|
+
}
|
|
5296
|
+
async function downloadBytes(input) {
|
|
5297
|
+
const encodedPath = input.file.path.split("/").map(encodeURIComponent).join("/");
|
|
5298
|
+
const url = `https://raw.githubusercontent.com/${input.owner}/${input.repo}/${input.commit}/${encodedPath}`;
|
|
5299
|
+
const response = await input.fetchImpl(url, {
|
|
5300
|
+
headers: githubHeaders(input.githubToken, "application/vnd.github.raw"),
|
|
5301
|
+
redirect: "follow"
|
|
5302
|
+
});
|
|
5303
|
+
if (!response.ok) {
|
|
5304
|
+
throw new GithubExtensionError(`GitHub file download failed (${response.status}): ${input.file.path}`, {
|
|
5305
|
+
code: "github_download_failed",
|
|
5306
|
+
status: response.status
|
|
5307
|
+
});
|
|
5308
|
+
}
|
|
5309
|
+
const contentLength = Number(response.headers.get("content-length"));
|
|
5310
|
+
if (Number.isFinite(contentLength) && contentLength > MAX_EXTENSION_FILE_BYTES) {
|
|
5311
|
+
throw new GithubExtensionError(`Extension file is too large: ${input.file.path}`, {
|
|
5312
|
+
code: "extension_file_too_large"
|
|
5313
|
+
});
|
|
5314
|
+
}
|
|
5315
|
+
const bytes = new Uint8Array(await response.arrayBuffer());
|
|
5316
|
+
if (bytes.byteLength > MAX_EXTENSION_FILE_BYTES) {
|
|
5317
|
+
throw new GithubExtensionError(`Extension file is too large: ${input.file.path}`, {
|
|
5318
|
+
code: "extension_file_too_large"
|
|
5319
|
+
});
|
|
5320
|
+
}
|
|
5321
|
+
return bytes;
|
|
5322
|
+
}
|
|
5323
|
+
async function githubJson(fetchImpl, githubToken, pathname) {
|
|
5324
|
+
const response = await fetchImpl(`https://api.github.com${pathname}`, {
|
|
5325
|
+
headers: githubHeaders(githubToken, "application/vnd.github+json")
|
|
5326
|
+
});
|
|
5327
|
+
if (!response.ok) {
|
|
5328
|
+
const details = await response.json().catch(() => null);
|
|
5329
|
+
const detail = typeof details?.message === "string" ? `: ${details.message}` : "";
|
|
5330
|
+
throw new GithubExtensionError(`GitHub request failed (${response.status})${detail}`, {
|
|
5331
|
+
code: response.status === 404 ? "github_repository_not_found" : "github_request_failed",
|
|
5332
|
+
status: response.status
|
|
5333
|
+
});
|
|
5334
|
+
}
|
|
5335
|
+
return await response.json();
|
|
5336
|
+
}
|
|
5337
|
+
function githubHeaders(token, accept) {
|
|
5338
|
+
const headers = new Headers({
|
|
5339
|
+
Accept: accept,
|
|
5340
|
+
"User-Agent": "openpond-extension-installer",
|
|
5341
|
+
"X-GitHub-Api-Version": "2022-11-28"
|
|
5342
|
+
});
|
|
5343
|
+
if (token)
|
|
5344
|
+
headers.set("Authorization", `Bearer ${token}`);
|
|
5345
|
+
return headers;
|
|
5346
|
+
}
|
|
5347
|
+
function validateDownloadLimits(skillPackages) {
|
|
5348
|
+
const files = /* @__PURE__ */ new Map();
|
|
5349
|
+
for (const skillPackage of skillPackages) {
|
|
5350
|
+
for (const file of skillPackage.files)
|
|
5351
|
+
files.set(file.path, file);
|
|
5352
|
+
}
|
|
5353
|
+
if (files.size > MAX_EXTENSION_FILES) {
|
|
5354
|
+
throw new GithubExtensionError(`Extension contains more than ${MAX_EXTENSION_FILES} skill files.`, {
|
|
5355
|
+
code: "extension_too_many_files"
|
|
5356
|
+
});
|
|
5357
|
+
}
|
|
5358
|
+
let totalBytes = 0;
|
|
5359
|
+
for (const file of files.values()) {
|
|
5360
|
+
if ((file.size ?? 0) > MAX_EXTENSION_FILE_BYTES) {
|
|
5361
|
+
throw new GithubExtensionError(`Extension file is too large: ${file.path}`, {
|
|
5362
|
+
code: "extension_file_too_large"
|
|
5363
|
+
});
|
|
5364
|
+
}
|
|
5365
|
+
totalBytes += file.size ?? 0;
|
|
5366
|
+
}
|
|
5367
|
+
if (totalBytes > MAX_EXTENSION_BYTES) {
|
|
5368
|
+
throw new GithubExtensionError("Extension exceeds the maximum allowed size.", {
|
|
5369
|
+
code: "extension_too_large"
|
|
5370
|
+
});
|
|
5371
|
+
}
|
|
5372
|
+
}
|
|
5373
|
+
function validTreeEntry(value) {
|
|
5374
|
+
if (!value || typeof value !== "object")
|
|
5375
|
+
return false;
|
|
5376
|
+
const entry = value;
|
|
5377
|
+
return typeof entry.path === "string" && !entry.path.startsWith("/") && !entry.path.split("/").includes("..") && typeof entry.mode === "string" && (entry.type === "blob" || entry.type === "tree" || entry.type === "commit") && typeof entry.sha === "string";
|
|
5378
|
+
}
|
|
5379
|
+
function hashTree(files) {
|
|
5380
|
+
const hash = createHash3("sha256");
|
|
5381
|
+
for (const file of files)
|
|
5382
|
+
hash.update(`${file.path}\0${file.sha}\0${file.size ?? ""}
|
|
5383
|
+
`);
|
|
5384
|
+
return hash.digest("hex");
|
|
5385
|
+
}
|
|
5386
|
+
function relativeSkillPath(root, filePath) {
|
|
5387
|
+
return root === "." ? filePath : filePath.slice(root.length + 1);
|
|
5388
|
+
}
|
|
5389
|
+
function duplicateValues(values) {
|
|
5390
|
+
const seen = /* @__PURE__ */ new Set();
|
|
5391
|
+
const duplicates = /* @__PURE__ */ new Set();
|
|
5392
|
+
for (const value of values) {
|
|
5393
|
+
if (seen.has(value))
|
|
5394
|
+
duplicates.add(value);
|
|
5395
|
+
seen.add(value);
|
|
5396
|
+
}
|
|
5397
|
+
return duplicates;
|
|
5398
|
+
}
|
|
5399
|
+
async function mapConcurrent(values, concurrency, mapper) {
|
|
5400
|
+
const results = new Array(values.length);
|
|
5401
|
+
let nextIndex = 0;
|
|
5402
|
+
async function worker() {
|
|
5403
|
+
while (nextIndex < values.length) {
|
|
5404
|
+
const index = nextIndex;
|
|
5405
|
+
nextIndex += 1;
|
|
5406
|
+
results[index] = await mapper(values[index]);
|
|
5407
|
+
}
|
|
5408
|
+
}
|
|
5409
|
+
await Promise.all(Array.from({ length: Math.min(concurrency, values.length) }, worker));
|
|
5410
|
+
return results;
|
|
5411
|
+
}
|
|
5412
|
+
function invalidSource(source) {
|
|
5413
|
+
return new GithubExtensionError(`Invalid GitHub extension source: ${source}. Use owner/repo or https://github.com/owner/repo.`, { code: "github_invalid_source" });
|
|
5414
|
+
}
|
|
5415
|
+
|
|
5416
|
+
// ../../packages/cloud/dist/extensions/extension-manager.js
|
|
5417
|
+
import { createHash as createHash4, randomUUID as randomUUID3 } from "node:crypto";
|
|
5418
|
+
import { existsSync as existsSync6 } from "node:fs";
|
|
5419
|
+
import { mkdir as mkdir2, readFile as readFile6, rename, rm, stat as stat4, writeFile as writeFile3 } from "node:fs/promises";
|
|
5420
|
+
import path11 from "node:path";
|
|
5421
|
+
var REGISTRY_SCHEMA_VERSION = 1;
|
|
5422
|
+
var OPERATION_LOCK_STALE_MS = 2 * 60 * 1e3;
|
|
5423
|
+
var OPERATION_LOCK_TIMEOUT_MS = 15e3;
|
|
5424
|
+
function createGithubExtensionManager(options = {}) {
|
|
5425
|
+
const rootPath = path11.resolve(options.rootPath ?? path11.join(openPondConfigDirectory(), "extensions"));
|
|
5426
|
+
const registryPath = path11.join(rootPath, "registry.json");
|
|
5427
|
+
const github = createGithubSourceClient({
|
|
5428
|
+
fetch: options.fetch,
|
|
5429
|
+
githubToken: options.githubToken
|
|
5430
|
+
});
|
|
5431
|
+
const now = options.now ?? (() => /* @__PURE__ */ new Date());
|
|
5432
|
+
async function list() {
|
|
5433
|
+
try {
|
|
5434
|
+
const registry = await readRegistry(registryPath);
|
|
5435
|
+
const extensions = await Promise.all(registry.extensions.map((extension) => hydrateExtension(rootPath, extension)));
|
|
5436
|
+
markInstalledSkillConflicts(extensions, await reservedSkillNames(options.reservedSkillNames));
|
|
5437
|
+
return {
|
|
5438
|
+
rootPath,
|
|
5439
|
+
registryPath,
|
|
5440
|
+
extensions: extensions.sort(extensionSort),
|
|
5441
|
+
error: null
|
|
5442
|
+
};
|
|
5443
|
+
} catch (error) {
|
|
5444
|
+
return {
|
|
5445
|
+
rootPath,
|
|
5446
|
+
registryPath,
|
|
5447
|
+
extensions: [],
|
|
5448
|
+
error: error instanceof Error ? error.message : String(error)
|
|
5449
|
+
};
|
|
5450
|
+
}
|
|
5451
|
+
}
|
|
5452
|
+
async function preview(request) {
|
|
5453
|
+
const resolution = await github.resolve(request);
|
|
5454
|
+
const registry = await readRegistry(registryPath);
|
|
5455
|
+
const existing = registry.extensions.find((extension) => extension.id === resolution.preview.id) ?? null;
|
|
5456
|
+
assertSkillNamesAvailable(resolution.preview, registry.extensions.filter((extension) => extension.id !== existing?.id), await reservedSkillNames(options.reservedSkillNames));
|
|
5457
|
+
return resolution.preview;
|
|
5458
|
+
}
|
|
5459
|
+
async function add(request) {
|
|
5460
|
+
const identity = parseGithubExtensionSource(request.source);
|
|
5461
|
+
return withExtensionLock(rootPath, identity.id, async () => {
|
|
5462
|
+
const registry = await readRegistry(registryPath);
|
|
5463
|
+
if (registry.extensions.some((extension) => extension.id === identity.id)) {
|
|
5464
|
+
throw new GithubExtensionError(`${identity.owner}/${identity.repo} is already installed.`, {
|
|
5465
|
+
code: "extension_already_installed",
|
|
5466
|
+
status: 409
|
|
5467
|
+
});
|
|
5468
|
+
}
|
|
5469
|
+
const resolution = await github.resolve(request);
|
|
5470
|
+
assertInstallable(resolution.preview);
|
|
5471
|
+
assertSkillNamesAvailable(resolution.preview, registry.extensions, await reservedSkillNames(options.reservedSkillNames));
|
|
5472
|
+
const timestamp = now().toISOString();
|
|
5473
|
+
const installed = await materializeExtension({
|
|
5474
|
+
rootPath,
|
|
5475
|
+
resolution,
|
|
5476
|
+
installedAt: timestamp,
|
|
5477
|
+
updatedAt: timestamp,
|
|
5478
|
+
github
|
|
5479
|
+
});
|
|
5480
|
+
try {
|
|
5481
|
+
const reserved = await reservedSkillNames(options.reservedSkillNames);
|
|
5482
|
+
await writeRegistry(registryPath, now, (current) => ({
|
|
5483
|
+
...current,
|
|
5484
|
+
extensions: appendInstalledExtension(current, installed, reserved)
|
|
5485
|
+
}));
|
|
5486
|
+
await finalizeMaterialization(rootPath, installed.id);
|
|
5487
|
+
return installed;
|
|
5488
|
+
} catch (error) {
|
|
5489
|
+
await rollbackMaterialization(rootPath, installed.id);
|
|
5490
|
+
throw error;
|
|
5491
|
+
}
|
|
5492
|
+
});
|
|
5493
|
+
}
|
|
5494
|
+
async function update(request) {
|
|
5495
|
+
const identity = parseGithubExtensionSource(request.source);
|
|
5496
|
+
return withExtensionLock(rootPath, identity.id, async () => {
|
|
5497
|
+
const registry = await readRegistry(registryPath);
|
|
5498
|
+
const existing = requireInstalled(registry, identity.id);
|
|
5499
|
+
const resolution = await github.resolve({
|
|
5500
|
+
source: existing.repositoryUrl,
|
|
5501
|
+
ref: request.ref?.trim() || existing.requestedRef
|
|
5502
|
+
});
|
|
5503
|
+
assertInstallable(resolution.preview);
|
|
5504
|
+
assertSkillNamesAvailable(resolution.preview, registry.extensions.filter((extension) => extension.id !== existing.id), await reservedSkillNames(options.reservedSkillNames));
|
|
5505
|
+
if (existing.resolvedCommit === resolution.preview.resolvedCommit && existing.packageHash === resolution.preview.packageHash && existing.requestedRef === resolution.preview.requestedRef) {
|
|
5506
|
+
return hydrateExtension(rootPath, existing);
|
|
5507
|
+
}
|
|
5508
|
+
const installed = await materializeExtension({
|
|
5509
|
+
rootPath,
|
|
5510
|
+
resolution,
|
|
5511
|
+
installedAt: existing.installedAt,
|
|
5512
|
+
updatedAt: now().toISOString(),
|
|
5513
|
+
github
|
|
5514
|
+
});
|
|
5515
|
+
try {
|
|
5516
|
+
const reserved = await reservedSkillNames(options.reservedSkillNames);
|
|
5517
|
+
await writeRegistry(registryPath, now, (current) => ({
|
|
5518
|
+
...current,
|
|
5519
|
+
extensions: replaceInstalledExtension(current, installed, reserved)
|
|
5520
|
+
}));
|
|
5521
|
+
await finalizeMaterialization(rootPath, installed.id);
|
|
5522
|
+
return installed;
|
|
5523
|
+
} catch (error) {
|
|
5524
|
+
await rollbackMaterialization(rootPath, installed.id);
|
|
5525
|
+
throw error;
|
|
5526
|
+
}
|
|
5527
|
+
});
|
|
5528
|
+
}
|
|
5529
|
+
async function updateAll() {
|
|
5530
|
+
const catalog = await list();
|
|
5531
|
+
if (catalog.error)
|
|
5532
|
+
throw new GithubExtensionError(catalog.error, { code: "extension_registry_error" });
|
|
5533
|
+
const result = { updated: [], unchanged: [], failed: [] };
|
|
5534
|
+
for (const extension of catalog.extensions) {
|
|
5535
|
+
try {
|
|
5536
|
+
const next = await update({ source: extension.repositoryUrl, ref: extension.requestedRef });
|
|
5537
|
+
if (next.resolvedCommit === extension.resolvedCommit && next.packageHash === extension.packageHash) {
|
|
5538
|
+
result.unchanged.push(next);
|
|
5539
|
+
} else {
|
|
5540
|
+
result.updated.push(next);
|
|
5541
|
+
}
|
|
5542
|
+
} catch (error) {
|
|
5543
|
+
result.failed.push({
|
|
5544
|
+
id: extension.id,
|
|
5545
|
+
error: error instanceof Error ? error.message : String(error)
|
|
5546
|
+
});
|
|
5547
|
+
}
|
|
5548
|
+
}
|
|
5549
|
+
return result;
|
|
5550
|
+
}
|
|
5551
|
+
async function inspect(source) {
|
|
5552
|
+
const identity = parseGithubExtensionSource(source);
|
|
5553
|
+
const registry = await readRegistry(registryPath);
|
|
5554
|
+
return hydrateExtension(rootPath, requireInstalled(registry, identity.id));
|
|
5555
|
+
}
|
|
5556
|
+
async function remove(source) {
|
|
5557
|
+
const identity = parseGithubExtensionSource(source);
|
|
5558
|
+
return withExtensionLock(rootPath, identity.id, async () => {
|
|
5559
|
+
const registry = await readRegistry(registryPath);
|
|
5560
|
+
const existing = requireInstalled(registry, identity.id);
|
|
5561
|
+
const target = extensionDirectory(rootPath, identity.owner, identity.repo);
|
|
5562
|
+
const trash = `${target}.${randomUUID3()}.remove`;
|
|
5563
|
+
if (existsSync6(target))
|
|
5564
|
+
await rename(target, trash);
|
|
5565
|
+
try {
|
|
5566
|
+
await writeRegistry(registryPath, now, (current) => ({
|
|
5567
|
+
...current,
|
|
5568
|
+
extensions: current.extensions.filter((extension) => extension.id !== existing.id)
|
|
5569
|
+
}));
|
|
5570
|
+
await rm(trash, { recursive: true, force: true });
|
|
5571
|
+
return existing;
|
|
5572
|
+
} catch (error) {
|
|
5573
|
+
if (existsSync6(trash) && !existsSync6(target))
|
|
5574
|
+
await rename(trash, target);
|
|
5575
|
+
throw error;
|
|
5576
|
+
}
|
|
5577
|
+
});
|
|
5578
|
+
}
|
|
5579
|
+
async function readSkill(nameInput) {
|
|
5580
|
+
const name = nameInput.trim();
|
|
5581
|
+
if (!/^[a-z0-9]+(?:-[a-z0-9]+)*$/.test(name)) {
|
|
5582
|
+
throw new GithubExtensionError("Extension skill name must be lowercase kebab-case.", {
|
|
5583
|
+
code: "extension_skill_invalid_name"
|
|
5584
|
+
});
|
|
5585
|
+
}
|
|
5586
|
+
const catalog = await list();
|
|
5587
|
+
if (catalog.error) {
|
|
5588
|
+
throw new GithubExtensionError(catalog.error, { code: "extension_registry_error" });
|
|
5589
|
+
}
|
|
5590
|
+
const matches = catalog.extensions.flatMap((extension) => extension.skills.filter((skill) => skill.name === name).map((skill) => ({ extension, skill })));
|
|
5591
|
+
if (matches.length === 0) {
|
|
5592
|
+
throw new GithubExtensionError(`Extension skill not found: ${name}`, {
|
|
5593
|
+
code: "extension_skill_not_found",
|
|
5594
|
+
status: 404
|
|
5595
|
+
});
|
|
5596
|
+
}
|
|
5597
|
+
if (matches.length > 1) {
|
|
5598
|
+
throw new GithubExtensionError(`Extension skill name is ambiguous: ${name}`, {
|
|
5599
|
+
code: "extension_skill_conflict",
|
|
5600
|
+
status: 409
|
|
5601
|
+
});
|
|
5602
|
+
}
|
|
5603
|
+
const match = matches[0];
|
|
5604
|
+
if (match.extension.validationStatus !== "valid" || match.skill.validationStatus !== "valid") {
|
|
5605
|
+
throw new GithubExtensionError(`Extension skill ${name} is not valid.`, {
|
|
5606
|
+
code: "extension_skill_invalid"
|
|
5607
|
+
});
|
|
5608
|
+
}
|
|
5609
|
+
const absolutePath = safeDestination(match.extension.sourcePath, match.skill.relativePath);
|
|
5610
|
+
const markdown = await readFile6(absolutePath, "utf8");
|
|
5611
|
+
const sourceHash = createHash4("sha256").update(markdown).digest("hex");
|
|
5612
|
+
if (sourceHash !== match.skill.sourceHash) {
|
|
5613
|
+
throw new GithubExtensionError(`Extension skill ${name} changed on disk. Update or reinstall its extension before using it.`, { code: "extension_skill_modified" });
|
|
5614
|
+
}
|
|
5615
|
+
const parsed = parseProfileSkillMarkdown(markdown);
|
|
5616
|
+
if (parsed.messages.length > 0 || parsed.name !== name || !parsed.description) {
|
|
5617
|
+
throw new GithubExtensionError(`Extension skill ${name} is not valid. ${parsed.messages.join(" ")}`.trim(), { code: "extension_skill_invalid" });
|
|
5618
|
+
}
|
|
5619
|
+
return {
|
|
5620
|
+
name,
|
|
5621
|
+
description: parsed.description,
|
|
5622
|
+
body: parsed.body,
|
|
5623
|
+
path: match.skill.relativePath,
|
|
5624
|
+
sourcePath: match.extension.sourcePath,
|
|
5625
|
+
sourceHash,
|
|
5626
|
+
charCount: markdown.length,
|
|
5627
|
+
packagePath: path11.dirname(absolutePath),
|
|
5628
|
+
resourceFiles: match.skill.resourceFiles
|
|
5629
|
+
};
|
|
5630
|
+
}
|
|
5631
|
+
return { rootPath, registryPath, list, preview, add, update, updateAll, inspect, remove, readSkill };
|
|
5632
|
+
}
|
|
5633
|
+
async function materializeExtension(input) {
|
|
5634
|
+
const preview = input.resolution.preview;
|
|
5635
|
+
const target = extensionDirectory(input.rootPath, preview.owner, preview.repo);
|
|
5636
|
+
const temporary = `${target}.${randomUUID3()}.install`;
|
|
5637
|
+
const backup = backupDirectory(input.rootPath, preview.id);
|
|
5638
|
+
const current = path11.join(temporary, "current");
|
|
5639
|
+
await rm(temporary, { recursive: true, force: true });
|
|
5640
|
+
await rm(backup, { recursive: true, force: true });
|
|
5641
|
+
await mkdir2(current, { recursive: true, mode: 448 });
|
|
5642
|
+
try {
|
|
5643
|
+
await input.github.download(input.resolution, async (relativePath, bytes, executable) => {
|
|
5644
|
+
const destination = safeDestination(current, relativePath);
|
|
5645
|
+
await mkdir2(path11.dirname(destination), { recursive: true, mode: 448 });
|
|
5646
|
+
await writeFile3(destination, bytes, { mode: executable ? 448 : 384 });
|
|
5647
|
+
});
|
|
5648
|
+
const extension = installedExtension(preview, target, input.installedAt, input.updatedAt);
|
|
5649
|
+
await writeFile3(path11.join(temporary, "extension.json"), `${JSON.stringify(extension, null, 2)}
|
|
5650
|
+
`, { mode: 384 });
|
|
5651
|
+
await mkdir2(path11.dirname(target), { recursive: true, mode: 448 });
|
|
5652
|
+
if (existsSync6(target))
|
|
5653
|
+
await rename(target, backup);
|
|
5654
|
+
await rename(temporary, target);
|
|
5655
|
+
return extension;
|
|
5656
|
+
} catch (error) {
|
|
5657
|
+
await rm(temporary, { recursive: true, force: true });
|
|
5658
|
+
if (existsSync6(backup) && !existsSync6(target))
|
|
5659
|
+
await rename(backup, target);
|
|
5660
|
+
throw error;
|
|
5661
|
+
}
|
|
5662
|
+
}
|
|
5663
|
+
function installedExtension(preview, target, installedAt, updatedAt) {
|
|
5664
|
+
const sourcePath = path11.join(target, "current");
|
|
5665
|
+
return {
|
|
5666
|
+
...preview,
|
|
5667
|
+
sourcePath,
|
|
5668
|
+
readmePath: preview.readmePath ? path11.join(sourcePath, preview.readmePath) : null,
|
|
5669
|
+
installedAt,
|
|
5670
|
+
updatedAt,
|
|
5671
|
+
skills: preview.skills.map((skill) => ({
|
|
5672
|
+
...skill,
|
|
5673
|
+
sourcePath: path11.join(sourcePath, skill.relativePath)
|
|
5674
|
+
}))
|
|
5675
|
+
};
|
|
5676
|
+
}
|
|
5677
|
+
async function finalizeMaterialization(rootPath, id) {
|
|
5678
|
+
await rm(backupDirectory(rootPath, id), { recursive: true, force: true });
|
|
5679
|
+
}
|
|
5680
|
+
async function rollbackMaterialization(rootPath, id) {
|
|
5681
|
+
const identity = parseGithubExtensionSource(id.replace(/^github:/, ""));
|
|
5682
|
+
const target = extensionDirectory(rootPath, identity.owner, identity.repo);
|
|
5683
|
+
const backup = backupDirectory(rootPath, id);
|
|
5684
|
+
await rm(target, { recursive: true, force: true });
|
|
5685
|
+
if (existsSync6(backup))
|
|
5686
|
+
await rename(backup, target);
|
|
5687
|
+
}
|
|
5688
|
+
async function hydrateExtension(rootPath, extension) {
|
|
5689
|
+
const target = extensionDirectory(rootPath, extension.owner, extension.repo);
|
|
5690
|
+
const sourcePath = path11.join(target, "current");
|
|
5691
|
+
const present = (await stat4(path11.join(target, "extension.json")).catch(() => null))?.isFile() ?? false;
|
|
5692
|
+
const validationMessages = extension.validationMessages.filter((message) => message !== "Installed files are missing.");
|
|
5693
|
+
if (!present)
|
|
5694
|
+
validationMessages.push("Installed files are missing.");
|
|
5695
|
+
return {
|
|
5696
|
+
...extension,
|
|
5697
|
+
sourcePath,
|
|
5698
|
+
readmePath: extension.readmePath ? path11.join(sourcePath, path11.basename(extension.readmePath)) : null,
|
|
5699
|
+
skills: extension.skills.map((skill) => ({
|
|
5700
|
+
...skill,
|
|
5701
|
+
sourcePath: path11.join(sourcePath, skill.relativePath)
|
|
5702
|
+
})),
|
|
5703
|
+
validationStatus: validationMessages.length === 0 ? "valid" : "error",
|
|
5704
|
+
validationMessages
|
|
5705
|
+
};
|
|
5706
|
+
}
|
|
5707
|
+
function assertInstallable(preview) {
|
|
5708
|
+
if (preview.validationStatus === "valid")
|
|
5709
|
+
return;
|
|
5710
|
+
throw new GithubExtensionError(`Extension contains invalid skills: ${preview.validationMessages.join(" ")}`, { code: "extension_invalid" });
|
|
5711
|
+
}
|
|
5712
|
+
function assertSkillNamesAvailable(preview, installed, reserved) {
|
|
5713
|
+
const owners = /* @__PURE__ */ new Map();
|
|
5714
|
+
for (const name of reserved)
|
|
5715
|
+
owners.set(name, "a shipped OpenPond skill");
|
|
5716
|
+
for (const extension of installed) {
|
|
5717
|
+
for (const skill of extension.skills)
|
|
5718
|
+
owners.set(skill.name, extension.id);
|
|
5719
|
+
}
|
|
5720
|
+
const conflicts = preview.skills.map((skill) => ({ name: skill.name, owner: owners.get(skill.name) })).filter((entry) => Boolean(entry.owner));
|
|
5721
|
+
if (conflicts.length === 0)
|
|
5722
|
+
return;
|
|
5723
|
+
throw new GithubExtensionError(`Skill name conflict: ${conflicts.map((entry) => `${entry.name} (${entry.owner})`).join(", ")}.`, { code: "extension_skill_conflict", status: 409 });
|
|
5724
|
+
}
|
|
5725
|
+
function appendInstalledExtension(registry, installed, reserved) {
|
|
5726
|
+
if (registry.extensions.some((extension) => extension.id === installed.id)) {
|
|
5727
|
+
throw new GithubExtensionError(`${installed.owner}/${installed.repo} is already installed.`, {
|
|
5728
|
+
code: "extension_already_installed",
|
|
5729
|
+
status: 409
|
|
5730
|
+
});
|
|
5731
|
+
}
|
|
5732
|
+
assertSkillNamesAvailable(installed, registry.extensions, reserved);
|
|
5733
|
+
return [...registry.extensions, installed].sort(extensionSort);
|
|
5734
|
+
}
|
|
5735
|
+
function replaceInstalledExtension(registry, installed, reserved) {
|
|
5736
|
+
requireInstalled(registry, installed.id);
|
|
5737
|
+
assertSkillNamesAvailable(installed, registry.extensions.filter((extension) => extension.id !== installed.id), reserved);
|
|
5738
|
+
return registry.extensions.map((extension) => extension.id === installed.id ? installed : extension).sort(extensionSort);
|
|
5739
|
+
}
|
|
5740
|
+
function markInstalledSkillConflicts(extensions, reserved) {
|
|
5741
|
+
const owners = /* @__PURE__ */ new Map();
|
|
5742
|
+
for (const name of reserved)
|
|
5743
|
+
owners.set(name, "built-in");
|
|
5744
|
+
for (const extension of extensions) {
|
|
5745
|
+
for (const skill of extension.skills) {
|
|
5746
|
+
const owner = owners.get(skill.name);
|
|
5747
|
+
if (!owner) {
|
|
5748
|
+
owners.set(skill.name, extension.id);
|
|
5749
|
+
continue;
|
|
5750
|
+
}
|
|
5751
|
+
const message = `Skill name conflicts with ${owner}: ${skill.name}`;
|
|
5752
|
+
skill.validationStatus = "error";
|
|
5753
|
+
skill.validationMessages = [.../* @__PURE__ */ new Set([...skill.validationMessages, message])];
|
|
5754
|
+
extension.validationStatus = "error";
|
|
5755
|
+
extension.validationMessages = [.../* @__PURE__ */ new Set([...extension.validationMessages, message])];
|
|
5756
|
+
}
|
|
5757
|
+
}
|
|
5758
|
+
}
|
|
5759
|
+
async function reservedSkillNames(source) {
|
|
5760
|
+
const values = typeof source === "function" ? await source() : source ?? [];
|
|
5761
|
+
return [...new Set(values.map((value) => value.trim()).filter(Boolean))];
|
|
5762
|
+
}
|
|
5763
|
+
function requireInstalled(registry, id) {
|
|
5764
|
+
const extension = registry.extensions.find((candidate) => candidate.id === id);
|
|
5765
|
+
if (extension)
|
|
5766
|
+
return extension;
|
|
5767
|
+
throw new GithubExtensionError(`${id.replace(/^github:/, "")} is not installed.`, {
|
|
5768
|
+
code: "extension_not_installed",
|
|
5769
|
+
status: 404
|
|
5770
|
+
});
|
|
5771
|
+
}
|
|
5772
|
+
async function readRegistry(registryPath) {
|
|
5773
|
+
try {
|
|
5774
|
+
const parsed = JSON.parse(await readFile6(registryPath, "utf8"));
|
|
5775
|
+
if (parsed.schemaVersion !== REGISTRY_SCHEMA_VERSION || !Array.isArray(parsed.extensions)) {
|
|
5776
|
+
throw new Error("Extension registry has an unsupported format.");
|
|
5777
|
+
}
|
|
5778
|
+
return {
|
|
5779
|
+
schemaVersion: REGISTRY_SCHEMA_VERSION,
|
|
5780
|
+
updatedAt: typeof parsed.updatedAt === "string" ? parsed.updatedAt : null,
|
|
5781
|
+
extensions: parsed.extensions.filter(isStoredExtension)
|
|
5782
|
+
};
|
|
5783
|
+
} catch (error) {
|
|
5784
|
+
if (error.code === "ENOENT")
|
|
5785
|
+
return emptyRegistry();
|
|
5786
|
+
throw error;
|
|
5787
|
+
}
|
|
5788
|
+
}
|
|
5789
|
+
async function writeRegistry(registryPath, now, update) {
|
|
5790
|
+
await updatePrivateJsonFile(registryPath, emptyRegistry, (current) => ({
|
|
5791
|
+
...update(normalizeRegistry(current)),
|
|
5792
|
+
schemaVersion: REGISTRY_SCHEMA_VERSION,
|
|
5793
|
+
updatedAt: now().toISOString()
|
|
5794
|
+
}));
|
|
5795
|
+
}
|
|
5796
|
+
function normalizeRegistry(value) {
|
|
5797
|
+
return {
|
|
5798
|
+
schemaVersion: REGISTRY_SCHEMA_VERSION,
|
|
5799
|
+
updatedAt: typeof value?.updatedAt === "string" ? value.updatedAt : null,
|
|
5800
|
+
extensions: Array.isArray(value?.extensions) ? value.extensions.filter(isStoredExtension) : []
|
|
5801
|
+
};
|
|
5802
|
+
}
|
|
5803
|
+
function emptyRegistry() {
|
|
5804
|
+
return { schemaVersion: REGISTRY_SCHEMA_VERSION, updatedAt: null, extensions: [] };
|
|
5805
|
+
}
|
|
5806
|
+
function isStoredExtension(value) {
|
|
5807
|
+
if (!value || typeof value !== "object")
|
|
5808
|
+
return false;
|
|
5809
|
+
const extension = value;
|
|
5810
|
+
return extension.source === "github" && typeof extension.id === "string" && typeof extension.owner === "string" && typeof extension.repo === "string" && typeof extension.repositoryUrl === "string" && typeof extension.requestedRef === "string" && typeof extension.resolvedCommit === "string" && Array.isArray(extension.skills);
|
|
5811
|
+
}
|
|
5812
|
+
function safeDestination(root, relativePath) {
|
|
5813
|
+
if (path11.isAbsolute(relativePath) || relativePath.split(/[\\/]/).includes("..")) {
|
|
5814
|
+
throw new GithubExtensionError(`Unsafe extension path: ${relativePath}`, {
|
|
5815
|
+
code: "extension_unsafe_path"
|
|
5816
|
+
});
|
|
5817
|
+
}
|
|
5818
|
+
const destination = path11.resolve(root, ...relativePath.split("/"));
|
|
5819
|
+
const prefix = `${path11.resolve(root)}${path11.sep}`;
|
|
5820
|
+
if (!destination.startsWith(prefix)) {
|
|
5821
|
+
throw new GithubExtensionError(`Unsafe extension path: ${relativePath}`, {
|
|
5822
|
+
code: "extension_unsafe_path"
|
|
5823
|
+
});
|
|
5824
|
+
}
|
|
5825
|
+
return destination;
|
|
5826
|
+
}
|
|
5827
|
+
function extensionDirectory(rootPath, owner, repo) {
|
|
5828
|
+
return path11.join(rootPath, "github", owner, repo);
|
|
5829
|
+
}
|
|
5830
|
+
function backupDirectory(rootPath, id) {
|
|
5831
|
+
const identity = parseGithubExtensionSource(id.replace(/^github:/, ""));
|
|
5832
|
+
return `${extensionDirectory(rootPath, identity.owner, identity.repo)}.previous`;
|
|
5833
|
+
}
|
|
5834
|
+
async function withExtensionLock(rootPath, id, operation) {
|
|
5835
|
+
const safeId = id.replace(/[^a-z0-9.-]+/gi, "-");
|
|
5836
|
+
const lockPath = path11.join(rootPath, ".locks", `${safeId}.lock`);
|
|
5837
|
+
await mkdir2(path11.dirname(lockPath), { recursive: true, mode: 448 });
|
|
5838
|
+
const deadline = Date.now() + OPERATION_LOCK_TIMEOUT_MS;
|
|
5839
|
+
while (true) {
|
|
5840
|
+
try {
|
|
5841
|
+
await mkdir2(lockPath, { mode: 448 });
|
|
5842
|
+
break;
|
|
5843
|
+
} catch (error) {
|
|
5844
|
+
if (error.code !== "EEXIST")
|
|
5845
|
+
throw error;
|
|
5846
|
+
const lockStat = await stat4(lockPath).catch(() => null);
|
|
5847
|
+
if (lockStat && Date.now() - lockStat.mtimeMs > OPERATION_LOCK_STALE_MS) {
|
|
5848
|
+
await rm(lockPath, { recursive: true, force: true });
|
|
5849
|
+
continue;
|
|
5850
|
+
}
|
|
5851
|
+
if (Date.now() >= deadline) {
|
|
5852
|
+
throw new GithubExtensionError(`Timed out waiting for extension operation: ${id}`, {
|
|
5853
|
+
code: "extension_operation_busy",
|
|
5854
|
+
status: 409
|
|
5855
|
+
});
|
|
5856
|
+
}
|
|
5857
|
+
await new Promise((resolve) => setTimeout(resolve, 30));
|
|
5858
|
+
}
|
|
5859
|
+
}
|
|
5860
|
+
try {
|
|
5861
|
+
return await operation();
|
|
5862
|
+
} finally {
|
|
5863
|
+
await rm(lockPath, { recursive: true, force: true });
|
|
5864
|
+
}
|
|
5865
|
+
}
|
|
5866
|
+
function extensionSort(left, right) {
|
|
5867
|
+
return left.id.localeCompare(right.id);
|
|
5868
|
+
}
|
|
5869
|
+
|
|
5022
5870
|
// ../../packages/cloud/dist/profile/hosted-run-idempotency.js
|
|
5023
|
-
import { createHash as
|
|
5871
|
+
import { createHash as createHash5, randomUUID as randomUUID4 } from "node:crypto";
|
|
5024
5872
|
function buildHostedRunIdempotencyKey(input) {
|
|
5025
5873
|
const explicit = input.explicitKey?.trim();
|
|
5026
5874
|
if (explicit)
|
|
@@ -5031,10 +5879,10 @@ function buildHostedRunIdempotencyKey(input) {
|
|
|
5031
5879
|
const base = `profile-push-run:${input.localHead}:${sourceHead}:${input.runtimeAgentId}:${targetProjectId}:${inputHash}`;
|
|
5032
5880
|
if (!input.retry)
|
|
5033
5881
|
return base;
|
|
5034
|
-
return `${base}:retry:${(input.randomId ??
|
|
5882
|
+
return `${base}:retry:${(input.randomId ?? randomUUID4)()}`;
|
|
5035
5883
|
}
|
|
5036
5884
|
function hashStableJson(value) {
|
|
5037
|
-
return
|
|
5885
|
+
return createHash5("sha256").update(stableJsonStringify(value)).digest("hex");
|
|
5038
5886
|
}
|
|
5039
5887
|
function stableJsonStringify(value) {
|
|
5040
5888
|
if (value === void 0)
|
|
@@ -5048,9 +5896,9 @@ function stableJsonStringify(value) {
|
|
|
5048
5896
|
}
|
|
5049
5897
|
|
|
5050
5898
|
// ../../packages/cloud/dist/profile/profile-skill-goal-executor.js
|
|
5051
|
-
import { existsSync as
|
|
5052
|
-
import { mkdir as
|
|
5053
|
-
import
|
|
5899
|
+
import { existsSync as existsSync7 } from "node:fs";
|
|
5900
|
+
import { mkdir as mkdir3, readFile as readFile7, writeFile as writeFile4 } from "node:fs/promises";
|
|
5901
|
+
import path12 from "node:path";
|
|
5054
5902
|
async function executeProfileSkillGoalRequest(goal) {
|
|
5055
5903
|
if (goal.operation === "edit")
|
|
5056
5904
|
return executeProfileSkillEdit(goal);
|
|
@@ -5061,9 +5909,9 @@ async function executeProfileSkillCreate(goal) {
|
|
|
5061
5909
|
const existingNames = new Set(existing.skills.map((skill) => skill.name));
|
|
5062
5910
|
const skillName = uniqueSkillName(goal.targetSkillName ?? goal.requestedName ?? inferSkillName(goal.userObjective), existingNames, goal.profileSourcePath);
|
|
5063
5911
|
const skillPath = profileSkillPath(skillName);
|
|
5064
|
-
const absolutePath =
|
|
5065
|
-
await
|
|
5066
|
-
await
|
|
5912
|
+
const absolutePath = path12.join(goal.profileSourcePath, skillPath);
|
|
5913
|
+
await mkdir3(path12.dirname(absolutePath), { recursive: true });
|
|
5914
|
+
await writeFile4(absolutePath, renderSkillMarkdown({
|
|
5067
5915
|
name: skillName,
|
|
5068
5916
|
description: descriptionForObjective(goal.userObjective),
|
|
5069
5917
|
body: bodyForObjective(goal.userObjective)
|
|
@@ -5075,10 +5923,10 @@ async function executeProfileSkillEdit(goal) {
|
|
|
5075
5923
|
if (!skillName)
|
|
5076
5924
|
throw new Error("Profile skill edit requires skillName.");
|
|
5077
5925
|
const skillPath = profileSkillPath(skillName);
|
|
5078
|
-
const absolutePath =
|
|
5079
|
-
if (!
|
|
5926
|
+
const absolutePath = path12.join(goal.profileSourcePath, skillPath);
|
|
5927
|
+
if (!existsSync7(absolutePath))
|
|
5080
5928
|
throw new Error(`Profile skill not found: ${skillName}`);
|
|
5081
|
-
const current = await
|
|
5929
|
+
const current = await readFile7(absolutePath, "utf8");
|
|
5082
5930
|
const parsed = parseProfileSkillMarkdown(current);
|
|
5083
5931
|
if (parsed.messages.length > 0 || !parsed.name || !parsed.description) {
|
|
5084
5932
|
throw new Error(`Profile skill ${skillName} is not valid. ${parsed.messages.join(" ")}`);
|
|
@@ -5092,7 +5940,7 @@ async function executeProfileSkillEdit(goal) {
|
|
|
5092
5940
|
change,
|
|
5093
5941
|
""
|
|
5094
5942
|
].join("\n");
|
|
5095
|
-
await
|
|
5943
|
+
await writeFile4(absolutePath, renderSkillMarkdown({
|
|
5096
5944
|
name: parsed.name,
|
|
5097
5945
|
description: parsed.description,
|
|
5098
5946
|
body
|
|
@@ -5108,7 +5956,7 @@ async function validateExecutedGoal(goal, skillName) {
|
|
|
5108
5956
|
...goal,
|
|
5109
5957
|
status: "completed",
|
|
5110
5958
|
targetSkillName: skillName,
|
|
5111
|
-
targetSkillPath:
|
|
5959
|
+
targetSkillPath: path12.join(goal.profileSourceRelativePath, PROFILE_SKILLS_DIR, skillName, PROFILE_SKILL_FILE).replace(/\\/g, "/")
|
|
5112
5960
|
};
|
|
5113
5961
|
const validationStatus = skill.validationStatus === "valid" ? "valid" : "error";
|
|
5114
5962
|
if (validationStatus !== "valid") {
|
|
@@ -5241,14 +6089,14 @@ function uniqueSkillName(baseName, existingNames, profileSourcePath2) {
|
|
|
5241
6089
|
const base = normalizeSkillName2(baseName) ?? "profile-skill";
|
|
5242
6090
|
let candidate = base;
|
|
5243
6091
|
let suffix = 2;
|
|
5244
|
-
while (existingNames.has(candidate) ||
|
|
6092
|
+
while (existingNames.has(candidate) || existsSync7(path12.join(profileSourcePath2, PROFILE_SKILLS_DIR, candidate))) {
|
|
5245
6093
|
candidate = `${base}-${suffix}`;
|
|
5246
6094
|
suffix += 1;
|
|
5247
6095
|
}
|
|
5248
6096
|
return candidate;
|
|
5249
6097
|
}
|
|
5250
6098
|
function profileSkillPath(skillName) {
|
|
5251
|
-
return
|
|
6099
|
+
return path12.join(PROFILE_SKILLS_DIR, skillName, PROFILE_SKILL_FILE).replace(/\\/g, "/");
|
|
5252
6100
|
}
|
|
5253
6101
|
function normalizeSkillName2(value) {
|
|
5254
6102
|
const normalized = value.trim().toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").replace(/-{2,}/g, "-");
|
|
@@ -7945,31 +8793,12 @@ var AccountProfileSchema = external_exports.object({
|
|
|
7945
8793
|
isVerified: external_exports.boolean().nullable(),
|
|
7946
8794
|
dailyAgentAppId: external_exports.string().nullable(),
|
|
7947
8795
|
dailyAgentDeploymentId: external_exports.string().nullable(),
|
|
7948
|
-
credits: external_exports.string().nullable()
|
|
7949
|
-
turnkeyWalletAddress: external_exports.string().nullable(),
|
|
7950
|
-
turnkeyOperatingWalletAddress: external_exports.string().nullable()
|
|
8796
|
+
credits: external_exports.string().nullable()
|
|
7951
8797
|
});
|
|
7952
8798
|
var ActiveProfileSelectorSchema = external_exports.object({
|
|
7953
8799
|
handle: external_exports.string(),
|
|
7954
8800
|
baseUrl: external_exports.string().nullable().optional()
|
|
7955
8801
|
});
|
|
7956
|
-
var AccountBalanceSchema = external_exports.object({
|
|
7957
|
-
balanceKind: external_exports.string(),
|
|
7958
|
-
balanceUsd: external_exports.string().nullable(),
|
|
7959
|
-
balanceUsdCents: external_exports.number().nullable(),
|
|
7960
|
-
currency: external_exports.string(),
|
|
7961
|
-
asOf: external_exports.string(),
|
|
7962
|
-
stale: external_exports.boolean(),
|
|
7963
|
-
error: external_exports.string().nullable(),
|
|
7964
|
-
breakdown: external_exports.array(external_exports.object({
|
|
7965
|
-
wallet: external_exports.string(),
|
|
7966
|
-
chain: external_exports.string(),
|
|
7967
|
-
chainId: external_exports.number().nullable(),
|
|
7968
|
-
asset: external_exports.string(),
|
|
7969
|
-
amount: external_exports.string().nullable(),
|
|
7970
|
-
usdValue: external_exports.string().nullable()
|
|
7971
|
-
}).passthrough())
|
|
7972
|
-
}).passthrough();
|
|
7973
8802
|
var AccountStateSchema = external_exports.object({
|
|
7974
8803
|
state: external_exports.enum(["signed_out", "signed_in", "loading", "switching", "auth_error"]),
|
|
7975
8804
|
activeProfile: ActiveProfileSelectorSchema.nullable(),
|
|
@@ -7980,8 +8809,6 @@ var AccountStateSchema = external_exports.object({
|
|
|
7980
8809
|
baseUrl: external_exports.string().nullable(),
|
|
7981
8810
|
apiBaseUrl: external_exports.string().nullable(),
|
|
7982
8811
|
chatApiBaseUrl: external_exports.string().nullable().optional().default(null),
|
|
7983
|
-
balanceLabel: external_exports.string(),
|
|
7984
|
-
balance: AccountBalanceSchema.nullable().optional().default(null),
|
|
7985
8812
|
creditsLabel: external_exports.string().nullable(),
|
|
7986
8813
|
profile: AccountProfileSchema.nullable(),
|
|
7987
8814
|
products: external_exports.array(AccountProductSchema),
|
|
@@ -8100,7 +8927,8 @@ var OpenPondProfileSkillSchema = external_exports.object({
|
|
|
8100
8927
|
charCount: external_exports.number(),
|
|
8101
8928
|
sourceHash: external_exports.string(),
|
|
8102
8929
|
validationStatus: external_exports.enum(["valid", "warning", "error"]),
|
|
8103
|
-
validationMessages: external_exports.array(external_exports.string())
|
|
8930
|
+
validationMessages: external_exports.array(external_exports.string()),
|
|
8931
|
+
resourceFiles: external_exports.array(external_exports.string()).optional().default([])
|
|
8104
8932
|
});
|
|
8105
8933
|
var OpenPondProfileEvalSchema = external_exports.object({
|
|
8106
8934
|
id: external_exports.string(),
|
|
@@ -8371,6 +9199,82 @@ function emptyOpenPondProfileState() {
|
|
|
8371
9199
|
};
|
|
8372
9200
|
}
|
|
8373
9201
|
|
|
9202
|
+
// ../../packages/contracts/dist/skills.js
|
|
9203
|
+
var CodexPersonalSkillSchema = external_exports.object({
|
|
9204
|
+
name: external_exports.string(),
|
|
9205
|
+
description: external_exports.string(),
|
|
9206
|
+
path: external_exports.string(),
|
|
9207
|
+
sourcePath: external_exports.string(),
|
|
9208
|
+
enabled: external_exports.boolean(),
|
|
9209
|
+
charCount: external_exports.number().int().nonnegative(),
|
|
9210
|
+
sourceHash: external_exports.string(),
|
|
9211
|
+
validationStatus: external_exports.enum(["valid", "error"]),
|
|
9212
|
+
validationMessages: external_exports.array(external_exports.string()),
|
|
9213
|
+
resourceFiles: external_exports.array(external_exports.string()),
|
|
9214
|
+
updatedAt: external_exports.string().nullable()
|
|
9215
|
+
});
|
|
9216
|
+
var SkillSourceScopeSchema = external_exports.enum(["codex", "profile", "extension"]);
|
|
9217
|
+
var SkillSourceFileSchema = external_exports.object({
|
|
9218
|
+
skillName: external_exports.string(),
|
|
9219
|
+
scope: SkillSourceScopeSchema,
|
|
9220
|
+
path: external_exports.string(),
|
|
9221
|
+
byteSize: external_exports.number().int().nonnegative(),
|
|
9222
|
+
isBinary: external_exports.boolean(),
|
|
9223
|
+
content: external_exports.string().nullable()
|
|
9224
|
+
});
|
|
9225
|
+
|
|
9226
|
+
// ../../packages/contracts/dist/extensions.js
|
|
9227
|
+
var SHIPPED_OPENPOND_SKILL_NAMES = [
|
|
9228
|
+
"openpond-cli",
|
|
9229
|
+
"openpond-desktop-harness",
|
|
9230
|
+
"openpond-taskset-authoring"
|
|
9231
|
+
];
|
|
9232
|
+
var OpenPondExtensionSkillSchema = external_exports.object({
|
|
9233
|
+
name: external_exports.string(),
|
|
9234
|
+
description: external_exports.string(),
|
|
9235
|
+
relativePath: external_exports.string(),
|
|
9236
|
+
sourcePath: external_exports.string(),
|
|
9237
|
+
charCount: external_exports.number().int().nonnegative(),
|
|
9238
|
+
sourceHash: external_exports.string(),
|
|
9239
|
+
resourceFiles: external_exports.array(external_exports.string()),
|
|
9240
|
+
validationStatus: external_exports.enum(["valid", "error"]),
|
|
9241
|
+
validationMessages: external_exports.array(external_exports.string())
|
|
9242
|
+
});
|
|
9243
|
+
var OpenPondExtensionSchema = external_exports.object({
|
|
9244
|
+
id: external_exports.string(),
|
|
9245
|
+
source: external_exports.literal("github"),
|
|
9246
|
+
owner: external_exports.string(),
|
|
9247
|
+
repo: external_exports.string(),
|
|
9248
|
+
repositoryUrl: external_exports.string().url(),
|
|
9249
|
+
requestedRef: external_exports.string(),
|
|
9250
|
+
resolvedCommit: external_exports.string(),
|
|
9251
|
+
sourcePath: external_exports.string(),
|
|
9252
|
+
readmePath: external_exports.string().nullable(),
|
|
9253
|
+
installedAt: external_exports.string(),
|
|
9254
|
+
updatedAt: external_exports.string(),
|
|
9255
|
+
packageHash: external_exports.string(),
|
|
9256
|
+
skills: external_exports.array(OpenPondExtensionSkillSchema),
|
|
9257
|
+
validationStatus: external_exports.enum(["valid", "error"]),
|
|
9258
|
+
validationMessages: external_exports.array(external_exports.string())
|
|
9259
|
+
});
|
|
9260
|
+
var OpenPondExtensionPreviewSchema = OpenPondExtensionSchema.omit({
|
|
9261
|
+
installedAt: true,
|
|
9262
|
+
updatedAt: true,
|
|
9263
|
+
sourcePath: true
|
|
9264
|
+
}).extend({
|
|
9265
|
+
sourcePath: external_exports.null()
|
|
9266
|
+
});
|
|
9267
|
+
var OpenPondExtensionCatalogSchema = external_exports.object({
|
|
9268
|
+
rootPath: external_exports.string(),
|
|
9269
|
+
registryPath: external_exports.string(),
|
|
9270
|
+
extensions: external_exports.array(OpenPondExtensionSchema),
|
|
9271
|
+
error: external_exports.string().nullable()
|
|
9272
|
+
});
|
|
9273
|
+
var OpenPondExtensionSourceRequestSchema = external_exports.object({
|
|
9274
|
+
source: external_exports.string().trim().min(1),
|
|
9275
|
+
ref: external_exports.string().trim().min(1).optional()
|
|
9276
|
+
});
|
|
9277
|
+
|
|
8374
9278
|
// ../../packages/contracts/dist/bootstrap.js
|
|
8375
9279
|
var BootstrapEventWindowSchema = external_exports.object({
|
|
8376
9280
|
latestSequence: external_exports.number().int().nonnegative(),
|
|
@@ -8394,6 +9298,13 @@ var BootstrapPayloadSchema = external_exports.object({
|
|
|
8394
9298
|
localProjects: external_exports.array(LocalProjectSchema).optional().default([]),
|
|
8395
9299
|
cloudProjects: external_exports.array(CloudProjectSchema).optional().default([]),
|
|
8396
9300
|
profile: OpenPondProfileStateSchema.optional().default(emptyOpenPondProfileState),
|
|
9301
|
+
codexPersonalSkills: external_exports.array(CodexPersonalSkillSchema).optional().default([]),
|
|
9302
|
+
extensionCatalog: OpenPondExtensionCatalogSchema.optional().default({
|
|
9303
|
+
rootPath: "",
|
|
9304
|
+
registryPath: "",
|
|
9305
|
+
extensions: [],
|
|
9306
|
+
error: null
|
|
9307
|
+
}),
|
|
8397
9308
|
codexHistorySessions: external_exports.array(SessionSchema).optional().default([]),
|
|
8398
9309
|
sidebarAppPreferences: SidebarAppPreferencesSchema,
|
|
8399
9310
|
sidebarFileBookmarks: external_exports.array(SidebarFileBookmarkSchema).optional().default([]),
|
|
@@ -11583,7 +12494,6 @@ export {
|
|
|
11583
12494
|
createRepo,
|
|
11584
12495
|
getAppEnvironment,
|
|
11585
12496
|
getOpenPondAccount,
|
|
11586
|
-
getOpenPondAccountBalance,
|
|
11587
12497
|
checkOpenPondApiHealth,
|
|
11588
12498
|
loadGlobalConfig,
|
|
11589
12499
|
listConfiguredProfiles,
|
|
@@ -11594,8 +12504,11 @@ export {
|
|
|
11594
12504
|
normalizeSandboxApiUrl,
|
|
11595
12505
|
createOpenPondSandboxClient,
|
|
11596
12506
|
executeConnectedAppToolCall,
|
|
11597
|
-
|
|
12507
|
+
GithubExtensionError,
|
|
12508
|
+
parseProfileSkillMarkdown,
|
|
11598
12509
|
readProfileSkill,
|
|
12510
|
+
createGithubExtensionManager,
|
|
12511
|
+
buildHostedRunIdempotencyKey,
|
|
11599
12512
|
buildOpenPondProfileSetupGate,
|
|
11600
12513
|
formatOpenPondProfileSetupRequirement,
|
|
11601
12514
|
readSourceUploadCache,
|
|
@@ -11731,6 +12644,8 @@ export {
|
|
|
11731
12644
|
SwitchOpenPondAccountRequestSchema,
|
|
11732
12645
|
SaveOpenPondAccountRequestSchema,
|
|
11733
12646
|
UpdateOpenPondAccountConfigRequestSchema,
|
|
12647
|
+
SHIPPED_OPENPOND_SKILL_NAMES,
|
|
12648
|
+
OpenPondExtensionSourceRequestSchema,
|
|
11734
12649
|
BootstrapPayloadSchema,
|
|
11735
12650
|
WorkspaceTemplateConfigViewSchema,
|
|
11736
12651
|
WorkspaceToolRequestSchema,
|