@lambdacurry/arbor 0.22.21 → 0.22.23
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 +100 -26
- 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.22.
|
|
5
|
+
version: "0.22.23",
|
|
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",
|
|
@@ -6712,6 +6712,69 @@ var computerRunStarts = sqliteTable("computer_run_starts", {
|
|
|
6712
6712
|
snapshotIdx: index("computer_run_starts_snapshot_idx").on(t.snapshotId),
|
|
6713
6713
|
runIdx: uniqueIndex("computer_run_starts_run_idx").on(t.runId)
|
|
6714
6714
|
}));
|
|
6715
|
+
var computerOutputCaptures = sqliteTable("computer_output_captures", {
|
|
6716
|
+
id: text("id").primaryKey(),
|
|
6717
|
+
runId: text("run_id").notNull().references(() => computerRuns.id),
|
|
6718
|
+
processId: text("process_id").notNull(),
|
|
6719
|
+
computerId: text("computer_id").notNull().references(() => threadComputers.id),
|
|
6720
|
+
threadId: text("thread_id").notNull().references(() => threads.id),
|
|
6721
|
+
computerSessionId: text("computer_session_id").notNull().references(() => computerSessions.id),
|
|
6722
|
+
runProfileId: text("run_profile_id").notNull().references(() => profiles.id),
|
|
6723
|
+
runExecutionContextId: text("run_execution_context_id").notNull().references(() => executionContexts.id),
|
|
6724
|
+
sessionProfileId: text("session_profile_id").notNull().references(() => profiles.id),
|
|
6725
|
+
sessionExecutionContextId: text("session_execution_context_id").notNull().references(() => executionContexts.id),
|
|
6726
|
+
execution: text("execution").$type().notNull(),
|
|
6727
|
+
processState: text("process_state").$type().notNull(),
|
|
6728
|
+
processActivityKind: text("process_activity_kind").$type(),
|
|
6729
|
+
processExecution: text("process_execution").$type(),
|
|
6730
|
+
providerGeneration: integer2("provider_generation"),
|
|
6731
|
+
workspaceGeneration: text("workspace_generation"),
|
|
6732
|
+
expectedCurrentSnapshotId: text("expected_current_snapshot_id").references(() => computerSnapshots.id),
|
|
6733
|
+
terminalOutcome: text("terminal_outcome").$type(),
|
|
6734
|
+
exitCode: integer2("exit_code"),
|
|
6735
|
+
timedOut: integer2("timed_out", { mode: "boolean" }),
|
|
6736
|
+
durationMs: integer2("duration_ms"),
|
|
6737
|
+
status: text("status").$type().notNull().default("pending"),
|
|
6738
|
+
stdoutBytes: integer2("stdout_bytes").notNull().default(0),
|
|
6739
|
+
stderrBytes: integer2("stderr_bytes").notNull().default(0),
|
|
6740
|
+
requestedStdoutBytes: integer2("requested_stdout_bytes"),
|
|
6741
|
+
requestedStderrBytes: integer2("requested_stderr_bytes"),
|
|
6742
|
+
pageIntentDigest: text("page_intent_digest"),
|
|
6743
|
+
intentStdoutBytes: integer2("intent_stdout_bytes"),
|
|
6744
|
+
intentStderrBytes: integer2("intent_stderr_bytes"),
|
|
6745
|
+
intentTerminalOutcome: text("intent_terminal_outcome").$type(),
|
|
6746
|
+
intentExitCode: integer2("intent_exit_code"),
|
|
6747
|
+
intentTimedOut: integer2("intent_timed_out", { mode: "boolean" }),
|
|
6748
|
+
intentDurationMs: integer2("intent_duration_ms"),
|
|
6749
|
+
lastPublishedIntentDigest: text("last_published_intent_digest"),
|
|
6750
|
+
cleanupToken: text("cleanup_token"),
|
|
6751
|
+
cleanupClaimedAt: ts("cleanup_claimed_at"),
|
|
6752
|
+
completedAt: ts("completed_at"),
|
|
6753
|
+
expiresAt: ts("expires_at"),
|
|
6754
|
+
updatedAt: ts("updated_at").notNull(),
|
|
6755
|
+
createdAt: ts("created_at").notNull()
|
|
6756
|
+
}, (t) => ({
|
|
6757
|
+
runProcessIdx: uniqueIndex("computer_output_captures_run_process_idx").on(t.runId, t.processId),
|
|
6758
|
+
computerIdx: index("computer_output_captures_computer_idx").on(t.computerId, t.status),
|
|
6759
|
+
pendingIdx: index("computer_output_captures_pending_idx").on(t.status, t.updatedAt),
|
|
6760
|
+
expiresIdx: index("computer_output_captures_expires_idx").on(t.status, t.expiresAt)
|
|
6761
|
+
}));
|
|
6762
|
+
var computerOutputChunks = sqliteTable("computer_output_chunks", {
|
|
6763
|
+
id: text("id").primaryKey(),
|
|
6764
|
+
captureId: text("capture_id").notNull().references(() => computerOutputCaptures.id),
|
|
6765
|
+
stream: text("stream").$type().notNull(),
|
|
6766
|
+
startOffset: integer2("start_offset").notNull(),
|
|
6767
|
+
size: integer2("size").notNull(),
|
|
6768
|
+
blobKey: text("blob_key").notNull(),
|
|
6769
|
+
sha256: text("sha256").notNull(),
|
|
6770
|
+
pageIntentDigest: text("page_intent_digest").notNull(),
|
|
6771
|
+
verifiedAt: ts("verified_at"),
|
|
6772
|
+
deletedAt: ts("deleted_at"),
|
|
6773
|
+
createdAt: ts("created_at").notNull()
|
|
6774
|
+
}, (t) => ({
|
|
6775
|
+
rangeIdx: uniqueIndex("computer_output_chunks_range_idx").on(t.captureId, t.stream, t.startOffset),
|
|
6776
|
+
blobKeyIdx: uniqueIndex("computer_output_chunks_blob_key_idx").on(t.blobKey)
|
|
6777
|
+
}));
|
|
6715
6778
|
var previews = sqliteTable("previews", {
|
|
6716
6779
|
id: text("id").primaryKey(),
|
|
6717
6780
|
threadId: text("thread_id").notNull().references(() => threads.id),
|
|
@@ -7548,6 +7611,8 @@ var assigneeColumns = {
|
|
|
7548
7611
|
color: profiles.color,
|
|
7549
7612
|
emoji: profiles.emoji
|
|
7550
7613
|
};
|
|
7614
|
+
// ../core/src/ops/computer-output.ts
|
|
7615
|
+
var COMPUTER_OUTPUT_DEFAULT_STALE_MS = 24 * 60 * 60 * 1000;
|
|
7551
7616
|
// ../core/src/ops/computer-recovery.ts
|
|
7552
7617
|
var COMPUTER_RECOVERY_GRANT_MAX_TTL_MS = 24 * 60 * 60 * 1000;
|
|
7553
7618
|
// ../core/src/ops/preview.ts
|
|
@@ -9163,6 +9228,7 @@ var MCP_OUTPUT_SCHEMAS = {
|
|
|
9163
9228
|
computer_process_read: looseObject({
|
|
9164
9229
|
processId: string2(),
|
|
9165
9230
|
status: string2(),
|
|
9231
|
+
outputRetention: object({ state: literal("preserved"), expiresAt: timestamp }).optional(),
|
|
9166
9232
|
timedOut: boolean2().optional(),
|
|
9167
9233
|
endedAt: timestamp.nullable().optional(),
|
|
9168
9234
|
durationMs: number2().int().min(0).nullable().optional(),
|
|
@@ -9563,6 +9629,7 @@ var OUTPUT_SHAPERS = {
|
|
|
9563
9629
|
computer_process_read: (result) => defined([
|
|
9564
9630
|
["processId", result.processId],
|
|
9565
9631
|
["status", result.status],
|
|
9632
|
+
["outputRetention", omitNull(result.outputRetention)],
|
|
9566
9633
|
["timedOut", omitNull(result.timedOut)],
|
|
9567
9634
|
["stdout", result.stdout],
|
|
9568
9635
|
["stderr", result.stderr],
|
|
@@ -9949,7 +10016,7 @@ Arbor's MCP is the collaboration and durable-knowledge surface. Configure, autho
|
|
|
9949
10016
|
|
|
9950
10017
|
Run \`arbor help\` (or read the MCP tool list) for the exact command/flags — those stay generated from the live action surface, so they're always current.`;
|
|
9951
10018
|
var ARBOR_SKILL_MARKDOWN = renderArborSkill(ORIENTATION);
|
|
9952
|
-
var COMPUTER_ORIENTATION = `Long Computer work returns a handle — do not hold one tool call for a full test or build. \`computer_exec\` runs a command; if the result is still running,
|
|
10019
|
+
var COMPUTER_ORIENTATION = `Long Computer work returns a processId handle — do not hold one tool call for a full test or build. \`computer_exec\` runs a command; if the result is still running, observe it with \`computer_process_read\`; read a truncated continuation only when you need more output. Finish and suspend preserve unread terminal output internally, with original process IDs/cursors recoverable for 30 days. Do not chain \`pnpm test && pnpm build\` in one exec; split steps or pass \`background:true\`. The CLI polls only while the process is silent unless \`--no-wait\`; it returns the first bounded output page instead of concatenating continuation pages into one agent context.
|
|
9953
10020
|
|
|
9954
10021
|
Arbor Computer is the complete software execution platform attached to Arbor's durable collaboration graph. It configures project environments, executes and verifies work, packages and releases Apps, and preserves reviewable evidence; it does not schedule agents or replace Arbor collaboration.
|
|
9955
10022
|
|
|
@@ -10712,9 +10779,9 @@ var ACTION_DEFINITIONS = [
|
|
|
10712
10779
|
{
|
|
10713
10780
|
name: "computer_run_suspend",
|
|
10714
10781
|
title: "Suspend a run",
|
|
10715
|
-
description: "Checkpoint an active WRITE Run for an external wait
|
|
10782
|
+
description: "Checkpoint an active WRITE Run for an external wait: isolated Runs publish their exact workspace and release the Sandbox; shared Runs checkpoint the parent, and the same runId resumes next. Preserves unread terminal output internally for 30 days; no caller drain is required, larger captures use bounded same-Run retries, and active/unknown work or failed preservation blocks release without replay.",
|
|
10716
10783
|
inputSchema: {
|
|
10717
|
-
runId: string2().describe("the active
|
|
10784
|
+
runId: string2().describe("the active WRITE Run to suspend, run_…")
|
|
10718
10785
|
},
|
|
10719
10786
|
surfaces: ["computer-mcp", "computer-cli"],
|
|
10720
10787
|
toolset: "loop",
|
|
@@ -10734,7 +10801,7 @@ var ACTION_DEFINITIONS = [
|
|
|
10734
10801
|
{
|
|
10735
10802
|
name: "computer_run_finish",
|
|
10736
10803
|
title: "Finish a run",
|
|
10737
|
-
description: "Finish a Run
|
|
10804
|
+
description: "Finish a Run, preserving unread terminal output for 30 days without caller drain; active/unknown operations, failed preservation, and proven non-durable isolated WRITE work block release, and the last shared Run stops the parent. To abandon an unknown or non-durable disposable Run, pass discard=true with outcome failed or cancelled; the receipt keeps evidence and repeating that outcome is safe.",
|
|
10738
10805
|
inputSchema: {
|
|
10739
10806
|
runId: string2().describe("the runId returned by computer_run_start, run_…"),
|
|
10740
10807
|
outcome: _enum(["finished", "failed", "cancelled"]).optional().describe("terminal outcome; defaults to finished"),
|
|
@@ -10773,7 +10840,7 @@ var ACTION_DEFINITIONS = [
|
|
|
10773
10840
|
{
|
|
10774
10841
|
name: "computer_exec",
|
|
10775
10842
|
title: "Run a command",
|
|
10776
|
-
description: "Run one bounded shell
|
|
10843
|
+
description: "Run one bounded shell command in runId with ambient GitHub authorization; timeout kills the process. Observe running work with computer_process_read; use nextCursor for a truncated output page only when needed and finish without draining; after a missed response use computer_run_receipt.operations[].operationId with computer_process_read instead of repeating the mutation.",
|
|
10777
10844
|
inputSchema: {
|
|
10778
10845
|
computerSessionId: string2().optional().describe("legacy alternative to runId: a computerSessionId on that Computer, cms_…; required unless runId is supplied"),
|
|
10779
10846
|
command: string2().min(1).describe("the shell command to run"),
|
|
@@ -10792,12 +10859,12 @@ var ACTION_DEFINITIONS = [
|
|
|
10792
10859
|
{
|
|
10793
10860
|
name: "computer_process_read",
|
|
10794
10861
|
title: "Read a background process",
|
|
10795
|
-
description: "Read
|
|
10862
|
+
description: "Read original process output using nextCursor; preserved output stays readable for 30 days after preservation, including repeated cursors after finish/suspend, without provider wake. Live reads retain the latest observation; a later timeout remains unknown/unsafe with its age, and Arbor settles the durable operation only from terminal or exact provider-absence proof.",
|
|
10796
10863
|
inputSchema: {
|
|
10797
10864
|
computerSessionId: string2().optional().describe("legacy alternative to runId: a computerSessionId on that Computer, cms_…; required unless runId is supplied"),
|
|
10798
10865
|
runId: string2().optional().describe("the Run that owns this process, if it was started inside a Run"),
|
|
10799
10866
|
processId: string2().min(1).describe("the processId returned by background exec, or matching computer_run_receipt.operations[].operationId for recovered foreground Run work, proc_…"),
|
|
10800
|
-
cursor: string2().optional().describe("continue after nextCursor from the prior
|
|
10867
|
+
cursor: string2().optional().describe("continue after nextCursor from the prior result; omit to read from the beginning"),
|
|
10801
10868
|
maxBytes: number2().int().min(1024).max(65536).optional().describe("maximum combined output bytes to return; default 4,096, opt up only when needed")
|
|
10802
10869
|
},
|
|
10803
10870
|
surfaces: ["computer-mcp", "computer-cli"],
|
|
@@ -11658,7 +11725,7 @@ var ACTION_DEFINITIONS = [
|
|
|
11658
11725
|
{
|
|
11659
11726
|
name: "service_register",
|
|
11660
11727
|
title: "Register a Computer lifecycle service",
|
|
11661
|
-
description: "Register a persistent service identity for Currybox Computer lifecycle maintenance and mint its API key (shown ONCE). Human owner/admin CLI setup only. The credential is restricted to computer.get + computer.lifecycle_runs + computer.append_run_lifecycle + computer.checkpoint + computer.suspend_run + computer.resume_run + computer.reconcile_runs and to the Spaces listed here; store it as the Currybox control plane's Arbor credential.",
|
|
11728
|
+
description: "Register a persistent service identity for Currybox Computer lifecycle maintenance and mint its API key (shown ONCE). Human owner/admin CLI setup only. The credential is restricted to computer.get + computer.lifecycle_runs + computer.append_run_lifecycle + computer.checkpoint + computer.preserve_run_output + computer.suspend_run + computer.resume_run + computer.reconcile_runs and to the Spaces listed here; store it as the Currybox control plane's Arbor credential.",
|
|
11662
11729
|
inputSchema: {
|
|
11663
11730
|
displayName: string2().min(1).describe("the service display name, e.g. Currybox lifecycle service"),
|
|
11664
11731
|
spaceIds: array(string2().min(1)).min(1).describe("Spaces whose Thread computers the service may maintain")
|
|
@@ -12918,6 +12985,7 @@ function codeForStatus(status) {
|
|
|
12918
12985
|
case 403:
|
|
12919
12986
|
return "FORBIDDEN";
|
|
12920
12987
|
case 404:
|
|
12988
|
+
case 410:
|
|
12921
12989
|
return "NOT_FOUND";
|
|
12922
12990
|
case 409:
|
|
12923
12991
|
return "CONFLICT";
|
|
@@ -12978,6 +13046,12 @@ function parseErrorDetails(value) {
|
|
|
12978
13046
|
details.operationId = raw.operationId;
|
|
12979
13047
|
if (typeof raw.processId === "string")
|
|
12980
13048
|
details.processId = raw.processId;
|
|
13049
|
+
if (raw.outputRetention && typeof raw.outputRetention === "object") {
|
|
13050
|
+
const retention = raw.outputRetention;
|
|
13051
|
+
if (retention.state === "expired" && typeof retention.expiresAt === "string") {
|
|
13052
|
+
details.outputRetention = { state: "expired", expiresAt: retention.expiresAt };
|
|
13053
|
+
}
|
|
13054
|
+
}
|
|
12981
13055
|
if (raw.commandExecution === "not-routed" || raw.commandExecution === "unknown") {
|
|
12982
13056
|
details.commandExecution = raw.commandExecution;
|
|
12983
13057
|
}
|
|
@@ -13520,6 +13594,7 @@ function emitDual(data, human, action, ctx) {
|
|
|
13520
13594
|
|
|
13521
13595
|
// src/computer-exec-wait.ts
|
|
13522
13596
|
var DEFAULT_PROCESS_DEADLINE_MS = 1800000;
|
|
13597
|
+
var PROCESS_OUTPUT_PAGE_BYTES = 4096;
|
|
13523
13598
|
var POLL_MS = 400;
|
|
13524
13599
|
var processRead = ACTIONS3.find((action) => action.name === "computer_process_read");
|
|
13525
13600
|
function record3(value) {
|
|
@@ -13540,6 +13615,12 @@ function isRunning(value) {
|
|
|
13540
13615
|
return false;
|
|
13541
13616
|
return typeof value.processId === "string";
|
|
13542
13617
|
}
|
|
13618
|
+
function hasCallerVisibleOutputPage(value) {
|
|
13619
|
+
return typeof value.stdout === "string" && value.stdout.length > 0 || typeof value.stderr === "string" && value.stderr.length > 0 || value.truncated === true;
|
|
13620
|
+
}
|
|
13621
|
+
function withContinuation(value) {
|
|
13622
|
+
return isRunning(value) || value.truncated === true ? { ...value, nextAction: "computer_process_read" } : value;
|
|
13623
|
+
}
|
|
13543
13624
|
function sleep(ms) {
|
|
13544
13625
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
13545
13626
|
}
|
|
@@ -13551,39 +13632,32 @@ async function waitForComputerExec(executor, input, value, ctx) {
|
|
|
13551
13632
|
if (!processRead || !isComputerExecHandle(value))
|
|
13552
13633
|
return value;
|
|
13553
13634
|
let latest = value;
|
|
13635
|
+
if (hasCallerVisibleOutputPage(latest))
|
|
13636
|
+
return withContinuation(latest);
|
|
13554
13637
|
let cursor = typeof latest.nextCursor === "string" && latest.nextCursor ? latest.nextCursor : undefined;
|
|
13555
|
-
let stdoutPages = typeof latest.stdout === "string" ? latest.stdout : "";
|
|
13556
|
-
let stderrPages = typeof latest.stderr === "string" ? latest.stderr : "";
|
|
13557
|
-
if (stdoutPages)
|
|
13558
|
-
advise(stdoutPages, ctx);
|
|
13559
13638
|
const deadline = Date.now() + (typeof input.timeout === "number" && Number.isFinite(input.timeout) ? input.timeout : DEFAULT_PROCESS_DEADLINE_MS);
|
|
13560
|
-
advise(
|
|
13561
|
-
` : `Process ${String(latest.processId)} has unread output; polling computer_process_read.
|
|
13639
|
+
advise(`Process ${String(latest.processId)} is still running; polling computer_process_read.
|
|
13562
13640
|
`, ctx);
|
|
13563
|
-
while (
|
|
13641
|
+
while (isRunning(latest) && Date.now() < deadline) {
|
|
13564
13642
|
await sleep(POLL_MS);
|
|
13565
13643
|
const read = record3(await processRead.run(executor, {
|
|
13566
13644
|
processId: latest.processId,
|
|
13645
|
+
maxBytes: PROCESS_OUTPUT_PAGE_BYTES,
|
|
13567
13646
|
...cursor ? { cursor } : {},
|
|
13568
13647
|
...typeof input.runId === "string" ? { runId: input.runId } : {},
|
|
13569
13648
|
...typeof input.computerSessionId === "string" ? { computerSessionId: input.computerSessionId } : {}
|
|
13570
13649
|
}));
|
|
13571
|
-
if (!read)
|
|
13650
|
+
if (!read)
|
|
13572
13651
|
throw new Error("computer_process_read returned an empty result");
|
|
13573
|
-
}
|
|
13574
13652
|
latest = read;
|
|
13575
13653
|
if (typeof read.nextCursor === "string" && read.nextCursor)
|
|
13576
13654
|
cursor = read.nextCursor;
|
|
13577
|
-
const stdout = typeof latest.stdout === "string" ? latest.stdout : "";
|
|
13578
|
-
const stderr = typeof latest.stderr === "string" ? latest.stderr : "";
|
|
13579
|
-
if (stdout)
|
|
13580
|
-
advise(stdout, ctx);
|
|
13581
|
-
stdoutPages += stdout;
|
|
13582
|
-
stderrPages += stderr;
|
|
13583
13655
|
if (latest.recovery)
|
|
13584
|
-
|
|
13656
|
+
return latest;
|
|
13657
|
+
if (hasCallerVisibleOutputPage(latest) || !isRunning(latest))
|
|
13658
|
+
return withContinuation(latest);
|
|
13585
13659
|
}
|
|
13586
|
-
return
|
|
13660
|
+
return withContinuation(latest);
|
|
13587
13661
|
}
|
|
13588
13662
|
|
|
13589
13663
|
// src/schema.ts
|
package/package.json
CHANGED