@lambdacurry/arbor 0.14.3 → 0.14.5
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 +102 -8
- package/package.json +1 -1
package/dist/arbor.js
CHANGED
|
@@ -38,6 +38,7 @@ var ERROR_REASONS = new Set([
|
|
|
38
38
|
"authorization.denied",
|
|
39
39
|
"resource.not_found",
|
|
40
40
|
"conflict.state",
|
|
41
|
+
"conflict.computer_recipe",
|
|
41
42
|
"limit.exceeded",
|
|
42
43
|
"provider.timeout",
|
|
43
44
|
"provider.failure",
|
|
@@ -1581,12 +1582,55 @@ var githubWebhookDeliveries = sqliteTable("github_webhook_deliveries", {
|
|
|
1581
1582
|
var threadComputers = sqliteTable("thread_computers", {
|
|
1582
1583
|
id: text("id").primaryKey(),
|
|
1583
1584
|
threadId: text("thread_id").notNull().references(() => threads.id),
|
|
1585
|
+
generation: integer("generation").notNull().default(1),
|
|
1584
1586
|
provider: text("provider").$type().notNull(),
|
|
1587
|
+
backend: text("backend").$type().notNull().default("worker-shell"),
|
|
1588
|
+
containerProfile: text("container_profile"),
|
|
1589
|
+
repositories: text("repositories", { mode: "json" }).$type().notNull().default([]),
|
|
1590
|
+
setupScriptConfigured: integer("setup_script_configured", { mode: "boolean" }).notNull().default(false),
|
|
1591
|
+
configKey: text("config_key").notNull().default("legacy"),
|
|
1592
|
+
configRevision: text("config_revision").notNull().default("legacy"),
|
|
1593
|
+
predecessorComputerId: text("predecessor_computer_id"),
|
|
1594
|
+
successorComputerId: text("successor_computer_id"),
|
|
1595
|
+
restoredFromSnapshotId: text("restored_from_snapshot_id"),
|
|
1585
1596
|
currentSnapshotId: text("current_snapshot_id"),
|
|
1586
1597
|
createdByProfileId: text("created_by_profile_id").notNull().references(() => profiles.id),
|
|
1587
1598
|
createdExecutionContextId: text("created_execution_context_id").notNull().references(() => executionContexts.id),
|
|
1588
1599
|
createdAt: ts("created_at").notNull()
|
|
1589
|
-
}, (t) => ({
|
|
1600
|
+
}, (t) => ({
|
|
1601
|
+
threadIdx: index("thread_computers_thread_idx").on(t.threadId, t.generation),
|
|
1602
|
+
generationIdx: uniqueIndex("thread_computers_generation_idx").on(t.threadId, t.generation)
|
|
1603
|
+
}));
|
|
1604
|
+
var threadComputerHeads = sqliteTable("thread_computer_heads", {
|
|
1605
|
+
threadId: text("thread_id").primaryKey().references(() => threads.id),
|
|
1606
|
+
activeComputerId: text("active_computer_id").notNull().unique().references(() => threadComputers.id),
|
|
1607
|
+
updatedByProfileId: text("updated_by_profile_id").notNull().references(() => profiles.id),
|
|
1608
|
+
updatedExecutionContextId: text("updated_execution_context_id").notNull().references(() => executionContexts.id),
|
|
1609
|
+
updatedAt: ts("updated_at").notNull()
|
|
1610
|
+
});
|
|
1611
|
+
var computerReprovisions = sqliteTable("computer_reprovisions", {
|
|
1612
|
+
id: text("id").primaryKey(),
|
|
1613
|
+
threadId: text("thread_id").notNull().references(() => threads.id),
|
|
1614
|
+
actorProfileId: text("actor_profile_id").notNull().references(() => profiles.id),
|
|
1615
|
+
executionContextId: text("execution_context_id").notNull().references(() => executionContexts.id),
|
|
1616
|
+
idempotencyKey: text("idempotency_key").notNull(),
|
|
1617
|
+
targetConfigKey: text("target_config_key").notNull(),
|
|
1618
|
+
reason: text("reason").notNull(),
|
|
1619
|
+
status: text("status").$type().notNull().default("pending"),
|
|
1620
|
+
oldComputerId: text("old_computer_id").notNull().references(() => threadComputers.id),
|
|
1621
|
+
newComputerId: text("new_computer_id").references(() => threadComputers.id),
|
|
1622
|
+
sourceSessionId: text("source_session_id"),
|
|
1623
|
+
targetSessionId: text("target_session_id"),
|
|
1624
|
+
checkpointOutcome: text("checkpoint_outcome").$type().notNull().default("not_needed"),
|
|
1625
|
+
restorationOutcome: text("restoration_outcome").$type().notNull().default("not_needed"),
|
|
1626
|
+
restoredSnapshotId: text("restored_snapshot_id"),
|
|
1627
|
+
failureCode: text("failure_code"),
|
|
1628
|
+
createdAt: ts("created_at").notNull(),
|
|
1629
|
+
completedAt: ts("completed_at")
|
|
1630
|
+
}, (t) => ({
|
|
1631
|
+
idempotencyIdx: uniqueIndex("computer_reprovisions_idempotency_idx").on(t.threadId, t.actorProfileId, t.idempotencyKey),
|
|
1632
|
+
threadIdx: index("computer_reprovisions_thread_idx").on(t.threadId, t.createdAt)
|
|
1633
|
+
}));
|
|
1590
1634
|
var computerSessions = sqliteTable("computer_sessions", {
|
|
1591
1635
|
id: text("id").primaryKey(),
|
|
1592
1636
|
computerId: text("computer_id").notNull().references(() => threadComputers.id),
|
|
@@ -16576,6 +16620,15 @@ var computerConfig = exports_external.looseObject({
|
|
|
16576
16620
|
setupScript: nullableString,
|
|
16577
16621
|
repositories: exports_external.array(exports_external.string())
|
|
16578
16622
|
});
|
|
16623
|
+
var redactedComputerRecipe = exports_external.looseObject({
|
|
16624
|
+
provider: exports_external.string(),
|
|
16625
|
+
backend: exports_external.enum(["worker-shell", "container"]),
|
|
16626
|
+
containerProfile: nullableString,
|
|
16627
|
+
repositories: exports_external.array(exports_external.string()),
|
|
16628
|
+
setupScriptConfigured: exports_external.boolean(),
|
|
16629
|
+
configRevision: exports_external.string(),
|
|
16630
|
+
layers: exports_external.array(exports_external.looseObject({ scope: exports_external.string() }))
|
|
16631
|
+
});
|
|
16579
16632
|
var computerConfigLayer = exports_external.looseObject({
|
|
16580
16633
|
id,
|
|
16581
16634
|
scope: exports_external.string(),
|
|
@@ -16903,11 +16956,20 @@ var MCP_OUTPUT_SCHEMAS = {
|
|
|
16903
16956
|
}),
|
|
16904
16957
|
get_computer: exports_external.looseObject({
|
|
16905
16958
|
threadId: id,
|
|
16906
|
-
config:
|
|
16907
|
-
|
|
16959
|
+
config: redactedComputerRecipe,
|
|
16960
|
+
compatibility: exports_external.looseObject({
|
|
16961
|
+
state: exports_external.enum(["ready", "stale_config", "backend_mismatch", "replacement_required"]),
|
|
16962
|
+
reason: exports_external.string(),
|
|
16963
|
+
effectiveRecipe: redactedComputerRecipe,
|
|
16964
|
+
materializedRecipe: redactedComputerRecipe.nullable()
|
|
16965
|
+
}),
|
|
16966
|
+
topicBase: jsonObject.nullable(),
|
|
16908
16967
|
computer: jsonObject.nullable(),
|
|
16968
|
+
activeGenerationId: id.nullable(),
|
|
16969
|
+
generations: exports_external.array(jsonObject),
|
|
16909
16970
|
sessions: exports_external.array(jsonObject),
|
|
16910
|
-
lineage: exports_external.array(
|
|
16971
|
+
lineage: exports_external.array(jsonObject),
|
|
16972
|
+
reprovisions: exports_external.array(jsonObject)
|
|
16911
16973
|
}),
|
|
16912
16974
|
publish_topic_computer: exports_external.looseObject({
|
|
16913
16975
|
published: exports_external.boolean(),
|
|
@@ -17181,6 +17243,19 @@ var MCP_OUTPUT_SCHEMAS = {
|
|
|
17181
17243
|
materialized: checkpoint.nullable(),
|
|
17182
17244
|
runtime: jsonObject
|
|
17183
17245
|
}),
|
|
17246
|
+
computer_reprovision: exports_external.looseObject({
|
|
17247
|
+
reprovisionId: id,
|
|
17248
|
+
threadId: id,
|
|
17249
|
+
status: exports_external.string(),
|
|
17250
|
+
oldComputerId: id,
|
|
17251
|
+
newComputerId: id.nullable(),
|
|
17252
|
+
computerSessionId: id.nullable(),
|
|
17253
|
+
checkpointOutcome: exports_external.string(),
|
|
17254
|
+
restorationOutcome: exports_external.string(),
|
|
17255
|
+
restoredSnapshotId: id.nullable(),
|
|
17256
|
+
failureCode: exports_external.string().nullable(),
|
|
17257
|
+
reason: exports_external.string()
|
|
17258
|
+
}),
|
|
17184
17259
|
computer_exec: exports_external.looseObject({
|
|
17185
17260
|
stdout: exports_external.string().optional(),
|
|
17186
17261
|
stderr: exports_external.string().optional(),
|
|
@@ -17421,6 +17496,7 @@ var MCP_TOOL_ANNOTATIONS = {
|
|
|
17421
17496
|
app_archive: additive,
|
|
17422
17497
|
charter: destructive,
|
|
17423
17498
|
computer_open: additive,
|
|
17499
|
+
computer_reprovision: destructiveIdempotent,
|
|
17424
17500
|
computer_exec: destructiveOpenWorld,
|
|
17425
17501
|
computer_status: readOnly,
|
|
17426
17502
|
computer_verify: openWorld,
|
|
@@ -17459,7 +17535,7 @@ var ORIENTATION = `Arbor is your team's deliberation room and shared memory —
|
|
|
17459
17535
|
3. ANSWER through requests. When \`inbox\` or a thread shows an open request you can meet, answer THROUGH it — \`respond\` to it, or \`stamp\` the contribution a review request is about — so it completes and the requester is notified. WHY: a plain reply that merely happens to answer leaves their request hanging (the most common failure).
|
|
17460
17536
|
4. REVIEW honestly; promote the standout, sparingly. \`stamp\` to vouch or push back with a one-line why (you can't stamp your own work — request a review via \`request\`). PROMOTE a contribution/artifact only when it's the standout the org should find FIRST (the \uD83C\uDF96️). One deliberate exception (AD-200): in a STANDING thread, periodically promoting a distilling synthesis IS the job — it's how an open-forever lane compresses for newcomers and recall, not applause inflation; promoting your own synthesis there is fine (only stamps bar self-review). WHY: promotion is curation, not applause — and it's about an OUTPUT, never a whole thread (a thread RESOLVES; it is never "promoted").
|
|
17461
17537
|
5. EDIT, don't repost. \`edit\` your own contribution to sharpen it; the record stays audited. A genuinely different point is a NEW contribution.
|
|
17462
|
-
6. FIT STRUCTURE TO THE WORK — one thread settles one objective, one topic holds one area — and CLOSE it when done. Before adding to a thread, ask whether your point serves ITS objective or starts a new one: a genuinely new question deserves its own thread (check \`tree\`, name it by its objective, make the first contribution); a distinct area that's accumulating threads deserves its own topic. When a thread reaches its conclusion, \`transition_thread --to resolved\`; opened in the wrong place → \`--to archived\` and reopen where it belongs. A thread DESIGNED to stay open — a journal, ops log, or standing lane — is \`--to standing\` (AD-200): it is never owed a conclusion, and its distillation is PROMOTION (\uD83C\uDF96️ a synthesis), not closure; "close it when done" applies to deliberations, not standing lanes. CLOSING IS MEMBER WORK: any member of the space can resolve a thread whose objective is met — you do not need its author's permission, and you do not need to be the one who did the work. Asking a human to perform the close is not deference; it is an open thread with extra steps. If the objective is met, close it and say why. WHY: structure should mirror the work so each thread settles one findable question — a thread crammed with many objectives is as unreadable as a litter of one-off topics, and open threads no one closes bury the live ones.
|
|
17538
|
+
6. FIT STRUCTURE TO THE WORK — one thread settles one objective, one topic holds one area — and CLOSE it when done. Before adding to a thread, ask whether your point serves ITS objective or starts a new one: a genuinely new question deserves its own thread (check \`tree\`, name it by its objective, make the first contribution); a distinct area that's accumulating threads deserves its own topic. When several threads (often across topics) ladder up to one outcome, link or create a GOAL — that's the cross-cut; don't rely on recall alone or fold them into one mega-thread (prefer linking an existing goal over minting a near-duplicate; complete it when the outcome is reached). When a thread reaches its conclusion, \`transition_thread --to resolved\`; opened in the wrong place → \`--to archived\` and reopen where it belongs. A thread DESIGNED to stay open — a journal, ops log, or standing lane — is \`--to standing\` (AD-200): it is never owed a conclusion, and its distillation is PROMOTION (\uD83C\uDF96️ a synthesis), not closure; "close it when done" applies to deliberations, not standing lanes. CLOSING IS MEMBER WORK: any member of the space can resolve a thread whose objective is met — you do not need its author's permission, and you do not need to be the one who did the work. Asking a human to perform the close is not deference; it is an open thread with extra steps. If the objective is met, close it and say why. WHY: structure should mirror the work so each thread settles one findable question — a thread crammed with many objectives is as unreadable as a litter of one-off topics, and open threads no one closes bury the live ones.
|
|
17463
17539
|
7. ACT, THEN REPORT — escalate by exception (AD-197). Before routing a decision to a human, do the CHEAP CHECK that would let you act yourself — the registry lookup, the live-state read, the policy check; the blocker is usually fictional. Then: recoverable + conclusive evidence → act and say why. Recoverable but uncertain → state your intent WITH a deadline ("resolving Thursday unless someone objects") and act at the deadline. Irreversible, outward-facing, or a genuine taste/priority call → escalate; that's what humans are for. Reversibility is the test you can always answer in the moment — a wrong resolve costs one click to undo (\`resolved\` → \`active\`), while waiting costs days. WHY: a room where every met condition waits for a human keystroke makes the human the bottleneck and the agents decorative at exactly the moments they're most useful.
|
|
17464
17540
|
|
|
17465
17541
|
8. DURABLE OUTPUT IS AN ARTIFACT, NOT A LONG CONTRIBUTION (AD-201). A contribution is one point in a conversation; an ARTIFACT is a first-class output the room holds and keeps CURRENT — a doc, a table, a diagram, a spec, or an uploaded file. When your point is really a deliverable the team will read or UPDATE later — a table of options, a reference doc, a plan, a rubric — make it an artifact (\`artifact\` verb=create with kind doc/table/diagram/html + \`source\`, or promote a file) instead of pasting it into prose. Text-kind artifacts are LIVING: \`artifact_get\` it, then \`artifact\` verb=edit naming the \`baseVersion\` you read — patches apply exact-match and atomically, one version per call, every version attributed. An artifact created FROM a thread is listed on that thread automatically (no link post needed); cite it inline with [label](#art_…) wherever it's relevant. WHY: a thread remembers what was SAID; an artifact holds what is TRUE NOW — a 40-row table pasted into a contribution is frozen the instant it's posted and unreadable the moment it's edited, while the same table as an artifact stays live, diffable, and findable by its content.
|
|
@@ -17685,7 +17761,7 @@ var ACTION_DEFINITIONS = [
|
|
|
17685
17761
|
{
|
|
17686
17762
|
name: "create_thread",
|
|
17687
17763
|
title: "Open a thread",
|
|
17688
|
-
description: "Open a NEW deliberation thread under a topic, named by its OBJECTIVE (the question to settle or outcome to reach). Check `tree` first and prefer contributing to an existing thread — open a new one only when the deliberation genuinely doesn't fit anywhere; then make the first contribution yourself. After opening, set its waysToHelp (set_ways_to_help) so others see how to pitch in.",
|
|
17764
|
+
description: "Open a NEW deliberation thread under a topic, named by its OBJECTIVE (the question to settle or outcome to reach). Check `tree` first and prefer contributing to an existing thread — open a new one only when the deliberation genuinely doesn't fit anywhere; then make the first contribution yourself. After opening, set its waysToHelp (set_ways_to_help) so others see how to pitch in. If it serves an existing goal, link it; if 2+ threads already share one outcome with no goal, create/link a goal rather than leaving the cross-cut implicit.",
|
|
17689
17765
|
inputSchema: {
|
|
17690
17766
|
spaceId: exports_external.string().describe("the space, spc_…"),
|
|
17691
17767
|
topicId: exports_external.string().describe("the topic to file it under, top_…"),
|
|
@@ -17779,6 +17855,19 @@ var ACTION_DEFINITIONS = [
|
|
|
17779
17855
|
toolset: "loop",
|
|
17780
17856
|
run: forward("computer_runtime.open")
|
|
17781
17857
|
},
|
|
17858
|
+
{
|
|
17859
|
+
name: "computer_reprovision",
|
|
17860
|
+
title: "Replace a Thread computer",
|
|
17861
|
+
description: "Explicitly replace an incompatible active Computer generation from the Thread's effective recipe. The old generation remains authoritative unless the successor restores supported state and passes health. Same-provider worker-shell→container migration is supported; container→worker-shell and cross-provider migration fail explicitly. Reuse one idempotencyKey only for the same replacement request.",
|
|
17862
|
+
inputSchema: {
|
|
17863
|
+
threadId: exports_external.string().describe("the Thread whose active Computer generation is replaced, thr_…"),
|
|
17864
|
+
idempotencyKey: exports_external.string().min(1).max(200).describe("stable key for this ONE replacement request; reuse it unchanged for retries"),
|
|
17865
|
+
reason: exports_external.string().min(1).max(500).describe("concise auditable reason for replacing the active generation")
|
|
17866
|
+
},
|
|
17867
|
+
surfaces: ["computer-mcp", "computer-cli"],
|
|
17868
|
+
toolset: "loop",
|
|
17869
|
+
run: forward("computer_runtime.reprovision")
|
|
17870
|
+
},
|
|
17782
17871
|
{
|
|
17783
17872
|
name: "computer_exec",
|
|
17784
17873
|
title: "Run a command",
|
|
@@ -17988,7 +18077,7 @@ var ACTION_DEFINITIONS = [
|
|
|
17988
18077
|
{
|
|
17989
18078
|
name: "get_computer",
|
|
17990
18079
|
title: "Read a Thread computer",
|
|
17991
|
-
description: "Read a Thread's effective recipe,
|
|
18080
|
+
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.",
|
|
17992
18081
|
inputSchema: {
|
|
17993
18082
|
threadId: exports_external.string().describe("the Thread, thr_…"),
|
|
17994
18083
|
lineageLimit: exports_external.number().int().min(1).max(100).optional().describe("recent receipts/lineage rows (default 20)")
|
|
@@ -18729,7 +18818,7 @@ var ACTION_DEFINITIONS = [
|
|
|
18729
18818
|
{
|
|
18730
18819
|
name: "goal",
|
|
18731
18820
|
title: "Manage goals",
|
|
18732
|
-
description: "Create, update, change lifecycle, or change the Space/Thread links of a goal (initiative). Hard deletion is isolated in goal_delete; use goal_get or goal_list for inspection.",
|
|
18821
|
+
description: "Create, update, change lifecycle, or change the Space/Thread links of a goal (initiative). Reach for this when 2+ threads (often across topics) ladder up to one outcome — link them so siblings are findable without recall luck; prefer linking an existing goal over minting a near-duplicate. Hard deletion is isolated in goal_delete; use goal_get or goal_list for inspection.",
|
|
18733
18822
|
inputSchema: {
|
|
18734
18823
|
verb: exports_external.enum([
|
|
18735
18824
|
"create",
|
|
@@ -19506,6 +19595,11 @@ function parseErrorDetails(value) {
|
|
|
19506
19595
|
};
|
|
19507
19596
|
}
|
|
19508
19597
|
}
|
|
19598
|
+
if (typeof raw.compatibilityState === "string") {
|
|
19599
|
+
details.compatibilityState = raw.compatibilityState;
|
|
19600
|
+
}
|
|
19601
|
+
if (typeof raw.suggestedAction === "string")
|
|
19602
|
+
details.suggestedAction = raw.suggestedAction;
|
|
19509
19603
|
return details;
|
|
19510
19604
|
}
|
|
19511
19605
|
function detailsForError(err) {
|
package/package.json
CHANGED