@lambdacurry/arbor 0.23.36 → 0.23.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/dist/arbor.js +197 -6
- package/package.json +1 -1
package/dist/arbor.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
// package.json
|
|
3
3
|
var package_default = {
|
|
4
4
|
name: "@lambdacurry/arbor",
|
|
5
|
-
version: "0.23.
|
|
5
|
+
version: "0.23.38",
|
|
6
6
|
description: "The Arbor CLI — a shared workspace for people and agents. The human + headless-agent write path over Arbor's guarded operation surface.",
|
|
7
7
|
keywords: [
|
|
8
8
|
"agents",
|
|
@@ -7384,6 +7384,9 @@ var artifactVersions = sqliteTable("artifact_versions", {
|
|
|
7384
7384
|
source: text("source").notNull(),
|
|
7385
7385
|
sourceAttachmentId: text("source_attachment_id").references(() => attachments.id),
|
|
7386
7386
|
sourceSha256: text("source_sha256"),
|
|
7387
|
+
gitCommitSha: text("git_commit_sha"),
|
|
7388
|
+
gitSourceSha256: text("git_source_sha256"),
|
|
7389
|
+
gitRepositoryName: text("git_repository_name"),
|
|
7387
7390
|
tldrawDocumentClock: integer2("tldraw_document_clock"),
|
|
7388
7391
|
editorProfileId: text("editor_profile_id").notNull().references(() => profiles.id),
|
|
7389
7392
|
executionContextId: text("execution_context_id").references(() => executionContexts.id),
|
|
@@ -7392,6 +7395,29 @@ var artifactVersions = sqliteTable("artifact_versions", {
|
|
|
7392
7395
|
}, (t) => ({
|
|
7393
7396
|
artifactVersionUq: uniqueIndex("artifact_versions_artifact_version_uq").on(t.artifactId, t.version)
|
|
7394
7397
|
}));
|
|
7398
|
+
var artifactGitWriteIntents = sqliteTable("artifact_git_write_intents", {
|
|
7399
|
+
artifactId: text("artifact_id").notNull(),
|
|
7400
|
+
requestKey: text("request_key").notNull(),
|
|
7401
|
+
fingerprint: text("fingerprint").notNull(),
|
|
7402
|
+
baseVersion: integer2("base_version").notNull(),
|
|
7403
|
+
expectedParentSha: text("expected_parent_sha"),
|
|
7404
|
+
targetVersion: integer2("target_version").notNull(),
|
|
7405
|
+
targetVersionId: text("target_version_id").notNull(),
|
|
7406
|
+
targetSourceSha256: text("target_source_sha256").notNull(),
|
|
7407
|
+
state: text("state").$type().notNull().default("pending"),
|
|
7408
|
+
gitCommitSha: text("git_commit_sha"),
|
|
7409
|
+
gitRepositoryName: text("git_repository_name"),
|
|
7410
|
+
createdAt: ts("created_at").notNull(),
|
|
7411
|
+
finalizedAt: ts("finalized_at"),
|
|
7412
|
+
requestJson: text("request_json")
|
|
7413
|
+
}, (t) => ({
|
|
7414
|
+
pk: primaryKey({ columns: [t.artifactId, t.requestKey] }),
|
|
7415
|
+
pendingUq: uniqueIndex("artifact_git_write_intents_one_pending_uq").on(t.artifactId).where(sql`${t.state} = 'pending'`),
|
|
7416
|
+
targetVersionIdx: index("artifact_git_write_intents_artifact_target_idx").on(t.artifactId, t.targetVersion),
|
|
7417
|
+
stateCheck: check("artifact_git_write_intents_state_check", sql`(${t.state} = 'pending' AND ${t.finalizedAt} IS NULL)
|
|
7418
|
+
OR (${t.state} = 'finalized' AND ${t.gitCommitSha} IS NOT NULL AND ${t.finalizedAt} IS NOT NULL)`),
|
|
7419
|
+
versionCheck: check("artifact_git_write_intents_version_check", sql`${t.baseVersion} >= 0 AND ${t.targetVersion} > 0`)
|
|
7420
|
+
}));
|
|
7395
7421
|
var artifactTldrawBoards = sqliteTable("artifact_tldraw_boards", {
|
|
7396
7422
|
artifactId: text("artifact_id").primaryKey().references(() => artifacts.id, { onDelete: "cascade" }),
|
|
7397
7423
|
roomGeneration: integer2("room_generation").notNull().default(1),
|
|
@@ -8245,6 +8271,12 @@ var SPACE_ARTIFACT_STATUSES = [
|
|
|
8245
8271
|
"archived"
|
|
8246
8272
|
];
|
|
8247
8273
|
var artifactUpdatedAt = sql`coalesce((select max(${events.createdAt}) from ${events} where ${events.objectType} = 'artifact' and ${events.objectId} = ${artifacts.id}), ${artifacts.createdAt})`;
|
|
8274
|
+
// ../core/src/ops/artifact-git-intent.ts
|
|
8275
|
+
var RETRYABLE_REPAIR = new Set([
|
|
8276
|
+
"pending_push_unconfirmed",
|
|
8277
|
+
"remote_unavailable",
|
|
8278
|
+
"finalize_failed"
|
|
8279
|
+
]);
|
|
8248
8280
|
// ../core/src/ops/request.ts
|
|
8249
8281
|
var REQUEST_TTL_MS = 14 * 24 * 60 * 60 * 1000;
|
|
8250
8282
|
|
|
@@ -11133,11 +11165,11 @@ var COMPUTER_ORIENTATION_SECTIONS = [
|
|
|
11133
11165
|
},
|
|
11134
11166
|
{
|
|
11135
11167
|
brief: "3. Computers are temporary: one Run per task; save work outside the Computer, then finish; suspend for a wait.",
|
|
11136
|
-
full: `3. ONE RUN PER TASK. A write Run defaults to an isolated execution environment with its own filesystem, processes, ports, and /tmp while preserving /workspace paths; a read Run shares the parent. Pass runId to Run-aware tools. If a response is lost, recover the durable operation/process identity from computer_run_receipt and read it before retrying. computer_process_read settles a provider-absent current-generation process from exact evidence; computer_process_terminate sends one termination request and preserves the actual native terminal outcome from one bounded read. computer_run_suspend performs bounded settlement internally and never replays unknown work. A still-active process returns a retryable busy state; an unknown current-generation mutation fail-closes.
|
|
11168
|
+
full: `3. ONE RUN PER TASK. A write Run defaults to an isolated execution environment with its own filesystem, processes, ports, and /tmp while preserving /workspace paths; a read Run shares the parent. Pass runId to Run-aware tools. Ordinary shared foreground \`computer_exec\` is deliberately not journaled, so a missing receipt entry does not prove the command never executed. Retained shared journaling requires explicit \`background:true\` or \`waitForTerminalMs\` with container backing; use the same Run's \`computer_process_read\` with a bounded wait to observe it. If a response is lost, recover the durable operation/process identity from computer_run_receipt and read it before retrying. computer_process_read settles a provider-absent current-generation process from exact evidence; computer_process_terminate sends one termination request and preserves the actual native terminal outcome from one bounded read. computer_run_suspend performs bounded settlement internally and never replays unknown work. A still-active process returns a retryable busy state; an unknown current-generation mutation fail-closes. Save or publish needed work outside the temporary Computer before suspending or finishing; an isolated local commit or Preview is not Git publication, so push coherent work before computer_run_finish. discard=true with outcome failed or cancelled explicitly abandons Git work only after provider work is quiescent; it never overrides active or unknown execution.`
|
|
11137
11169
|
},
|
|
11138
11170
|
{
|
|
11139
11171
|
brief: "4. Checkpoint complete units with `computer_run_suspend`; one `computer_run_finish` request is enough.",
|
|
11140
|
-
full: `4. CHECKPOINT COMPLETE UNITS THROUGH THE RUN. computer_run_suspend(runId) checkpoints an intermediate complete unit — an isolated Run publishes its exact workspace and releases its Sandbox, a shared Run
|
|
11172
|
+
full: `4. CHECKPOINT COMPLETE UNITS THROUGH THE RUN. computer_run_suspend(runId) checkpoints an intermediate complete unit — an isolated Run publishes its exact workspace and releases its Sandbox, while a shared Run checkpoints the parent without releasing it — and the same runId resumes later. A normal shared computer_run_finish(runId) checkpoints the parent and stops it when this is the last active shared Run; shared discard with outcome=cancelled or failed closes only the Run record, without checkpointing, stopping shared processes, or preserving unread output. Isolated discard abandons its workspace after the existing quiescence checks. An accepted isolated finish may return status active with finishRequest.state pending while the lifecycle owner preserves output, verifies Git, checkpoints, and releases without caller cleanup; one request is sufficient, and computer_run_receipt is an optional observation rather than a progress trigger. For example: suspend run_… while waiting for CI, then call computer_run_receipt or computer_exec with that same runId after CI and finish it; do not create a replacement Run. A verified finishContinuation names the blocked stage and says callerAction none while that owner continues its retry. An isolated Run Preview is durable review output, not adoption or a checkpoint. The internal provider-handle publication operations are not agent tools.`
|
|
11141
11173
|
},
|
|
11142
11174
|
{
|
|
11143
11175
|
brief: "5. Git and gh run through `computer_exec` once authorized; fetch before trusting remote state.",
|
|
@@ -11954,7 +11986,7 @@ var ACTION_DEFINITIONS = [
|
|
|
11954
11986
|
{
|
|
11955
11987
|
name: "computer_run_suspend",
|
|
11956
11988
|
title: "Suspend a run",
|
|
11957
|
-
description: "Checkpoint an active WRITE Run for an external wait: isolated Runs publish their exact workspace and release the Sandbox;
|
|
11989
|
+
description: "Checkpoint an active WRITE Run for an external wait: save or publish needed work outside the Computer first; shared Runs checkpoint the parent without releasing it, while isolated Runs publish their exact workspace and release the Sandbox; resume with the same runId. Unread terminal output is retained for 30 days; no drain required; active/unknown work or failed preservation blocks release.",
|
|
11958
11990
|
inputSchema: {
|
|
11959
11991
|
runId: string2().describe("the active WRITE Run to suspend, run_…")
|
|
11960
11992
|
},
|
|
@@ -11976,7 +12008,7 @@ var ACTION_DEFINITIONS = [
|
|
|
11976
12008
|
{
|
|
11977
12009
|
name: "computer_run_finish",
|
|
11978
12010
|
title: "Finish a run",
|
|
11979
|
-
description: "Finish after
|
|
12011
|
+
description: "Finish after saving/publishing needed work outside the Computer; shared finish checkpoints parent and stops last shared Run; shared discard with failed/cancelled only closes record (no checkpoint, shared stop, unread preservation); isolated discard abandons workspace after quiescence. May stay pending for quiescence, durability, checkpoint, release; discard=true requires failed/cancelled.",
|
|
11980
12012
|
inputSchema: {
|
|
11981
12013
|
runId: string2().describe("the runId returned by computer_run_start, run_…"),
|
|
11982
12014
|
outcome: _enum(["finished", "failed", "cancelled"]).optional().describe("terminal outcome; defaults to finished"),
|
|
@@ -12414,7 +12446,8 @@ var ACTION_DEFINITIONS = [
|
|
|
12414
12446
|
baseVersion: number2().describe("the version you READ (get_artifact) — stale is rejected"),
|
|
12415
12447
|
source: string2().optional().describe("full replace: the complete new content"),
|
|
12416
12448
|
patches: array(object({ old: string2(), new: string2() })).optional().describe("exact-match hunks applied in order; each old must match exactly once"),
|
|
12417
|
-
note: string2().optional().describe("one-line summary of what changed")
|
|
12449
|
+
note: string2().optional().describe("one-line summary of what changed"),
|
|
12450
|
+
idempotencyKey: string2().min(1).max(200).optional().describe("stable retry key for this logical edit; the CLI derives one from the artifact, base version, and content when omitted")
|
|
12418
12451
|
},
|
|
12419
12452
|
surfaces: ["cli"],
|
|
12420
12453
|
toolset: "artifacts",
|
|
@@ -15220,6 +15253,159 @@ function buildInput(inputSchema, flags, command) {
|
|
|
15220
15253
|
}
|
|
15221
15254
|
|
|
15222
15255
|
// src/commands.ts
|
|
15256
|
+
var SHA256_K = [
|
|
15257
|
+
1116352408,
|
|
15258
|
+
1899447441,
|
|
15259
|
+
3049323471,
|
|
15260
|
+
3921009573,
|
|
15261
|
+
961987163,
|
|
15262
|
+
1508970993,
|
|
15263
|
+
2453635748,
|
|
15264
|
+
2870763221,
|
|
15265
|
+
3624381080,
|
|
15266
|
+
310598401,
|
|
15267
|
+
607225278,
|
|
15268
|
+
1426881987,
|
|
15269
|
+
1925078388,
|
|
15270
|
+
2162078206,
|
|
15271
|
+
2614888103,
|
|
15272
|
+
3248222580,
|
|
15273
|
+
3835390401,
|
|
15274
|
+
4022224774,
|
|
15275
|
+
264347078,
|
|
15276
|
+
604807628,
|
|
15277
|
+
770255983,
|
|
15278
|
+
1249150122,
|
|
15279
|
+
1555081692,
|
|
15280
|
+
1996064986,
|
|
15281
|
+
2554220882,
|
|
15282
|
+
2821834349,
|
|
15283
|
+
2952996808,
|
|
15284
|
+
3210313671,
|
|
15285
|
+
3336571891,
|
|
15286
|
+
3584528711,
|
|
15287
|
+
113926993,
|
|
15288
|
+
338241895,
|
|
15289
|
+
666307205,
|
|
15290
|
+
773529912,
|
|
15291
|
+
1294757372,
|
|
15292
|
+
1396182291,
|
|
15293
|
+
1695183700,
|
|
15294
|
+
1986661051,
|
|
15295
|
+
2177026350,
|
|
15296
|
+
2456956037,
|
|
15297
|
+
2730485921,
|
|
15298
|
+
2820302411,
|
|
15299
|
+
3259730800,
|
|
15300
|
+
3345764771,
|
|
15301
|
+
3516065817,
|
|
15302
|
+
3600352804,
|
|
15303
|
+
4094571909,
|
|
15304
|
+
275423344,
|
|
15305
|
+
430227734,
|
|
15306
|
+
506948616,
|
|
15307
|
+
659060556,
|
|
15308
|
+
883997877,
|
|
15309
|
+
958139571,
|
|
15310
|
+
1322822218,
|
|
15311
|
+
1537002063,
|
|
15312
|
+
1747873779,
|
|
15313
|
+
1955562222,
|
|
15314
|
+
2024104815,
|
|
15315
|
+
2227730452,
|
|
15316
|
+
2361852424,
|
|
15317
|
+
2428436474,
|
|
15318
|
+
2756734187,
|
|
15319
|
+
3204031479,
|
|
15320
|
+
3329325298
|
|
15321
|
+
];
|
|
15322
|
+
function rotateRight(value, bits) {
|
|
15323
|
+
return value >>> bits | value << 32 - bits;
|
|
15324
|
+
}
|
|
15325
|
+
function sha256Hex(value) {
|
|
15326
|
+
const bytes = new TextEncoder().encode(value);
|
|
15327
|
+
const bitLength = bytes.length * 8;
|
|
15328
|
+
const paddedLength = bytes.length + 9 + 63 >> 6 << 6;
|
|
15329
|
+
const padded = new Uint8Array(paddedLength);
|
|
15330
|
+
padded.set(bytes);
|
|
15331
|
+
padded[bytes.length] = 128;
|
|
15332
|
+
const highLength = Math.floor(bitLength / 4294967296);
|
|
15333
|
+
const lowLength = bitLength >>> 0;
|
|
15334
|
+
for (let i = 0;i < 4; i++) {
|
|
15335
|
+
padded[paddedLength - 8 + i] = highLength >>> 24 - i * 8;
|
|
15336
|
+
padded[paddedLength - 4 + i] = lowLength >>> 24 - i * 8;
|
|
15337
|
+
}
|
|
15338
|
+
const hash = [
|
|
15339
|
+
1779033703,
|
|
15340
|
+
3144134277,
|
|
15341
|
+
1013904242,
|
|
15342
|
+
2773480762,
|
|
15343
|
+
1359893119,
|
|
15344
|
+
2600822924,
|
|
15345
|
+
528734635,
|
|
15346
|
+
1541459225
|
|
15347
|
+
];
|
|
15348
|
+
const words = new Uint32Array(64);
|
|
15349
|
+
for (let offset = 0;offset < padded.length; offset += 64) {
|
|
15350
|
+
for (let i = 0;i < 16; i++) {
|
|
15351
|
+
const index = offset + i * 4;
|
|
15352
|
+
words[i] = padded[index] << 24 | padded[index + 1] << 16 | padded[index + 2] << 8 | padded[index + 3];
|
|
15353
|
+
}
|
|
15354
|
+
for (let i = 16;i < 64; i++) {
|
|
15355
|
+
const x = words[i - 15];
|
|
15356
|
+
const y = words[i - 2];
|
|
15357
|
+
const sigma0 = rotateRight(x, 7) ^ rotateRight(x, 18) ^ x >>> 3;
|
|
15358
|
+
const sigma1 = rotateRight(y, 17) ^ rotateRight(y, 19) ^ y >>> 10;
|
|
15359
|
+
words[i] = words[i - 16] + sigma0 + words[i - 7] + sigma1 >>> 0;
|
|
15360
|
+
}
|
|
15361
|
+
let [a, b, c, d, e, f, g, h] = hash;
|
|
15362
|
+
for (let i = 0;i < 64; i++) {
|
|
15363
|
+
const sigma1 = rotateRight(e, 6) ^ rotateRight(e, 11) ^ rotateRight(e, 25);
|
|
15364
|
+
const choice = e & f ^ ~e & g;
|
|
15365
|
+
const temp1 = h + sigma1 + choice + SHA256_K[i] + words[i] >>> 0;
|
|
15366
|
+
const sigma0 = rotateRight(a, 2) ^ rotateRight(a, 13) ^ rotateRight(a, 22);
|
|
15367
|
+
const majority = a & b ^ a & c ^ b & c;
|
|
15368
|
+
const temp2 = sigma0 + majority >>> 0;
|
|
15369
|
+
h = g;
|
|
15370
|
+
g = f;
|
|
15371
|
+
f = e;
|
|
15372
|
+
e = d + temp1 >>> 0;
|
|
15373
|
+
d = c;
|
|
15374
|
+
c = b;
|
|
15375
|
+
b = a;
|
|
15376
|
+
a = temp1 + temp2 >>> 0;
|
|
15377
|
+
}
|
|
15378
|
+
hash[0] = hash[0] + a >>> 0;
|
|
15379
|
+
hash[1] = hash[1] + b >>> 0;
|
|
15380
|
+
hash[2] = hash[2] + c >>> 0;
|
|
15381
|
+
hash[3] = hash[3] + d >>> 0;
|
|
15382
|
+
hash[4] = hash[4] + e >>> 0;
|
|
15383
|
+
hash[5] = hash[5] + f >>> 0;
|
|
15384
|
+
hash[6] = hash[6] + g >>> 0;
|
|
15385
|
+
hash[7] = hash[7] + h >>> 0;
|
|
15386
|
+
}
|
|
15387
|
+
return hash.map((word) => word.toString(16).padStart(8, "0")).join("");
|
|
15388
|
+
}
|
|
15389
|
+
function artifactEditIdempotencyKey(input) {
|
|
15390
|
+
const artifactId = input.artifactId;
|
|
15391
|
+
const baseVersion = input.baseVersion;
|
|
15392
|
+
const hasSource = typeof input.source === "string";
|
|
15393
|
+
const hasPatches = Array.isArray(input.patches);
|
|
15394
|
+
if (typeof artifactId !== "string" || !Number.isInteger(baseVersion) || !hasSource && !hasPatches) {
|
|
15395
|
+
return;
|
|
15396
|
+
}
|
|
15397
|
+
const version = baseVersion;
|
|
15398
|
+
const payload = JSON.stringify({
|
|
15399
|
+
artifactId,
|
|
15400
|
+
baseVersion: version,
|
|
15401
|
+
source: hasSource ? input.source : undefined,
|
|
15402
|
+
patches: hasPatches ? input.patches : undefined,
|
|
15403
|
+
note: typeof input.note === "string" ? input.note : undefined,
|
|
15404
|
+
retainSource: typeof input.retainSource === "boolean" ? input.retainSource : undefined
|
|
15405
|
+
});
|
|
15406
|
+
const digest = sha256Hex(payload);
|
|
15407
|
+
return `cli-artifact-edit:${artifactId}:${version}:${digest}`;
|
|
15408
|
+
}
|
|
15223
15409
|
var COMMAND_WORD_OVERRIDES = {
|
|
15224
15410
|
contribute_arbor_feedback: "feedback",
|
|
15225
15411
|
feedback_recall: "feedback find",
|
|
@@ -15502,6 +15688,11 @@ async function runObjectVerb(positionals, flags, ctx) {
|
|
|
15502
15688
|
delete inputFlags.json;
|
|
15503
15689
|
}
|
|
15504
15690
|
const input = buildInput(action.inputSchema, inputFlags, commandWords(action));
|
|
15691
|
+
if (action.name === "edit_artifact" && input.idempotencyKey === undefined) {
|
|
15692
|
+
const idempotencyKey = artifactEditIdempotencyKey(input);
|
|
15693
|
+
if (idempotencyKey !== undefined)
|
|
15694
|
+
input.idempotencyKey = idempotencyKey;
|
|
15695
|
+
}
|
|
15505
15696
|
if (action.name === "computer_exec" && flags["no-wait"] !== undefined && input.waitForTerminalMs !== undefined) {
|
|
15506
15697
|
throw new UsageError("--no-wait and --wait-for-terminal-ms are mutually exclusive", {
|
|
15507
15698
|
reason: "validation.invalid_value",
|
package/package.json
CHANGED