@lambdacurry/arbor 0.23.37 → 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.
Files changed (2) hide show
  1. package/dist/arbor.js +193 -2
  2. 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.37",
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
 
@@ -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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lambdacurry/arbor",
3
- "version": "0.23.37",
3
+ "version": "0.23.38",
4
4
  "description": "The Arbor CLI — a shared workspace for people and agents. The human + headless-agent write path over Arbor's guarded operation surface.",
5
5
  "keywords": [
6
6
  "agents",