@brainbase-labs/cli 0.53.0 → 0.55.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.
- package/dist/index.js +2089 -496
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -35182,9 +35182,9 @@ var require_dist2 = __commonJS((exports, module) => {
|
|
|
35182
35182
|
});
|
|
35183
35183
|
|
|
35184
35184
|
// src/index.ts
|
|
35185
|
-
var
|
|
35185
|
+
var import_picocolors81 = __toESM(require_picocolors(), 1);
|
|
35186
35186
|
import process14 from "node:process";
|
|
35187
|
-
import
|
|
35187
|
+
import fs96 from "node:fs";
|
|
35188
35188
|
|
|
35189
35189
|
// src/cli/template.ts
|
|
35190
35190
|
var import_picocolors12 = __toESM(require_picocolors(), 1);
|
|
@@ -36091,7 +36091,7 @@ function padStart(s, n) {
|
|
|
36091
36091
|
// package.json
|
|
36092
36092
|
var package_default = {
|
|
36093
36093
|
name: "@brainbase-labs/cli",
|
|
36094
|
-
version: "0.
|
|
36094
|
+
version: "0.55.0",
|
|
36095
36095
|
description: "Pack, share, and install agent templates across harnesses (Claude Code, Codex, ...).",
|
|
36096
36096
|
type: "module",
|
|
36097
36097
|
bin: {
|
|
@@ -67885,6 +67885,14 @@ function automationErrorEnvelope(command, error) {
|
|
|
67885
67885
|
};
|
|
67886
67886
|
}
|
|
67887
67887
|
|
|
67888
|
+
// src/ui/terminal-safe.ts
|
|
67889
|
+
function sanitizeLabel(s3) {
|
|
67890
|
+
return s3.replace(/\u001b\][\s\S]*?(?:\u0007|\u001b\\|$)/g, "").replace(/\u001b\[[\u0030-\u003f]*[\u0020-\u002f]*[\u0040-\u007e]?/g, "").replace(/\u001b[\s\S]?/g, "").replace(/[\u0000-\u001f\u007f-\u009f\u2028\u2029]/g, "");
|
|
67891
|
+
}
|
|
67892
|
+
function sanitizeLines(s3) {
|
|
67893
|
+
return s3.split(/\r\n|[\n\r\u2028\u2029]/).map(sanitizeLabel);
|
|
67894
|
+
}
|
|
67895
|
+
|
|
67888
67896
|
// src/core/fastapi-detail.ts
|
|
67889
67897
|
function record(value) {
|
|
67890
67898
|
return value && typeof value === "object" && !Array.isArray(value) ? value : null;
|
|
@@ -67893,22 +67901,22 @@ function fastApiDetails(body) {
|
|
|
67893
67901
|
const detail = record(body)?.detail;
|
|
67894
67902
|
return Array.isArray(detail) ? detail.filter((entry) => !!record(entry)) : [];
|
|
67895
67903
|
}
|
|
67904
|
+
function fastApiValidationMessage(body) {
|
|
67905
|
+
const parts = fastApiDetails(body).map((entry) => {
|
|
67906
|
+
const msg = typeof entry.msg === "string" ? sanitizeLabel(entry.msg.trim()) : "";
|
|
67907
|
+
if (!msg)
|
|
67908
|
+
return null;
|
|
67909
|
+
const loc = Array.isArray(entry.loc) ? sanitizeLabel(entry.loc.filter((part) => part !== "body").map(String).join(".")) : "";
|
|
67910
|
+
return loc ? `${loc}: ${msg}` : msg;
|
|
67911
|
+
}).filter((part) => !!part);
|
|
67912
|
+
return parts.length ? parts.join("; ") : null;
|
|
67913
|
+
}
|
|
67896
67914
|
function rejectsBodyField(body, field) {
|
|
67897
67915
|
return fastApiDetails(body).some((entry) => entry.type === "extra_forbidden" && Array.isArray(entry.loc) && entry.loc[0] === "body" && entry.loc[1] === field);
|
|
67898
67916
|
}
|
|
67899
67917
|
|
|
67900
67918
|
// src/core/interfaces-api.ts
|
|
67901
67919
|
import { randomUUID as randomUUID2 } from "node:crypto";
|
|
67902
|
-
|
|
67903
|
-
// src/ui/terminal-safe.ts
|
|
67904
|
-
function sanitizeLabel(s3) {
|
|
67905
|
-
return s3.replace(/\u001b\][\s\S]*?(?:\u0007|\u001b\\|$)/g, "").replace(/\u001b\[[\u0030-\u003f]*[\u0020-\u002f]*[\u0040-\u007e]?/g, "").replace(/\u001b[\s\S]?/g, "").replace(/[\u0000-\u001f\u007f-\u009f\u2028\u2029]/g, "");
|
|
67906
|
-
}
|
|
67907
|
-
function sanitizeLines(s3) {
|
|
67908
|
-
return s3.split(/\r\n|[\n\r\u2028\u2029]/).map(sanitizeLabel);
|
|
67909
|
-
}
|
|
67910
|
-
|
|
67911
|
-
// src/core/interfaces-api.ts
|
|
67912
67920
|
function isSettled(status) {
|
|
67913
67921
|
return status === "succeeded" || status === "failed";
|
|
67914
67922
|
}
|
|
@@ -68022,17 +68030,7 @@ function clean(value) {
|
|
|
68022
68030
|
`);
|
|
68023
68031
|
}
|
|
68024
68032
|
function fieldMessages(fields) {
|
|
68025
|
-
|
|
68026
|
-
return null;
|
|
68027
|
-
const parts = fields.map((entry) => {
|
|
68028
|
-
const item = record2(entry);
|
|
68029
|
-
if (!item)
|
|
68030
|
-
return null;
|
|
68031
|
-
const loc = Array.isArray(item.loc) ? sanitizeLabel(item.loc.filter((part) => part !== "body").map(String).join(".")) : "";
|
|
68032
|
-
const msg = text2(item.msg);
|
|
68033
|
-
return msg ? loc ? `${loc}: ${sanitizeLabel(msg)}` : sanitizeLabel(msg) : null;
|
|
68034
|
-
}).filter((part) => !!part);
|
|
68035
|
-
return parts.length ? parts.join("; ") : null;
|
|
68033
|
+
return fastApiValidationMessage({ detail: fields });
|
|
68036
68034
|
}
|
|
68037
68035
|
function toInterfaceError(error, options = {}) {
|
|
68038
68036
|
if (error instanceof InterfaceApiError || !(error instanceof ApiError))
|
|
@@ -68082,9 +68080,8 @@ function toInterfaceError(error, options = {}) {
|
|
|
68082
68080
|
break;
|
|
68083
68081
|
}
|
|
68084
68082
|
default:
|
|
68085
|
-
if (status === 422
|
|
68086
|
-
message =
|
|
68087
|
-
}
|
|
68083
|
+
if (status === 422)
|
|
68084
|
+
message = fastApiValidationMessage(body) ?? serverMessage;
|
|
68088
68085
|
}
|
|
68089
68086
|
const rawInterfaceId = text2(details?.interface_id);
|
|
68090
68087
|
const interfaceId = rawInterfaceId ? sanitizeLabel(rawInterfaceId) : null;
|
|
@@ -82448,6 +82445,10 @@ var SyncedScheduleTriggerSchema = exports_external.object({
|
|
|
82448
82445
|
node_id: exports_external.string(),
|
|
82449
82446
|
hash: exports_external.string()
|
|
82450
82447
|
});
|
|
82448
|
+
var SyncedDecisionSchema = exports_external.object({
|
|
82449
|
+
id: exports_external.string(),
|
|
82450
|
+
hash: exports_external.string()
|
|
82451
|
+
});
|
|
82451
82452
|
var SyncedOrchestrationMetaSchema = exports_external.object({
|
|
82452
82453
|
name: exports_external.string().optional(),
|
|
82453
82454
|
description: exports_external.string().optional(),
|
|
@@ -82463,6 +82464,7 @@ var OrchestrationSyncStateSchema = exports_external.object({
|
|
|
82463
82464
|
members: exports_external.array(SyncedMemberSchema),
|
|
82464
82465
|
edges: exports_external.array(SyncedEdgeSchema),
|
|
82465
82466
|
triggers: exports_external.array(SyncedScheduleTriggerSchema).optional(),
|
|
82467
|
+
decisions: exports_external.array(SyncedDecisionSchema).optional(),
|
|
82466
82468
|
meta: SyncedOrchestrationMetaSchema.optional()
|
|
82467
82469
|
});
|
|
82468
82470
|
function orchLinkPath(cwd2) {
|
|
@@ -82884,6 +82886,9 @@ var TriggerEdgeSchema = exports_external.object({
|
|
|
82884
82886
|
payload_schema: exports_external.record(exports_external.unknown()).optional()
|
|
82885
82887
|
});
|
|
82886
82888
|
var UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
82889
|
+
function canonicalUuid2(value2) {
|
|
82890
|
+
return UUID_RE.test(value2) ? value2.toLowerCase() : value2;
|
|
82891
|
+
}
|
|
82887
82892
|
var ScheduleTriggerSchema = exports_external.object({
|
|
82888
82893
|
type: exports_external.literal("schedule"),
|
|
82889
82894
|
node_id: exports_external.string().regex(UUID_RE, "must be a UUID"),
|
|
@@ -82901,12 +82906,52 @@ var ReadOnlyTriggerSchema = exports_external.object({
|
|
|
82901
82906
|
to: exports_external.array(TriggerEdgeSchema).default([])
|
|
82902
82907
|
});
|
|
82903
82908
|
var TriggerSchema = exports_external.union([ScheduleTriggerSchema, ReadOnlyTriggerSchema]);
|
|
82909
|
+
var DECISION_MODELS = [
|
|
82910
|
+
"jev",
|
|
82911
|
+
"kev-4b",
|
|
82912
|
+
"clef",
|
|
82913
|
+
"clef-flash",
|
|
82914
|
+
"gpt-6-luna"
|
|
82915
|
+
];
|
|
82916
|
+
var DEFAULT_DECISION_MODEL = "clef-flash";
|
|
82917
|
+
var DECISION_LIMITS = {
|
|
82918
|
+
name: 200,
|
|
82919
|
+
model: 100,
|
|
82920
|
+
instructions: 4000,
|
|
82921
|
+
answersMin: 2,
|
|
82922
|
+
answersMax: 20,
|
|
82923
|
+
answer: 200,
|
|
82924
|
+
criterion: 1000
|
|
82925
|
+
};
|
|
82926
|
+
var DecisionTargetSchema = exports_external.object({
|
|
82927
|
+
agent: exports_external.string().min(1).optional(),
|
|
82928
|
+
decision: exports_external.string().regex(UUID_RE, "must be a UUID").optional(),
|
|
82929
|
+
description: exports_external.string().optional()
|
|
82930
|
+
}).refine((t) => t.agent === undefined !== (t.decision === undefined), {
|
|
82931
|
+
message: "set exactly one of agent or decision"
|
|
82932
|
+
});
|
|
82933
|
+
var DecisionAnswerSchema = exports_external.object({
|
|
82934
|
+
answer: exports_external.string(),
|
|
82935
|
+
criterion: exports_external.string().optional(),
|
|
82936
|
+
to: exports_external.array(DecisionTargetSchema).default([])
|
|
82937
|
+
});
|
|
82938
|
+
var DecisionSchema = exports_external.object({
|
|
82939
|
+
id: exports_external.string().regex(UUID_RE, "must be a UUID"),
|
|
82940
|
+
name: exports_external.string(),
|
|
82941
|
+
model: exports_external.string().optional(),
|
|
82942
|
+
instructions: exports_external.string().optional(),
|
|
82943
|
+
confidence_threshold: exports_external.number().min(0).max(1).nullable().optional(),
|
|
82944
|
+
from: exports_external.array(exports_external.object({ trigger: exports_external.string().regex(UUID_RE, "must be a UUID") })).default([]),
|
|
82945
|
+
answers: exports_external.array(DecisionAnswerSchema),
|
|
82946
|
+
fallback: exports_external.array(DecisionTargetSchema).default([])
|
|
82947
|
+
});
|
|
82904
82948
|
var OrchestrationManifestSchema = exports_external.object({
|
|
82905
82949
|
schema: exports_external.literal(1),
|
|
82906
82950
|
orchestration: OrchMetaSchema,
|
|
82907
82951
|
members: exports_external.array(MemberSchema).default([]),
|
|
82908
82952
|
edges: exports_external.array(EdgeSchema).default([]),
|
|
82909
|
-
triggers: exports_external.array(TriggerSchema).optional()
|
|
82953
|
+
triggers: exports_external.array(TriggerSchema).optional(),
|
|
82954
|
+
decisions: exports_external.array(DecisionSchema).optional()
|
|
82910
82955
|
});
|
|
82911
82956
|
function orchManifestPath(cwd2) {
|
|
82912
82957
|
return path96.join(cwd2, ORCH_MANIFEST_FILE);
|
|
@@ -83331,6 +83376,132 @@ function syncedScheduleTriggers(triggers) {
|
|
|
83331
83376
|
hash: scheduleTriggerHash(t)
|
|
83332
83377
|
}));
|
|
83333
83378
|
}
|
|
83379
|
+
var DECISION = "decision";
|
|
83380
|
+
function manifestDecisions(manifest, slugToAgentId) {
|
|
83381
|
+
const target = (t) => {
|
|
83382
|
+
const agentId = t.agent !== undefined ? slugToAgentId?.get(t.agent) : undefined;
|
|
83383
|
+
return {
|
|
83384
|
+
...t.agent !== undefined ? { agent: t.agent, ...agentId ? { agent_id: agentId } : {} } : { decision: canonicalUuid2(t.decision) },
|
|
83385
|
+
description: t.description ?? ""
|
|
83386
|
+
};
|
|
83387
|
+
};
|
|
83388
|
+
return (manifest?.decisions ?? []).map((d3) => ({
|
|
83389
|
+
id: canonicalUuid2(d3.id),
|
|
83390
|
+
name: d3.name.trim(),
|
|
83391
|
+
model: (d3.model ?? DEFAULT_DECISION_MODEL).trim(),
|
|
83392
|
+
instructions: d3.instructions ?? "",
|
|
83393
|
+
confidence_threshold: d3.confidence_threshold ?? null,
|
|
83394
|
+
triggers: d3.from.map((f4) => canonicalUuid2(f4.trigger)),
|
|
83395
|
+
answers: d3.answers.map((a3) => ({
|
|
83396
|
+
answer: a3.answer.trim(),
|
|
83397
|
+
criterion: (a3.criterion ?? "").trim(),
|
|
83398
|
+
to: a3.to.map(target)
|
|
83399
|
+
})),
|
|
83400
|
+
fallback: d3.fallback.map(target)
|
|
83401
|
+
}));
|
|
83402
|
+
}
|
|
83403
|
+
function liveDecisionLinks(cloud) {
|
|
83404
|
+
const agents = new Set(cloud.members.map((m3) => m3.agent_id));
|
|
83405
|
+
const decisions = new Set((cloud.decisions ?? []).map((d3) => canonicalUuid2(d3.id)));
|
|
83406
|
+
const triggers = new Set((cloud.triggers ?? []).map((t) => canonicalUuid2(t.node_id)));
|
|
83407
|
+
return (d3) => {
|
|
83408
|
+
const answers = new Set(d3.answers.map((a3) => a3.answer));
|
|
83409
|
+
return {
|
|
83410
|
+
routes: d3.routes.filter((r2) => (r2.is_fallback || r2.answer != null && answers.has(r2.answer)) && (r2.to_agent_id ? agents.has(r2.to_agent_id) : r2.to_decision_id != null && decisions.has(canonicalUuid2(r2.to_decision_id)))),
|
|
83411
|
+
inputs: d3.inputs.filter((i) => triggers.has(canonicalUuid2(i.from_trigger_node_id)))
|
|
83412
|
+
};
|
|
83413
|
+
};
|
|
83414
|
+
}
|
|
83415
|
+
function cloudDecisions(cloud, slugForAgent) {
|
|
83416
|
+
if (cloud.decisions == null)
|
|
83417
|
+
return null;
|
|
83418
|
+
const live = liveDecisionLinks(cloud);
|
|
83419
|
+
return cloud.decisions.map((d3) => {
|
|
83420
|
+
const { routes, inputs } = live(d3);
|
|
83421
|
+
const target = (r2) => ({
|
|
83422
|
+
...r2.to_agent_id ? {
|
|
83423
|
+
agent: slugForAgent(r2.to_agent_id, r2.to_slug ?? r2.to_agent_id),
|
|
83424
|
+
agent_id: r2.to_agent_id
|
|
83425
|
+
} : { decision: canonicalUuid2(r2.to_decision_id) },
|
|
83426
|
+
description: r2.description ?? ""
|
|
83427
|
+
});
|
|
83428
|
+
return {
|
|
83429
|
+
id: canonicalUuid2(d3.id),
|
|
83430
|
+
name: d3.name.trim(),
|
|
83431
|
+
model: d3.model.trim(),
|
|
83432
|
+
instructions: d3.instructions ?? "",
|
|
83433
|
+
confidence_threshold: d3.confidence_threshold ?? null,
|
|
83434
|
+
triggers: inputs.map((i) => canonicalUuid2(i.from_trigger_node_id)),
|
|
83435
|
+
answers: d3.answers.map((a3) => ({
|
|
83436
|
+
answer: a3.answer.trim(),
|
|
83437
|
+
criterion: (a3.criterion ?? "").trim(),
|
|
83438
|
+
to: routes.filter((r2) => !r2.is_fallback && r2.answer === a3.answer).map(target)
|
|
83439
|
+
})),
|
|
83440
|
+
fallback: routes.filter((r2) => r2.is_fallback).map(target)
|
|
83441
|
+
};
|
|
83442
|
+
});
|
|
83443
|
+
}
|
|
83444
|
+
function deadDecisionLinks(cloud) {
|
|
83445
|
+
const live = liveDecisionLinks(cloud);
|
|
83446
|
+
const out = new Map;
|
|
83447
|
+
for (const d3 of cloud.decisions ?? []) {
|
|
83448
|
+
const { routes, inputs } = live(d3);
|
|
83449
|
+
const dead = d3.routes.length - routes.length + d3.inputs.length - inputs.length;
|
|
83450
|
+
if (dead > 0)
|
|
83451
|
+
out.set(d3.id, dead);
|
|
83452
|
+
}
|
|
83453
|
+
return out;
|
|
83454
|
+
}
|
|
83455
|
+
function decisionHash(d3) {
|
|
83456
|
+
const targets = (ts2) => ts2.map(({ agent, agent_id, ...rest2 }) => stableJson(agent_id !== undefined ? { agent_id, ...rest2 } : { agent, ...rest2 })).sort();
|
|
83457
|
+
const canonical = {
|
|
83458
|
+
name: d3.name,
|
|
83459
|
+
model: d3.model,
|
|
83460
|
+
instructions: d3.instructions,
|
|
83461
|
+
confidence_threshold: d3.confidence_threshold,
|
|
83462
|
+
triggers: [...d3.triggers].sort(),
|
|
83463
|
+
answers: d3.answers.map((a3) => ({
|
|
83464
|
+
answer: a3.answer,
|
|
83465
|
+
criterion: a3.criterion,
|
|
83466
|
+
to: targets(a3.to)
|
|
83467
|
+
})),
|
|
83468
|
+
fallback: targets(d3.fallback)
|
|
83469
|
+
};
|
|
83470
|
+
return crypto6.createHash("sha256").update(stableJson(canonical)).digest("hex");
|
|
83471
|
+
}
|
|
83472
|
+
function decisionLabel(d3) {
|
|
83473
|
+
return `decision "${d3.name}" (${d3.id})`;
|
|
83474
|
+
}
|
|
83475
|
+
function decideDecisionReconcile(input) {
|
|
83476
|
+
const rows = threeWayDiff({
|
|
83477
|
+
local: input.local.map((d3) => ({
|
|
83478
|
+
type: DECISION,
|
|
83479
|
+
slug: d3.id,
|
|
83480
|
+
hash: decisionHash(d3)
|
|
83481
|
+
})),
|
|
83482
|
+
lock: (input.baseline ?? []).map((d3) => ({
|
|
83483
|
+
type: DECISION,
|
|
83484
|
+
slug: d3.id,
|
|
83485
|
+
hash: d3.hash,
|
|
83486
|
+
installedPaths: []
|
|
83487
|
+
})),
|
|
83488
|
+
cloud: input.cloud.map((d3) => ({
|
|
83489
|
+
type: DECISION,
|
|
83490
|
+
slug: d3.id,
|
|
83491
|
+
hash: decisionHash(d3),
|
|
83492
|
+
files: []
|
|
83493
|
+
}))
|
|
83494
|
+
});
|
|
83495
|
+
return decideCollectionReconcile({
|
|
83496
|
+
rows,
|
|
83497
|
+
type: DECISION,
|
|
83498
|
+
claims: input.local.length > 0,
|
|
83499
|
+
force: input.force
|
|
83500
|
+
});
|
|
83501
|
+
}
|
|
83502
|
+
function syncedDecisions(decisions) {
|
|
83503
|
+
return decisions.map((d3) => ({ id: d3.id, hash: decisionHash(d3) }));
|
|
83504
|
+
}
|
|
83334
83505
|
var ORCH_META_FIELDS = [
|
|
83335
83506
|
"name",
|
|
83336
83507
|
"description",
|
|
@@ -83413,6 +83584,26 @@ function triggersForManifest(triggers, slugFor) {
|
|
|
83413
83584
|
};
|
|
83414
83585
|
});
|
|
83415
83586
|
}
|
|
83587
|
+
function decisionsForManifest(decisions) {
|
|
83588
|
+
const target = (t) => ({
|
|
83589
|
+
...t.agent !== undefined ? { agent: t.agent } : { decision: t.decision },
|
|
83590
|
+
...t.description ? { description: t.description } : {}
|
|
83591
|
+
});
|
|
83592
|
+
return decisions.map((d3) => ({
|
|
83593
|
+
id: d3.id,
|
|
83594
|
+
name: d3.name,
|
|
83595
|
+
model: d3.model,
|
|
83596
|
+
...d3.instructions ? { instructions: d3.instructions } : {},
|
|
83597
|
+
...d3.confidence_threshold != null ? { confidence_threshold: d3.confidence_threshold } : {},
|
|
83598
|
+
...d3.triggers.length ? { from: d3.triggers.map((trigger) => ({ trigger })) } : {},
|
|
83599
|
+
answers: d3.answers.map((a3) => ({
|
|
83600
|
+
answer: a3.answer,
|
|
83601
|
+
...a3.criterion ? { criterion: a3.criterion } : {},
|
|
83602
|
+
...a3.to.length ? { to: a3.to.map(target) } : {}
|
|
83603
|
+
})),
|
|
83604
|
+
...d3.fallback.length ? { fallback: d3.fallback.map(target) } : {}
|
|
83605
|
+
}));
|
|
83606
|
+
}
|
|
83416
83607
|
async function runOrchestrationPull(cwd2, args) {
|
|
83417
83608
|
banner("orchestration pull — fetch orchestration + all member agents");
|
|
83418
83609
|
let orchId = null;
|
|
@@ -83463,6 +83654,14 @@ async function runOrchestrationPull(cwd2, args) {
|
|
|
83463
83654
|
planLines.push(` ${import_picocolors52.default.cyan(from)} ${import_picocolors52.default.dim("→")} ${import_picocolors52.default.cyan(to2)}${desc}`);
|
|
83464
83655
|
}
|
|
83465
83656
|
}
|
|
83657
|
+
const pulledDecisions = cloudDecisions(cloud, (agentId, fallback) => slugByAgent.get(agentId) ?? fallback);
|
|
83658
|
+
if (pulledDecisions?.length) {
|
|
83659
|
+
planLines.push("");
|
|
83660
|
+
planLines.push(` ${import_picocolors52.default.dim("decisions:")}`);
|
|
83661
|
+
for (const d3 of pulledDecisions) {
|
|
83662
|
+
planLines.push(` ${import_picocolors52.default.cyan("◆")} ${import_picocolors52.default.bold(d3.name)} ${import_picocolors52.default.dim(`(${d3.model}, ${d3.answers.length} answers)`)}`);
|
|
83663
|
+
}
|
|
83664
|
+
}
|
|
83466
83665
|
planLines.push("");
|
|
83467
83666
|
console.log(planLines.join(`
|
|
83468
83667
|
`));
|
|
@@ -83528,6 +83727,19 @@ async function runOrchestrationPull(cwd2, args) {
|
|
|
83528
83727
|
}
|
|
83529
83728
|
}
|
|
83530
83729
|
const manifestTriggers = triggersForManifest(cloud.triggers ?? [], slugFor);
|
|
83730
|
+
let manifestDecisions2 = pulledDecisions ? decisionsForManifest(pulledDecisions) : undefined;
|
|
83731
|
+
let decisionBaseline = pulledDecisions ? syncedDecisions(pulledDecisions) : undefined;
|
|
83732
|
+
if (!pulledDecisions) {
|
|
83733
|
+
try {
|
|
83734
|
+
manifestDecisions2 = readOrchManifest(cwd2)?.decisions;
|
|
83735
|
+
} catch {}
|
|
83736
|
+
const lock = readOrchSyncState(cwd2);
|
|
83737
|
+
decisionBaseline = lock?.orchestration_id === cloud.id ? lock.decisions : undefined;
|
|
83738
|
+
}
|
|
83739
|
+
for (const [decisionId, count] of deadDecisionLinks(cloud)) {
|
|
83740
|
+
const name = pulledDecisions?.find((d3) => d3.id === decisionId)?.name;
|
|
83741
|
+
f2.warn(`Decision ${import_picocolors52.default.bold(name ?? decisionId)} has ${count} route${count === 1 ? "" : "s"} or input${count === 1 ? "" : "s"} that lead${count === 1 ? "s" : ""} nowhere: on an answer it no longer has, or to an agent, decision or trigger no longer in this orchestration. They never run and are not in ${import_picocolors52.default.bold("brainbase-orchestration.yaml")}; the next push of decisions removes them.`);
|
|
83742
|
+
}
|
|
83531
83743
|
const manifest = {
|
|
83532
83744
|
schema: 1,
|
|
83533
83745
|
orchestration: {
|
|
@@ -83551,7 +83763,8 @@ async function runOrchestrationPull(cwd2, args) {
|
|
|
83551
83763
|
...e2.payload_schema && Object.keys(e2.payload_schema).length ? { payload_schema: e2.payload_schema } : {},
|
|
83552
83764
|
...e2.settings && Object.keys(e2.settings).length ? { settings: e2.settings } : {}
|
|
83553
83765
|
})),
|
|
83554
|
-
...manifestTriggers.length ? { triggers: manifestTriggers } : {}
|
|
83766
|
+
...manifestTriggers.length ? { triggers: manifestTriggers } : {},
|
|
83767
|
+
...manifestDecisions2?.length ? { decisions: manifestDecisions2 } : {}
|
|
83555
83768
|
};
|
|
83556
83769
|
writeOrchManifest(cwd2, manifest);
|
|
83557
83770
|
writeOrchLink(cwd2, {
|
|
@@ -83577,6 +83790,7 @@ async function runOrchestrationPull(cwd2, args) {
|
|
|
83577
83790
|
payload_schema: e2.payload_schema ?? {}
|
|
83578
83791
|
})),
|
|
83579
83792
|
triggers: syncedScheduleTriggers(cloudScheduleTriggers(cloud, (agentId, fallback) => slugFor(agentId) || fallback)),
|
|
83793
|
+
...decisionBaseline ? { decisions: decisionBaseline } : {},
|
|
83580
83794
|
meta: syncedOrchestrationMeta(cloud)
|
|
83581
83795
|
});
|
|
83582
83796
|
if (missingMembers.length > 0) {
|
|
@@ -83604,6 +83818,83 @@ function handleApiError5(err) {
|
|
|
83604
83818
|
var import_picocolors53 = __toESM(require_picocolors(), 1);
|
|
83605
83819
|
|
|
83606
83820
|
// src/core/orchestration-outgoing.ts
|
|
83821
|
+
function charLength(value2) {
|
|
83822
|
+
return Array.from(value2).length;
|
|
83823
|
+
}
|
|
83824
|
+
function validateDecisions(decisions, memberSlugs, triggerNodeIds) {
|
|
83825
|
+
const ids = new Set;
|
|
83826
|
+
for (const d3 of decisions) {
|
|
83827
|
+
if (ids.has(d3.id))
|
|
83828
|
+
throw new Error(`Decision ${d3.id} is duplicated.`);
|
|
83829
|
+
ids.add(d3.id);
|
|
83830
|
+
}
|
|
83831
|
+
for (const d3 of decisions) {
|
|
83832
|
+
const label2 = `Decision "${d3.name || d3.id}"`;
|
|
83833
|
+
const fail3 = (message) => {
|
|
83834
|
+
throw new Error(`${label2}: ${message}`);
|
|
83835
|
+
};
|
|
83836
|
+
if (!d3.name || charLength(d3.name) > DECISION_LIMITS.name) {
|
|
83837
|
+
fail3(`name must be 1 to ${DECISION_LIMITS.name} characters.`);
|
|
83838
|
+
}
|
|
83839
|
+
if (!d3.model || charLength(d3.model) > DECISION_LIMITS.model) {
|
|
83840
|
+
fail3(`model must be 1 to ${DECISION_LIMITS.model} characters.`);
|
|
83841
|
+
}
|
|
83842
|
+
if (charLength(d3.instructions) > DECISION_LIMITS.instructions) {
|
|
83843
|
+
fail3(`instructions must be ${DECISION_LIMITS.instructions} characters or fewer.`);
|
|
83844
|
+
}
|
|
83845
|
+
const count = d3.answers.length;
|
|
83846
|
+
if (count < DECISION_LIMITS.answersMin || count > DECISION_LIMITS.answersMax) {
|
|
83847
|
+
fail3(`needs ${DECISION_LIMITS.answersMin} to ${DECISION_LIMITS.answersMax} answers (has ${count}).`);
|
|
83848
|
+
}
|
|
83849
|
+
const answers = new Set;
|
|
83850
|
+
for (const a3 of d3.answers) {
|
|
83851
|
+
if (!a3.answer || charLength(a3.answer) > DECISION_LIMITS.answer) {
|
|
83852
|
+
fail3(`each answer must be 1 to ${DECISION_LIMITS.answer} characters.`);
|
|
83853
|
+
}
|
|
83854
|
+
if (answers.has(a3.answer))
|
|
83855
|
+
fail3(`answer "${a3.answer}" appears twice.`);
|
|
83856
|
+
answers.add(a3.answer);
|
|
83857
|
+
if (charLength(a3.criterion) > DECISION_LIMITS.criterion) {
|
|
83858
|
+
fail3(`the criterion for "${a3.answer}" must be ${DECISION_LIMITS.criterion} characters or fewer.`);
|
|
83859
|
+
}
|
|
83860
|
+
}
|
|
83861
|
+
const fed = new Set;
|
|
83862
|
+
for (const nodeId of d3.triggers) {
|
|
83863
|
+
if (!triggerNodeIds.has(nodeId)) {
|
|
83864
|
+
fail3(`from trigger ${nodeId}, which isn't in triggers.`);
|
|
83865
|
+
}
|
|
83866
|
+
if (fed.has(nodeId))
|
|
83867
|
+
fail3(`trigger ${nodeId} is listed twice in from.`);
|
|
83868
|
+
fed.add(nodeId);
|
|
83869
|
+
}
|
|
83870
|
+
const checkTargets = (targets, branch) => {
|
|
83871
|
+
const seen = new Set;
|
|
83872
|
+
for (const t of targets) {
|
|
83873
|
+
if (t.agent !== undefined && !memberSlugs.has(t.agent)) {
|
|
83874
|
+
fail3(`${branch} routes to "${t.agent}", which isn't in members.`);
|
|
83875
|
+
}
|
|
83876
|
+
if (t.decision !== undefined) {
|
|
83877
|
+
if (t.decision === d3.id)
|
|
83878
|
+
fail3(`${branch} routes to the decision itself.`);
|
|
83879
|
+
if (!ids.has(t.decision)) {
|
|
83880
|
+
fail3(`${branch} routes to decision ${t.decision}, which isn't in decisions.`);
|
|
83881
|
+
}
|
|
83882
|
+
}
|
|
83883
|
+
const key2 = t.agent !== undefined ? `agent:${t.agent}` : `decision:${t.decision}`;
|
|
83884
|
+
if (seen.has(key2))
|
|
83885
|
+
fail3(`${branch} routes to ${key2.replace(":", " ")} twice.`);
|
|
83886
|
+
seen.add(key2);
|
|
83887
|
+
}
|
|
83888
|
+
};
|
|
83889
|
+
for (const a3 of d3.answers)
|
|
83890
|
+
checkTargets(a3.to, `answer "${a3.answer}"`);
|
|
83891
|
+
checkTargets(d3.fallback, "fallback");
|
|
83892
|
+
}
|
|
83893
|
+
}
|
|
83894
|
+
function unknownDecisionModels(manifest) {
|
|
83895
|
+
const known = new Set(DECISION_MODELS);
|
|
83896
|
+
return manifestDecisions(manifest).filter((d3) => !known.has(d3.model)).map((d3) => ({ name: d3.name, model: d3.model }));
|
|
83897
|
+
}
|
|
83607
83898
|
function buildOrchestrationGraphPayload(manifest, slugToAgentId) {
|
|
83608
83899
|
const memberSlugs = new Set(manifest.members.map((m3) => m3.slug));
|
|
83609
83900
|
for (const e2 of manifest.edges) {
|
|
@@ -83664,6 +83955,32 @@ function buildOrchestrationGraphPayload(manifest, slugToAgentId) {
|
|
|
83664
83955
|
}))
|
|
83665
83956
|
};
|
|
83666
83957
|
}
|
|
83958
|
+
function buildDecisionsPayload(manifest, slugToAgentId) {
|
|
83959
|
+
const decisions = manifestDecisions(manifest, slugToAgentId);
|
|
83960
|
+
validateDecisions(decisions, new Set(manifest.members.map((m3) => m3.slug)), new Set((manifest.triggers ?? []).map((t) => canonicalUuid2(t.node_id))));
|
|
83961
|
+
return decisions.map((d3) => decisionPayload(d3, slugToAgentId));
|
|
83962
|
+
}
|
|
83963
|
+
function decisionPayload(d3, slugToAgentId) {
|
|
83964
|
+
const route = (answer, t) => ({
|
|
83965
|
+
answer,
|
|
83966
|
+
is_fallback: answer === null,
|
|
83967
|
+
...t.agent !== undefined ? { to_agent_id: slugToAgentId.get(t.agent) } : { to_decision_id: t.decision },
|
|
83968
|
+
description: t.description
|
|
83969
|
+
});
|
|
83970
|
+
return {
|
|
83971
|
+
id: d3.id,
|
|
83972
|
+
name: d3.name,
|
|
83973
|
+
model: d3.model,
|
|
83974
|
+
instructions: d3.instructions,
|
|
83975
|
+
answers: d3.answers.map((a3) => ({ answer: a3.answer, criterion: a3.criterion })),
|
|
83976
|
+
confidence_threshold: d3.confidence_threshold,
|
|
83977
|
+
inputs: d3.triggers.map((nodeId) => ({ from_trigger_node_id: nodeId })),
|
|
83978
|
+
routes: [
|
|
83979
|
+
...d3.answers.flatMap((a3) => a3.to.map((t) => route(a3.answer, t))),
|
|
83980
|
+
...d3.fallback.map((t) => route(null, t))
|
|
83981
|
+
]
|
|
83982
|
+
};
|
|
83983
|
+
}
|
|
83667
83984
|
|
|
83668
83985
|
// src/cli/orchestration-push.ts
|
|
83669
83986
|
function joinList(items) {
|
|
@@ -83791,7 +84108,21 @@ async function runOrchestrationPush(cwd2, args) {
|
|
|
83791
84108
|
const metaOverwrites = metaDecisions.filter((d3) => d3.kind === "push");
|
|
83792
84109
|
const metaKept = metaDecisions.filter((d3) => d3.kind === "keep");
|
|
83793
84110
|
const blockedTriggers = triggerDecision.kind === "blocked" ? triggerDecision : null;
|
|
83794
|
-
|
|
84111
|
+
const localDecisions = manifestDecisions(manifest, slugToAgentId);
|
|
84112
|
+
const cloudDecisionList = cloudDecisions(cloud, slugForAgent);
|
|
84113
|
+
const decisionPlan = cloudDecisionList ? decideDecisionReconcile({
|
|
84114
|
+
local: localDecisions,
|
|
84115
|
+
cloud: cloudDecisionList,
|
|
84116
|
+
baseline: lock?.decisions,
|
|
84117
|
+
force: !!args.force
|
|
84118
|
+
}) : null;
|
|
84119
|
+
const decisionById = new Map([...cloudDecisionList ?? [], ...localDecisions].map((d3) => [d3.id, d3]));
|
|
84120
|
+
const decisionLabelFor = (id) => {
|
|
84121
|
+
const d3 = decisionById.get(id);
|
|
84122
|
+
return d3 ? decisionLabel(d3) : id;
|
|
84123
|
+
};
|
|
84124
|
+
const blockedDecisions = decisionPlan?.kind === "blocked" ? decisionPlan : null;
|
|
84125
|
+
if (blockedTriggers || blockedDecisions || metaConflicts.length > 0) {
|
|
83795
84126
|
const pullTargets = [];
|
|
83796
84127
|
const forceEffects = [];
|
|
83797
84128
|
if (blockedTriggers) {
|
|
@@ -83810,6 +84141,22 @@ async function runOrchestrationPush(cwd2, args) {
|
|
|
83810
84141
|
pullTargets.push(`${total} schedule trigger${total === 1 ? "" : "s"}`);
|
|
83811
84142
|
forceEffects.push("make your local schedule triggers authoritative (deleting the cloud ones above)");
|
|
83812
84143
|
}
|
|
84144
|
+
if (blockedDecisions) {
|
|
84145
|
+
const { unseen, cloudModified, staleArchives } = blockedDecisions;
|
|
84146
|
+
f2.error(unseen.length > 0 ? "Cannot push: the cloud has decisions this folder has never seen." : "Cannot push: decisions changed both locally and in the cloud.");
|
|
84147
|
+
for (const id of unseen) {
|
|
84148
|
+
console.error(` ${import_picocolors53.default.red("!")} ${import_picocolors53.default.bold(decisionLabelFor(id))} ${import_picocolors53.default.dim("(only in the cloud — pushing would delete it)")}`);
|
|
84149
|
+
}
|
|
84150
|
+
for (const id of cloudModified) {
|
|
84151
|
+
console.error(` ${import_picocolors53.default.red("!")} ${import_picocolors53.default.bold(decisionLabelFor(id))} ${import_picocolors53.default.dim("(edited in the cloud — pushing would overwrite that edit)")}`);
|
|
84152
|
+
}
|
|
84153
|
+
for (const id of staleArchives) {
|
|
84154
|
+
console.error(` ${import_picocolors53.default.red("!")} ${import_picocolors53.default.bold(decisionLabelFor(id))} ${import_picocolors53.default.dim("(deleted here, edited in the cloud since — pushing would delete that edit)")}`);
|
|
84155
|
+
}
|
|
84156
|
+
const total = unseen.length + cloudModified.length + staleArchives.length;
|
|
84157
|
+
pullTargets.push(`${total} decision${total === 1 ? "" : "s"}`);
|
|
84158
|
+
forceEffects.push("make your local decisions authoritative (deleting or overwriting the cloud ones above)");
|
|
84159
|
+
}
|
|
83813
84160
|
if (metaConflicts.length > 0) {
|
|
83814
84161
|
f2.error("Cannot push: orchestration metadata changed both locally and in the cloud.");
|
|
83815
84162
|
for (const d3 of metaConflicts) {
|
|
@@ -83842,9 +84189,30 @@ async function runOrchestrationPush(cwd2, args) {
|
|
|
83842
84189
|
f2.warn(`${cloudTriggers.length} cloud schedule trigger${cloudTriggers.length === 1 ? "" : "s"} ${cloudTriggers.length === 1 ? "is" : "are"} not in ${import_picocolors53.default.bold(ORCH_MANIFEST_FILE)} and will be left untouched. Run ${import_picocolors53.default.cyan("brainbase orchestration pull")} to manage ${cloudTriggers.length === 1 ? "it" : "them"} from here.`);
|
|
83843
84190
|
}
|
|
83844
84191
|
const triggerDeletes = triggerDecision.kind === "reconcile" ? triggerDecision.archives : [];
|
|
84192
|
+
const decisionDeletes = decisionPlan?.kind === "reconcile" ? decisionPlan.archives : [];
|
|
84193
|
+
const sendDecisions = decisionPlan?.kind === "reconcile" && (localDecisions.length > 0 || decisionDeletes.length > 0);
|
|
84194
|
+
if (!cloudDecisionList && localDecisions.length > 0) {
|
|
84195
|
+
f2.warn(`The cloud did not return decision nodes for this account, so the ${localDecisions.length} decision${localDecisions.length === 1 ? "" : "s"} in ${import_picocolors53.default.bold(ORCH_MANIFEST_FILE)} ${localDecisions.length === 1 ? "is" : "are"} left out of this push and the cloud's are left alone.`);
|
|
84196
|
+
} else if (decisionPlan?.kind === "skip") {
|
|
84197
|
+
const left = decisionPlan.unseen.length + decisionPlan.cloudModified.length;
|
|
84198
|
+
f2.warn(`${left} cloud decision${left === 1 ? "" : "s"} ${left === 1 ? "is" : "are"} not in ${import_picocolors53.default.bold(ORCH_MANIFEST_FILE)} and will be left untouched. Run ${import_picocolors53.default.cyan("brainbase orchestration pull")} to manage ${left === 1 ? "it" : "them"} from here.`);
|
|
84199
|
+
}
|
|
84200
|
+
let decisionsPayload = [];
|
|
84201
|
+
if (sendDecisions) {
|
|
84202
|
+
try {
|
|
84203
|
+
decisionsPayload = buildDecisionsPayload(manifest, slugToAgentId);
|
|
84204
|
+
} catch (err) {
|
|
84205
|
+
f2.error(err.message);
|
|
84206
|
+
process.exitCode = 1;
|
|
84207
|
+
return;
|
|
84208
|
+
}
|
|
84209
|
+
for (const { name, model } of unknownDecisionModels(manifest)) {
|
|
84210
|
+
f2.warn(`Decision ${import_picocolors53.default.bold(name)} uses model ${import_picocolors53.default.bold(model)}, which is not one the canvas offers. It is pushed as written; if the gateway does not know it, the decision fails when its trigger fires.`);
|
|
84211
|
+
}
|
|
84212
|
+
}
|
|
83845
84213
|
const plan = [""];
|
|
83846
84214
|
plan.push(` ${import_picocolors53.default.bold(link2.name)} ${import_picocolors53.default.dim(`(${link2.orchestration_id})`)}`);
|
|
83847
|
-
plan.push(` ${import_picocolors53.default.dim(`${manifest.members.length} member${manifest.members.length === 1 ? "" : "s"}, ${manifest.edges.length} edge${manifest.edges.length === 1 ? "" : "s"}, ${graph.triggers.length} trigger${graph.triggers.length === 1 ? "" : "s"}`)}`);
|
|
84215
|
+
plan.push(` ${import_picocolors53.default.dim(`${manifest.members.length} member${manifest.members.length === 1 ? "" : "s"}, ${manifest.edges.length} edge${manifest.edges.length === 1 ? "" : "s"}, ${graph.triggers.length} trigger${graph.triggers.length === 1 ? "" : "s"}${sendDecisions ? `, ${decisionsPayload.length} decision${decisionsPayload.length === 1 ? "" : "s"}` : ""}`)}`);
|
|
83848
84216
|
plan.push("");
|
|
83849
84217
|
if (!args.graphOnly) {
|
|
83850
84218
|
plan.push(` ${import_picocolors53.default.dim("per-member agent push:")}`);
|
|
@@ -83860,6 +84228,13 @@ async function runOrchestrationPush(cwd2, args) {
|
|
|
83860
84228
|
}
|
|
83861
84229
|
plan.push("");
|
|
83862
84230
|
}
|
|
84231
|
+
if (decisionDeletes.length) {
|
|
84232
|
+
plan.push(` ${import_picocolors53.default.bold("decisions this push will delete")} ${import_picocolors53.default.dim(`(${decisionDeletes.length})`)}`);
|
|
84233
|
+
for (const id of decisionDeletes) {
|
|
84234
|
+
plan.push(` ${import_picocolors53.default.yellow("⨯")} ${decisionLabelFor(id)}`);
|
|
84235
|
+
}
|
|
84236
|
+
plan.push("");
|
|
84237
|
+
}
|
|
83863
84238
|
if (metaOverwrites.length) {
|
|
83864
84239
|
plan.push(` ${import_picocolors53.default.bold("orchestration metadata this push will overwrite")}`);
|
|
83865
84240
|
for (const m3 of metaOverwrites) {
|
|
@@ -83878,9 +84253,13 @@ async function runOrchestrationPush(cwd2, args) {
|
|
|
83878
84253
|
console.log(plan.join(`
|
|
83879
84254
|
`));
|
|
83880
84255
|
if (!autoProceed(args.yes)) {
|
|
84256
|
+
const deletions = [
|
|
84257
|
+
...triggerDeletes.length ? [`${triggerDeletes.length} schedule trigger${triggerDeletes.length === 1 ? "" : "s"}`] : [],
|
|
84258
|
+
...decisionDeletes.length ? [`${decisionDeletes.length} decision${decisionDeletes.length === 1 ? "" : "s"}`] : []
|
|
84259
|
+
];
|
|
83881
84260
|
const ok = await se({
|
|
83882
|
-
message:
|
|
83883
|
-
initialValue:
|
|
84261
|
+
message: deletions.length ? `Push, deleting ${joinList(deletions)}?` : args.graphOnly ? "Push graph (members, edges + triggers) only?" : "Push each member, then update the graph?",
|
|
84262
|
+
initialValue: deletions.length === 0
|
|
83884
84263
|
});
|
|
83885
84264
|
if (!ensureNotCancelled(ok)) {
|
|
83886
84265
|
$e("Aborted.");
|
|
@@ -83926,9 +84305,11 @@ async function runOrchestrationPush(cwd2, args) {
|
|
|
83926
84305
|
members: graph.memberIds,
|
|
83927
84306
|
edges: graph.edges,
|
|
83928
84307
|
triggers: graph.triggers,
|
|
84308
|
+
...sendDecisions ? { decisions: decisionsPayload } : {},
|
|
83929
84309
|
...lock?.revision != null ? { base_revision: lock.revision } : {}
|
|
83930
84310
|
});
|
|
83931
84311
|
sp.stop(`Graph updated. New cloud revision ${updated.revision}.`);
|
|
84312
|
+
const settledDecisions = sendDecisions ? cloudDecisions(updated, slugForAgent) : decisionPlan?.kind === "reconcile" ? cloudDecisionList : null;
|
|
83932
84313
|
writeOrchSyncState(cwd2, {
|
|
83933
84314
|
schemaVersion: 1,
|
|
83934
84315
|
orchestration_id: updated.id,
|
|
@@ -83946,6 +84327,7 @@ async function runOrchestrationPush(cwd2, args) {
|
|
|
83946
84327
|
payload_schema: e2.payload_schema ?? {}
|
|
83947
84328
|
})),
|
|
83948
84329
|
triggers: triggerDecision.kind === "skip" ? lock?.triggers ?? [] : syncedScheduleTriggers(cloudScheduleTriggers(updated, slugForAgent)),
|
|
84330
|
+
...settledDecisions ? { decisions: syncedDecisions(settledDecisions) } : lock?.decisions ? { decisions: lock.decisions } : {},
|
|
83949
84331
|
meta: nextOrchestrationMeta({
|
|
83950
84332
|
applied: updated,
|
|
83951
84333
|
decisions: metaDecisions,
|
|
@@ -84118,6 +84500,64 @@ async function runOrchestrationStatus(cwd2) {
|
|
|
84118
84500
|
lines.push(` ${import_picocolors54.default.dim(`${left.length} cloud schedule trigger${left.length === 1 ? "" : "s"} not managed by this manifest — push leaves ${left.length === 1 ? "it" : "them"} untouched`)}`);
|
|
84119
84501
|
lines.push("");
|
|
84120
84502
|
}
|
|
84503
|
+
const localDecisions = manifestDecisions(localManifest, new Map([...localSlugByAgentId].map(([agentId, slug]) => [slug, agentId])));
|
|
84504
|
+
const cloudDecisionList = cloudDecisions(cloud, slugForAgent);
|
|
84505
|
+
let decisionsToPush = [];
|
|
84506
|
+
let decisionsToPull = [];
|
|
84507
|
+
if (!cloudDecisionList) {
|
|
84508
|
+
if (localDecisions.length) {
|
|
84509
|
+
lines.push(` ${import_picocolors54.default.dim(`${localDecisions.length} decision${localDecisions.length === 1 ? "" : "s"} in yaml, but the cloud does not show decision nodes to this account — push leaves ${localDecisions.length === 1 ? "it" : "them"} alone`)}`);
|
|
84510
|
+
lines.push("");
|
|
84511
|
+
}
|
|
84512
|
+
} else {
|
|
84513
|
+
const decisionPlan = decideDecisionReconcile({
|
|
84514
|
+
local: localDecisions,
|
|
84515
|
+
cloud: cloudDecisionList,
|
|
84516
|
+
baseline: lock?.decisions,
|
|
84517
|
+
force: false
|
|
84518
|
+
});
|
|
84519
|
+
const byId = new Map([...cloudDecisionList, ...localDecisions].map((d3) => [d3.id, d3]));
|
|
84520
|
+
const label2 = (id) => {
|
|
84521
|
+
const d3 = byId.get(id);
|
|
84522
|
+
return d3 ? decisionLabel(d3) : id;
|
|
84523
|
+
};
|
|
84524
|
+
const localIds = new Set(localDecisions.map((d3) => d3.id));
|
|
84525
|
+
const cloudById = new Map(cloudDecisionList.map((d3) => [d3.id, d3]));
|
|
84526
|
+
decisionsToPush = localDecisions.filter((d3) => {
|
|
84527
|
+
const remote = cloudById.get(d3.id);
|
|
84528
|
+
return !remote || decisionHash(remote) !== decisionHash(d3);
|
|
84529
|
+
});
|
|
84530
|
+
decisionsToPull = cloudDecisionList.filter((d3) => !localIds.has(d3.id));
|
|
84531
|
+
const decisionDeletes = decisionPlan.kind === "reconcile" ? decisionPlan.archives : [];
|
|
84532
|
+
if (decisionsToPush.length || decisionsToPull.length) {
|
|
84533
|
+
lines.push(` ${import_picocolors54.default.bold("decisions")}`);
|
|
84534
|
+
for (const d3 of decisionsToPush) {
|
|
84535
|
+
lines.push(` ${import_picocolors54.default.yellow("→ push")} added/changed in yaml: ${decisionLabel(d3)}`);
|
|
84536
|
+
}
|
|
84537
|
+
for (const d3 of decisionsToPull) {
|
|
84538
|
+
lines.push(decisionDeletes.includes(d3.id) ? ` ${import_picocolors54.default.red("⨯ push deletes")} ${decisionLabel(d3)}` : ` ${import_picocolors54.default.cyan("← pull")} only on cloud: ${decisionLabel(d3)}`);
|
|
84539
|
+
}
|
|
84540
|
+
lines.push("");
|
|
84541
|
+
}
|
|
84542
|
+
if (decisionPlan.kind === "blocked") {
|
|
84543
|
+
lines.push(` ${import_picocolors54.default.bold(import_picocolors54.default.red("decisions: push blocked"))}`);
|
|
84544
|
+
for (const id of decisionPlan.unseen) {
|
|
84545
|
+
lines.push(` ${import_picocolors54.default.red("!")} ${label2(id)} ${import_picocolors54.default.dim("— only in the cloud; pushing would delete it")}`);
|
|
84546
|
+
}
|
|
84547
|
+
for (const id of decisionPlan.cloudModified) {
|
|
84548
|
+
lines.push(` ${import_picocolors54.default.red("!")} ${label2(id)} ${import_picocolors54.default.dim("— edited in the cloud; pushing would overwrite that edit")}`);
|
|
84549
|
+
}
|
|
84550
|
+
for (const id of decisionPlan.staleArchives) {
|
|
84551
|
+
lines.push(` ${import_picocolors54.default.red("!")} ${label2(id)} ${import_picocolors54.default.dim("— deleted here, edited in the cloud since; pushing would delete that edit")}`);
|
|
84552
|
+
}
|
|
84553
|
+
lines.push(` ${import_picocolors54.default.dim("run")} ${import_picocolors54.default.cyan("brainbase orchestration pull")} ${import_picocolors54.default.dim("first")}`);
|
|
84554
|
+
lines.push("");
|
|
84555
|
+
} else if (decisionPlan.kind === "skip") {
|
|
84556
|
+
const left = untouchedRows(decisionPlan);
|
|
84557
|
+
lines.push(` ${import_picocolors54.default.dim(`${left.length} cloud decision${left.length === 1 ? "" : "s"} not managed by this manifest — push leaves ${left.length === 1 ? "it" : "them"} untouched`)}`);
|
|
84558
|
+
lines.push("");
|
|
84559
|
+
}
|
|
84560
|
+
}
|
|
84121
84561
|
const lockByAgentId = new Map((lock?.members ?? []).map((m3) => [m3.agent_id, m3]));
|
|
84122
84562
|
const memberDrift = [];
|
|
84123
84563
|
for (const m3 of cloud.members) {
|
|
@@ -84151,7 +84591,7 @@ async function runOrchestrationStatus(cwd2) {
|
|
|
84151
84591
|
lines.push(` ${import_picocolors54.default.cyan("← pull")} cloud changed since last pull: ${import_picocolors54.default.dim(`lock ${lock.revision} → cloud ${cloud.revision}`)}`);
|
|
84152
84592
|
lines.push("");
|
|
84153
84593
|
}
|
|
84154
|
-
if (!membersAdded.length && !membersRemoved.length && !edgesAdded.length && !edgesRemoved.length && !triggersToPush.length && !triggersToPull.length && !metaDecisions.length && !memberDrift.length && !revisionDrift) {
|
|
84594
|
+
if (!membersAdded.length && !membersRemoved.length && !edgesAdded.length && !edgesRemoved.length && !triggersToPush.length && !triggersToPull.length && !decisionsToPush.length && !decisionsToPull.length && !metaDecisions.length && !memberDrift.length && !revisionDrift) {
|
|
84155
84595
|
lines.push(` ${import_picocolors54.default.green("✓")} everything is in sync`);
|
|
84156
84596
|
lines.push("");
|
|
84157
84597
|
console.log(lines.join(`
|
|
@@ -84506,6 +84946,10 @@ async function runOrchestrationCreate(cwd2, args) {
|
|
|
84506
84946
|
payload_schema: e2.payload_schema ?? {}
|
|
84507
84947
|
}))
|
|
84508
84948
|
});
|
|
84949
|
+
const decisionCount = manifest.decisions?.length ?? 0;
|
|
84950
|
+
if (decisionCount) {
|
|
84951
|
+
f2.info(`Run ${import_picocolors57.default.cyan("brainbase orchestration push")} to add the ${decisionCount} decision${decisionCount === 1 ? "" : "s"} in this manifest.`);
|
|
84952
|
+
}
|
|
84509
84953
|
$e(`Created ${created.name} at revision ${created.revision}.`);
|
|
84510
84954
|
} catch (err) {
|
|
84511
84955
|
sp.stop("Failed.");
|
|
@@ -85764,7 +86208,324 @@ function printTokenHelp() {
|
|
|
85764
86208
|
}
|
|
85765
86209
|
|
|
85766
86210
|
// src/cli/integrations.ts
|
|
86211
|
+
var import_picocolors63 = __toESM(require_picocolors(), 1);
|
|
86212
|
+
|
|
86213
|
+
// src/cli/integration-context.ts
|
|
85767
86214
|
var import_picocolors62 = __toESM(require_picocolors(), 1);
|
|
86215
|
+
|
|
86216
|
+
// src/core/integration-contexts-api.ts
|
|
86217
|
+
var REQUEST_TIMEOUT_MS2 = 30000;
|
|
86218
|
+
var TOKEN_REFUSED_MESSAGE = "Integration contexts can only be created or ended with your own `brainbase login` session, and BRAINBASE_TOKEN is set. " + "Personal access tokens and task keys cannot create or end them. Unset BRAINBASE_TOKEN and run `brainbase login`.";
|
|
86219
|
+
async function resolveHumanSession() {
|
|
86220
|
+
if (process.env.BRAINBASE_TOKEN?.trim()) {
|
|
86221
|
+
throw new ApiError(TOKEN_REFUSED_MESSAGE, 401);
|
|
86222
|
+
}
|
|
86223
|
+
const session = await ensureFreshSession();
|
|
86224
|
+
if (session)
|
|
86225
|
+
return session;
|
|
86226
|
+
const stored = readToken() ? ` The PAT saved in ${TOKEN_FILE} cannot create or end integration contexts.` : "";
|
|
86227
|
+
const problem = readAuth() ? "Your login session has expired and could not be renewed." : "Not logged in.";
|
|
86228
|
+
throw new ApiError(`${problem} Run \`brainbase login\`.${stored}`, 401);
|
|
86229
|
+
}
|
|
86230
|
+
async function contextRequest(pathname, body, operation) {
|
|
86231
|
+
const session = await resolveHumanSession();
|
|
86232
|
+
const base2 = masControlPlaneBaseUrl(session);
|
|
86233
|
+
const send = async (refreshed) => {
|
|
86234
|
+
const current = refreshed ?? session;
|
|
86235
|
+
try {
|
|
86236
|
+
return await fetch(`${masControlPlaneBaseUrl(current)}/v2${pathname}`, {
|
|
86237
|
+
method: "POST",
|
|
86238
|
+
headers: {
|
|
86239
|
+
Authorization: `Bearer ${current.access_token}`,
|
|
86240
|
+
Accept: "application/json",
|
|
86241
|
+
"Content-Type": "application/json"
|
|
86242
|
+
},
|
|
86243
|
+
body: JSON.stringify(body),
|
|
86244
|
+
signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS2)
|
|
86245
|
+
});
|
|
86246
|
+
} catch (err) {
|
|
86247
|
+
throw new ApiError(`Network error: ${err.message}`);
|
|
86248
|
+
}
|
|
86249
|
+
};
|
|
86250
|
+
const res = await sendWithAuthRetry(session, send);
|
|
86251
|
+
let text3;
|
|
86252
|
+
try {
|
|
86253
|
+
text3 = await res.text();
|
|
86254
|
+
} catch (err) {
|
|
86255
|
+
throw new ApiError(`Network error while reading the response: ${err.message}`);
|
|
86256
|
+
}
|
|
86257
|
+
let parsed = text3;
|
|
86258
|
+
try {
|
|
86259
|
+
parsed = text3 ? JSON.parse(text3) : null;
|
|
86260
|
+
} catch {}
|
|
86261
|
+
if (!res.ok) {
|
|
86262
|
+
throw new ApiError(contextErrorMessage(res.status, parsed, operation, base2), res.status, parsed);
|
|
86263
|
+
}
|
|
86264
|
+
return parsed;
|
|
86265
|
+
}
|
|
86266
|
+
function nonEmptyString(value2) {
|
|
86267
|
+
return typeof value2 === "string" && value2.length > 0;
|
|
86268
|
+
}
|
|
86269
|
+
function absentOrString(value2) {
|
|
86270
|
+
return value2 === undefined || typeof value2 === "string";
|
|
86271
|
+
}
|
|
86272
|
+
function isCreatedContext(value2) {
|
|
86273
|
+
const body = record(value2);
|
|
86274
|
+
return !!body && nonEmptyString(body.context_id) && nonEmptyString(body.renewal_handle) && absentOrString(body.renewal_expires_at) && absentOrString(body.max_expires_at);
|
|
86275
|
+
}
|
|
86276
|
+
function isEndedContext(value2) {
|
|
86277
|
+
return typeof record(value2)?.state === "string";
|
|
86278
|
+
}
|
|
86279
|
+
function contextErrorMessage(status, body, operation, base2) {
|
|
86280
|
+
const detail = record(body)?.detail;
|
|
86281
|
+
if (status === 404) {
|
|
86282
|
+
if (detail === "Not Found") {
|
|
86283
|
+
return `Standalone integration contexts are not enabled on this Brainbase deployment (${hostOf(base2)}).`;
|
|
86284
|
+
}
|
|
86285
|
+
if (detail === "agent not found" && operation.kind === "create") {
|
|
86286
|
+
return `Agent ${operation.agentId} was not found, or you cannot manage it. Creating an integration context needs management rights on the agent.`;
|
|
86287
|
+
}
|
|
86288
|
+
if (detail === "integration context not found" && operation.kind === "end") {
|
|
86289
|
+
return `Integration context ${operation.contextId} was not found, or you cannot manage its agent.`;
|
|
86290
|
+
}
|
|
86291
|
+
}
|
|
86292
|
+
if (status === 403 && record(detail)?.code === "human_credential_required") {
|
|
86293
|
+
return "Brainbase refused this credential: integration contexts can only be created or ended with your own `brainbase login` session. Run `brainbase login` and try again.";
|
|
86294
|
+
}
|
|
86295
|
+
if (status === 401) {
|
|
86296
|
+
return `Brainbase did not accept your login session (${sanitizeLabel(masApiErrorMessage(body, status))}). Run \`brainbase login\` to sign in again.`;
|
|
86297
|
+
}
|
|
86298
|
+
if (status === 422) {
|
|
86299
|
+
const fields = fastApiValidationMessage(body);
|
|
86300
|
+
if (fields)
|
|
86301
|
+
return `Brainbase rejected the request: ${fields}`;
|
|
86302
|
+
}
|
|
86303
|
+
return sanitizeLabel(masApiErrorMessage(body, status));
|
|
86304
|
+
}
|
|
86305
|
+
function hostOf(base2) {
|
|
86306
|
+
try {
|
|
86307
|
+
return new URL(base2).host;
|
|
86308
|
+
} catch {
|
|
86309
|
+
return sanitizeLabel(base2);
|
|
86310
|
+
}
|
|
86311
|
+
}
|
|
86312
|
+
var integrationContextsApi = {
|
|
86313
|
+
async create(input) {
|
|
86314
|
+
const created = await contextRequest("/integration-contexts", input, {
|
|
86315
|
+
kind: "create",
|
|
86316
|
+
agentId: input.agent_id
|
|
86317
|
+
});
|
|
86318
|
+
if (!isCreatedContext(created)) {
|
|
86319
|
+
throw new ApiError("Brainbase answered without a context id and renewal handle.");
|
|
86320
|
+
}
|
|
86321
|
+
return created;
|
|
86322
|
+
},
|
|
86323
|
+
async end(contextId, reason) {
|
|
86324
|
+
const ended = await contextRequest(`/integration-contexts/${encodeURIComponent(contextId)}/end`, { reason }, { kind: "end", contextId });
|
|
86325
|
+
if (!isEndedContext(ended)) {
|
|
86326
|
+
throw new ApiError("Brainbase answered without the context state.");
|
|
86327
|
+
}
|
|
86328
|
+
return ended;
|
|
86329
|
+
}
|
|
86330
|
+
};
|
|
86331
|
+
|
|
86332
|
+
// src/cli/integration-context.ts
|
|
86333
|
+
var MIN_LIFETIME_S = 60;
|
|
86334
|
+
var MAX_LIFETIME_S = 30 * 24 * 60 * 60;
|
|
86335
|
+
var DEFAULT_LIFETIME_S = 7 * 24 * 60 * 60;
|
|
86336
|
+
var DEFAULT_END_REASON = "ended with brainbase integrations context end";
|
|
86337
|
+
var MAX_REASON_LENGTH2 = 200;
|
|
86338
|
+
var APPLICATION_PATTERN = /^[a-z0-9][a-z0-9._:/-]{0,119}$/;
|
|
86339
|
+
var UUID_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
86340
|
+
var UNIT_SECONDS = { "": 1, s: 1, m: 60, h: 3600, d: 86400 };
|
|
86341
|
+
var CONTEXT_USAGE = `Usage: brainbase integrations context <create|end> [--json]
|
|
86342
|
+
|
|
86343
|
+
create [--agent <id>] --application <name> [--max-lifetime <dur>]
|
|
86344
|
+
Let a program outside Brainbase (the Brainbase SDK) use the agent's
|
|
86345
|
+
integrations on your behalf. Prints a renewal handle once: store it in
|
|
86346
|
+
that program's secret store. It rotates on every renewal, so the program
|
|
86347
|
+
must keep the newest one.
|
|
86348
|
+
--agent the agent's id; defaults to the agent this folder is linked to
|
|
86349
|
+
--application names the program: up to 120 of a-z 0-9 . _ : / -,
|
|
86350
|
+
starting with a letter or digit (e.g. billing-sync)
|
|
86351
|
+
--max-lifetime when the context ends at the latest: 60s to 30d, as
|
|
86352
|
+
seconds or <n>s, <n>m, <n>h, <n>d. Default 7d.
|
|
86353
|
+
|
|
86354
|
+
end <context-id> [--reason <text>]
|
|
86355
|
+
End a context now. Its renewal handle and access grants stop working.
|
|
86356
|
+
--reason recorded with the context, 1-200 characters
|
|
86357
|
+
(default "${DEFAULT_END_REASON}")
|
|
86358
|
+
|
|
86359
|
+
Both need your own \`brainbase login\` session and management rights on the
|
|
86360
|
+
agent. BRAINBASE_TOKEN and the PAT saved by \`brainbase token create\` are refused.
|
|
86361
|
+
`;
|
|
86362
|
+
async function runIntegrationContext(cwd2, argv, options) {
|
|
86363
|
+
const { write: write3, fail: fail3 } = options;
|
|
86364
|
+
const [action, ...rest2] = argv;
|
|
86365
|
+
const parsed = parseContextArgs(rest2, "--application", "--max-lifetime", "--reason");
|
|
86366
|
+
if (action === "help" || action === "--help" || action === "-h" || "help" in parsed) {
|
|
86367
|
+
write3(CONTEXT_USAGE);
|
|
86368
|
+
return 0;
|
|
86369
|
+
}
|
|
86370
|
+
if (action !== "create" && action !== "end") {
|
|
86371
|
+
const problem = action ? `Unknown integrations context subcommand: ${sanitizeLabel(action)}.` : "Missing integrations context subcommand.";
|
|
86372
|
+
return fail3(`${problem} ${CONTEXT_USAGE.split(`
|
|
86373
|
+
`)[0]}`);
|
|
86374
|
+
}
|
|
86375
|
+
if ("error" in parsed)
|
|
86376
|
+
return fail3(parsed.error);
|
|
86377
|
+
const { values: values2, positionals } = parsed;
|
|
86378
|
+
if (action === "create") {
|
|
86379
|
+
if (positionals.length > 0)
|
|
86380
|
+
return fail3(`Unexpected argument: ${sanitizeLabel(positionals[0])}. ${CREATE_USAGE}`);
|
|
86381
|
+
if (values2.has("--reason"))
|
|
86382
|
+
return fail3(`--reason is for \`context end\`. ${CREATE_USAGE}`);
|
|
86383
|
+
const target = cloudTargetAgent(cwd2, options);
|
|
86384
|
+
if (!target)
|
|
86385
|
+
return fail3(NO_AGENT_MESSAGE);
|
|
86386
|
+
if ("error" in target)
|
|
86387
|
+
return fail3(target.error);
|
|
86388
|
+
if (!UUID_PATTERN.test(target.agentId)) {
|
|
86389
|
+
return fail3(`${sanitizeLabel(target.agentId)} is not an agent id. --agent takes the agent's UUID, as \`brainbase agent list\` shows it.`);
|
|
86390
|
+
}
|
|
86391
|
+
const agentId = target.agentId.toLowerCase();
|
|
86392
|
+
const application = values2.get("--application");
|
|
86393
|
+
if (application === undefined)
|
|
86394
|
+
return fail3(`--application is required. ${CREATE_USAGE}`);
|
|
86395
|
+
if (!APPLICATION_PATTERN.test(application)) {
|
|
86396
|
+
return fail3(`--application must be 1-120 characters of lowercase letters, digits and . _ : / -, starting with a letter or digit (e.g. billing-sync); got "${sanitizeLabel(application)}".`);
|
|
86397
|
+
}
|
|
86398
|
+
const rawLifetime = values2.get("--max-lifetime");
|
|
86399
|
+
const lifetime = rawLifetime === undefined ? DEFAULT_LIFETIME_S : parseMaxLifetime(rawLifetime);
|
|
86400
|
+
if (typeof lifetime !== "number")
|
|
86401
|
+
return fail3(lifetime.error);
|
|
86402
|
+
let created;
|
|
86403
|
+
try {
|
|
86404
|
+
created = await integrationContextsApi.create({
|
|
86405
|
+
agent_id: agentId,
|
|
86406
|
+
application,
|
|
86407
|
+
max_lifetime_s: lifetime
|
|
86408
|
+
});
|
|
86409
|
+
} catch (err) {
|
|
86410
|
+
return fail3(`brainbase integrations context create failed: ${message(err)}`);
|
|
86411
|
+
}
|
|
86412
|
+
if (options.json) {
|
|
86413
|
+
write3(JSON.stringify(created) + `
|
|
86414
|
+
`);
|
|
86415
|
+
return 0;
|
|
86416
|
+
}
|
|
86417
|
+
write3(renderCreated(created, agentId, application));
|
|
86418
|
+
return 0;
|
|
86419
|
+
}
|
|
86420
|
+
if (values2.has("--application") || values2.has("--max-lifetime")) {
|
|
86421
|
+
return fail3(`--application and --max-lifetime are for \`context create\`. ${END_USAGE}`);
|
|
86422
|
+
}
|
|
86423
|
+
if (positionals.length !== 1)
|
|
86424
|
+
return fail3(END_USAGE);
|
|
86425
|
+
const contextId = positionals[0];
|
|
86426
|
+
if (!UUID_PATTERN.test(contextId)) {
|
|
86427
|
+
return fail3(`${sanitizeLabel(contextId)} is not a context id. Pass the context_id \`context create\` printed.`);
|
|
86428
|
+
}
|
|
86429
|
+
const reason = (values2.get("--reason") ?? DEFAULT_END_REASON).trim();
|
|
86430
|
+
const reasonLength = [...reason].length;
|
|
86431
|
+
if (reasonLength < 1 || reasonLength > MAX_REASON_LENGTH2) {
|
|
86432
|
+
return fail3(`--reason must be 1-${MAX_REASON_LENGTH2} characters; got ${reasonLength}.`);
|
|
86433
|
+
}
|
|
86434
|
+
let ended;
|
|
86435
|
+
try {
|
|
86436
|
+
ended = await integrationContextsApi.end(contextId.toLowerCase(), reason);
|
|
86437
|
+
} catch (err) {
|
|
86438
|
+
return fail3(`brainbase integrations context end failed: ${message(err)}`);
|
|
86439
|
+
}
|
|
86440
|
+
const id = contextId.toLowerCase();
|
|
86441
|
+
if (options.json) {
|
|
86442
|
+
write3(JSON.stringify({ context_id: id, ...ended }) + `
|
|
86443
|
+
`);
|
|
86444
|
+
return 0;
|
|
86445
|
+
}
|
|
86446
|
+
const state = sanitizeLabel(ended.state);
|
|
86447
|
+
write3(state === "ended" ? `${import_picocolors62.default.green("✓")} Ended integration context ${id}. Its renewal handle and access grants no longer work.
|
|
86448
|
+
` : `Integration context ${id} is ${state}. Its renewal handle and access grants no longer work.
|
|
86449
|
+
`);
|
|
86450
|
+
return 0;
|
|
86451
|
+
}
|
|
86452
|
+
var CREATE_USAGE = "Usage: brainbase integrations context create [--agent <id>] --application <name> [--max-lifetime <dur>]";
|
|
86453
|
+
var END_USAGE = "Usage: brainbase integrations context end <context-id> [--reason <text>]";
|
|
86454
|
+
function parseContextArgs(rest2, ...valueFlags) {
|
|
86455
|
+
for (let i = 0;i < rest2.length; i++) {
|
|
86456
|
+
if (valueFlags.includes(rest2[i]))
|
|
86457
|
+
i++;
|
|
86458
|
+
else if (rest2[i] === "--help" || rest2[i] === "-h")
|
|
86459
|
+
return { help: true };
|
|
86460
|
+
}
|
|
86461
|
+
const values2 = new Map;
|
|
86462
|
+
const positionals = [];
|
|
86463
|
+
for (let i = 0;i < rest2.length; i++) {
|
|
86464
|
+
const arg = rest2[i];
|
|
86465
|
+
const eq = arg.indexOf("=");
|
|
86466
|
+
const name = arg.startsWith("--") && eq > 0 ? arg.slice(0, eq) : arg;
|
|
86467
|
+
if (valueFlags.includes(name)) {
|
|
86468
|
+
let value2;
|
|
86469
|
+
if (name !== arg) {
|
|
86470
|
+
value2 = arg.slice(eq + 1);
|
|
86471
|
+
} else {
|
|
86472
|
+
value2 = rest2[i + 1];
|
|
86473
|
+
if (value2 === undefined || name !== "--reason" && value2.startsWith("-")) {
|
|
86474
|
+
return { error: `${name} needs a value.` };
|
|
86475
|
+
}
|
|
86476
|
+
i++;
|
|
86477
|
+
}
|
|
86478
|
+
if (values2.has(name))
|
|
86479
|
+
return { error: `${name} was given more than once.` };
|
|
86480
|
+
values2.set(name, value2);
|
|
86481
|
+
continue;
|
|
86482
|
+
}
|
|
86483
|
+
if (arg.startsWith("-")) {
|
|
86484
|
+
return { error: `Unknown option for brainbase integrations context: ${sanitizeLabel(arg)}` };
|
|
86485
|
+
}
|
|
86486
|
+
positionals.push(arg);
|
|
86487
|
+
}
|
|
86488
|
+
return { values: values2, positionals };
|
|
86489
|
+
}
|
|
86490
|
+
function parseMaxLifetime(raw) {
|
|
86491
|
+
const match = /^(\d+)([smhd]?)$/i.exec(raw.trim());
|
|
86492
|
+
if (!match) {
|
|
86493
|
+
return { error: `--max-lifetime takes seconds or a duration such as 90m, 12h or 7d; got "${sanitizeLabel(raw)}".` };
|
|
86494
|
+
}
|
|
86495
|
+
const seconds = Number(match[1]) * UNIT_SECONDS[match[2].toLowerCase()];
|
|
86496
|
+
if (!Number.isSafeInteger(seconds) || seconds < MIN_LIFETIME_S || seconds > MAX_LIFETIME_S) {
|
|
86497
|
+
return {
|
|
86498
|
+
error: `--max-lifetime must be between 60s and 30d (${MAX_LIFETIME_S} seconds); got "${sanitizeLabel(raw)}".`
|
|
86499
|
+
};
|
|
86500
|
+
}
|
|
86501
|
+
return seconds;
|
|
86502
|
+
}
|
|
86503
|
+
function renderCreated(created, agentId, application) {
|
|
86504
|
+
const id = sanitizeLabel(created.context_id);
|
|
86505
|
+
const lines = [
|
|
86506
|
+
`${import_picocolors62.default.green("✓")} Created integration context ${id}`,
|
|
86507
|
+
` ${import_picocolors62.default.dim(`agent ${agentId} · application ${application}`)}`,
|
|
86508
|
+
"",
|
|
86509
|
+
" Renewal handle:",
|
|
86510
|
+
"",
|
|
86511
|
+
` ${sanitizeLabel(created.renewal_handle)}`,
|
|
86512
|
+
"",
|
|
86513
|
+
import_picocolors62.default.yellow(" Store it now in the SDK program's secret store: it is shown only this once, and it rotates on every renewal, so the program must save the newest handle each time."),
|
|
86514
|
+
"",
|
|
86515
|
+
` Handle expires ${sanitizeLabel(created.renewal_expires_at ?? "unknown")}`,
|
|
86516
|
+
` Context ends ${sanitizeLabel(created.max_expires_at ?? "unknown")} ${import_picocolors62.default.dim("(its maximum lifetime)")}`,
|
|
86517
|
+
"",
|
|
86518
|
+
import_picocolors62.default.dim(` End it sooner with \`brainbase integrations context end ${id}\`.`),
|
|
86519
|
+
""
|
|
86520
|
+
];
|
|
86521
|
+
return lines.join(`
|
|
86522
|
+
`);
|
|
86523
|
+
}
|
|
86524
|
+
function message(err) {
|
|
86525
|
+
return sanitizeLabel(err?.message ?? String(err));
|
|
86526
|
+
}
|
|
86527
|
+
|
|
86528
|
+
// src/cli/integrations.ts
|
|
85768
86529
|
var EFFECTS = ["allow", "ask", "deny"];
|
|
85769
86530
|
var USAGE = `Usage: brainbase integrations <command> [--agent <id>] [--json]
|
|
85770
86531
|
|
|
@@ -85776,6 +86537,12 @@ var USAGE = `Usage: brainbase integrations <command> [--agent <id>] [--json]
|
|
|
85776
86537
|
disconnect <app> delete the app's connected account [--account <id>] [--yes]
|
|
85777
86538
|
remove <app> uninstall an app that needs no account
|
|
85778
86539
|
allow|ask|deny <app>[.<action>] set the permission for an app or one action
|
|
86540
|
+
context create --application <name> [--max-lifetime <dur>]
|
|
86541
|
+
let a program outside Brainbase (the SDK) use the agent's
|
|
86542
|
+
integrations; prints a renewal handle once. Lifetime 60s-30d, default 7d
|
|
86543
|
+
context end <context-id> [--reason <text>]
|
|
86544
|
+
end a standalone integration context now
|
|
86545
|
+
(\`brainbase integrations context --help\` for details)
|
|
85779
86546
|
`;
|
|
85780
86547
|
var POLL_INTERVAL_MS2 = 2000;
|
|
85781
86548
|
var MAX_CONSECUTIVE_POLL_FAILURES2 = 5;
|
|
@@ -85785,12 +86552,12 @@ async function runIntegrations(cwd2, sub, argv, options) {
|
|
|
85785
86552
|
const write3 = options.write ?? ((s3) => process.stdout.write(s3));
|
|
85786
86553
|
const writeErr = options.writeErr ?? ((s3) => process.stderr.write(s3));
|
|
85787
86554
|
const api4 = { ...integrationsApi, ...options.api };
|
|
85788
|
-
const fail3 = (
|
|
86555
|
+
const fail3 = (message2) => {
|
|
85789
86556
|
if (options.json)
|
|
85790
|
-
write3(JSON.stringify({ error:
|
|
86557
|
+
write3(JSON.stringify({ error: message2 }) + `
|
|
85791
86558
|
`);
|
|
85792
86559
|
else
|
|
85793
|
-
writeErr(
|
|
86560
|
+
writeErr(message2 + `
|
|
85794
86561
|
`);
|
|
85795
86562
|
return 1;
|
|
85796
86563
|
};
|
|
@@ -85799,6 +86566,15 @@ async function runIntegrations(cwd2, sub, argv, options) {
|
|
|
85799
86566
|
` : human);
|
|
85800
86567
|
return 0;
|
|
85801
86568
|
};
|
|
86569
|
+
if (sub === "context") {
|
|
86570
|
+
return await runIntegrationContext(cwd2, argv, {
|
|
86571
|
+
json: options.json,
|
|
86572
|
+
agentId: options.agentId,
|
|
86573
|
+
resolveAgentId: options.resolveAgentId,
|
|
86574
|
+
write: write3,
|
|
86575
|
+
fail: fail3
|
|
86576
|
+
});
|
|
86577
|
+
}
|
|
85802
86578
|
const isHelpFlag = (s3) => s3 === "--help" || s3 === "-h";
|
|
85803
86579
|
if (sub === "help" || isHelpFlag(sub) || argv.some(isHelpFlag)) {
|
|
85804
86580
|
write3(USAGE);
|
|
@@ -85824,7 +86600,7 @@ ${USAGE}`);
|
|
|
85824
86600
|
const apps = await api4.searchApps(arg);
|
|
85825
86601
|
return out({ apps }, renderSearch(apps));
|
|
85826
86602
|
} catch (err) {
|
|
85827
|
-
return fail3(`brainbase integrations search failed: ${
|
|
86603
|
+
return fail3(`brainbase integrations search failed: ${message2(err)}`);
|
|
85828
86604
|
}
|
|
85829
86605
|
}
|
|
85830
86606
|
const target = cloudTargetAgent(cwd2, options);
|
|
@@ -85851,7 +86627,7 @@ ${USAGE}`);
|
|
|
85851
86627
|
return await setEffect(agentId, sub, arg);
|
|
85852
86628
|
}
|
|
85853
86629
|
} catch (err) {
|
|
85854
|
-
return fail3(`brainbase integrations ${sub} failed: ${
|
|
86630
|
+
return fail3(`brainbase integrations ${sub} failed: ${message2(err)}`);
|
|
85855
86631
|
}
|
|
85856
86632
|
async function list3(agentId2) {
|
|
85857
86633
|
const [accounts, noAuthApps, permissions] = await Promise.all([
|
|
@@ -85904,7 +86680,7 @@ ${USAGE}`);
|
|
|
85904
86680
|
if (needsAccount(app))
|
|
85905
86681
|
return await connect2(agentId2, slug, app);
|
|
85906
86682
|
const added = await api4.addNoAuthApp(agentId2, slug);
|
|
85907
|
-
return out({ app: added.appSlug, name: added.name, needs_account: false, added: true }, `${
|
|
86683
|
+
return out({ app: added.appSlug, name: added.name, needs_account: false, added: true }, `${import_picocolors63.default.green("✓")} Added ${import_picocolors63.default.bold(label2(added.name))}. It needs no account; your agent can use it on its next turn.
|
|
85908
86684
|
`);
|
|
85909
86685
|
}
|
|
85910
86686
|
async function connect2(agentId2, slug, known2) {
|
|
@@ -85924,20 +86700,20 @@ ${USAGE}`);
|
|
|
85924
86700
|
return 0;
|
|
85925
86701
|
}
|
|
85926
86702
|
const interactive = options.interactive ?? isInteractive();
|
|
85927
|
-
write3(`Open this link to connect ${
|
|
86703
|
+
write3(`Open this link to connect ${import_picocolors63.default.bold(name)}:
|
|
85928
86704
|
|
|
85929
|
-
${
|
|
86705
|
+
${import_picocolors63.default.cyan(url2)}
|
|
85930
86706
|
|
|
85931
86707
|
`);
|
|
85932
|
-
write3(
|
|
86708
|
+
write3(import_picocolors63.default.dim(`Anyone with this link can connect an account to this agent until it expires, so do not share it.
|
|
85933
86709
|
`));
|
|
85934
86710
|
if (!options.noOpen && interactive) {
|
|
85935
|
-
write3(
|
|
86711
|
+
write3(import_picocolors63.default.dim(`Opening your browser…
|
|
85936
86712
|
`));
|
|
85937
86713
|
(options.openUrl ?? openInBrowser)(url2);
|
|
85938
86714
|
}
|
|
85939
86715
|
if (options.noWait) {
|
|
85940
|
-
write3(
|
|
86716
|
+
write3(import_picocolors63.default.dim("Not waiting. Run `brainbase integrations list` to see when it is connected.\n"));
|
|
85941
86717
|
return 0;
|
|
85942
86718
|
}
|
|
85943
86719
|
const controller = new AbortController;
|
|
@@ -85970,7 +86746,7 @@ ${USAGE}`);
|
|
|
85970
86746
|
if (spinner2)
|
|
85971
86747
|
spinner2.stop(text3, ok ? 0 : 2);
|
|
85972
86748
|
else if (ok)
|
|
85973
|
-
write3(`${
|
|
86749
|
+
write3(`${import_picocolors63.default.green("✔")} ${text3}
|
|
85974
86750
|
`);
|
|
85975
86751
|
else
|
|
85976
86752
|
writeErr(`${text3}
|
|
@@ -86010,11 +86786,11 @@ ${USAGE}`);
|
|
|
86010
86786
|
const confirm = options.confirmDisconnect ?? promptForDisconnect;
|
|
86011
86787
|
const accountLabel = account.name ? `${label2(account.name)} (${account.id})` : account.id;
|
|
86012
86788
|
if (!await confirm(`Disconnect ${label2(slug)} account ${accountLabel}? Everyone using this agent loses it.`, options.yes)) {
|
|
86013
|
-
return out({ app: slug, account_id: account.id, disconnected: false, outcome: "declined" }, ` ${
|
|
86789
|
+
return out({ app: slug, account_id: account.id, disconnected: false, outcome: "declined" }, ` ${import_picocolors63.default.dim("Left alone.")}
|
|
86014
86790
|
`);
|
|
86015
86791
|
}
|
|
86016
86792
|
await api4.deleteAccount(agentId2, account.id);
|
|
86017
|
-
return out({ app: slug, account_id: account.id, disconnected: true }, `${
|
|
86793
|
+
return out({ app: slug, account_id: account.id, disconnected: true }, `${import_picocolors63.default.green("✓")} Disconnected ${import_picocolors63.default.bold(label2(slug))} account ${accountLabel}.
|
|
86018
86794
|
`);
|
|
86019
86795
|
}
|
|
86020
86796
|
async function remove2(agentId2, slug) {
|
|
@@ -86027,7 +86803,7 @@ ${USAGE}`);
|
|
|
86027
86803
|
return fail3(`${label2(slug)} is not installed on this agent.`);
|
|
86028
86804
|
}
|
|
86029
86805
|
await api4.removeNoAuthApp(agentId2, slug);
|
|
86030
|
-
return out({ app: slug, removed: true }, `${
|
|
86806
|
+
return out({ app: slug, removed: true }, `${import_picocolors63.default.green("✓")} Removed ${import_picocolors63.default.bold(label2(slug))}.
|
|
86031
86807
|
`);
|
|
86032
86808
|
}
|
|
86033
86809
|
async function setEffect(agentId2, effect, raw) {
|
|
@@ -86040,7 +86816,7 @@ ${USAGE}`);
|
|
|
86040
86816
|
const capability = pattern(appSlug(app), action);
|
|
86041
86817
|
await api4.setPermission(agentId2, capability, effect);
|
|
86042
86818
|
const scope = action ? `${label2(action)} on ${label2(app)}` : `every ${label2(app)} action without its own rule`;
|
|
86043
|
-
return out({ capability_pattern: capability, effect }, `${
|
|
86819
|
+
return out({ capability_pattern: capability, effect }, `${import_picocolors63.default.green("✓")} ${capability} → ${import_picocolors63.default.bold(effect)} ${import_picocolors63.default.dim(`(${scope})`)}
|
|
86044
86820
|
`);
|
|
86045
86821
|
}
|
|
86046
86822
|
}
|
|
@@ -86050,7 +86826,7 @@ function appSlug(raw) {
|
|
|
86050
86826
|
function label2(s3) {
|
|
86051
86827
|
return sanitizeLabel(s3);
|
|
86052
86828
|
}
|
|
86053
|
-
function
|
|
86829
|
+
function message2(err) {
|
|
86054
86830
|
return sanitizeLabel(err?.message ?? String(err));
|
|
86055
86831
|
}
|
|
86056
86832
|
function needsAccount(app) {
|
|
@@ -86093,27 +86869,27 @@ async function promptForDisconnect(question, yes) {
|
|
|
86093
86869
|
return ensureNotCancelled(answer);
|
|
86094
86870
|
}
|
|
86095
86871
|
var EFFECT_COLOR = {
|
|
86096
|
-
allow:
|
|
86097
|
-
ask:
|
|
86098
|
-
deny:
|
|
86872
|
+
allow: import_picocolors63.default.green,
|
|
86873
|
+
ask: import_picocolors63.default.yellow,
|
|
86874
|
+
deny: import_picocolors63.default.red
|
|
86099
86875
|
};
|
|
86100
86876
|
function effectLabel(effect, width = 0) {
|
|
86101
|
-
return (EFFECT_COLOR[effect] ??
|
|
86877
|
+
return (EFFECT_COLOR[effect] ?? import_picocolors63.default.dim)(sanitizeLabel(effect).padEnd(width));
|
|
86102
86878
|
}
|
|
86103
86879
|
function renderList(rows, permissions) {
|
|
86104
86880
|
const lines = [""];
|
|
86105
86881
|
if (!permissions.permissionsAvailable) {
|
|
86106
|
-
lines.push(
|
|
86882
|
+
lines.push(import_picocolors63.default.yellow(" Integrations only work on Kafka agents for now; this agent cannot use them."), "");
|
|
86107
86883
|
}
|
|
86108
86884
|
if (rows.length === 0) {
|
|
86109
|
-
lines.push(
|
|
86110
|
-
lines.push(
|
|
86885
|
+
lines.push(import_picocolors63.default.dim(" No integrations on this agent."));
|
|
86886
|
+
lines.push(import_picocolors63.default.dim(" Find one with `brainbase integrations search <query>`, then `brainbase integrations add <app>`."), "");
|
|
86111
86887
|
return lines.join(`
|
|
86112
86888
|
`);
|
|
86113
86889
|
}
|
|
86114
86890
|
for (const row of rows) {
|
|
86115
86891
|
const healthy = row.accounts.every((a3) => a3.healthy);
|
|
86116
|
-
const mark = healthy ?
|
|
86892
|
+
const mark = healthy ? import_picocolors63.default.green("✓") : import_picocolors63.default.yellow("!");
|
|
86117
86893
|
const bits = [sanitizeLabel(row.name)];
|
|
86118
86894
|
if (!row.needs_account)
|
|
86119
86895
|
bits.push("no account needed");
|
|
@@ -86121,35 +86897,35 @@ function renderList(rows, permissions) {
|
|
|
86121
86897
|
bits.push(`account ${account.name ? sanitizeLabel(account.name) : account.id}${account.healthy ? "" : " (needs reconnecting)"}`);
|
|
86122
86898
|
}
|
|
86123
86899
|
const effect = row.effect ?? permissions.defaultEffect;
|
|
86124
|
-
lines.push(` ${mark} ${
|
|
86900
|
+
lines.push(` ${mark} ${import_picocolors63.default.bold(sanitizeLabel(row.app))} ${import_picocolors63.default.dim(bits.join(" · "))} ${effectLabel(effect)}${row.effect ? "" : import_picocolors63.default.dim(" (default)")}`);
|
|
86125
86901
|
}
|
|
86126
|
-
lines.push("",
|
|
86902
|
+
lines.push("", import_picocolors63.default.dim(" Run `brainbase integrations actions <app>` to see and set per-action permissions."), "");
|
|
86127
86903
|
return lines.join(`
|
|
86128
86904
|
`);
|
|
86129
86905
|
}
|
|
86130
86906
|
function renderSearch(apps) {
|
|
86131
86907
|
if (apps.length === 0)
|
|
86132
|
-
return
|
|
86908
|
+
return import_picocolors63.default.dim("No apps match.") + `
|
|
86133
86909
|
`;
|
|
86134
86910
|
const lines = [""];
|
|
86135
86911
|
for (const app of apps) {
|
|
86136
|
-
const hint = needsAccount(app) ? "" :
|
|
86137
|
-
lines.push(` ${
|
|
86912
|
+
const hint = needsAccount(app) ? "" : import_picocolors63.default.dim(" no account needed");
|
|
86913
|
+
lines.push(` ${import_picocolors63.default.bold(sanitizeLabel(app.nameSlug))} ${sanitizeLabel(app.name)}${hint}`);
|
|
86138
86914
|
}
|
|
86139
|
-
lines.push("",
|
|
86915
|
+
lines.push("", import_picocolors63.default.dim(" Add one with `brainbase integrations add <app>`."), "");
|
|
86140
86916
|
return lines.join(`
|
|
86141
86917
|
`);
|
|
86142
86918
|
}
|
|
86143
86919
|
function renderActions(slug, rows) {
|
|
86144
86920
|
if (rows.length === 0)
|
|
86145
|
-
return
|
|
86921
|
+
return import_picocolors63.default.dim(`No actions found for ${sanitizeLabel(slug)}.`) + `
|
|
86146
86922
|
`;
|
|
86147
86923
|
const lines = [""];
|
|
86148
86924
|
for (const row of rows) {
|
|
86149
|
-
const source =
|
|
86150
|
-
lines.push(` ${effectLabel(row.effect, 5)} ${source} ${
|
|
86925
|
+
const source = import_picocolors63.default.dim((row.source === "action" ? "" : `(${row.source})`).padEnd(9));
|
|
86926
|
+
lines.push(` ${effectLabel(row.effect, 5)} ${source} ${import_picocolors63.default.bold(sanitizeLabel(row.key))} ${import_picocolors63.default.dim(sanitizeLabel(row.name))}`);
|
|
86151
86927
|
}
|
|
86152
|
-
lines.push("",
|
|
86928
|
+
lines.push("", import_picocolors63.default.dim(` Change one with \`brainbase integrations allow|ask|deny ${sanitizeLabel(slug)}.<action>\`, or the whole app with \`… ${sanitizeLabel(slug)}\`.`), "");
|
|
86153
86929
|
return lines.join(`
|
|
86154
86930
|
`);
|
|
86155
86931
|
}
|
|
@@ -86213,14 +86989,14 @@ async function waitForAccount(agentId, slug, before2, options) {
|
|
|
86213
86989
|
}
|
|
86214
86990
|
|
|
86215
86991
|
// src/cli/task.ts
|
|
86216
|
-
var
|
|
86992
|
+
var import_picocolors69 = __toESM(require_picocolors(), 1);
|
|
86217
86993
|
|
|
86218
86994
|
// src/cli/task-create.ts
|
|
86219
|
-
var
|
|
86995
|
+
var import_picocolors65 = __toESM(require_picocolors(), 1);
|
|
86220
86996
|
import { randomUUID as randomUUID4 } from "node:crypto";
|
|
86221
86997
|
|
|
86222
86998
|
// src/cli/task-update.ts
|
|
86223
|
-
var
|
|
86999
|
+
var import_picocolors64 = __toESM(require_picocolors(), 1);
|
|
86224
87000
|
var TASK_UPDATE_USAGE = "brainbase task update <task-id> [--title <text> | --clear-title] [--metadata key=value]... [--unset-metadata <key>]... [--clear-metadata] [--model <id> | --clear-model] [--json]";
|
|
86225
87001
|
var TITLE_MAX = 200;
|
|
86226
87002
|
var MODEL_UNSUPPORTED = "This control plane does not support changing a task's model yet.";
|
|
@@ -86359,25 +87135,25 @@ function applyLabelEdit(current, edit) {
|
|
|
86359
87135
|
}
|
|
86360
87136
|
function format(task) {
|
|
86361
87137
|
const lines = [""];
|
|
86362
|
-
const title = task.title?.trim() ? sanitizeLabel(task.title) :
|
|
86363
|
-
lines.push(` ${
|
|
87138
|
+
const title = task.title?.trim() ? sanitizeLabel(task.title) : import_picocolors64.default.dim("(untitled)");
|
|
87139
|
+
lines.push(` ${import_picocolors64.default.green("updated")} ${import_picocolors64.default.bold(title)}`);
|
|
86364
87140
|
lines.push("");
|
|
86365
|
-
lines.push(` ${
|
|
87141
|
+
lines.push(` ${import_picocolors64.default.dim("task")} ${sanitizeLabel(task.id)}`);
|
|
86366
87142
|
if (task.model !== undefined) {
|
|
86367
|
-
const model = task.model?.trim() ? sanitizeLabel(task.model) :
|
|
86368
|
-
lines.push(` ${
|
|
87143
|
+
const model = task.model?.trim() ? sanitizeLabel(task.model) : import_picocolors64.default.dim("agent default");
|
|
87144
|
+
lines.push(` ${import_picocolors64.default.dim("model")} ${model}`);
|
|
86369
87145
|
}
|
|
86370
87146
|
const metadata = Object.entries(task.metadata ?? {});
|
|
86371
87147
|
lines.push("");
|
|
86372
|
-
lines.push(` ${
|
|
87148
|
+
lines.push(` ${import_picocolors64.default.bold(import_picocolors64.default.dim("METADATA"))}`);
|
|
86373
87149
|
if (metadata.length === 0) {
|
|
86374
|
-
lines.push(` ${
|
|
87150
|
+
lines.push(` ${import_picocolors64.default.dim("none")}`);
|
|
86375
87151
|
}
|
|
86376
87152
|
for (const [key2, value2] of metadata) {
|
|
86377
|
-
lines.push(` ${
|
|
87153
|
+
lines.push(` ${import_picocolors64.default.dim(sanitizeLabel(key2))} ${sanitizeLabel(value2)}`);
|
|
86378
87154
|
}
|
|
86379
87155
|
lines.push("");
|
|
86380
|
-
lines.push(` ${
|
|
87156
|
+
lines.push(` ${import_picocolors64.default.dim("read it with")} ${import_picocolors64.default.cyan(`brainbase task get ${sanitizeLabel(task.id)}`)}`, "");
|
|
86381
87157
|
return lines.join(`
|
|
86382
87158
|
`);
|
|
86383
87159
|
}
|
|
@@ -86423,13 +87199,13 @@ async function resolveAgentId2(cwd2, agentId, interfaceId, readLocalManifest) {
|
|
|
86423
87199
|
return manifest.id;
|
|
86424
87200
|
}
|
|
86425
87201
|
function isPublishScopeError(error2) {
|
|
86426
|
-
const
|
|
87202
|
+
const message3 = error2 instanceof Error ? error2.message : String(error2);
|
|
86427
87203
|
const body = error2 && typeof error2 === "object" && "body" in error2 ? JSON.stringify(error2.body) : "";
|
|
86428
|
-
return /PAT lacks required scope:\s*publish/i.test(`${
|
|
87204
|
+
return /PAT lacks required scope:\s*publish/i.test(`${message3} ${body}`);
|
|
86429
87205
|
}
|
|
86430
87206
|
async function runTaskCreate(cwd2, options, dependencies = {}) {
|
|
86431
87207
|
const idempotencyKey = (dependencies.randomUUID ?? randomUUID4)();
|
|
86432
|
-
const
|
|
87208
|
+
const message3 = requiredValue(options.message, "--message");
|
|
86433
87209
|
const interfaceId = optionalValue(options.interfaceId, "--interface");
|
|
86434
87210
|
const agentId = await resolveAgentId2(cwd2, options.agentId, interfaceId, dependencies.readManifest ?? readManifest);
|
|
86435
87211
|
const title = optionalValue(options.title, "--title");
|
|
@@ -86439,7 +87215,7 @@ async function runTaskCreate(cwd2, options, dependencies = {}) {
|
|
|
86439
87215
|
const version2 = versionRef ? (await agentVersionsApi.resolve(agentId, versionRef)).version : undefined;
|
|
86440
87216
|
const input = {
|
|
86441
87217
|
agent_id: agentId,
|
|
86442
|
-
initial_messages: [{ role: "user", content:
|
|
87218
|
+
initial_messages: [{ role: "user", content: message3 }],
|
|
86443
87219
|
auto_run: true,
|
|
86444
87220
|
...title ? { title } : {},
|
|
86445
87221
|
...model ? { default_model: model } : {},
|
|
@@ -86515,24 +87291,24 @@ async function waitForCreatedTask(created, options, dependencies, version2) {
|
|
|
86515
87291
|
return;
|
|
86516
87292
|
}
|
|
86517
87293
|
if (outcome.kind === "timeout") {
|
|
86518
|
-
console.log(
|
|
87294
|
+
console.log(import_picocolors65.default.yellow(`Timed out after ${options.timeoutSeconds}s with the task still ${status}.`));
|
|
86519
87295
|
return;
|
|
86520
87296
|
}
|
|
86521
87297
|
if (outcome.kind === "interrupted") {
|
|
86522
|
-
console.log(
|
|
87298
|
+
console.log(import_picocolors65.default.yellow("Interrupted. The task is still running."));
|
|
86523
87299
|
return;
|
|
86524
87300
|
}
|
|
86525
|
-
console.log(code === 0 ?
|
|
87301
|
+
console.log(code === 0 ? import_picocolors65.default.green("Task completed.") : import_picocolors65.default.red(`Task finished as ${status}.`));
|
|
86526
87302
|
} finally {
|
|
86527
87303
|
process.removeListener("SIGINT", onSigint);
|
|
86528
87304
|
}
|
|
86529
87305
|
}
|
|
86530
87306
|
|
|
86531
87307
|
// src/cli/task-get.ts
|
|
86532
|
-
var
|
|
87308
|
+
var import_picocolors67 = __toESM(require_picocolors(), 1);
|
|
86533
87309
|
|
|
86534
87310
|
// src/cli/task-list.ts
|
|
86535
|
-
var
|
|
87311
|
+
var import_picocolors66 = __toESM(require_picocolors(), 1);
|
|
86536
87312
|
|
|
86537
87313
|
// src/core/agent-names.ts
|
|
86538
87314
|
async function agentNames(ids) {
|
|
@@ -86597,29 +87373,29 @@ function labelFilter(options) {
|
|
|
86597
87373
|
function formatTaskList(tasks, names, agentId, interfaceId, labelFiltered = false) {
|
|
86598
87374
|
const lines = [""];
|
|
86599
87375
|
if (tasks.length === 0 && labelFiltered) {
|
|
86600
|
-
lines.push(` ${
|
|
87376
|
+
lines.push(` ${import_picocolors66.default.dim("No tasks carry every label given with --metadata.")}`, "");
|
|
86601
87377
|
return lines.join(`
|
|
86602
87378
|
`);
|
|
86603
87379
|
}
|
|
86604
87380
|
if (tasks.length === 0 && interfaceId) {
|
|
86605
87381
|
const id = sanitizeLabel(interfaceId);
|
|
86606
|
-
lines.push(` ${
|
|
87382
|
+
lines.push(` ${import_picocolors66.default.dim(`No build conversations for interface ${id}.`)}`, "", ` ${import_picocolors66.default.dim("start one with")} ${import_picocolors66.default.cyan(`brainbase interface build ${id} "..."`)}`, "");
|
|
86607
87383
|
return lines.join(`
|
|
86608
87384
|
`);
|
|
86609
87385
|
}
|
|
86610
87386
|
if (tasks.length === 0) {
|
|
86611
|
-
lines.push(` ${
|
|
87387
|
+
lines.push(` ${import_picocolors66.default.dim(agentId ? `No tasks for agent ${agentId}.` : "No tasks yet.")}`, "", ` ${import_picocolors66.default.dim("start one with")} ${import_picocolors66.default.cyan('brainbase task create --message "..."')}`, "");
|
|
86612
87388
|
return lines.join(`
|
|
86613
87389
|
`);
|
|
86614
87390
|
}
|
|
86615
87391
|
for (const task of tasks) {
|
|
86616
|
-
const title = sanitizeLabel(task.title ?? "").trim() ||
|
|
86617
|
-
lines.push(` ${statusLabel(task.status)} ${
|
|
86618
|
-
lines.push(` ${
|
|
86619
|
-
lines.push(` ${
|
|
87392
|
+
const title = sanitizeLabel(task.title ?? "").trim() || import_picocolors66.default.dim("(untitled)");
|
|
87393
|
+
lines.push(` ${statusLabel(task.status)} ${import_picocolors66.default.bold(title)}`);
|
|
87394
|
+
lines.push(` ${import_picocolors66.default.dim(sanitizeLabel(task.id))}`);
|
|
87395
|
+
lines.push(` ${import_picocolors66.default.dim(`agent ${agentLabel(task.agent_id, names)} · created ${sanitizeLabel(task.created_at)}`)}`);
|
|
86620
87396
|
lines.push("");
|
|
86621
87397
|
}
|
|
86622
|
-
lines.push(` ${
|
|
87398
|
+
lines.push(` ${import_picocolors66.default.dim("inspect one with")} ${import_picocolors66.default.cyan("brainbase task get <id>")}`, "");
|
|
86623
87399
|
return lines.join(`
|
|
86624
87400
|
`);
|
|
86625
87401
|
}
|
|
@@ -86627,16 +87403,16 @@ function statusLabel(status) {
|
|
|
86627
87403
|
const padded = sanitizeLabel(status).padEnd(14);
|
|
86628
87404
|
switch (status) {
|
|
86629
87405
|
case "success":
|
|
86630
|
-
return
|
|
87406
|
+
return import_picocolors66.default.green(padded);
|
|
86631
87407
|
case "fail":
|
|
86632
|
-
return
|
|
87408
|
+
return import_picocolors66.default.red(padded);
|
|
86633
87409
|
case "need_more_info":
|
|
86634
|
-
return
|
|
87410
|
+
return import_picocolors66.default.yellow(padded);
|
|
86635
87411
|
case "running":
|
|
86636
87412
|
case "initializing":
|
|
86637
|
-
return
|
|
87413
|
+
return import_picocolors66.default.cyan(padded);
|
|
86638
87414
|
default:
|
|
86639
|
-
return
|
|
87415
|
+
return import_picocolors66.default.dim(padded);
|
|
86640
87416
|
}
|
|
86641
87417
|
}
|
|
86642
87418
|
|
|
@@ -86670,60 +87446,60 @@ async function readEvalRuns(task) {
|
|
|
86670
87446
|
}
|
|
86671
87447
|
function format2(task, evals, names) {
|
|
86672
87448
|
const lines = [""];
|
|
86673
|
-
const title = sanitizeLabel(task.title ?? "").trim() ||
|
|
87449
|
+
const title = sanitizeLabel(task.title ?? "").trim() || import_picocolors67.default.dim("(untitled)");
|
|
86674
87450
|
const id = sanitizeLabel(task.id);
|
|
86675
|
-
lines.push(` ${statusLabel(task.status)} ${
|
|
87451
|
+
lines.push(` ${statusLabel(task.status)} ${import_picocolors67.default.bold(title)}`);
|
|
86676
87452
|
lines.push("");
|
|
86677
|
-
lines.push(` ${
|
|
86678
|
-
lines.push(` ${
|
|
87453
|
+
lines.push(` ${import_picocolors67.default.dim("task")} ${id}`);
|
|
87454
|
+
lines.push(` ${import_picocolors67.default.dim("agent")} ${agentLabel(task.agent_id, names)}`);
|
|
86679
87455
|
if (task.model !== undefined) {
|
|
86680
|
-
const model = task.model?.trim() ? sanitizeLabel(task.model) :
|
|
86681
|
-
lines.push(` ${
|
|
87456
|
+
const model = task.model?.trim() ? sanitizeLabel(task.model) : import_picocolors67.default.dim("agent default");
|
|
87457
|
+
lines.push(` ${import_picocolors67.default.dim("model")} ${model}`);
|
|
86682
87458
|
}
|
|
86683
|
-
lines.push(` ${
|
|
87459
|
+
lines.push(` ${import_picocolors67.default.dim("created")} ${sanitizeLabel(task.created_at)}`);
|
|
86684
87460
|
if (task.parent_task_id) {
|
|
86685
|
-
lines.push(` ${
|
|
87461
|
+
lines.push(` ${import_picocolors67.default.dim("parent")} ${sanitizeLabel(task.parent_task_id)}`);
|
|
86686
87462
|
}
|
|
86687
87463
|
if (task.machine_id) {
|
|
86688
87464
|
const size2 = task.machine_size ? ` (size ${sanitizeLabel(task.machine_size)})` : "";
|
|
86689
|
-
lines.push(` ${
|
|
87465
|
+
lines.push(` ${import_picocolors67.default.dim("machine")} ${sanitizeLabel(task.machine_id)}${size2}`);
|
|
86690
87466
|
}
|
|
86691
87467
|
if (task.sandbox_id)
|
|
86692
|
-
lines.push(` ${
|
|
87468
|
+
lines.push(` ${import_picocolors67.default.dim("sandbox")} ${sanitizeLabel(task.sandbox_id)}`);
|
|
86693
87469
|
const [failure, ...failureRest] = sanitizeLines(failureSummary(task) ?? "").filter((line2) => line2.trim());
|
|
86694
87470
|
if (failure) {
|
|
86695
87471
|
const label3 = " failure ";
|
|
86696
87472
|
lines.push("");
|
|
86697
|
-
lines.push(` ${
|
|
87473
|
+
lines.push(` ${import_picocolors67.default.red("failure")} ${failure}`);
|
|
86698
87474
|
for (const line2 of failureRest)
|
|
86699
87475
|
lines.push(`${" ".repeat(label3.length)}${line2}`);
|
|
86700
87476
|
}
|
|
86701
87477
|
const metadata = Object.entries(task.metadata ?? {});
|
|
86702
87478
|
if (metadata.length > 0) {
|
|
86703
87479
|
lines.push("");
|
|
86704
|
-
lines.push(` ${
|
|
87480
|
+
lines.push(` ${import_picocolors67.default.bold(import_picocolors67.default.dim("METADATA"))}`);
|
|
86705
87481
|
for (const [key2, value2] of metadata) {
|
|
86706
|
-
lines.push(` ${
|
|
87482
|
+
lines.push(` ${import_picocolors67.default.dim(sanitizeLabel(key2))} ${sanitizeLabel(String(value2))}`);
|
|
86707
87483
|
}
|
|
86708
87484
|
}
|
|
86709
87485
|
lines.push("");
|
|
86710
|
-
lines.push(` ${
|
|
87486
|
+
lines.push(` ${import_picocolors67.default.bold(import_picocolors67.default.dim("EVAL VERDICTS"))}`);
|
|
86711
87487
|
if (evals.unavailable) {
|
|
86712
|
-
lines.push(` ${
|
|
87488
|
+
lines.push(` ${import_picocolors67.default.dim(sanitizeLabel(evals.unavailable))}`);
|
|
86713
87489
|
} else if (evals.runs.length === 0) {
|
|
86714
|
-
lines.push(` ${
|
|
87490
|
+
lines.push(` ${import_picocolors67.default.dim("none")}`);
|
|
86715
87491
|
} else {
|
|
86716
87492
|
for (const run of evals.runs) {
|
|
86717
|
-
const verdict = run.passed === true ?
|
|
87493
|
+
const verdict = run.passed === true ? import_picocolors67.default.green("pass") : run.passed === false ? import_picocolors67.default.red("fail") : import_picocolors67.default.dim(sanitizeLabel(run.status));
|
|
86718
87494
|
lines.push(` ${verdict} ${sanitizeLabel(run.eval_slug ?? run.eval_id)}`);
|
|
86719
87495
|
for (const line2 of sanitizeLines(run.reasoning ?? "")) {
|
|
86720
87496
|
if (line2.trim())
|
|
86721
|
-
lines.push(` ${
|
|
87497
|
+
lines.push(` ${import_picocolors67.default.dim(line2)}`);
|
|
86722
87498
|
}
|
|
86723
87499
|
}
|
|
86724
87500
|
}
|
|
86725
87501
|
lines.push("");
|
|
86726
|
-
lines.push(` ${
|
|
87502
|
+
lines.push(` ${import_picocolors67.default.dim("read its transcript with")} ${import_picocolors67.default.cyan(`brainbase task logs ${id}`)}`, "");
|
|
86727
87503
|
return lines.join(`
|
|
86728
87504
|
`);
|
|
86729
87505
|
}
|
|
@@ -86740,7 +87516,7 @@ function failureSummary(task) {
|
|
|
86740
87516
|
}
|
|
86741
87517
|
|
|
86742
87518
|
// src/cli/task-logs.ts
|
|
86743
|
-
var
|
|
87519
|
+
var import_picocolors68 = __toESM(require_picocolors(), 1);
|
|
86744
87520
|
|
|
86745
87521
|
// src/core/task-events.ts
|
|
86746
87522
|
var DEFAULT_RETRY_BUDGET_MS = 60000;
|
|
@@ -86816,12 +87592,12 @@ function followTaskEvents(options) {
|
|
|
86816
87592
|
onOpen?.();
|
|
86817
87593
|
});
|
|
86818
87594
|
source.addEventListener("error", (event) => {
|
|
86819
|
-
const { message:
|
|
87595
|
+
const { message: message3, code } = event;
|
|
86820
87596
|
if (source.readyState === source.CLOSED) {
|
|
86821
|
-
finish(streamError(
|
|
87597
|
+
finish(streamError(message3, code));
|
|
86822
87598
|
return;
|
|
86823
87599
|
}
|
|
86824
|
-
lastReason =
|
|
87600
|
+
lastReason = message3?.trim() || "connection lost";
|
|
86825
87601
|
onReconnect?.(lastReason);
|
|
86826
87602
|
if (downTimer === undefined) {
|
|
86827
87603
|
downTimer = setTimeout(() => {
|
|
@@ -86841,8 +87617,8 @@ function parseFrameData(raw) {
|
|
|
86841
87617
|
return raw;
|
|
86842
87618
|
}
|
|
86843
87619
|
}
|
|
86844
|
-
function streamError(
|
|
86845
|
-
const detail =
|
|
87620
|
+
function streamError(message3, code) {
|
|
87621
|
+
const detail = message3?.trim() || "the log stream closed";
|
|
86846
87622
|
switch (code) {
|
|
86847
87623
|
case 401:
|
|
86848
87624
|
return new ApiError(`Not authorized to read this task's events: ${detail}`, 401);
|
|
@@ -87023,14 +87799,14 @@ async function runTaskLogs(taskId, options = {}, dependencies = {}) {
|
|
|
87023
87799
|
console.log(renderEvent(event, messages));
|
|
87024
87800
|
}
|
|
87025
87801
|
if (ordered.length === 0) {
|
|
87026
|
-
console.log(
|
|
87802
|
+
console.log(import_picocolors68.default.dim("No events for this task yet."));
|
|
87027
87803
|
}
|
|
87028
87804
|
}
|
|
87029
87805
|
async function followTranscript(taskId, options, dependencies) {
|
|
87030
87806
|
const backfill = options.limit === undefined ? "" : `?backfill=${options.limit}`;
|
|
87031
87807
|
const { url: url2, resolveBearer } = await masStreamTarget(`/tasks/${encodeURIComponent(taskId)}/events/stream${backfill}`);
|
|
87032
87808
|
if (!options.json) {
|
|
87033
|
-
console.log(
|
|
87809
|
+
console.log(import_picocolors68.default.dim(`Following task ${taskId} — Ctrl-C to stop.`));
|
|
87034
87810
|
}
|
|
87035
87811
|
const setExitCode = dependencies.setExitCode ?? ((code) => process.exitCode = code);
|
|
87036
87812
|
const controller = new AbortController;
|
|
@@ -87072,13 +87848,13 @@ async function followTranscript(taskId, options, dependencies) {
|
|
|
87072
87848
|
} else if (options.json) {
|
|
87073
87849
|
console.log(JSON.stringify(frame));
|
|
87074
87850
|
} else {
|
|
87075
|
-
console.log(
|
|
87851
|
+
console.log(import_picocolors68.default.dim(frame.type));
|
|
87076
87852
|
}
|
|
87077
87853
|
},
|
|
87078
87854
|
onOpen: () => settle.noteFrame(),
|
|
87079
87855
|
onReconnect: (reason) => {
|
|
87080
87856
|
settle.noteDisconnected();
|
|
87081
|
-
console.error(
|
|
87857
|
+
console.error(import_picocolors68.default.dim(`reconnecting — ${reason}`));
|
|
87082
87858
|
}
|
|
87083
87859
|
});
|
|
87084
87860
|
if (interruptCode !== undefined)
|
|
@@ -87234,8 +88010,8 @@ function errorCode(error2) {
|
|
|
87234
88010
|
const code = detail.code;
|
|
87235
88011
|
return typeof code === "string" ? code : undefined;
|
|
87236
88012
|
}
|
|
87237
|
-
function jsonError(error2,
|
|
87238
|
-
return { ...errorShape(error2), message:
|
|
88013
|
+
function jsonError(error2, message3, status, code) {
|
|
88014
|
+
return { ...errorShape(error2), message: message3, status, ...code ? { code } : {} };
|
|
87239
88015
|
}
|
|
87240
88016
|
function stopRetryCommand(taskId, generation) {
|
|
87241
88017
|
const argument = /^[A-Za-z0-9_-]+$/.test(taskId) ? taskId : `'${sanitizeLabel(taskId).replaceAll("'", "'\\''")}'`;
|
|
@@ -87285,8 +88061,8 @@ function onInterrupt(handler) {
|
|
|
87285
88061
|
process.off(name, listener);
|
|
87286
88062
|
};
|
|
87287
88063
|
}
|
|
87288
|
-
async function runTaskSend(taskId,
|
|
87289
|
-
if (!
|
|
88064
|
+
async function runTaskSend(taskId, message3, options = {}) {
|
|
88065
|
+
if (!message3.trim())
|
|
87290
88066
|
throw new Error("The follow-up message must not be blank.");
|
|
87291
88067
|
const inputId = options.inputId?.trim().toLowerCase() ?? randomUUID5();
|
|
87292
88068
|
if (!/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(inputId)) {
|
|
@@ -87305,7 +88081,7 @@ async function runTaskSend(taskId, message2, options = {}) {
|
|
|
87305
88081
|
attempted = true;
|
|
87306
88082
|
result2 = await masApi.sendTaskInput(taskId, {
|
|
87307
88083
|
input_id: inputId,
|
|
87308
|
-
messages: [{ role: "user", content:
|
|
88084
|
+
messages: [{ role: "user", content: message3 }],
|
|
87309
88085
|
expected_generation: expectedGeneration
|
|
87310
88086
|
});
|
|
87311
88087
|
} catch (error2) {
|
|
@@ -87384,17 +88160,17 @@ async function runTaskStop(taskId, options = {}) {
|
|
|
87384
88160
|
${retry}
|
|
87385
88161
|
Omit --generation only for a deliberately new Stop.`;
|
|
87386
88162
|
}
|
|
87387
|
-
const
|
|
88163
|
+
const message3 = `${detail}${guidance}`;
|
|
87388
88164
|
if (options.json) {
|
|
87389
88165
|
console.log(JSON.stringify({
|
|
87390
88166
|
task_id: taskId,
|
|
87391
88167
|
expected_generation: expectedGeneration,
|
|
87392
|
-
error: jsonError(error2,
|
|
88168
|
+
error: jsonError(error2, message3, status, code)
|
|
87393
88169
|
}));
|
|
87394
88170
|
process.exitCode = 1;
|
|
87395
88171
|
return;
|
|
87396
88172
|
}
|
|
87397
|
-
throw new ApiError(
|
|
88173
|
+
throw new ApiError(message3, status, error2 instanceof ApiError ? error2.body : undefined);
|
|
87398
88174
|
}
|
|
87399
88175
|
if (options.json) {
|
|
87400
88176
|
console.log(JSON.stringify({ ...task, expected_generation: expectedGeneration }, null, 2));
|
|
@@ -87756,78 +88532,78 @@ ${didYouMean(sub, ["create", "list", "get", "logs", "send", "stop", "update", "d
|
|
|
87756
88532
|
function printHelp5() {
|
|
87757
88533
|
const out = [];
|
|
87758
88534
|
out.push("");
|
|
87759
|
-
out.push(` ${
|
|
88535
|
+
out.push(` ${import_picocolors69.default.bold("brainbase task")} ${import_picocolors69.default.dim("<sub> [options]")}`);
|
|
87760
88536
|
out.push("");
|
|
87761
|
-
out.push(` ${
|
|
87762
|
-
out.push(` ${
|
|
87763
|
-
out.push(` ${
|
|
87764
|
-
out.push(` ${
|
|
87765
|
-
out.push(` ${
|
|
87766
|
-
out.push(` ${
|
|
87767
|
-
out.push(` ${
|
|
87768
|
-
out.push(` ${
|
|
88537
|
+
out.push(` ${import_picocolors69.default.cyan("create")} ${import_picocolors69.default.dim("--message <text>")} ${import_picocolors69.default.dim("create a task and start its first run")}`);
|
|
88538
|
+
out.push(` ${import_picocolors69.default.cyan("list | ls")} ${import_picocolors69.default.dim("recent tasks you can reach (--json for scripts)")}`);
|
|
88539
|
+
out.push(` ${import_picocolors69.default.cyan("get")} ${import_picocolors69.default.dim("<task-id>")} ${import_picocolors69.default.dim("one task: status, agent, machine, eval verdicts")}`);
|
|
88540
|
+
out.push(` ${import_picocolors69.default.cyan("logs")} ${import_picocolors69.default.dim("<task-id> [--follow]")} ${import_picocolors69.default.dim("one line per event in the task's transcript, or tail it live")}`);
|
|
88541
|
+
out.push(` ${import_picocolors69.default.cyan("send")} ${import_picocolors69.default.dim("<task-id> <message>")} ${import_picocolors69.default.dim("send a follow-up, including while the agent is running")}`);
|
|
88542
|
+
out.push(` ${import_picocolors69.default.cyan("stop")} ${import_picocolors69.default.dim("<task-id>")} ${import_picocolors69.default.dim("stop execution and cancel pending follow-ups, retaining their text")}`);
|
|
88543
|
+
out.push(` ${import_picocolors69.default.cyan("update")} ${import_picocolors69.default.dim("<task-id>")} ${import_picocolors69.default.dim("rename a task, change its metadata labels, switch its model or reset it to the agent default, including while it runs")}`);
|
|
88544
|
+
out.push(` ${import_picocolors69.default.cyan("delete")} ${import_picocolors69.default.dim("<task-id>")} ${import_picocolors69.default.dim("permanently delete a stopped task and tear down its sandbox (--yes to skip the prompt)")}`);
|
|
87769
88545
|
out.push("");
|
|
87770
|
-
out.push(` ${
|
|
87771
|
-
out.push(` ${
|
|
87772
|
-
out.push(` ${
|
|
87773
|
-
out.push(` ${
|
|
87774
|
-
out.push(` ${
|
|
87775
|
-
out.push(` ${
|
|
87776
|
-
out.push(` ${
|
|
87777
|
-
out.push(` ${
|
|
87778
|
-
out.push(` ${
|
|
87779
|
-
out.push(` ${
|
|
88546
|
+
out.push(` ${import_picocolors69.default.bold("create flags")}`);
|
|
88547
|
+
out.push(` ${import_picocolors69.default.dim("--message <text>")} required first user message`);
|
|
88548
|
+
out.push(` ${import_picocolors69.default.dim("--agent <id>")} override the claimed agent in brainbase.agent.yaml`);
|
|
88549
|
+
out.push(` ${import_picocolors69.default.dim("--interface <id>")} open it as a build conversation for this interface (agent defaults to the interface's)`);
|
|
88550
|
+
out.push(` ${import_picocolors69.default.dim("--title <text>")} optional task title`);
|
|
88551
|
+
out.push(` ${import_picocolors69.default.dim("--model <id>")} optional model override`);
|
|
88552
|
+
out.push(` ${import_picocolors69.default.dim("--version <v>")} run a saved version of the agent: 12, v12 or a version id (\`agent versions list\`)`);
|
|
88553
|
+
out.push(` ${import_picocolors69.default.dim("--metadata key=value")} label the task (repeatable)`);
|
|
88554
|
+
out.push(` ${import_picocolors69.default.dim("--wait")} block until the task finishes; exit 1 unless it succeeded`);
|
|
88555
|
+
out.push(` ${import_picocolors69.default.dim("--timeout <secs>")} give up waiting after <secs> and exit 1 (needs --wait)`);
|
|
87780
88556
|
out.push("");
|
|
87781
|
-
out.push(` ${
|
|
87782
|
-
out.push(` ${
|
|
87783
|
-
out.push(` ${
|
|
87784
|
-
out.push(` ${
|
|
87785
|
-
out.push(` ${
|
|
88557
|
+
out.push(` ${import_picocolors69.default.bold("list flags")}`);
|
|
88558
|
+
out.push(` ${import_picocolors69.default.dim("--agent <id>")} only this agent's tasks`);
|
|
88559
|
+
out.push(` ${import_picocolors69.default.dim("--interface <id>")} only this interface's build conversations (hidden from a plain list)`);
|
|
88560
|
+
out.push(` ${import_picocolors69.default.dim("--metadata key=value")} only tasks carrying this label (repeatable; all must match)`);
|
|
88561
|
+
out.push(` ${import_picocolors69.default.dim("--limit <n>")} cap the page (1-200, server default 50)`);
|
|
87786
88562
|
out.push("");
|
|
87787
|
-
out.push(` ${
|
|
87788
|
-
out.push(` ${
|
|
87789
|
-
out.push(` ${
|
|
88563
|
+
out.push(` ${import_picocolors69.default.bold("logs flags")}`);
|
|
88564
|
+
out.push(` ${import_picocolors69.default.dim("--limit <n>")} stop after <n> events instead of the whole transcript; with --follow, the first page size`);
|
|
88565
|
+
out.push(` ${import_picocolors69.default.dim("--follow, -f")} stay attached and print events as they land, until the task finishes and any queued follow-ups have run`);
|
|
87790
88566
|
out.push("");
|
|
87791
|
-
out.push(` ${
|
|
87792
|
-
out.push(` ${
|
|
87793
|
-
out.push(` ${
|
|
87794
|
-
out.push(` ${
|
|
87795
|
-
out.push(` ${
|
|
87796
|
-
out.push(` ${
|
|
87797
|
-
out.push(` ${
|
|
87798
|
-
out.push(` ${
|
|
87799
|
-
out.push(` ${
|
|
88567
|
+
out.push(` ${import_picocolors69.default.bold("update flags")}`);
|
|
88568
|
+
out.push(` ${import_picocolors69.default.dim("--title <text>")} new title`);
|
|
88569
|
+
out.push(` ${import_picocolors69.default.dim("--clear-title")} remove the title; automatic titling may name the task again on a later turn`);
|
|
88570
|
+
out.push(` ${import_picocolors69.default.dim("--metadata key=value")} set one label, keeping the others (repeatable)`);
|
|
88571
|
+
out.push(` ${import_picocolors69.default.dim("--unset-metadata <key>")} remove one label (repeatable)`);
|
|
88572
|
+
out.push(` ${import_picocolors69.default.dim(" the server applies label edits in one step, so concurrent edits from other clients are kept")}`);
|
|
88573
|
+
out.push(` ${import_picocolors69.default.dim("--clear-metadata")} remove every label; with --metadata, the labels become exactly those given`);
|
|
88574
|
+
out.push(` ${import_picocolors69.default.dim("--model <id>")} switch the model the task's next turn runs on (the running turn keeps its model)`);
|
|
88575
|
+
out.push(` ${import_picocolors69.default.dim("--clear-model")} go back to the agent's default model from the next turn`);
|
|
87800
88576
|
out.push("");
|
|
87801
|
-
out.push(` ${
|
|
87802
|
-
out.push(` ${
|
|
87803
|
-
out.push(` ${
|
|
87804
|
-
out.push(` ${
|
|
88577
|
+
out.push(` ${import_picocolors69.default.bold("send flags")}`);
|
|
88578
|
+
out.push(` ${import_picocolors69.default.dim("--input-id <uuid>")} recover the same request using its original ID and identical message`);
|
|
88579
|
+
out.push(` ${import_picocolors69.default.dim(" omit it to send a new follow-up; an unconfirmed receipt is never automatically replayed")}`);
|
|
88580
|
+
out.push(` ${import_picocolors69.default.dim(" admission disabled/recovery unavailable means no input was admitted; retry the same ID after recovery")}`);
|
|
87805
88581
|
out.push("");
|
|
87806
|
-
out.push(` ${
|
|
87807
|
-
out.push(` ${
|
|
87808
|
-
out.push(` ${
|
|
88582
|
+
out.push(` ${import_picocolors69.default.bold("send and stop flags")}`);
|
|
88583
|
+
out.push(` ${import_picocolors69.default.dim("--generation <n>")} retain the printed generation when retrying; defaults to a fresh snapshot for a new operation`);
|
|
88584
|
+
out.push(` ${import_picocolors69.default.dim(" Stop errors may follow queued-input cancellation; retry the printed command to avoid stopping newer work")}`);
|
|
87809
88585
|
out.push("");
|
|
87810
|
-
out.push(` ${
|
|
87811
|
-
out.push(` ${
|
|
87812
|
-
out.push(` ${
|
|
87813
|
-
out.push(` ${
|
|
88586
|
+
out.push(` ${import_picocolors69.default.bold("every subcommand")}`);
|
|
88587
|
+
out.push(` ${import_picocolors69.default.dim("--json")} machine-readable output — create prints task_id, agent_id and status (with --version, also agent_version_id and version_number); list, get, logs, send, stop and update print the raw records; delete prints id and deleted`);
|
|
88588
|
+
out.push(` ${import_picocolors69.default.dim(" send and stop include expected_generation for safe retries; send also reports idempotency_replayed when present")}`);
|
|
88589
|
+
out.push(` ${import_picocolors69.default.dim(" logs --follow --json prints one record per line, since a live stream has no end to close on")}`);
|
|
87814
88590
|
out.push("");
|
|
87815
|
-
out.push(` ${
|
|
87816
|
-
out.push(` ${
|
|
87817
|
-
out.push(` ${
|
|
87818
|
-
out.push(` ${
|
|
88591
|
+
out.push(` ${import_picocolors69.default.dim("Exit codes with --wait:")} ${import_picocolors69.default.dim("0 succeeded · 1 failed, needs input, or timed out · 130 interrupted")}`);
|
|
88592
|
+
out.push(` ${import_picocolors69.default.dim("Exit codes with --follow:")} ${import_picocolors69.default.dim("0 task reached a terminal state · 1 stream refused, or unreachable for 60s · 130 interrupted (Ctrl-C) · 143 terminated")}`);
|
|
88593
|
+
out.push(` ${import_picocolors69.default.dim("Exit codes with send:")} ${import_picocolors69.default.dim("0 queued, dispatching, submitted or completed · 1 unconfirmed, cancelled, failed or request error")}`);
|
|
88594
|
+
out.push(` ${import_picocolors69.default.dim("Ctrl-C while waiting or following logs detaches; use task stop to cancel remote work.")}`);
|
|
87819
88595
|
out.push("");
|
|
87820
|
-
out.push(` ${
|
|
88596
|
+
out.push(` ${import_picocolors69.default.dim("Flag-like values:")} use ${import_picocolors69.default.cyan("--flag=value")} or ${import_picocolors69.default.cyan("--flag -- <value>")}`);
|
|
87821
88597
|
out.push("");
|
|
87822
88598
|
console.log(out.join(`
|
|
87823
88599
|
`));
|
|
87824
88600
|
}
|
|
87825
88601
|
|
|
87826
88602
|
// src/cli/machine.ts
|
|
87827
|
-
var
|
|
88603
|
+
var import_picocolors72 = __toESM(require_picocolors(), 1);
|
|
87828
88604
|
|
|
87829
88605
|
// src/cli/machine-list.ts
|
|
87830
|
-
var
|
|
88606
|
+
var import_picocolors70 = __toESM(require_picocolors(), 1);
|
|
87831
88607
|
async function runMachineList(args = {}) {
|
|
87832
88608
|
if (!args.json)
|
|
87833
88609
|
banner("machine list — sandboxes you can reach");
|
|
@@ -87845,7 +88621,7 @@ async function runMachineList(args = {}) {
|
|
|
87845
88621
|
function formatMachineList(machines, includedDead, names = new Map) {
|
|
87846
88622
|
const lines = [""];
|
|
87847
88623
|
if (machines.length === 0) {
|
|
87848
|
-
lines.push(` ${
|
|
88624
|
+
lines.push(` ${import_picocolors70.default.dim(includedDead ? "No machines." : "No live machines. Pass --all to include torn-down ones.")}`, "");
|
|
87849
88625
|
return lines.join(`
|
|
87850
88626
|
`);
|
|
87851
88627
|
}
|
|
@@ -87865,7 +88641,7 @@ function formatMachineList(machines, includedDead, names = new Map) {
|
|
|
87865
88641
|
const statusWidth = width((row) => row.status);
|
|
87866
88642
|
const sizeWidth = width((row) => row.size);
|
|
87867
88643
|
const agentWidth = width((row) => row.agent);
|
|
87868
|
-
lines.push(` ${
|
|
88644
|
+
lines.push(` ${import_picocolors70.default.dim([
|
|
87869
88645
|
header.id.padEnd(idWidth),
|
|
87870
88646
|
header.kind.padEnd(kindWidth),
|
|
87871
88647
|
header.status.padEnd(statusWidth),
|
|
@@ -87881,21 +88657,21 @@ function formatMachineList(machines, includedDead, names = new Map) {
|
|
|
87881
88657
|
row.dead ? status : statusTint(row.status, status),
|
|
87882
88658
|
row.size.padEnd(sizeWidth),
|
|
87883
88659
|
row.agent.padEnd(agentWidth),
|
|
87884
|
-
|
|
88660
|
+
import_picocolors70.default.dim(row.age)
|
|
87885
88661
|
].join(" ");
|
|
87886
|
-
lines.push(` ${row.dead ?
|
|
88662
|
+
lines.push(` ${row.dead ? import_picocolors70.default.dim(cells) : cells}`);
|
|
87887
88663
|
}
|
|
87888
|
-
lines.push("", ` ${
|
|
88664
|
+
lines.push("", ` ${import_picocolors70.default.dim("tear one down with")} ${import_picocolors70.default.cyan("brainbase machine rm <id>")}`, "");
|
|
87889
88665
|
return lines.join(`
|
|
87890
88666
|
`);
|
|
87891
88667
|
}
|
|
87892
88668
|
function statusTint(status, padded) {
|
|
87893
88669
|
switch (status) {
|
|
87894
88670
|
case "running":
|
|
87895
|
-
return
|
|
88671
|
+
return import_picocolors70.default.green(padded);
|
|
87896
88672
|
case "stopped":
|
|
87897
88673
|
case "starting":
|
|
87898
|
-
return
|
|
88674
|
+
return import_picocolors70.default.yellow(padded);
|
|
87899
88675
|
default:
|
|
87900
88676
|
return padded;
|
|
87901
88677
|
}
|
|
@@ -87918,7 +88694,7 @@ function age(createdAt) {
|
|
|
87918
88694
|
}
|
|
87919
88695
|
|
|
87920
88696
|
// src/cli/machine-rm.ts
|
|
87921
|
-
var
|
|
88697
|
+
var import_picocolors71 = __toESM(require_picocolors(), 1);
|
|
87922
88698
|
async function runMachineRm(args, dependencies = {}) {
|
|
87923
88699
|
const setExitCode = dependencies.setExitCode ?? ((code) => process.exitCode = code);
|
|
87924
88700
|
const machineId = args.machineId?.trim();
|
|
@@ -87932,7 +88708,7 @@ async function runMachineRm(args, dependencies = {}) {
|
|
|
87932
88708
|
if (args.json) {
|
|
87933
88709
|
console.log(JSON.stringify({ id: machineId, torn_down: false, outcome: "declined" }, null, 2));
|
|
87934
88710
|
} else {
|
|
87935
|
-
console.log(` ${
|
|
88711
|
+
console.log(` ${import_picocolors71.default.dim("Left alone.")}`);
|
|
87936
88712
|
}
|
|
87937
88713
|
return;
|
|
87938
88714
|
}
|
|
@@ -87950,7 +88726,7 @@ async function promptForTeardown(args) {
|
|
|
87950
88726
|
return true;
|
|
87951
88727
|
if (!args.json) {
|
|
87952
88728
|
console.log(`
|
|
87953
|
-
${
|
|
88729
|
+
${import_picocolors71.default.red("This destroys the sandbox.")} ${import_picocolors71.default.dim("Anything not committed out of it is lost. The machine row is kept for cost history.")}
|
|
87954
88730
|
`);
|
|
87955
88731
|
}
|
|
87956
88732
|
const answer = await se({
|
|
@@ -87962,9 +88738,9 @@ async function promptForTeardown(args) {
|
|
|
87962
88738
|
function formatMachineRm(machine) {
|
|
87963
88739
|
const lines = [""];
|
|
87964
88740
|
if (machine.destroyed_at) {
|
|
87965
|
-
lines.push(` ${
|
|
88741
|
+
lines.push(` ${import_picocolors71.default.green("✓")} ${machine.kind} sandbox ${machine.id} is torn down.`, ` ${import_picocolors71.default.dim(`destroyed_at ${machine.destroyed_at}`)}`);
|
|
87966
88742
|
} else {
|
|
87967
|
-
lines.push(` ${
|
|
88743
|
+
lines.push(` ${import_picocolors71.default.yellow("!")} ${machine.id} came back without a teardown timestamp (status ${machine.status}).`, ` ${import_picocolors71.default.dim("Re-check with `brainbase machine ls --all` before assuming it stopped billing.")}`);
|
|
87968
88744
|
}
|
|
87969
88745
|
lines.push("");
|
|
87970
88746
|
return lines.join(`
|
|
@@ -88005,25 +88781,25 @@ ${didYouMean(sub, ["ls", "rm"], "brainbase machine")}`);
|
|
|
88005
88781
|
function printHelp6() {
|
|
88006
88782
|
const out = [];
|
|
88007
88783
|
out.push("");
|
|
88008
|
-
out.push(` ${
|
|
88784
|
+
out.push(` ${import_picocolors72.default.bold("brainbase machine")} ${import_picocolors72.default.dim("<sub> [options]")}`);
|
|
88009
88785
|
out.push("");
|
|
88010
|
-
out.push(` ${
|
|
88011
|
-
out.push(` ${
|
|
88786
|
+
out.push(` ${import_picocolors72.default.cyan("ls")} ${import_picocolors72.default.dim("list your sandboxes — live ones only unless --all")}`);
|
|
88787
|
+
out.push(` ${import_picocolors72.default.cyan("rm")} ${import_picocolors72.default.dim("<id>")} ${import_picocolors72.default.dim("tear a sandbox down (terminal; the row is kept for cost history)")}`);
|
|
88012
88788
|
out.push("");
|
|
88013
|
-
out.push(` ${
|
|
88014
|
-
out.push(` ${
|
|
88015
|
-
out.push(` ${
|
|
88016
|
-
out.push(` ${
|
|
88789
|
+
out.push(` ${import_picocolors72.default.dim("--all")} ${import_picocolors72.default.dim("for ls: include machines already torn down")}`);
|
|
88790
|
+
out.push(` ${import_picocolors72.default.dim("--limit <n>")} ${import_picocolors72.default.dim("for ls: how many to fetch (1-200, default 50)")}`);
|
|
88791
|
+
out.push(` ${import_picocolors72.default.dim("--yes, -y")} ${import_picocolors72.default.dim("for rm: skip the confirmation")}`);
|
|
88792
|
+
out.push(` ${import_picocolors72.default.dim("--json")} ${import_picocolors72.default.dim("machine-readable output")}`);
|
|
88017
88793
|
out.push("");
|
|
88018
88794
|
console.log(out.join(`
|
|
88019
88795
|
`));
|
|
88020
88796
|
}
|
|
88021
88797
|
|
|
88022
88798
|
// src/cli/interface.ts
|
|
88023
|
-
var
|
|
88799
|
+
var import_picocolors78 = __toESM(require_picocolors(), 1);
|
|
88024
88800
|
|
|
88025
88801
|
// src/cli/interface-build.ts
|
|
88026
|
-
var
|
|
88802
|
+
var import_picocolors73 = __toESM(require_picocolors(), 1);
|
|
88027
88803
|
var USAGE2 = 'brainbase interface build <id> "<request>" [--timeout <seconds>] [--idempotency-key <key>] [--json]';
|
|
88028
88804
|
var SETTLE_TIMEOUT_MS = 120000;
|
|
88029
88805
|
async function reportingErrors(json3, work) {
|
|
@@ -88050,8 +88826,8 @@ function heldBy(row, ownTaskId) {
|
|
|
88050
88826
|
const taskId = held.thread_id;
|
|
88051
88827
|
if (ownTaskId !== undefined && taskId === ownTaskId)
|
|
88052
88828
|
return null;
|
|
88053
|
-
const
|
|
88054
|
-
return cliRefusal("conflict", "generation_running",
|
|
88829
|
+
const message3 = taskId ? `Another build conversation (${safe(taskId)}) is working on this interface. Follow it with \`brainbase task logs ${safe(taskId)} --follow\`, or wait for it to finish and run this again.` : `A build conversation is working on this interface (operation ${safe(held.operation_id)}). Wait for it to finish and run this again.`;
|
|
88830
|
+
return cliRefusal("conflict", "generation_running", message3, {
|
|
88055
88831
|
operation_id: held.operation_id,
|
|
88056
88832
|
task_id: taskId
|
|
88057
88833
|
});
|
|
@@ -88122,28 +88898,28 @@ function buildExitCode(outcome) {
|
|
|
88122
88898
|
function reportBuild(say, interfaceId, outcome, timeoutSeconds) {
|
|
88123
88899
|
switch (outcome.kind) {
|
|
88124
88900
|
case "built":
|
|
88125
|
-
say(` ${
|
|
88901
|
+
say(` ${import_picocolors73.default.dim("build")} ${safe(outcome.build.id)} ${import_picocolors73.default.green("succeeded")}`);
|
|
88126
88902
|
say("");
|
|
88127
|
-
say(` ${
|
|
88903
|
+
say(` ${import_picocolors73.default.dim("Next:")} ${import_picocolors73.default.cyan(`brainbase interface publish ${safe(interfaceId)}`)}`);
|
|
88128
88904
|
return;
|
|
88129
88905
|
case "failed": {
|
|
88130
88906
|
const reason = outcome.build?.error_summary ?? outcome.operation?.error ?? outcome.operation?.reason ?? null;
|
|
88131
|
-
say(` ${
|
|
88907
|
+
say(` ${import_picocolors73.default.dim("build")} ${outcome.build ? safe(outcome.build.id) : import_picocolors73.default.dim("none")} ${import_picocolors73.default.red("failed")}`);
|
|
88132
88908
|
if (reason)
|
|
88133
88909
|
say(` ${safeBlock(reason).split(`
|
|
88134
88910
|
`).join(`
|
|
88135
88911
|
`)}`);
|
|
88136
|
-
say(` ${
|
|
88912
|
+
say(` ${import_picocolors73.default.dim("Try again with")} ${import_picocolors73.default.cyan(`brainbase interface rebuild ${safe(interfaceId)}`)}`);
|
|
88137
88913
|
return;
|
|
88138
88914
|
}
|
|
88139
88915
|
case "busy":
|
|
88140
|
-
say(` ${
|
|
88916
|
+
say(` ${import_picocolors73.default.yellow(safe(outcome.message))}`);
|
|
88141
88917
|
return;
|
|
88142
88918
|
case "timeout":
|
|
88143
|
-
say(` ${
|
|
88919
|
+
say(` ${import_picocolors73.default.yellow(`Still building after ${timeoutSeconds}s.`)} ${import_picocolors73.default.dim(`It keeps going; check \`brainbase interface builds ${safe(interfaceId)}\`.`)}`);
|
|
88144
88920
|
return;
|
|
88145
88921
|
case "interrupted":
|
|
88146
|
-
say(` ${
|
|
88922
|
+
say(` ${import_picocolors73.default.yellow("Stopped waiting.")} ${import_picocolors73.default.dim(`The build keeps going; check \`brainbase interface builds ${safe(interfaceId)}\`.`)}`);
|
|
88147
88923
|
return;
|
|
88148
88924
|
default: {
|
|
88149
88925
|
const unreachable = outcome;
|
|
@@ -88190,8 +88966,8 @@ async function build(ctx) {
|
|
|
88190
88966
|
throw held;
|
|
88191
88967
|
}
|
|
88192
88968
|
const reattach = `brainbase task logs ${safe(taskId)} --follow`;
|
|
88193
|
-
say(` ${
|
|
88194
|
-
say(` ${
|
|
88969
|
+
say(` ${import_picocolors73.default.dim("Build conversation")} ${import_picocolors73.default.bold(safe(taskId))} ${import_picocolors73.default.dim(`on ${safe(before2.name)}`)}`);
|
|
88970
|
+
say(` ${import_picocolors73.default.dim(`If this stops early, reattach with \`${reattach}\`.`)}`);
|
|
88195
88971
|
const finish = (result2, exitCode) => {
|
|
88196
88972
|
if (json3)
|
|
88197
88973
|
console.log(JSON.stringify({ type: "result", task_id: taskId, ...result2 }));
|
|
@@ -88208,13 +88984,13 @@ async function build(ctx) {
|
|
|
88208
88984
|
});
|
|
88209
88985
|
} catch (error2) {
|
|
88210
88986
|
say("");
|
|
88211
|
-
say(` ${
|
|
88212
|
-
say(` ${
|
|
88987
|
+
say(` ${import_picocolors73.default.red(`Lost the conversation's event stream: ${safe(error2.message)}`)}`);
|
|
88988
|
+
say(` ${import_picocolors73.default.dim(`Conversation ${safe(taskId)} may still be running. Reattach with`)} ${import_picocolors73.default.cyan(reattach)}`);
|
|
88213
88989
|
finish({ version_id: null, build_id: null, status: "stream_lost", task_status: null }, 1);
|
|
88214
88990
|
return;
|
|
88215
88991
|
}
|
|
88216
88992
|
if (followExit !== undefined) {
|
|
88217
|
-
say(` ${
|
|
88993
|
+
say(` ${import_picocolors73.default.yellow("Stopped following.")} ${import_picocolors73.default.dim(`The conversation keeps running. Reattach with \`${reattach}\`.`)}`);
|
|
88218
88994
|
finish({ version_id: null, build_id: null, status: "interrupted", task_status: null }, followExit);
|
|
88219
88995
|
return;
|
|
88220
88996
|
}
|
|
@@ -88229,7 +89005,7 @@ async function build(ctx) {
|
|
|
88229
89005
|
if (settled.kind !== "terminal") {
|
|
88230
89006
|
const interrupted = settled.kind === "interrupted";
|
|
88231
89007
|
const status2 = settled.task?.status ?? null;
|
|
88232
|
-
say(` ${
|
|
89008
|
+
say(` ${import_picocolors73.default.yellow(interrupted ? "Stopped." : `The conversation is still ${safe(status2 ?? "running")}.`)} ${import_picocolors73.default.dim(`Check it with \`brainbase task get ${safe(taskId)}\`.`)}`);
|
|
88233
89009
|
finish({ version_id: null, build_id: null, status: interrupted ? "interrupted" : "task_unsettled", task_status: status2 }, interrupted ? SIGINT_EXIT_CODE : 1);
|
|
88234
89010
|
return;
|
|
88235
89011
|
}
|
|
@@ -88249,36 +89025,36 @@ async function build(ctx) {
|
|
|
88249
89025
|
}
|
|
88250
89026
|
const codes = [exitCodeForTaskStatus(task.status)];
|
|
88251
89027
|
say("");
|
|
88252
|
-
say(` ${
|
|
89028
|
+
say(` ${import_picocolors73.default.dim("conversation")} ${safe(taskId)} ${import_picocolors73.default.dim("ended")} ${safe(task.status)}`);
|
|
88253
89029
|
if (mine?.status === "failed") {
|
|
88254
89030
|
codes.push(1);
|
|
88255
89031
|
const why = [mine.reason, mine.error].filter(Boolean).map((part) => safe(part)).join(": ");
|
|
88256
|
-
say(` ${
|
|
89032
|
+
say(` ${import_picocolors73.default.red(`This conversation's build work failed${why ? ` (${why})` : ""}.`)}`);
|
|
88257
89033
|
} else if (task.status !== "success" && task.status !== "need_more_info") {
|
|
88258
|
-
say(` ${
|
|
89034
|
+
say(` ${import_picocolors73.default.red(`The conversation finished as ${safe(task.status)}.`)} ${import_picocolors73.default.dim(`See \`brainbase task logs ${safe(taskId)}\`.`)}`);
|
|
88259
89035
|
}
|
|
88260
89036
|
if (task.status === "need_more_info") {
|
|
88261
89037
|
const question = await lastAgentMessage(taskId);
|
|
88262
89038
|
say("");
|
|
88263
89039
|
if (question) {
|
|
88264
|
-
say(` ${
|
|
89040
|
+
say(` ${import_picocolors73.default.bold("The agent asks:")}`);
|
|
88265
89041
|
say(` ${safeBlock(question).split(`
|
|
88266
89042
|
`).join(`
|
|
88267
89043
|
`)}`);
|
|
88268
89044
|
} else {
|
|
88269
|
-
say(` ${
|
|
89045
|
+
say(` ${import_picocolors73.default.bold("The agent needs more from you before it can go on.")}`);
|
|
88270
89046
|
}
|
|
88271
89047
|
say("");
|
|
88272
|
-
say(` ${
|
|
88273
|
-
say(` ${
|
|
89048
|
+
say(` ${import_picocolors73.default.dim("Reply with")} ${import_picocolors73.default.cyan(`brainbase task send ${safe(taskId)} "<reply>"`)}`);
|
|
89049
|
+
say(` ${import_picocolors73.default.dim("then follow it with")} ${import_picocolors73.default.cyan(reattach)}`);
|
|
88274
89050
|
}
|
|
88275
89051
|
let status;
|
|
88276
89052
|
let buildId = null;
|
|
88277
89053
|
if (versionId) {
|
|
88278
89054
|
say("");
|
|
88279
|
-
say(` ${
|
|
89055
|
+
say(` ${import_picocolors73.default.dim("version")} ${safe(versionId)}`);
|
|
88280
89056
|
if (!json3)
|
|
88281
|
-
say(` ${
|
|
89057
|
+
say(` ${import_picocolors73.default.dim("Waiting for its build...")}`);
|
|
88282
89058
|
const buildKey = `${key2}-build`;
|
|
88283
89059
|
let outcome;
|
|
88284
89060
|
try {
|
|
@@ -88288,7 +89064,7 @@ async function build(ctx) {
|
|
|
88288
89064
|
signal: stop.signal,
|
|
88289
89065
|
now: deps.now,
|
|
88290
89066
|
idempotencyKey: buildKey,
|
|
88291
|
-
onStall: () => say(` ${
|
|
89067
|
+
onStall: () => say(` ${import_picocolors73.default.yellow("The build looks stalled; still waiting in case another worker picks it up.")}`)
|
|
88292
89068
|
});
|
|
88293
89069
|
} catch (error2) {
|
|
88294
89070
|
if (error2 instanceof LostResponseError) {
|
|
@@ -88304,9 +89080,9 @@ async function build(ctx) {
|
|
|
88304
89080
|
status = noVersionStatus(mine?.status === "failed", task.status);
|
|
88305
89081
|
if (status === "no_version") {
|
|
88306
89082
|
codes.push(1);
|
|
88307
|
-
say(` ${
|
|
89083
|
+
say(` ${import_picocolors73.default.red("The conversation finished without committing a version, so there is nothing to build.")}`);
|
|
88308
89084
|
} else if (task.status !== "need_more_info") {
|
|
88309
|
-
say(` ${
|
|
89085
|
+
say(` ${import_picocolors73.default.dim("This conversation produced no version, so there is nothing to build.")}`);
|
|
88310
89086
|
}
|
|
88311
89087
|
}
|
|
88312
89088
|
if (!json3)
|
|
@@ -88321,7 +89097,7 @@ async function build(ctx) {
|
|
|
88321
89097
|
var buildCommands = { build };
|
|
88322
89098
|
|
|
88323
89099
|
// src/cli/interface-lifecycle.ts
|
|
88324
|
-
var
|
|
89100
|
+
var import_picocolors75 = __toESM(require_picocolors(), 1);
|
|
88325
89101
|
|
|
88326
89102
|
// src/core/org-members.ts
|
|
88327
89103
|
async function listAllOrgMembers(orgId) {
|
|
@@ -88375,7 +89151,7 @@ function membersById(members) {
|
|
|
88375
89151
|
}
|
|
88376
89152
|
|
|
88377
89153
|
// src/cli/interface-read.ts
|
|
88378
|
-
var
|
|
89154
|
+
var import_picocolors74 = __toESM(require_picocolors(), 1);
|
|
88379
89155
|
function interfaceState(row) {
|
|
88380
89156
|
if (row.archived_at)
|
|
88381
89157
|
return "archived";
|
|
@@ -88397,11 +89173,11 @@ function threadsLabel(shared) {
|
|
|
88397
89173
|
function stateTint(state) {
|
|
88398
89174
|
switch (state) {
|
|
88399
89175
|
case "live":
|
|
88400
|
-
return
|
|
89176
|
+
return import_picocolors74.default.green;
|
|
88401
89177
|
case "building":
|
|
88402
|
-
return
|
|
89178
|
+
return import_picocolors74.default.yellow;
|
|
88403
89179
|
case "archived":
|
|
88404
|
-
return
|
|
89180
|
+
return import_picocolors74.default.dim;
|
|
88405
89181
|
case "draft":
|
|
88406
89182
|
return (cell) => cell;
|
|
88407
89183
|
default: {
|
|
@@ -88434,7 +89210,7 @@ async function list3(ctx) {
|
|
|
88434
89210
|
if (shown.length === 0) {
|
|
88435
89211
|
const empty = onlyArchived ? "No archived interfaces." : includeArchived ? "No interfaces. Create one with `brainbase interface create`." : await emptyWithoutArchived(agentId);
|
|
88436
89212
|
console.log(`
|
|
88437
|
-
${
|
|
89213
|
+
${import_picocolors74.default.dim(empty)}
|
|
88438
89214
|
`);
|
|
88439
89215
|
return;
|
|
88440
89216
|
}
|
|
@@ -88447,7 +89223,7 @@ async function list3(ctx) {
|
|
|
88447
89223
|
audienceWord(row),
|
|
88448
89224
|
ago(row.last_edited_at ?? row.created_at, now2)
|
|
88449
89225
|
]);
|
|
88450
|
-
console.log(["", ...table(cells, [null,
|
|
89226
|
+
console.log(["", ...table(cells, [null, import_picocolors74.default.bold, null, null, null, import_picocolors74.default.dim]), ""].join(`
|
|
88451
89227
|
`));
|
|
88452
89228
|
});
|
|
88453
89229
|
}
|
|
@@ -88481,13 +89257,13 @@ async function get2(ctx) {
|
|
|
88481
89257
|
out.push(field("id", safe(row.id)));
|
|
88482
89258
|
out.push(field("agent", agentLabel(safe(row.agent_id), await agentNames([row.agent_id]))));
|
|
88483
89259
|
out.push(field("state", stateTint(state)(state)));
|
|
88484
|
-
out.push(field("address", row.live_release ? safe(row.live_release.url) : `${safe(row.slug)} ${
|
|
89260
|
+
out.push(field("address", row.live_release ? safe(row.live_release.url) : `${safe(row.slug)} ${import_picocolors74.default.dim("(nothing live yet)")}`));
|
|
88485
89261
|
out.push(field("audience", audienceLabel(row)));
|
|
88486
89262
|
out.push(field("threads", threadsLabel(row.share_agent_threads)));
|
|
88487
|
-
out.push(field("live", row.live_release ? `${safe(row.live_release.id)} ${
|
|
88488
|
-
out.push(field("draft", row.draft_version_id ? safe(row.draft_version_id) :
|
|
89263
|
+
out.push(field("live", row.live_release ? `${safe(row.live_release.id)} ${import_picocolors74.default.dim(`published ${ago(row.live_release.published_at)}`)}` : import_picocolors74.default.dim("none")));
|
|
89264
|
+
out.push(field("draft", row.draft_version_id ? safe(row.draft_version_id) : import_picocolors74.default.dim("none yet")));
|
|
88489
89265
|
if (row.running_generation) {
|
|
88490
|
-
out.push(field("building", `conversation ${safe(row.running_generation.thread_id ?? "")} ${
|
|
89266
|
+
out.push(field("building", `conversation ${safe(row.running_generation.thread_id ?? "")} ${import_picocolors74.default.dim(`(follow it with \`brainbase task logs ${safe(row.running_generation.thread_id ?? "")} --follow\`)`)}`));
|
|
88491
89267
|
}
|
|
88492
89268
|
if (row.archived_at)
|
|
88493
89269
|
out.push(field("archived", ago(row.archived_at)));
|
|
@@ -88516,7 +89292,7 @@ async function open(ctx) {
|
|
|
88516
89292
|
}
|
|
88517
89293
|
console.log(safe(url2));
|
|
88518
89294
|
if (new URL(url2).hostname.endsWith("vercel.app")) {
|
|
88519
|
-
console.error(
|
|
89295
|
+
console.error(import_picocolors74.default.yellow("This is the raw Vercel deployment address, which sits behind Vercel protection and will not open for viewers. The control plane has no public interfaces domain configured."));
|
|
88520
89296
|
}
|
|
88521
89297
|
});
|
|
88522
89298
|
}
|
|
@@ -88554,7 +89330,7 @@ async function history(ctx, name) {
|
|
|
88554
89330
|
banner(`interface ${name} — ${safe(id)}`);
|
|
88555
89331
|
if (rows.length === 0) {
|
|
88556
89332
|
console.log(`
|
|
88557
|
-
${
|
|
89333
|
+
${import_picocolors74.default.dim(`No ${name} yet.`)}
|
|
88558
89334
|
`);
|
|
88559
89335
|
return;
|
|
88560
89336
|
}
|
|
@@ -88631,7 +89407,7 @@ function exactlyOne(parsed, flags) {
|
|
|
88631
89407
|
}
|
|
88632
89408
|
function peopleLine(access, members) {
|
|
88633
89409
|
const ids = grantIds(access);
|
|
88634
|
-
return ids.length ? namesOf(ids, members) :
|
|
89410
|
+
return ids.length ? namesOf(ids, members) : import_picocolors75.default.dim("nobody named");
|
|
88635
89411
|
}
|
|
88636
89412
|
function printAccess(row, access, members) {
|
|
88637
89413
|
console.log([
|
|
@@ -88692,8 +89468,8 @@ async function create3(ctx) {
|
|
|
88692
89468
|
}
|
|
88693
89469
|
} catch (error2) {
|
|
88694
89470
|
readFailed = true;
|
|
88695
|
-
const
|
|
88696
|
-
accessError = error2 instanceof InterfaceApiError ? new InterfaceApiError(
|
|
89471
|
+
const message3 = `Created ${created.id}, but its audience could not be read, so it was not changed. ` + `Check it with \`brainbase interface access ${created.id}\`. (${error2.message})`;
|
|
89472
|
+
accessError = error2 instanceof InterfaceApiError ? new InterfaceApiError(message3, error2.code, error2.reason, error2.details, error2.status, error2.body) : new Error(message3);
|
|
88697
89473
|
}
|
|
88698
89474
|
}
|
|
88699
89475
|
if (audience && !note && !readFailed) {
|
|
@@ -88727,11 +89503,11 @@ async function create3(ctx) {
|
|
|
88727
89503
|
const id = safe(created.id);
|
|
88728
89504
|
const out = [
|
|
88729
89505
|
"",
|
|
88730
|
-
` ${
|
|
89506
|
+
` ${import_picocolors75.default.green("Created")} ${import_picocolors75.default.bold(safe(created.name))}`,
|
|
88731
89507
|
"",
|
|
88732
89508
|
field("id", id),
|
|
88733
89509
|
field("agent", safe(created.agent_id)),
|
|
88734
|
-
field("address", `${safe(created.slug)} ${
|
|
89510
|
+
field("address", `${safe(created.slug)} ${import_picocolors75.default.dim("(nothing live yet)")}`),
|
|
88735
89511
|
field("threads", threadsLabel(created.share_agent_threads))
|
|
88736
89512
|
];
|
|
88737
89513
|
if (access) {
|
|
@@ -88743,11 +89519,11 @@ async function create3(ctx) {
|
|
|
88743
89519
|
out.push("", ` Nobody can open it until you choose who can: \`brainbase interface access ${id} --everyone\` or \`--people <emails>\`.`);
|
|
88744
89520
|
}
|
|
88745
89521
|
if (created.share_agent_threads) {
|
|
88746
|
-
out.push(` ${
|
|
89522
|
+
out.push(` ${import_picocolors75.default.dim(`To show viewers only their own conversations: \`brainbase interface threads ${id} --private\`.`)}`);
|
|
88747
89523
|
}
|
|
88748
89524
|
if (note)
|
|
88749
89525
|
out.push("", ` ${safe(note)}`);
|
|
88750
|
-
out.push("", ` ${
|
|
89526
|
+
out.push("", ` ${import_picocolors75.default.dim(`Next: \`brainbase interface build ${id} "<what to build>"\``)}`, "");
|
|
88751
89527
|
console.log(out.join(`
|
|
88752
89528
|
`));
|
|
88753
89529
|
if (readFailed) {
|
|
@@ -88883,7 +89659,7 @@ async function threads(ctx) {
|
|
|
88883
89659
|
printJson({ id: row.id, share_agent_threads: row.share_agent_threads });
|
|
88884
89660
|
return;
|
|
88885
89661
|
}
|
|
88886
|
-
const already = wanted === null ? "" : ` ${
|
|
89662
|
+
const already = wanted === null ? "" : ` ${import_picocolors75.default.dim("(already set; nothing changed)")}`;
|
|
88887
89663
|
console.log(`
|
|
88888
89664
|
${field("threads", `${threadsLabel(row.share_agent_threads)}${already}`)}
|
|
88889
89665
|
`);
|
|
@@ -88922,7 +89698,7 @@ async function rename(ctx) {
|
|
|
88922
89698
|
return;
|
|
88923
89699
|
}
|
|
88924
89700
|
console.log(`
|
|
88925
|
-
Renamed ${safe(updated.id)} to ${
|
|
89701
|
+
Renamed ${safe(updated.id)} to ${import_picocolors75.default.bold(safe(updated.name))}.
|
|
88926
89702
|
`);
|
|
88927
89703
|
});
|
|
88928
89704
|
}
|
|
@@ -88958,7 +89734,7 @@ async function address(ctx) {
|
|
|
88958
89734
|
}
|
|
88959
89735
|
const where = updated.live_release ? safe(updated.live_release.url) : safe(updated.slug);
|
|
88960
89736
|
console.log(`
|
|
88961
|
-
${safe(updated.name)} is now at ${
|
|
89737
|
+
${safe(updated.name)} is now at ${import_picocolors75.default.bold(where)}.
|
|
88962
89738
|
`);
|
|
88963
89739
|
});
|
|
88964
89740
|
}
|
|
@@ -89050,9 +89826,9 @@ var lifecycleCommands = {
|
|
|
89050
89826
|
};
|
|
89051
89827
|
|
|
89052
89828
|
// src/cli/interface-preview.ts
|
|
89053
|
-
var
|
|
89829
|
+
var import_picocolors76 = __toESM(require_picocolors(), 1);
|
|
89054
89830
|
function warn(line2) {
|
|
89055
|
-
console.error(
|
|
89831
|
+
console.error(import_picocolors76.default.yellow(line2));
|
|
89056
89832
|
}
|
|
89057
89833
|
var PREVIEW_TIMEOUT_SECONDS = 300;
|
|
89058
89834
|
var PROBE_INTERVAL_MS = 2000;
|
|
@@ -89142,12 +89918,12 @@ async function preview(ctx) {
|
|
|
89142
89918
|
const say = progress(json3);
|
|
89143
89919
|
const row = await interfacesApi.get(id);
|
|
89144
89920
|
const { taskId, why } = await pickConversation(row, stringOption(parsed, "task")?.trim() || undefined);
|
|
89145
|
-
say(
|
|
89921
|
+
say(import_picocolors76.default.dim(` Previewing ${why}, ${safe(taskId)}.`));
|
|
89146
89922
|
const started = await interfacesApi.startPreview(taskId, row.id);
|
|
89147
89923
|
const address2 = previewAddress(started, row);
|
|
89148
89924
|
let outcome = started.state === "serving" ? "serving" : "not_waited";
|
|
89149
89925
|
if (outcome !== "serving" && !noWait) {
|
|
89150
|
-
say(
|
|
89926
|
+
say(import_picocolors76.default.dim(" Starting the dev server in the sandbox…"));
|
|
89151
89927
|
outcome = await waitUntilServing(started, { timeoutMs: waitMs, deps: ctx.deps });
|
|
89152
89928
|
}
|
|
89153
89929
|
if (json3) {
|
|
@@ -89155,12 +89931,12 @@ async function preview(ctx) {
|
|
|
89155
89931
|
} else {
|
|
89156
89932
|
const out = [
|
|
89157
89933
|
"",
|
|
89158
|
-
` ${outcome === "serving" ?
|
|
89934
|
+
` ${outcome === "serving" ? import_picocolors76.default.green("Preview ready") : import_picocolors76.default.yellow("Preview starting")} ${import_picocolors76.default.bold(safe(started.name))}`,
|
|
89159
89935
|
"",
|
|
89160
|
-
field("address", address2 ? safe(address2) :
|
|
89936
|
+
field("address", address2 ? safe(address2) : import_picocolors76.default.dim(missingAddress(started))),
|
|
89161
89937
|
field("showing", showing(started, taskId)),
|
|
89162
89938
|
"",
|
|
89163
|
-
` ${
|
|
89939
|
+
` ${import_picocolors76.default.dim("Opens for people who can edit the agent, after signing in. Nothing is published.")}`,
|
|
89164
89940
|
""
|
|
89165
89941
|
];
|
|
89166
89942
|
console.log(out.join(`
|
|
@@ -89181,19 +89957,19 @@ async function preview(ctx) {
|
|
|
89181
89957
|
var previewCommands = { preview };
|
|
89182
89958
|
|
|
89183
89959
|
// src/cli/interface-release.ts
|
|
89184
|
-
var
|
|
89960
|
+
var import_picocolors77 = __toESM(require_picocolors(), 1);
|
|
89185
89961
|
var PUBLISH_TIMEOUT_SECONDS = 300;
|
|
89186
89962
|
var REBUILD_USAGE = "brainbase interface rebuild <id> [--version <version id>] [--yes]";
|
|
89187
89963
|
var PUBLISH_USAGE = "brainbase interface publish <id> [--build <build id>]";
|
|
89188
89964
|
var ROLLBACK_USAGE = "brainbase interface rollback <id> --release <release id>";
|
|
89189
89965
|
function warn2(line2) {
|
|
89190
|
-
console.error(
|
|
89966
|
+
console.error(import_picocolors77.default.yellow(line2));
|
|
89191
89967
|
}
|
|
89192
89968
|
function text3(value2) {
|
|
89193
89969
|
return typeof value2 === "string" && value2.trim() ? value2 : null;
|
|
89194
89970
|
}
|
|
89195
|
-
function reword(error2,
|
|
89196
|
-
return new InterfaceApiError(
|
|
89971
|
+
function reword(error2, message3) {
|
|
89972
|
+
return new InterfaceApiError(message3, error2.code, error2.reason, error2.details, error2.status, error2.body);
|
|
89197
89973
|
}
|
|
89198
89974
|
async function follow(operationId, what, options) {
|
|
89199
89975
|
const stop = interruption(options.deps);
|
|
@@ -89204,7 +89980,7 @@ async function follow(operationId, what, options) {
|
|
|
89204
89980
|
intervalMs: options.deps.pollIntervalMs,
|
|
89205
89981
|
signal: stop.signal,
|
|
89206
89982
|
now: options.deps.now,
|
|
89207
|
-
onStatus: (operation) => say(
|
|
89983
|
+
onStatus: (operation) => say(import_picocolors77.default.dim(` ${what} ${operation.status}`)),
|
|
89208
89984
|
onStall: () => warn2(`The ${what} looks stalled: its worker stopped checking in. Still waiting, in case another worker picks it up.`)
|
|
89209
89985
|
});
|
|
89210
89986
|
if (outcome.kind === "settled") {
|
|
@@ -89223,7 +89999,7 @@ function reportUnsuccessful(result2, what, options) {
|
|
|
89223
89999
|
if (options.json) {
|
|
89224
90000
|
printJson({ outcome: result2.outcome, operation_id: result2.operationId, operation: result2.operation });
|
|
89225
90001
|
} else if (result2.outcome === "failed") {
|
|
89226
|
-
console.error(
|
|
90002
|
+
console.error(import_picocolors77.default.red(`The ${what} failed (operation ${id}):`));
|
|
89227
90003
|
console.error(safeBlock(result2.operation?.error ?? "Brainbase gave no reason."));
|
|
89228
90004
|
} else if (result2.outcome === "timeout") {
|
|
89229
90005
|
warn2(`Stopped waiting after ${Math.round(options.timeoutMs / 1000)}s. The ${what} keeps running on the server (operation ${id}).`);
|
|
@@ -89283,7 +90059,7 @@ async function rebuild(ctx) {
|
|
|
89283
90059
|
if (json3)
|
|
89284
90060
|
printJson({ outcome: "started", operation_id: operationId, operation });
|
|
89285
90061
|
else
|
|
89286
|
-
console.log(
|
|
90062
|
+
console.log(import_picocolors77.default.dim(` Follow it with \`brainbase interface builds ${safe(id)}\`.`));
|
|
89287
90063
|
return;
|
|
89288
90064
|
}
|
|
89289
90065
|
const result2 = await follow(operationId, "build", { json: json3, timeoutMs: waitMs, deps: ctx.deps });
|
|
@@ -89295,8 +90071,8 @@ async function rebuild(ctx) {
|
|
|
89295
90071
|
}
|
|
89296
90072
|
const buildId = safe(result2.operation?.build_id ?? "");
|
|
89297
90073
|
const version2 = safe(result2.operation?.source_version_id ?? "");
|
|
89298
|
-
console.log(
|
|
89299
|
-
console.log(
|
|
90074
|
+
console.log(import_picocolors77.default.green(`✓ Build ${buildId} succeeded${version2 ? ` (version ${version2})` : ""}.`));
|
|
90075
|
+
console.log(import_picocolors77.default.dim(` Publish it with \`brainbase interface publish ${safe(id)} --build ${buildId}\`.`));
|
|
89300
90076
|
});
|
|
89301
90077
|
}
|
|
89302
90078
|
function liveBuildOf(row, releases) {
|
|
@@ -89354,7 +90130,7 @@ function describeBuild(buildId, builds) {
|
|
|
89354
90130
|
const build2 = builds.find((candidate) => candidate.id === buildId);
|
|
89355
90131
|
if (!build2)
|
|
89356
90132
|
return `build ${safe(buildId)}`;
|
|
89357
|
-
return `build ${safe(build2.id)} ${
|
|
90133
|
+
return `build ${safe(build2.id)} ${import_picocolors77.default.dim(`(version ${safe(build2.source_version_id)}, built ${ago(build2.created_at)})`)}`;
|
|
89358
90134
|
}
|
|
89359
90135
|
function reportAlreadyLive(json3, buildId, releaseId, url2) {
|
|
89360
90136
|
if (json3) {
|
|
@@ -89408,8 +90184,8 @@ async function publish(ctx) {
|
|
|
89408
90184
|
}
|
|
89409
90185
|
if (!json3) {
|
|
89410
90186
|
console.log("");
|
|
89411
|
-
console.log(` ${
|
|
89412
|
-
console.log(` ${
|
|
90187
|
+
console.log(` ${import_picocolors77.default.dim("Live now".padEnd(14))}${liveBuildId ? `${describeBuild(liveBuildId, builds)} at ${safe(row.live_release?.url)}` : row.live_release ? `release ${safe(row.live_release.id)} at ${safe(row.live_release.url)}` : import_picocolors77.default.dim("nothing")}`);
|
|
90188
|
+
console.log(` ${import_picocolors77.default.dim("Will publish".padEnd(14))}${describeBuild(buildId, builds)}`);
|
|
89413
90189
|
console.log("");
|
|
89414
90190
|
}
|
|
89415
90191
|
const proceed = await confirmChange({
|
|
@@ -89452,7 +90228,7 @@ async function publish(ctx) {
|
|
|
89452
90228
|
if (json3)
|
|
89453
90229
|
printJson({ outcome: "started", operation_id: operationId, operation });
|
|
89454
90230
|
else
|
|
89455
|
-
console.log(
|
|
90231
|
+
console.log(import_picocolors77.default.dim(` Check it with \`brainbase interface get ${safe(id)}\`.`));
|
|
89456
90232
|
return;
|
|
89457
90233
|
}
|
|
89458
90234
|
const result2 = await follow(operationId, "publish", { json: json3, timeoutMs: waitMs, deps: ctx.deps });
|
|
@@ -89469,11 +90245,11 @@ async function publish(ctx) {
|
|
|
89469
90245
|
printJson({ outcome: "succeeded", operation_id: operationId, operation: result2.operation, url: url2 });
|
|
89470
90246
|
return;
|
|
89471
90247
|
}
|
|
89472
|
-
console.log(
|
|
90248
|
+
console.log(import_picocolors77.default.green(`✓ Build ${safe(buildId)} is live.`));
|
|
89473
90249
|
if (url2)
|
|
89474
90250
|
console.log(` ${safe(url2)}`);
|
|
89475
90251
|
if (urlUnread) {
|
|
89476
|
-
console.log(
|
|
90252
|
+
console.log(import_picocolors77.default.dim(` Its address could not be read just now; see it with \`brainbase interface open ${safe(id)}\`.`));
|
|
89477
90253
|
}
|
|
89478
90254
|
});
|
|
89479
90255
|
}
|
|
@@ -89509,8 +90285,8 @@ async function rollback(ctx) {
|
|
|
89509
90285
|
}
|
|
89510
90286
|
if (!json3) {
|
|
89511
90287
|
console.log("");
|
|
89512
|
-
console.log(` ${
|
|
89513
|
-
console.log(` ${
|
|
90288
|
+
console.log(` ${import_picocolors77.default.dim("Live now".padEnd(16))}release ${safe(row.live_release.id)} at ${safe(row.live_release.url)}`);
|
|
90289
|
+
console.log(` ${import_picocolors77.default.dim("Will republish".padEnd(16))}release ${safe(releaseId)} ${import_picocolors77.default.dim("as a new release, with a new id")}`);
|
|
89514
90290
|
console.log("");
|
|
89515
90291
|
}
|
|
89516
90292
|
const proceed = await confirmChange({
|
|
@@ -89543,7 +90319,7 @@ async function rollback(ctx) {
|
|
|
89543
90319
|
printJson(release);
|
|
89544
90320
|
return;
|
|
89545
90321
|
}
|
|
89546
|
-
console.log(
|
|
90322
|
+
console.log(import_picocolors77.default.green(release.id === releaseId ? `✓ Release ${safe(releaseId)} is live (build ${safe(release.build_id)}).` : `✓ Republished release ${safe(releaseId)} as new release ${safe(release.id)} (build ${safe(release.build_id)}). It is live.`));
|
|
89547
90323
|
console.log(` ${safe(release.url)}`);
|
|
89548
90324
|
});
|
|
89549
90325
|
}
|
|
@@ -89578,14 +90354,14 @@ ${didYouMean(sub, Object.keys(COMMANDS2), "brainbase interface")}`);
|
|
|
89578
90354
|
await command({ cwd: cwd2, args, deps });
|
|
89579
90355
|
}
|
|
89580
90356
|
function line2(command, args, description) {
|
|
89581
|
-
return ` ${
|
|
89582
|
-
${
|
|
90357
|
+
return ` ${import_picocolors78.default.cyan(command)}${args ? ` ${import_picocolors78.default.dim(args)}` : ""}
|
|
90358
|
+
${import_picocolors78.default.dim(description)}`;
|
|
89583
90359
|
}
|
|
89584
90360
|
function printHelp7() {
|
|
89585
90361
|
const out = [];
|
|
89586
90362
|
out.push("");
|
|
89587
|
-
out.push(` ${
|
|
89588
|
-
out.push(` ${
|
|
90363
|
+
out.push(` ${import_picocolors78.default.bold("brainbase interface")} ${import_picocolors78.default.dim("<sub> [options]")}`);
|
|
90364
|
+
out.push(` ${import_picocolors78.default.dim("Dashboards for an agent: build them in a conversation, publish them, choose who can open them.")}`);
|
|
89589
90365
|
out.push("");
|
|
89590
90366
|
out.push(line2("ls", "[--agent <id>] [--archived | --only-archived]", "list interfaces you can see"));
|
|
89591
90367
|
out.push(line2("get", "<id>", "one interface: address, audience, live release, draft, running build conversation"));
|
|
@@ -89605,22 +90381,22 @@ function printHelp7() {
|
|
|
89605
90381
|
out.push(line2("rollback", "<id> --release <id>", "republish an earlier release; it goes live under a new release id"));
|
|
89606
90382
|
out.push(line2("preview", "<id> [--task <id>] [--no-wait]", "serve the unpublished draft from its build conversation and print the preview address"));
|
|
89607
90383
|
out.push("");
|
|
89608
|
-
out.push(` ${
|
|
89609
|
-
out.push(` ${
|
|
89610
|
-
out.push(` ${
|
|
89611
|
-
out.push(` ${
|
|
89612
|
-
out.push(` ${
|
|
90384
|
+
out.push(` ${import_picocolors78.default.dim("--json")} machine-readable output; never prompts`);
|
|
90385
|
+
out.push(` ${import_picocolors78.default.dim("--yes, -y")} skip confirmation (required without a terminal)`);
|
|
90386
|
+
out.push(` ${import_picocolors78.default.dim("--no-wait")} for rebuild and publish: return the operation at once; for preview: do not wait for the dev server`);
|
|
90387
|
+
out.push(` ${import_picocolors78.default.dim("--timeout <seconds>")} for build, rebuild, publish and preview: how long to wait (builds 900, publish and preview 300)`);
|
|
90388
|
+
out.push(` ${import_picocolors78.default.dim("--idempotency-key <key>")} replay a create, build, rebuild, publish or rollback whose answer was lost`);
|
|
89613
90389
|
out.push("");
|
|
89614
|
-
out.push(` ${
|
|
89615
|
-
out.push(` ${
|
|
89616
|
-
out.push(` ${
|
|
90390
|
+
out.push(` ${import_picocolors78.default.dim("People are emails (see `brainbase member ls`), user ids, or `me`. Audience members also need access to the agent.")}`);
|
|
90391
|
+
out.push(` ${import_picocolors78.default.dim("Audience: everyone (--everyone, `org` under --json) or chosen people (--people, `users` under --json).")}`);
|
|
90392
|
+
out.push(` ${import_picocolors78.default.dim("Exit codes: 0 done, 1 refused or failed, 130 interrupted (the server keeps working).")}`);
|
|
89617
90393
|
out.push("");
|
|
89618
90394
|
console.log(out.join(`
|
|
89619
90395
|
`));
|
|
89620
90396
|
}
|
|
89621
90397
|
|
|
89622
90398
|
// src/cli/member.ts
|
|
89623
|
-
var
|
|
90399
|
+
var import_picocolors79 = __toESM(require_picocolors(), 1);
|
|
89624
90400
|
async function runMember(sub, args, opts) {
|
|
89625
90401
|
if (args.some((arg) => arg === "--help" || arg === "-h")) {
|
|
89626
90402
|
printHelp8();
|
|
@@ -89663,7 +90439,7 @@ async function runMemberList(opts) {
|
|
|
89663
90439
|
function formatMemberList(members) {
|
|
89664
90440
|
if (members.length === 0)
|
|
89665
90441
|
return `
|
|
89666
|
-
${
|
|
90442
|
+
${import_picocolors79.default.dim("Nobody here you can see.")}
|
|
89667
90443
|
`;
|
|
89668
90444
|
const sorted = [...members].sort((a3, b4) => (a3.email ?? a3.id).localeCompare(b4.email ?? b4.id));
|
|
89669
90445
|
const rows = sorted.map((member) => ({
|
|
@@ -89677,24 +90453,24 @@ function formatMemberList(members) {
|
|
|
89677
90453
|
const roleWidth = Math.max(...rows.map((row) => row.role.length));
|
|
89678
90454
|
const lines = [""];
|
|
89679
90455
|
for (const row of rows) {
|
|
89680
|
-
lines.push(` ${row.email.padEnd(emailWidth)} ${row.name.padEnd(nameWidth)} ${
|
|
90456
|
+
lines.push(` ${row.email.padEnd(emailWidth)} ${row.name.padEnd(nameWidth)} ${import_picocolors79.default.dim(row.role.padEnd(roleWidth))} ${import_picocolors79.default.dim(row.teams)}`.trimEnd());
|
|
89681
90457
|
}
|
|
89682
|
-
lines.push("", ` ${
|
|
90458
|
+
lines.push("", ` ${import_picocolors79.default.dim("share a dashboard with one of them:")} ${import_picocolors79.default.cyan("brainbase interface access <id> --add <email>")}`, "");
|
|
89683
90459
|
return lines.join(`
|
|
89684
90460
|
`);
|
|
89685
90461
|
}
|
|
89686
90462
|
function printHelp8() {
|
|
89687
90463
|
const out = [];
|
|
89688
90464
|
out.push("");
|
|
89689
|
-
out.push(` ${
|
|
90465
|
+
out.push(` ${import_picocolors79.default.bold("brainbase member")} ${import_picocolors79.default.dim("<sub> [options]")}`);
|
|
89690
90466
|
out.push("");
|
|
89691
|
-
out.push(` ${
|
|
90467
|
+
out.push(` ${import_picocolors79.default.cyan("ls")} ${import_picocolors79.default.dim("the people in an organization you can see, with their emails, roles and teams")}`);
|
|
89692
90468
|
out.push("");
|
|
89693
|
-
out.push(` ${
|
|
89694
|
-
out.push(` ${
|
|
90469
|
+
out.push(` ${import_picocolors79.default.dim("--org <id-or-slug>")} ${import_picocolors79.default.dim("which organization (picked automatically when you are in one)")}`);
|
|
90470
|
+
out.push(` ${import_picocolors79.default.dim("--json")} ${import_picocolors79.default.dim("machine-readable output")}`);
|
|
89695
90471
|
out.push("");
|
|
89696
|
-
out.push(` ${
|
|
89697
|
-
out.push(` ${
|
|
90472
|
+
out.push(` ${import_picocolors79.default.dim("Owners and admins see everyone. Anyone else sees the owners, the admins, themselves")}`);
|
|
90473
|
+
out.push(` ${import_picocolors79.default.dim("and the people who share a team with them, as in the web app.")}`);
|
|
89698
90474
|
out.push("");
|
|
89699
90475
|
console.log(out.join(`
|
|
89700
90476
|
`));
|
|
@@ -90146,8 +90922,8 @@ var BENCHMARK_CAPABILITIES = {
|
|
|
90146
90922
|
class BenchmarkPhaseError extends Error {
|
|
90147
90923
|
code;
|
|
90148
90924
|
details;
|
|
90149
|
-
constructor(code,
|
|
90150
|
-
super(
|
|
90925
|
+
constructor(code, message3, details) {
|
|
90926
|
+
super(message3);
|
|
90151
90927
|
this.code = code;
|
|
90152
90928
|
this.details = details;
|
|
90153
90929
|
this.name = "BenchmarkPhaseError";
|
|
@@ -90158,8 +90934,8 @@ class BenchmarkCommandExecutionError extends BenchmarkPhaseError {
|
|
|
90158
90934
|
stdout;
|
|
90159
90935
|
stderr;
|
|
90160
90936
|
durationMs;
|
|
90161
|
-
constructor(code,
|
|
90162
|
-
super(code,
|
|
90937
|
+
constructor(code, message3, stdout, stderr, durationMs) {
|
|
90938
|
+
super(code, message3);
|
|
90163
90939
|
this.stdout = stdout;
|
|
90164
90940
|
this.stderr = stderr;
|
|
90165
90941
|
this.durationMs = durationMs;
|
|
@@ -92787,7 +93563,7 @@ async function runBenchmarkPhase(specPathInput, resultPathInput, expectedPhase,
|
|
|
92787
93563
|
}
|
|
92788
93564
|
|
|
92789
93565
|
// src/cli/benchmark-control.ts
|
|
92790
|
-
var
|
|
93566
|
+
var import_picocolors80 = __toESM(require_picocolors(), 1);
|
|
92791
93567
|
import fs92 from "node:fs";
|
|
92792
93568
|
import path103 from "node:path";
|
|
92793
93569
|
|
|
@@ -92799,8 +93575,8 @@ var BENCHMARK_UPLOAD_MIN_BYTES_PER_SECOND = 256 * 1024;
|
|
|
92799
93575
|
class BenchmarkClientUsageError extends Error {
|
|
92800
93576
|
code = "invalid_arguments";
|
|
92801
93577
|
retryable = false;
|
|
92802
|
-
constructor(
|
|
92803
|
-
super(
|
|
93578
|
+
constructor(message3) {
|
|
93579
|
+
super(message3);
|
|
92804
93580
|
this.name = "BenchmarkClientUsageError";
|
|
92805
93581
|
}
|
|
92806
93582
|
}
|
|
@@ -92809,8 +93585,8 @@ class BenchmarkApiError extends ApiError {
|
|
|
92809
93585
|
code;
|
|
92810
93586
|
requestId;
|
|
92811
93587
|
retryable;
|
|
92812
|
-
constructor(
|
|
92813
|
-
super(
|
|
93588
|
+
constructor(message3, status, body, code, requestId, retryable) {
|
|
93589
|
+
super(message3, status, body);
|
|
92814
93590
|
this.code = code;
|
|
92815
93591
|
this.requestId = requestId;
|
|
92816
93592
|
this.name = "BenchmarkApiError";
|
|
@@ -95091,8 +95867,8 @@ function expectPositionals2(positionals, minimum, maximum, usage) {
|
|
|
95091
95867
|
throw usageError(`Usage: ${usage}`);
|
|
95092
95868
|
}
|
|
95093
95869
|
}
|
|
95094
|
-
function usageError(
|
|
95095
|
-
return Object.assign(new Error(
|
|
95870
|
+
function usageError(message3) {
|
|
95871
|
+
return Object.assign(new Error(message3), {
|
|
95096
95872
|
code: "invalid_arguments",
|
|
95097
95873
|
retryable: false
|
|
95098
95874
|
});
|
|
@@ -95801,20 +96577,20 @@ async function emitCursorPages(output, fetchPage, options) {
|
|
|
95801
96577
|
function commandHelp() {
|
|
95802
96578
|
return [
|
|
95803
96579
|
"",
|
|
95804
|
-
` ${
|
|
96580
|
+
` ${import_picocolors80.default.bold("brainbase benchmark")} ${import_picocolors80.default.dim("<command> [options]")}`,
|
|
95805
96581
|
"",
|
|
95806
|
-
` ${
|
|
95807
|
-
` ${
|
|
95808
|
-
` ${
|
|
95809
|
-
` ${
|
|
95810
|
-
` ${
|
|
96582
|
+
` ${import_picocolors80.default.cyan("init | list | show | create | validate | pull | push")}`,
|
|
96583
|
+
` ${import_picocolors80.default.cyan("publish | revisions | import | export | archive | restore")}`,
|
|
96584
|
+
` ${import_picocolors80.default.cyan("run plan|start|watch|list|show|cancel|resume")}`,
|
|
96585
|
+
` ${import_picocolors80.default.cyan("results | diagnoses | attempt | artifacts | export-results")}`,
|
|
96586
|
+
` ${import_picocolors80.default.cyan("history | baseline show|set|clear")}`,
|
|
95811
96587
|
"",
|
|
95812
|
-
` ${
|
|
96588
|
+
` ${import_picocolors80.default.dim("Use --agent to override brainbase.agent.yaml, and --json or --jsonl for automation.")}`,
|
|
95813
96589
|
"",
|
|
95814
|
-
` ${
|
|
95815
|
-
` ${
|
|
95816
|
-
` ${
|
|
95817
|
-
` ${
|
|
96590
|
+
` ${import_picocolors80.default.bold("benchmark runtime (machine-only)")}`,
|
|
96591
|
+
` ${import_picocolors80.default.cyan("hydrate")} ${import_picocolors80.default.dim("--spec <path> --result <path> --json")}`,
|
|
96592
|
+
` ${import_picocolors80.default.cyan("evaluate")} ${import_picocolors80.default.dim("--spec <path> --result <path> --json")}`,
|
|
96593
|
+
` ${import_picocolors80.default.cyan("capabilities")} ${import_picocolors80.default.dim("--json")}`,
|
|
95818
96594
|
""
|
|
95819
96595
|
].join(`
|
|
95820
96596
|
`);
|
|
@@ -96260,8 +97036,8 @@ async function runStart(cwd2, argv, deps) {
|
|
|
96260
97036
|
}
|
|
96261
97037
|
function pausedRunHint(runId, run, agentId) {
|
|
96262
97038
|
const reason = run.paused_reason;
|
|
96263
|
-
const
|
|
96264
|
-
const first = typeof
|
|
97039
|
+
const message3 = reason && typeof reason === "object" && !Array.isArray(reason) ? reason.message : undefined;
|
|
97040
|
+
const first = typeof message3 === "string" && message3.trim() ? `Run paused: ${message3.trim()}` : "Run paused.";
|
|
96265
97041
|
const agent = agentId ? ` --agent ${agentId}` : "";
|
|
96266
97042
|
return `${first}
|
|
96267
97043
|
Resume with: brainbase benchmark run resume ${runId} --yes${agent}`;
|
|
@@ -96917,7 +97693,7 @@ function parsePhaseArgs(args) {
|
|
|
96917
97693
|
throw new Error("--json is required for benchmark phase commands");
|
|
96918
97694
|
return { spec, result: result2, json: true };
|
|
96919
97695
|
}
|
|
96920
|
-
function argumentFailure(phase,
|
|
97696
|
+
function argumentFailure(phase, message3) {
|
|
96921
97697
|
const timestamp = new Date().toISOString();
|
|
96922
97698
|
return {
|
|
96923
97699
|
schema_version: "1",
|
|
@@ -96935,11 +97711,11 @@ function argumentFailure(phase, message2) {
|
|
|
96935
97711
|
outputs: [],
|
|
96936
97712
|
error: {
|
|
96937
97713
|
code: "invalid_arguments",
|
|
96938
|
-
message:
|
|
97714
|
+
message: message3
|
|
96939
97715
|
}
|
|
96940
97716
|
};
|
|
96941
97717
|
}
|
|
96942
|
-
function phaseFailure(invocation, startedAt, started, code,
|
|
97718
|
+
function phaseFailure(invocation, startedAt, started, code, message3) {
|
|
96943
97719
|
return {
|
|
96944
97720
|
schema_version: "1",
|
|
96945
97721
|
cli_version: VERSION,
|
|
@@ -96954,7 +97730,7 @@ function phaseFailure(invocation, startedAt, started, code, message2) {
|
|
|
96954
97730
|
steps: [],
|
|
96955
97731
|
inputs: [],
|
|
96956
97732
|
outputs: [],
|
|
96957
|
-
error: { code, message:
|
|
97733
|
+
error: { code, message: message3 }
|
|
96958
97734
|
};
|
|
96959
97735
|
}
|
|
96960
97736
|
function descendantPids2(parentPid) {
|
|
@@ -97215,6 +97991,806 @@ async function runBenchmark(sub, args, write3 = (value2) => process.stdout.write
|
|
|
97215
97991
|
}
|
|
97216
97992
|
}
|
|
97217
97993
|
|
|
97994
|
+
// src/cli/decide.ts
|
|
97995
|
+
import fs95 from "node:fs";
|
|
97996
|
+
import path107 from "node:path";
|
|
97997
|
+
|
|
97998
|
+
// src/core/decide-api.ts
|
|
97999
|
+
import path105 from "node:path";
|
|
98000
|
+
function decideKeysFile() {
|
|
98001
|
+
return path105.join(process.env.BRAINBASE_HOME ?? BRAINBASE_HOME, "decide-keys.json");
|
|
98002
|
+
}
|
|
98003
|
+
var ATTEMPTS = 3;
|
|
98004
|
+
var RETRY_STATUSES = new Set([429, 502, 503, 504]);
|
|
98005
|
+
var MAX_RETRY_DELAY_MS = 30000;
|
|
98006
|
+
var REQUEST_TIMEOUT_MS3 = 5 * 60000;
|
|
98007
|
+
|
|
98008
|
+
class DecideHttpError extends Error {
|
|
98009
|
+
status;
|
|
98010
|
+
constructor(message3, status) {
|
|
98011
|
+
super(message3);
|
|
98012
|
+
this.status = status;
|
|
98013
|
+
this.name = "DecideHttpError";
|
|
98014
|
+
}
|
|
98015
|
+
}
|
|
98016
|
+
function cacheKey(base2, agentId) {
|
|
98017
|
+
return `${base2}|${agentId}`;
|
|
98018
|
+
}
|
|
98019
|
+
async function resolveDecideCredential(cwd2, agentFlag) {
|
|
98020
|
+
const base2 = proxyBaseUrl(authStatus().session ?? null);
|
|
98021
|
+
const taskKey = process.env.BB_TASK_KEY?.trim();
|
|
98022
|
+
if (taskKey)
|
|
98023
|
+
return { key: taskKey, base: base2, source: "task_key" };
|
|
98024
|
+
const agentId = agentFlag?.trim() || readLink(cwd2)?.agent_id;
|
|
98025
|
+
if (!agentId) {
|
|
98026
|
+
throw new DecideHttpError("No agent to bill. Run inside a linked folder, or pass --agent <id> (see `brainbase agent list`).", null);
|
|
98027
|
+
}
|
|
98028
|
+
const cached2 = readJsonOr(decideKeysFile(), {})[cacheKey(base2, agentId)];
|
|
98029
|
+
if (cached2?.key)
|
|
98030
|
+
return { key: cached2.key, base: base2, source: "agent_key", agentId };
|
|
98031
|
+
return mintAgentKey(base2, agentId);
|
|
98032
|
+
}
|
|
98033
|
+
async function mintAgentKey(base2, agentId) {
|
|
98034
|
+
const created = await api.createCliKey(agentId, { name: "brainbase decide" });
|
|
98035
|
+
const cache3 = readJsonOr(decideKeysFile(), {});
|
|
98036
|
+
cache3[cacheKey(base2, agentId)] = { key: created.key, key_id: created.id };
|
|
98037
|
+
writeJsonAtomic(decideKeysFile(), cache3);
|
|
98038
|
+
return { key: created.key, base: base2, source: "agent_key", agentId };
|
|
98039
|
+
}
|
|
98040
|
+
async function replaceAgentKey(credential) {
|
|
98041
|
+
if (credential.source !== "agent_key" || !credential.agentId)
|
|
98042
|
+
return credential;
|
|
98043
|
+
const cache3 = readJsonOr(decideKeysFile(), {});
|
|
98044
|
+
delete cache3[cacheKey(credential.base, credential.agentId)];
|
|
98045
|
+
writeJsonAtomic(decideKeysFile(), cache3);
|
|
98046
|
+
return mintAgentKey(credential.base, credential.agentId);
|
|
98047
|
+
}
|
|
98048
|
+
function retryDelayMs(attempt2, retryAfter) {
|
|
98049
|
+
const seconds = retryAfter === null ? Number.NaN : Number(retryAfter);
|
|
98050
|
+
const base2 = Number.isFinite(seconds) ? seconds * 1000 : 1000 * 2 ** attempt2;
|
|
98051
|
+
return Math.min(Math.max(base2, 0), MAX_RETRY_DELAY_MS) + Math.random() * 500;
|
|
98052
|
+
}
|
|
98053
|
+
function errorMessage2(status, text4) {
|
|
98054
|
+
try {
|
|
98055
|
+
const body = JSON.parse(text4);
|
|
98056
|
+
const message3 = body.error?.message ?? body.detail;
|
|
98057
|
+
if (typeof message3 === "string" && message3)
|
|
98058
|
+
return message3;
|
|
98059
|
+
} catch {}
|
|
98060
|
+
return `HTTP ${status}`;
|
|
98061
|
+
}
|
|
98062
|
+
async function postDecide(credential, body, options = {}) {
|
|
98063
|
+
const sleep3 = options.sleep ?? ((ms2) => new Promise((resolve) => setTimeout(resolve, ms2)));
|
|
98064
|
+
const payload = JSON.stringify(body);
|
|
98065
|
+
let failure = new DecideHttpError("The decide request failed", null);
|
|
98066
|
+
for (let attempt2 = 0;attempt2 < ATTEMPTS; attempt2 += 1) {
|
|
98067
|
+
let retryAfter = null;
|
|
98068
|
+
try {
|
|
98069
|
+
const response = await fetch(`${credential.base}/v1/decide`, {
|
|
98070
|
+
method: "POST",
|
|
98071
|
+
headers: {
|
|
98072
|
+
Authorization: `Bearer ${credential.key}`,
|
|
98073
|
+
"Content-Type": "application/json"
|
|
98074
|
+
},
|
|
98075
|
+
body: payload,
|
|
98076
|
+
signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS3)
|
|
98077
|
+
});
|
|
98078
|
+
const text4 = await response.text();
|
|
98079
|
+
if (response.ok) {
|
|
98080
|
+
try {
|
|
98081
|
+
return JSON.parse(text4);
|
|
98082
|
+
} catch {
|
|
98083
|
+
throw new DecideHttpError("The server sent an unreadable response", response.status);
|
|
98084
|
+
}
|
|
98085
|
+
}
|
|
98086
|
+
failure = new DecideHttpError(errorMessage2(response.status, text4), response.status);
|
|
98087
|
+
if (!RETRY_STATUSES.has(response.status))
|
|
98088
|
+
throw failure;
|
|
98089
|
+
retryAfter = response.headers.get("retry-after");
|
|
98090
|
+
} catch (error2) {
|
|
98091
|
+
if (error2 instanceof DecideHttpError)
|
|
98092
|
+
throw error2;
|
|
98093
|
+
failure = new DecideHttpError(`Network error: ${error2.message}`, null);
|
|
98094
|
+
}
|
|
98095
|
+
if (attempt2 + 1 < ATTEMPTS)
|
|
98096
|
+
await sleep3(retryDelayMs(attempt2, retryAfter));
|
|
98097
|
+
}
|
|
98098
|
+
throw failure;
|
|
98099
|
+
}
|
|
98100
|
+
|
|
98101
|
+
// src/core/decide-items.ts
|
|
98102
|
+
import fs94 from "node:fs";
|
|
98103
|
+
import path106 from "node:path";
|
|
98104
|
+
|
|
98105
|
+
class DecideInputError extends Error {
|
|
98106
|
+
constructor(message3) {
|
|
98107
|
+
super(message3);
|
|
98108
|
+
this.name = "DecideInputError";
|
|
98109
|
+
}
|
|
98110
|
+
}
|
|
98111
|
+
var GLOB_CHARS = /[*?[{]/;
|
|
98112
|
+
function fileId(cwd2, file) {
|
|
98113
|
+
return path106.relative(cwd2, file).split(path106.sep).join("/") || path106.basename(file);
|
|
98114
|
+
}
|
|
98115
|
+
function isHidden2(name) {
|
|
98116
|
+
return name.startsWith(".") || name === "node_modules";
|
|
98117
|
+
}
|
|
98118
|
+
function appendAll(into, from) {
|
|
98119
|
+
for (const value2 of from)
|
|
98120
|
+
into.push(value2);
|
|
98121
|
+
}
|
|
98122
|
+
function walk(dir, out = []) {
|
|
98123
|
+
for (const entry of fs94.readdirSync(dir, { withFileTypes: true })) {
|
|
98124
|
+
if (isHidden2(entry.name))
|
|
98125
|
+
continue;
|
|
98126
|
+
const full = path106.join(dir, entry.name);
|
|
98127
|
+
if (entry.isDirectory())
|
|
98128
|
+
walk(full, out);
|
|
98129
|
+
else if (entry.isFile())
|
|
98130
|
+
out.push(full);
|
|
98131
|
+
else if (entry.isSymbolicLink()) {
|
|
98132
|
+
try {
|
|
98133
|
+
if (fs94.statSync(full).isFile())
|
|
98134
|
+
out.push(full);
|
|
98135
|
+
} catch {}
|
|
98136
|
+
}
|
|
98137
|
+
}
|
|
98138
|
+
return out;
|
|
98139
|
+
}
|
|
98140
|
+
function walkSorted(dir) {
|
|
98141
|
+
return walk(dir).sort();
|
|
98142
|
+
}
|
|
98143
|
+
function globToRegExp(pattern2) {
|
|
98144
|
+
let source = "";
|
|
98145
|
+
for (let i = 0;i < pattern2.length; i += 1) {
|
|
98146
|
+
const char = pattern2[i];
|
|
98147
|
+
if (char === "*") {
|
|
98148
|
+
if (pattern2[i + 1] === "*") {
|
|
98149
|
+
const slashFollows = pattern2[i + 2] === "/";
|
|
98150
|
+
source += slashFollows ? "(?:.*/)?" : ".*";
|
|
98151
|
+
i += slashFollows ? 2 : 1;
|
|
98152
|
+
} else {
|
|
98153
|
+
source += "[^/]*";
|
|
98154
|
+
}
|
|
98155
|
+
} else if (char === "?") {
|
|
98156
|
+
source += "[^/]";
|
|
98157
|
+
} else if (char === "{") {
|
|
98158
|
+
const close = pattern2.indexOf("}", i);
|
|
98159
|
+
if (close === -1) {
|
|
98160
|
+
source += "\\{";
|
|
98161
|
+
continue;
|
|
98162
|
+
}
|
|
98163
|
+
const choices = pattern2.slice(i + 1, close).split(",");
|
|
98164
|
+
source += `(?:${choices.map((choice) => globToRegExp(choice).source.slice(1, -1)).join("|")})`;
|
|
98165
|
+
i = close;
|
|
98166
|
+
} else if (char === "[") {
|
|
98167
|
+
const close = pattern2.indexOf("]", i + 1);
|
|
98168
|
+
if (close === -1) {
|
|
98169
|
+
source += "\\[";
|
|
98170
|
+
continue;
|
|
98171
|
+
}
|
|
98172
|
+
let body = pattern2.slice(i + 1, close);
|
|
98173
|
+
if (body.startsWith("!"))
|
|
98174
|
+
body = `^${body.slice(1)}`;
|
|
98175
|
+
source += `[${body.replace(/\\/g, "\\\\")}]`;
|
|
98176
|
+
i = close;
|
|
98177
|
+
} else {
|
|
98178
|
+
source += char.replace(/[.+^$()|\\/]/g, "\\$&");
|
|
98179
|
+
}
|
|
98180
|
+
}
|
|
98181
|
+
return new RegExp(`^${source}$`);
|
|
98182
|
+
}
|
|
98183
|
+
function expandGlob(cwd2, pattern2) {
|
|
98184
|
+
const absolute = path106.isAbsolute(pattern2);
|
|
98185
|
+
const segments = pattern2.split("/");
|
|
98186
|
+
const fixed = [];
|
|
98187
|
+
for (const segment of segments) {
|
|
98188
|
+
if (GLOB_CHARS.test(segment))
|
|
98189
|
+
break;
|
|
98190
|
+
fixed.push(segment);
|
|
98191
|
+
}
|
|
98192
|
+
if (fixed.length === segments.length) {
|
|
98193
|
+
return [path106.resolve(cwd2, pattern2)];
|
|
98194
|
+
}
|
|
98195
|
+
const root = path106.resolve(cwd2, fixed.join("/") || ".");
|
|
98196
|
+
if (!fs94.existsSync(root) || !fs94.statSync(root).isDirectory())
|
|
98197
|
+
return [];
|
|
98198
|
+
const matcher = globToRegExp(absolute ? pattern2 : path106.posix.normalize(segments.join("/")));
|
|
98199
|
+
return walkSorted(root).filter((file) => {
|
|
98200
|
+
const candidate = absolute ? file.split(path106.sep).join("/") : fileId(cwd2, file);
|
|
98201
|
+
return matcher.test(candidate);
|
|
98202
|
+
});
|
|
98203
|
+
}
|
|
98204
|
+
function readFileItem(cwd2, file) {
|
|
98205
|
+
const id = fileId(cwd2, file);
|
|
98206
|
+
let bytes;
|
|
98207
|
+
try {
|
|
98208
|
+
bytes = fs94.readFileSync(file);
|
|
98209
|
+
} catch (error2) {
|
|
98210
|
+
return { id, error: `Could not read the file: ${error2.message}` };
|
|
98211
|
+
}
|
|
98212
|
+
if (bytes.includes(0))
|
|
98213
|
+
return { id, error: "Not a text file" };
|
|
98214
|
+
let text4;
|
|
98215
|
+
try {
|
|
98216
|
+
text4 = new TextDecoder("utf-8", { fatal: true }).decode(bytes);
|
|
98217
|
+
} catch {
|
|
98218
|
+
return { id, error: "Not UTF-8 text" };
|
|
98219
|
+
}
|
|
98220
|
+
if (!text4.trim())
|
|
98221
|
+
return { id, error: "Empty file" };
|
|
98222
|
+
return { id, text: text4 };
|
|
98223
|
+
}
|
|
98224
|
+
function fileItems(cwd2, paths, globs) {
|
|
98225
|
+
const files = [];
|
|
98226
|
+
for (const entry of paths) {
|
|
98227
|
+
const full = path106.resolve(cwd2, entry);
|
|
98228
|
+
let stat;
|
|
98229
|
+
try {
|
|
98230
|
+
stat = fs94.statSync(full);
|
|
98231
|
+
} catch {
|
|
98232
|
+
throw new DecideInputError(`No such file or directory: ${entry}`);
|
|
98233
|
+
}
|
|
98234
|
+
if (stat.isDirectory())
|
|
98235
|
+
appendAll(files, walkSorted(full));
|
|
98236
|
+
else
|
|
98237
|
+
files.push(full);
|
|
98238
|
+
}
|
|
98239
|
+
for (const pattern2 of globs) {
|
|
98240
|
+
const matched = expandGlob(cwd2, pattern2);
|
|
98241
|
+
if (matched.length === 0 || !matched.some((file) => fs94.existsSync(file))) {
|
|
98242
|
+
throw new DecideInputError(`No files match ${pattern2}`);
|
|
98243
|
+
}
|
|
98244
|
+
appendAll(files, matched);
|
|
98245
|
+
}
|
|
98246
|
+
return [...new Set(files)];
|
|
98247
|
+
}
|
|
98248
|
+
function readFileItems(cwd2, files) {
|
|
98249
|
+
const set3 = { items: [], failures: [] };
|
|
98250
|
+
for (const file of files) {
|
|
98251
|
+
const item = readFileItem(cwd2, file);
|
|
98252
|
+
if ("error" in item)
|
|
98253
|
+
set3.failures.push(item);
|
|
98254
|
+
else
|
|
98255
|
+
set3.items.push(item);
|
|
98256
|
+
}
|
|
98257
|
+
return set3;
|
|
98258
|
+
}
|
|
98259
|
+
function isRecord2(value2) {
|
|
98260
|
+
return typeof value2 === "object" && value2 !== null && !Array.isArray(value2);
|
|
98261
|
+
}
|
|
98262
|
+
function rowItem(row, options, fallbackId) {
|
|
98263
|
+
const idField = options.idField ?? "id";
|
|
98264
|
+
const rawId = isRecord2(row) ? row[idField] : undefined;
|
|
98265
|
+
let id = fallbackId;
|
|
98266
|
+
if (rawId !== undefined && rawId !== null && rawId !== "")
|
|
98267
|
+
id = String(rawId);
|
|
98268
|
+
else if (options.idField)
|
|
98269
|
+
return { id: fallbackId, error: `Missing ${options.idField}` };
|
|
98270
|
+
if (options.textFields.length === 0)
|
|
98271
|
+
return { id, json: row };
|
|
98272
|
+
if (!isRecord2(row))
|
|
98273
|
+
return { id, error: "Not an object, so --text-field has nothing to select" };
|
|
98274
|
+
if (options.textFields.length === 1) {
|
|
98275
|
+
const field2 = options.textFields[0];
|
|
98276
|
+
const value2 = row[field2];
|
|
98277
|
+
if (value2 === undefined || value2 === null || value2 === "")
|
|
98278
|
+
return { id, error: `Empty ${field2}` };
|
|
98279
|
+
return { id, text: typeof value2 === "string" ? value2 : JSON.stringify(value2) };
|
|
98280
|
+
}
|
|
98281
|
+
const missing = options.textFields.filter((field2) => row[field2] === undefined);
|
|
98282
|
+
if (missing.length)
|
|
98283
|
+
return { id, error: `Missing ${missing.join(", ")}` };
|
|
98284
|
+
const picked = {};
|
|
98285
|
+
for (const field2 of options.textFields)
|
|
98286
|
+
picked[field2] = row[field2];
|
|
98287
|
+
return { id, json: picked };
|
|
98288
|
+
}
|
|
98289
|
+
function sourceLabel(cwd2, file) {
|
|
98290
|
+
return fileId(cwd2, path106.resolve(cwd2, file));
|
|
98291
|
+
}
|
|
98292
|
+
function readSource(cwd2, file) {
|
|
98293
|
+
try {
|
|
98294
|
+
return fs94.readFileSync(path106.resolve(cwd2, file), "utf8");
|
|
98295
|
+
} catch (error2) {
|
|
98296
|
+
throw new DecideInputError(`Could not read ${file}: ${error2.message}`);
|
|
98297
|
+
}
|
|
98298
|
+
}
|
|
98299
|
+
function jsonlItems(cwd2, file, options) {
|
|
98300
|
+
const set3 = { items: [], failures: [] };
|
|
98301
|
+
const label3 = sourceLabel(cwd2, file);
|
|
98302
|
+
readSource(cwd2, file).split(`
|
|
98303
|
+
`).forEach((line3, index) => {
|
|
98304
|
+
if (!line3.trim())
|
|
98305
|
+
return;
|
|
98306
|
+
const fallbackId = `${label3}:${index + 1}`;
|
|
98307
|
+
let row;
|
|
98308
|
+
try {
|
|
98309
|
+
row = JSON.parse(line3);
|
|
98310
|
+
} catch {
|
|
98311
|
+
set3.failures.push({ id: fallbackId, error: "Not valid JSON" });
|
|
98312
|
+
return;
|
|
98313
|
+
}
|
|
98314
|
+
const item = rowItem(row, options, fallbackId);
|
|
98315
|
+
if ("error" in item)
|
|
98316
|
+
set3.failures.push(item);
|
|
98317
|
+
else
|
|
98318
|
+
set3.items.push(item);
|
|
98319
|
+
});
|
|
98320
|
+
return set3;
|
|
98321
|
+
}
|
|
98322
|
+
function parseCsv(text4) {
|
|
98323
|
+
const rows = [];
|
|
98324
|
+
let row = [];
|
|
98325
|
+
let field2 = "";
|
|
98326
|
+
let quoted = false;
|
|
98327
|
+
for (let i = 0;i < text4.length; i += 1) {
|
|
98328
|
+
const char = text4[i];
|
|
98329
|
+
if (quoted) {
|
|
98330
|
+
if (char === '"' && text4[i + 1] === '"') {
|
|
98331
|
+
field2 += '"';
|
|
98332
|
+
i += 1;
|
|
98333
|
+
} else if (char === '"') {
|
|
98334
|
+
quoted = false;
|
|
98335
|
+
} else {
|
|
98336
|
+
field2 += char;
|
|
98337
|
+
}
|
|
98338
|
+
} else if (char === '"' && field2 === "") {
|
|
98339
|
+
quoted = true;
|
|
98340
|
+
} else if (char === ",") {
|
|
98341
|
+
row.push(field2);
|
|
98342
|
+
field2 = "";
|
|
98343
|
+
} else if (char === `
|
|
98344
|
+
` || char === "\r") {
|
|
98345
|
+
if (char === "\r" && text4[i + 1] === `
|
|
98346
|
+
`)
|
|
98347
|
+
i += 1;
|
|
98348
|
+
row.push(field2);
|
|
98349
|
+
rows.push(row);
|
|
98350
|
+
row = [];
|
|
98351
|
+
field2 = "";
|
|
98352
|
+
} else {
|
|
98353
|
+
field2 += char;
|
|
98354
|
+
}
|
|
98355
|
+
}
|
|
98356
|
+
if (field2 !== "" || row.length > 0) {
|
|
98357
|
+
row.push(field2);
|
|
98358
|
+
rows.push(row);
|
|
98359
|
+
}
|
|
98360
|
+
return rows.filter((cells) => cells.some((cell) => cell !== ""));
|
|
98361
|
+
}
|
|
98362
|
+
function csvItems(cwd2, file, options) {
|
|
98363
|
+
const set3 = { items: [], failures: [] };
|
|
98364
|
+
const label3 = sourceLabel(cwd2, file);
|
|
98365
|
+
const [header, ...rows] = parseCsv(readSource(cwd2, file).replace(/^/, ""));
|
|
98366
|
+
if (!header)
|
|
98367
|
+
return set3;
|
|
98368
|
+
rows.forEach((cells, index) => {
|
|
98369
|
+
const row = {};
|
|
98370
|
+
header.forEach((name, column) => {
|
|
98371
|
+
row[name] = cells[column] ?? "";
|
|
98372
|
+
});
|
|
98373
|
+
const item = rowItem(row, options, `${label3}:${index + 2}`);
|
|
98374
|
+
if ("error" in item)
|
|
98375
|
+
set3.failures.push(item);
|
|
98376
|
+
else
|
|
98377
|
+
set3.items.push(item);
|
|
98378
|
+
});
|
|
98379
|
+
return set3;
|
|
98380
|
+
}
|
|
98381
|
+
function readResults(file) {
|
|
98382
|
+
const rows = new Map;
|
|
98383
|
+
if (!fs94.existsSync(file))
|
|
98384
|
+
return rows;
|
|
98385
|
+
for (const line3 of fs94.readFileSync(file, "utf8").split(`
|
|
98386
|
+
`)) {
|
|
98387
|
+
if (!line3.trim())
|
|
98388
|
+
continue;
|
|
98389
|
+
try {
|
|
98390
|
+
const row = JSON.parse(line3);
|
|
98391
|
+
if (row && typeof row.id === "string")
|
|
98392
|
+
rows.set(row.id, row);
|
|
98393
|
+
} catch {}
|
|
98394
|
+
}
|
|
98395
|
+
return rows;
|
|
98396
|
+
}
|
|
98397
|
+
function repairResultsTail(file) {
|
|
98398
|
+
if (!fs94.existsSync(file))
|
|
98399
|
+
return;
|
|
98400
|
+
const text4 = fs94.readFileSync(file, "utf8");
|
|
98401
|
+
if (!text4 || text4.endsWith(`
|
|
98402
|
+
`))
|
|
98403
|
+
return;
|
|
98404
|
+
const cut = text4.lastIndexOf(`
|
|
98405
|
+
`) + 1;
|
|
98406
|
+
const tail2 = text4.slice(cut);
|
|
98407
|
+
let complete = false;
|
|
98408
|
+
try {
|
|
98409
|
+
const row = JSON.parse(tail2);
|
|
98410
|
+
complete = Boolean(row) && typeof row.id === "string";
|
|
98411
|
+
} catch {
|
|
98412
|
+
complete = false;
|
|
98413
|
+
}
|
|
98414
|
+
if (complete)
|
|
98415
|
+
fs94.appendFileSync(file, `
|
|
98416
|
+
`);
|
|
98417
|
+
else
|
|
98418
|
+
fs94.truncateSync(file, Buffer.byteLength(text4.slice(0, cut)));
|
|
98419
|
+
}
|
|
98420
|
+
function parseWhere(value2) {
|
|
98421
|
+
if (value2 === "failed")
|
|
98422
|
+
return { kind: "failed" };
|
|
98423
|
+
if (value2 === "uncertain")
|
|
98424
|
+
return { kind: "uncertain" };
|
|
98425
|
+
const split2 = value2.indexOf("=");
|
|
98426
|
+
if (split2 > 0 && split2 < value2.length - 1) {
|
|
98427
|
+
return { kind: "answer", question: value2.slice(0, split2), answer: value2.slice(split2 + 1) };
|
|
98428
|
+
}
|
|
98429
|
+
throw new DecideInputError(`--where takes failed, uncertain or <question>=<answer>, not ${value2}`);
|
|
98430
|
+
}
|
|
98431
|
+
function rowMatches(row, where) {
|
|
98432
|
+
switch (where.kind) {
|
|
98433
|
+
case "failed":
|
|
98434
|
+
return row.error !== undefined;
|
|
98435
|
+
case "uncertain":
|
|
98436
|
+
return row.error === undefined && row.uncertain === true;
|
|
98437
|
+
case "answer":
|
|
98438
|
+
return row.error === undefined && row.answers?.[where.question]?.choice === where.answer;
|
|
98439
|
+
}
|
|
98440
|
+
}
|
|
98441
|
+
|
|
98442
|
+
// src/cli/decide.ts
|
|
98443
|
+
var DEFAULT_OUT = "decide-results.jsonl";
|
|
98444
|
+
var MAX_ITEMS_PER_REQUEST = 200;
|
|
98445
|
+
var MAX_REQUEST_BYTES = 6 * 1024 * 1024;
|
|
98446
|
+
var DEFAULT_CONCURRENCY = 4;
|
|
98447
|
+
var MAX_CONCURRENCY = 16;
|
|
98448
|
+
var SUMMARY_UNCERTAIN_IDS = 20;
|
|
98449
|
+
var SUMMARY_FAILED = 10;
|
|
98450
|
+
var STOP_STATUSES = new Set([401, 402, 403, 404]);
|
|
98451
|
+
var OPTIONS = [
|
|
98452
|
+
{ key: "questions", names: ["--questions", "-q"], kind: "value" },
|
|
98453
|
+
{ key: "items", names: ["--items"], kind: "value", multiple: true },
|
|
98454
|
+
{ key: "jsonl", names: ["--jsonl"], kind: "value", multiple: true },
|
|
98455
|
+
{ key: "csv", names: ["--csv"], kind: "value", multiple: true },
|
|
98456
|
+
{ key: "idField", names: ["--id-field"], kind: "value" },
|
|
98457
|
+
{ key: "textField", names: ["--text-field"], kind: "value", multiple: true },
|
|
98458
|
+
{ key: "model", names: ["--model"], kind: "value" },
|
|
98459
|
+
{ key: "minConfidence", names: ["--min-confidence"], kind: "value" },
|
|
98460
|
+
{ key: "out", names: ["--out", "-o"], kind: "value" },
|
|
98461
|
+
{ key: "resume", names: ["--resume"], kind: "boolean" },
|
|
98462
|
+
{ key: "overwrite", names: ["--overwrite"], kind: "boolean" },
|
|
98463
|
+
{ key: "selectFrom", names: ["--select-from"], kind: "value" },
|
|
98464
|
+
{ key: "where", names: ["--where"], kind: "value" },
|
|
98465
|
+
{ key: "agent", names: ["--agent"], kind: "value" },
|
|
98466
|
+
{ key: "concurrency", names: ["--concurrency"], kind: "value" },
|
|
98467
|
+
{ key: "help", names: ["--help", "-h"], kind: "boolean" }
|
|
98468
|
+
];
|
|
98469
|
+
var DECIDE_USAGE = `Usage: brainbase decide --questions <file.json> <sources...> [options]
|
|
98470
|
+
|
|
98471
|
+
Answer the same decision-model questions over many items. Items are read on
|
|
98472
|
+
this machine and never pass through your agent's context.
|
|
98473
|
+
|
|
98474
|
+
Sources (at least one):
|
|
98475
|
+
<path>... files, or directories (every file under them)
|
|
98476
|
+
--items <glob> files matching a glob; quote it ('docs/**/*.md')
|
|
98477
|
+
--jsonl <file> one item per line
|
|
98478
|
+
--csv <file> one item per row; the first row names the fields
|
|
98479
|
+
--id-field <name> JSONL/CSV field holding each item's id
|
|
98480
|
+
(default: id when present, else file:line)
|
|
98481
|
+
--text-field <name> field to judge; repeat for several (a row
|
|
98482
|
+
missing any of them fails without being sent)
|
|
98483
|
+
(default: the whole row)
|
|
98484
|
+
|
|
98485
|
+
Questions:
|
|
98486
|
+
--questions, -q <file> JSON object of System One questions, e.g.
|
|
98487
|
+
{"team": {"type": "choice", "instructions": "Which team?",
|
|
98488
|
+
"criteria": {"billing": "...", "infra": "..."}}}
|
|
98489
|
+
--model <slug> jev, kev-4b, clef, clef-flash or gpt-6-luna
|
|
98490
|
+
(default: the server's default)
|
|
98491
|
+
--min-confidence <0-1> mark answers below this confidence as uncertain
|
|
98492
|
+
|
|
98493
|
+
Results:
|
|
98494
|
+
--out, -o <file> one JSON line per item (default: ${DEFAULT_OUT})
|
|
98495
|
+
--resume skip ids already answered in --out; append the rest
|
|
98496
|
+
--overwrite replace an existing --out
|
|
98497
|
+
--select-from <file> only items whose row in this earlier results file
|
|
98498
|
+
--where <filter> matches: failed, uncertain or <question>=<answer>
|
|
98499
|
+
|
|
98500
|
+
Other:
|
|
98501
|
+
--agent <id> agent to bill outside a Brainbase task
|
|
98502
|
+
(default: this folder's linked agent)
|
|
98503
|
+
--concurrency <n> requests in flight, 1-${MAX_CONCURRENCY} (default: ${DEFAULT_CONCURRENCY})
|
|
98504
|
+
|
|
98505
|
+
Prints one JSON summary on stdout. Exits 0 when every item was sent (check
|
|
98506
|
+
counts.failed), 1 when the run stopped early (rerun with --resume), 2 for a
|
|
98507
|
+
usage error.
|
|
98508
|
+
`;
|
|
98509
|
+
function usageError2(stderr, message3) {
|
|
98510
|
+
stderr(`brainbase decide: ${message3}
|
|
98511
|
+
Run \`brainbase decide --help\` for usage.
|
|
98512
|
+
`);
|
|
98513
|
+
return 2;
|
|
98514
|
+
}
|
|
98515
|
+
function readQuestions(cwd2, file) {
|
|
98516
|
+
let parsed;
|
|
98517
|
+
try {
|
|
98518
|
+
parsed = JSON.parse(fs95.readFileSync(path107.resolve(cwd2, file), "utf8"));
|
|
98519
|
+
} catch (error2) {
|
|
98520
|
+
throw new DecideInputError(`Could not read questions from ${file}: ${error2.message}`);
|
|
98521
|
+
}
|
|
98522
|
+
if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed) || !Object.keys(parsed).length) {
|
|
98523
|
+
throw new DecideInputError(`${file} must hold a JSON object of questions`);
|
|
98524
|
+
}
|
|
98525
|
+
return parsed;
|
|
98526
|
+
}
|
|
98527
|
+
function mergeSets(sets) {
|
|
98528
|
+
const merged = { items: [], failures: [] };
|
|
98529
|
+
for (const set3 of sets) {
|
|
98530
|
+
appendAll(merged.items, set3.items);
|
|
98531
|
+
appendAll(merged.failures, set3.failures);
|
|
98532
|
+
}
|
|
98533
|
+
const seen = new Set;
|
|
98534
|
+
for (const { id } of [...merged.items, ...merged.failures]) {
|
|
98535
|
+
if (seen.has(id)) {
|
|
98536
|
+
throw new DecideInputError(`Two items share the id ${JSON.stringify(id)}; pass --id-field naming a unique field`);
|
|
98537
|
+
}
|
|
98538
|
+
seen.add(id);
|
|
98539
|
+
}
|
|
98540
|
+
return merged;
|
|
98541
|
+
}
|
|
98542
|
+
function chunk2(items, failures) {
|
|
98543
|
+
const chunks = [];
|
|
98544
|
+
let current = [];
|
|
98545
|
+
let bytes = 0;
|
|
98546
|
+
for (const item of items) {
|
|
98547
|
+
const size2 = Buffer.byteLength(JSON.stringify(item));
|
|
98548
|
+
if (size2 > MAX_REQUEST_BYTES) {
|
|
98549
|
+
failures.push({ id: item.id, error: "Larger than one request can carry (6 MB)" });
|
|
98550
|
+
continue;
|
|
98551
|
+
}
|
|
98552
|
+
if (current.length === MAX_ITEMS_PER_REQUEST || bytes + size2 > MAX_REQUEST_BYTES) {
|
|
98553
|
+
chunks.push(current);
|
|
98554
|
+
current = [];
|
|
98555
|
+
bytes = 0;
|
|
98556
|
+
}
|
|
98557
|
+
current.push(item);
|
|
98558
|
+
bytes += size2;
|
|
98559
|
+
}
|
|
98560
|
+
if (current.length)
|
|
98561
|
+
chunks.push(current);
|
|
98562
|
+
return chunks;
|
|
98563
|
+
}
|
|
98564
|
+
|
|
98565
|
+
class Tally {
|
|
98566
|
+
done = 0;
|
|
98567
|
+
uncertainIds = [];
|
|
98568
|
+
failed = [];
|
|
98569
|
+
answers = {};
|
|
98570
|
+
credits = 0;
|
|
98571
|
+
model = null;
|
|
98572
|
+
addRow(row) {
|
|
98573
|
+
if (row.error !== undefined) {
|
|
98574
|
+
this.failed.push({ id: row.id, reason: row.error });
|
|
98575
|
+
return;
|
|
98576
|
+
}
|
|
98577
|
+
this.done += 1;
|
|
98578
|
+
if (row.uncertain)
|
|
98579
|
+
this.uncertainIds.push(row.id);
|
|
98580
|
+
}
|
|
98581
|
+
addResponse(response) {
|
|
98582
|
+
this.model ??= response.model;
|
|
98583
|
+
this.credits += response.credits;
|
|
98584
|
+
for (const [question, counts] of Object.entries(response.answers)) {
|
|
98585
|
+
const into = this.answers[question] ??= {};
|
|
98586
|
+
for (const [answer, count] of Object.entries(counts)) {
|
|
98587
|
+
into[answer] = (into[answer] ?? 0) + count;
|
|
98588
|
+
}
|
|
98589
|
+
}
|
|
98590
|
+
}
|
|
98591
|
+
}
|
|
98592
|
+
async function runDecide(cwd2, argv, deps = {}) {
|
|
98593
|
+
const stdout = deps.stdout ?? ((text4) => void process.stdout.write(text4));
|
|
98594
|
+
const stderr = deps.stderr ?? ((text4) => void process.stderr.write(text4));
|
|
98595
|
+
const started = Date.now();
|
|
98596
|
+
let parsed;
|
|
98597
|
+
try {
|
|
98598
|
+
parsed = parseArgv(argv, OPTIONS);
|
|
98599
|
+
} catch (error2) {
|
|
98600
|
+
if (error2 instanceof ArgvParseError)
|
|
98601
|
+
return usageError2(stderr, error2.message);
|
|
98602
|
+
throw error2;
|
|
98603
|
+
}
|
|
98604
|
+
if (booleanOption(parsed, "help")) {
|
|
98605
|
+
stdout(DECIDE_USAGE);
|
|
98606
|
+
return 0;
|
|
98607
|
+
}
|
|
98608
|
+
const questionsFile = stringOption(parsed, "questions");
|
|
98609
|
+
if (!questionsFile)
|
|
98610
|
+
return usageError2(stderr, "--questions <file.json> is required");
|
|
98611
|
+
const paths = parsed.positionals;
|
|
98612
|
+
const globs = stringOptions(parsed, "items");
|
|
98613
|
+
const jsonlFiles = stringOptions(parsed, "jsonl");
|
|
98614
|
+
const csvFiles = stringOptions(parsed, "csv");
|
|
98615
|
+
if (!paths.length && !globs.length && !jsonlFiles.length && !csvFiles.length) {
|
|
98616
|
+
return usageError2(stderr, "name at least one source: paths, --items, --jsonl or --csv");
|
|
98617
|
+
}
|
|
98618
|
+
const minConfidenceRaw = stringOption(parsed, "minConfidence");
|
|
98619
|
+
const minConfidence = minConfidenceRaw === undefined ? undefined : Number(minConfidenceRaw);
|
|
98620
|
+
if (minConfidence !== undefined && !(minConfidence >= 0 && minConfidence <= 1)) {
|
|
98621
|
+
return usageError2(stderr, "--min-confidence takes a number from 0 to 1");
|
|
98622
|
+
}
|
|
98623
|
+
const concurrencyRaw = stringOption(parsed, "concurrency");
|
|
98624
|
+
const concurrency = concurrencyRaw === undefined ? DEFAULT_CONCURRENCY : Number(concurrencyRaw);
|
|
98625
|
+
if (!Number.isInteger(concurrency) || concurrency < 1 || concurrency > MAX_CONCURRENCY) {
|
|
98626
|
+
return usageError2(stderr, `--concurrency takes a whole number from 1 to ${MAX_CONCURRENCY}`);
|
|
98627
|
+
}
|
|
98628
|
+
const selectFrom = stringOption(parsed, "selectFrom");
|
|
98629
|
+
const whereRaw = stringOption(parsed, "where");
|
|
98630
|
+
if (Boolean(selectFrom) !== Boolean(whereRaw)) {
|
|
98631
|
+
return usageError2(stderr, "--select-from and --where go together");
|
|
98632
|
+
}
|
|
98633
|
+
const resume = booleanOption(parsed, "resume");
|
|
98634
|
+
const overwrite = booleanOption(parsed, "overwrite");
|
|
98635
|
+
if (resume && overwrite)
|
|
98636
|
+
return usageError2(stderr, "--resume and --overwrite cannot be combined");
|
|
98637
|
+
const outArg = stringOption(parsed, "out") ?? DEFAULT_OUT;
|
|
98638
|
+
const outPath = path107.resolve(cwd2, outArg);
|
|
98639
|
+
let questions;
|
|
98640
|
+
let set3;
|
|
98641
|
+
let skipped = 0;
|
|
98642
|
+
try {
|
|
98643
|
+
questions = readQuestions(cwd2, questionsFile);
|
|
98644
|
+
const rowOptions = {
|
|
98645
|
+
idField: stringOption(parsed, "idField"),
|
|
98646
|
+
textFields: stringOptions(parsed, "textField")
|
|
98647
|
+
};
|
|
98648
|
+
set3 = mergeSets([
|
|
98649
|
+
readFileItems(cwd2, fileItems(cwd2, paths, globs)),
|
|
98650
|
+
...jsonlFiles.map((file) => jsonlItems(cwd2, file, rowOptions)),
|
|
98651
|
+
...csvFiles.map((file) => csvItems(cwd2, file, rowOptions))
|
|
98652
|
+
]);
|
|
98653
|
+
if (selectFrom && whereRaw) {
|
|
98654
|
+
const where = parseWhere(whereRaw);
|
|
98655
|
+
const earlier = path107.resolve(cwd2, selectFrom);
|
|
98656
|
+
if (!fs95.existsSync(earlier))
|
|
98657
|
+
throw new DecideInputError(`No such results file: ${selectFrom}`);
|
|
98658
|
+
const rows = readResults(earlier);
|
|
98659
|
+
const keep = (id) => {
|
|
98660
|
+
const row = rows.get(id);
|
|
98661
|
+
return row !== undefined && rowMatches(row, where);
|
|
98662
|
+
};
|
|
98663
|
+
set3 = { items: set3.items.filter((item) => keep(item.id)), failures: set3.failures.filter((f4) => keep(f4.id)) };
|
|
98664
|
+
}
|
|
98665
|
+
const outHasRows = fs95.existsSync(outPath) && fs95.statSync(outPath).size > 0;
|
|
98666
|
+
if (outHasRows && !resume && !overwrite) {
|
|
98667
|
+
throw new DecideInputError(`${outArg} already has results; pass --resume to continue it or --overwrite to replace it`);
|
|
98668
|
+
}
|
|
98669
|
+
if (resume) {
|
|
98670
|
+
const answered = new Set([...readResults(outPath).values()].filter((row) => row.error === undefined).map((row) => row.id));
|
|
98671
|
+
const before2 = set3.items.length + set3.failures.length;
|
|
98672
|
+
set3 = {
|
|
98673
|
+
items: set3.items.filter((item) => !answered.has(item.id)),
|
|
98674
|
+
failures: set3.failures.filter((failure) => !answered.has(failure.id))
|
|
98675
|
+
};
|
|
98676
|
+
skipped = before2 - set3.items.length - set3.failures.length;
|
|
98677
|
+
}
|
|
98678
|
+
} catch (error2) {
|
|
98679
|
+
if (error2 instanceof DecideInputError)
|
|
98680
|
+
return usageError2(stderr, error2.message);
|
|
98681
|
+
throw error2;
|
|
98682
|
+
}
|
|
98683
|
+
fs95.mkdirSync(path107.dirname(outPath), { recursive: true });
|
|
98684
|
+
if (resume)
|
|
98685
|
+
repairResultsTail(outPath);
|
|
98686
|
+
else
|
|
98687
|
+
fs95.writeFileSync(outPath, "");
|
|
98688
|
+
const append = (rows) => {
|
|
98689
|
+
if (rows.length)
|
|
98690
|
+
fs95.appendFileSync(outPath, rows.map((row) => JSON.stringify(row)).join(`
|
|
98691
|
+
`) + `
|
|
98692
|
+
`);
|
|
98693
|
+
};
|
|
98694
|
+
const tally = new Tally;
|
|
98695
|
+
const localFailures = [...set3.failures];
|
|
98696
|
+
const chunks = chunk2(set3.items, localFailures);
|
|
98697
|
+
const localRows = localFailures.map((failure) => ({ id: failure.id, error: failure.error }));
|
|
98698
|
+
append(localRows);
|
|
98699
|
+
localRows.forEach((row) => tally.addRow(row));
|
|
98700
|
+
const total = set3.items.length + set3.failures.length;
|
|
98701
|
+
let stopError;
|
|
98702
|
+
let unsent = 0;
|
|
98703
|
+
let next = 0;
|
|
98704
|
+
if (chunks.length) {
|
|
98705
|
+
let credential;
|
|
98706
|
+
try {
|
|
98707
|
+
credential = await resolveDecideCredential(cwd2, stringOption(parsed, "agent"));
|
|
98708
|
+
} catch (error2) {
|
|
98709
|
+
stopError = error2.message;
|
|
98710
|
+
}
|
|
98711
|
+
if (credential) {
|
|
98712
|
+
const modelFlag = stringOption(parsed, "model");
|
|
98713
|
+
const body = (items) => ({
|
|
98714
|
+
questions,
|
|
98715
|
+
items,
|
|
98716
|
+
...modelFlag ? { model: modelFlag } : {},
|
|
98717
|
+
...minConfidence !== undefined ? { min_confidence: minConfidence } : {},
|
|
98718
|
+
output: "full"
|
|
98719
|
+
});
|
|
98720
|
+
const progress2 = process.stderr.isTTY && !deps.stderr;
|
|
98721
|
+
let answeredSoFar = localRows.length;
|
|
98722
|
+
let replacement;
|
|
98723
|
+
const send = async (items) => {
|
|
98724
|
+
const used = credential;
|
|
98725
|
+
try {
|
|
98726
|
+
return await postDecide(used, body(items), deps);
|
|
98727
|
+
} catch (error2) {
|
|
98728
|
+
if (!(error2 instanceof DecideHttpError && error2.status === 401 && used.source === "agent_key")) {
|
|
98729
|
+
throw error2;
|
|
98730
|
+
}
|
|
98731
|
+
replacement ??= replaceAgentKey(used).then((fresh2) => credential = fresh2);
|
|
98732
|
+
const fresh = await replacement;
|
|
98733
|
+
if (fresh.key === used.key)
|
|
98734
|
+
throw error2;
|
|
98735
|
+
return postDecide(fresh, body(items), deps);
|
|
98736
|
+
}
|
|
98737
|
+
};
|
|
98738
|
+
const worker = async () => {
|
|
98739
|
+
while (next < chunks.length && stopError === undefined) {
|
|
98740
|
+
const items = chunks[next++];
|
|
98741
|
+
let rows;
|
|
98742
|
+
try {
|
|
98743
|
+
const response = await send(items);
|
|
98744
|
+
tally.addResponse(response);
|
|
98745
|
+
rows = response.rows;
|
|
98746
|
+
} catch (error2) {
|
|
98747
|
+
const message3 = error2.message;
|
|
98748
|
+
const refusal = error2 instanceof DecideHttpError;
|
|
98749
|
+
if (!refusal || error2.status !== null && STOP_STATUSES.has(error2.status)) {
|
|
98750
|
+
stopError ??= refusal && error2.status === 404 ? `/v1/decide is not available on ${credential.base} (${message3})` : message3;
|
|
98751
|
+
unsent += items.length;
|
|
98752
|
+
continue;
|
|
98753
|
+
}
|
|
98754
|
+
rows = items.map((item) => ({ id: item.id, error: `Request failed: ${message3}` }));
|
|
98755
|
+
}
|
|
98756
|
+
append(rows);
|
|
98757
|
+
rows.forEach((row) => tally.addRow(row));
|
|
98758
|
+
answeredSoFar += rows.length;
|
|
98759
|
+
if (progress2)
|
|
98760
|
+
process.stderr.write(`\rdecided ${answeredSoFar}/${total}`);
|
|
98761
|
+
}
|
|
98762
|
+
};
|
|
98763
|
+
await Promise.all(Array.from({ length: Math.min(concurrency, chunks.length) }, worker));
|
|
98764
|
+
if (progress2)
|
|
98765
|
+
process.stderr.write(`
|
|
98766
|
+
`);
|
|
98767
|
+
}
|
|
98768
|
+
unsent += chunks.slice(next).reduce((count, items) => count + items.length, 0);
|
|
98769
|
+
}
|
|
98770
|
+
const summary = {
|
|
98771
|
+
status: stopError === undefined ? "done" : "stopped",
|
|
98772
|
+
model: tally.model ?? stringOption(parsed, "model") ?? null,
|
|
98773
|
+
counts: {
|
|
98774
|
+
total,
|
|
98775
|
+
done: tally.done,
|
|
98776
|
+
uncertain: tally.uncertainIds.length,
|
|
98777
|
+
failed: tally.failed.length,
|
|
98778
|
+
skipped,
|
|
98779
|
+
unsent
|
|
98780
|
+
},
|
|
98781
|
+
answers: tally.answers,
|
|
98782
|
+
uncertain_ids: tally.uncertainIds.slice(0, SUMMARY_UNCERTAIN_IDS),
|
|
98783
|
+
failed: tally.failed.slice(0, SUMMARY_FAILED),
|
|
98784
|
+
credits: tally.credits,
|
|
98785
|
+
elapsed_ms: Date.now() - started,
|
|
98786
|
+
out: path107.relative(cwd2, outPath) || outArg,
|
|
98787
|
+
...stopError !== undefined ? { error: `${stopError}. Answers so far are in ${outArg}; rerun with --resume to continue.` } : {}
|
|
98788
|
+
};
|
|
98789
|
+
stdout(JSON.stringify(summary, null, 2) + `
|
|
98790
|
+
`);
|
|
98791
|
+
return stopError === undefined ? 0 : 1;
|
|
98792
|
+
}
|
|
98793
|
+
|
|
97218
98794
|
// src/ui/console-streams.ts
|
|
97219
98795
|
import { format as format3 } from "node:util";
|
|
97220
98796
|
function routeConsoleThroughStreams() {
|
|
@@ -97272,6 +98848,7 @@ var COMMANDS3 = [
|
|
|
97272
98848
|
"status",
|
|
97273
98849
|
"mcp",
|
|
97274
98850
|
"integrations",
|
|
98851
|
+
"decide",
|
|
97275
98852
|
"run",
|
|
97276
98853
|
"help",
|
|
97277
98854
|
"version"
|
|
@@ -97282,208 +98859,217 @@ var SUBCOMMAND_OWNED_FLAGS = {
|
|
|
97282
98859
|
function help() {
|
|
97283
98860
|
const out = [];
|
|
97284
98861
|
out.push("");
|
|
97285
|
-
out.push(` ${brandTint("◆")} ${
|
|
97286
|
-
out.push(` ${
|
|
98862
|
+
out.push(` ${brandTint("◆")} ${import_picocolors81.default.bold("brainbase")} ${import_picocolors81.default.dim(`v${VERSION}`)}`);
|
|
98863
|
+
out.push(` ${import_picocolors81.default.dim("connect your local agent to the brainbase platform")}`);
|
|
97287
98864
|
out.push("");
|
|
97288
98865
|
out.push(divider("USAGE"));
|
|
97289
98866
|
out.push("");
|
|
97290
|
-
out.push(` ${
|
|
98867
|
+
out.push(` ${import_picocolors81.default.bold("brainbase")} ${import_picocolors81.default.dim("<command> [options]")}`);
|
|
97291
98868
|
out.push("");
|
|
97292
98869
|
out.push(divider("AUTH"));
|
|
97293
98870
|
out.push("");
|
|
97294
|
-
out.push(` ${
|
|
97295
|
-
out.push(` ${
|
|
97296
|
-
out.push(` ${
|
|
98871
|
+
out.push(` ${import_picocolors81.default.cyan("login")} ${import_picocolors81.default.dim(" open the web app and connect this device")}`);
|
|
98872
|
+
out.push(` ${import_picocolors81.default.cyan("logout")} ${import_picocolors81.default.dim(" clear the local session")}`);
|
|
98873
|
+
out.push(` ${import_picocolors81.default.cyan("whoami")} ${import_picocolors81.default.dim("[--json]")} ${import_picocolors81.default.dim(" show which credential is in use and what it covers")}`);
|
|
97297
98874
|
out.push("");
|
|
97298
98875
|
out.push(divider("DISCOVERY"));
|
|
97299
98876
|
out.push("");
|
|
97300
|
-
out.push(` ${
|
|
97301
|
-
out.push(` ${
|
|
97302
|
-
out.push(` ${
|
|
98877
|
+
out.push(` ${import_picocolors81.default.cyan("team list")} ${import_picocolors81.default.dim("show the teams you can create agents in")}`);
|
|
98878
|
+
out.push(` ${import_picocolors81.default.cyan("member ls")} ${import_picocolors81.default.dim("show the people in an organization, with the emails interface access takes")}`);
|
|
98879
|
+
out.push(` ${import_picocolors81.default.cyan("agent list")} ${import_picocolors81.default.dim("show a team's agents and their ids")}`);
|
|
97303
98880
|
out.push("");
|
|
97304
98881
|
out.push(divider("LINKED AGENT"));
|
|
97305
98882
|
out.push("");
|
|
97306
|
-
out.push(` ${
|
|
97307
|
-
out.push(` ${
|
|
97308
|
-
out.push(` ${
|
|
97309
|
-
out.push(` ${
|
|
97310
|
-
out.push(` ${
|
|
97311
|
-
out.push(` ${
|
|
97312
|
-
out.push(` ${
|
|
97313
|
-
out.push(` ${
|
|
97314
|
-
out.push(` ${
|
|
97315
|
-
out.push(` ${
|
|
97316
|
-
out.push(` ${
|
|
97317
|
-
out.push(` ${
|
|
97318
|
-
out.push(` ${
|
|
97319
|
-
out.push(` ${
|
|
97320
|
-
out.push(` ${
|
|
97321
|
-
out.push(` ${
|
|
97322
|
-
out.push(` ${
|
|
97323
|
-
out.push(` ${
|
|
98883
|
+
out.push(` ${import_picocolors81.default.cyan("agent init")} ${import_picocolors81.default.dim("write a starter brainbase.agent.yaml here — offline, no login needed")}`);
|
|
98884
|
+
out.push(` ${import_picocolors81.default.cyan("agent create")} ${import_picocolors81.default.dim("claim an unclaimed brainbase.agent.yaml and create the cloud agent")}`);
|
|
98885
|
+
out.push(` ${import_picocolors81.default.cyan("agent pull")} ${import_picocolors81.default.dim("[<id>]")} ${import_picocolors81.default.dim("bring cloud changes into this folder (--force to override; --run-entrypoint to also execute the agent entrypoint; --link to link first)")}`);
|
|
98886
|
+
out.push(` ${import_picocolors81.default.cyan("agent push")} ${import_picocolors81.default.dim("send local changes to the cloud (--force to overwrite cloud-side conflicts with local)")}`);
|
|
98887
|
+
out.push(` ${import_picocolors81.default.cyan("agent delete")} ${import_picocolors81.default.dim("<id>")} ${import_picocolors81.default.dim("permanently delete a cloud agent and every task it has run")}`);
|
|
98888
|
+
out.push(` ${import_picocolors81.default.cyan("agent unpack")} ${import_picocolors81.default.dim("install the claimed agent into a harness layout")}`);
|
|
98889
|
+
out.push(` ${import_picocolors81.default.cyan("link")} ${import_picocolors81.default.dim("attach this folder to an existing agent")}`);
|
|
98890
|
+
out.push(` ${import_picocolors81.default.cyan("agent status")} ${import_picocolors81.default.dim("show what would pull and what would push")}`);
|
|
98891
|
+
out.push(` ${import_picocolors81.default.cyan("agent connections")} ${import_picocolors81.default.dim("show which integrations this agent is wired to (--json for CI)")}`);
|
|
98892
|
+
out.push(` ${import_picocolors81.default.cyan("agent connect")} ${import_picocolors81.default.dim("<name>")} ${import_picocolors81.default.dim("connect chat, slack, meeting, github, linear or phone")}`);
|
|
98893
|
+
out.push(` ${import_picocolors81.default.cyan("agent disconnect")} ${import_picocolors81.default.dim("<name>")} ${import_picocolors81.default.dim("disable or disconnect an agent surface")}`);
|
|
98894
|
+
out.push(` ${import_picocolors81.default.cyan("agent surface")} ${import_picocolors81.default.dim("<name>")} ${import_picocolors81.default.dim("status, settings and setup for all six surfaces (--help)")}`);
|
|
98895
|
+
out.push(` ${import_picocolors81.default.cyan("agent versions")} ${import_picocolors81.default.dim("saved versions: list, show, diff, label, restore, pin and unpin (`agent versions --help`)")}`);
|
|
98896
|
+
out.push(` ${import_picocolors81.default.cyan("agent eval")} ${import_picocolors81.default.dim("<list|runs>")} ${import_picocolors81.default.dim("read eval definitions and judge verdicts (`agent eval --help`)")}`);
|
|
98897
|
+
out.push(` ${import_picocolors81.default.cyan("agent env")} ${import_picocolors81.default.dim("print export lines for `eval $(brainbase agent env)`")}`);
|
|
98898
|
+
out.push(` ${import_picocolors81.default.cyan("run")} ${import_picocolors81.default.dim("<cmd> [args...]")} ${import_picocolors81.default.dim("run <cmd> with secrets.env loaded into env")}`);
|
|
98899
|
+
out.push(` ${import_picocolors81.default.cyan("status")} ${import_picocolors81.default.dim("show what this folder is linked to")}`);
|
|
98900
|
+
out.push(` ${import_picocolors81.default.cyan("unlink")} ${import_picocolors81.default.dim("disconnect this folder")}`);
|
|
97324
98901
|
out.push("");
|
|
97325
98902
|
out.push(divider("TASKS"));
|
|
97326
98903
|
out.push("");
|
|
97327
|
-
out.push(` ${
|
|
97328
|
-
out.push(` ${
|
|
97329
|
-
out.push(` ${
|
|
97330
|
-
out.push(` ${
|
|
97331
|
-
out.push(` ${
|
|
97332
|
-
out.push(` ${
|
|
97333
|
-
out.push(` ${
|
|
97334
|
-
out.push(` ${
|
|
98904
|
+
out.push(` ${import_picocolors81.default.cyan("task create")} ${import_picocolors81.default.dim("--message <text>")} ${import_picocolors81.default.dim("create a managed task and start its first run (--wait to block on it; --interface <id> for a build conversation)")}`);
|
|
98905
|
+
out.push(` ${import_picocolors81.default.cyan("task list")} ${import_picocolors81.default.dim("recent tasks you can reach (--metadata k=v to filter by label; --interface <id> for its build conversations)")}`);
|
|
98906
|
+
out.push(` ${import_picocolors81.default.cyan("task get")} ${import_picocolors81.default.dim("<task-id>")} ${import_picocolors81.default.dim("one task: status, agent, machine, eval verdicts")}`);
|
|
98907
|
+
out.push(` ${import_picocolors81.default.cyan("task logs")} ${import_picocolors81.default.dim("<task-id> [--follow]")} ${import_picocolors81.default.dim("one line per event in the task's transcript, or tail it live")}`);
|
|
98908
|
+
out.push(` ${import_picocolors81.default.cyan("task send")} ${import_picocolors81.default.dim("<task-id> <message>")} ${import_picocolors81.default.dim("send a follow-up during execution, or queue it for the next turn")}`);
|
|
98909
|
+
out.push(` ${import_picocolors81.default.cyan("task stop")} ${import_picocolors81.default.dim("<task-id>")} ${import_picocolors81.default.dim("stop execution and cancel pending follow-ups, retaining their text")}`);
|
|
98910
|
+
out.push(` ${import_picocolors81.default.cyan("task update")} ${import_picocolors81.default.dim("<task-id>")} ${import_picocolors81.default.dim("rename a task, change its metadata labels, switch its model or reset it to the agent default, including while it runs")}`);
|
|
98911
|
+
out.push(` ${import_picocolors81.default.cyan("task delete")} ${import_picocolors81.default.dim("<task-id>")} ${import_picocolors81.default.dim("permanently delete a stopped task and tear down its sandbox")}`);
|
|
97335
98912
|
out.push("");
|
|
97336
98913
|
out.push(divider("INTERFACES"));
|
|
97337
98914
|
out.push("");
|
|
97338
|
-
out.push(` ${
|
|
97339
|
-
out.push(` ${
|
|
97340
|
-
out.push(` ${
|
|
97341
|
-
out.push(` ${
|
|
97342
|
-
out.push(` ${
|
|
97343
|
-
out.push(` ${
|
|
97344
|
-
out.push(` ${
|
|
98915
|
+
out.push(` ${import_picocolors81.default.cyan("interface ls")} ${import_picocolors81.default.dim("dashboards you can see (--agent to narrow)")}`);
|
|
98916
|
+
out.push(` ${import_picocolors81.default.cyan("interface create")} ${import_picocolors81.default.dim("--name <n>")} ${import_picocolors81.default.dim("create one on an agent, with who can open it")}`);
|
|
98917
|
+
out.push(` ${import_picocolors81.default.cyan("interface build")} ${import_picocolors81.default.dim('<id> "<ask>"')} ${import_picocolors81.default.dim("describe a change; the agent builds it while you watch")}`);
|
|
98918
|
+
out.push(` ${import_picocolors81.default.cyan("interface publish")} ${import_picocolors81.default.dim("<id>")} ${import_picocolors81.default.dim("make the newest succeeded build live")}`);
|
|
98919
|
+
out.push(` ${import_picocolors81.default.cyan("interface rollback")} ${import_picocolors81.default.dim("<id>")} ${import_picocolors81.default.dim("republish an earlier release under a new id (--release <id>)")}`);
|
|
98920
|
+
out.push(` ${import_picocolors81.default.cyan("interface access")} ${import_picocolors81.default.dim("<id>")} ${import_picocolors81.default.dim("show or set who can open it")}`);
|
|
98921
|
+
out.push(` ${import_picocolors81.default.cyan("interface --help")} ${import_picocolors81.default.dim("every interface subcommand")}`);
|
|
97345
98922
|
out.push("");
|
|
97346
98923
|
out.push(divider("SANDBOXES"));
|
|
97347
98924
|
out.push("");
|
|
97348
|
-
out.push(` ${
|
|
97349
|
-
out.push(` ${
|
|
98925
|
+
out.push(` ${import_picocolors81.default.cyan("machine ls")} ${import_picocolors81.default.dim("[--all]")} ${import_picocolors81.default.dim("list your sandboxes — live ones only unless --all")}`);
|
|
98926
|
+
out.push(` ${import_picocolors81.default.cyan("machine rm")} ${import_picocolors81.default.dim("<id>")} ${import_picocolors81.default.dim("tear a sandbox down (it bills until you do)")}`);
|
|
97350
98927
|
out.push("");
|
|
97351
98928
|
out.push(divider("BENCHMARKS"));
|
|
97352
98929
|
out.push("");
|
|
97353
|
-
out.push(` ${
|
|
97354
|
-
out.push(` ${
|
|
97355
|
-
out.push(` ${
|
|
97356
|
-
out.push(` ${
|
|
97357
|
-
out.push(` ${
|
|
98930
|
+
out.push(` ${import_picocolors81.default.cyan("benchmark list")} ${import_picocolors81.default.dim("list benchmarks for the linked agent")}`);
|
|
98931
|
+
out.push(` ${import_picocolors81.default.cyan("benchmark init")} ${import_picocolors81.default.dim("[directory]")} ${import_picocolors81.default.dim("scaffold a local benchmark")}`);
|
|
98932
|
+
out.push(` ${import_picocolors81.default.cyan("benchmark create")} ${import_picocolors81.default.dim("[path|-]")} ${import_picocolors81.default.dim("create a benchmark draft")}`);
|
|
98933
|
+
out.push(` ${import_picocolors81.default.cyan("benchmark run")} ${import_picocolors81.default.dim("<benchmark> --yes")} ${import_picocolors81.default.dim("plan and start a benchmark run")}`);
|
|
98934
|
+
out.push(` ${import_picocolors81.default.cyan("benchmark results")} ${import_picocolors81.default.dim("<run>")} ${import_picocolors81.default.dim("inspect normalized benchmark results")}`);
|
|
97358
98935
|
out.push("");
|
|
97359
98936
|
out.push(divider("BENCHMARK RUNTIME"));
|
|
97360
98937
|
out.push("");
|
|
97361
|
-
out.push(` ${
|
|
97362
|
-
out.push(` ${
|
|
97363
|
-
out.push(` ${
|
|
98938
|
+
out.push(` ${import_picocolors81.default.cyan("benchmark hydrate")} ${import_picocolors81.default.dim("--spec <path> --result <path> --json")}`);
|
|
98939
|
+
out.push(` ${import_picocolors81.default.cyan("benchmark evaluate")} ${import_picocolors81.default.dim("--spec <path> --result <path> --json")}`);
|
|
98940
|
+
out.push(` ${import_picocolors81.default.cyan("benchmark capabilities")} ${import_picocolors81.default.dim("--json")}`);
|
|
97364
98941
|
out.push("");
|
|
97365
98942
|
out.push(divider("ORCHESTRATIONS"));
|
|
97366
98943
|
out.push("");
|
|
97367
|
-
out.push(` ${
|
|
97368
|
-
out.push(` ${
|
|
97369
|
-
out.push(` ${
|
|
97370
|
-
out.push(` ${
|
|
97371
|
-
out.push(` ${
|
|
97372
|
-
out.push(` ${
|
|
97373
|
-
out.push(` ${
|
|
98944
|
+
out.push(` ${import_picocolors81.default.cyan("orchestration init")} ${import_picocolors81.default.dim("write a starter brainbase-orchestration.yaml here (offline, no login)")}`);
|
|
98945
|
+
out.push(` ${import_picocolors81.default.cyan("orchestration create")} ${import_picocolors81.default.dim("claim a local orchestration manifest and create it in the cloud")}`);
|
|
98946
|
+
out.push(` ${import_picocolors81.default.cyan("orchestration list")} ${import_picocolors81.default.dim("list orchestrations under a team")}`);
|
|
98947
|
+
out.push(` ${import_picocolors81.default.cyan("orchestration pull")} ${import_picocolors81.default.dim("<id>")} ${import_picocolors81.default.dim("recursively fetch an orchestration + every member agent")}`);
|
|
98948
|
+
out.push(` ${import_picocolors81.default.cyan("orchestration push")} ${import_picocolors81.default.dim("recursively push each member, then update the graph")}`);
|
|
98949
|
+
out.push(` ${import_picocolors81.default.cyan("orchestration status")} ${import_picocolors81.default.dim("show what would push and what would pull")}`);
|
|
98950
|
+
out.push(` ${import_picocolors81.default.cyan("orchestration delete")} ${import_picocolors81.default.dim("<id>")} ${import_picocolors81.default.dim("permanently delete an orchestration graph (member agents are kept)")}`);
|
|
97374
98951
|
out.push("");
|
|
97375
98952
|
out.push(divider("TEMPLATES"));
|
|
97376
98953
|
out.push("");
|
|
97377
|
-
out.push(` ${
|
|
97378
|
-
out.push(` ${
|
|
97379
|
-
out.push(` ${
|
|
97380
|
-
out.push(` ${
|
|
97381
|
-
out.push(` ${
|
|
97382
|
-
out.push(` ${
|
|
97383
|
-
out.push(` ${
|
|
98954
|
+
out.push(` ${import_picocolors81.default.cyan("template pack")} ${import_picocolors81.default.dim("bundle the current agent into a template")}`);
|
|
98955
|
+
out.push(` ${import_picocolors81.default.cyan("template publish")} ${import_picocolors81.default.dim("upload a template to the registry")}`);
|
|
98956
|
+
out.push(` ${import_picocolors81.default.cyan("template search")} ${import_picocolors81.default.dim("[query]")} ${import_picocolors81.default.dim("search the registry")}`);
|
|
98957
|
+
out.push(` ${import_picocolors81.default.cyan("template info")} ${import_picocolors81.default.dim("<creator/slug>")} ${import_picocolors81.default.dim("show registry details for a template")}`);
|
|
98958
|
+
out.push(` ${import_picocolors81.default.cyan("template onboard")} ${import_picocolors81.default.dim("<creator/slug>")} ${import_picocolors81.default.dim("install (or refresh) a template")}`);
|
|
98959
|
+
out.push(` ${import_picocolors81.default.cyan("template list")} ${import_picocolors81.default.dim("show installed templates")}`);
|
|
98960
|
+
out.push(` ${import_picocolors81.default.cyan("template remove")} ${import_picocolors81.default.dim("<creator/slug>")} ${import_picocolors81.default.dim("uninstall a template")}`);
|
|
97384
98961
|
out.push("");
|
|
97385
98962
|
out.push(divider("SKILLS"));
|
|
97386
98963
|
out.push("");
|
|
97387
|
-
out.push(` ${
|
|
97388
|
-
out.push(` ${
|
|
97389
|
-
out.push(` ${
|
|
97390
|
-
out.push(` ${
|
|
97391
|
-
out.push(` ${
|
|
97392
|
-
out.push(` ${
|
|
97393
|
-
out.push(` ${
|
|
98964
|
+
out.push(` ${import_picocolors81.default.cyan("skill add")} ${import_picocolors81.default.dim("<source>")} ${import_picocolors81.default.dim("install a skill (github / git / brainbase)")}`);
|
|
98965
|
+
out.push(` ${import_picocolors81.default.cyan("skill list")} ${import_picocolors81.default.dim("show locally installed skills + their source")}`);
|
|
98966
|
+
out.push(` ${import_picocolors81.default.cyan("skill update")} ${import_picocolors81.default.dim("<slug>")} ${import_picocolors81.default.dim("re-fetch a skill from its recorded source")}`);
|
|
98967
|
+
out.push(` ${import_picocolors81.default.cyan("skill remove")} ${import_picocolors81.default.dim("<slug>")} ${import_picocolors81.default.dim("uninstall a skill")}`);
|
|
98968
|
+
out.push(` ${import_picocolors81.default.cyan("skill search")} ${import_picocolors81.default.dim("[query]")} ${import_picocolors81.default.dim("search the brainbase skill registry")}`);
|
|
98969
|
+
out.push(` ${import_picocolors81.default.cyan("skill info")} ${import_picocolors81.default.dim("<creator/slug>")} ${import_picocolors81.default.dim("show registry details for a skill")}`);
|
|
98970
|
+
out.push(` ${import_picocolors81.default.cyan("skill publish")} ${import_picocolors81.default.dim("[dir]")} ${import_picocolors81.default.dim("publish a SKILL.md folder (defaults to .)")}`);
|
|
97394
98971
|
out.push("");
|
|
97395
98972
|
out.push(divider("CLI TOKENS"));
|
|
97396
98973
|
out.push("");
|
|
97397
|
-
out.push(` ${
|
|
97398
|
-
out.push(` ${
|
|
97399
|
-
out.push(` ${
|
|
97400
|
-
out.push(` ${
|
|
98974
|
+
out.push(` ${import_picocolors81.default.cyan("token create")} ${import_picocolors81.default.dim("issue a long-lived CLI key for CI / scripts")}`);
|
|
98975
|
+
out.push(` ${import_picocolors81.default.cyan("token list")} ${import_picocolors81.default.dim("show your tokens")}`);
|
|
98976
|
+
out.push(` ${import_picocolors81.default.cyan("token rename")} ${import_picocolors81.default.dim("<id>")} ${import_picocolors81.default.dim("relabel a token")}`);
|
|
98977
|
+
out.push(` ${import_picocolors81.default.cyan("token revoke")} ${import_picocolors81.default.dim("<id>")} ${import_picocolors81.default.dim("revoke a token")}`);
|
|
98978
|
+
out.push("");
|
|
98979
|
+
out.push(divider("DECISIONS"));
|
|
98980
|
+
out.push("");
|
|
98981
|
+
out.push(` ${import_picocolors81.default.cyan("decide")} ${import_picocolors81.default.dim("-q <questions.json> <sources...>")} ${import_picocolors81.default.dim("answer decision-model questions over many files or rows in a few requests (`decide --help`)")}`);
|
|
97401
98982
|
out.push("");
|
|
97402
98983
|
out.push(divider("MCP"));
|
|
97403
98984
|
out.push("");
|
|
97404
|
-
out.push(` ${
|
|
97405
|
-
out.push(` ${
|
|
97406
|
-
out.push(` ${
|
|
98985
|
+
out.push(` ${import_picocolors81.default.cyan("mcp check")} ${import_picocolors81.default.dim("[--json]")} ${import_picocolors81.default.dim("verify MCP server connectivity through the brainbase proxy (runs at sandbox bootstrap)")}`);
|
|
98986
|
+
out.push(` ${import_picocolors81.default.cyan("mcp list")} ${import_picocolors81.default.dim("[--json]")} ${import_picocolors81.default.dim("show configured servers with OAuth state and expiry")}`);
|
|
98987
|
+
out.push(` ${import_picocolors81.default.cyan("mcp connect")} ${import_picocolors81.default.dim("<name>")} ${import_picocolors81.default.dim("authorize an OAuth-backed server: prints a single-use link, opens it, waits for approval")}`);
|
|
97407
98988
|
out.push("");
|
|
97408
98989
|
out.push(divider("INTEGRATIONS"));
|
|
97409
98990
|
out.push("");
|
|
97410
|
-
out.push(` ${
|
|
97411
|
-
out.push(` ${
|
|
97412
|
-
out.push(` ${
|
|
97413
|
-
out.push(` ${
|
|
97414
|
-
out.push(` ${
|
|
97415
|
-
out.push(` ${
|
|
97416
|
-
out.push(` ${
|
|
97417
|
-
out.push(` ${
|
|
98991
|
+
out.push(` ${import_picocolors81.default.cyan("integrations list")} ${import_picocolors81.default.dim("show the agent's Pipedream apps, accounts and app-level permission")}`);
|
|
98992
|
+
out.push(` ${import_picocolors81.default.cyan("integrations search")} ${import_picocolors81.default.dim("<query>")} ${import_picocolors81.default.dim("find apps in the Pipedream catalog")}`);
|
|
98993
|
+
out.push(` ${import_picocolors81.default.cyan("integrations actions")} ${import_picocolors81.default.dim("<app>")} ${import_picocolors81.default.dim("list an app's actions and whether each is allowed")}`);
|
|
98994
|
+
out.push(` ${import_picocolors81.default.cyan("integrations add")} ${import_picocolors81.default.dim("<app>")} ${import_picocolors81.default.dim("install an app; one that needs an account runs connect")}`);
|
|
98995
|
+
out.push(` ${import_picocolors81.default.cyan("integrations connect")} ${import_picocolors81.default.dim("<app>")} ${import_picocolors81.default.dim("open Pipedream's connect page for the app and wait for the account")}`);
|
|
98996
|
+
out.push(` ${import_picocolors81.default.cyan("integrations disconnect")} ${import_picocolors81.default.dim("<app>")} ${import_picocolors81.default.dim("delete the app's connected account")}`);
|
|
98997
|
+
out.push(` ${import_picocolors81.default.cyan("integrations remove")} ${import_picocolors81.default.dim("<app>")} ${import_picocolors81.default.dim("uninstall an app that needs no account")}`);
|
|
98998
|
+
out.push(` ${import_picocolors81.default.cyan("integrations allow|ask|deny")} ${import_picocolors81.default.dim("<app>[.<action>]")} ${import_picocolors81.default.dim("set the permission for an app or one of its actions")}`);
|
|
98999
|
+
out.push(` ${import_picocolors81.default.cyan("integrations context create")} ${import_picocolors81.default.dim("--application <name>")} ${import_picocolors81.default.dim("let a program outside Brainbase (the SDK) use the agent's integrations; prints a renewal handle once")}`);
|
|
99000
|
+
out.push(` ${import_picocolors81.default.cyan("integrations context end")} ${import_picocolors81.default.dim("<context-id>")} ${import_picocolors81.default.dim("end a standalone integration context now")}`);
|
|
97418
99001
|
out.push("");
|
|
97419
99002
|
out.push(divider("FLAGS"));
|
|
97420
99003
|
out.push("");
|
|
97421
|
-
out.push(` ${
|
|
97422
|
-
out.push(` ${
|
|
97423
|
-
out.push(` ${
|
|
99004
|
+
out.push(` ${import_picocolors81.default.dim("--harness <id>")} force harness for onboard / sync (e.g. claude-code)`);
|
|
99005
|
+
out.push(` ${import_picocolors81.default.dim("--scope <s>")} force scope: global | project`);
|
|
99006
|
+
out.push(` ${import_picocolors81.default.dim("--yes, -y")} skip confirmations / auto-overwrite`);
|
|
97424
99007
|
out.push(` ${" ".repeat("--yes, -y".length)} required for destructive commands with no terminal (pipes, CI)`);
|
|
97425
|
-
out.push(` ${
|
|
97426
|
-
out.push(` ${
|
|
97427
|
-
out.push(` ${
|
|
97428
|
-
out.push(` ${
|
|
97429
|
-
out.push(` ${
|
|
97430
|
-
out.push(` ${
|
|
97431
|
-
out.push(` ${
|
|
97432
|
-
out.push(` ${
|
|
97433
|
-
out.push(` ${
|
|
97434
|
-
out.push(` ${
|
|
97435
|
-
out.push(` ${
|
|
97436
|
-
out.push(` ${
|
|
97437
|
-
out.push(` ${
|
|
97438
|
-
out.push(` ${
|
|
97439
|
-
out.push(` ${
|
|
97440
|
-
out.push(` ${
|
|
97441
|
-
out.push(` ${
|
|
97442
|
-
out.push(` ${
|
|
97443
|
-
out.push(` ${
|
|
97444
|
-
out.push(` ${
|
|
97445
|
-
out.push(` ${
|
|
97446
|
-
out.push(` ${
|
|
97447
|
-
out.push(` ${
|
|
97448
|
-
out.push(` ${
|
|
97449
|
-
out.push(` ${
|
|
97450
|
-
out.push(` ${
|
|
97451
|
-
out.push(` ${
|
|
97452
|
-
out.push(` ${
|
|
97453
|
-
out.push(` ${
|
|
97454
|
-
out.push(` ${
|
|
97455
|
-
out.push(` ${
|
|
97456
|
-
out.push(` ${
|
|
97457
|
-
out.push(` ${
|
|
97458
|
-
out.push(` ${
|
|
99008
|
+
out.push(` ${import_picocolors81.default.dim("--agent <id>")} for link/task create/mcp list/mcp connect/integrations: use this agent id explicitly instead of the linked folder's (task list: filter to it)`);
|
|
99009
|
+
out.push(` ${import_picocolors81.default.dim("--message <text>")} for task create: required first user message`);
|
|
99010
|
+
out.push(` ${import_picocolors81.default.dim("--title <text>")} for task create: optional task title; for task update: the new title`);
|
|
99011
|
+
out.push(` ${import_picocolors81.default.dim("--clear-title")} for task update: remove the title (automatic titling may name it again later)`);
|
|
99012
|
+
out.push(` ${import_picocolors81.default.dim("--metadata k=v")} for task create: label the task; for task list: only tasks with this label; for task update: set one label, keeping the others (all repeatable)`);
|
|
99013
|
+
out.push(` ${import_picocolors81.default.dim("--unset-metadata <k>")} for task update: remove one label (repeatable)`);
|
|
99014
|
+
out.push(` ${import_picocolors81.default.dim("--clear-metadata")} for task update: remove every label; with --metadata, keep only those given`);
|
|
99015
|
+
out.push(` ${import_picocolors81.default.dim("--model <id>")} for task create: optional model override; for task update: switch the model the task's next turn runs on (the running turn keeps its model)`);
|
|
99016
|
+
out.push(` ${import_picocolors81.default.dim("--clear-model")} for task update: go back to the agent's default model from the next turn`);
|
|
99017
|
+
out.push(` ${import_picocolors81.default.dim("--version <v>")} for task create: run a saved version of the agent (12, v12 or a version id)`);
|
|
99018
|
+
out.push(` ${import_picocolors81.default.dim("--wait")} for task create: block until the task finishes; exit 1 unless it succeeded`);
|
|
99019
|
+
out.push(` ${import_picocolors81.default.dim("--timeout <secs>")} for task create --wait: give up after <secs> and exit 1`);
|
|
99020
|
+
out.push(` ${import_picocolors81.default.dim("--limit <n>")} for task list (1-200), task logs (events to print; with --follow, the first page size) and machine ls`);
|
|
99021
|
+
out.push(` ${import_picocolors81.default.dim("--follow, -f")} for task logs: stay attached and print events as they land`);
|
|
99022
|
+
out.push(` ${import_picocolors81.default.dim("--org <id-or-slug>")} pick the organization (team/agent list, agent create, orchestration create/list)`);
|
|
99023
|
+
out.push(` ${import_picocolors81.default.dim("--team <id>")} pick the team, same commands (works without --org)`);
|
|
99024
|
+
out.push(` ${import_picocolors81.default.dim("--all-teams")} for agent list: every team in the org (the default with no terminal)`);
|
|
99025
|
+
out.push(` ${import_picocolors81.default.dim("--json")} machine-readable output for supported commands`);
|
|
99026
|
+
out.push(` ${import_picocolors81.default.dim("--no-tracking")} for link / agent pull --link: skip routing LLM traffic through brainbase`);
|
|
99027
|
+
out.push(` ${import_picocolors81.default.dim("--link")} for agent pull: link this folder to the agent first, as \`brainbase link --agent <id> --yes\` would, in one process`);
|
|
99028
|
+
out.push(` ${import_picocolors81.default.dim("--track")} for agent create: enable tracking non-interactively (off without a TTY)`);
|
|
99029
|
+
out.push(` ${import_picocolors81.default.dim("--shell <sh|fish>")} for agent env: pick output format (auto-detected from $SHELL)`);
|
|
99030
|
+
out.push(` ${import_picocolors81.default.dim("--bot-token <t>")} for agent connect slack (or BRAINBASE_SLACK_BOT_TOKEN, or stdin)`);
|
|
99031
|
+
out.push(` ${import_picocolors81.default.dim("--signing-secret <s>")} for agent connect slack (or BRAINBASE_SLACK_SIGNING_SECRET, or stdin)`);
|
|
99032
|
+
out.push(` ${import_picocolors81.default.dim("--bot-name <name>")} for agent connect meeting: the bot's display name`);
|
|
99033
|
+
out.push(` ${import_picocolors81.default.dim("--app-id <id> / --app-name <name>")} optional Slack app identity`);
|
|
99034
|
+
out.push(` ${import_picocolors81.default.dim("--bot-image-url <url>")} optional meeting bot image`);
|
|
99035
|
+
out.push(` ${import_picocolors81.default.dim("--full")} for agent/orchestration init: write a commented template covering every block`);
|
|
99036
|
+
out.push(` ${import_picocolors81.default.dim("--minimal")} for agent init: write the starter manifest (the default)`);
|
|
99037
|
+
out.push(` ${import_picocolors81.default.dim("--all")} for template list: include installs from other folders; for machine ls: include torn-down machines`);
|
|
99038
|
+
out.push(` ${import_picocolors81.default.dim("--web <url>")} for login: web app URL (default https://app.brainbaselabs.com)`);
|
|
99039
|
+
out.push(` ${import_picocolors81.default.dim("--no-open")} for mcp/integrations connect: print the link without opening a browser (implied with no terminal)`);
|
|
99040
|
+
out.push(` ${import_picocolors81.default.dim("--no-wait")} for mcp/integrations connect: print the link and exit instead of waiting`);
|
|
99041
|
+
out.push(` ${import_picocolors81.default.dim("--account <id>")} for integrations disconnect: which account, when the app has more than one`);
|
|
99042
|
+
out.push(` ${import_picocolors81.default.dim("--application <name>")} for integrations context create: names the program the context is for`);
|
|
99043
|
+
out.push(` ${import_picocolors81.default.dim("--max-lifetime <dur>")} for integrations context create: when the context ends at the latest, 60s-30d (default 7d)`);
|
|
99044
|
+
out.push(` ${import_picocolors81.default.dim("--reason <text>")} for integrations context end: recorded with the context`);
|
|
97459
99045
|
out.push("");
|
|
97460
99046
|
out.push(divider("ENV"));
|
|
97461
99047
|
out.push("");
|
|
97462
|
-
out.push(` ${
|
|
97463
|
-
out.push(` ${
|
|
97464
|
-
out.push(` ${
|
|
97465
|
-
out.push(` ${
|
|
97466
|
-
out.push(` ${
|
|
97467
|
-
out.push(` ${
|
|
97468
|
-
out.push(` ${
|
|
97469
|
-
out.push(` ${
|
|
97470
|
-
out.push(` ${
|
|
97471
|
-
out.push(` ${
|
|
97472
|
-
out.push(` ${
|
|
99048
|
+
out.push(` ${import_picocolors81.default.dim("BRAINBASE_HOME")} override the local config dir (default ~/.brainbase)`);
|
|
99049
|
+
out.push(` ${import_picocolors81.default.dim("BRAINBASE_DEBUG")} print full stack traces on error (any value; unset to disable)`);
|
|
99050
|
+
out.push(` ${import_picocolors81.default.dim("BRAINBASE_WEB_URL")} override the web app URL used by login, console links and integrations`);
|
|
99051
|
+
out.push(` ${import_picocolors81.default.dim("BRAINBASE_CONTROL_PLANE_URL")} override the MAS host (/v2/cli; task and interface commands use /v2/tasks and /v2/interfaces)`);
|
|
99052
|
+
out.push(` ${import_picocolors81.default.dim("BRAINBASE_API_URL")} legacy KLS host override (uses /api/cli; proxy/registry fallback)`);
|
|
99053
|
+
out.push(` ${import_picocolors81.default.dim("BRAINBASE_PROXY_URL")} override the model-proxy URL used by harness traffic (default https://api.v1.brainbaselabs.com)`);
|
|
99054
|
+
out.push(` ${import_picocolors81.default.dim("BRAINBASE_REGISTRY_URL")} override the registry API URL (default https://api.v1.brainbaselabs.com)`);
|
|
99055
|
+
out.push(` ${import_picocolors81.default.dim("BRAINBASE_TOKEN")} long-lived CLI PAT; outranks the login session and the PAT saved in token.json`);
|
|
99056
|
+
out.push(` ${import_picocolors81.default.dim("BRAINBASE_SKIP_AUTH")} bypass the auth gate for development`);
|
|
99057
|
+
out.push(` ${import_picocolors81.default.dim("BRAINBASE_NON_INTERACTIVE")} force non-interactive mode — skip/auto-default prompts (CI & agents)`);
|
|
99058
|
+
out.push(` ${import_picocolors81.default.dim("BRAINBASE_RUN_ENTRYPOINT")} =1 → agent pull executes the agent entrypoint (sandbox boots; or pass --run-entrypoint)`);
|
|
97473
99059
|
out.push("");
|
|
97474
|
-
out.push(` ${
|
|
97475
|
-
out.push(` ${
|
|
97476
|
-
out.push(` ${
|
|
97477
|
-
out.push(` ${
|
|
97478
|
-
out.push(` ${
|
|
97479
|
-
out.push(` ${
|
|
97480
|
-
out.push(` ${
|
|
99060
|
+
out.push(` ${import_picocolors81.default.dim("BRAINBASE_MEMORY_MCP_URL")} override the built-in memory MCP host`);
|
|
99061
|
+
out.push(` ${import_picocolors81.default.dim("BRAINBASE_BROWSER_MCP_URL")} override the built-in browser MCP host`);
|
|
99062
|
+
out.push(` ${import_picocolors81.default.dim("BRAINBASE_SLACK_MCP_URL")} override the built-in Slack MCP host`);
|
|
99063
|
+
out.push(` ${import_picocolors81.default.dim("BRAINBASE_MEETING_MCP_URL")} override the built-in meeting MCP host`);
|
|
99064
|
+
out.push(` ${import_picocolors81.default.dim("BRAINBASE_GITHUB_MCP_URL")} override the built-in GitHub MCP host`);
|
|
99065
|
+
out.push(` ${import_picocolors81.default.dim("BRAINBASE_LINEAR_MCP_URL")} override the built-in Linear MCP host`);
|
|
99066
|
+
out.push(` ${import_picocolors81.default.dim("BRAINBASE_ORCHESTRATION_MCP_URL")} override the built-in orchestration MCP host`);
|
|
97481
99067
|
out.push("");
|
|
97482
99068
|
out.push(divider("HARNESSES"));
|
|
97483
99069
|
out.push("");
|
|
97484
|
-
out.push(` ${
|
|
97485
|
-
out.push(` ${
|
|
97486
|
-
out.push(` ${
|
|
99070
|
+
out.push(` ${import_picocolors81.default.dim("•")} ${import_picocolors81.default.bold("claude-code")} ${import_picocolors81.default.dim("skills, mcps, agents, commands, playbooks, instructions, files")}`);
|
|
99071
|
+
out.push(` ${import_picocolors81.default.dim("•")} ${import_picocolors81.default.bold("codex")} ${import_picocolors81.default.dim("skills, mcps, commands, playbooks, instructions, files")}`);
|
|
99072
|
+
out.push(` ${import_picocolors81.default.dim("•")} ${import_picocolors81.default.bold("kafka")} ${import_picocolors81.default.dim("skills, mcps, agents, commands, playbooks, instructions, files")}`);
|
|
97487
99073
|
out.push("");
|
|
97488
99074
|
console.log(out.join(`
|
|
97489
99075
|
`));
|
|
@@ -97517,7 +99103,10 @@ var VALUE_TAKING_FLAGS = new Set([
|
|
|
97517
99103
|
"--bot-image-url",
|
|
97518
99104
|
"--task-id",
|
|
97519
99105
|
"--limit",
|
|
97520
|
-
"--file"
|
|
99106
|
+
"--file",
|
|
99107
|
+
"--application",
|
|
99108
|
+
"--max-lifetime",
|
|
99109
|
+
"--reason"
|
|
97521
99110
|
]);
|
|
97522
99111
|
function isValueOfPriorFlag2(args, index) {
|
|
97523
99112
|
return index > 0 && VALUE_TAKING_FLAGS.has(args[index - 1]);
|
|
@@ -97638,10 +99227,10 @@ async function requireAuth(cmd) {
|
|
|
97638
99227
|
if (storedPatFor(status.session))
|
|
97639
99228
|
return;
|
|
97640
99229
|
console.error("");
|
|
97641
|
-
console.error(` ${brandTint("◆")} ${
|
|
99230
|
+
console.error(` ${brandTint("◆")} ${import_picocolors81.default.bold("brainbase")}`);
|
|
97642
99231
|
console.error("");
|
|
97643
|
-
console.error(` ${
|
|
97644
|
-
console.error(` ${
|
|
99232
|
+
console.error(` ${import_picocolors81.default.red("✗")} You need to sign in to use ${import_picocolors81.default.bold("brainbase " + cmd)}.`);
|
|
99233
|
+
console.error(` ${import_picocolors81.default.dim(noUsableCredentialMessage())}`);
|
|
97645
99234
|
console.error("");
|
|
97646
99235
|
process14.exit(1);
|
|
97647
99236
|
}
|
|
@@ -97651,7 +99240,7 @@ async function main() {
|
|
|
97651
99240
|
const rawCwd = process14.cwd();
|
|
97652
99241
|
const cwd2 = (() => {
|
|
97653
99242
|
try {
|
|
97654
|
-
return
|
|
99243
|
+
return fs96.realpathSync(rawCwd);
|
|
97655
99244
|
} catch {
|
|
97656
99245
|
return rawCwd;
|
|
97657
99246
|
}
|
|
@@ -97668,7 +99257,7 @@ async function main() {
|
|
|
97668
99257
|
await runRun(cwd2, argv);
|
|
97669
99258
|
return;
|
|
97670
99259
|
}
|
|
97671
|
-
const ownsArgs = new Set(["task", "benchmark", "interface", "interfaces"]);
|
|
99260
|
+
const ownsArgs = new Set(["task", "benchmark", "interface", "interfaces", "decide"]);
|
|
97672
99261
|
if (cmd === "agent")
|
|
97673
99262
|
argv.splice(0, argv.length, ...routeAgentSurfaceArgs(argv));
|
|
97674
99263
|
const sharedArgs = ownsArgs.has(cmd) || cmd === "agent" && ["versions", "surface", "connect", "disconnect", "connections"].includes(argv[0] ?? "") ? [] : argv;
|
|
@@ -97905,6 +99494,10 @@ async function main() {
|
|
|
97905
99494
|
process14.exitCode = code;
|
|
97906
99495
|
break;
|
|
97907
99496
|
}
|
|
99497
|
+
case "decide": {
|
|
99498
|
+
process14.exitCode = await runDecide(cwd2, argv);
|
|
99499
|
+
break;
|
|
99500
|
+
}
|
|
97908
99501
|
case "integration":
|
|
97909
99502
|
case "integrations": {
|
|
97910
99503
|
const sub = argv.shift();
|
|
@@ -97925,12 +99518,12 @@ ${didYouMean(cmd, COMMANDS3, "brainbase")}`);
|
|
|
97925
99518
|
process14.exit(1);
|
|
97926
99519
|
}
|
|
97927
99520
|
} catch (err) {
|
|
97928
|
-
const
|
|
99521
|
+
const message3 = sanitizeLines(err.message).join(`
|
|
97929
99522
|
`);
|
|
97930
|
-
console.error(
|
|
97931
|
-
${
|
|
99523
|
+
console.error(import_picocolors81.default.red(`
|
|
99524
|
+
${message3}`));
|
|
97932
99525
|
if (err instanceof ApiError && err.status === 401 && !err.message.includes("brainbase login")) {
|
|
97933
|
-
console.error(` Run ${
|
|
99526
|
+
console.error(` Run ${import_picocolors81.default.cyan("brainbase login")} to connect this device.`);
|
|
97934
99527
|
}
|
|
97935
99528
|
if (process14.env.BRAINBASE_DEBUG)
|
|
97936
99529
|
console.error(err.stack);
|