@buildautomaton/cli 0.1.95 → 0.1.97

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 CHANGED
@@ -20771,7 +20771,6 @@ import os from "node:os";
20771
20771
  var INDEX_WORK_YIELD_EVERY, INDEX_DIR, INDEX_HASH_LEN;
20772
20772
  var init_constants = __esm({
20773
20773
  "../bridge/src/files/index/constants.ts"() {
20774
- "use strict";
20775
20774
  INDEX_WORK_YIELD_EVERY = 128;
20776
20775
  INDEX_DIR = path3.join(os.homedir(), ".buildautomaton");
20777
20776
  INDEX_HASH_LEN = 16;
@@ -21126,6 +21125,7 @@ function isCliSqliteLockError(e) {
21126
21125
  var CliSqliteInterrupted;
21127
21126
  var init_sqlite_errors = __esm({
21128
21127
  "../bridge/src/sqlite/sqlite-errors.ts"() {
21128
+ "use strict";
21129
21129
  CliSqliteInterrupted = class extends Error {
21130
21130
  name = "CliSqliteInterrupted";
21131
21131
  constructor() {
@@ -21236,6 +21236,7 @@ function maybeLogCodeNavCacheWorkerError(message) {
21236
21236
  var diagnosticSink, lastDiagnosticKey;
21237
21237
  var init_code_nav_cache_log = __esm({
21238
21238
  "../bridge/src/sqlite/code-nav-cache/code-nav-cache-log.ts"() {
21239
+ "use strict";
21239
21240
  init_log();
21240
21241
  init_sqlite_errors();
21241
21242
  init_sqlite_lock_path();
@@ -21400,7 +21401,6 @@ function resetSymbolIndexWorkerShutdownForTests() {
21400
21401
  var symbolIndexWorkerShutdownRequested;
21401
21402
  var init_shutdown_state = __esm({
21402
21403
  "../bridge/src/code-nav/symbol-index/worker/shutdown-state.ts"() {
21403
- "use strict";
21404
21404
  symbolIndexWorkerShutdownRequested = false;
21405
21405
  }
21406
21406
  });
@@ -31937,7 +31937,7 @@ var coerce = {
31937
31937
  };
31938
31938
  var NEVER = INVALID;
31939
31939
 
31940
- // ../types/src/work-items.ts
31940
+ // ../core/src/work-items.ts
31941
31941
  var WorkItemStatusSchema = external_exports.enum(["backlog", "in-progress", "completed"]);
31942
31942
  var WorkItemProgressSchema = external_exports.object({
31943
31943
  remainingCriteria: external_exports.array(external_exports.string()).default([]),
@@ -31978,7 +31978,7 @@ var WorkItemSchema = external_exports.object({
31978
31978
  assignedToUserId: external_exports.string().optional()
31979
31979
  });
31980
31980
 
31981
- // ../types/src/user-profiles.ts
31981
+ // ../core/src/user-profiles.ts
31982
31982
  var UserWorkspaceProfileSchema = external_exports.object({
31983
31983
  id: external_exports.string(),
31984
31984
  workspaceId: external_exports.string(),
@@ -31989,7 +31989,7 @@ var UserWorkspaceProfileSchema = external_exports.object({
31989
31989
  learnings: external_exports.array(external_exports.string())
31990
31990
  });
31991
31991
 
31992
- // ../types/src/runtime.ts
31992
+ // ../core/src/runtime.ts
31993
31993
  var WorkspaceOwnerInfoSchema = external_exports.object({
31994
31994
  ownerId: external_exports.string(),
31995
31995
  ownerName: external_exports.string().optional(),
@@ -32004,7 +32004,7 @@ var WorkspaceRuntimeEntrySchema = external_exports.object({
32004
32004
  isOwner: external_exports.boolean().optional()
32005
32005
  });
32006
32006
 
32007
- // ../types/src/agent.ts
32007
+ // ../core/src/agent.ts
32008
32008
  var ProjectContextSchema = external_exports.object({
32009
32009
  projectId: external_exports.string(),
32010
32010
  context: external_exports.record(external_exports.unknown()).default({}),
@@ -32030,7 +32030,7 @@ var WebSocketMessageSchema = external_exports.object({
32030
32030
  error: external_exports.string().optional()
32031
32031
  });
32032
32032
 
32033
- // ../types/src/integrations/link-detection/linear.ts
32033
+ // ../core/src/integrations/link-detection/linear.ts
32034
32034
  function detectLinearLink(url2) {
32035
32035
  const linearMatch = url2.match(
32036
32036
  /https?:\/\/(?:app\.)?linear\.app\/([^/]+)\/issue\/([A-Z]+-\d+)/i
@@ -32047,7 +32047,7 @@ function detectLinearLink(url2) {
32047
32047
  return null;
32048
32048
  }
32049
32049
 
32050
- // ../types/src/integrations/link-detection/github.ts
32050
+ // ../core/src/integrations/link-detection/github.ts
32051
32051
  function detectGitHubLink(url2) {
32052
32052
  const githubIssueMatch = url2.match(
32053
32053
  /https?:\/\/github\.com\/([^/]+)\/([^/]+)\/issues\/(\d+)/i
@@ -32078,7 +32078,7 @@ function detectGitHubLink(url2) {
32078
32078
  return null;
32079
32079
  }
32080
32080
 
32081
- // ../types/src/integrations/link-detection/jira.ts
32081
+ // ../core/src/integrations/link-detection/jira.ts
32082
32082
  function detectJIRALink(url2) {
32083
32083
  const jiraMatch = url2.match(
32084
32084
  /https?:\/\/([^/]+)\.atlassian\.net\/(?:browse|jira\/software\/projects\/[^/]+\/issues)\/([A-Z]+-\d+)/i
@@ -32095,7 +32095,7 @@ function detectJIRALink(url2) {
32095
32095
  return null;
32096
32096
  }
32097
32097
 
32098
- // ../types/src/integrations/link-detection/notion.ts
32098
+ // ../core/src/integrations/link-detection/notion.ts
32099
32099
  function formatNotionPageId(hex3) {
32100
32100
  if (hex3.length !== 32) return hex3;
32101
32101
  return `${hex3.slice(0, 8)}-${hex3.slice(8, 12)}-${hex3.slice(12, 16)}-${hex3.slice(16, 20)}-${hex3.slice(20, 32)}`;
@@ -32127,48 +32127,7 @@ function detectNotionLink(url2) {
32127
32127
  return null;
32128
32128
  }
32129
32129
 
32130
- // ../types/src/integrations/link-detection/slack.ts
32131
- function detectSlackLink(url2) {
32132
- const archiveThreadMatch = url2.match(
32133
- /https?:\/\/(?:([^./]+)\.)?slack\.com\/archives\/([A-Z0-9]+)\/p(\d+)(?:\?.*)?$/i
32134
- );
32135
- if (archiveThreadMatch) {
32136
- return {
32137
- url: url2,
32138
- integrationType: "slack",
32139
- resourceType: "thread",
32140
- resourceId: `${archiveThreadMatch[2]}-${archiveThreadMatch[3]}`,
32141
- isChannel: false
32142
- };
32143
- }
32144
- const appThreadMatch = url2.match(
32145
- /https?:\/\/app\.slack\.com\/client\/([^/]+)\/([A-Z0-9]+)\/thread\/[A-Z0-9]+-(\d+)/i
32146
- );
32147
- if (appThreadMatch) {
32148
- return {
32149
- url: url2,
32150
- integrationType: "slack",
32151
- resourceType: "thread",
32152
- resourceId: `${appThreadMatch[2]}-${appThreadMatch[3]}`,
32153
- isChannel: false
32154
- };
32155
- }
32156
- const channelOnlyMatch = url2.match(
32157
- /https?:\/\/(?:app\.)?(?:([^./]+)\.)?slack\.com\/archives\/([A-Z0-9]+)\/?(\?.*)?$/i
32158
- );
32159
- if (channelOnlyMatch && !url2.includes("/p")) {
32160
- return {
32161
- url: url2,
32162
- integrationType: "slack",
32163
- resourceType: "channel",
32164
- resourceId: channelOnlyMatch[2],
32165
- isChannel: true
32166
- };
32167
- }
32168
- return null;
32169
- }
32170
-
32171
- // ../types/src/integrations/link-detection/zoom.ts
32130
+ // ../core/src/integrations/link-detection/zoom.ts
32172
32131
  function detectZoomLink(url2) {
32173
32132
  try {
32174
32133
  const u = new URL(url2);
@@ -32192,7 +32151,7 @@ function detectZoomLink(url2) {
32192
32151
  return null;
32193
32152
  }
32194
32153
 
32195
- // ../types/src/integrations/link-detection/asana.ts
32154
+ // ../core/src/integrations/link-detection/asana.ts
32196
32155
  var ASANA_TASK_GID = /\d{10,}/;
32197
32156
  function parseAsanaTaskGid(segment) {
32198
32157
  const trimmed2 = segment.trim();
@@ -32244,9 +32203,9 @@ function detectAsanaLink(url2) {
32244
32203
  return null;
32245
32204
  }
32246
32205
 
32247
- // ../types/src/integrations/link-detection/index.ts
32206
+ // ../core/src/integrations/link-detection/index.ts
32248
32207
  function detectIntegrationLink(url2) {
32249
- return detectLinearLink(url2) || detectGitHubLink(url2) || detectJIRALink(url2) || detectNotionLink(url2) || detectSlackLink(url2) || detectZoomLink(url2) || detectAsanaLink(url2);
32208
+ return detectLinearLink(url2) || detectGitHubLink(url2) || detectJIRALink(url2) || detectNotionLink(url2) || detectZoomLink(url2) || detectAsanaLink(url2);
32250
32209
  }
32251
32210
  function extractIntegrationLinks(text) {
32252
32211
  const urlRegex = /https?:\/\/[^\s<>"{}|\\^`[\]]+/gi;
@@ -32259,10 +32218,10 @@ function extractIntegrationLinks(text) {
32259
32218
  return links;
32260
32219
  }
32261
32220
  function extractFetchableIntegrationLinks(text) {
32262
- return extractIntegrationLinks(text).filter((link) => !(link.integrationType === "slack" && link.isChannel));
32221
+ return extractIntegrationLinks(text);
32263
32222
  }
32264
32223
 
32265
- // ../types/src/checkpoints.ts
32224
+ // ../core/src/checkpoints.ts
32266
32225
  var CheckpointKindSchema = external_exports.enum(["daily", "weekly", "overall"]);
32267
32226
  var CheckpointSummarySchema = external_exports.object({
32268
32227
  id: external_exports.string(),
@@ -32274,11 +32233,11 @@ var CheckpointSummarySchema = external_exports.object({
32274
32233
  updatedAt: external_exports.string()
32275
32234
  });
32276
32235
 
32277
- // ../types/src/threads.ts
32236
+ // ../core/src/threads.ts
32278
32237
  var ThreadMetaSchema = external_exports.object({
32279
32238
  threadId: external_exports.string(),
32280
32239
  workspaceId: external_exports.string(),
32281
- /** External source (e.g. slack, discord); null if internal-only */
32240
+ /** External source (e.g. discord); null if internal-only */
32282
32241
  externalSource: external_exports.string().nullable(),
32283
32242
  /** Id in the external system (e.g. channel_id + thread_ts) */
32284
32243
  externalId: external_exports.string().nullable(),
@@ -32303,15 +32262,15 @@ var ThreadCheckpointSummarySchema = CheckpointSummarySchema.extend({
32303
32262
  threadId: external_exports.string()
32304
32263
  });
32305
32264
 
32306
- // ../types/src/content-items.ts
32307
- var ContentSourceSchema = external_exports.enum(["notion", "doc", "slack_thread", "other"]);
32265
+ // ../core/src/content-items.ts
32266
+ var ContentSourceSchema = external_exports.enum(["notion", "doc", "other"]);
32308
32267
  var ContentItemMetaSchema = external_exports.object({
32309
32268
  contentId: external_exports.string(),
32310
32269
  workspaceId: external_exports.string(),
32311
32270
  source: ContentSourceSchema,
32312
32271
  /** Id in the external system (e.g. Notion page id, doc url) */
32313
32272
  externalId: external_exports.string(),
32314
- /** If source is slack_thread, points to Thread DO id */
32273
+ /** Optional linked thread DO id */
32315
32274
  threadId: external_exports.string().nullable(),
32316
32275
  title: external_exports.string().optional(),
32317
32276
  createdAt: external_exports.string(),
@@ -32326,7 +32285,7 @@ var ContentCheckpointSummarySchema = CheckpointSummarySchema.extend({
32326
32285
  contentId: external_exports.string()
32327
32286
  });
32328
32287
 
32329
- // ../types/src/stories.ts
32288
+ // ../core/src/stories.ts
32330
32289
  var StoryMetaSchema = external_exports.object({
32331
32290
  storyId: external_exports.string(),
32332
32291
  workspaceId: external_exports.string(),
@@ -32350,7 +32309,7 @@ var StoryCheckpointSummarySchema = CheckpointSummarySchema.extend({
32350
32309
  storyId: external_exports.string()
32351
32310
  });
32352
32311
 
32353
- // ../types/src/sessions.ts
32312
+ // ../core/src/sessions.ts
32354
32313
  var SessionMetaSchema = external_exports.object({
32355
32314
  sessionId: external_exports.string(),
32356
32315
  workspaceId: external_exports.string(),
@@ -32404,104 +32363,7 @@ function isUserEndedSessionTurnErrorText(errorText) {
32404
32363
  return LEGACY_USER_ENDED_SESSION_TURN_ERRORS.includes(raw);
32405
32364
  }
32406
32365
 
32407
- // ../types/src/session-kind.ts
32408
- var SESSION_KINDS = ["regular", "planned"];
32409
- var SESSION_KIND_SET = new Set(SESSION_KINDS);
32410
-
32411
- // ../types/src/diff/line-diff.ts
32412
- function normalizeDiffLineText(line) {
32413
- return line.replace(/\r$/, "").replace(/\s*\\s*$/, "");
32414
- }
32415
- function normalizePatchContent(patch) {
32416
- return patch.replace(/^\n+/, "").replace(/\n+$/, "");
32417
- }
32418
- function splitTextIntoDiffLines(text) {
32419
- if (text.length === 0) return [];
32420
- const lines = text.split("\n").map((line) => normalizeDiffLineText(line));
32421
- if (text.endsWith("\n") && lines.at(-1) === "") {
32422
- lines.pop();
32423
- }
32424
- return lines;
32425
- }
32426
- function createEofNewlineDiffLine(change) {
32427
- return {
32428
- type: change === "added" ? "add" : "remove",
32429
- line: "",
32430
- oldLineNo: null,
32431
- newLineNo: null,
32432
- eofNewlineChange: change
32433
- };
32434
- }
32435
- function hasSameLogicalLines(left, right) {
32436
- return left.length === right.length && left.every((line, index) => line === right[index]);
32437
- }
32438
- function detectEofNewlineChange(oldText, newText, oldLines, newLines) {
32439
- if (!hasSameLogicalLines(oldLines, newLines) || oldLines.length === 0) return null;
32440
- if (!oldText.endsWith("\n") && newText.endsWith("\n")) return "added";
32441
- if (oldText.endsWith("\n") && !newText.endsWith("\n")) return "removed";
32442
- return null;
32443
- }
32444
- function computeLineDiff(oldText, newText) {
32445
- const oldLines = splitTextIntoDiffLines(oldText);
32446
- const newLines = splitTextIntoDiffLines(newText);
32447
- const m = oldLines.length;
32448
- const n = newLines.length;
32449
- const dp = Array(m + 1);
32450
- for (let i2 = 0; i2 <= m; i2++) dp[i2] = Array(n + 1).fill(0);
32451
- for (let i2 = 1; i2 <= m; i2++) {
32452
- for (let j2 = 1; j2 <= n; j2++) {
32453
- if (oldLines[i2 - 1] === newLines[j2 - 1]) {
32454
- dp[i2][j2] = dp[i2 - 1][j2 - 1] + 1;
32455
- } else {
32456
- dp[i2][j2] = Math.max(dp[i2 - 1][j2], dp[i2][j2 - 1]);
32457
- }
32458
- }
32459
- }
32460
- const result = [];
32461
- let i = m;
32462
- let j = n;
32463
- while (i > 0 || j > 0) {
32464
- if (i > 0 && j > 0 && oldLines[i - 1] === newLines[j - 1]) {
32465
- result.unshift({ type: "context", line: oldLines[i - 1] });
32466
- i--;
32467
- j--;
32468
- } else if (j > 0 && (i === 0 || dp[i][j - 1] >= dp[i - 1][j])) {
32469
- result.unshift({ type: "add", line: newLines[j - 1] });
32470
- j--;
32471
- } else {
32472
- result.unshift({ type: "remove", line: oldLines[i - 1] });
32473
- i--;
32474
- }
32475
- }
32476
- const eofNewlineChange = detectEofNewlineChange(oldText, newText, oldLines, newLines);
32477
- if (eofNewlineChange) result.push(createEofNewlineDiffLine(eofNewlineChange));
32478
- return result;
32479
- }
32480
- function editSnippetToUnifiedDiff(filePath, oldText, newText) {
32481
- const lines = computeLineDiff(oldText, newText);
32482
- const out = [`--- ${filePath}`, `+++ ${filePath}`];
32483
- for (const d of lines) {
32484
- if (d.eofNewlineChange) {
32485
- const previous = out.at(-1);
32486
- if (previous?.startsWith(" ")) {
32487
- const line = previous.slice(1);
32488
- out.pop();
32489
- if (d.eofNewlineChange === "added") {
32490
- out.push(`-${line}`, "\", `+${line}`);
32491
- } else {
32492
- out.push(`-${line}`, `+${line}`, "\");
32493
- }
32494
- continue;
32495
- }
32496
- }
32497
- if (d.type === "add") out.push(`+${d.line}`);
32498
- else if (d.type === "remove") out.push(`-${d.line}`);
32499
- else out.push(` ${d.line}`);
32500
- }
32501
- return out.join("\n");
32502
- }
32503
-
32504
- // ../types/src/artifacts.ts
32366
+ // ../core/src/artifacts.ts
32505
32367
  var ArtifactMetaSchema = external_exports.object({
32506
32368
  artifactId: external_exports.string(),
32507
32369
  workspaceId: external_exports.string(),
@@ -32516,7 +32378,7 @@ var ArtifactMetaSchema = external_exports.object({
32516
32378
  updatedAt: external_exports.string()
32517
32379
  });
32518
32380
 
32519
- // ../types/src/templates.ts
32381
+ // ../core/src/templates.ts
32520
32382
  var TemplateMetaSchema = external_exports.object({
32521
32383
  templateId: external_exports.string(),
32522
32384
  workspaceId: external_exports.string(),
@@ -32527,7 +32389,7 @@ var TemplateMetaSchema = external_exports.object({
32527
32389
  updatedAt: external_exports.string()
32528
32390
  });
32529
32391
 
32530
- // ../types/src/git-repos.ts
32392
+ // ../core/src/git-repos.ts
32531
32393
  var GitRepoMetaSchema = external_exports.object({
32532
32394
  /** Stable id for the repo (e.g. hash of normalized canonical URL). Used for DO idFromName. */
32533
32395
  repoId: external_exports.string(),
@@ -32540,7 +32402,7 @@ var GitRepoMetaSchema = external_exports.object({
32540
32402
  updatedAt: external_exports.string()
32541
32403
  });
32542
32404
 
32543
- // ../types/src/mcp/bridge-mcp-constants.ts
32405
+ // ../core/src/mcp/bridge-mcp-constants.ts
32544
32406
  var GET_INTEGRATION_CONTENT_TOOL = "get_integration_content";
32545
32407
  var LIST_PARENT_SESSION_PROMPTS_TOOL = "list_parent_session_prompts";
32546
32408
  var GET_PARENT_SESSION_TURN_TRANSCRIPT_TOOL = "get_parent_session_turn_transcript";
@@ -32550,12 +32412,12 @@ var BRIDGE_MCP_TOOL_LABELS = {
32550
32412
  [GET_PARENT_SESSION_TURN_TRANSCRIPT_TOOL]: "Read parent session transcript"
32551
32413
  };
32552
32414
 
32553
- // ../types/src/prompts/server.ts
32415
+ // ../core/src/prompts/server.ts
32554
32416
  function isRunnableBridgePromptTurnServerState(state) {
32555
32417
  return state === "queued" || state === "requeued" || state === "requeued_with_revert";
32556
32418
  }
32557
32419
 
32558
- // ../types/src/claude-code-permission-mode.ts
32420
+ // ../core/src/claude-code-permission-mode.ts
32559
32421
  var CLAUDE_CODE_PERMISSION_MODES = [
32560
32422
  "default",
32561
32423
  "acceptEdits",
@@ -32569,7 +32431,7 @@ function isClaudeCodePermissionMode(value) {
32569
32431
  return MODE_SET.has(value);
32570
32432
  }
32571
32433
 
32572
- // ../types/src/codex-permission-mode.ts
32434
+ // ../core/src/codex-permission-mode.ts
32573
32435
  function isCodexPermissionMode(value) {
32574
32436
  return value.trim() !== "";
32575
32437
  }
@@ -32579,7 +32441,7 @@ function normalizeCodexPermissionModeInput(raw) {
32579
32441
  return isCodexPermissionMode(t) ? t : null;
32580
32442
  }
32581
32443
 
32582
- // ../types/src/cli-permission-mode.ts
32444
+ // ../core/src/cli-permission-mode.ts
32583
32445
  var CLI_PERMISSION_MODE_DEFAULT = "default";
32584
32446
  var CLI_PERMISSION_MODE_DANGEROUS = "dangerous";
32585
32447
  function normalizeCliPermissionModeInput(raw) {
@@ -32590,7 +32452,7 @@ function normalizeCliPermissionModeInput(raw) {
32590
32452
  return CLI_PERMISSION_MODE_DEFAULT;
32591
32453
  }
32592
32454
 
32593
- // ../types/src/acp-permission-auto-approve.ts
32455
+ // ../core/src/acp-permission-auto-approve.ts
32594
32456
  function isRejectKind(kind) {
32595
32457
  return kind === "reject_once" || kind === "reject_always";
32596
32458
  }
@@ -32647,7 +32509,7 @@ function buildCliAutoApprovedPermissionRpcResult(requestParams) {
32647
32509
  };
32648
32510
  }
32649
32511
 
32650
- // ../types/src/agent-config.ts
32512
+ // ../core/src/agent-config.ts
32651
32513
  var AGENT_CONFIG_CLAUDE_PERMISSION_MODE_KEY = "claude_permission_mode";
32652
32514
  var AGENT_CONFIG_CLI_PERMISSION_MODE_KEY = "cli_permission_mode";
32653
32515
  var AGENT_CONFIG_CODEX_PERMISSION_MODE_KEY = "codex_permission_mode";
@@ -32675,11 +32537,104 @@ function getAgentModelFromAgentConfig(config2) {
32675
32537
  return t !== "" ? t : null;
32676
32538
  }
32677
32539
 
32678
- // ../types/src/overview/heatmap/constants.ts
32540
+ // ../core/src/diff/line-diff.ts
32541
+ function normalizeDiffLineText(line) {
32542
+ return line.replace(/\r$/, "").replace(/\s*\\s*$/, "");
32543
+ }
32544
+ function normalizePatchContent(patch) {
32545
+ return patch.replace(/^\n+/, "").replace(/\n+$/, "");
32546
+ }
32547
+ function splitTextIntoDiffLines(text) {
32548
+ if (text.length === 0) return [];
32549
+ const lines = text.split("\n").map((line) => normalizeDiffLineText(line));
32550
+ if (text.endsWith("\n") && lines.at(-1) === "") {
32551
+ lines.pop();
32552
+ }
32553
+ return lines;
32554
+ }
32555
+ function createEofNewlineDiffLine(change) {
32556
+ return {
32557
+ type: change === "added" ? "add" : "remove",
32558
+ line: "",
32559
+ oldLineNo: null,
32560
+ newLineNo: null,
32561
+ eofNewlineChange: change
32562
+ };
32563
+ }
32564
+ function hasSameLogicalLines(left, right) {
32565
+ return left.length === right.length && left.every((line, index) => line === right[index]);
32566
+ }
32567
+ function detectEofNewlineChange(oldText, newText, oldLines, newLines) {
32568
+ if (!hasSameLogicalLines(oldLines, newLines) || oldLines.length === 0) return null;
32569
+ if (!oldText.endsWith("\n") && newText.endsWith("\n")) return "added";
32570
+ if (oldText.endsWith("\n") && !newText.endsWith("\n")) return "removed";
32571
+ return null;
32572
+ }
32573
+ function computeLineDiff(oldText, newText) {
32574
+ const oldLines = splitTextIntoDiffLines(oldText);
32575
+ const newLines = splitTextIntoDiffLines(newText);
32576
+ const m = oldLines.length;
32577
+ const n = newLines.length;
32578
+ const dp = Array(m + 1);
32579
+ for (let i2 = 0; i2 <= m; i2++) dp[i2] = Array(n + 1).fill(0);
32580
+ for (let i2 = 1; i2 <= m; i2++) {
32581
+ for (let j2 = 1; j2 <= n; j2++) {
32582
+ if (oldLines[i2 - 1] === newLines[j2 - 1]) {
32583
+ dp[i2][j2] = dp[i2 - 1][j2 - 1] + 1;
32584
+ } else {
32585
+ dp[i2][j2] = Math.max(dp[i2 - 1][j2], dp[i2][j2 - 1]);
32586
+ }
32587
+ }
32588
+ }
32589
+ const result = [];
32590
+ let i = m;
32591
+ let j = n;
32592
+ while (i > 0 || j > 0) {
32593
+ if (i > 0 && j > 0 && oldLines[i - 1] === newLines[j - 1]) {
32594
+ result.unshift({ type: "context", line: oldLines[i - 1] });
32595
+ i--;
32596
+ j--;
32597
+ } else if (j > 0 && (i === 0 || dp[i][j - 1] >= dp[i - 1][j])) {
32598
+ result.unshift({ type: "add", line: newLines[j - 1] });
32599
+ j--;
32600
+ } else {
32601
+ result.unshift({ type: "remove", line: oldLines[i - 1] });
32602
+ i--;
32603
+ }
32604
+ }
32605
+ const eofNewlineChange = detectEofNewlineChange(oldText, newText, oldLines, newLines);
32606
+ if (eofNewlineChange) result.push(createEofNewlineDiffLine(eofNewlineChange));
32607
+ return result;
32608
+ }
32609
+ function editSnippetToUnifiedDiff(filePath, oldText, newText) {
32610
+ const lines = computeLineDiff(oldText, newText);
32611
+ const out = [`--- ${filePath}`, `+++ ${filePath}`];
32612
+ for (const d of lines) {
32613
+ if (d.eofNewlineChange) {
32614
+ const previous = out.at(-1);
32615
+ if (previous?.startsWith(" ")) {
32616
+ const line = previous.slice(1);
32617
+ out.pop();
32618
+ if (d.eofNewlineChange === "added") {
32619
+ out.push(`-${line}`, "\", `+${line}`);
32620
+ } else {
32621
+ out.push(`-${line}`, `+${line}`, "\");
32622
+ }
32623
+ continue;
32624
+ }
32625
+ }
32626
+ if (d.type === "add") out.push(`+${d.line}`);
32627
+ else if (d.type === "remove") out.push(`-${d.line}`);
32628
+ else out.push(` ${d.line}`);
32629
+ }
32630
+ return out.join("\n");
32631
+ }
32632
+
32633
+ // ../core/src/overview/heatmap/constants.ts
32679
32634
  var HOUR_MS = 36e5;
32680
32635
  var DAY_MS = 24 * HOUR_MS;
32681
32636
 
32682
- // ../types/src/hosts/skus.ts
32637
+ // ../core/src/hosts/skus.ts
32683
32638
  function defineHostSku(params) {
32684
32639
  return structuredClone(params);
32685
32640
  }
@@ -32713,7 +32668,7 @@ var HOST_SKUS_BY_ID = {
32713
32668
  [FLY_DEFAULT_HOST_SKU.id]: FLY_DEFAULT_HOST_SKU
32714
32669
  };
32715
32670
 
32716
- // ../types/src/bridges/agents/types.ts
32671
+ // ../core/src/bridges/agents/types.ts
32717
32672
  var INSTALLABLE_BRIDGE_AGENTS = [
32718
32673
  { value: "claude-code", label: "Anthropic Claude Code", tokenLabel: "Anthropic API key", tokenEnvVar: "ANTHROPIC_API_KEY" },
32719
32674
  { value: "codex-acp", label: "Codex", tokenLabel: "OpenAI API key", tokenEnvVar: "OPENAI_API_KEY" },
@@ -32721,12 +32676,12 @@ var INSTALLABLE_BRIDGE_AGENTS = [
32721
32676
  { value: "opencode", label: "OpenCode agent", tokenLabel: "Provider API key", tokenEnvVar: "OPENCODE_API_KEY" }
32722
32677
  ];
32723
32678
 
32724
- // ../types/src/agent-subscriptions.ts
32679
+ // ../core/src/agent-subscriptions.ts
32725
32680
  var AGENT_SUBSCRIPTION_TYPES = INSTALLABLE_BRIDGE_AGENTS.map(
32726
32681
  (a) => a.value
32727
32682
  );
32728
32683
 
32729
- // ../types/src/role-payment-model.ts
32684
+ // ../core/src/role-payment-model.ts
32730
32685
  var ROLE_FIXED_AMOUNT_USD_MAX = 5e4;
32731
32686
  var ROLE_PER_SESSION_USD_MIN = 0;
32732
32687
  var ROLE_PER_SESSION_USD_MAX = 200;
@@ -32751,14 +32706,14 @@ var RolePaymentModelWireSchema = external_exports.discriminatedUnion("type", [
32751
32706
  })
32752
32707
  ]);
32753
32708
 
32754
- // ../types/src/role-period-days.ts
32709
+ // ../core/src/role-period-days.ts
32755
32710
  var ROLE_PERIOD_MIN_DAYS = 1;
32756
32711
  var ROLE_PERIOD_DAYS_PER_WEEK = 5;
32757
32712
  var ROLE_PERIOD_WEEKS_PER_MONTH = 4;
32758
32713
  var ROLE_PERIOD_DAYS_PER_MONTH = ROLE_PERIOD_DAYS_PER_WEEK * ROLE_PERIOD_WEEKS_PER_MONTH;
32759
32714
  var ROLE_PERIOD_MAX_DAYS = ROLE_PERIOD_DAYS_PER_MONTH * 6;
32760
32715
 
32761
- // ../types/src/role-length.ts
32716
+ // ../core/src/role-length.ts
32762
32717
  var ROLE_LENGTH_MAX_SESSIONS_MIN = 1;
32763
32718
  var ROLE_LENGTH_MAX_SESSIONS_MAX = 50;
32764
32719
  var ROLE_LENGTH_SESSIONS_UNLIMITED_STOP = ROLE_LENGTH_MAX_SESSIONS_MAX + 8;
@@ -32773,7 +32728,7 @@ var RoleLengthWireSchema = external_exports.discriminatedUnion("type", [
32773
32728
  external_exports.object({ type: external_exports.literal("session_count"), max_sessions: MaxSessionsSchema })
32774
32729
  ]);
32775
32730
 
32776
- // ../types/src/role-access-restrictions.ts
32731
+ // ../core/src/role-access-restrictions.ts
32777
32732
  var EMPTY_ROLE_ACCESS_RESTRICTIONS = {
32778
32733
  sessionsOwnAndExplicitOnly: false,
32779
32734
  bridgesOwnAndExplicitOnly: false,
@@ -32791,7 +32746,7 @@ function roleAccessRestrictionsToWire(restrictions) {
32791
32746
  };
32792
32747
  }
32793
32748
 
32794
- // ../types/src/role-details.ts
32749
+ // ../core/src/role-details.ts
32795
32750
  var InitialPeriodDaysSchema = external_exports.number().int().min(ROLE_PERIOD_MIN_DAYS).max(ROLE_PERIOD_MAX_DAYS);
32796
32751
  var AgentSubscriptionIdsSchema = external_exports.array(external_exports.string().min(1)).default([]);
32797
32752
  var BoolFalseSchema = external_exports.boolean().default(false);
@@ -36729,7 +36684,31 @@ function createBridgeOnRequest(opts) {
36729
36684
  }
36730
36685
 
36731
36686
  // ../bridge/src/agents/acp/hooks/bridge-on-session-update/constants.ts
36732
- var PATH_SNAPSHOT_DEBOUNCE_MS = 500;
36687
+ var PATH_SNAPSHOT_DEBOUNCE_MS = 150;
36688
+
36689
+ // ../bridge/src/agents/acp/hooks/bridge-on-session-update/pair-path-snapshot-changes.ts
36690
+ function isDeleted(c) {
36691
+ return c.newText === "" && c.oldText.length > 0;
36692
+ }
36693
+ function isAdded(c) {
36694
+ return c.oldText === "" && c.newText.length > 0 && !c.movedFromPath;
36695
+ }
36696
+ function pairPathSnapshotChanges(changes) {
36697
+ const out = changes.map((c) => ({ ...c }));
36698
+ const deleted = out.filter(isDeleted);
36699
+ const usedDeleted = /* @__PURE__ */ new Set();
36700
+ for (const add of out) {
36701
+ if (!isAdded(add)) continue;
36702
+ const match = deleted.find(
36703
+ (d) => !usedDeleted.has(d.displayPath) && d.oldText === add.newText && d.displayPath !== add.displayPath
36704
+ );
36705
+ if (!match) continue;
36706
+ add.movedFromPath = match.displayPath;
36707
+ add.oldText = match.oldText;
36708
+ usedDeleted.add(match.displayPath);
36709
+ }
36710
+ return out.filter((c) => !(isDeleted(c) && usedDeleted.has(c.displayPath))).map(({ displayPath: _d, ...payload }) => payload);
36711
+ }
36733
36712
 
36734
36713
  // ../bridge/src/agents/acp/hooks/bridge-on-session-update/tool-key.ts
36735
36714
  function getToolCallId(params) {
@@ -36821,26 +36800,31 @@ var PathSnapshotTracker = class {
36821
36800
  if (!beforeMap || beforeMap.size === 0) return;
36822
36801
  this.beforeByToolKey.delete(toolKey);
36823
36802
  if (!send || !runId || !sessionId) return;
36803
+ const pending2 = [];
36824
36804
  for (const [displayPath, oldText] of beforeMap) {
36825
36805
  const newText = readUtf8WorkspaceFile(sessionParentPath, displayPath);
36826
36806
  if (oldText === newText) continue;
36827
36807
  const patchContent = editSnippetToUnifiedDiff(displayPath, oldText, newText);
36828
36808
  const dirFlags = getSessionFileChangeDirectoryFlags(sessionParentPath, displayPath);
36809
+ pending2.push({
36810
+ type: "session_file_change",
36811
+ sessionId,
36812
+ runId,
36813
+ path: displayPath,
36814
+ displayPath,
36815
+ oldText,
36816
+ newText,
36817
+ patchContent,
36818
+ isDirectory: dirFlags.isDirectory,
36819
+ directoryRemoved: dirFlags.directoryRemoved
36820
+ });
36821
+ }
36822
+ for (const payload of pairPathSnapshotChanges(pending2)) {
36829
36823
  try {
36830
- send({
36831
- type: "session_file_change",
36832
- sessionId,
36833
- runId,
36834
- path: displayPath,
36835
- oldText,
36836
- newText,
36837
- patchContent,
36838
- isDirectory: dirFlags.isDirectory,
36839
- directoryRemoved: dirFlags.directoryRemoved
36840
- });
36841
- sentPaths.add(displayPath);
36824
+ send(payload);
36825
+ sentPaths.add(payload.path);
36842
36826
  } catch (err) {
36843
- log2(`[Bridge service] Session file change failed for ${displayPath}: ${errorMessage(err)}`);
36827
+ log2(`[Bridge service] Session file change failed for ${payload.path}: ${errorMessage(err)}`);
36844
36828
  }
36845
36829
  }
36846
36830
  }
@@ -37945,16 +37929,9 @@ async function collectTurnGitDiffFromPreTurnSnapshot(options) {
37945
37929
  // ../bridge/src/agents/acp/prompts/report-post-turn-enrichment.ts
37946
37930
  function reportPostTurnEnrichment(options) {
37947
37931
  void (async () => {
37948
- const {
37949
- sessionId,
37950
- runId,
37951
- agentCwd,
37952
- result,
37953
- sendSessionUpdate,
37954
- log: log2
37955
- } = options;
37932
+ const { sessionId, runId, agentCwd, sendSessionUpdate, log: log2 } = options;
37956
37933
  await yieldToEventLoop();
37957
- if (sessionId && runId && sendSessionUpdate && agentCwd && result.success) {
37934
+ if (sessionId && runId && sendSessionUpdate && agentCwd) {
37958
37935
  await collectTurnGitDiffFromPreTurnSnapshot({
37959
37936
  sessionId,
37960
37937
  runId,
@@ -40386,7 +40363,7 @@ function createBridgeHeartbeatController(params) {
40386
40363
  }
40387
40364
 
40388
40365
  // ../bridge/src/cli/cli-version.ts
40389
- var CLI_VERSION = "0.1.95".length > 0 ? "0.1.95" : "0.0.0-dev";
40366
+ var CLI_VERSION = "0.1.97".length > 0 ? "0.1.97" : "0.0.0-dev";
40390
40367
 
40391
40368
  // ../bridge/src/connection/identify/send-bridge-identify.ts
40392
40369
  function sendBridgeIdentify(ws, params) {
@@ -50880,6 +50857,7 @@ async function executePromptQueueActions(actions, deps) {
50880
50857
  continue;
50881
50858
  }
50882
50859
  if (action.type === "start_run") {
50860
+ if (getRunIdQueueKey(action.turn.turnId)) continue;
50883
50861
  const ok = await markTurnRunning(action.queueKey, action.turn, deps);
50884
50862
  if (!ok) {
50885
50863
  report[action.queueKey] = [{ turnId: action.turn.turnId, cliState: "failed" }];
@@ -50930,7 +50908,7 @@ var SLOW_QUEUE_SYNC_MS = 2e3;
50930
50908
  async function persistAndReconcileQueue(queueKey, serverTurns, deps) {
50931
50909
  const prev = await readPersistedQueue(queueKey);
50932
50910
  const merged = mergeServerSnapshotWithLocal(queueKey, serverTurns, prev);
50933
- const liveCheck = (runId) => deps.acpManager.isRegisteredRun(runId);
50911
+ const liveCheck = (runId) => deps.acpManager.isRegisteredRun(runId) || getRunIdQueueKey(runId) != null;
50934
50912
  const actions = reconcileQueueActions(queueKey, merged.turns, liveCheck);
50935
50913
  merged.turns = applyStaleRunningNormalization(merged.turns, liveCheck);
50936
50914
  await writePersistedQueue(merged);
@@ -53344,7 +53322,7 @@ function createPendingAuthOnMessage(params) {
53344
53322
  }
53345
53323
 
53346
53324
  // src/cli-version.ts
53347
- var CLI_VERSION2 = "0.1.95".length > 0 ? "0.1.95" : "0.0.0-dev";
53325
+ var CLI_VERSION2 = "0.1.97".length > 0 ? "0.1.97" : "0.0.0-dev";
53348
53326
 
53349
53327
  // src/auth/pending/pending-auth-on-open.ts
53350
53328
  function createPendingAuthOnOpen(params) {
@@ -53843,7 +53821,7 @@ var SESSION_ID_SCHEMA2 = {
53843
53821
  var INTEGRATION_CONTENT_MCP_TOOL_DEFINITIONS = [
53844
53822
  {
53845
53823
  name: GET_INTEGRATION_CONTENT_TOOL2,
53846
- description: "Fetch the full content of a supported external integration link (Linear, GitHub, Jira, Notion, Slack thread, Zoom meeting, Asana). Requires sessionId and url. By default, links the URL as this session external ticket when the session has none yet. Pass associateAsSessionTicket: false to fetch content only (e.g. additional context links). Returns an error when the URL is unsupported, the integration is not connected, or content is temporarily unavailable (retry may succeed).",
53824
+ description: "Fetch the full content of a supported external integration link (Linear, GitHub, Jira, Notion, Zoom meeting, Asana). Requires sessionId and url. By default, links the URL as this session external ticket when the session has none yet. Pass associateAsSessionTicket: false to fetch content only (e.g. additional context links). Returns an error when the URL is unsupported, the integration is not connected, or content is temporarily unavailable (retry may succeed).",
53847
53825
  inputSchema: {
53848
53826
  type: "object",
53849
53827
  properties: {
@@ -54051,7 +54029,7 @@ async function enrichForkedSessionPromptForAgent(params) {
54051
54029
  function buildIntegrationContentAgentPromptNote(sessionId) {
54052
54030
  const sessionRef = sessionId.trim();
54053
54031
  return [
54054
- "The user message includes link(s) to external integration resources (Linear, GitHub, Jira, Notion, Slack thread, Zoom, or Asana).",
54032
+ "The user message includes link(s) to external integration resources (Linear, GitHub, Jira, Notion, Zoom, or Asana).",
54055
54033
  "Use the get_integration_content MCP tool on the buildautomaton-bridge server to fetch the full content of each link.",
54056
54034
  `When calling the tool, pass sessionId "${sessionRef}" and the URL as url.`,
54057
54035
  "By default the tool links the fetched URL as this session external ticket when the session has none yet. Pass associateAsSessionTicket: false when fetching additional links for context only (after the primary ticket is linked, or when you do not want association).",