@lambdacurry/arbor 0.21.9 → 0.21.11
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 +140 -30
- package/package.json +1 -1
package/dist/arbor.js
CHANGED
|
@@ -17207,6 +17207,17 @@ function date4(params) {
|
|
|
17207
17207
|
|
|
17208
17208
|
// ../../node_modules/.pnpm/zod@4.4.3/node_modules/zod/v4/classic/external.js
|
|
17209
17209
|
config(en_default());
|
|
17210
|
+
// ../actions/src/external-read-defaults.ts
|
|
17211
|
+
var EXTERNAL_DEFAULT_PAGE_SIZE = 50;
|
|
17212
|
+
var EXTERNAL_DEFAULT_CONTRIB_LIMIT = 50;
|
|
17213
|
+
var EXTERNAL_DEFAULT_THREAD_VIEW = "compact";
|
|
17214
|
+
var EXTERNAL_READ_DEFAULTS_BY_OPERATION = {};
|
|
17215
|
+
function recordExternalReadDefaults(operation, defaults) {
|
|
17216
|
+
if (!operation || !defaults)
|
|
17217
|
+
return;
|
|
17218
|
+
EXTERNAL_READ_DEFAULTS_BY_OPERATION[operation] = defaults;
|
|
17219
|
+
}
|
|
17220
|
+
|
|
17210
17221
|
// ../actions/src/output-schemas.ts
|
|
17211
17222
|
var id = exports_external.string();
|
|
17212
17223
|
var timestamp = exports_external.string();
|
|
@@ -18365,7 +18376,9 @@ var MCP_OUTPUT_SCHEMAS = {
|
|
|
18365
18376
|
exitCode: exports_external.number().optional(),
|
|
18366
18377
|
processId: exports_external.string().optional(),
|
|
18367
18378
|
status: exports_external.string().optional(),
|
|
18368
|
-
cwd: exports_external.string().optional()
|
|
18379
|
+
cwd: exports_external.string().optional(),
|
|
18380
|
+
execution: exports_external.enum(["completed", "running"]).optional(),
|
|
18381
|
+
nextAction: exports_external.literal("computer_process_read").optional()
|
|
18369
18382
|
}),
|
|
18370
18383
|
computer_process_read: exports_external.looseObject({
|
|
18371
18384
|
status: exports_external.string(),
|
|
@@ -18505,7 +18518,6 @@ var MCP_OUTPUT_SCHEMAS = {
|
|
|
18505
18518
|
function outputSchemaFor(actionName) {
|
|
18506
18519
|
return MCP_OUTPUT_SCHEMAS[actionName];
|
|
18507
18520
|
}
|
|
18508
|
-
|
|
18509
18521
|
// ../actions/src/output-shaping.ts
|
|
18510
18522
|
function record2(value) {
|
|
18511
18523
|
return value !== null && typeof value === "object" && !Array.isArray(value) ? value : null;
|
|
@@ -18682,6 +18694,8 @@ var OUTPUT_SHAPERS = {
|
|
|
18682
18694
|
["exitCode", result.exitCode],
|
|
18683
18695
|
["processId", result.processId],
|
|
18684
18696
|
["status", result.status],
|
|
18697
|
+
["execution", result.execution],
|
|
18698
|
+
["nextAction", result.nextAction],
|
|
18685
18699
|
["cwd", input.cwd === undefined ? result.cwd : undefined]
|
|
18686
18700
|
]),
|
|
18687
18701
|
computer_process_read: (result) => defined([
|
|
@@ -18906,7 +18920,9 @@ Arbor's MCP is the collaboration and durable-knowledge surface. Configure, autho
|
|
|
18906
18920
|
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.
|
|
18907
18921
|
|
|
18908
18922
|
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.`;
|
|
18909
|
-
var COMPUTER_ORIENTATION = `
|
|
18923
|
+
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, take \`processId\` and poll \`computer_process_read\`. Do not chain \`pnpm test && pnpm build\` in one exec; split steps or pass \`background:true\`. The CLI waits on the same handle unless \`--no-wait\`.
|
|
18924
|
+
|
|
18925
|
+
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.
|
|
18910
18926
|
|
|
18911
18927
|
${ARBOR_FEEDBACK_GUIDANCE}
|
|
18912
18928
|
|
|
@@ -18929,7 +18945,15 @@ function isProseList(schema) {
|
|
|
18929
18945
|
return PROSE_LISTS.has(schema);
|
|
18930
18946
|
}
|
|
18931
18947
|
function forward(operation) {
|
|
18932
|
-
|
|
18948
|
+
const run = (ex, input) => ex.call(operation, input);
|
|
18949
|
+
run.operation = operation;
|
|
18950
|
+
return run;
|
|
18951
|
+
}
|
|
18952
|
+
function forwardedOperation(run) {
|
|
18953
|
+
if (!("operation" in run))
|
|
18954
|
+
return;
|
|
18955
|
+
const value = run.operation;
|
|
18956
|
+
return typeof value === "string" ? value : undefined;
|
|
18933
18957
|
}
|
|
18934
18958
|
function dispatch(map2, reshape) {
|
|
18935
18959
|
return (ex, input) => {
|
|
@@ -18985,8 +19009,9 @@ function runAdminFeedback(ex, input) {
|
|
|
18985
19009
|
}
|
|
18986
19010
|
var NOTIFICATION_TRIAGE_DESCRIPTION = "READ ONLY: List your awareness feed newest first with unseen count and derived triage class: `settled-context` = settled Thread context; `owed-by-me` = an open request pointing to `inbox`; `judgment-available` = live engagement inviting judgment; `closed-loop` = your request completed; `room-motion` = ambient activity. Notifications are FYI, not a second obligation surface: `inbox` alone contains work owed by you; this cannot mark notifications read or modify inbox obligations.";
|
|
18987
19011
|
var PAGINATION_INPUT = {
|
|
18988
|
-
limit: exports_external.number().int().min(1).optional().describe(
|
|
18989
|
-
cursor: exports_external.string().optional().describe("opaque cursor from a prior response's nextCursor (use with --limit)")
|
|
19012
|
+
limit: exports_external.number().int().min(1).optional().describe(`max items to return. MCP/CLI/API default to ${EXTERNAL_DEFAULT_PAGE_SIZE} and return nextCursor when more remain; pass all=true/--all for the complete list. In-process web omit is still a compatibility full read`),
|
|
19013
|
+
cursor: exports_external.string().optional().describe("opaque cursor from a prior response's nextCursor (use with --limit)"),
|
|
19014
|
+
all: exports_external.boolean().optional().describe("explicit complete retrieval — skip the bounded default page. Prefer limit+cursor unless you need the whole collection")
|
|
18990
19015
|
};
|
|
18991
19016
|
var LIVE_PREVIEW_CONFIG_INPUT = {
|
|
18992
19017
|
livePreview: exports_external.object({
|
|
@@ -19612,14 +19637,14 @@ var ACTION_DEFINITIONS = [
|
|
|
19612
19637
|
{
|
|
19613
19638
|
name: "computer_exec",
|
|
19614
19639
|
title: "Run a command",
|
|
19615
|
-
description: "Run one bounded shell operation in a parent Computer or Run with ambient GitHub authorization for connected humans.
|
|
19640
|
+
description: "Run one bounded shell operation in a parent Computer or Run with ambient GitHub authorization for connected humans. A long command returns processId if still running — poll computer_process_read (background:true skips the wait; timeout kills the process); after a missed isolated response use computer_run_receipt.operations[].operationId with computer_process_read instead of repeating the mutation.",
|
|
19616
19641
|
inputSchema: {
|
|
19617
19642
|
computerSessionId: exports_external.string().optional().describe("the computerSessionId returned by computer_open, cms_…; required unless runId is supplied"),
|
|
19618
19643
|
command: exports_external.string().min(1).describe("the shell command to run"),
|
|
19619
19644
|
runId: exports_external.string().optional().describe("route this command according to this Run execution placement, run_… (from computer_run_start)"),
|
|
19620
19645
|
cwd: exports_external.string().optional().describe("working directory under /workspace, or under the run; omit to use defaultCwd"),
|
|
19621
|
-
timeout: exports_external.number().int().min(1000).max(1800000).optional().describe("
|
|
19622
|
-
background: exports_external.boolean().optional().describe("start
|
|
19646
|
+
timeout: exports_external.number().int().min(1000).max(1800000).optional().describe("process kill deadline in milliseconds, from 1,000 through 1,800,000 — not the RPC hold"),
|
|
19647
|
+
background: exports_external.boolean().optional().describe("start the process and return immediately without the short RPC wait"),
|
|
19623
19648
|
activityLabel: exports_external.string().min(1).max(COMPUTER_RUN_ACTIVITY_LABEL_MAX).optional().describe("short human-readable label for run-scoped background work; Arbor records this label instead of the raw command or output"),
|
|
19624
19649
|
activityKind: exports_external.literal("verification").optional().describe("mark a labeled run-scoped background command as a verification check; its provider-observed terminal result is recorded as verification.finished"),
|
|
19625
19650
|
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")
|
|
@@ -20210,14 +20235,19 @@ var ACTION_DEFINITIONS = [
|
|
|
20210
20235
|
{
|
|
20211
20236
|
name: "thread_get",
|
|
20212
20237
|
title: "Read a thread",
|
|
20213
|
-
description: "READ ONLY: Read one Thread
|
|
20238
|
+
description: "READ ONLY: Read one Thread as compact current context (distillate, requests, artifacts, recent tail, cursored unchanged checks) — not the durable transcript; pass view=full to page history (contribLimit default 50) or all=true for the complete transcript. Read it before contributing so you can answer open requests correctly.",
|
|
20214
20239
|
inputSchema: {
|
|
20215
20240
|
threadId: exports_external.string().describe("the thread id, e.g. thr_…"),
|
|
20216
|
-
view: exports_external.enum(["full", "compact"]).optional().describe("
|
|
20241
|
+
view: exports_external.enum(["full", "compact"]).optional().describe("MCP/CLI/API default compact = bounded decision-ready context; full = transcript page"),
|
|
20217
20242
|
cursor: exports_external.string().optional().describe("compact reads only: cursor from the previous compact response; if context is unchanged the response collapses to a tiny unchanged envelope"),
|
|
20218
20243
|
recentLimit: exports_external.number().int().min(1).max(20).optional().describe("compact reads only: latest contributions to include (default 6, max 20)"),
|
|
20219
|
-
contribLimit: exports_external.number().int().positive().optional().describe(
|
|
20220
|
-
contribCursor: exports_external.string().optional().describe("full reads only: continuation cursor from a previous page's contributionPage.nextCursor")
|
|
20244
|
+
contribLimit: exports_external.number().int().positive().optional().describe(`full reads only: max contributions to return (AD-151 keyset paging). MCP/CLI/API default to ${EXTERNAL_DEFAULT_CONTRIB_LIMIT}; pass all=true for the whole thread`),
|
|
20245
|
+
contribCursor: exports_external.string().optional().describe("full reads only: continuation cursor from a previous page's contributionPage.nextCursor"),
|
|
20246
|
+
all: exports_external.boolean().optional().describe("explicit complete transcript on view=full — skip the bounded contribLimit. Prefer contribLimit+contribCursor unless you need every contribution")
|
|
20247
|
+
},
|
|
20248
|
+
externalReadDefaults: {
|
|
20249
|
+
view: EXTERNAL_DEFAULT_THREAD_VIEW,
|
|
20250
|
+
contribLimit: EXTERNAL_DEFAULT_CONTRIB_LIMIT
|
|
20221
20251
|
},
|
|
20222
20252
|
surfaces: ["mcp", "cli"],
|
|
20223
20253
|
toolset: "loop",
|
|
@@ -21327,15 +21357,17 @@ var ACTIONS = ACTION_DEFINITIONS.map((action) => {
|
|
|
21327
21357
|
if (action.requiresCapability && !action.surfaces.includes("mcp")) {
|
|
21328
21358
|
throw new Error(`${action.name}: requiresCapability is an MCP catalog gate`);
|
|
21329
21359
|
}
|
|
21360
|
+
const externalReadDefaults = action.inputSchema.limit === PAGINATION_INPUT.limit ? { ...action.externalReadDefaults, limit: EXTERNAL_DEFAULT_PAGE_SIZE } : action.externalReadDefaults;
|
|
21361
|
+
recordExternalReadDefaults(forwardedOperation(action.run), externalReadDefaults);
|
|
21330
21362
|
if (!action.surfaces.some((surface) => surface === "mcp" || surface === "computer-mcp")) {
|
|
21331
|
-
return action;
|
|
21363
|
+
return externalReadDefaults ? { ...action, externalReadDefaults } : action;
|
|
21332
21364
|
}
|
|
21333
21365
|
const outputSchema = outputSchemaFor(action.name);
|
|
21334
21366
|
if (!outputSchema)
|
|
21335
21367
|
throw new Error(`${action.name}: MCP action is missing an output schema`);
|
|
21336
21368
|
const annotations = mcpAnnotationsFor(action.name);
|
|
21337
21369
|
const description = annotations.readOnlyHint && !action.description.startsWith("READ ONLY") ? `READ ONLY: ${action.description}` : action.description;
|
|
21338
|
-
return { ...action, description, outputSchema, annotations };
|
|
21370
|
+
return { ...action, externalReadDefaults, description, outputSchema, annotations };
|
|
21339
21371
|
});
|
|
21340
21372
|
|
|
21341
21373
|
// src/config.ts
|
|
@@ -21633,7 +21665,8 @@ var GLOBAL_BOOLEAN_FLAGS = new Set([
|
|
|
21633
21665
|
"json",
|
|
21634
21666
|
"quiet",
|
|
21635
21667
|
"no-quiet",
|
|
21636
|
-
"help"
|
|
21668
|
+
"help",
|
|
21669
|
+
"no-wait"
|
|
21637
21670
|
]);
|
|
21638
21671
|
var RESERVED_FLAGS = new Set([
|
|
21639
21672
|
...GLOBAL_BOOLEAN_FLAGS,
|
|
@@ -21725,6 +21758,66 @@ function emitDual(data, human, action, ctx) {
|
|
|
21725
21758
|
process.stdout.write(human);
|
|
21726
21759
|
}
|
|
21727
21760
|
|
|
21761
|
+
// src/computer-exec-wait.ts
|
|
21762
|
+
var DEFAULT_PROCESS_DEADLINE_MS = 1800000;
|
|
21763
|
+
var POLL_MS = 400;
|
|
21764
|
+
var processRead = ACTIONS.find((action) => action.name === "computer_process_read");
|
|
21765
|
+
function record3(value) {
|
|
21766
|
+
return value !== null && typeof value === "object" && !Array.isArray(value) ? value : null;
|
|
21767
|
+
}
|
|
21768
|
+
function isRunning(value) {
|
|
21769
|
+
const status = typeof value.status === "string" ? value.status.toLowerCase() : "";
|
|
21770
|
+
if (value.done === false)
|
|
21771
|
+
return true;
|
|
21772
|
+
if (status === "running" || status === "started" || status === "starting")
|
|
21773
|
+
return true;
|
|
21774
|
+
if (value.done === true)
|
|
21775
|
+
return false;
|
|
21776
|
+
if (status === "completed" || status === "exited" || status === "failed" || status === "cancelled" || status === "terminated" || status === "killed" || status === "unknown") {
|
|
21777
|
+
return false;
|
|
21778
|
+
}
|
|
21779
|
+
if (typeof value.exitCode === "number")
|
|
21780
|
+
return false;
|
|
21781
|
+
return typeof value.processId === "string";
|
|
21782
|
+
}
|
|
21783
|
+
function sleep(ms) {
|
|
21784
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
21785
|
+
}
|
|
21786
|
+
function isComputerExecHandle(value) {
|
|
21787
|
+
const rec = record3(value);
|
|
21788
|
+
return Boolean(rec && typeof rec.processId === "string" && isRunning(rec));
|
|
21789
|
+
}
|
|
21790
|
+
async function waitForComputerExec(executor, input, value, ctx) {
|
|
21791
|
+
if (!processRead || !isComputerExecHandle(value))
|
|
21792
|
+
return value;
|
|
21793
|
+
let latest = value;
|
|
21794
|
+
let cursor = typeof latest.nextCursor === "string" && latest.nextCursor ? latest.nextCursor : undefined;
|
|
21795
|
+
const deadline = Date.now() + (typeof input.timeout === "number" && Number.isFinite(input.timeout) ? input.timeout : DEFAULT_PROCESS_DEADLINE_MS);
|
|
21796
|
+
advise(`Process ${String(latest.processId)} is still running; polling computer_process_read.
|
|
21797
|
+
`, ctx);
|
|
21798
|
+
while (isRunning(latest) && Date.now() < deadline) {
|
|
21799
|
+
await sleep(POLL_MS);
|
|
21800
|
+
const read = record3(await processRead.run(executor, {
|
|
21801
|
+
processId: latest.processId,
|
|
21802
|
+
...cursor ? { cursor } : {},
|
|
21803
|
+
...typeof input.runId === "string" ? { runId: input.runId } : {},
|
|
21804
|
+
...typeof input.computerSessionId === "string" ? { computerSessionId: input.computerSessionId } : {}
|
|
21805
|
+
}));
|
|
21806
|
+
if (!read) {
|
|
21807
|
+
throw new Error("computer_process_read returned an empty result");
|
|
21808
|
+
}
|
|
21809
|
+
latest = read;
|
|
21810
|
+
if (typeof read.nextCursor === "string" && read.nextCursor)
|
|
21811
|
+
cursor = read.nextCursor;
|
|
21812
|
+
const stdout = typeof latest.stdout === "string" ? latest.stdout : "";
|
|
21813
|
+
if (stdout)
|
|
21814
|
+
advise(stdout, ctx);
|
|
21815
|
+
if (latest.recovery)
|
|
21816
|
+
break;
|
|
21817
|
+
}
|
|
21818
|
+
return latest;
|
|
21819
|
+
}
|
|
21820
|
+
|
|
21728
21821
|
// src/schema.ts
|
|
21729
21822
|
import { readFileSync as readFileSync2 } from "node:fs";
|
|
21730
21823
|
function kebab(field) {
|
|
@@ -22067,11 +22160,14 @@ Bare arguments fill ${explicitPositionals.map((spec) => `--${spec.flag}`).join("
|
|
|
22067
22160
|
|
|
22068
22161
|
Alias: \`arbor ${alias2}\` (the tool-name form) resolves to this same command.` : "";
|
|
22069
22162
|
const heading = `${commandWords(action)}${alias2 ? ` (alias: ${alias2})` : ""}`;
|
|
22163
|
+
const waitLines = action.name === "computer_exec" ? [
|
|
22164
|
+
" --no-wait [<boolean>] [optional] — return a running processId immediately instead of polling computer_process_read"
|
|
22165
|
+
] : [];
|
|
22070
22166
|
return `${heading} — ${action.description}
|
|
22071
22167
|
|
|
22072
|
-
${usage}
|
|
22168
|
+
${usage}${waitLines.length > 0 ? " [--no-wait]" : ""}
|
|
22073
22169
|
|
|
22074
|
-
${lines.join(`
|
|
22170
|
+
${[...lines, ...waitLines].join(`
|
|
22075
22171
|
`)}${primaryNote}${explicitNote}${aliasNote}
|
|
22076
22172
|
`;
|
|
22077
22173
|
}
|
|
@@ -22080,13 +22176,24 @@ function commandCatalog() {
|
|
|
22080
22176
|
command: commandWords(action),
|
|
22081
22177
|
name: action.name,
|
|
22082
22178
|
description: action.description,
|
|
22083
|
-
flags:
|
|
22084
|
-
|
|
22085
|
-
|
|
22086
|
-
|
|
22087
|
-
|
|
22088
|
-
|
|
22089
|
-
|
|
22179
|
+
flags: [
|
|
22180
|
+
...flagsForSchema(action.inputSchema).map((f) => ({
|
|
22181
|
+
flag: f.flag,
|
|
22182
|
+
kind: f.kind,
|
|
22183
|
+
required: f.required,
|
|
22184
|
+
acceptsFile: f.kind === "string",
|
|
22185
|
+
description: f.description
|
|
22186
|
+
})),
|
|
22187
|
+
...action.name === "computer_exec" ? [
|
|
22188
|
+
{
|
|
22189
|
+
flag: "no-wait",
|
|
22190
|
+
kind: "boolean",
|
|
22191
|
+
required: false,
|
|
22192
|
+
acceptsFile: false,
|
|
22193
|
+
description: "return a running processId immediately instead of polling computer_process_read"
|
|
22194
|
+
}
|
|
22195
|
+
] : []
|
|
22196
|
+
]
|
|
22090
22197
|
}));
|
|
22091
22198
|
}
|
|
22092
22199
|
function applyPositionals(action, extras, flags) {
|
|
@@ -22165,13 +22272,16 @@ async function runObjectVerb(positionals, flags, ctx) {
|
|
|
22165
22272
|
advise(`Agent registered. Save its apiKey now — it is shown only once:
|
|
22166
22273
|
`, ctx);
|
|
22167
22274
|
}
|
|
22168
|
-
|
|
22275
|
+
let value = await action.run(httpExecutor, input);
|
|
22276
|
+
if (action.name === "computer_exec" && !truthyFlag(flags["no-wait"])) {
|
|
22277
|
+
value = await waitForComputerExec(httpExecutor, input, value, ctx);
|
|
22278
|
+
}
|
|
22169
22279
|
emitData(shapeActionOutput(action.name, value, input), action.name, ctx);
|
|
22170
22280
|
}
|
|
22171
22281
|
|
|
22172
22282
|
// src/connect.ts
|
|
22173
22283
|
var DEFAULT_POLL_INTERVAL_MS = 2000;
|
|
22174
|
-
var
|
|
22284
|
+
var sleep2 = (ms) => new Promise((r) => setTimeout(r, ms));
|
|
22175
22285
|
function bareConnectUrl(apiUrl, returnedUrl) {
|
|
22176
22286
|
const fallback = `${apiUrl.replace(/\/$/, "")}/connect`;
|
|
22177
22287
|
if (!returnedUrl)
|
|
@@ -22215,7 +22325,7 @@ async function connect(opts) {
|
|
|
22215
22325
|
if (Date.now() > deadline) {
|
|
22216
22326
|
throw new Error("pairing timed out — ask for a new pairing key and run `arbor connect` again");
|
|
22217
22327
|
}
|
|
22218
|
-
await
|
|
22328
|
+
await sleep2(pollIntervalMs);
|
|
22219
22329
|
const tokRes = await fetch(`${apiUrl}/api/agent/connect/token`, {
|
|
22220
22330
|
method: "POST",
|
|
22221
22331
|
headers,
|
|
@@ -22241,7 +22351,7 @@ async function connect(opts) {
|
|
|
22241
22351
|
// src/login.ts
|
|
22242
22352
|
var CLIENT_ID = "arbor-cli";
|
|
22243
22353
|
var GRANT_TYPE = "urn:ietf:params:oauth:grant-type:device_code";
|
|
22244
|
-
var
|
|
22354
|
+
var sleep3 = (ms) => new Promise((r) => setTimeout(r, ms));
|
|
22245
22355
|
async function login(opts) {
|
|
22246
22356
|
const apiUrl = opts.url ?? loadConfig().apiUrl;
|
|
22247
22357
|
const codeRes = await fetch(`${apiUrl}/api/auth/device/code`, {
|
|
@@ -22266,7 +22376,7 @@ async function login(opts) {
|
|
|
22266
22376
|
for (;; ) {
|
|
22267
22377
|
if (Date.now() > deadline)
|
|
22268
22378
|
throw new Error("login timed out — run `arbor login` again");
|
|
22269
|
-
await
|
|
22379
|
+
await sleep3(interval);
|
|
22270
22380
|
const tokRes = await fetch(`${apiUrl}/api/auth/device/token`, {
|
|
22271
22381
|
method: "POST",
|
|
22272
22382
|
headers: { "content-type": "application/json" },
|
package/package.json
CHANGED