@lambdacurry/arbor 0.17.6 → 0.18.0

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 +148 -5
  2. package/package.json +1 -1
package/dist/arbor.js CHANGED
@@ -1671,6 +1671,29 @@ var computerSessions = sqliteTable("computer_sessions", {
1671
1671
  computerIdx: index("computer_sessions_computer_idx").on(t.computerId, t.attachedAt),
1672
1672
  threadIdx: index("computer_sessions_thread_idx").on(t.threadId, t.attachedAt)
1673
1673
  }));
1674
+ var computerRuns = sqliteTable("computer_runs", {
1675
+ id: text("id").primaryKey(),
1676
+ computerId: text("computer_id").notNull().references(() => threadComputers.id),
1677
+ threadId: text("thread_id").notNull().references(() => threads.id),
1678
+ computerSessionId: text("computer_session_id").notNull().references(() => computerSessions.id),
1679
+ profileId: text("profile_id").notNull().references(() => profiles.id),
1680
+ executionContextId: text("execution_context_id").notNull().references(() => executionContexts.id),
1681
+ mode: text("mode").$type().notNull(),
1682
+ isolation: text("isolation").$type().notNull(),
1683
+ workspaceDir: text("workspace_dir").notNull(),
1684
+ workspaceRef: text("workspace_ref"),
1685
+ baseSnapshotId: text("base_snapshot_id"),
1686
+ status: text("status").$type().notNull().default("active"),
1687
+ label: text("label"),
1688
+ reason: text("reason"),
1689
+ startedAt: ts("started_at").notNull(),
1690
+ endedAt: ts("ended_at")
1691
+ }, (t) => ({
1692
+ computerIdx: index("computer_runs_computer_idx").on(t.computerId, t.startedAt),
1693
+ threadIdx: index("computer_runs_thread_idx").on(t.threadId, t.startedAt),
1694
+ sessionIdx: index("computer_runs_session_idx").on(t.computerSessionId, t.startedAt),
1695
+ statusIdx: index("computer_runs_status_idx").on(t.computerId, t.status)
1696
+ }));
1674
1697
  var computerSnapshots = sqliteTable("computer_snapshots", {
1675
1698
  id: text("id").primaryKey(),
1676
1699
  ownerScope: text("owner_scope").$type().notNull(),
@@ -2174,6 +2197,11 @@ var watches = sqliteTable("watches", {
2174
2197
  watchUq: uniqueIndex("watches_watcher_target_uniq").on(t.watcherProfileId, t.targetType, t.targetId),
2175
2198
  watchTargetIdx: index("watches_target_idx").on(t.targetType, t.targetId)
2176
2199
  }));
2200
+ // ../core/src/ops/computer-run.ts
2201
+ var COMPUTER_WORKSPACE_ROOT = "/workspace";
2202
+ var COMPUTER_RUN_WORKSPACE_ROOT = `${COMPUTER_WORKSPACE_ROOT}/.arbor-runs`;
2203
+ var TERMINAL = new Set(["finished", "failed", "cancelled"]);
2204
+
2177
2205
  // ../core/src/ops/computer.ts
2178
2206
  var MAX_COMPUTER_REPOSITORIES = 10;
2179
2207
 
@@ -16737,6 +16765,43 @@ var computerProfile = exports_external.looseObject({
16737
16765
  tools: exports_external.array(exports_external.string()),
16738
16766
  recommendedEditingPrimitive: exports_external.string()
16739
16767
  });
16768
+ var computerRun = exports_external.looseObject({
16769
+ runId: id,
16770
+ computerId: id,
16771
+ threadId: id,
16772
+ computerSessionId: id,
16773
+ profileId: id,
16774
+ executionContextId: id,
16775
+ mode: exports_external.enum(["read", "write"]),
16776
+ isolation: exports_external.enum(["shared", "isolated"]),
16777
+ workspaceDir: exports_external.string(),
16778
+ workspaceRef: exports_external.string().nullable(),
16779
+ baseSnapshotId: id.nullable(),
16780
+ status: exports_external.enum(["active", "finished", "failed", "cancelled"]),
16781
+ label: exports_external.string().nullable(),
16782
+ reason: exports_external.string().nullable(),
16783
+ startedAt: exports_external.string(),
16784
+ endedAt: exports_external.string().nullable()
16785
+ });
16786
+ var computerRunReceipt = exports_external.looseObject({
16787
+ runId: id,
16788
+ threadId: id,
16789
+ computerId: id,
16790
+ computerSessionId: id,
16791
+ actor: exports_external.looseObject({ profileId: id, executionContextId: id }),
16792
+ label: exports_external.string().nullable(),
16793
+ mode: exports_external.enum(["read", "write"]),
16794
+ isolation: exports_external.enum(["shared", "isolated"]),
16795
+ workspace: exports_external.looseObject({ dir: exports_external.string(), ref: exports_external.string().nullable() }),
16796
+ baseSnapshotId: id.nullable(),
16797
+ status: exports_external.enum(["active", "finished", "failed", "cancelled"]),
16798
+ outcome: exports_external.enum(["finished", "failed", "cancelled"]).nullable(),
16799
+ reason: exports_external.string().nullable(),
16800
+ startedAt: exports_external.string(),
16801
+ endedAt: exports_external.string().nullable(),
16802
+ durationMs: exports_external.number().nullable(),
16803
+ lifecycle: exports_external.array(exports_external.looseObject({ type: exports_external.string(), at: exports_external.string() }))
16804
+ });
16740
16805
  var computerCapabilityCard = exports_external.looseObject({
16741
16806
  capabilities: exports_external.array(exports_external.looseObject({
16742
16807
  id: exports_external.string(),
@@ -17354,6 +17419,28 @@ var MCP_OUTPUT_SCHEMAS = {
17354
17419
  toContainerProfileRevision: exports_external.number().int().nullable()
17355
17420
  }).optional()
17356
17421
  }),
17422
+ computer_run_start: exports_external.looseObject({
17423
+ run: computerRun,
17424
+ workspace: exports_external.looseObject({
17425
+ workspaceRoot: exports_external.string(),
17426
+ repositories: exports_external.array(exports_external.looseObject({ repository: exports_external.string(), path: exports_external.string() })),
17427
+ defaultCwd: exports_external.string(),
17428
+ ref: exports_external.string().nullable().optional(),
17429
+ root: exports_external.string().optional()
17430
+ })
17431
+ }),
17432
+ computer_run_finish: exports_external.looseObject({
17433
+ run: computerRun,
17434
+ replayed: exports_external.boolean()
17435
+ }),
17436
+ computer_run_receipt: exports_external.looseObject({
17437
+ receipt: computerRunReceipt
17438
+ }),
17439
+ computer_runs: exports_external.looseObject({
17440
+ computerId: id,
17441
+ threadId: id,
17442
+ runs: exports_external.array(computerRun)
17443
+ }),
17357
17444
  computer_reprovision: exports_external.looseObject({
17358
17445
  reprovisionId: id,
17359
17446
  threadId: id,
@@ -17620,6 +17707,10 @@ var MCP_TOOL_ANNOTATIONS = {
17620
17707
  github_connect_repository: idempotent,
17621
17708
  computer_open: additive,
17622
17709
  computer_reprovision: destructiveIdempotent,
17710
+ computer_run_start: additive,
17711
+ computer_run_finish: idempotent,
17712
+ computer_run_receipt: readOnly,
17713
+ computer_runs: readOnly,
17623
17714
  computer_exec: destructiveOpenWorld,
17624
17715
  computer_process_read: readOnly,
17625
17716
  computer_process_terminate: destructiveOpenWorld,
@@ -18020,14 +18111,65 @@ var ACTION_DEFINITIONS = [
18020
18111
  toolset: "loop",
18021
18112
  run: forward("computer_runtime.reprovision")
18022
18113
  },
18114
+ {
18115
+ name: "computer_run_start",
18116
+ title: "Start a run",
18117
+ description: "Start one unit of work inside an opened Thread computer and receive the workspace it may use. A write run is given its OWN mutable checkout — a working tree per materialized repository, forked from the computer's current shared state — so a second task started on the SAME computer does not land in its edits. Pass the returned runId to computer_exec and computer_write: exec starts in that checkout and write's path is confined to it, so an Arbor-routed path cannot address the shared workspace or another run's checkout. This routes collaborating tasks apart rather than sandboxing them — the raw command text is not sandboxed, so an absolute path inside a command string still reaches the shared workspace or another run's checkout in the shared container, while relative paths keep a command's writes in your own checkout. It is isolation against collision, not against untrusted code. A read run stays on the shared /workspace. Finish every run with computer_run_finish. This creates no Thread and no second computer.",
18118
+ inputSchema: {
18119
+ computerSessionId: exports_external.string().describe("the computerSessionId returned by computer_open, cms_…"),
18120
+ mode: exports_external.enum(["read", "write"]).describe("write for an isolated mutable checkout; read to share /workspace"),
18121
+ label: exports_external.string().max(120).optional().describe("short factual label for this unit of work")
18122
+ },
18123
+ surfaces: ["computer-mcp", "computer-cli"],
18124
+ toolset: "loop",
18125
+ run: forward("computer_runtime.run_start")
18126
+ },
18127
+ {
18128
+ name: "computer_run_finish",
18129
+ title: "Finish a run",
18130
+ description: "Close a run with its terminal outcome and the one line that explains it. Checkpoint anything worth keeping first (computer_checkpoint or computer_stop); finishing a run releases the unit of work, it does not save or discard the files in its checkout. Repeating the same outcome is a safe no-op, and it keeps the reason the first caller settled — a different outcome is a conflict. Say what happened in reason: it is what computer_run_receipt shows a reader who was not here.",
18131
+ inputSchema: {
18132
+ runId: exports_external.string().describe("the runId returned by computer_run_start, run_…"),
18133
+ outcome: exports_external.enum(["finished", "failed", "cancelled"]).optional().describe("terminal outcome; defaults to finished"),
18134
+ reason: exports_external.string().max(500).optional().describe("one factual line on how this unit of work ended, e.g. what shipped or what broke")
18135
+ },
18136
+ surfaces: ["computer-mcp", "computer-cli"],
18137
+ toolset: "loop",
18138
+ run: forward("computer_runtime.run_finish")
18139
+ },
18140
+ {
18141
+ name: "computer_run_receipt",
18142
+ title: "Read a run receipt",
18143
+ description: "READ ONLY: read one run's compact receipt — its purpose, actor, computer session, the base snapshot it forked from, its workspace and effective isolation, how it ended and why, how long it took, and its lifecycle events. This is the normal way to inspect a run you or someone else started, and it stays readable after the run is terminal. Arbor keeps no process state and no command output, so the receipt says what the protocol recorded, not what scrolled past in the shell.",
18144
+ inputSchema: {
18145
+ runId: exports_external.string().describe("the run to read, run_… (from computer_run_start or computer_runs)")
18146
+ },
18147
+ surfaces: ["computer-mcp", "computer-cli"],
18148
+ toolset: "loop",
18149
+ run: forward("computer_runtime.run_receipt")
18150
+ },
18151
+ {
18152
+ name: "computer_runs",
18153
+ title: "List runs",
18154
+ description: "READ ONLY: list the active and recent runs of this Thread computer with each run's mode, effective isolation, and workspace identity. Use it to see what other work is in flight on the same computer before starting or finishing your own.",
18155
+ inputSchema: {
18156
+ computerSessionId: exports_external.string().describe("the computerSessionId returned by computer_open, cms_…"),
18157
+ status: exports_external.enum(["active", "finished", "failed", "cancelled"]).optional().describe("filter to one lifecycle status"),
18158
+ limit: exports_external.number().int().min(1).max(100).optional().describe("rows to return (default 20)")
18159
+ },
18160
+ surfaces: ["computer-mcp", "computer-cli"],
18161
+ toolset: "loop",
18162
+ run: forward("computer_runtime.run_list")
18163
+ },
18023
18164
  {
18024
18165
  name: "computer_exec",
18025
18166
  title: "Run a command",
18026
- description: "Run one bounded logical operation in an opened Thread computer. Omitting cwd runs from the Computer's defaultCwd — the one materialized checkout when the recipe has exactly one repository, otherwise the workspace root — and the receipt echoes the cwd it ran in; pass cwd explicitly to override it. Strict Bash semantics are ON by default: an early command failure or failed pipeline makes the execution nonzero, while explicit handling such as `cmd || fallback` still works. Set strict=false only for an intentional best-effort script. For a connected human, Arbor supplies ambient GitHub authorization for normal gh/HTTPS Git commands and GitHub-linked author/committer identity ephemerally for every exec without writing credentials into the workspace; command-local Git environment overrides may still replace the identity. Use background only for the container backend; it returns a processId for computer_process_read / computer_process_terminate. worker-shell deliberately serializes mutations and rejects long-lived processes.",
18167
+ description: "Run one bounded logical operation in an opened Thread computer. Omitting cwd runs from the Computer's defaultCwd — the one materialized checkout when the recipe has exactly one repository, otherwise the workspace root — and the receipt echoes the cwd it ran in; pass cwd explicitly to override it. Pass runId to work inside that run's own checkout: the command starts there and relative paths keep its writes there, while the raw command text is not sandboxed — an absolute path still reaches the shared workspace or another run's checkout in the shared container. Strict Bash semantics are ON by default: an early command failure or failed pipeline makes the execution nonzero, while explicit handling such as `cmd || fallback` still works. Set strict=false only for an intentional best-effort script. For a connected human, Arbor supplies ambient GitHub authorization for normal gh/HTTPS Git commands and GitHub-linked author/committer identity ephemerally for every exec without writing credentials into the workspace; command-local Git environment overrides may still replace the identity. Use background only for the container backend; it returns a processId for computer_process_read / computer_process_terminate. worker-shell deliberately serializes mutations and rejects long-lived processes.",
18027
18168
  inputSchema: {
18028
18169
  computerSessionId: exports_external.string().describe("the computerSessionId returned by computer_open, cms_…"),
18029
18170
  command: exports_external.string().min(1).describe("the shell command to run"),
18030
- cwd: exports_external.string().optional().describe("working directory under /workspace"),
18171
+ runId: exports_external.string().optional().describe("run this inside the checkout of this run, run_… (from computer_run_start)"),
18172
+ cwd: exports_external.string().optional().describe("working directory under /workspace, or under the run"),
18031
18173
  timeout: exports_external.number().int().min(1000).max(1800000).optional().describe("timeout in milliseconds, from 1,000 through 1,800,000"),
18032
18174
  background: exports_external.boolean().optional().describe("start a container process and return its pid"),
18033
18175
  strict: exports_external.boolean().optional().describe("fail on the first unhandled command or pipeline failure; defaults to true, set false only for intentional best-effort execution")
@@ -18166,10 +18308,11 @@ var ACTION_DEFINITIONS = [
18166
18308
  {
18167
18309
  name: "computer_write",
18168
18310
  title: "Write a project file",
18169
- description: "Write one file under /workspace. Content is UTF-8 by default; pass encoding=base64 only for binary bytes. Prefer normal editing tools for code changes; reach for this when the MCP/CLI computer surface is the only filesystem path.",
18311
+ description: "Write one file under /workspace. Content is UTF-8 by default; pass encoding=base64 only for binary bytes. Pass runId to write inside that run's own checkout, where the path may be relative and, being an Arbor-routed path, cannot reach the shared workspace or another run's files. Prefer normal editing tools for code changes; reach for this when the MCP/CLI computer surface is the only filesystem path.",
18170
18312
  inputSchema: {
18171
18313
  computerSessionId: exports_external.string().describe("the computerSessionId returned by computer_open, cms_…"),
18172
- path: exports_external.string().describe("absolute path under /workspace"),
18314
+ path: exports_external.string().describe("absolute path under /workspace, or a path inside the run"),
18315
+ runId: exports_external.string().optional().describe("write into the checkout of this run, run_… (from computer_run_start)"),
18173
18316
  content: exports_external.string().describe("complete UTF-8 content, or base64 bytes when encoding=base64"),
18174
18317
  encoding: exports_external.enum(["utf8", "base64"]).optional().describe("content encoding; defaults to utf8, use base64 for binary files")
18175
18318
  },
@@ -18238,7 +18381,7 @@ var ACTION_DEFINITIONS = [
18238
18381
  {
18239
18382
  name: "get_computer",
18240
18383
  title: "Read a Thread computer",
18241
- description: "Read a Thread's redacted effective recipe, active materialized generation, compatibility state, historical generation lineage, current Topic/Thread snapshot refs, recent attachment receipts, and replacement outcomes. Recipe metadata includes provider/backend/profile/repositories/config revision and whether setup is configured, never setup content or credentials. This is durable Arbor protocol state, not live process/presence status.",
18384
+ description: "Read a Thread's redacted effective recipe, active materialized generation, compatibility state, historical generation lineage, current Topic/Thread snapshot refs, recent attachment receipts, active and recent runs with each run's mode/isolation/workspace, and replacement outcomes. Recipe metadata includes provider/backend/profile/repositories/config revision and whether setup is configured, never setup content or credentials. This is durable Arbor protocol state, not live process/presence status.",
18242
18385
  inputSchema: {
18243
18386
  threadId: exports_external.string().describe("the Thread, thr_…"),
18244
18387
  lineageLimit: exports_external.number().int().min(1).max(100).optional().describe("recent receipts/lineage rows (default 20)")
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lambdacurry/arbor",
3
- "version": "0.17.6",
3
+ "version": "0.18.0",
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",