@buildautomaton/cli 0.1.47 → 0.1.48

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/cli.js CHANGED
@@ -25174,7 +25174,7 @@ var {
25174
25174
  } = import_index.default;
25175
25175
 
25176
25176
  // src/cli-version.ts
25177
- var CLI_VERSION = "0.1.47".length > 0 ? "0.1.47" : "0.0.0-dev";
25177
+ var CLI_VERSION = "0.1.48".length > 0 ? "0.1.48" : "0.0.0-dev";
25178
25178
 
25179
25179
  // src/cli/defaults.ts
25180
25180
  var DEFAULT_API_URL = process.env.BUILDAUTOMATON_API_URL ?? "https://api.buildautomaton.com";
@@ -25477,6 +25477,72 @@ function createCliE2eeRuntime(key) {
25477
25477
  };
25478
25478
  }
25479
25479
 
25480
+ // src/lib/e2ee/decrypt-stored-e2ee-content.ts
25481
+ function parseJsonObject(raw) {
25482
+ try {
25483
+ const parsed = JSON.parse(raw);
25484
+ if (parsed !== null && typeof parsed === "object" && !Array.isArray(parsed)) {
25485
+ return parsed;
25486
+ }
25487
+ } catch {
25488
+ return null;
25489
+ }
25490
+ return null;
25491
+ }
25492
+ function storedStringHasE2eeEnvelope(raw) {
25493
+ const record2 = parseJsonObject(raw);
25494
+ return record2 != null && isE2eeEnvelope(record2.ee);
25495
+ }
25496
+ function e2eeKeyIdFromStoredString(raw) {
25497
+ const record2 = parseJsonObject(raw);
25498
+ if (record2 != null && isE2eeEnvelope(record2.ee)) return record2.ee.k;
25499
+ return null;
25500
+ }
25501
+ function decryptStoredE2eeRecord(record2, e2ee) {
25502
+ if (!isE2eeEnvelope(record2.ee)) return record2;
25503
+ if (!e2ee) {
25504
+ throw new Error(`E2EE_REQUIRED:${record2.ee.k}`);
25505
+ }
25506
+ if (record2.ee.k !== e2ee.keyId) {
25507
+ throw new Error(`E2EE_KEY_MISMATCH:encrypted=${record2.ee.k}:cli=${e2ee.keyId}`);
25508
+ }
25509
+ return e2ee.decryptMessage(record2);
25510
+ }
25511
+ function formatCliE2eeDecryptError(error40, e2ee) {
25512
+ const message = error40 instanceof Error ? error40.message : String(error40);
25513
+ const required2 = /^E2EE_REQUIRED:(.+)$/.exec(message.trim());
25514
+ if (required2) {
25515
+ const keyId = required2[1]?.trim() || "unknown";
25516
+ return `Parent session content is encrypted (key ${keyId}) but this bridge was not started with E2EE certificates. Restart the CLI with your E2EE certificate to read fork parent history.`;
25517
+ }
25518
+ const mismatch = /^E2EE_KEY_MISMATCH:encrypted=(.+):cli=(.*)$/.exec(message.trim());
25519
+ if (mismatch) {
25520
+ const encryptedKeyId = mismatch[1]?.trim() || "unknown";
25521
+ const cliKeyId = mismatch[2]?.trim() || e2ee?.keyId || "none";
25522
+ return `Parent session content is encrypted with key ${encryptedKeyId}, but this bridge certificate key is ${cliKeyId}. Use the same E2EE certificate that was used for the parent session.`;
25523
+ }
25524
+ if (message.includes("E2EE key mismatch")) {
25525
+ return `Parent session content could not be decrypted: ${message}`;
25526
+ }
25527
+ return `Parent session content could not be decrypted: ${message}`;
25528
+ }
25529
+ function decryptCliE2eeTranscriptPayload(payload, e2ee) {
25530
+ const record2 = parseJsonObject(payload);
25531
+ if (!record2 || !isE2eeEnvelope(record2.ee)) return payload;
25532
+ const decrypted = decryptStoredE2eeRecord(record2, e2ee);
25533
+ if (typeof decrypted.payload === "string") return decrypted.payload;
25534
+ return JSON.stringify(decrypted.payload ?? decrypted);
25535
+ }
25536
+ function decryptCliE2eeMessageField(payload, field, e2ee) {
25537
+ if (payload == null) return null;
25538
+ const record2 = parseJsonObject(payload);
25539
+ if (!record2 || !isE2eeEnvelope(record2.ee)) return payload;
25540
+ const decrypted = decryptStoredE2eeRecord(record2, e2ee);
25541
+ const value = decrypted[field];
25542
+ if (value == null) return null;
25543
+ return typeof value === "string" ? value : JSON.stringify(value);
25544
+ }
25545
+
25480
25546
  // src/e2e-certificates/certificates.ts
