@brainbase-labs/cli 0.16.5 → 0.17.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/README.md +9 -5
- package/dist/index.js +606 -156
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -18,6 +18,8 @@ brainbase template pack # bundle the current agent into a template
|
|
|
18
18
|
brainbase template publish # upload to the registry
|
|
19
19
|
brainbase template search # find templates published by your team
|
|
20
20
|
brainbase template onboard <creator/slug> # install or refresh a template
|
|
21
|
+
brainbase agent create # claim a local brainbase.agent.yaml
|
|
22
|
+
brainbase task create --message "Review this project and propose next steps"
|
|
21
23
|
```
|
|
22
24
|
|
|
23
25
|
Run `brainbase help` to see every command.
|
|
@@ -74,7 +76,7 @@ Playbook files carry a small YAML frontmatter (`title`, `description`) — the C
|
|
|
74
76
|
|
|
75
77
|
| Variable | Purpose |
|
|
76
78
|
|-|-|
|
|
77
|
-
| `BRAINBASE_CONTROL_PLANE_URL` | Override the MAS
|
|
79
|
+
| `BRAINBASE_CONTROL_PLANE_URL` | Override the MAS host. Agent/orchestration requests use `/v2/cli`; `task create` uses `/v2/tasks`. The default is `https://api.brainbaselabs.com`. |
|
|
78
80
|
| `BRAINBASE_API_URL` | Legacy KLS host override. Control requests use `/api/cli`; it is also the fallback for model-proxy and registry traffic. |
|
|
79
81
|
| `BRAINBASE_PROXY_URL` | Override the model-proxy host used when enabling harness tracking. |
|
|
80
82
|
| `BRAINBASE_REGISTRY_URL` | Override the registry API host. |
|
|
@@ -86,12 +88,14 @@ the server captured at login, and finally `https://api.v1.brainbaselabs.com`.
|
|
|
86
88
|
|
|
87
89
|
## Auth
|
|
88
90
|
|
|
89
|
-
|
|
91
|
+
Managed task creation uses this authentication precedence:
|
|
90
92
|
|
|
91
|
-
1. `
|
|
92
|
-
2. `brainbase
|
|
93
|
+
1. `BRAINBASE_TOKEN` — an explicit PAT from the environment.
|
|
94
|
+
2. `brainbase login` — a Supabase session stored in `~/.brainbase/auth.json`.
|
|
95
|
+
3. `brainbase token create --scopes read,publish` — a PAT stored in `~/.brainbase/token.json` when no login session is configured.
|
|
93
96
|
|
|
94
|
-
|
|
97
|
+
An explicit PAT does not inherit routing from a stored login. Set
|
|
98
|
+
`BRAINBASE_CONTROL_PLANE_URL` when using a PAT against a non-default MAS host.
|
|
95
99
|
|
|
96
100
|
## License
|
|
97
101
|
|
package/dist/index.js
CHANGED
|
@@ -35141,7 +35141,7 @@ var require_dist2 = __commonJS((exports, module) => {
|
|
|
35141
35141
|
});
|
|
35142
35142
|
|
|
35143
35143
|
// src/index.ts
|
|
35144
|
-
var
|
|
35144
|
+
var import_picocolors44 = __toESM(require_picocolors(), 1);
|
|
35145
35145
|
import process14 from "node:process";
|
|
35146
35146
|
import fs79 from "node:fs";
|
|
35147
35147
|
|
|
@@ -36008,7 +36008,7 @@ function padStart(s, n) {
|
|
|
36008
36008
|
// package.json
|
|
36009
36009
|
var package_default = {
|
|
36010
36010
|
name: "@brainbase-labs/cli",
|
|
36011
|
-
version: "0.
|
|
36011
|
+
version: "0.17.0",
|
|
36012
36012
|
description: "Pack, share, and install agent templates across harnesses (Claude Code, Codex, ...).",
|
|
36013
36013
|
type: "module",
|
|
36014
36014
|
bin: {
|
|
@@ -53841,9 +53841,80 @@ function apiErrorMessage(body, status) {
|
|
|
53841
53841
|
return `HTTP ${status}`;
|
|
53842
53842
|
}
|
|
53843
53843
|
|
|
53844
|
+
// src/core/token.ts
|
|
53845
|
+
import path57 from "node:path";
|
|
53846
|
+
import fs47 from "node:fs";
|
|
53847
|
+
var TOKEN_FILE = path57.join(BRAINBASE_HOME, "token.json");
|
|
53848
|
+
var TOKEN_PREFIX = "bbpat_";
|
|
53849
|
+
var TOKEN_PREFIX_LEN = 14;
|
|
53850
|
+
function tokenPrefix(token) {
|
|
53851
|
+
if (!token.startsWith(TOKEN_PREFIX)) {
|
|
53852
|
+
throw new Error(`not a brainbase PAT: missing ${TOKEN_PREFIX} prefix`);
|
|
53853
|
+
}
|
|
53854
|
+
return token.slice(0, TOKEN_PREFIX_LEN);
|
|
53855
|
+
}
|
|
53856
|
+
function isValidTokenFormat(token) {
|
|
53857
|
+
if (typeof token !== "string")
|
|
53858
|
+
return false;
|
|
53859
|
+
if (!token.startsWith(TOKEN_PREFIX))
|
|
53860
|
+
return false;
|
|
53861
|
+
return /^bbpat_[A-Za-z0-9]{20,}$/.test(token);
|
|
53862
|
+
}
|
|
53863
|
+
var StoredTokenSchema = exports_external.object({
|
|
53864
|
+
schemaVersion: exports_external.literal(1),
|
|
53865
|
+
token: exports_external.string(),
|
|
53866
|
+
prefix: exports_external.string(),
|
|
53867
|
+
name: exports_external.string().optional(),
|
|
53868
|
+
createdAt: exports_external.string()
|
|
53869
|
+
});
|
|
53870
|
+
function readToken() {
|
|
53871
|
+
if (!exists(TOKEN_FILE))
|
|
53872
|
+
return null;
|
|
53873
|
+
try {
|
|
53874
|
+
return StoredTokenSchema.parse(readJson(TOKEN_FILE));
|
|
53875
|
+
} catch {
|
|
53876
|
+
return null;
|
|
53877
|
+
}
|
|
53878
|
+
}
|
|
53879
|
+
function writeToken(token, name) {
|
|
53880
|
+
if (!isValidTokenFormat(token)) {
|
|
53881
|
+
throw new Error("refusing to store token: invalid format");
|
|
53882
|
+
}
|
|
53883
|
+
ensureDir(BRAINBASE_HOME);
|
|
53884
|
+
const stored = {
|
|
53885
|
+
schemaVersion: 1,
|
|
53886
|
+
token,
|
|
53887
|
+
prefix: tokenPrefix(token),
|
|
53888
|
+
name,
|
|
53889
|
+
createdAt: new Date().toISOString()
|
|
53890
|
+
};
|
|
53891
|
+
writeJson(TOKEN_FILE, stored);
|
|
53892
|
+
try {
|
|
53893
|
+
fs47.chmodSync(TOKEN_FILE, 384);
|
|
53894
|
+
} catch {}
|
|
53895
|
+
return stored;
|
|
53896
|
+
}
|
|
53897
|
+
function clearToken() {
|
|
53898
|
+
if (exists(TOKEN_FILE))
|
|
53899
|
+
fs47.rmSync(TOKEN_FILE);
|
|
53900
|
+
}
|
|
53901
|
+
|
|
53844
53902
|
// src/core/api.ts
|
|
53845
53903
|
var DEFAULT_CONTROL_PLANE_BASE = "https://api.brainbaselabs.com";
|
|
53846
53904
|
var DEFAULT_PROXY_BASE = "https://api.v1.brainbaselabs.com";
|
|
53905
|
+
var MAS_IN_PROGRESS_MAX_WAIT_MS = 15000;
|
|
53906
|
+
var MAS_REQUEST_TIMEOUT_MS = 30000;
|
|
53907
|
+
var MAS_MIN_RETRY_DELAY_MS = 100;
|
|
53908
|
+
var MAS_MAX_RETRY_DELAY_MS = 2000;
|
|
53909
|
+
var DEFINITELY_UNSENT_NETWORK_CODES = new Set([
|
|
53910
|
+
"ConnectionRefused",
|
|
53911
|
+
"ECONNREFUSED",
|
|
53912
|
+
"ENOTFOUND",
|
|
53913
|
+
"EAI_AGAIN",
|
|
53914
|
+
"ERR_INVALID_URL",
|
|
53915
|
+
"FailedToOpenSocket",
|
|
53916
|
+
"UND_ERR_CONNECT_TIMEOUT"
|
|
53917
|
+
]);
|
|
53847
53918
|
|
|
53848
53919
|
class ApiError extends Error {
|
|
53849
53920
|
status;
|
|
@@ -53855,6 +53926,17 @@ class ApiError extends Error {
|
|
|
53855
53926
|
this.name = "ApiError";
|
|
53856
53927
|
}
|
|
53857
53928
|
}
|
|
53929
|
+
|
|
53930
|
+
class NetworkApiError extends ApiError {
|
|
53931
|
+
definitelyUnsent;
|
|
53932
|
+
constructor(message, definitelyUnsent) {
|
|
53933
|
+
super(message);
|
|
53934
|
+
this.definitelyUnsent = definitelyUnsent;
|
|
53935
|
+
}
|
|
53936
|
+
}
|
|
53937
|
+
|
|
53938
|
+
class TaskRecoveryDeadlineError extends ApiError {
|
|
53939
|
+
}
|
|
53858
53940
|
function normalizeControlPlaneUrl(url) {
|
|
53859
53941
|
const normalized = url?.trim().replace(/\/+$/, "");
|
|
53860
53942
|
return normalized || DEFAULT_CONTROL_PLANE_BASE;
|
|
@@ -53870,10 +53952,17 @@ function controlPlaneBaseUrl(session) {
|
|
|
53870
53952
|
}
|
|
53871
53953
|
return normalizeControlPlaneUrl(session?.control_plane_url);
|
|
53872
53954
|
}
|
|
53955
|
+
function masControlPlaneBaseUrl(session) {
|
|
53956
|
+
const controlPlane = process.env.BRAINBASE_CONTROL_PLANE_URL?.trim();
|
|
53957
|
+
return normalizeControlPlaneUrl(controlPlane || session?.control_plane_url);
|
|
53958
|
+
}
|
|
53873
53959
|
function apiBase(session) {
|
|
53874
53960
|
const suffix = usesLegacyControlPlane() ? "/api/cli" : "/v2/cli";
|
|
53875
53961
|
return `${controlPlaneBaseUrl(session)}${suffix}`;
|
|
53876
53962
|
}
|
|
53963
|
+
function masApiBase(session) {
|
|
53964
|
+
return `${masControlPlaneBaseUrl(session)}/v2`;
|
|
53965
|
+
}
|
|
53877
53966
|
function usesLegacyControlPlane() {
|
|
53878
53967
|
return !process.env.BRAINBASE_CONTROL_PLANE_URL?.trim() && !!process.env.BRAINBASE_API_URL?.trim();
|
|
53879
53968
|
}
|
|
@@ -53903,6 +53992,53 @@ async function resolveCredential() {
|
|
|
53903
53992
|
const status = authStatus();
|
|
53904
53993
|
throw new ApiError(status.ok ? "CLI authentication changed while this command was starting; retry it" : status.reason ?? "not logged in", 401);
|
|
53905
53994
|
}
|
|
53995
|
+
async function resolveMasCredential() {
|
|
53996
|
+
const configuredSession = readAuth();
|
|
53997
|
+
try {
|
|
53998
|
+
return await resolveCredential();
|
|
53999
|
+
} catch (error) {
|
|
54000
|
+
if (!(error instanceof ApiError && error.status === 401)) {
|
|
54001
|
+
throw error;
|
|
54002
|
+
}
|
|
54003
|
+
if (configuredSession || readAuth()) {
|
|
54004
|
+
if (readToken()) {
|
|
54005
|
+
throw new ApiError(`${error.message}. A stored PAT is available but will not be used while a login session is configured. Run \`brainbase logout\` to use the stored PAT, or \`brainbase login\` to refresh the session.`, 401);
|
|
54006
|
+
}
|
|
54007
|
+
throw error;
|
|
54008
|
+
}
|
|
54009
|
+
}
|
|
54010
|
+
const storedToken = readToken();
|
|
54011
|
+
if (storedToken) {
|
|
54012
|
+
return {
|
|
54013
|
+
bearer: storedToken.token,
|
|
54014
|
+
session: null,
|
|
54015
|
+
source: "stored_pat"
|
|
54016
|
+
};
|
|
54017
|
+
}
|
|
54018
|
+
const status = authStatus();
|
|
54019
|
+
throw new ApiError(status.ok ? "CLI authentication changed while this command was starting; retry it" : status.reason ?? "not logged in", 401);
|
|
54020
|
+
}
|
|
54021
|
+
function networkErrorCode(error) {
|
|
54022
|
+
if (!error || typeof error !== "object")
|
|
54023
|
+
return;
|
|
54024
|
+
const code = error.code;
|
|
54025
|
+
if (typeof code === "string")
|
|
54026
|
+
return code;
|
|
54027
|
+
const cause = error.cause;
|
|
54028
|
+
if (!cause || typeof cause !== "object")
|
|
54029
|
+
return;
|
|
54030
|
+
const causeCode = cause.code;
|
|
54031
|
+
return typeof causeCode === "string" ? causeCode : undefined;
|
|
54032
|
+
}
|
|
54033
|
+
function isDefinitelyUnsentNetworkError(error) {
|
|
54034
|
+
const code = networkErrorCode(error);
|
|
54035
|
+
if (DEFINITELY_UNSENT_NETWORK_CODES.has(code ?? ""))
|
|
54036
|
+
return true;
|
|
54037
|
+
if (!error || typeof error !== "object")
|
|
54038
|
+
return false;
|
|
54039
|
+
const cause = error.cause;
|
|
54040
|
+
return !!cause && typeof cause === "object" && cause.message === "bad port";
|
|
54041
|
+
}
|
|
53906
54042
|
async function sendRequest(url, init, bearer) {
|
|
53907
54043
|
const headers = new Headers(init.headers);
|
|
53908
54044
|
if (!headers.has("Authorization")) {
|
|
@@ -53916,7 +54052,7 @@ async function sendRequest(url, init, bearer) {
|
|
|
53916
54052
|
try {
|
|
53917
54053
|
return await fetch(url, { ...init, headers });
|
|
53918
54054
|
} catch (err) {
|
|
53919
|
-
throw new
|
|
54055
|
+
throw new NetworkApiError(`Network error: ${err.message}`, isDefinitelyUnsentNetworkError(err));
|
|
53920
54056
|
}
|
|
53921
54057
|
}
|
|
53922
54058
|
async function sendWithAuthRetry(session, send) {
|
|
@@ -53945,6 +54081,160 @@ async function request(pathname, init = {}) {
|
|
|
53945
54081
|
}
|
|
53946
54082
|
return body;
|
|
53947
54083
|
}
|
|
54084
|
+
function masApiErrorMessage(body, status) {
|
|
54085
|
+
if (body && typeof body === "object") {
|
|
54086
|
+
const obj = body;
|
|
54087
|
+
if (typeof obj.error === "string" && obj.error.trim() && typeof obj.message === "string" && obj.message.trim()) {
|
|
54088
|
+
const error = obj.error.trim();
|
|
54089
|
+
const message = obj.message.trim();
|
|
54090
|
+
return error === message ? message : `${error}: ${message}`;
|
|
54091
|
+
}
|
|
54092
|
+
for (const key2 of ["detail", "error", "message"]) {
|
|
54093
|
+
const value = obj[key2];
|
|
54094
|
+
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
54095
|
+
continue;
|
|
54096
|
+
const nested = value;
|
|
54097
|
+
for (const nestedKey of ["message", "detail", "error"]) {
|
|
54098
|
+
const message = nested[nestedKey];
|
|
54099
|
+
if (typeof message === "string" && message.trim()) {
|
|
54100
|
+
return message.trim();
|
|
54101
|
+
}
|
|
54102
|
+
}
|
|
54103
|
+
}
|
|
54104
|
+
}
|
|
54105
|
+
return apiErrorMessage(body, status);
|
|
54106
|
+
}
|
|
54107
|
+
function masRetryDelayMs(retryAfterHeader, fallbackMs) {
|
|
54108
|
+
const normalized = retryAfterHeader?.trim();
|
|
54109
|
+
if (!normalized)
|
|
54110
|
+
return fallbackMs;
|
|
54111
|
+
const retryAfterSeconds = Number(normalized);
|
|
54112
|
+
if (!Number.isFinite(retryAfterSeconds) || retryAfterSeconds < 0) {
|
|
54113
|
+
return fallbackMs;
|
|
54114
|
+
}
|
|
54115
|
+
return Math.min(MAS_MAX_RETRY_DELAY_MS, Math.max(MAS_MIN_RETRY_DELAY_MS, retryAfterSeconds * 1000));
|
|
54116
|
+
}
|
|
54117
|
+
function parseMasTaskCreateResponse(body) {
|
|
54118
|
+
if (!body || typeof body !== "object") {
|
|
54119
|
+
throw new ApiError("Task creation may have succeeded, but MAS returned an invalid response. Check your tasks before running this command again.", undefined, body);
|
|
54120
|
+
}
|
|
54121
|
+
const task = body;
|
|
54122
|
+
if (typeof task.id !== "string" || !task.id.trim() || typeof task.agent_id !== "string" || !task.agent_id.trim() || typeof task.status !== "string" || !task.status.trim()) {
|
|
54123
|
+
throw new ApiError("Task creation may have succeeded, but MAS returned an invalid response. Check your tasks before running this command again.", undefined, body);
|
|
54124
|
+
}
|
|
54125
|
+
return {
|
|
54126
|
+
id: task.id,
|
|
54127
|
+
agent_id: task.agent_id,
|
|
54128
|
+
status: task.status
|
|
54129
|
+
};
|
|
54130
|
+
}
|
|
54131
|
+
async function masRequest(pathname, init) {
|
|
54132
|
+
const credential = await resolveMasCredential();
|
|
54133
|
+
let currentSession = credential.session;
|
|
54134
|
+
let ambiguousNetworkRetriesRemaining = 1;
|
|
54135
|
+
let requestMayHaveSucceeded = false;
|
|
54136
|
+
let transientHttpRetriesRemaining = 1;
|
|
54137
|
+
let recoveryDeadline = null;
|
|
54138
|
+
let recoveryTaskId = null;
|
|
54139
|
+
const recoveryRequestTimeoutMs = () => {
|
|
54140
|
+
if (recoveryDeadline === null)
|
|
54141
|
+
return MAS_REQUEST_TIMEOUT_MS;
|
|
54142
|
+
const remainingMs = recoveryDeadline - Date.now();
|
|
54143
|
+
if (remainingMs <= 0) {
|
|
54144
|
+
throw new TaskRecoveryDeadlineError(recoveryTaskId ? `Task ${recoveryTaskId} is still being processed. Check its status before starting another task.` : "Task creation may still be processing. Check your tasks before running this command again.");
|
|
54145
|
+
}
|
|
54146
|
+
return Math.min(MAS_REQUEST_TIMEOUT_MS, remainingMs);
|
|
54147
|
+
};
|
|
54148
|
+
while (true) {
|
|
54149
|
+
const retrySession = credential.source === "session" ? currentSession : null;
|
|
54150
|
+
let res;
|
|
54151
|
+
try {
|
|
54152
|
+
res = await sendWithAuthRetry(retrySession, async (refreshed) => {
|
|
54153
|
+
if (refreshed)
|
|
54154
|
+
currentSession = refreshed;
|
|
54155
|
+
while (true) {
|
|
54156
|
+
const signal = AbortSignal.timeout(recoveryRequestTimeoutMs());
|
|
54157
|
+
try {
|
|
54158
|
+
return await sendRequest(`${masApiBase(currentSession)}${pathname}`, {
|
|
54159
|
+
...init,
|
|
54160
|
+
signal
|
|
54161
|
+
}, currentSession?.access_token ?? credential.bearer);
|
|
54162
|
+
} catch (error) {
|
|
54163
|
+
if (error instanceof NetworkApiError && error.definitelyUnsent) {
|
|
54164
|
+
throw error;
|
|
54165
|
+
}
|
|
54166
|
+
if (ambiguousNetworkRetriesRemaining === 0)
|
|
54167
|
+
throw error;
|
|
54168
|
+
requestMayHaveSucceeded = true;
|
|
54169
|
+
ambiguousNetworkRetriesRemaining -= 1;
|
|
54170
|
+
}
|
|
54171
|
+
}
|
|
54172
|
+
});
|
|
54173
|
+
} catch (error) {
|
|
54174
|
+
if (error instanceof TaskRecoveryDeadlineError)
|
|
54175
|
+
throw error;
|
|
54176
|
+
if (recoveryTaskId || recoveryDeadline !== null || requestMayHaveSucceeded) {
|
|
54177
|
+
throw new ApiError(recoveryTaskId ? `Task ${recoveryTaskId} may still be processing. Check its status before starting another task. ${error.message}` : `Task creation may still be processing. Check your tasks before running this command again. ${error.message}`);
|
|
54178
|
+
}
|
|
54179
|
+
throw error;
|
|
54180
|
+
}
|
|
54181
|
+
let text2;
|
|
54182
|
+
try {
|
|
54183
|
+
text2 = await res.text();
|
|
54184
|
+
} catch (error) {
|
|
54185
|
+
if (ambiguousNetworkRetriesRemaining > 0) {
|
|
54186
|
+
requestMayHaveSucceeded = true;
|
|
54187
|
+
ambiguousNetworkRetriesRemaining -= 1;
|
|
54188
|
+
continue;
|
|
54189
|
+
}
|
|
54190
|
+
throw new ApiError(recoveryTaskId ? `Task ${recoveryTaskId} may still be processing. Check its status before starting another task. ${error.message}` : recoveryDeadline !== null || requestMayHaveSucceeded ? `Task creation may still be processing. Check your tasks before running this command again. ${error.message}` : `Network error while reading response: ${error.message}`);
|
|
54191
|
+
}
|
|
54192
|
+
let body = text2;
|
|
54193
|
+
try {
|
|
54194
|
+
body = text2 ? JSON.parse(text2) : null;
|
|
54195
|
+
} catch {}
|
|
54196
|
+
const detail = body && typeof body === "object" ? body.detail : null;
|
|
54197
|
+
const detailObject = detail && typeof detail === "object" ? detail : null;
|
|
54198
|
+
const code = detailObject?.code;
|
|
54199
|
+
if (res.status === 409 && code === "idempotency_request_in_progress") {
|
|
54200
|
+
if (typeof detailObject?.task_id === "string") {
|
|
54201
|
+
recoveryTaskId = detailObject.task_id;
|
|
54202
|
+
}
|
|
54203
|
+
recoveryDeadline ??= Date.now() + MAS_IN_PROGRESS_MAX_WAIT_MS;
|
|
54204
|
+
const delayMs = masRetryDelayMs(res.headers.get("Retry-After"), 1000);
|
|
54205
|
+
if (Date.now() + delayMs >= recoveryDeadline) {
|
|
54206
|
+
throw new ApiError(recoveryTaskId ? `Task ${recoveryTaskId} is still being processed. Check its status before starting another task.` : masApiErrorMessage(body, res.status), res.status, body);
|
|
54207
|
+
}
|
|
54208
|
+
await new Promise((resolve) => setTimeout(resolve, delayMs));
|
|
54209
|
+
continue;
|
|
54210
|
+
}
|
|
54211
|
+
if (res.status >= 500 && transientHttpRetriesRemaining > 0) {
|
|
54212
|
+
transientHttpRetriesRemaining -= 1;
|
|
54213
|
+
requestMayHaveSucceeded = true;
|
|
54214
|
+
const delayMs = masRetryDelayMs(res.headers.get("Retry-After"), 250);
|
|
54215
|
+
if (recoveryDeadline !== null && Date.now() + delayMs >= recoveryDeadline) {
|
|
54216
|
+
throw new TaskRecoveryDeadlineError(recoveryTaskId ? `Task ${recoveryTaskId} is still being processed. Check its status before starting another task.` : "Task creation may still be processing. Check your tasks before running this command again.");
|
|
54217
|
+
}
|
|
54218
|
+
await new Promise((resolve) => setTimeout(resolve, delayMs));
|
|
54219
|
+
continue;
|
|
54220
|
+
}
|
|
54221
|
+
if (!res.ok) {
|
|
54222
|
+
const message = masApiErrorMessage(body, res.status);
|
|
54223
|
+
throw new ApiError(res.status >= 500 ? `${message} Task creation may still be processing; check your tasks before running this command again.` : message, res.status, body);
|
|
54224
|
+
}
|
|
54225
|
+
return body;
|
|
54226
|
+
}
|
|
54227
|
+
}
|
|
54228
|
+
var masApi = {
|
|
54229
|
+
async createTask(input, options) {
|
|
54230
|
+
const body = await masRequest("/tasks", {
|
|
54231
|
+
method: "POST",
|
|
54232
|
+
headers: { "Idempotency-Key": options.idempotencyKey },
|
|
54233
|
+
body: JSON.stringify(input)
|
|
54234
|
+
});
|
|
54235
|
+
return parseMasTaskCreateResponse(body);
|
|
54236
|
+
}
|
|
54237
|
+
};
|
|
53948
54238
|
var api = {
|
|
53949
54239
|
listOrgs() {
|
|
53950
54240
|
return request("/orgs");
|
|
@@ -54059,64 +54349,6 @@ function proxyBaseUrl(session) {
|
|
|
54059
54349
|
return DEFAULT_PROXY_BASE.replace(/\/+$/, "");
|
|
54060
54350
|
}
|
|
54061
54351
|
|
|
54062
|
-
// src/core/token.ts
|
|
54063
|
-
import path57 from "node:path";
|
|
54064
|
-
import fs47 from "node:fs";
|
|
54065
|
-
var TOKEN_FILE = path57.join(BRAINBASE_HOME, "token.json");
|
|
54066
|
-
var TOKEN_PREFIX = "bbpat_";
|
|
54067
|
-
var TOKEN_PREFIX_LEN = 14;
|
|
54068
|
-
function tokenPrefix(token) {
|
|
54069
|
-
if (!token.startsWith(TOKEN_PREFIX)) {
|
|
54070
|
-
throw new Error(`not a brainbase PAT: missing ${TOKEN_PREFIX} prefix`);
|
|
54071
|
-
}
|
|
54072
|
-
return token.slice(0, TOKEN_PREFIX_LEN);
|
|
54073
|
-
}
|
|
54074
|
-
function isValidTokenFormat(token) {
|
|
54075
|
-
if (typeof token !== "string")
|
|
54076
|
-
return false;
|
|
54077
|
-
if (!token.startsWith(TOKEN_PREFIX))
|
|
54078
|
-
return false;
|
|
54079
|
-
return /^bbpat_[A-Za-z0-9]{20,}$/.test(token);
|
|
54080
|
-
}
|
|
54081
|
-
var StoredTokenSchema = exports_external.object({
|
|
54082
|
-
schemaVersion: exports_external.literal(1),
|
|
54083
|
-
token: exports_external.string(),
|
|
54084
|
-
prefix: exports_external.string(),
|
|
54085
|
-
name: exports_external.string().optional(),
|
|
54086
|
-
createdAt: exports_external.string()
|
|
54087
|
-
});
|
|
54088
|
-
function readToken() {
|
|
54089
|
-
if (!exists(TOKEN_FILE))
|
|
54090
|
-
return null;
|
|
54091
|
-
try {
|
|
54092
|
-
return StoredTokenSchema.parse(readJson(TOKEN_FILE));
|
|
54093
|
-
} catch {
|
|
54094
|
-
return null;
|
|
54095
|
-
}
|
|
54096
|
-
}
|
|
54097
|
-
function writeToken(token, name) {
|
|
54098
|
-
if (!isValidTokenFormat(token)) {
|
|
54099
|
-
throw new Error("refusing to store token: invalid format");
|
|
54100
|
-
}
|
|
54101
|
-
ensureDir(BRAINBASE_HOME);
|
|
54102
|
-
const stored = {
|
|
54103
|
-
schemaVersion: 1,
|
|
54104
|
-
token,
|
|
54105
|
-
prefix: tokenPrefix(token),
|
|
54106
|
-
name,
|
|
54107
|
-
createdAt: new Date().toISOString()
|
|
54108
|
-
};
|
|
54109
|
-
writeJson(TOKEN_FILE, stored);
|
|
54110
|
-
try {
|
|
54111
|
-
fs47.chmodSync(TOKEN_FILE, 384);
|
|
54112
|
-
} catch {}
|
|
54113
|
-
return stored;
|
|
54114
|
-
}
|
|
54115
|
-
function clearToken() {
|
|
54116
|
-
if (exists(TOKEN_FILE))
|
|
54117
|
-
fs47.rmSync(TOKEN_FILE);
|
|
54118
|
-
}
|
|
54119
|
-
|
|
54120
54352
|
// src/core/registry-client.ts
|
|
54121
54353
|
var DEFAULT_BASE = "https://api.v1.brainbaselabs.com";
|
|
54122
54354
|
function baseUrl(session) {
|
|
@@ -76345,6 +76577,210 @@ async function runMcp(cwd2, sub, _argv, options) {
|
|
|
76345
76577
|
}
|
|
76346
76578
|
}
|
|
76347
76579
|
|
|
76580
|
+
// src/cli/task.ts
|
|
76581
|
+
var import_picocolors43 = __toESM(require_picocolors(), 1);
|
|
76582
|
+
|
|
76583
|
+
// src/cli/task-create.ts
|
|
76584
|
+
import { randomUUID as randomUUID2 } from "node:crypto";
|
|
76585
|
+
async function createTask(input, options) {
|
|
76586
|
+
return await masApi.createTask(input, options);
|
|
76587
|
+
}
|
|
76588
|
+
function requiredValue(value, flag) {
|
|
76589
|
+
const normalized = value?.trim();
|
|
76590
|
+
if (!normalized) {
|
|
76591
|
+
throw new Error(`${flag} is required and must not be blank.`);
|
|
76592
|
+
}
|
|
76593
|
+
return normalized;
|
|
76594
|
+
}
|
|
76595
|
+
function optionalValue(value, flag) {
|
|
76596
|
+
if (value === undefined)
|
|
76597
|
+
return;
|
|
76598
|
+
const normalized = value.trim();
|
|
76599
|
+
if (!normalized) {
|
|
76600
|
+
throw new Error(`${flag} must not be blank when provided.`);
|
|
76601
|
+
}
|
|
76602
|
+
return normalized;
|
|
76603
|
+
}
|
|
76604
|
+
function resolveAgentId(cwd2, agentId, readLocalManifest) {
|
|
76605
|
+
if (agentId !== undefined) {
|
|
76606
|
+
return requiredValue(agentId, "--agent");
|
|
76607
|
+
}
|
|
76608
|
+
const manifest = readLocalManifest(cwd2);
|
|
76609
|
+
if (!manifest?.id) {
|
|
76610
|
+
throw new Error("No claimed agent found in brainbase.agent.yaml. Run `brainbase agent create` first, or pass --agent <id>.");
|
|
76611
|
+
}
|
|
76612
|
+
return manifest.id;
|
|
76613
|
+
}
|
|
76614
|
+
function isPublishScopeError(error2) {
|
|
76615
|
+
const message = error2 instanceof Error ? error2.message : String(error2);
|
|
76616
|
+
const body = error2 && typeof error2 === "object" && "body" in error2 ? JSON.stringify(error2.body) : "";
|
|
76617
|
+
return /PAT lacks required scope:\s*publish/i.test(`${message} ${body}`);
|
|
76618
|
+
}
|
|
76619
|
+
async function runTaskCreate(cwd2, options, dependencies = {}) {
|
|
76620
|
+
const idempotencyKey = (dependencies.randomUUID ?? randomUUID2)();
|
|
76621
|
+
const message = requiredValue(options.message, "--message");
|
|
76622
|
+
const agentId = resolveAgentId(cwd2, options.agentId, dependencies.readManifest ?? readManifest);
|
|
76623
|
+
const title = optionalValue(options.title, "--title");
|
|
76624
|
+
const model = optionalValue(options.model, "--model");
|
|
76625
|
+
const input = {
|
|
76626
|
+
agent_id: agentId,
|
|
76627
|
+
initial_messages: [{ role: "user", content: message }],
|
|
76628
|
+
auto_run: true,
|
|
76629
|
+
...title ? { title } : {},
|
|
76630
|
+
...model ? { default_model: model } : {}
|
|
76631
|
+
};
|
|
76632
|
+
let created;
|
|
76633
|
+
try {
|
|
76634
|
+
created = await (dependencies.createTask ?? createTask)(input, {
|
|
76635
|
+
idempotencyKey
|
|
76636
|
+
});
|
|
76637
|
+
} catch (error2) {
|
|
76638
|
+
if (isPublishScopeError(error2)) {
|
|
76639
|
+
throw new Error("PAT lacks required scope: publish. Mint a replacement with `brainbase token create --scopes read,publish` and try again.");
|
|
76640
|
+
}
|
|
76641
|
+
throw error2;
|
|
76642
|
+
}
|
|
76643
|
+
if (options.json) {
|
|
76644
|
+
console.log(JSON.stringify({
|
|
76645
|
+
task_id: created.id,
|
|
76646
|
+
agent_id: created.agent_id,
|
|
76647
|
+
status: created.status
|
|
76648
|
+
}));
|
|
76649
|
+
return;
|
|
76650
|
+
}
|
|
76651
|
+
console.log([
|
|
76652
|
+
`Task ID: ${created.id}`,
|
|
76653
|
+
`Agent ID: ${created.agent_id}`,
|
|
76654
|
+
`Status: ${created.status}`,
|
|
76655
|
+
"First run accepted."
|
|
76656
|
+
].join(`
|
|
76657
|
+
`));
|
|
76658
|
+
}
|
|
76659
|
+
|
|
76660
|
+
// src/cli/task.ts
|
|
76661
|
+
var VALUE_FLAGS = [
|
|
76662
|
+
["--agent", "agentId"],
|
|
76663
|
+
["--message", "message"],
|
|
76664
|
+
["--title", "title"],
|
|
76665
|
+
["--model", "model"]
|
|
76666
|
+
];
|
|
76667
|
+
var TASK_OPTION_NAMES = new Set([
|
|
76668
|
+
...VALUE_FLAGS.map(([flag]) => flag),
|
|
76669
|
+
"--json"
|
|
76670
|
+
]);
|
|
76671
|
+
var HELP_FLAGS = new Set(["--help", "-h"]);
|
|
76672
|
+
function missingValueError(flag) {
|
|
76673
|
+
if (flag === "--message" || flag === "--agent") {
|
|
76674
|
+
return new Error(`${flag} is required and must not be blank.`);
|
|
76675
|
+
}
|
|
76676
|
+
return new Error(`${flag} must not be blank when provided.`);
|
|
76677
|
+
}
|
|
76678
|
+
function flagLikeValueError(flag, value) {
|
|
76679
|
+
return new Error(`${flag} requires a value. If you meant the literal "${value}", use ${flag}=${value} or ${flag} -- ${value}.`);
|
|
76680
|
+
}
|
|
76681
|
+
function parseCreateArgs(args) {
|
|
76682
|
+
const options = {};
|
|
76683
|
+
const seen = new Set;
|
|
76684
|
+
for (let index = 0;index < args.length; index += 1) {
|
|
76685
|
+
const arg = args[index];
|
|
76686
|
+
if (HELP_FLAGS.has(arg)) {
|
|
76687
|
+
return { help: true, options };
|
|
76688
|
+
}
|
|
76689
|
+
if (arg === "--json") {
|
|
76690
|
+
if (seen.has(arg)) {
|
|
76691
|
+
throw new Error(`Duplicate task create option: ${arg}`);
|
|
76692
|
+
}
|
|
76693
|
+
seen.add(arg);
|
|
76694
|
+
options.json = true;
|
|
76695
|
+
continue;
|
|
76696
|
+
}
|
|
76697
|
+
let matched = false;
|
|
76698
|
+
for (const [flag, option] of VALUE_FLAGS) {
|
|
76699
|
+
if (arg === flag) {
|
|
76700
|
+
if (seen.has(flag)) {
|
|
76701
|
+
throw new Error(`Duplicate task create option: ${flag}`);
|
|
76702
|
+
}
|
|
76703
|
+
seen.add(flag);
|
|
76704
|
+
let value = args[index + 1];
|
|
76705
|
+
if (value === undefined) {
|
|
76706
|
+
throw missingValueError(flag);
|
|
76707
|
+
}
|
|
76708
|
+
if (value === "--") {
|
|
76709
|
+
value = args[index + 2];
|
|
76710
|
+
if (value === undefined)
|
|
76711
|
+
throw missingValueError(flag);
|
|
76712
|
+
index += 1;
|
|
76713
|
+
} else if (HELP_FLAGS.has(value) && (option === "agentId" || option === "model")) {
|
|
76714
|
+
return { help: true, options };
|
|
76715
|
+
} else if (TASK_OPTION_NAMES.has(value)) {
|
|
76716
|
+
throw flagLikeValueError(flag, value);
|
|
76717
|
+
}
|
|
76718
|
+
options[option] = value;
|
|
76719
|
+
index += 1;
|
|
76720
|
+
matched = true;
|
|
76721
|
+
break;
|
|
76722
|
+
}
|
|
76723
|
+
const prefix = `${flag}=`;
|
|
76724
|
+
if (arg.startsWith(prefix)) {
|
|
76725
|
+
if (seen.has(flag)) {
|
|
76726
|
+
throw new Error(`Duplicate task create option: ${flag}`);
|
|
76727
|
+
}
|
|
76728
|
+
seen.add(flag);
|
|
76729
|
+
options[option] = arg.slice(prefix.length);
|
|
76730
|
+
matched = true;
|
|
76731
|
+
break;
|
|
76732
|
+
}
|
|
76733
|
+
}
|
|
76734
|
+
if (!matched) {
|
|
76735
|
+
throw new Error(`Unknown task create argument: ${arg}`);
|
|
76736
|
+
}
|
|
76737
|
+
}
|
|
76738
|
+
return { help: false, options };
|
|
76739
|
+
}
|
|
76740
|
+
async function runTask(cwd2, sub, args) {
|
|
76741
|
+
switch (sub) {
|
|
76742
|
+
case "create": {
|
|
76743
|
+
const parsed = parseCreateArgs(args);
|
|
76744
|
+
if (parsed.help) {
|
|
76745
|
+
printHelp3();
|
|
76746
|
+
return;
|
|
76747
|
+
}
|
|
76748
|
+
await runTaskCreate(cwd2, parsed.options);
|
|
76749
|
+
return;
|
|
76750
|
+
}
|
|
76751
|
+
case undefined:
|
|
76752
|
+
case "help":
|
|
76753
|
+
case "-h":
|
|
76754
|
+
case "--help":
|
|
76755
|
+
printHelp3();
|
|
76756
|
+
return;
|
|
76757
|
+
default:
|
|
76758
|
+
console.error(`Unknown task subcommand: ${sub}
|
|
76759
|
+
`);
|
|
76760
|
+
printHelp3();
|
|
76761
|
+
process.exit(1);
|
|
76762
|
+
}
|
|
76763
|
+
}
|
|
76764
|
+
function printHelp3() {
|
|
76765
|
+
const out = [];
|
|
76766
|
+
out.push("");
|
|
76767
|
+
out.push(` ${import_picocolors43.default.bold("brainbase task")} ${import_picocolors43.default.dim("<sub> [options]")}`);
|
|
76768
|
+
out.push("");
|
|
76769
|
+
out.push(` ${import_picocolors43.default.cyan("create")} ${import_picocolors43.default.dim("--message <text>")} ${import_picocolors43.default.dim("create a task and start its first run")}`);
|
|
76770
|
+
out.push("");
|
|
76771
|
+
out.push(` ${import_picocolors43.default.bold("create flags")}`);
|
|
76772
|
+
out.push(` ${import_picocolors43.default.dim("--message <text>")} required first user message`);
|
|
76773
|
+
out.push(` ${import_picocolors43.default.dim("--agent <id>")} override the claimed agent in brainbase.agent.yaml`);
|
|
76774
|
+
out.push(` ${import_picocolors43.default.dim("--title <text>")} optional task title`);
|
|
76775
|
+
out.push(` ${import_picocolors43.default.dim("--model <id>")} optional model override`);
|
|
76776
|
+
out.push(` ${import_picocolors43.default.dim("--json")} print task_id, agent_id, and status as JSON`);
|
|
76777
|
+
out.push("");
|
|
76778
|
+
out.push(` ${import_picocolors43.default.dim("Flag-like values:")} use ${import_picocolors43.default.cyan("--flag=value")} or ${import_picocolors43.default.cyan("--flag -- <value>")}`);
|
|
76779
|
+
out.push("");
|
|
76780
|
+
console.log(out.join(`
|
|
76781
|
+
`));
|
|
76782
|
+
}
|
|
76783
|
+
|
|
76348
76784
|
// src/index.ts
|
|
76349
76785
|
var PROTECTED = new Set([
|
|
76350
76786
|
"template",
|
|
@@ -76365,100 +76801,108 @@ var STORED_PAT_COMMANDS = new Set([
|
|
|
76365
76801
|
function help() {
|
|
76366
76802
|
const out = [];
|
|
76367
76803
|
out.push("");
|
|
76368
|
-
out.push(` ${brandTint("◆")} ${
|
|
76369
|
-
out.push(` ${
|
|
76804
|
+
out.push(` ${brandTint("◆")} ${import_picocolors44.default.bold("brainbase")} ${import_picocolors44.default.dim(`v${VERSION}`)}`);
|
|
76805
|
+
out.push(` ${import_picocolors44.default.dim("connect your local agent to the brainbase platform")}`);
|
|
76370
76806
|
out.push("");
|
|
76371
76807
|
out.push(divider("USAGE"));
|
|
76372
76808
|
out.push("");
|
|
76373
|
-
out.push(` ${
|
|
76809
|
+
out.push(` ${import_picocolors44.default.bold("brainbase")} ${import_picocolors44.default.dim("<command> [options]")}`);
|
|
76374
76810
|
out.push("");
|
|
76375
76811
|
out.push(divider("AUTH"));
|
|
76376
76812
|
out.push("");
|
|
76377
|
-
out.push(` ${
|
|
76378
|
-
out.push(` ${
|
|
76379
|
-
out.push(` ${
|
|
76813
|
+
out.push(` ${import_picocolors44.default.cyan("login")} ${import_picocolors44.default.dim(" open the web app and connect this device")}`);
|
|
76814
|
+
out.push(` ${import_picocolors44.default.cyan("logout")} ${import_picocolors44.default.dim(" clear the local session")}`);
|
|
76815
|
+
out.push(` ${import_picocolors44.default.cyan("whoami")} ${import_picocolors44.default.dim(" show the current user")}`);
|
|
76380
76816
|
out.push("");
|
|
76381
76817
|
out.push(divider("LINKED AGENT"));
|
|
76382
76818
|
out.push("");
|
|
76383
|
-
out.push(` ${
|
|
76384
|
-
out.push(` ${
|
|
76385
|
-
out.push(` ${
|
|
76386
|
-
out.push(` ${
|
|
76387
|
-
out.push(` ${
|
|
76388
|
-
out.push(` ${
|
|
76389
|
-
out.push(` ${
|
|
76390
|
-
out.push(` ${
|
|
76391
|
-
out.push(` ${
|
|
76392
|
-
out.push(` ${
|
|
76819
|
+
out.push(` ${import_picocolors44.default.cyan("agent create")} ${import_picocolors44.default.dim("claim an unclaimed brainbase.agent.yaml and create the cloud agent")}`);
|
|
76820
|
+
out.push(` ${import_picocolors44.default.cyan("agent pull")} ${import_picocolors44.default.dim("[<id>]")} ${import_picocolors44.default.dim("bring cloud changes into this folder (--force to override; --run-entrypoint to also execute the agent entrypoint)")}`);
|
|
76821
|
+
out.push(` ${import_picocolors44.default.cyan("agent push")} ${import_picocolors44.default.dim("send local changes to the cloud (--force to overwrite cloud-side conflicts with local)")}`);
|
|
76822
|
+
out.push(` ${import_picocolors44.default.cyan("agent unpack")} ${import_picocolors44.default.dim("install the claimed agent into a harness layout")}`);
|
|
76823
|
+
out.push(` ${import_picocolors44.default.cyan("link")} ${import_picocolors44.default.dim("attach this folder to an existing agent")}`);
|
|
76824
|
+
out.push(` ${import_picocolors44.default.cyan("agent status")} ${import_picocolors44.default.dim("show what would pull and what would push")}`);
|
|
76825
|
+
out.push(` ${import_picocolors44.default.cyan("agent env")} ${import_picocolors44.default.dim("print export lines for `eval $(brainbase agent env)`")}`);
|
|
76826
|
+
out.push(` ${import_picocolors44.default.cyan("run")} ${import_picocolors44.default.dim("<cmd> [args...]")} ${import_picocolors44.default.dim("run <cmd> with secrets.env loaded into env")}`);
|
|
76827
|
+
out.push(` ${import_picocolors44.default.cyan("status")} ${import_picocolors44.default.dim("show what this folder is linked to")}`);
|
|
76828
|
+
out.push(` ${import_picocolors44.default.cyan("unlink")} ${import_picocolors44.default.dim("disconnect this folder")}`);
|
|
76829
|
+
out.push("");
|
|
76830
|
+
out.push(divider("TASKS"));
|
|
76831
|
+
out.push("");
|
|
76832
|
+
out.push(` ${import_picocolors44.default.cyan("task create")} ${import_picocolors44.default.dim("--message <text>")} ${import_picocolors44.default.dim("create a managed task and start its first run")}`);
|
|
76393
76833
|
out.push("");
|
|
76394
76834
|
out.push(divider("ORCHESTRATIONS"));
|
|
76395
76835
|
out.push("");
|
|
76396
|
-
out.push(` ${
|
|
76397
|
-
out.push(` ${
|
|
76398
|
-
out.push(` ${
|
|
76399
|
-
out.push(` ${
|
|
76400
|
-
out.push(` ${
|
|
76836
|
+
out.push(` ${import_picocolors44.default.cyan("orchestration create")} ${import_picocolors44.default.dim("claim a local orchestration manifest and create it in the cloud")}`);
|
|
76837
|
+
out.push(` ${import_picocolors44.default.cyan("orchestration list")} ${import_picocolors44.default.dim("list orchestrations under a team")}`);
|
|
76838
|
+
out.push(` ${import_picocolors44.default.cyan("orchestration pull")} ${import_picocolors44.default.dim("<id>")} ${import_picocolors44.default.dim("recursively fetch an orchestration + every member agent")}`);
|
|
76839
|
+
out.push(` ${import_picocolors44.default.cyan("orchestration push")} ${import_picocolors44.default.dim("recursively push each member, then update the graph")}`);
|
|
76840
|
+
out.push(` ${import_picocolors44.default.cyan("orchestration status")} ${import_picocolors44.default.dim("show what would push and what would pull")}`);
|
|
76401
76841
|
out.push("");
|
|
76402
76842
|
out.push(divider("TEMPLATES"));
|
|
76403
76843
|
out.push("");
|
|
76404
|
-
out.push(` ${
|
|
76405
|
-
out.push(` ${
|
|
76406
|
-
out.push(` ${
|
|
76407
|
-
out.push(` ${
|
|
76408
|
-
out.push(` ${
|
|
76409
|
-
out.push(` ${
|
|
76410
|
-
out.push(` ${
|
|
76844
|
+
out.push(` ${import_picocolors44.default.cyan("template pack")} ${import_picocolors44.default.dim("bundle the current agent into a template")}`);
|
|
76845
|
+
out.push(` ${import_picocolors44.default.cyan("template publish")} ${import_picocolors44.default.dim("upload a template to the registry")}`);
|
|
76846
|
+
out.push(` ${import_picocolors44.default.cyan("template search")} ${import_picocolors44.default.dim("[query]")} ${import_picocolors44.default.dim("search the registry")}`);
|
|
76847
|
+
out.push(` ${import_picocolors44.default.cyan("template info")} ${import_picocolors44.default.dim("<creator/slug>")} ${import_picocolors44.default.dim("show registry details for a template")}`);
|
|
76848
|
+
out.push(` ${import_picocolors44.default.cyan("template onboard")} ${import_picocolors44.default.dim("<creator/slug>")} ${import_picocolors44.default.dim("install (or refresh) a template")}`);
|
|
76849
|
+
out.push(` ${import_picocolors44.default.cyan("template list")} ${import_picocolors44.default.dim("show installed templates")}`);
|
|
76850
|
+
out.push(` ${import_picocolors44.default.cyan("template remove")} ${import_picocolors44.default.dim("<creator/slug>")} ${import_picocolors44.default.dim("uninstall a template")}`);
|
|
76411
76851
|
out.push("");
|
|
76412
76852
|
out.push(divider("SKILLS"));
|
|
76413
76853
|
out.push("");
|
|
76414
|
-
out.push(` ${
|
|
76415
|
-
out.push(` ${
|
|
76416
|
-
out.push(` ${
|
|
76417
|
-
out.push(` ${
|
|
76418
|
-
out.push(` ${
|
|
76419
|
-
out.push(` ${
|
|
76420
|
-
out.push(` ${
|
|
76854
|
+
out.push(` ${import_picocolors44.default.cyan("skill add")} ${import_picocolors44.default.dim("<source>")} ${import_picocolors44.default.dim("install a skill (github / git / brainbase)")}`);
|
|
76855
|
+
out.push(` ${import_picocolors44.default.cyan("skill list")} ${import_picocolors44.default.dim("show locally installed skills + their source")}`);
|
|
76856
|
+
out.push(` ${import_picocolors44.default.cyan("skill update")} ${import_picocolors44.default.dim("<slug>")} ${import_picocolors44.default.dim("re-fetch a skill from its recorded source")}`);
|
|
76857
|
+
out.push(` ${import_picocolors44.default.cyan("skill remove")} ${import_picocolors44.default.dim("<slug>")} ${import_picocolors44.default.dim("uninstall a skill")}`);
|
|
76858
|
+
out.push(` ${import_picocolors44.default.cyan("skill search")} ${import_picocolors44.default.dim("[query]")} ${import_picocolors44.default.dim("search the brainbase skill registry")}`);
|
|
76859
|
+
out.push(` ${import_picocolors44.default.cyan("skill info")} ${import_picocolors44.default.dim("<creator/slug>")} ${import_picocolors44.default.dim("show registry details for a skill")}`);
|
|
76860
|
+
out.push(` ${import_picocolors44.default.cyan("skill publish")} ${import_picocolors44.default.dim("[dir]")} ${import_picocolors44.default.dim("publish a SKILL.md folder (defaults to .)")}`);
|
|
76421
76861
|
out.push("");
|
|
76422
76862
|
out.push(divider("CLI TOKENS"));
|
|
76423
76863
|
out.push("");
|
|
76424
|
-
out.push(` ${
|
|
76425
|
-
out.push(` ${
|
|
76426
|
-
out.push(` ${
|
|
76864
|
+
out.push(` ${import_picocolors44.default.cyan("token create")} ${import_picocolors44.default.dim("issue a long-lived CLI key for CI / scripts")}`);
|
|
76865
|
+
out.push(` ${import_picocolors44.default.cyan("token list")} ${import_picocolors44.default.dim("show your active tokens")}`);
|
|
76866
|
+
out.push(` ${import_picocolors44.default.cyan("token revoke")} ${import_picocolors44.default.dim("<id>")} ${import_picocolors44.default.dim("revoke a token")}`);
|
|
76427
76867
|
out.push("");
|
|
76428
76868
|
out.push(divider("MCP"));
|
|
76429
76869
|
out.push("");
|
|
76430
|
-
out.push(` ${
|
|
76870
|
+
out.push(` ${import_picocolors44.default.cyan("mcp check")} ${import_picocolors44.default.dim("[--json]")} ${import_picocolors44.default.dim("verify MCP server connectivity through the brainbase proxy (runs at sandbox bootstrap)")}`);
|
|
76431
76871
|
out.push("");
|
|
76432
76872
|
out.push(divider("FLAGS"));
|
|
76433
76873
|
out.push("");
|
|
76434
|
-
out.push(` ${
|
|
76435
|
-
out.push(` ${
|
|
76436
|
-
out.push(` ${
|
|
76437
|
-
out.push(` ${
|
|
76438
|
-
out.push(` ${
|
|
76439
|
-
out.push(` ${
|
|
76440
|
-
out.push(` ${
|
|
76441
|
-
out.push(` ${
|
|
76442
|
-
out.push(` ${
|
|
76874
|
+
out.push(` ${import_picocolors44.default.dim("--harness <id>")} force harness for onboard / sync (e.g. claude-code)`);
|
|
76875
|
+
out.push(` ${import_picocolors44.default.dim("--scope <s>")} force scope: global | project`);
|
|
76876
|
+
out.push(` ${import_picocolors44.default.dim("--yes, -y")} skip confirmations / auto-overwrite`);
|
|
76877
|
+
out.push(` ${import_picocolors44.default.dim("--agent <id>")} for link/task create: use this agent id explicitly`);
|
|
76878
|
+
out.push(` ${import_picocolors44.default.dim("--message <text>")} for task create: required first user message`);
|
|
76879
|
+
out.push(` ${import_picocolors44.default.dim("--title <text>")} for task create: optional task title`);
|
|
76880
|
+
out.push(` ${import_picocolors44.default.dim("--model <id>")} for task create: optional model override`);
|
|
76881
|
+
out.push(` ${import_picocolors44.default.dim("--json")} for task create/mcp check: machine-readable output`);
|
|
76882
|
+
out.push(` ${import_picocolors44.default.dim("--no-tracking")} for link: skip routing LLM traffic through brainbase`);
|
|
76883
|
+
out.push(` ${import_picocolors44.default.dim("--track")} for agent create: enable tracking non-interactively (off without a TTY)`);
|
|
76884
|
+
out.push(` ${import_picocolors44.default.dim("--shell <sh|fish>")} for agent env: pick output format (auto-detected from $SHELL)`);
|
|
76885
|
+
out.push(` ${import_picocolors44.default.dim("--all")} for template list: include installs from other folders`);
|
|
76886
|
+
out.push(` ${import_picocolors44.default.dim("--web <url>")} for login: web app URL (default https://app.brainbaselabs.com)`);
|
|
76443
76887
|
out.push("");
|
|
76444
76888
|
out.push(divider("ENV"));
|
|
76445
76889
|
out.push("");
|
|
76446
|
-
out.push(` ${
|
|
76447
|
-
out.push(` ${
|
|
76448
|
-
out.push(` ${
|
|
76449
|
-
out.push(` ${
|
|
76450
|
-
out.push(` ${
|
|
76451
|
-
out.push(` ${
|
|
76452
|
-
out.push(` ${
|
|
76453
|
-
out.push(` ${
|
|
76454
|
-
out.push(` ${
|
|
76455
|
-
out.push(` ${
|
|
76890
|
+
out.push(` ${import_picocolors44.default.dim("BRAINBASE_HOME")} override the local config dir (default ~/.brainbase)`);
|
|
76891
|
+
out.push(` ${import_picocolors44.default.dim("BRAINBASE_WEB_URL")} override the web app URL used by login`);
|
|
76892
|
+
out.push(` ${import_picocolors44.default.dim("BRAINBASE_CONTROL_PLANE_URL")} override the MAS host (/v2/cli; task create uses /v2/tasks)`);
|
|
76893
|
+
out.push(` ${import_picocolors44.default.dim("BRAINBASE_API_URL")} legacy KLS host override (uses /api/cli; proxy/registry fallback)`);
|
|
76894
|
+
out.push(` ${import_picocolors44.default.dim("BRAINBASE_PROXY_URL")} override the model-proxy URL used by harness traffic (default https://api.v1.brainbaselabs.com)`);
|
|
76895
|
+
out.push(` ${import_picocolors44.default.dim("BRAINBASE_REGISTRY_URL")} override the registry API URL (default https://api.v1.brainbaselabs.com)`);
|
|
76896
|
+
out.push(` ${import_picocolors44.default.dim("BRAINBASE_TOKEN")} long-lived CLI PAT (overrides token.json)`);
|
|
76897
|
+
out.push(` ${import_picocolors44.default.dim("BRAINBASE_SKIP_AUTH")} bypass the auth gate for development`);
|
|
76898
|
+
out.push(` ${import_picocolors44.default.dim("BRAINBASE_NON_INTERACTIVE")} force non-interactive mode — skip/auto-default prompts (CI & agents)`);
|
|
76899
|
+
out.push(` ${import_picocolors44.default.dim("BRAINBASE_RUN_ENTRYPOINT")} =1 → agent pull executes the agent entrypoint (sandbox boots; or pass --run-entrypoint)`);
|
|
76456
76900
|
out.push("");
|
|
76457
76901
|
out.push(divider("HARNESSES"));
|
|
76458
76902
|
out.push("");
|
|
76459
|
-
out.push(` ${
|
|
76460
|
-
out.push(` ${
|
|
76461
|
-
out.push(` ${
|
|
76903
|
+
out.push(` ${import_picocolors44.default.dim("•")} ${import_picocolors44.default.bold("claude-code")} ${import_picocolors44.default.dim("skills, mcps, agents, commands, playbooks, instructions, files")}`);
|
|
76904
|
+
out.push(` ${import_picocolors44.default.dim("•")} ${import_picocolors44.default.bold("codex")} ${import_picocolors44.default.dim("skills, mcps, commands, playbooks, instructions, files")}`);
|
|
76905
|
+
out.push(` ${import_picocolors44.default.dim("•")} ${import_picocolors44.default.bold("kafka")} ${import_picocolors44.default.dim("skills, mcps, agents, commands, playbooks, instructions, files")}`);
|
|
76462
76906
|
out.push("");
|
|
76463
76907
|
console.log(out.join(`
|
|
76464
76908
|
`));
|
|
@@ -76522,13 +76966,13 @@ async function requireAuth(cmd) {
|
|
|
76522
76966
|
if (STORED_PAT_COMMANDS.has(cmd) && readToken())
|
|
76523
76967
|
return;
|
|
76524
76968
|
console.error("");
|
|
76525
|
-
console.error(` ${brandTint("◆")} ${
|
|
76969
|
+
console.error(` ${brandTint("◆")} ${import_picocolors44.default.bold("brainbase")}`);
|
|
76526
76970
|
console.error("");
|
|
76527
|
-
console.error(` ${
|
|
76971
|
+
console.error(` ${import_picocolors44.default.red("✗")} You need to sign in to use ${import_picocolors44.default.bold("brainbase " + cmd)}.`);
|
|
76528
76972
|
if (status.reason)
|
|
76529
|
-
console.error(` ${
|
|
76973
|
+
console.error(` ${import_picocolors44.default.dim(status.reason)}`);
|
|
76530
76974
|
console.error("");
|
|
76531
|
-
console.error(` Run ${
|
|
76975
|
+
console.error(` Run ${import_picocolors44.default.cyan("brainbase login")} to connect this device.`);
|
|
76532
76976
|
console.error("");
|
|
76533
76977
|
process14.exit(1);
|
|
76534
76978
|
}
|
|
@@ -76551,36 +76995,37 @@ async function main() {
|
|
|
76551
76995
|
await runRun(cwd2, argv);
|
|
76552
76996
|
return;
|
|
76553
76997
|
}
|
|
76554
|
-
const
|
|
76555
|
-
const
|
|
76556
|
-
const
|
|
76557
|
-
const
|
|
76558
|
-
const
|
|
76559
|
-
const
|
|
76560
|
-
const
|
|
76561
|
-
const
|
|
76562
|
-
const
|
|
76998
|
+
const sharedArgs = cmd === "task" ? [] : argv;
|
|
76999
|
+
const yes = hasFlag2(sharedArgs, "--yes", "-y");
|
|
77000
|
+
const all = hasFlag2(sharedArgs, "--all");
|
|
77001
|
+
const harness = getFlag(sharedArgs, "--harness");
|
|
77002
|
+
const scopeFlag = getFlag(sharedArgs, "--scope");
|
|
77003
|
+
const web = getFlag(sharedArgs, "--web");
|
|
77004
|
+
const visibility = getFlag(sharedArgs, "--visibility");
|
|
77005
|
+
const category = getFlag(sharedArgs, "--category");
|
|
77006
|
+
const target = getFlag(sharedArgs, "--target");
|
|
77007
|
+
const pageRaw = getFlag(sharedArgs, "--page");
|
|
76563
77008
|
const page = pageRaw && /^\d+$/.test(pageRaw) ? Number(pageRaw) : undefined;
|
|
76564
|
-
const asSlug = getFlag(
|
|
76565
|
-
const agentFlag = getFlag(
|
|
76566
|
-
const shellFlag = getFlag(
|
|
76567
|
-
const noTracking = hasFlag2(
|
|
76568
|
-
const track = hasFlag2(
|
|
76569
|
-
const forceFlag = hasFlag2(
|
|
76570
|
-
const runEntrypointFlag = hasFlag2(
|
|
76571
|
-
const graphOnlyFlag = hasFlag2(
|
|
76572
|
-
const nameFlag = getFlag(
|
|
76573
|
-
const skillVersionFlag = getFlag(
|
|
76574
|
-
const taglineFlag = getFlag(
|
|
76575
|
-
const orgIdFlag = getFlag(
|
|
76576
|
-
const teamIdFlag = getFlag(
|
|
76577
|
-
const fromFlags = getFlagAll(
|
|
76578
|
-
const toFlags = getFlagAll(
|
|
76579
|
-
const descriptionFlag = getFlag(
|
|
76580
|
-
const schemaFlag = getFlag(
|
|
76581
|
-
const noPushFlag = hasFlag2(
|
|
76582
|
-
const jsonFlag = hasFlag2(
|
|
76583
|
-
const acpFlag = hasFlag2(
|
|
77009
|
+
const asSlug = getFlag(sharedArgs, "--as");
|
|
77010
|
+
const agentFlag = getFlag(sharedArgs, "--agent");
|
|
77011
|
+
const shellFlag = getFlag(sharedArgs, "--shell");
|
|
77012
|
+
const noTracking = hasFlag2(sharedArgs, "--no-tracking");
|
|
77013
|
+
const track = hasFlag2(sharedArgs, "--track");
|
|
77014
|
+
const forceFlag = hasFlag2(sharedArgs, "--force");
|
|
77015
|
+
const runEntrypointFlag = hasFlag2(sharedArgs, "--run-entrypoint");
|
|
77016
|
+
const graphOnlyFlag = hasFlag2(sharedArgs, "--graph-only");
|
|
77017
|
+
const nameFlag = getFlag(sharedArgs, "--name");
|
|
77018
|
+
const skillVersionFlag = getFlag(sharedArgs, "--skill-version");
|
|
77019
|
+
const taglineFlag = getFlag(sharedArgs, "--tagline");
|
|
77020
|
+
const orgIdFlag = getFlag(sharedArgs, "--org");
|
|
77021
|
+
const teamIdFlag = getFlag(sharedArgs, "--team");
|
|
77022
|
+
const fromFlags = getFlagAll(sharedArgs, "--from");
|
|
77023
|
+
const toFlags = getFlagAll(sharedArgs, "--to");
|
|
77024
|
+
const descriptionFlag = getFlag(sharedArgs, "--description");
|
|
77025
|
+
const schemaFlag = getFlag(sharedArgs, "--schema");
|
|
77026
|
+
const noPushFlag = hasFlag2(sharedArgs, "--no-push");
|
|
77027
|
+
const jsonFlag = hasFlag2(sharedArgs, "--json");
|
|
77028
|
+
const acpFlag = hasFlag2(sharedArgs, "--acp");
|
|
76584
77029
|
ensureSkillResolversRegistered();
|
|
76585
77030
|
await requireAuth(cmd);
|
|
76586
77031
|
try {
|
|
@@ -76667,6 +77112,11 @@ async function main() {
|
|
|
76667
77112
|
});
|
|
76668
77113
|
break;
|
|
76669
77114
|
}
|
|
77115
|
+
case "task": {
|
|
77116
|
+
const sub = argv.shift();
|
|
77117
|
+
await runTask(cwd2, sub, argv);
|
|
77118
|
+
break;
|
|
77119
|
+
}
|
|
76670
77120
|
case "orchestration":
|
|
76671
77121
|
case "orch": {
|
|
76672
77122
|
const sub = argv.shift();
|
|
@@ -76706,7 +77156,7 @@ async function main() {
|
|
|
76706
77156
|
process14.exit(1);
|
|
76707
77157
|
}
|
|
76708
77158
|
} catch (err) {
|
|
76709
|
-
console.error(
|
|
77159
|
+
console.error(import_picocolors44.default.red(`
|
|
76710
77160
|
${err.message}`));
|
|
76711
77161
|
if (process14.env.BRAINBASE_DEBUG)
|
|
76712
77162
|
console.error(err.stack);
|