@lambdacurry/arbor 0.13.7 → 0.13.9
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 +101 -21
- package/package.json +1 -1
package/dist/arbor.js
CHANGED
|
@@ -1847,7 +1847,7 @@ var apps = sqliteTable("apps", {
|
|
|
1847
1847
|
stateMode: text("state_mode").$type().notNull(),
|
|
1848
1848
|
stateIdentity: text("state_identity").notNull(),
|
|
1849
1849
|
stateGeneration: integer("state_generation").notNull().default(0),
|
|
1850
|
-
|
|
1850
|
+
pendingStateOperationId: text("pending_state_reset_id"),
|
|
1851
1851
|
currentStateSchemaVersion: integer("current_state_schema_version").notNull().default(0),
|
|
1852
1852
|
deploymentRevision: integer("deployment_revision").notNull().default(0),
|
|
1853
1853
|
metadataRevision: integer("metadata_revision").notNull().default(0),
|
|
@@ -1897,6 +1897,19 @@ var appStateResets = sqliteTable("app_state_resets", {
|
|
|
1897
1897
|
activeDeploymentId: text("active_deployment_id"),
|
|
1898
1898
|
deploymentRevision: integer("deployment_revision"),
|
|
1899
1899
|
targetStateSchemaVersion: integer("target_state_schema_version"),
|
|
1900
|
+
recoveryBookmark: text("recovery_bookmark"),
|
|
1901
|
+
recoveryExpiresAt: ts("recovery_expires_at"),
|
|
1902
|
+
previousStateSchemaVersion: integer("previous_state_schema_version"),
|
|
1903
|
+
restoreIdempotencyKey: text("restore_idempotency_key"),
|
|
1904
|
+
restoredByProfileId: text("restored_by_profile_id").references(() => profiles.id),
|
|
1905
|
+
restoreExecutionContextId: text("restore_execution_context_id").references(() => executionContexts.id),
|
|
1906
|
+
restoreProviderReceipt: text("restore_provider_receipt", {
|
|
1907
|
+
mode: "json"
|
|
1908
|
+
}).$type(),
|
|
1909
|
+
restoreFromGeneration: integer("restore_from_generation"),
|
|
1910
|
+
restoreToGeneration: integer("restore_to_generation"),
|
|
1911
|
+
restoreRequestedAt: ts("restore_requested_at"),
|
|
1912
|
+
restoredAt: ts("restored_at"),
|
|
1900
1913
|
createdAt: ts("created_at").notNull(),
|
|
1901
1914
|
completedAt: ts("completed_at")
|
|
1902
1915
|
}, (t) => ({
|
|
@@ -16983,6 +16996,7 @@ var MCP_OUTPUT_SCHEMAS = {
|
|
|
16983
16996
|
}),
|
|
16984
16997
|
app_set_access: app2,
|
|
16985
16998
|
app_reset_state: exports_external.looseObject({ reset: jsonObject, replayed: exports_external.boolean() }),
|
|
16999
|
+
app_restore_state: exports_external.looseObject({ reset: jsonObject, replayed: exports_external.boolean() }),
|
|
16986
17000
|
app_archive: app2,
|
|
16987
17001
|
charter: exports_external.looseObject({
|
|
16988
17002
|
ok: exports_external.boolean().optional(),
|
|
@@ -17231,6 +17245,7 @@ var MCP_TOOL_ANNOTATIONS = {
|
|
|
17231
17245
|
app_rollback: additive,
|
|
17232
17246
|
app_set_access: additive,
|
|
17233
17247
|
app_reset_state: destructiveIdempotent,
|
|
17248
|
+
app_restore_state: destructiveIdempotent,
|
|
17234
17249
|
app_archive: additive,
|
|
17235
17250
|
charter: destructive,
|
|
17236
17251
|
computer_open: additive,
|
|
@@ -18874,7 +18889,7 @@ var ACTION_DEFINITIONS = [
|
|
|
18874
18889
|
path: exports_external.string().min(1).max(2048).describe("relative App path beginning with /; may include a query string"),
|
|
18875
18890
|
method: exports_external.enum(["GET", "HEAD"]).optional().describe("safe read method; default GET")
|
|
18876
18891
|
},
|
|
18877
|
-
surfaces: ["mcp"],
|
|
18892
|
+
surfaces: ["mcp", "cli"],
|
|
18878
18893
|
toolset: "apps",
|
|
18879
18894
|
run: forward("app.fetch")
|
|
18880
18895
|
},
|
|
@@ -18886,11 +18901,11 @@ var ACTION_DEFINITIONS = [
|
|
|
18886
18901
|
appId: exports_external.string().describe("target App, app_…"),
|
|
18887
18902
|
path: exports_external.string().min(1).max(2048).describe("relative App path beginning with /; may include a query string"),
|
|
18888
18903
|
method: exports_external.enum(["POST", "PUT", "PATCH", "DELETE"]).describe("mutating HTTP method"),
|
|
18889
|
-
json: exports_external.json().optional().describe("JSON request value; mutually exclusive with body and sets application/json"),
|
|
18904
|
+
json: exports_external.json().optional().describe("JSON request value; mutually exclusive with body and sets application/json. On the CLI, pass serialized JSON after the command as --json '<value>'"),
|
|
18890
18905
|
body: exports_external.string().optional().describe("UTF-8 request body; mutually exclusive with json"),
|
|
18891
18906
|
contentType: exports_external.string().max(160).optional().describe("body media type; allowed only with body, default text/plain; charset=utf-8")
|
|
18892
18907
|
},
|
|
18893
|
-
surfaces: ["mcp"],
|
|
18908
|
+
surfaces: ["mcp", "cli"],
|
|
18894
18909
|
toolset: "apps",
|
|
18895
18910
|
run: forward("app.request")
|
|
18896
18911
|
},
|
|
@@ -18936,7 +18951,7 @@ var ACTION_DEFINITIONS = [
|
|
|
18936
18951
|
{
|
|
18937
18952
|
name: "app_reset_state",
|
|
18938
18953
|
title: "Reset durable App state",
|
|
18939
|
-
description: "
|
|
18954
|
+
description: "Delete one durable App facet's isolated SQLite database as an explicit attributed transition after capturing a Cloudflare recovery point valid for 30 days. Only the App creator or an Org owner/admin may do this; deploying or rolling back never does. Read app_get first, pass its expectedGeneration, and keep the same idempotencyKey across retries. A provider interruption leaves a visible pending intent that the same call resumes; do not change release or archive while pending.",
|
|
18940
18955
|
inputSchema: {
|
|
18941
18956
|
appId: exports_external.string().describe("durable App, app_…"),
|
|
18942
18957
|
expectedGeneration: exports_external.number().int().min(0).describe("state generation from app_get"),
|
|
@@ -18946,6 +18961,20 @@ var ACTION_DEFINITIONS = [
|
|
|
18946
18961
|
toolset: "apps",
|
|
18947
18962
|
run: forward("app.reset_state")
|
|
18948
18963
|
},
|
|
18964
|
+
{
|
|
18965
|
+
name: "app_restore_state",
|
|
18966
|
+
title: "Restore durable App state",
|
|
18967
|
+
description: "Restore the latest completed durable-state reset from its automatic Cloudflare recovery point, discarding state written after that reset. Recovery is available for 30 days, only while that reset remains latest and its active release has not changed. Only the App creator or an Org owner/admin may do this. Read app_get first, pass the reset id and current generation, and keep the same idempotencyKey across retries.",
|
|
18968
|
+
inputSchema: {
|
|
18969
|
+
appId: exports_external.string().describe("durable App, app_…"),
|
|
18970
|
+
resetId: exports_external.string().describe("latest recoverable reset from app_get, rst_…"),
|
|
18971
|
+
expectedGeneration: exports_external.number().int().min(0).describe("state generation from app_get"),
|
|
18972
|
+
idempotencyKey: exports_external.string().min(1).max(200).describe("stable key for this one deliberate recovery")
|
|
18973
|
+
},
|
|
18974
|
+
surfaces: ["mcp", "cli"],
|
|
18975
|
+
toolset: "apps",
|
|
18976
|
+
run: forward("app.restore_state")
|
|
18977
|
+
},
|
|
18949
18978
|
{
|
|
18950
18979
|
name: "app_archive",
|
|
18951
18980
|
title: "Archive an App",
|
|
@@ -19472,6 +19501,17 @@ function commandWords(action) {
|
|
|
19472
19501
|
var CLI_ACTIONS = ACTIONS.filter((a) => a.surfaces.includes("cli") || a.surfaces.includes("computer-cli"));
|
|
19473
19502
|
var BY_COMMAND = new Map(CLI_ACTIONS.map((a) => [commandWords(a), a]));
|
|
19474
19503
|
var MAX_WORDS = Math.max(1, ...CLI_ACTIONS.map((a) => commandWords(a).split(" ").length));
|
|
19504
|
+
var POSITIONAL_FIELDS = {
|
|
19505
|
+
app_fetch: ["appId", "path"],
|
|
19506
|
+
app_request: ["appId", "path"]
|
|
19507
|
+
};
|
|
19508
|
+
function positionalSpecs(action) {
|
|
19509
|
+
const fields = POSITIONAL_FIELDS[action.name];
|
|
19510
|
+
if (!fields)
|
|
19511
|
+
return [];
|
|
19512
|
+
const specs = flagsForSchema(action.inputSchema);
|
|
19513
|
+
return fields.map((field) => specs.find((spec) => spec.field === field));
|
|
19514
|
+
}
|
|
19475
19515
|
var KNOWN_MISREACHES = [
|
|
19476
19516
|
{ tried: "thread list", use: "tree --depth threads", why: "threads are listed by the tree" },
|
|
19477
19517
|
{ tried: "threads", use: "tree --depth threads", why: "threads are listed by the tree" },
|
|
@@ -19530,12 +19570,15 @@ function toolNameAlias(action) {
|
|
|
19530
19570
|
return action.name.includes("_") ? action.name : "";
|
|
19531
19571
|
}
|
|
19532
19572
|
function helpLine(action) {
|
|
19533
|
-
const
|
|
19573
|
+
const positionals = positionalSpecs(action);
|
|
19574
|
+
const positionalFlags = new Set(positionals.map((spec) => spec.flag));
|
|
19575
|
+
const args = positionals.map((spec) => ` <${spec.field}>`).join("");
|
|
19576
|
+
const flags = flagsForSchema(action.inputSchema).filter((spec) => !positionalFlags.has(spec.flag)).map((f) => {
|
|
19534
19577
|
const token = f.kind === "boolean" ? `--${f.flag}` : `--${f.flag} <>`;
|
|
19535
19578
|
return f.required ? token : `[${token}]`;
|
|
19536
19579
|
}).join(" ");
|
|
19537
19580
|
const alias2 = toolNameAlias(action);
|
|
19538
|
-
const head = ` ${commandWords(action)}${alias2 ? ` (${alias2})` : ""}${flags ? ` ${flags}` : ""}`;
|
|
19581
|
+
const head = ` ${commandWords(action)}${alias2 ? ` (${alias2})` : ""}${args}${flags ? ` ${flags}` : ""}`;
|
|
19539
19582
|
return `${head}
|
|
19540
19583
|
${action.description}`;
|
|
19541
19584
|
}
|
|
@@ -19547,12 +19590,15 @@ function commandHelp(positionals) {
|
|
|
19547
19590
|
return;
|
|
19548
19591
|
const { action } = match;
|
|
19549
19592
|
const specs = flagsForSchema(action.inputSchema);
|
|
19550
|
-
const
|
|
19551
|
-
const
|
|
19593
|
+
const explicitPositionals = positionalSpecs(action);
|
|
19594
|
+
const primary = explicitPositionals.length === 0 ? primaryPositionalField(action.inputSchema) : undefined;
|
|
19595
|
+
const positionalFlags = new Set(explicitPositionals.map((spec) => spec.flag));
|
|
19596
|
+
const usageFlags = specs.filter((spec) => !positionalFlags.has(spec.flag)).map((f) => {
|
|
19552
19597
|
const token = f.kind === "boolean" ? `--${f.flag}` : `--${f.flag} <${f.kind}>`;
|
|
19553
19598
|
return f.required ? token : `[${token}]`;
|
|
19554
19599
|
}).join(" ");
|
|
19555
|
-
const
|
|
19600
|
+
const explicitArgs = explicitPositionals.map((spec) => ` <${spec.field}>`).join("");
|
|
19601
|
+
const usage = `Usage: arbor ${commandWords(action)}${explicitArgs}${primary ? ` [<${primary.field}>]` : ""}${usageFlags ? ` ${usageFlags}` : ""}`;
|
|
19556
19602
|
const lines = specs.map((f) => {
|
|
19557
19603
|
const req = f.required ? "required" : "optional";
|
|
19558
19604
|
const fileNote = f.kind === "string" ? ` (or --${f.flag}-file <path|->)` : "";
|
|
@@ -19565,6 +19611,9 @@ function commandHelp(positionals) {
|
|
|
19565
19611
|
const primaryNote = primary ? `
|
|
19566
19612
|
|
|
19567
19613
|
A single bare argument fills --${primary.flag} (e.g. \`arbor ${commandWords(action)} <${primary.field}>\`).` : "";
|
|
19614
|
+
const explicitNote = explicitPositionals.length > 0 ? `
|
|
19615
|
+
|
|
19616
|
+
Bare arguments fill ${explicitPositionals.map((spec) => `--${spec.flag}`).join(" then ")}; the equivalent flags remain accepted.` : "";
|
|
19568
19617
|
const alias2 = toolNameAlias(action);
|
|
19569
19618
|
const aliasNote = alias2 ? `
|
|
19570
19619
|
|
|
@@ -19575,7 +19624,7 @@ Alias: \`arbor ${alias2}\` (the tool-name form) resolves to this same command.`
|
|
|
19575
19624
|
${usage}
|
|
19576
19625
|
|
|
19577
19626
|
${lines.join(`
|
|
19578
|
-
`)}${primaryNote}${aliasNote}
|
|
19627
|
+
`)}${primaryNote}${explicitNote}${aliasNote}
|
|
19579
19628
|
`;
|
|
19580
19629
|
}
|
|
19581
19630
|
function commandCatalog() {
|
|
@@ -19601,17 +19650,21 @@ async function runObjectVerb(positionals, flags, ctx) {
|
|
|
19601
19650
|
const { action, words } = match;
|
|
19602
19651
|
const extras = positionals.slice(words);
|
|
19603
19652
|
if (extras.length > 0) {
|
|
19604
|
-
const
|
|
19605
|
-
|
|
19653
|
+
const explicitPositionals = positionalSpecs(action);
|
|
19654
|
+
const positionalTargets = explicitPositionals.length > 0 ? explicitPositionals : [primaryPositionalField(action.inputSchema)].filter((spec) => spec !== undefined);
|
|
19655
|
+
if (positionalTargets.length === 0) {
|
|
19606
19656
|
throw new UsageError(`unexpected argument: ${extras[0]} (\`${commandWords(action)}\` takes no positional — use flags)`);
|
|
19607
19657
|
}
|
|
19608
|
-
if (extras.length >
|
|
19609
|
-
throw new UsageError(`too many arguments: \`${commandWords(action)}\` takes one positional
|
|
19658
|
+
if (extras.length > positionalTargets.length) {
|
|
19659
|
+
throw new UsageError(`too many arguments: \`${commandWords(action)}\` takes ${positionalTargets.length === 1 ? "one positional" : `${positionalTargets.length} positionals`}; pass the rest as flags`);
|
|
19610
19660
|
}
|
|
19611
|
-
|
|
19612
|
-
|
|
19661
|
+
for (const [index2, value] of extras.entries()) {
|
|
19662
|
+
const target = positionalTargets[index2];
|
|
19663
|
+
if (flags[target.flag] !== undefined || flags[`${target.flag}-file`] !== undefined) {
|
|
19664
|
+
throw new UsageError(`pass --${target.flag} either as a flag or as the positional argument, not both`);
|
|
19665
|
+
}
|
|
19666
|
+
flags[target.flag] = value;
|
|
19613
19667
|
}
|
|
19614
|
-
flags[primary.flag] = extras[0];
|
|
19615
19668
|
}
|
|
19616
19669
|
const accepted = acceptedFlags(action.inputSchema);
|
|
19617
19670
|
const unknown2 = Object.keys(flags).filter((f) => !accepted.has(f) && !RESERVED_FLAGS.has(f));
|
|
@@ -19619,7 +19672,27 @@ async function runObjectVerb(positionals, flags, ctx) {
|
|
|
19619
19672
|
const hints = unknown2.map((f) => listFileHint(action, f)).filter(Boolean);
|
|
19620
19673
|
throw new UsageError(`unknown flag${unknown2.length > 1 ? "s" : ""}: ${unknown2.map((f) => `--${f}`).join(", ")}${hints.length > 0 ? ` — ${hints.join("; ")}` : ""}`);
|
|
19621
19674
|
}
|
|
19622
|
-
const
|
|
19675
|
+
const inputFlags = { ...flags };
|
|
19676
|
+
if (action.name === "app_request" && lastValue(inputFlags.json) === true) {
|
|
19677
|
+
delete inputFlags.json;
|
|
19678
|
+
}
|
|
19679
|
+
const input = buildInput(action.inputSchema, inputFlags, commandWords(action));
|
|
19680
|
+
if (action.name === "app_request" && input.json !== undefined) {
|
|
19681
|
+
if (input.body !== undefined) {
|
|
19682
|
+
throw new UsageError("--json and --body are mutually exclusive", {
|
|
19683
|
+
reason: "validation.invalid_value",
|
|
19684
|
+
field: "body"
|
|
19685
|
+
});
|
|
19686
|
+
}
|
|
19687
|
+
try {
|
|
19688
|
+
input.json = JSON.parse(String(input.json));
|
|
19689
|
+
} catch {
|
|
19690
|
+
throw new UsageError("--json expects a valid serialized JSON value", {
|
|
19691
|
+
reason: "validation.invalid_value",
|
|
19692
|
+
field: "json"
|
|
19693
|
+
});
|
|
19694
|
+
}
|
|
19695
|
+
}
|
|
19623
19696
|
if (action.name === "agent_register") {
|
|
19624
19697
|
advise(`Agent registered. Save its apiKey now — it is shown only once:
|
|
19625
19698
|
`, ctx);
|
|
@@ -19732,6 +19805,11 @@ async function login(opts) {
|
|
|
19732
19805
|
}
|
|
19733
19806
|
|
|
19734
19807
|
// src/index.ts
|
|
19808
|
+
function resolveCommandOutput(positionals, flags, opts) {
|
|
19809
|
+
const actionName = matchCommand(positionals)?.action.name;
|
|
19810
|
+
const resolved = resolveOutput(flags, opts);
|
|
19811
|
+
return actionName === "app_fetch" || actionName === "app_request" ? { ...resolved, json: true, quiet: true } : resolved;
|
|
19812
|
+
}
|
|
19735
19813
|
function setFlag(flags, key, value) {
|
|
19736
19814
|
const prev = flags[key];
|
|
19737
19815
|
if (prev === undefined || typeof value === "boolean" || typeof prev === "boolean") {
|
|
@@ -19748,9 +19826,11 @@ function parseArgs(argv) {
|
|
|
19748
19826
|
if (arg.startsWith("--")) {
|
|
19749
19827
|
const body = arg.slice(2);
|
|
19750
19828
|
const eq = body.indexOf("=");
|
|
19829
|
+
const appRequestWords = positionals[0] === "app" && positionals[1] === "request" ? 2 : positionals[0] === "app_request" ? 1 : 0;
|
|
19830
|
+
const hasAppRequestTarget = appRequestWords > 0 && (positionals.length >= appRequestWords + 2 || flags["app-id"] !== undefined && flags.path !== undefined);
|
|
19751
19831
|
if (eq !== -1) {
|
|
19752
19832
|
setFlag(flags, body.slice(0, eq), body.slice(eq + 1));
|
|
19753
|
-
} else if (!GLOBAL_BOOLEAN_FLAGS.has(body) && i + 1 < argv.length && !argv[i + 1].startsWith("--")) {
|
|
19833
|
+
} else if ((!GLOBAL_BOOLEAN_FLAGS.has(body) || body === "json" && hasAppRequestTarget) && i + 1 < argv.length && !argv[i + 1].startsWith("--")) {
|
|
19754
19834
|
setFlag(flags, body, argv[++i]);
|
|
19755
19835
|
} else {
|
|
19756
19836
|
setFlag(flags, body, true);
|
|
@@ -19880,7 +19960,7 @@ async function renderHealth(ctx) {
|
|
|
19880
19960
|
}
|
|
19881
19961
|
async function main() {
|
|
19882
19962
|
const { positionals, flags } = parseArgs(process.argv.slice(2));
|
|
19883
|
-
const ctx =
|
|
19963
|
+
const ctx = resolveCommandOutput(positionals, flags);
|
|
19884
19964
|
const [cmd] = positionals;
|
|
19885
19965
|
try {
|
|
19886
19966
|
if (flags.version !== undefined && positionals.length === 0 || cmd === "version") {
|
package/package.json
CHANGED