25481
25547
  var E2E_CERTIFICATE_ALGORITHM = "A1";
25482
25548
  var CERTIFICATE_FILE_EXTENSIONS = /* @__PURE__ */ new Set([".pem", ".key", ".crt"]);
@@ -36081,54 +36147,101 @@ function buildForkedSessionAgentPrompt(userPrompt, childSessionId, parentSession
36081
36147
  ].join("\n");
36082
36148
  }
36083
36149
 
36084
- // src/mcp/tools/session-history/fetch-parent-session-cloud.ts
36150
+ // src/mcp/tools/session-history/cloud/internal-api.ts
36085
36151
  function internalApiBase(cloudApiBaseUrl) {
36086
36152
  return cloudApiBaseUrl.replace(/\/+$/, "");
36087
36153
  }
36088
- async function fetchCloudSessionMeta(params) {
36154
+ async function fetchInternalApiJson(params) {
36089
36155
  const token = params.getCloudAccessToken();
36090
36156
  if (!token) return { ok: false, error: "Missing cloud access token." };
36091
- const url2 = `${internalApiBase(params.cloudApiBaseUrl)}/internal/sessions/${encodeURIComponent(params.sessionId)}/meta`;
36157
+ const url2 = `${internalApiBase(params.cloudApiBaseUrl)}${params.path}`;
36092
36158
  const res = await fetch(url2, { headers: { Authorization: `Bearer ${token}` } });
36093
36159
  if (!res.ok) {
36094
36160
  const t = await res.text().catch(() => "");
36095
- return { ok: false, error: `Session meta fetch failed (${res.status}): ${t.slice(0, 200)}` };
36161
+ return { ok: false, error: `${params.errorLabel} (${res.status}): ${t.slice(0, 200)}` };
36096
36162
  }
36097
36163
  const data = await res.json().catch(() => null);
36098
- if (!data) return { ok: false, error: "Invalid session meta response." };
36164
+ if (!data) return { ok: false, error: `Invalid ${params.errorLabel.toLowerCase()} response.` };
36099
36165
  return { ok: true, data };
36100
36166
  }
36101
- async function fetchCloudParentSessionPrompts(params) {
36102
- const token = params.getCloudAccessToken();
36103
- if (!token) return { ok: false, error: "Missing cloud access token." };
36104
- const url2 = `${internalApiBase(params.cloudApiBaseUrl)}/internal/sessions/${encodeURIComponent(params.childSessionId)}/parent/prompts`;
36105
- const res = await fetch(url2, { headers: { Authorization: `Bearer ${token}` } });
36106
- if (!res.ok) {
36107
- const t = await res.text().catch(() => "");
36108
- return { ok: false, error: `Parent prompts fetch failed (${res.status}): ${t.slice(0, 200)}` };
36167
+
36168
+ // src/mcp/tools/session-history/cloud/fetch-session-meta.ts
36169
+ async function fetchCloudSessionMeta(params) {
36170
+ return fetchInternalApiJson({
36171
+ ...params,
36172
+ path: `/internal/sessions/${encodeURIComponent(params.sessionId)}/meta`,
36173
+ errorLabel: "Session meta fetch failed"
36174
+ });
36175
+ }
36176
+
36177
+ // src/mcp/tools/session-history/cloud/decrypt-parent-prompt-turns.ts
36178
+ function assertE2eeRuntimeForEnvelope(raw, e2ee) {
36179
+ if (storedStringHasE2eeEnvelope(raw) && !e2ee) {
36180
+ throw new Error(`E2EE_REQUIRED:${e2eeKeyIdFromStoredString(raw) ?? "unknown"}`);
36109
36181
  }
36110
- const data = await res.json().catch(() => null);
36111
- if (!data) return { ok: false, error: "Invalid parent prompts response." };
36112
- return { ok: true, data };
36113
36182
  }
36114
- async function fetchCloudParentTurnTranscript(params) {
36115
- const token = params.getCloudAccessToken();
36116
- if (!token) return { ok: false, error: "Missing cloud access token." };
36117
- const url2 = `${internalApiBase(params.cloudApiBaseUrl)}/internal/sessions/${encodeURIComponent(params.childSessionId)}/parent/turns/${encodeURIComponent(params.turnId)}/transcript`;
36118
- const res = await fetch(url2, { headers: { Authorization: `Bearer ${token}` } });
36119
- if (!res.ok) {
36120
- const t = await res.text().catch(() => "");
36121
- return { ok: false, error: `Transcript fetch failed (${res.status}): ${t.slice(0, 200)}` };
36183
+ function decryptParentPromptTurns(turns, e2ee) {
36184
+ return turns.map((turn) => {
36185
+ const promptRaw = typeof turn.promptText === "string" ? turn.promptText : null;
36186
+ const titleRaw = typeof turn.title === "string" ? turn.title : null;
36187
+ if (promptRaw) assertE2eeRuntimeForEnvelope(promptRaw, e2ee);
36188
+ if (titleRaw) assertE2eeRuntimeForEnvelope(titleRaw, e2ee);
36189
+ return {
36190
+ ...turn,
36191
+ promptText: decryptCliE2eeMessageField(promptRaw, "prompt", e2ee),
36192
+ title: decryptCliE2eeMessageField(titleRaw, "title", e2ee)
36193
+ };
36194
+ });
36195
+ }
36196
+
36197
+ // src/mcp/tools/session-history/cloud/fetch-parent-prompts.ts
36198
+ async function fetchCloudParentSessionPrompts(params) {
36199
+ const fetched = await fetchInternalApiJson({
36200
+ ...params,
36201
+ path: `/internal/sessions/${encodeURIComponent(params.childSessionId)}/parent/prompts`,
36202
+ errorLabel: "Parent prompts fetch failed"
36203
+ });
36204
+ if (!fetched.ok) return fetched;
36205
+ const turns = Array.isArray(fetched.data.turns) ? fetched.data.turns : [];
36206
+ try {
36207
+ const decryptedTurns = decryptParentPromptTurns(turns, params.e2ee);
36208
+ return { ok: true, data: { ...fetched.data, turns: decryptedTurns } };
36209
+ } catch (error40) {
36210
+ return { ok: false, error: formatCliE2eeDecryptError(error40, params.e2ee) };
36122
36211
  }
36123
- const data = await res.json().catch(() => null);
36124
- const rows = Array.isArray(data?.transcript) ? data.transcript : [];
36212
+ }
36213
+
36214
+ // src/mcp/tools/session-history/cloud/format-parent-transcript-text.ts
36215
+ function formatParentTranscriptText(rows, e2ee) {
36125
36216
  const lines = rows.map((row) => {
36126
36217
  const kind = typeof row.kind === "string" ? row.kind : "event";
36127
- const payload = typeof row.payload === "string" ? row.payload : JSON.stringify(row.payload ?? "");
36218
+ const rawPayload = typeof row.payload === "string" ? row.payload : JSON.stringify(row.payload ?? "");
36219
+ if (storedStringHasE2eeEnvelope(rawPayload) && !e2ee) {
36220
+ throw new Error(`E2EE_REQUIRED:${e2eeKeyIdFromStoredString(rawPayload) ?? "unknown"}`);
36221
+ }
36222
+ const payload = decryptCliE2eeTranscriptPayload(rawPayload, e2ee);
36128
36223
  return `[${kind}] ${payload}`;
36129
36224
  });
36130
- return { ok: true, text: lines.join("\n") };
36225
+ return lines.join("\n");
36226
+ }
36227
+
36228
+ // src/mcp/tools/session-history/cloud/fetch-parent-transcript.ts
36229
+ async function fetchCloudParentTurnTranscript(params) {
36230
+ const fetched = await fetchInternalApiJson({
36231
+ ...params,
36232
+ path: `/internal/sessions/${encodeURIComponent(params.childSessionId)}/parent/turns/${encodeURIComponent(params.turnId)}/transcript`,
36233
+ errorLabel: "Transcript fetch failed"
36234
+ });
36235
+ if (!fetched.ok) return fetched;
36236
+ const rows = Array.isArray(fetched.data.transcript) ? fetched.data.transcript : [];
36237
+ try {
36238
+ return { ok: true, text: formatParentTranscriptText(rows, params.e2ee) };
36239
+ } catch (error40) {
36240
+ return { ok: false, error: formatCliE2eeDecryptError(error40, params.e2ee) };
36241
+ }
36131
36242
  }
36243
+
36244
+ // src/mcp/tools/session-history/cloud/resolve-parent-session-id.ts
36132
36245
  async function resolveParentSessionIdForChild(params) {
36133
36246
  const meta = await fetchCloudSessionMeta({
36134
36247
  sessionId: params.childSessionId,
@@ -42423,9 +42536,74 @@ async function warmupAgentCapabilitiesOnConnect(params) {
42423
42536
  })();
42424
42537
  }
42425
42538
 
42426
- // src/mcp/tools/session-history/fork-session-mcp-tools.ts
42539
+ // src/mcp/tools/session-history/fork/mcp-text-result.ts
42540
+ function mcpTextResult(text, isError = false) {
42541
+ return { content: [{ type: "text", text }], ...isError ? { isError: true } : {} };
42542
+ }
42543
+
42544
+ // src/mcp/tools/session-history/fork/call-get-parent-session-turn-transcript.ts
42545
+ async function callGetParentSessionTurnTranscriptTool(ctx, cloud, childSessionId, args) {
42546
+ const turnId = typeof args.turnId === "string" ? args.turnId.trim() : "";
42547
+ if (!turnId) return mcpTextResult("turnId is required.", true);
42548
+ const transcript = await fetchCloudParentTurnTranscript({
42549
+ childSessionId,
42550
+ turnId,
42551
+ cloudApiBaseUrl: cloud.cloudApiBaseUrl,
42552
+ getCloudAccessToken: cloud.getCloudAccessToken,
42553
+ e2ee: ctx.e2ee
42554
+ });
42555
+ if (!transcript.ok) return mcpTextResult(transcript.error, true);
42556
+ return mcpTextResult(transcript.text);
42557
+ }
42558
+
42559
+ // src/mcp/tools/session-history/fork/call-list-parent-session-prompts.ts
42560
+ async function callListParentSessionPromptsTool(ctx, cloud, childSessionId, parentSessionId) {
42561
+ const detail = await fetchCloudParentSessionPrompts({
42562
+ childSessionId,
42563
+ cloudApiBaseUrl: cloud.cloudApiBaseUrl,
42564
+ getCloudAccessToken: cloud.getCloudAccessToken,
42565
+ e2ee: ctx.e2ee
42566
+ });
42567
+ if (!detail.ok) return mcpTextResult(detail.error, true);
42568
+ const turns = Array.isArray(detail.data.turns) ? detail.data.turns : [];
42569
+ const payload = turns.map((t) => ({
42570
+ turnId: typeof t.turnId === "string" ? t.turnId : "",
42571
+ title: typeof t.title === "string" ? t.title : null,
42572
+ status: typeof t.status === "string" ? t.status : null,
42573
+ promptText: typeof t.promptText === "string" ? t.promptText : null
42574
+ }));
42575
+ return mcpTextResult(JSON.stringify({ parentSessionId, turns: payload }, null, 2));
42576
+ }
42577
+
42578
+ // src/mcp/tools/session-history/fork/tool-names.ts
42427
42579
  var LIST_PARENT_SESSION_PROMPTS_TOOL = "list_parent_session_prompts";
42428
42580
  var GET_PARENT_SESSION_TURN_TRANSCRIPT_TOOL = "get_parent_session_turn_transcript";
42581
+
42582
+ // src/mcp/tools/session-history/fork/call-fork-session-mcp-tool.ts
42583
+ async function callForkSessionMcpTool(ctx, cloud, name, args) {
42584
+ const childSessionId = ctx.sessionId.trim();
42585
+ if (!childSessionId) {
42586
+ return mcpTextResult("sessionId is required.", true);
42587
+ }
42588
+ const parentResolved = await resolveParentSessionIdForChild({
42589
+ childSessionId,
42590
+ cloudApiBaseUrl: cloud.cloudApiBaseUrl,
42591
+ getCloudAccessToken: cloud.getCloudAccessToken
42592
+ });
42593
+ if (!parentResolved.ok) {
42594
+ return mcpTextResult(parentResolved.error, true);
42595
+ }
42596
+ const parentSessionId = parentResolved.parentSessionId;
42597
+ if (name === LIST_PARENT_SESSION_PROMPTS_TOOL) {
42598
+ return callListParentSessionPromptsTool(ctx, cloud, childSessionId, parentSessionId);
42599
+ }
42600
+ if (name === GET_PARENT_SESSION_TURN_TRANSCRIPT_TOOL) {
42601
+ return callGetParentSessionTurnTranscriptTool(ctx, cloud, childSessionId, args);
42602
+ }
42603
+ return mcpTextResult(`Unknown fork session tool: ${name}`, true);
42604
+ }
42605
+
42606
+ // src/mcp/tools/session-history/fork/tool-definitions.ts
42429
42607
  var SESSION_ID_SCHEMA = {
42430
42608
  type: "string",
42431
42609
  description: "Id of this forked (child) session \u2014 not the parent session id. Required on every tool call."
@@ -42455,57 +42633,11 @@ var FORK_SESSION_MCP_TOOL_DEFINITIONS = [
42455
42633
  }
42456
42634
  }
42457
42635
  ];
42458
- function textResult(text, isError = false) {
42459
- return { content: [{ type: "text", text }], ...isError ? { isError: true } : {} };
42460
- }
42636
+
42637
+ // src/mcp/tools/session-history/fork/is-fork-session-mcp-tool-name.ts
42461
42638
  function isForkSessionMcpToolName(name) {
42462
42639
  return name === LIST_PARENT_SESSION_PROMPTS_TOOL || name === GET_PARENT_SESSION_TURN_TRANSCRIPT_TOOL;
42463
42640
  }
42464
- async function callForkSessionMcpTool(ctx, cloud, name, args) {
42465
- const childSessionId = ctx.sessionId.trim();
42466
- if (!childSessionId) {
42467
- return textResult("sessionId is required.", true);
42468
- }
42469
- const parentResolved = await resolveParentSessionIdForChild({
42470
- childSessionId,
42471
- cloudApiBaseUrl: cloud.cloudApiBaseUrl,
42472
- getCloudAccessToken: cloud.getCloudAccessToken
42473
- });
42474
- if (!parentResolved.ok) {
42475
- return textResult(parentResolved.error, true);
42476
- }
42477
- const parentSessionId = parentResolved.parentSessionId;
42478
- if (name === LIST_PARENT_SESSION_PROMPTS_TOOL) {
42479
- const detail = await fetchCloudParentSessionPrompts({
42480
- childSessionId,
42481
- cloudApiBaseUrl: cloud.cloudApiBaseUrl,
42482
- getCloudAccessToken: cloud.getCloudAccessToken
42483
- });
42484
- if (!detail.ok) return textResult(detail.error, true);
42485
- const turns = Array.isArray(detail.data.turns) ? detail.data.turns : [];
42486
- const payload = turns.map((t) => ({
42487
- turnId: typeof t.turnId === "string" ? t.turnId : "",
42488
- title: typeof t.title === "string" ? t.title : null,
42489
- status: typeof t.status === "string" ? t.status : null,
42490
- promptText: typeof t.promptText === "string" ? t.promptText : null
42491
- }));
42492
- return textResult(JSON.stringify({ parentSessionId, turns: payload }, null, 2));
42493
- }
42494
- if (name === GET_PARENT_SESSION_TURN_TRANSCRIPT_TOOL) {
42495
- const turnId = typeof args.turnId === "string" ? args.turnId.trim() : "";
42496
- if (!turnId) return textResult("turnId is required.", true);
42497
- const transcript = await fetchCloudParentTurnTranscript({
42498
- childSessionId,
42499
- turnId,
42500
- cloudApiBaseUrl: cloud.cloudApiBaseUrl,
42501
- getCloudAccessToken: cloud.getCloudAccessToken,
42502
- e2ee: ctx.e2ee
42503
- });
42504
- if (!transcript.ok) return textResult(transcript.error, true);
42505
- return textResult(transcript.text);
42506
- }
42507
- return textResult(`Unknown fork session tool: ${name}`, true);
42508
- }
42509
42641
 
42510
42642
  // src/mcp/bridge-mcp-tools.ts
42511
42643
  function requireCloud(shared) {