@agentbridge1/cli 0.0.2 → 0.0.4

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.
@@ -1,6 +1,6 @@
1
1
  {
2
- "builtAt": "2026-06-01T12:37:10.739Z",
3
- "gitHead": "6278b82",
4
- "sourceLatestMtime": "2026-06-01T12:30:06.968Z",
5
- "sourceLatestFile": "src/commands/verify.ts"
2
+ "builtAt": "2026-06-02T04:55:04.008Z",
3
+ "gitHead": "86fed7f",
4
+ "sourceLatestMtime": "2026-06-02T04:51:46.614Z",
5
+ "sourceLatestFile": "src/commands/connect.ts"
6
6
  }
@@ -7,38 +7,71 @@ const http_1 = require("../http");
7
7
  function resolveBaseUrl(override) {
8
8
  return (override ??
9
9
  process.env.AGENTBRIDGE_BASE_URL ??
10
- "https://agentauth-api-production.up.railway.app");
10
+ config_1.DEFAULT_API_BASE_URL);
11
11
  }
12
12
  async function verifyCredentials(projectId, apiKey, apiBaseUrl) {
13
- const url = `${apiBaseUrl}/v1/dev/projects/${projectId}/health`;
14
- let res;
15
- try {
16
- res = await fetch(url, {
17
- method: "GET",
18
- headers: {
19
- Authorization: `Bearer ${apiKey}`,
20
- "Content-Type": "application/json",
21
- },
22
- });
13
+ const summaryUrl = `${apiBaseUrl}/v1/dev/projects/${projectId}/summary`;
14
+ const packetUrl = `${apiBaseUrl}/v1/dev/projects/${projectId}/packet`;
15
+ const headers = {
16
+ Authorization: `Bearer ${apiKey}`,
17
+ "Content-Type": "application/json",
18
+ };
19
+ async function get(url) {
20
+ try {
21
+ return await fetch(url, { method: "GET", headers });
22
+ }
23
+ catch (e) {
24
+ const msg = e instanceof Error ? e.message : String(e);
25
+ throw new errors_1.SafeCliError(`Could not reach AgentBridge server at ${apiBaseUrl}.\nNetwork error: ${msg}\n\nCheck your AGENTBRIDGE_BASE_URL or internet connection.`);
26
+ }
23
27
  }
24
- catch (e) {
25
- const msg = e instanceof Error ? e.message : String(e);
26
- throw new errors_1.SafeCliError(`Could not reach AgentBridge server at ${apiBaseUrl}.\nNetwork error: ${msg}\n\nCheck your AGENTBRIDGE_BASE_URL or internet connection.`);
28
+ async function readBody(res) {
29
+ try {
30
+ return await res.text();
31
+ }
32
+ catch {
33
+ return "";
34
+ }
27
35
  }
28
- if (res.status === 401 || res.status === 403) {
29
- throw new errors_1.SafeCliError(`API key rejected (HTTP ${res.status}).\n\nGet a valid key at https://agentbridge.dev/dashboard and set AGENTBRIDGE_API_KEY.`);
36
+ function isRouteMissing(body) {
37
+ return body.toLowerCase().includes("route not found");
30
38
  }
31
- if (res.status === 404) {
32
- throw new errors_1.SafeCliError(`Project ${projectId} not found (HTTP 404).\n\nConfirm AGENTBRIDGE_PROJECT_ID is correct for this project.`);
39
+ async function throwAuthOrNotFound(res) {
40
+ if (res.status === 401 || res.status === 403) {
41
+ throw new errors_1.SafeCliError(`API key rejected (HTTP ${res.status}).\n\nGet a valid key at https://agentbridge.dev/dashboard and set AGENTBRIDGE_API_KEY.`);
42
+ }
43
+ if (res.status === 404) {
44
+ throw new errors_1.SafeCliError(`Project not found or key has no access on ${apiBaseUrl}.\nCheck project ID, API key, and backend URL.`);
45
+ }
46
+ const text = await readBody(res);
47
+ throw new http_1.CliHttpError(`GET ${summaryUrl} failed (${res.status}): ${text || "<empty>"}`, res.status, text);
48
+ }
49
+ let res;
50
+ res = await get(summaryUrl);
51
+ if (res.ok) {
52
+ const body = (await res.json());
53
+ return {
54
+ projectName: body.project_name ?? body.projectName ?? projectId,
55
+ agentCount: typeof body.agent_count === "number"
56
+ ? body.agent_count
57
+ : Array.isArray(body.agents)
58
+ ? body.agents.length
59
+ : 0,
60
+ };
33
61
  }
34
- if (!res.ok) {
35
- const text = await res.text();
36
- throw new http_1.CliHttpError(`GET ${url} failed (${res.status}): ${text || "<empty>"}`, res.status, text);
62
+ const summaryBody = await readBody(res);
63
+ if (!(res.status === 404 && isRouteMissing(summaryBody))) {
64
+ await throwAuthOrNotFound(res);
37
65
  }
38
- const body = (await res.json());
66
+ // Backward compatibility for servers that haven't shipped /summary yet.
67
+ const packetRes = await get(packetUrl);
68
+ if (!packetRes.ok) {
69
+ await throwAuthOrNotFound(packetRes);
70
+ }
71
+ const packetBody = (await packetRes.json());
39
72
  return {
40
- projectName: body.projectName ?? projectId,
41
- agentCount: Array.isArray(body.agents) ? body.agents.length : 0,
73
+ projectName: packetBody.project_name ?? projectId,
74
+ agentCount: 0,
42
75
  };
43
76
  }
44
77
  async function listAgents(projectId, apiKey, apiBaseUrl) {
@@ -98,7 +131,7 @@ async function runConnect(options = {}) {
98
131
  ].join("\n"));
99
132
  process.exit(1);
100
133
  }
101
- process.stdout.write(`Connecting to project ${projectId} … `);
134
+ process.stdout.write(`Connecting to project ${projectId} at ${apiBaseUrl} … `);
102
135
  let projectName;
103
136
  let agentCount;
104
137
  try {
@@ -86,6 +86,12 @@ function extractHttpReason(error) {
86
86
  }
87
87
  return `http_${error.status}`;
88
88
  }
89
+ function recoveryRequiredByPacket(packet) {
90
+ if (!packet || packet.project_mode !== "recovery")
91
+ return false;
92
+ const status = packet.recovery_status ?? null;
93
+ return status === "baseline_required" || status === "pending" || status === null;
94
+ }
89
95
  async function checkProjectAccess(ctx) {
90
96
  if (!ctx.configComplete) {
91
97
  return {
@@ -97,8 +103,8 @@ async function checkProjectAccess(ctx) {
97
103
  const apiKey = ctx.apiKey;
98
104
  const apiBaseUrl = ctx.apiBaseUrl;
99
105
  try {
100
- await (0, http_1.getJson)({ projectId, apiKey, apiBaseUrl, apiKeySource: "config" }, `/v1/dev/projects/${encodeURIComponent(projectId)}/packet`);
101
- return { status: "ok" };
106
+ const packet = await (0, http_1.getJson)({ projectId, apiKey, apiBaseUrl, apiKeySource: "config" }, `/v1/dev/projects/${encodeURIComponent(projectId)}/packet`);
107
+ return { status: "ok", packet };
102
108
  }
103
109
  catch (error) {
104
110
  if (error instanceof http_1.CliHttpError) {
@@ -176,7 +182,7 @@ async function runDoctor(cliRootOverride) {
176
182
  const resolvedApiKey = process.env.AGENTBRIDGE_API_KEY ?? cfg.apiKey;
177
183
  const resolvedBaseUrl = process.env.AGENTBRIDGE_BASE_URL ??
178
184
  cfg.apiBaseUrl ??
179
- "https://agentauth-api-production.up.railway.app";
185
+ config_1.DEFAULT_API_BASE_URL;
180
186
  const resolvedAgentId = process.env.AGENTBRIDGE_AGENT_ID ?? cfg.activeAgentId;
181
187
  const projectIdPresent = Boolean(resolvedProjectId);
182
188
  const apiKeyPresent = Boolean(resolvedApiKey);
@@ -251,10 +257,9 @@ async function runDoctor(cliRootOverride) {
251
257
  productStatus = "active_work_found";
252
258
  }
253
259
  else {
254
- productStatus =
255
- cfg.domains && cfg.domains.length > 0
256
- ? "ready"
257
- : "needs_recover";
260
+ productStatus = recoveryRequiredByPacket(projectAccess.packet)
261
+ ? "needs_recover"
262
+ : "ready";
258
263
  }
259
264
  }
260
265
  lines.push("");
@@ -21,10 +21,18 @@ function resolveNetworkContext() {
21
21
  }
22
22
  function renderRecoverOutput(packet) {
23
23
  const lines = [];
24
+ const domainCount = packet.domains_summary.length;
25
+ const ruleCount = packet.global_rules?.length ?? 0;
26
+ const hasCharterContext = Boolean(packet.charter_summary?.purpose);
24
27
  lines.push("Project recovered.");
25
28
  lines.push("");
26
29
  lines.push(`Project: ${packet.project_name ?? packet.project_id}`);
27
- if (packet.domains_summary.length > 0) {
30
+ lines.push("");
31
+ lines.push("Recovered artifacts:");
32
+ lines.push(`- Domains: ${domainCount}`);
33
+ lines.push(`- Project rules: ${ruleCount}`);
34
+ lines.push(`- Charter context: ${hasCharterContext ? "yes" : "no"}`);
35
+ if (domainCount > 0) {
28
36
  lines.push("");
29
37
  lines.push("Domains found:");
30
38
  for (const domain of packet.domains_summary) {
@@ -50,6 +58,26 @@ function renderRecoverOutput(packet) {
50
58
  lines.push("");
51
59
  return lines.join("\n");
52
60
  }
61
+ function recoveryStatusLabel(packet) {
62
+ return packet.recovery_status ?? "unknown";
63
+ }
64
+ function baselineRequired(packet) {
65
+ const status = packet.recovery_status ?? null;
66
+ if (packet.project_mode !== "recovery")
67
+ return false;
68
+ return status === "baseline_required" || status === "pending" || status === null;
69
+ }
70
+ function renderRecoveryStatusBlock(input) {
71
+ const lines = [];
72
+ lines.push(`Project: ${input.projectId}`);
73
+ lines.push(`Recovery status before: ${recoveryStatusLabel(input.before)}`);
74
+ lines.push(`Action: ${input.action}`);
75
+ lines.push(`Recovery status after: ${recoveryStatusLabel(input.after)}`);
76
+ lines.push("Next:");
77
+ lines.push(` ${input.next}`);
78
+ lines.push("");
79
+ return lines.join("\n");
80
+ }
53
81
  async function runRecover(options = {}) {
54
82
  process.exitCode = 0;
55
83
  process.stdout.write([
@@ -91,26 +119,42 @@ async function runRecover(options = {}) {
91
119
  process.exitCode = 1;
92
120
  return;
93
121
  }
94
- const alreadyRecovered = (packet.domains_summary?.length ?? 0) > 0 ||
95
- (packet.recovery_status !== null &&
96
- packet.recovery_status !== undefined &&
97
- packet.recovery_status !== "pending");
98
- if (!options.force && alreadyRecovered) {
99
- const repoRoot = (0, node_process_1.cwd)();
100
- (0, gates_1.ensureGitignoreSessionEntry)(repoRoot);
101
- (0, gates_1.ensureGatesFile)(repoRoot);
102
- process.stdout.write("Project context already exists.\n\n");
103
- process.stdout.write(renderRecoverOutput(packet));
104
- return;
105
- }
106
- if (!alreadyRecovered) {
107
- process.stdout.write("No baseline found. Building recovery baseline now...\n");
122
+ const beforePacket = packet;
123
+ const needsRecovery = baselineRequired(beforePacket);
124
+ let actionTaken = "baseline already exists; no rebuild needed";
125
+ if (needsRecovery || options.force) {
126
+ actionTaken = needsRecovery
127
+ ? "build recovery baseline from repository evidence"
128
+ : "force-refresh recovery baseline from repository evidence";
129
+ process.stdout.write("Building recovery baseline now...\n");
108
130
  await (0, init_1.runBootstrapRecovery)(ctx);
109
131
  packet = await (0, server_sync_1.fetchProjectPacket)(ctx);
110
132
  }
111
- // force mode or partial state: show current state
133
+ const afterPacket = packet;
134
+ if (baselineRequired(afterPacket)) {
135
+ process.stderr.write([
136
+ "Recovery could not complete: baseline still required.",
137
+ "",
138
+ renderRecoveryStatusBlock({
139
+ projectId: ctx.projectId,
140
+ before: beforePacket,
141
+ after: afterPacket,
142
+ action: actionTaken,
143
+ next: "agentbridge doctor",
144
+ }),
145
+ ].join("\n"));
146
+ process.exitCode = 1;
147
+ return;
148
+ }
112
149
  const repoRoot = (0, node_process_1.cwd)();
113
150
  (0, gates_1.ensureGitignoreSessionEntry)(repoRoot);
114
151
  (0, gates_1.ensureGatesFile)(repoRoot);
152
+ process.stdout.write(renderRecoveryStatusBlock({
153
+ projectId: ctx.projectId,
154
+ before: beforePacket,
155
+ after: afterPacket,
156
+ action: actionTaken,
157
+ next: "agentbridge start",
158
+ }));
115
159
  process.stdout.write(renderRecoverOutput(packet));
116
160
  }
package/dist/config.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.CONFIG_PATH = exports.CONFIG_DIR = void 0;
3
+ exports.DEFAULT_API_BASE_URL = exports.CONFIG_PATH = exports.CONFIG_DIR = void 0;
4
4
  exports.readConfig = readConfig;
5
5
  exports.writeConfig = writeConfig;
6
6
  exports.updateConfig = updateConfig;
@@ -9,6 +9,7 @@ const node_fs_1 = require("node:fs");
9
9
  const node_path_1 = require("node:path");
10
10
  exports.CONFIG_DIR = ".agentbridge";
11
11
  exports.CONFIG_PATH = (0, node_path_1.resolve)(process.cwd(), exports.CONFIG_DIR, "config.json");
12
+ exports.DEFAULT_API_BASE_URL = "https://agentauth-api-production.up.railway.app";
12
13
  function ensureConfigDir() {
13
14
  (0, node_fs_1.mkdirSync)((0, node_path_1.resolve)(process.cwd(), exports.CONFIG_DIR), { recursive: true });
14
15
  }
@@ -33,7 +34,7 @@ function contextFromConfig() {
33
34
  const cfg = readConfig();
34
35
  const apiBaseUrl = process.env.AGENTBRIDGE_BASE_URL ??
35
36
  cfg.apiBaseUrl ??
36
- "https://agentauth-api-production.up.railway.app";
37
+ exports.DEFAULT_API_BASE_URL;
37
38
  const apiKey = process.env.AGENTBRIDGE_API_KEY ?? cfg.apiKey;
38
39
  const projectId = process.env.AGENTBRIDGE_PROJECT_ID ?? cfg.projectId;
39
40
  if (!apiBaseUrl || !apiKey || !projectId) {
package/dist/index.js CHANGED
@@ -221,7 +221,7 @@ function resolveInitContext(overrides) {
221
221
  const apiBaseUrl = overrides.apiBaseUrl ??
222
222
  process.env.AGENTBRIDGE_BASE_URL ??
223
223
  cfg.apiBaseUrl ??
224
- "https://agentauth-api-production.up.railway.app";
224
+ config_1.DEFAULT_API_BASE_URL;
225
225
  if (!projectId) {
226
226
  throw (0, errors_1.catalogCliError)("CONFIG_INCOMPLETE");
227
227
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agentbridge1/cli",
3
- "version": "0.0.2",
3
+ "version": "0.0.4",
4
4
  "description": "CLI for AgentBridge — structured AI agent work sessions with domain authority and approval gates",
5
5
  "type": "commonjs",
6
6
  "bin": {