@odla-ai/cli 0.16.2 → 0.16.4
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 +9 -6
- package/dist/bin.cjs +237 -102
- package/dist/bin.cjs.map +1 -1
- package/dist/bin.js +1 -1
- package/dist/{chunk-PQX6SKYJ.js → chunk-GAFC4EPJ.js} +227 -93
- package/dist/chunk-GAFC4EPJ.js.map +1 -0
- package/dist/index.cjs +239 -102
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +16 -4
- package/dist/index.d.ts +16 -4
- package/dist/index.js +3 -1
- package/dist/runtime/pi-agent.js +330317 -0
- package/package.json +2 -2
- package/skills/odla-migrate/references/phase-2-db.md +2 -2
- package/dist/chunk-PQX6SKYJ.js.map +0 -1
package/dist/index.cjs
CHANGED
|
@@ -61,6 +61,7 @@ __export(index_exports, {
|
|
|
61
61
|
isTerminalHostedSecurityStatus: () => isTerminalHostedSecurityStatus,
|
|
62
62
|
listGitHubSecuritySources: () => listGitHubSecuritySources,
|
|
63
63
|
listHostedSecurityJobs: () => listHostedSecurityJobs,
|
|
64
|
+
prepareCodeImages: () => prepareCodeImages,
|
|
64
65
|
printCapabilities: () => printCapabilities,
|
|
65
66
|
provision: () => provision,
|
|
66
67
|
redactSecrets: () => redactSecrets,
|
|
@@ -1992,13 +1993,13 @@ function printStatus(status, json, out) {
|
|
|
1992
1993
|
|
|
1993
1994
|
// src/code-connect.ts
|
|
1994
1995
|
var import_node_fs7 = require("fs");
|
|
1995
|
-
var
|
|
1996
|
-
var
|
|
1996
|
+
var import_node_os2 = require("os");
|
|
1997
|
+
var import_node_path5 = require("path");
|
|
1997
1998
|
|
|
1998
|
-
// ../harness/dist/chunk-
|
|
1999
|
+
// ../harness/dist/chunk-QTUEF2HZ.js
|
|
1999
2000
|
var HARNESS_PROTOCOL_VERSION = 1;
|
|
2000
2001
|
|
|
2001
|
-
// ../harness/dist/chunk-
|
|
2002
|
+
// ../harness/dist/chunk-GE6CCN7W.js
|
|
2002
2003
|
var CONTROL = /[\u0000-\u0008\u000b\u000c\u000e-\u001f\u007f]/;
|
|
2003
2004
|
var HarnessProtocolError = class extends Error {
|
|
2004
2005
|
name = "HarnessProtocolError";
|
|
@@ -2076,7 +2077,7 @@ function encodeAgentInput(message2) {
|
|
|
2076
2077
|
`;
|
|
2077
2078
|
}
|
|
2078
2079
|
|
|
2079
|
-
// ../harness/dist/chunk-
|
|
2080
|
+
// ../harness/dist/chunk-NOBK6PCT.js
|
|
2080
2081
|
var import_child_process = require("child_process");
|
|
2081
2082
|
var import_fs = require("fs");
|
|
2082
2083
|
var import_promises2 = require("fs/promises");
|
|
@@ -2129,7 +2130,7 @@ async function selectContainerEngine(requested = "auto", options = {}) {
|
|
|
2129
2130
|
throw new TypeError("no rootless Podman found; install Podman or explicitly choose --engine docker after reviewing its daemon boundary");
|
|
2130
2131
|
}
|
|
2131
2132
|
if (platform === "darwin") {
|
|
2132
|
-
throw new TypeError("
|
|
2133
|
+
throw new TypeError("Apple container is not installed; on Apple Silicon macOS 26 run `brew install container`, then retry (Podman Machine is the fallback)");
|
|
2133
2134
|
}
|
|
2134
2135
|
throw new TypeError("no supported container engine found");
|
|
2135
2136
|
}
|
|
@@ -2593,7 +2594,7 @@ async function stageWorkspacePair(baselineSource, workspaceSource, options = {})
|
|
|
2593
2594
|
}
|
|
2594
2595
|
}
|
|
2595
2596
|
|
|
2596
|
-
// ../harness/dist/chunk-
|
|
2597
|
+
// ../harness/dist/chunk-6J2ZETST.js
|
|
2597
2598
|
var import_crypto = require("crypto");
|
|
2598
2599
|
var import_promises5 = require("fs/promises");
|
|
2599
2600
|
var import_path5 = require("path");
|
|
@@ -2930,7 +2931,7 @@ function validateSnapshot(snapshot, limits) {
|
|
|
2930
2931
|
}
|
|
2931
2932
|
}
|
|
2932
2933
|
|
|
2933
|
-
// ../harness/dist/chunk-
|
|
2934
|
+
// ../harness/dist/chunk-6J2ZETST.js
|
|
2934
2935
|
var import_child_process4 = require("child_process");
|
|
2935
2936
|
var import_promises6 = require("fs/promises");
|
|
2936
2937
|
var import_path6 = require("path");
|
|
@@ -3223,7 +3224,7 @@ function looksLikeDestination(value) {
|
|
|
3223
3224
|
return /^(?:[a-z][a-z0-9+.-]*:\/\/|\/|\\\\)/i.test(text) || /^[\w.-]+\.[a-z]{2,}(?:[/:]|$)/i.test(text);
|
|
3224
3225
|
}
|
|
3225
3226
|
|
|
3226
|
-
// ../harness/dist/chunk-
|
|
3227
|
+
// ../harness/dist/chunk-6J2ZETST.js
|
|
3227
3228
|
var import_crypto4 = require("crypto");
|
|
3228
3229
|
async function digestStagedWorkspace(root, limits) {
|
|
3229
3230
|
const files = [];
|
|
@@ -4414,6 +4415,7 @@ function codeCommandMetadata(payload, resume) {
|
|
|
4414
4415
|
const role = payload.role;
|
|
4415
4416
|
const title = payload.title;
|
|
4416
4417
|
const prompt = payload.prompt;
|
|
4418
|
+
const maxTokensPerInteraction = payload.maxTokensPerInteraction ?? 32e3;
|
|
4417
4419
|
if (role !== "coding" && role !== "review" || typeof title !== "string" || typeof prompt !== "string") {
|
|
4418
4420
|
throw new TypeError(`invalid Code ${resume ? "resume" : "start"} metadata`);
|
|
4419
4421
|
}
|
|
@@ -4425,10 +4427,14 @@ function codeCommandMetadata(payload, resume) {
|
|
|
4425
4427
|
if (typeof repository !== "string" || !repository.includes("/") || typeof baseCommitSha !== "string" || !/^[0-9a-f]{40}$/.test(baseCommitSha) || typeof sourceTreeDigest !== "string" || !/^sha256:[0-9a-f]{64}$/.test(sourceTreeDigest)) {
|
|
4426
4428
|
throw new TypeError(`invalid Code ${resume ? "resume" : "start"} trusted base`);
|
|
4427
4429
|
}
|
|
4430
|
+
if (!Number.isSafeInteger(maxTokensPerInteraction) || Number(maxTokensPerInteraction) < 4e3 || Number(maxTokensPerInteraction) > 2e5) {
|
|
4431
|
+
throw new TypeError(`invalid Code ${resume ? "resume" : "start"} interaction token limit`);
|
|
4432
|
+
}
|
|
4428
4433
|
return {
|
|
4429
4434
|
role,
|
|
4430
4435
|
title,
|
|
4431
4436
|
prompt,
|
|
4437
|
+
maxTokensPerInteraction: Number(maxTokensPerInteraction),
|
|
4432
4438
|
planningInputDigest: typeof planning === "string" && /^sha256:[0-9a-f]{64}$/.test(planning) ? planning : null,
|
|
4433
4439
|
attestationDigest: typeof attestation === "string" ? attestation : "resume",
|
|
4434
4440
|
repository,
|
|
@@ -4504,6 +4510,57 @@ function createCodeRuntimeToolBroker(input, lease, role) {
|
|
|
4504
4510
|
});
|
|
4505
4511
|
return role === "coding" ? broker : { execute: (context, request) => request.tool === "sandbox.read" ? broker.execute(context, request) : Promise.resolve({ requestId: request.requestId, ok: false, content: "review sessions are read-only" }) };
|
|
4506
4512
|
}
|
|
4513
|
+
async function handleCodeRuntimeInference(input) {
|
|
4514
|
+
const { command, metadata: metadata2, request, state } = input;
|
|
4515
|
+
if (state.tokens >= metadata2.maxTokensPerInteraction) {
|
|
4516
|
+
if (!state.noticeEmitted) {
|
|
4517
|
+
state.noticeEmitted = true;
|
|
4518
|
+
await input.event({
|
|
4519
|
+
type: "message",
|
|
4520
|
+
actor: "system",
|
|
4521
|
+
body: `Pi paused at the ${metadata2.maxTokensPerInteraction.toLocaleString("en-US")}-token per-interaction limit. Send a new instruction to continue.`
|
|
4522
|
+
}).catch(() => void 0);
|
|
4523
|
+
}
|
|
4524
|
+
return {
|
|
4525
|
+
protocolVersion: HARNESS_PROTOCOL_VERSION,
|
|
4526
|
+
type: "inference.response",
|
|
4527
|
+
requestId: request.requestId,
|
|
4528
|
+
response: {
|
|
4529
|
+
id: `budget:${command.commandId}`,
|
|
4530
|
+
provider: "openai",
|
|
4531
|
+
model: "interaction-budget",
|
|
4532
|
+
role: "assistant",
|
|
4533
|
+
content: [{ type: "text", text: "Pause now. The owner-set token limit for this interaction has been reached." }],
|
|
4534
|
+
stopReason: "end_turn",
|
|
4535
|
+
usage: { inputTokens: 0, outputTokens: 0 }
|
|
4536
|
+
}
|
|
4537
|
+
};
|
|
4538
|
+
}
|
|
4539
|
+
const startedAt = Date.now();
|
|
4540
|
+
const response2 = await input.control.infer(command.sessionId, {
|
|
4541
|
+
requestId: request.requestId,
|
|
4542
|
+
interactionId: command.commandId,
|
|
4543
|
+
call: request.call
|
|
4544
|
+
});
|
|
4545
|
+
state.tokens += response2.receipt.inputTokens + response2.receipt.outputTokens;
|
|
4546
|
+
await input.event({
|
|
4547
|
+
type: "usage",
|
|
4548
|
+
provider: response2.receipt.provider,
|
|
4549
|
+
model: response2.receipt.model,
|
|
4550
|
+
inputTokens: response2.receipt.inputTokens,
|
|
4551
|
+
outputTokens: response2.receipt.outputTokens,
|
|
4552
|
+
durationMs: Date.now() - startedAt,
|
|
4553
|
+
interactionId: command.commandId,
|
|
4554
|
+
interactionTokens: state.tokens,
|
|
4555
|
+
interactionMaxTokens: metadata2.maxTokensPerInteraction
|
|
4556
|
+
}).catch(() => void 0);
|
|
4557
|
+
return {
|
|
4558
|
+
protocolVersion: HARNESS_PROTOCOL_VERSION,
|
|
4559
|
+
type: "inference.response",
|
|
4560
|
+
requestId: request.requestId,
|
|
4561
|
+
response: response2.response
|
|
4562
|
+
};
|
|
4563
|
+
}
|
|
4507
4564
|
async function appendCodeRuntimeEvent(control, command, event, refs) {
|
|
4508
4565
|
const eventId = `${command.commandId.slice(0, 45)}:${refs.length + 1}`;
|
|
4509
4566
|
refs.push(eventId);
|
|
@@ -4533,6 +4590,7 @@ function runtimeResultError(value) {
|
|
|
4533
4590
|
var CodePiRuntimeEngine = class {
|
|
4534
4591
|
constructor(options) {
|
|
4535
4592
|
this.options = options;
|
|
4593
|
+
if (options.imageAuthorization === "cli_embedded" && !/^odla-ai\/pi-agent:embedded-sha256-[0-9a-f]{64}$/.test(options.image)) throw new TypeError("CLI-embedded Pi image must use its content-addressed local tag");
|
|
4536
4594
|
this.#run = options.runAttempt ?? runContainerAttempt;
|
|
4537
4595
|
this.#buildPolicyDigest = digestRuntimeValue(JSON.stringify(options.recipes));
|
|
4538
4596
|
this.#checkpoints = new CodeRuntimeCheckpointManager({
|
|
@@ -4615,6 +4673,7 @@ var CodePiRuntimeEngine = class {
|
|
|
4615
4673
|
acknowledged: false,
|
|
4616
4674
|
role: metadata2.role,
|
|
4617
4675
|
title: metadata2.title,
|
|
4676
|
+
maxTokensPerInteraction: metadata2.maxTokensPerInteraction,
|
|
4618
4677
|
baseCommitSha: metadata2.baseCommitSha,
|
|
4619
4678
|
repository: metadata2.repository,
|
|
4620
4679
|
sourceTreeDigest: metadata2.sourceTreeDigest,
|
|
@@ -4651,6 +4710,11 @@ var CodePiRuntimeEngine = class {
|
|
|
4651
4710
|
if (!active || typeof prompt !== "string" || !prompt.trim() || prompt.length > 2e4) {
|
|
4652
4711
|
throw new TypeError("prompt requires an active Code session and bounded text");
|
|
4653
4712
|
}
|
|
4713
|
+
const requestedLimit = command.payload.maxTokensPerInteraction ?? active.maxTokensPerInteraction;
|
|
4714
|
+
if (!Number.isSafeInteger(requestedLimit) || Number(requestedLimit) < 4e3 || Number(requestedLimit) > 2e5) {
|
|
4715
|
+
throw new TypeError("prompt requires a valid interaction token limit");
|
|
4716
|
+
}
|
|
4717
|
+
active.maxTokensPerInteraction = Number(requestedLimit);
|
|
4654
4718
|
await active.done;
|
|
4655
4719
|
active.abort = new AbortController();
|
|
4656
4720
|
active.acknowledged = false;
|
|
@@ -4659,6 +4723,7 @@ var CodePiRuntimeEngine = class {
|
|
|
4659
4723
|
role: active.role,
|
|
4660
4724
|
title: active.title,
|
|
4661
4725
|
prompt,
|
|
4726
|
+
maxTokensPerInteraction: active.maxTokensPerInteraction,
|
|
4662
4727
|
planningInputDigest: active.planningInputDigest,
|
|
4663
4728
|
attestationDigest: "follow-up",
|
|
4664
4729
|
repository: active.repository,
|
|
@@ -4687,9 +4752,11 @@ var CodePiRuntimeEngine = class {
|
|
|
4687
4752
|
}, lease, metadata2.role);
|
|
4688
4753
|
const startedAt = Date.now();
|
|
4689
4754
|
let completionSeen = false;
|
|
4755
|
+
const interaction = { tokens: 0, noticeEmitted: false };
|
|
4690
4756
|
const result = await this.#run({
|
|
4691
4757
|
engine: this.options.engine,
|
|
4692
4758
|
image: this.options.image,
|
|
4759
|
+
allowUnpinnedImage: this.options.imageAuthorization === "cli_embedded",
|
|
4693
4760
|
workspaceDir: active.workspace.workspaceDir,
|
|
4694
4761
|
workspaceAccess: "none",
|
|
4695
4762
|
task: lease.task,
|
|
@@ -4702,25 +4769,18 @@ var CodePiRuntimeEngine = class {
|
|
|
4702
4769
|
}, active.conversationRefs),
|
|
4703
4770
|
onMessage: async (output) => {
|
|
4704
4771
|
if (output.type === "inference.request") {
|
|
4705
|
-
|
|
4706
|
-
|
|
4707
|
-
|
|
4708
|
-
|
|
4772
|
+
return handleCodeRuntimeInference({
|
|
4773
|
+
command,
|
|
4774
|
+
metadata: metadata2,
|
|
4775
|
+
request: output,
|
|
4776
|
+
state: interaction,
|
|
4777
|
+
control: this.options.control,
|
|
4778
|
+
event: (event) => this.#event(
|
|
4779
|
+
command,
|
|
4780
|
+
event,
|
|
4781
|
+
active.conversationRefs
|
|
4782
|
+
)
|
|
4709
4783
|
});
|
|
4710
|
-
await this.#event(command, {
|
|
4711
|
-
type: "usage",
|
|
4712
|
-
provider: response2.receipt.provider,
|
|
4713
|
-
model: response2.receipt.model,
|
|
4714
|
-
inputTokens: response2.receipt.inputTokens,
|
|
4715
|
-
outputTokens: response2.receipt.outputTokens,
|
|
4716
|
-
durationMs: Date.now() - inferenceStarted
|
|
4717
|
-
}, active.conversationRefs).catch(() => void 0);
|
|
4718
|
-
return {
|
|
4719
|
-
protocolVersion: HARNESS_PROTOCOL_VERSION,
|
|
4720
|
-
type: "inference.response",
|
|
4721
|
-
requestId: output.requestId,
|
|
4722
|
-
response: response2.response
|
|
4723
|
-
};
|
|
4724
4784
|
}
|
|
4725
4785
|
if (output.type === "tool.request") {
|
|
4726
4786
|
const toolStarted = Date.now();
|
|
@@ -5206,25 +5266,23 @@ function digestText(value) {
|
|
|
5206
5266
|
|
|
5207
5267
|
// src/code-images.ts
|
|
5208
5268
|
var import_node_child_process4 = require("child_process");
|
|
5209
|
-
|
|
5210
|
-
|
|
5211
|
-
|
|
5212
|
-
|
|
5213
|
-
|
|
5214
|
-
if (error) reject(new Error(`could not prepare pinned Code image ${image}`));
|
|
5215
|
-
else accept();
|
|
5216
|
-
});
|
|
5217
|
-
});
|
|
5218
|
-
}
|
|
5219
|
-
}
|
|
5269
|
+
var import_node_crypto2 = require("crypto");
|
|
5270
|
+
var import_promises10 = require("fs/promises");
|
|
5271
|
+
var import_node_os = require("os");
|
|
5272
|
+
var import_node_path4 = require("path");
|
|
5273
|
+
var import_node_url2 = require("url");
|
|
5220
5274
|
|
|
5221
5275
|
// src/code-runtime-config.ts
|
|
5222
|
-
var CODE_PI_IMAGE = "
|
|
5276
|
+
var CODE_PI_IMAGE = "odla-ai/pi-agent:embedded";
|
|
5277
|
+
var CODE_NODE_IMAGE = "node:24-alpine@sha256:a0b9bf06e4e6193cf7a0f58816cc935ff8c2a908f81e6f1a95432d679c54fbfd";
|
|
5223
5278
|
var CODE_BUILD_RECIPES = Object.freeze([{
|
|
5224
5279
|
id: "odla-code-contracts",
|
|
5225
|
-
image:
|
|
5280
|
+
image: CODE_NODE_IMAGE,
|
|
5226
5281
|
command: [
|
|
5227
5282
|
"node",
|
|
5283
|
+
// The clean source mount deliberately has no node_modules. Reuse the
|
|
5284
|
+
// semver copy inside this digest-pinned npm image without network access.
|
|
5285
|
+
"--import=data:text/javascript,import%20Module%20from%20%22node%3Amodule%22%3Bprocess.env.NODE_PATH%3D%22%2Fusr%2Flocal%2Flib%2Fnode_modules%2Fnpm%2Fnode_modules%22%3BModule._initPaths%28%29",
|
|
5228
5286
|
"--test",
|
|
5229
5287
|
"scripts/lib/directories.test.mjs",
|
|
5230
5288
|
"scripts/lib/internal-deps.test.mjs",
|
|
@@ -5239,10 +5297,84 @@ var CODE_BUILD_RECIPES = Object.freeze([{
|
|
|
5239
5297
|
pids: 128
|
|
5240
5298
|
}]);
|
|
5241
5299
|
|
|
5300
|
+
// src/code-images.ts
|
|
5301
|
+
var runCodeImageCommand = (command, args, stdio) => new Promise((accept, reject) => {
|
|
5302
|
+
const child = (0, import_node_child_process4.spawn)(command, [...args], { shell: false, stdio });
|
|
5303
|
+
child.once("error", reject);
|
|
5304
|
+
child.once("exit", (code, signal) => {
|
|
5305
|
+
if (code === 0) accept();
|
|
5306
|
+
else reject(new Error(`${command} ${args.join(" ")} exited ${code ?? signal ?? "without a status"}`));
|
|
5307
|
+
});
|
|
5308
|
+
});
|
|
5309
|
+
async function prepareCodeImages(engine, images, run = runCodeImageCommand, buildEmbedded = buildEmbeddedPiImage, nameEmbedded = embeddedPiImageName) {
|
|
5310
|
+
if (engine === "container") {
|
|
5311
|
+
try {
|
|
5312
|
+
await run(engine, ["system", "start"], "inherit");
|
|
5313
|
+
} catch {
|
|
5314
|
+
throw new Error("Apple container could not start; run `container system start` once to complete its lightweight VM setup, then retry");
|
|
5315
|
+
}
|
|
5316
|
+
}
|
|
5317
|
+
const prepared = [];
|
|
5318
|
+
for (const image of images) {
|
|
5319
|
+
const runtimeImage = image === CODE_PI_IMAGE ? await nameEmbedded() : image;
|
|
5320
|
+
const inspectArgs = ["image", "inspect", runtimeImage];
|
|
5321
|
+
try {
|
|
5322
|
+
await run(engine, inspectArgs, "ignore");
|
|
5323
|
+
prepared.push(runtimeImage);
|
|
5324
|
+
continue;
|
|
5325
|
+
} catch {
|
|
5326
|
+
}
|
|
5327
|
+
if (image === CODE_PI_IMAGE) {
|
|
5328
|
+
try {
|
|
5329
|
+
await buildEmbedded(engine, runtimeImage, run);
|
|
5330
|
+
} catch (error) {
|
|
5331
|
+
const detail = error instanceof Error && error.message ? `: ${error.message}` : "";
|
|
5332
|
+
throw new Error(`could not prepare CLI-embedded Code image${detail}`);
|
|
5333
|
+
}
|
|
5334
|
+
prepared.push(runtimeImage);
|
|
5335
|
+
continue;
|
|
5336
|
+
}
|
|
5337
|
+
const args = engine === "container" ? ["image", "pull", image] : ["pull", image];
|
|
5338
|
+
try {
|
|
5339
|
+
await run(engine, args, "inherit");
|
|
5340
|
+
} catch (error) {
|
|
5341
|
+
const detail = error instanceof Error && error.message ? `: ${error.message}` : "";
|
|
5342
|
+
throw new Error(`could not prepare pinned Code image ${image}${detail}`);
|
|
5343
|
+
}
|
|
5344
|
+
prepared.push(image);
|
|
5345
|
+
}
|
|
5346
|
+
return prepared;
|
|
5347
|
+
}
|
|
5348
|
+
function embeddedPiAssetPath() {
|
|
5349
|
+
return (0, import_node_url2.fileURLToPath)(new URL("./runtime/pi-agent.js", importMetaUrl));
|
|
5350
|
+
}
|
|
5351
|
+
async function embeddedPiImageName() {
|
|
5352
|
+
const bundle = await (0, import_promises10.readFile)(embeddedPiAssetPath()).catch(() => {
|
|
5353
|
+
throw new Error("CLI-embedded Pi runtime is missing; reinstall this exact @odla-ai/cli version");
|
|
5354
|
+
});
|
|
5355
|
+
return `odla-ai/pi-agent:embedded-sha256-${(0, import_node_crypto2.createHash)("sha256").update(bundle).digest("hex")}`;
|
|
5356
|
+
}
|
|
5357
|
+
async function buildEmbeddedPiImage(engine, image, run) {
|
|
5358
|
+
const context = await (0, import_promises10.mkdtemp)((0, import_node_path4.join)((0, import_node_os.tmpdir)(), "odla-code-pi-"));
|
|
5359
|
+
try {
|
|
5360
|
+
await (0, import_promises10.copyFile)(embeddedPiAssetPath(), (0, import_node_path4.join)(context, "pi-agent.js"));
|
|
5361
|
+
await (0, import_promises10.writeFile)((0, import_node_path4.join)(context, "Dockerfile"), [
|
|
5362
|
+
`FROM ${CODE_NODE_IMAGE}`,
|
|
5363
|
+
"COPY pi-agent.js /opt/odla/pi-agent.js",
|
|
5364
|
+
"WORKDIR /workspace",
|
|
5365
|
+
'ENTRYPOINT ["node", "/opt/odla/pi-agent.js"]',
|
|
5366
|
+
""
|
|
5367
|
+
].join("\n"), { mode: 384 });
|
|
5368
|
+
await run(engine, ["build", "--tag", image, context], "inherit");
|
|
5369
|
+
} finally {
|
|
5370
|
+
await (0, import_promises10.rm)(context, { recursive: true, force: true });
|
|
5371
|
+
}
|
|
5372
|
+
}
|
|
5373
|
+
|
|
5242
5374
|
// src/code-connect.ts
|
|
5243
5375
|
async function codeConnect(options) {
|
|
5244
5376
|
const cwd = options.cwd ?? process.cwd();
|
|
5245
|
-
const configPath = (0,
|
|
5377
|
+
const configPath = (0, import_node_path5.resolve)(cwd, options.configPath);
|
|
5246
5378
|
const cfg = (0, import_node_fs7.existsSync)(configPath) ? await loadProjectConfig(configPath) : null;
|
|
5247
5379
|
const requestedAppId = options.appId?.trim();
|
|
5248
5380
|
if (requestedAppId && !/^[a-z0-9][a-z0-9-]{1,62}$/.test(requestedAppId)) {
|
|
@@ -5271,12 +5403,13 @@ async function codeConnect(options) {
|
|
|
5271
5403
|
const out = options.stdout ?? console;
|
|
5272
5404
|
const doFetch = options.fetch ?? fetch;
|
|
5273
5405
|
const engine = await (options.selectEngine ?? selectContainerEngine)(options.engine ?? "auto");
|
|
5274
|
-
await (options.prepareImages ?? prepareCodeImages)(
|
|
5275
|
-
|
|
5276
|
-
...new Set(CODE_BUILD_RECIPES.map((recipe2) => recipe2.image))
|
|
5277
|
-
|
|
5406
|
+
const [piImage] = await (options.prepareImages ?? prepareCodeImages)(
|
|
5407
|
+
engine,
|
|
5408
|
+
[CODE_PI_IMAGE, ...new Set(CODE_BUILD_RECIPES.map((recipe2) => recipe2.image))]
|
|
5409
|
+
);
|
|
5410
|
+
if (!piImage || !/^odla-ai\/pi-agent:embedded-sha256-[0-9a-f]{64}$/.test(piImage)) throw new Error("Code image preflight did not produce the content-addressed embedded Pi runtime");
|
|
5278
5411
|
const hostPlatform = process.platform === "darwin" ? "macos" : "linux";
|
|
5279
|
-
const hostName = (options.name ?? (0,
|
|
5412
|
+
const hostName = (options.name ?? (0, import_node_os2.hostname)()).trim();
|
|
5280
5413
|
if (!hostName || hostName.length > 120) throw new Error("--name must contain 1 to 120 characters");
|
|
5281
5414
|
const repository = await inferGitHubRepository(cwd, options.readGitOrigin);
|
|
5282
5415
|
const localSource = await (options.prepareLocalSource ?? prepareCodeLocalSource)(
|
|
@@ -5313,12 +5446,13 @@ async function codeConnect(options) {
|
|
|
5313
5446
|
platform: hostPlatform,
|
|
5314
5447
|
arch: process.arch,
|
|
5315
5448
|
engines: [engine],
|
|
5316
|
-
cpuCount: (0,
|
|
5317
|
-
memoryBytes: (0,
|
|
5449
|
+
cpuCount: (0, import_node_os2.cpus)().length,
|
|
5450
|
+
memoryBytes: (0, import_node_os2.totalmem)(),
|
|
5318
5451
|
source: descriptor2,
|
|
5319
5452
|
images: {
|
|
5320
5453
|
ready: true,
|
|
5321
|
-
pi:
|
|
5454
|
+
pi: piImage,
|
|
5455
|
+
piSource: "cli_embedded",
|
|
5322
5456
|
recipes: CODE_BUILD_RECIPES.map((recipe2) => ({ id: recipe2.id, image: recipe2.image }))
|
|
5323
5457
|
}
|
|
5324
5458
|
};
|
|
@@ -5333,6 +5467,7 @@ async function codeConnect(options) {
|
|
|
5333
5467
|
engine,
|
|
5334
5468
|
capabilities,
|
|
5335
5469
|
localSource,
|
|
5470
|
+
piImage,
|
|
5336
5471
|
heartbeatMs,
|
|
5337
5472
|
once: options.once === true,
|
|
5338
5473
|
signal: options.signal,
|
|
@@ -5362,7 +5497,8 @@ async function runCodeRuntime(input) {
|
|
|
5362
5497
|
const commandEngine = new CodePiRuntimeEngine({
|
|
5363
5498
|
control,
|
|
5364
5499
|
engine: input.engine,
|
|
5365
|
-
image:
|
|
5500
|
+
image: input.piImage ?? input.capabilities.images.pi,
|
|
5501
|
+
imageAuthorization: "cli_embedded",
|
|
5366
5502
|
recipes: CODE_BUILD_RECIPES,
|
|
5367
5503
|
recipeAuthorization: "registered_recipe",
|
|
5368
5504
|
localSource: input.localSource,
|
|
@@ -5459,12 +5595,12 @@ async function codeCommand(parsed, dependencies) {
|
|
|
5459
5595
|
// src/doctor-checks.ts
|
|
5460
5596
|
var import_node_child_process6 = require("child_process");
|
|
5461
5597
|
var import_node_fs9 = require("fs");
|
|
5462
|
-
var
|
|
5598
|
+
var import_node_path7 = require("path");
|
|
5463
5599
|
|
|
5464
5600
|
// src/wrangler.ts
|
|
5465
5601
|
var import_node_child_process5 = require("child_process");
|
|
5466
5602
|
var import_node_fs8 = require("fs");
|
|
5467
|
-
var
|
|
5603
|
+
var import_node_path6 = require("path");
|
|
5468
5604
|
var defaultRunner = (cmd, args, opts) => new Promise((resolvePromise, reject) => {
|
|
5469
5605
|
const child = (0, import_node_child_process5.spawn)(cmd, args, { cwd: opts?.cwd, stdio: ["pipe", "pipe", "pipe"] });
|
|
5470
5606
|
let stdout = "";
|
|
@@ -5478,7 +5614,7 @@ var defaultRunner = (cmd, args, opts) => new Promise((resolvePromise, reject) =>
|
|
|
5478
5614
|
var WRANGLER_CONFIG_FILES = ["wrangler.jsonc", "wrangler.json", "wrangler.toml"];
|
|
5479
5615
|
function findWranglerConfig(rootDir) {
|
|
5480
5616
|
for (const name of WRANGLER_CONFIG_FILES) {
|
|
5481
|
-
const path = (0,
|
|
5617
|
+
const path = (0, import_node_path6.join)(rootDir, name);
|
|
5482
5618
|
if ((0, import_node_fs8.existsSync)(path)) return path;
|
|
5483
5619
|
}
|
|
5484
5620
|
return null;
|
|
@@ -5584,10 +5720,10 @@ function wranglerWarnings(rootDir) {
|
|
|
5584
5720
|
for (const { label, block } of blocks) {
|
|
5585
5721
|
const assets = block.assets;
|
|
5586
5722
|
if (assets?.directory) {
|
|
5587
|
-
const dir = (0,
|
|
5588
|
-
if (dir === (0,
|
|
5723
|
+
const dir = (0, import_node_path7.resolve)(rootDir, assets.directory);
|
|
5724
|
+
if (dir === (0, import_node_path7.resolve)(rootDir)) {
|
|
5589
5725
|
warnings.push(`${label}assets.directory is the project root \u2014 point it at a dedicated build dir (wrangler dev fails with "spawn EBADF")`);
|
|
5590
|
-
} else if ((0, import_node_fs9.existsSync)((0,
|
|
5726
|
+
} else if ((0, import_node_fs9.existsSync)((0, import_node_path7.join)(dir, "node_modules"))) {
|
|
5591
5727
|
warnings.push(`${label}assets.directory contains node_modules \u2014 wrangler dev's watcher will exhaust file descriptors`);
|
|
5592
5728
|
}
|
|
5593
5729
|
}
|
|
@@ -5622,7 +5758,7 @@ function o11yProjectWarnings(rootDir) {
|
|
|
5622
5758
|
warnings.push("cannot verify o11y Worker instrumentation \u2014 add a parseable wrangler.jsonc/json config");
|
|
5623
5759
|
return warnings;
|
|
5624
5760
|
}
|
|
5625
|
-
const main = typeof config.main === "string" ? (0,
|
|
5761
|
+
const main = typeof config.main === "string" ? (0, import_node_path7.resolve)(rootDir, config.main) : null;
|
|
5626
5762
|
if (!main || !(0, import_node_fs9.existsSync)(main)) {
|
|
5627
5763
|
warnings.push("cannot verify o11y Worker instrumentation \u2014 wrangler main is missing or unreadable");
|
|
5628
5764
|
} else {
|
|
@@ -5652,7 +5788,7 @@ function calendarProjectWarnings(rootDir) {
|
|
|
5652
5788
|
}
|
|
5653
5789
|
function readPackageJson(rootDir) {
|
|
5654
5790
|
try {
|
|
5655
|
-
return JSON.parse((0, import_node_fs9.readFileSync)((0,
|
|
5791
|
+
return JSON.parse((0, import_node_fs9.readFileSync)((0, import_node_path7.join)(rootDir, "package.json"), "utf8"));
|
|
5656
5792
|
} catch {
|
|
5657
5793
|
return null;
|
|
5658
5794
|
}
|
|
@@ -5854,11 +5990,11 @@ function harnessOption(value, flag) {
|
|
|
5854
5990
|
|
|
5855
5991
|
// src/init.ts
|
|
5856
5992
|
var import_node_fs10 = require("fs");
|
|
5857
|
-
var
|
|
5993
|
+
var import_node_path8 = require("path");
|
|
5858
5994
|
function initProject(options) {
|
|
5859
5995
|
const out = options.stdout ?? console;
|
|
5860
|
-
const rootDir = (0,
|
|
5861
|
-
const configPath = (0,
|
|
5996
|
+
const rootDir = (0, import_node_path8.resolve)(options.rootDir ?? process.cwd());
|
|
5997
|
+
const configPath = (0, import_node_path8.resolve)(rootDir, options.configPath ?? "odla.config.mjs");
|
|
5862
5998
|
if ((0, import_node_fs10.existsSync)(configPath) && !options.force) {
|
|
5863
5999
|
throw new Error(`${configPath} already exists. Pass --force to overwrite.`);
|
|
5864
6000
|
}
|
|
@@ -5869,12 +6005,12 @@ function initProject(options) {
|
|
|
5869
6005
|
const services = options.services?.length ? options.services : ["db", "ai"];
|
|
5870
6006
|
if (services.includes("calendar") && !services.includes("db")) throw new Error("--services calendar requires db");
|
|
5871
6007
|
const aiProvider = options.aiProvider ?? "anthropic";
|
|
5872
|
-
(0, import_node_fs10.mkdirSync)((0,
|
|
5873
|
-
(0, import_node_fs10.mkdirSync)((0,
|
|
5874
|
-
(0, import_node_fs10.mkdirSync)((0,
|
|
6008
|
+
(0, import_node_fs10.mkdirSync)((0, import_node_path8.dirname)(configPath), { recursive: true });
|
|
6009
|
+
(0, import_node_fs10.mkdirSync)((0, import_node_path8.resolve)(rootDir, "src/odla"), { recursive: true });
|
|
6010
|
+
(0, import_node_fs10.mkdirSync)((0, import_node_path8.resolve)(rootDir, ".odla"), { recursive: true });
|
|
5875
6011
|
(0, import_node_fs10.writeFileSync)(configPath, configTemplate({ appId: options.appId, name: options.name, envs, services, aiProvider }));
|
|
5876
|
-
writeIfMissing((0,
|
|
5877
|
-
writeIfMissing((0,
|
|
6012
|
+
writeIfMissing((0, import_node_path8.resolve)(rootDir, "src/odla/schema.mjs"), schemaTemplate());
|
|
6013
|
+
writeIfMissing((0, import_node_path8.resolve)(rootDir, "src/odla/rules.mjs"), rulesTemplate());
|
|
5878
6014
|
ensureGitignore(rootDir);
|
|
5879
6015
|
out.log(`created ${relativeDisplay(configPath, rootDir)}`);
|
|
5880
6016
|
out.log("created src/odla/schema.mjs and src/odla/rules.mjs");
|
|
@@ -6524,7 +6660,7 @@ async function resolveVaultWrite(options) {
|
|
|
6524
6660
|
}
|
|
6525
6661
|
|
|
6526
6662
|
// src/security-command-context.ts
|
|
6527
|
-
var
|
|
6663
|
+
var import_promises11 = require("readline/promises");
|
|
6528
6664
|
async function hostedSecurityContext(parsed, dependencies) {
|
|
6529
6665
|
const configPath = stringOpt(parsed.options.config) ?? "odla.config.mjs";
|
|
6530
6666
|
const cfg = await loadProjectConfig(configPath);
|
|
@@ -6550,7 +6686,7 @@ async function hostedSecurityContext(parsed, dependencies) {
|
|
|
6550
6686
|
async function interactiveConfirmation(message2, dependencies) {
|
|
6551
6687
|
if (dependencies.confirm) return dependencies.confirm(message2);
|
|
6552
6688
|
if (!process.stdin.isTTY || !process.stdout.isTTY) return false;
|
|
6553
|
-
const prompt = (0,
|
|
6689
|
+
const prompt = (0, import_promises11.createInterface)({ input: process.stdin, output: process.stdout });
|
|
6554
6690
|
try {
|
|
6555
6691
|
const answer = await prompt.question(`${message2} [y/N] `);
|
|
6556
6692
|
return /^y(?:es)?$/i.test(answer.trim());
|
|
@@ -6677,7 +6813,7 @@ function hostedSeverity(value, flag) {
|
|
|
6677
6813
|
var import_security2 = require("@odla-ai/security");
|
|
6678
6814
|
|
|
6679
6815
|
// src/security.ts
|
|
6680
|
-
var
|
|
6816
|
+
var import_node_path9 = require("path");
|
|
6681
6817
|
var import_security = require("@odla-ai/security");
|
|
6682
6818
|
var import_node3 = require("@odla-ai/security/node");
|
|
6683
6819
|
async function runHostedSecurity(options) {
|
|
@@ -6689,9 +6825,9 @@ async function runHostedSecurity(options) {
|
|
|
6689
6825
|
const appId = selfAudit ? "odla-ai" : cfg.app.id;
|
|
6690
6826
|
const env = selfAudit ? "prod" : selectEnv(options.env, cfg.envs, cfg.configPath, cfg.rootDir);
|
|
6691
6827
|
const platform = options.platform ?? cfg?.platformUrl ?? "https://odla.ai";
|
|
6692
|
-
const target = (0,
|
|
6693
|
-
const output = (0,
|
|
6694
|
-
const outputRelative = (0,
|
|
6828
|
+
const target = (0, import_node_path9.resolve)(options.target ?? cfg?.rootDir ?? ".");
|
|
6829
|
+
const output = (0, import_node_path9.resolve)(options.out ?? (0, import_node_path9.resolve)(target, ".odla/security/hosted"));
|
|
6830
|
+
const outputRelative = (0, import_node_path9.relative)(target, output).split(import_node_path9.sep).join("/");
|
|
6695
6831
|
if (!outputRelative) throw new Error("Hosted security output cannot be the repository root");
|
|
6696
6832
|
const profile = profileFor(options.profile ?? "odla", options.maxHuntTasks ?? 12);
|
|
6697
6833
|
const tokenRequest = {
|
|
@@ -6703,7 +6839,7 @@ async function runHostedSecurity(options) {
|
|
|
6703
6839
|
};
|
|
6704
6840
|
const token = await injectedToken(options, tokenRequest);
|
|
6705
6841
|
const snapshot = await (0, import_node3.snapshotDirectory)(target, {
|
|
6706
|
-
exclude: !outputRelative.startsWith("../") && !(0,
|
|
6842
|
+
exclude: !outputRelative.startsWith("../") && !(0, import_node_path9.isAbsolute)(outputRelative) ? [outputRelative] : []
|
|
6707
6843
|
});
|
|
6708
6844
|
const hosted = await (0, import_security.createPlatformSecurityReasoners)({
|
|
6709
6845
|
platform,
|
|
@@ -6721,7 +6857,7 @@ async function runHostedSecurity(options) {
|
|
|
6721
6857
|
});
|
|
6722
6858
|
const harness = (0, import_security.createSecurityHarness)({
|
|
6723
6859
|
profile,
|
|
6724
|
-
store: new import_node3.FileRunStore((0,
|
|
6860
|
+
store: new import_node3.FileRunStore((0, import_node_path9.resolve)(output, "state")),
|
|
6725
6861
|
discoveryReasoner: hosted.discoveryReasoner,
|
|
6726
6862
|
validationReasoner: hosted.validationReasoner,
|
|
6727
6863
|
policy: {
|
|
@@ -6745,7 +6881,7 @@ async function runHostedSecurity(options) {
|
|
|
6745
6881
|
function selectEnv(requested, declared, configPath, rootDir) {
|
|
6746
6882
|
const env = requested ?? (declared.includes("dev") ? "dev" : declared[0]);
|
|
6747
6883
|
if (!env || !declared.includes(env)) {
|
|
6748
|
-
const shown = (0,
|
|
6884
|
+
const shown = (0, import_node_path9.relative)(rootDir, configPath) || configPath;
|
|
6749
6885
|
throw new Error(`env "${env ?? ""}" is not declared in ${shown}`);
|
|
6750
6886
|
}
|
|
6751
6887
|
return env;
|
|
@@ -6774,7 +6910,7 @@ function printSummary(out, appId, env, run, report2, output) {
|
|
|
6774
6910
|
out.log(` coverage: ${report2.coverageStatus} ${complete}/${report2.coverage.length} blocked=${report2.metrics.blockedCells} shallow=${report2.metrics.shallowCells} unscheduled=${report2.metrics.unscheduledCells} budget_exhausted=${report2.metrics.budgetExhaustedCells}`);
|
|
6775
6911
|
if (report2.callBudget) out.log(` calls: discovery=${formatBudget(report2.callBudget.discovery)} validation=${formatBudget(report2.callBudget.validation)}`);
|
|
6776
6912
|
out.log(` findings: confirmed=${report2.metrics.confirmed} needs_reproduction=${report2.metrics.needsReproduction} candidates=${report2.metrics.candidates}`);
|
|
6777
|
-
out.log(` report: ${(0,
|
|
6913
|
+
out.log(` report: ${(0, import_node_path9.resolve)(output, "REPORT.md")}`);
|
|
6778
6914
|
}
|
|
6779
6915
|
function formatBudget(usage) {
|
|
6780
6916
|
return usage ? `${usage.usedCalls}/${usage.maxCalls} skipped=${usage.skippedCalls}` : "caller-managed";
|
|
@@ -7224,9 +7360,9 @@ async function securityStatus(parsed, dependencies) {
|
|
|
7224
7360
|
|
|
7225
7361
|
// src/skill.ts
|
|
7226
7362
|
var import_node_fs11 = require("fs");
|
|
7227
|
-
var
|
|
7228
|
-
var
|
|
7229
|
-
var
|
|
7363
|
+
var import_node_os3 = require("os");
|
|
7364
|
+
var import_node_path10 = require("path");
|
|
7365
|
+
var import_node_url3 = require("url");
|
|
7230
7366
|
|
|
7231
7367
|
// src/skill-adapters.ts
|
|
7232
7368
|
var PROJECT_INSTRUCTIONS = `<!-- odla-ai agent setup:start -->
|
|
@@ -7282,12 +7418,12 @@ runbook. Do not substitute a remote documentation page for the installed copy.
|
|
|
7282
7418
|
var AGENT_HARNESSES = ["claude", "codex", "cursor", "copilot", "gemini", "agents"];
|
|
7283
7419
|
function installSkill(options = {}) {
|
|
7284
7420
|
const out = options.stdout ?? console;
|
|
7285
|
-
const sourceDir = options.sourceDir ?? (0,
|
|
7421
|
+
const sourceDir = options.sourceDir ?? (0, import_node_url3.fileURLToPath)(new URL("../skills", importMetaUrl));
|
|
7286
7422
|
const files = listFiles(sourceDir);
|
|
7287
7423
|
if (files.length === 0) throw new Error(`no bundled skills found at ${sourceDir}`);
|
|
7288
7424
|
const harnesses = normalizeHarnesses(options.harnesses, options.global === true);
|
|
7289
|
-
const root = (0,
|
|
7290
|
-
const home = (0,
|
|
7425
|
+
const root = (0, import_node_path10.resolve)(options.dir ?? process.cwd());
|
|
7426
|
+
const home = (0, import_node_path10.resolve)(options.homeDir ?? (0, import_node_os3.homedir)());
|
|
7291
7427
|
const plans = /* @__PURE__ */ new Map();
|
|
7292
7428
|
const targets = /* @__PURE__ */ new Map();
|
|
7293
7429
|
const rememberTarget = (harness, target) => {
|
|
@@ -7301,48 +7437,48 @@ function installSkill(options = {}) {
|
|
|
7301
7437
|
plans.set(target, { target, content, boundary, managedMerge });
|
|
7302
7438
|
};
|
|
7303
7439
|
const planSkillTree = (targetDir2, boundary = root) => {
|
|
7304
|
-
for (const rel of files) plan((0,
|
|
7440
|
+
for (const rel of files) plan((0, import_node_path10.join)(targetDir2, rel), (0, import_node_fs11.readFileSync)((0, import_node_path10.join)(sourceDir, rel), "utf8"), false, boundary);
|
|
7305
7441
|
};
|
|
7306
7442
|
let targetDir;
|
|
7307
7443
|
if (options.global) {
|
|
7308
|
-
const claudeRoot = (0,
|
|
7309
|
-
const codexRoot = (0,
|
|
7444
|
+
const claudeRoot = (0, import_node_path10.join)(home, ".claude", "skills");
|
|
7445
|
+
const codexRoot = (0, import_node_path10.resolve)(options.codexHomeDir ?? process.env.CODEX_HOME ?? (0, import_node_path10.join)(home, ".codex"), "skills");
|
|
7310
7446
|
targetDir = harnesses[0] === "codex" ? codexRoot : claudeRoot;
|
|
7311
7447
|
for (const harness of harnesses) {
|
|
7312
7448
|
const skillRoot = harness === "claude" ? claudeRoot : codexRoot;
|
|
7313
|
-
planSkillTree(skillRoot, harness === "claude" ? home : (0,
|
|
7449
|
+
planSkillTree(skillRoot, harness === "claude" ? home : (0, import_node_path10.dirname)((0, import_node_path10.dirname)(codexRoot)));
|
|
7314
7450
|
rememberTarget(harness, skillRoot);
|
|
7315
7451
|
}
|
|
7316
7452
|
} else {
|
|
7317
|
-
const sharedRoot = (0,
|
|
7453
|
+
const sharedRoot = (0, import_node_path10.join)(root, ".agents", "skills");
|
|
7318
7454
|
planSkillTree(sharedRoot);
|
|
7319
|
-
const claudeRoot = (0,
|
|
7455
|
+
const claudeRoot = (0, import_node_path10.join)(root, ".claude", "skills");
|
|
7320
7456
|
targetDir = harnesses.includes("claude") ? claudeRoot : sharedRoot;
|
|
7321
7457
|
for (const harness of harnesses) rememberTarget(harness, sharedRoot);
|
|
7322
7458
|
if (harnesses.includes("claude")) {
|
|
7323
7459
|
for (const skill of skillNames(files)) {
|
|
7324
|
-
const canonical = (0, import_node_fs11.readFileSync)((0,
|
|
7325
|
-
plan((0,
|
|
7460
|
+
const canonical = (0, import_node_fs11.readFileSync)((0, import_node_path10.join)(sourceDir, skill, "SKILL.md"), "utf8");
|
|
7461
|
+
plan((0, import_node_path10.join)(claudeRoot, skill, "SKILL.md"), claudeAdapter(skill, canonical));
|
|
7326
7462
|
}
|
|
7327
7463
|
rememberTarget("claude", claudeRoot);
|
|
7328
7464
|
}
|
|
7329
7465
|
if (harnesses.includes("cursor")) {
|
|
7330
|
-
const cursorRule = (0,
|
|
7466
|
+
const cursorRule = (0, import_node_path10.join)(root, ".cursor", "rules", "odla.mdc");
|
|
7331
7467
|
plan(cursorRule, CURSOR_RULE);
|
|
7332
7468
|
rememberTarget("cursor", cursorRule);
|
|
7333
7469
|
}
|
|
7334
7470
|
if (harnesses.includes("agents")) {
|
|
7335
|
-
const agentsFile = (0,
|
|
7471
|
+
const agentsFile = (0, import_node_path10.join)(root, "AGENTS.md");
|
|
7336
7472
|
plan(agentsFile, managedFileContent(agentsFile, PROJECT_INSTRUCTIONS, options.force === true, root), true);
|
|
7337
7473
|
rememberTarget("agents", agentsFile);
|
|
7338
7474
|
}
|
|
7339
7475
|
if (harnesses.includes("copilot")) {
|
|
7340
|
-
const copilotFile = (0,
|
|
7476
|
+
const copilotFile = (0, import_node_path10.join)(root, ".github", "copilot-instructions.md");
|
|
7341
7477
|
plan(copilotFile, managedFileContent(copilotFile, PROJECT_INSTRUCTIONS, options.force === true, root), true);
|
|
7342
7478
|
rememberTarget("copilot", copilotFile);
|
|
7343
7479
|
}
|
|
7344
7480
|
if (harnesses.includes("gemini")) {
|
|
7345
|
-
const geminiFile = (0,
|
|
7481
|
+
const geminiFile = (0, import_node_path10.join)(root, "GEMINI.md");
|
|
7346
7482
|
plan(geminiFile, managedFileContent(geminiFile, PROJECT_INSTRUCTIONS, options.force === true, root), true);
|
|
7347
7483
|
rememberTarget("gemini", geminiFile);
|
|
7348
7484
|
}
|
|
@@ -7378,7 +7514,7 @@ ${conflicts.map((f) => ` - ${f}`).join("\n")}`
|
|
|
7378
7514
|
}
|
|
7379
7515
|
for (const file of plans.values()) {
|
|
7380
7516
|
if (!(0, import_node_fs11.existsSync)(file.target) || (0, import_node_fs11.readFileSync)(file.target, "utf8") !== file.content) {
|
|
7381
|
-
(0, import_node_fs11.mkdirSync)((0,
|
|
7517
|
+
(0, import_node_fs11.mkdirSync)((0, import_node_path10.dirname)(file.target), { recursive: true });
|
|
7382
7518
|
(0, import_node_fs11.writeFileSync)(file.target, file.content);
|
|
7383
7519
|
}
|
|
7384
7520
|
}
|
|
@@ -7398,7 +7534,7 @@ ${conflicts.map((f) => ` - ${f}`).join("\n")}`
|
|
|
7398
7534
|
};
|
|
7399
7535
|
}
|
|
7400
7536
|
function pathsUnder(root, paths) {
|
|
7401
|
-
return [...paths].map((path) => (0,
|
|
7537
|
+
return [...paths].map((path) => (0, import_node_path10.relative)(root, path)).filter((path) => path !== ".." && !path.startsWith(`..${import_node_path10.sep}`) && !(0, import_node_path10.isAbsolute)(path)).sort();
|
|
7402
7538
|
}
|
|
7403
7539
|
function normalizeHarnesses(values, global) {
|
|
7404
7540
|
const requested = values?.length ? values : ["claude"];
|
|
@@ -7443,13 +7579,13 @@ function managedFileContent(path, block, force, boundary) {
|
|
|
7443
7579
|
return `${current.slice(0, startAt)}${block}${current.slice(afterEnd)}`;
|
|
7444
7580
|
}
|
|
7445
7581
|
function symlinkedComponent(boundary, target) {
|
|
7446
|
-
const rel = (0,
|
|
7447
|
-
if (rel === ".." || rel.startsWith(`..${
|
|
7582
|
+
const rel = (0, import_node_path10.relative)(boundary, target);
|
|
7583
|
+
if (rel === ".." || rel.startsWith(`..${import_node_path10.sep}`) || (0, import_node_path10.isAbsolute)(rel)) {
|
|
7448
7584
|
throw new Error(`agent setup target escapes its install root: ${target}`);
|
|
7449
7585
|
}
|
|
7450
7586
|
let current = boundary;
|
|
7451
|
-
for (const part of rel.split(
|
|
7452
|
-
current = (0,
|
|
7587
|
+
for (const part of rel.split(import_node_path10.sep).filter(Boolean)) {
|
|
7588
|
+
current = (0, import_node_path10.join)(current, part);
|
|
7453
7589
|
try {
|
|
7454
7590
|
if ((0, import_node_fs11.lstatSync)(current).isSymbolicLink()) return current;
|
|
7455
7591
|
} catch (error) {
|
|
@@ -7466,9 +7602,9 @@ function listFiles(dir) {
|
|
|
7466
7602
|
const results = [];
|
|
7467
7603
|
const walk = (current) => {
|
|
7468
7604
|
for (const entry of (0, import_node_fs11.readdirSync)(current, { withFileTypes: true })) {
|
|
7469
|
-
const path = (0,
|
|
7605
|
+
const path = (0, import_node_path10.join)(current, entry.name);
|
|
7470
7606
|
if (entry.isDirectory()) walk(path);
|
|
7471
|
-
else results.push((0,
|
|
7607
|
+
else results.push((0, import_node_path10.relative)(dir, path));
|
|
7472
7608
|
}
|
|
7473
7609
|
};
|
|
7474
7610
|
walk(dir);
|
|
@@ -7840,6 +7976,7 @@ async function calendarCommand(parsed, dependencies) {
|
|
|
7840
7976
|
isTerminalHostedSecurityStatus,
|
|
7841
7977
|
listGitHubSecuritySources,
|
|
7842
7978
|
listHostedSecurityJobs,
|
|
7979
|
+
prepareCodeImages,
|
|
7843
7980
|
printCapabilities,
|
|
7844
7981
|
provision,
|
|
7845
7982
|
redactSecrets,
|