@adhdev/daemon-standalone 0.9.54 → 0.9.56

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
@@ -29812,6 +29812,7 @@ var require_dist2 = __commonJS({
29812
29812
  sendDelayMs: typeof provider.sendDelayMs === "number" ? Math.max(0, provider.sendDelayMs) : 0,
29813
29813
  sendKey: typeof provider.sendKey === "string" && provider.sendKey.length > 0 ? provider.sendKey : "\r",
29814
29814
  submitStrategy: provider.submitStrategy === "immediate" ? "immediate" : "wait_for_echo",
29815
+ requirePromptEchoBeforeSubmit: provider.requirePromptEchoBeforeSubmit === true,
29815
29816
  providerResolutionMeta: {
29816
29817
  type: provider.type,
29817
29818
  name: provider.name,
@@ -30077,6 +30078,7 @@ var require_dist2 = __commonJS({
30077
30078
  this.sendDelayMs = resolvedConfig.sendDelayMs;
30078
30079
  this.sendKey = resolvedConfig.sendKey;
30079
30080
  this.submitStrategy = resolvedConfig.submitStrategy;
30081
+ this.requirePromptEchoBeforeSubmit = resolvedConfig.requirePromptEchoBeforeSubmit;
30080
30082
  this.providerResolutionMeta = resolvedConfig.providerResolutionMeta;
30081
30083
  this.cliScripts = provider.scripts || {};
30082
30084
  const scriptNames = listCliScriptNames(this.cliScripts);
@@ -30173,6 +30175,12 @@ var require_dist2 = __commonJS({
30173
30175
  accumulatedRawBuffer = "";
30174
30176
  /** Current visible terminal screen snapshot */
30175
30177
  terminalScreen = new TerminalScreen(24, 80);
30178
+ static MAX_RESPONSE_BUFFER = 8e3;
30179
+ static MAX_RECENT_OUTPUT_BUFFER = 1e3;
30180
+ responseBufferDroppedChars = 0;
30181
+ recentOutputDroppedChars = 0;
30182
+ accumulatedBufferDroppedChars = 0;
30183
+ accumulatedRawBufferDroppedChars = 0;
30176
30184
  /** Max accumulated buffer size. Sized to comfortably hold a single long
30177
30185
  * Hermes turn (tool calls + reasoning + final bubble) without the
30178
30186
  * rolling window pushing the turn's ╭─ opening line out of view. */
@@ -30190,6 +30198,23 @@ var require_dist2 = __commonJS({
30190
30198
  providerResolutionMeta;
30191
30199
  static FINISH_RETRY_DELAY_MS = 300;
30192
30200
  static MAX_FINISH_RETRIES = 2;
30201
+ getBufferState() {
30202
+ const build = (droppedChars, maxChars) => droppedChars > 0 ? { truncated: true, droppedChars, maxChars } : void 0;
30203
+ const responseBuffer = build(this.responseBufferDroppedChars, _ProviderCliAdapter.MAX_RESPONSE_BUFFER);
30204
+ const recentOutputBuffer = build(this.recentOutputDroppedChars, _ProviderCliAdapter.MAX_RECENT_OUTPUT_BUFFER);
30205
+ const accumulatedBuffer = build(this.accumulatedBufferDroppedChars, _ProviderCliAdapter.MAX_ACCUMULATED_BUFFER);
30206
+ const accumulatedRawBuffer = build(this.accumulatedRawBufferDroppedChars, _ProviderCliAdapter.MAX_ACCUMULATED_BUFFER);
30207
+ if (!responseBuffer && !recentOutputBuffer && !accumulatedBuffer && !accumulatedRawBuffer) return void 0;
30208
+ return {
30209
+ ...responseBuffer ? { responseBuffer } : {},
30210
+ ...recentOutputBuffer ? { recentOutputBuffer } : {},
30211
+ ...accumulatedBuffer ? { accumulatedBuffer } : {},
30212
+ ...accumulatedRawBuffer ? { accumulatedRawBuffer } : {}
30213
+ };
30214
+ }
30215
+ recordBoundedAppendDrop(previousLength, appendedLength, nextLength) {
30216
+ return Math.max(0, previousLength + appendedLength - nextLength);
30217
+ }
30193
30218
  buildCommittedMessagesActivitySignature() {
30194
30219
  const last = this.committedMessages[this.committedMessages.length - 1];
30195
30220
  return [
@@ -30373,6 +30398,7 @@ var require_dist2 = __commonJS({
30373
30398
  sendDelayMs;
30374
30399
  sendKey;
30375
30400
  submitStrategy;
30401
+ requirePromptEchoBeforeSubmit;
30376
30402
  static SCRIPT_STATUS_DEBOUNCE_MS = 3e3;
30377
30403
  /** Inject CLI scripts after construction (e.g. when resolved by ProviderLoader) */
30378
30404
  setCliScripts(scripts) {
@@ -30554,7 +30580,9 @@ var require_dist2 = __commonJS({
30554
30580
  this.scheduleStartupSettleCheck();
30555
30581
  }
30556
30582
  if (this.isWaitingForResponse && cleanData) {
30557
- this.responseBuffer = appendBoundedText(this.responseBuffer, cleanData, 8e3);
30583
+ const previousResponseLen = this.responseBuffer.length;
30584
+ this.responseBuffer = appendBoundedText(this.responseBuffer, cleanData, _ProviderCliAdapter.MAX_RESPONSE_BUFFER);
30585
+ this.responseBufferDroppedChars += this.recordBoundedAppendDrop(previousResponseLen, cleanData.length, this.responseBuffer.length);
30558
30586
  }
30559
30587
  if (cleanData.trim()) {
30560
30588
  if (this.serverConn) {
@@ -30563,14 +30591,19 @@ var require_dist2 = __commonJS({
30563
30591
  this.logBuffer.push({ message: cleanData.trim(), level: "info" });
30564
30592
  }
30565
30593
  }
30594
+ const prevRecentLen = this.recentOutputBuffer.length;
30566
30595
  const prevAccumulatedLen = this.accumulatedBuffer.length;
30567
30596
  const prevAccumulatedRawLen = this.accumulatedRawBuffer.length;
30568
- this.recentOutputBuffer = appendBoundedText(this.recentOutputBuffer, cleanData, 1e3);
30597
+ this.recentOutputBuffer = appendBoundedText(this.recentOutputBuffer, cleanData, _ProviderCliAdapter.MAX_RECENT_OUTPUT_BUFFER);
30569
30598
  this.accumulatedBuffer = appendBoundedText(this.accumulatedBuffer, cleanData, _ProviderCliAdapter.MAX_ACCUMULATED_BUFFER);
30570
30599
  this.accumulatedRawBuffer = appendBoundedText(this.accumulatedRawBuffer, rawData, _ProviderCliAdapter.MAX_ACCUMULATED_BUFFER);
30600
+ const droppedRecent = this.recordBoundedAppendDrop(prevRecentLen, cleanData.length, this.recentOutputBuffer.length);
30601
+ const droppedClean = this.recordBoundedAppendDrop(prevAccumulatedLen, cleanData.length, this.accumulatedBuffer.length);
30602
+ const droppedRaw = this.recordBoundedAppendDrop(prevAccumulatedRawLen, rawData.length, this.accumulatedRawBuffer.length);
30603
+ this.recentOutputDroppedChars += droppedRecent;
30604
+ this.accumulatedBufferDroppedChars += droppedClean;
30605
+ this.accumulatedRawBufferDroppedChars += droppedRaw;
30571
30606
  if (this.currentTurnScope) {
30572
- const droppedClean = prevAccumulatedLen + cleanData.length - this.accumulatedBuffer.length;
30573
- const droppedRaw = prevAccumulatedRawLen + rawData.length - this.accumulatedRawBuffer.length;
30574
30607
  if (droppedClean > 0) {
30575
30608
  this.currentTurnScope.bufferStart = Math.max(0, this.currentTurnScope.bufferStart - droppedClean);
30576
30609
  }
@@ -31400,13 +31433,15 @@ var require_dist2 = __commonJS({
31400
31433
  effectiveModal = parsedModal;
31401
31434
  }
31402
31435
  }
31436
+ const bufferState = this.getBufferState();
31403
31437
  return {
31404
31438
  status: effectiveStatus,
31405
31439
  messages: [...this.committedMessages],
31406
31440
  workingDir: this.workingDir,
31407
31441
  activeModal: effectiveModal,
31408
31442
  errorMessage: this.parseErrorMessage || void 0,
31409
- errorReason: this.parseErrorMessage ? "parse_error" : void 0
31443
+ errorReason: this.parseErrorMessage ? "parse_error" : void 0,
31444
+ ...bufferState ? { bufferState } : {}
31410
31445
  };
31411
31446
  }
31412
31447
  seedCommittedMessages(messages) {
@@ -31588,10 +31623,12 @@ var require_dist2 = __commonJS({
31588
31623
  messages: hydratedMessages,
31589
31624
  activeModal: parsed.activeModal ?? this.activeModal,
31590
31625
  providerSessionId: typeof parsed.providerSessionId === "string" ? parsed.providerSessionId : void 0,
31626
+ ...this.getBufferState() ? { bufferState: this.getBufferState() } : {},
31591
31627
  ...this.providerOwnsTranscript() ? { transcriptAuthority: "provider", coverage: this.shouldUseFullProviderTranscriptContext() ? "full" : "tail" } : {}
31592
31628
  };
31593
31629
  } else {
31594
31630
  const messages = [...this.committedMessages];
31631
+ const bufferState = this.getBufferState();
31595
31632
  result = {
31596
31633
  id: "cli_session",
31597
31634
  status: this.currentStatus,
@@ -31602,7 +31639,8 @@ var require_dist2 = __commonJS({
31602
31639
  index: typeof message.index === "number" ? message.index : index,
31603
31640
  receivedAt: typeof message.receivedAt === "number" ? message.receivedAt : message.timestamp
31604
31641
  })),
31605
- activeModal: this.activeModal
31642
+ activeModal: this.activeModal,
31643
+ ...bufferState ? { bufferState } : {}
31606
31644
  };
31607
31645
  }
31608
31646
  const hasVisibleAssistantMessage = Array.isArray(result?.messages) && result.messages.some((message) => message?.role === "assistant" && typeof message?.content === "string" && message.content.trim());
@@ -31893,6 +31931,22 @@ var require_dist2 = __commonJS({
31893
31931
  }
31894
31932
  }
31895
31933
  if (elapsed >= state.maxEchoWaitMs) {
31934
+ const diagnostic = {
31935
+ elapsed,
31936
+ maxEchoWaitMs: state.maxEchoWaitMs,
31937
+ submitDelayMs: state.submitDelayMs,
31938
+ promptSnippet: state.normalizedPromptSnippet,
31939
+ requirePromptEchoBeforeSubmit: this.requirePromptEchoBeforeSubmit,
31940
+ screenText: summarizeCliTraceText(screenText, 1e3)
31941
+ };
31942
+ this.recordTrace("submit_echo_missing", diagnostic);
31943
+ if (this.requirePromptEchoBeforeSubmit) {
31944
+ const message = `${this.cliName} prompt echo was not observed on the PTY screen before submit`;
31945
+ LOG2.warn("CLI", `[${this.cliType}] ${message} elapsed=${elapsed}ms maxEchoWaitMs=${state.maxEchoWaitMs} screen=${JSON.stringify(diagnostic.screenText).slice(0, 240)}`);
31946
+ completion.rejectOnce(new Error(message));
31947
+ return;
31948
+ }
31949
+ LOG2.warn("CLI", `[${this.cliType}] prompt echo was not observed before submit; sending submit key anyway elapsed=${elapsed}ms maxEchoWaitMs=${state.maxEchoWaitMs}`);
31896
31950
  this.submitSendKey(state, completion);
31897
31951
  return;
31898
31952
  }
@@ -32357,6 +32411,7 @@ var require_dist2 = __commonJS({
32357
32411
  sendDelayMs: this.sendDelayMs,
32358
32412
  sendKey: this.sendKey,
32359
32413
  submitStrategy: this.submitStrategy,
32414
+ requirePromptEchoBeforeSubmit: this.requirePromptEchoBeforeSubmit,
32360
32415
  submitPendingUntil: this.submitPendingUntil,
32361
32416
  responseSettleIgnoreUntil: this.responseSettleIgnoreUntil,
32362
32417
  resizeSuppressUntil: this.resizeSuppressUntil,
@@ -32442,6 +32497,7 @@ var require_dist2 = __commonJS({
32442
32497
  ProviderLoader: () => ProviderLoader,
32443
32498
  STANDALONE_CDP_SCAN_INTERVAL_MS: () => STANDALONE_CDP_SCAN_INTERVAL_MS2,
32444
32499
  SessionHostPtyTransportFactory: () => SessionHostPtyTransportFactory2,
32500
+ TurnSnapshotTracker: () => TurnSnapshotTracker,
32445
32501
  VersionArchive: () => VersionArchive,
32446
32502
  appendRecentActivity: () => appendRecentActivity,
32447
32503
  buildAssistantChatMessage: () => buildAssistantChatMessage,
@@ -33439,13 +33495,8 @@ var require_dist2 = __commonJS({
33439
33495
  "git_checkpoint",
33440
33496
  "git_stash_push",
33441
33497
  "git_stash_pop",
33442
- "git_checkout_files"
33443
- ]);
33444
- var MUTATING_COMMAND_NAMES = /* @__PURE__ */ new Set([
33445
- "git_checkpoint",
33446
- "git_stash_push",
33447
- "git_stash_pop",
33448
- "git_checkout_files"
33498
+ "git_checkout_files",
33499
+ "git_remote_url"
33449
33500
  ]);
33450
33501
  var SNAPSHOT_REASONS = /* @__PURE__ */ new Set([
33451
33502
  "session_baseline",
@@ -33486,7 +33537,12 @@ var require_dist2 = __commonJS({
33486
33537
  turnId
33487
33538
  }),
33488
33539
  compareSnapshots: ({ beforeSnapshotId, afterSnapshotId }) => defaultSnapshotStore.compare(beforeSnapshotId, afterSnapshotId),
33489
- getLog: ({ workspace, limit, path: filePath, since, until }) => getGitLog(workspace, { limit, path: filePath, since, until })
33540
+ getLog: ({ workspace, limit, path: filePath, since, until }) => getGitLog(workspace, { limit, path: filePath, since, until }),
33541
+ checkpoint: async ({ workspace, message, includeUntracked = false }) => gitCheckpoint(workspace, message, includeUntracked),
33542
+ stashPush: async ({ workspace, message, includeUntracked = false }) => gitStashPush(workspace, message, includeUntracked),
33543
+ stashPop: async ({ workspace, stashRef }) => gitStashPop(workspace, stashRef),
33544
+ checkoutFiles: async ({ workspace, paths }) => gitCheckoutFiles(workspace, paths),
33545
+ getRemoteUrl: async ({ workspace, remote = "origin" }) => gitGetRemoteUrl(workspace, remote)
33490
33546
  };
33491
33547
  }
33492
33548
  var defaultGitCommandServices = createDefaultGitCommandServices();
@@ -33550,9 +33606,6 @@ var require_dist2 = __commonJS({
33550
33606
  if (!isGitCommandName(command)) {
33551
33607
  return failure("invalid_args", `Unknown Git command: ${command}`);
33552
33608
  }
33553
- if (MUTATING_COMMAND_NAMES.has(command)) {
33554
- return failure("invalid_args", `${command} is not implemented in daemon-core read-only Git routing`);
33555
- }
33556
33609
  const workspaceResult = validateWorkspace2(args);
33557
33610
  if ("success" in workspaceResult) return workspaceResult;
33558
33611
  const { workspace } = workspaceResult;
@@ -33612,10 +33665,153 @@ var require_dist2 = __commonJS({
33612
33665
  }));
33613
33666
  return "success" in log ? log : { success: true, log };
33614
33667
  }
33668
+ case "git_checkpoint": {
33669
+ if (!services.checkpoint) return serviceNotImplemented(command);
33670
+ const msg = validateMutatingMessage(args?.message);
33671
+ if (typeof msg !== "string") return msg;
33672
+ const includeUntracked = Boolean(args?.includeUntracked);
33673
+ const checkpoint = await runService(() => services.checkpoint({ workspace, message: msg, includeUntracked }));
33674
+ return "success" in checkpoint ? checkpoint : { success: true, checkpoint };
33675
+ }
33676
+ case "git_stash_push": {
33677
+ if (!services.stashPush) return serviceNotImplemented(command);
33678
+ const msg = validateMutatingMessage(args?.message);
33679
+ if (typeof msg !== "string") return msg;
33680
+ const includeUntracked = Boolean(args?.includeUntracked);
33681
+ const stash = await runService(() => services.stashPush({ workspace, message: msg, includeUntracked }));
33682
+ return "success" in stash ? stash : { success: true, stash };
33683
+ }
33684
+ case "git_stash_pop": {
33685
+ if (!services.stashPop) return serviceNotImplemented(command);
33686
+ const stashRef = optionalString(args?.stashRef);
33687
+ if (stashRef !== void 0 && !/^stash@\{\d+\}$/.test(stashRef)) {
33688
+ return failure("invalid_args", "stashRef must match stash@{N} format");
33689
+ }
33690
+ const popResult = await runService(() => services.stashPop({ workspace, stashRef }));
33691
+ if (popResult !== void 0 && "success" in popResult) return popResult;
33692
+ return { success: true, stashPopped: true };
33693
+ }
33694
+ case "git_checkout_files": {
33695
+ if (!services.checkoutFiles) return serviceNotImplemented(command);
33696
+ const paths = args?.paths;
33697
+ if (!Array.isArray(paths) || paths.length === 0) {
33698
+ return failure("invalid_args", "paths must be a non-empty array");
33699
+ }
33700
+ if (paths.length > 50) {
33701
+ return failure("invalid_args", "paths array exceeds maximum of 50 entries");
33702
+ }
33703
+ const checkoutResult = await runService(() => services.checkoutFiles({ workspace, paths }));
33704
+ return "success" in checkoutResult ? checkoutResult : { success: true, checkedOut: checkoutResult.checkedOut };
33705
+ }
33706
+ case "git_remote_url": {
33707
+ if (!services.getRemoteUrl) return serviceNotImplemented(command);
33708
+ const remote = typeof args?.remote === "string" && args.remote.trim() ? args.remote.trim() : "origin";
33709
+ const remoteResult = await runService(() => services.getRemoteUrl({ workspace, remote }));
33710
+ if ("success" in remoteResult) return remoteResult;
33711
+ return { success: true, remoteUrl: remoteResult.remoteUrl, remote: remoteResult.remote };
33712
+ }
33615
33713
  default:
33616
33714
  return failure("invalid_args", `Unknown Git command: ${command}`);
33617
33715
  }
33618
33716
  }
33717
+ function validateMutatingMessage(value) {
33718
+ if (typeof value !== "string" || !value.trim()) {
33719
+ return failure("invalid_args", "message must be a non-empty string");
33720
+ }
33721
+ const msg = value.trim();
33722
+ if (msg.length > 200) {
33723
+ return failure("invalid_args", "message must be 200 characters or fewer");
33724
+ }
33725
+ return msg;
33726
+ }
33727
+ async function gitCheckpoint(workspace, message, includeUntracked) {
33728
+ const repo = await resolveGitRepository(workspace);
33729
+ const repoRoot = repo.repoRoot;
33730
+ const statusResult = await getGitRepoStatus(workspace);
33731
+ if (statusResult.hasConflicts) {
33732
+ throw new GitCommandError("conflict", "Repository has conflicts \u2014 resolve before checkpointing");
33733
+ }
33734
+ const addArgs = includeUntracked ? ["-A"] : ["-u"];
33735
+ await runGit(repo, ["add", ...addArgs], { cwd: repoRoot });
33736
+ const fullMsg = `adhdev: checkpoint ${message}`;
33737
+ let commitSha;
33738
+ try {
33739
+ await runGit(repo, ["commit", "-m", fullMsg], { cwd: repoRoot });
33740
+ const revResult = await runGit(repo, ["rev-parse", "HEAD"], { cwd: repoRoot });
33741
+ commitSha = revResult.stdout.trim();
33742
+ } catch (err) {
33743
+ const output = (err?.stdout || "") + (err?.stderr || "");
33744
+ if (/nothing to commit/i.test(output)) {
33745
+ throw new GitCommandError("git_command_failed", "Nothing to commit");
33746
+ }
33747
+ throw err;
33748
+ }
33749
+ return {
33750
+ workspace: repo.workspace,
33751
+ repoRoot,
33752
+ isGitRepo: true,
33753
+ commit: commitSha,
33754
+ message: fullMsg,
33755
+ lastCheckedAt: Date.now()
33756
+ };
33757
+ }
33758
+ async function gitStashPush(workspace, message, includeUntracked) {
33759
+ const repo = await resolveGitRepository(workspace);
33760
+ const repoRoot = repo.repoRoot;
33761
+ const stashArgs = ["stash", "push", "-m", message];
33762
+ if (includeUntracked) stashArgs.push("--include-untracked");
33763
+ const result = await runGit(repo, stashArgs, { cwd: repoRoot });
33764
+ if (/No local changes to save/i.test(result.stdout + result.stderr)) {
33765
+ throw new GitCommandError("git_command_failed", "Nothing to stash");
33766
+ }
33767
+ return {
33768
+ workspace: repo.workspace,
33769
+ repoRoot,
33770
+ isGitRepo: true,
33771
+ stashRef: "stash@{0}",
33772
+ message,
33773
+ lastCheckedAt: Date.now()
33774
+ };
33775
+ }
33776
+ async function gitStashPop(workspace, stashRef) {
33777
+ const repo = await resolveGitRepository(workspace);
33778
+ const repoRoot = repo.repoRoot;
33779
+ const popArgs = stashRef ? ["stash", "pop", stashRef] : ["stash", "pop"];
33780
+ await runGit(repo, popArgs, { cwd: repoRoot });
33781
+ }
33782
+ async function gitCheckoutFiles(workspace, paths) {
33783
+ const repo = await resolveGitRepository(workspace);
33784
+ const repoRoot = repo.repoRoot;
33785
+ const normalizedPaths = [];
33786
+ for (const p of paths) {
33787
+ if (typeof p !== "string" || !p.trim() || p.includes("\0")) {
33788
+ throw new GitCommandError("invalid_args", `Invalid path: ${String(p)}`);
33789
+ }
33790
+ if (path32.isAbsolute(p)) {
33791
+ throw new GitCommandError("invalid_args", `Path must be repository-relative, not absolute: ${p}`);
33792
+ }
33793
+ const normalized = path32.normalize(p.trim()).split(path32.sep).join("/");
33794
+ if (normalized.startsWith("../") || normalized === "..") {
33795
+ throw new GitCommandError("path_outside_repo", `Path is outside repository root: ${p}`);
33796
+ }
33797
+ const absolutePath = path32.resolve(repoRoot, normalized);
33798
+ if (!isPathInside(repoRoot, absolutePath)) {
33799
+ throw new GitCommandError("path_outside_repo", `Path is outside repository root: ${p}`);
33800
+ }
33801
+ normalizedPaths.push(normalized);
33802
+ }
33803
+ await runGit(repo, ["checkout", "--", ...normalizedPaths], { cwd: repoRoot });
33804
+ return { checkedOut: normalizedPaths };
33805
+ }
33806
+ async function gitGetRemoteUrl(workspace, remote) {
33807
+ const repo = await resolveGitRepository(workspace);
33808
+ const result = await runGit(repo, ["remote", "get-url", remote], { cwd: repo.repoRoot });
33809
+ const remoteUrl = result.stdout.trim();
33810
+ if (!remoteUrl) {
33811
+ throw new GitCommandError("git_command_failed", `Remote '${remote}' has no URL`);
33812
+ }
33813
+ return { remoteUrl, remote };
33814
+ }
33619
33815
  function formatOptionalGitLogRangeArg(flag, value) {
33620
33816
  return value ? [`${flag}=${value}`] : [];
33621
33817
  }
@@ -33673,6 +33869,25 @@ var require_dist2 = __commonJS({
33673
33869
  }
33674
33870
  return normalized;
33675
33871
  }
33872
+ var BUSY_STATUSES = /* @__PURE__ */ new Set(["streaming", "waiting_approval"]);
33873
+ var TERMINAL_STATUSES = /* @__PURE__ */ new Set(["idle", "error"]);
33874
+ var TurnSnapshotTracker = class {
33875
+ lastStatus = /* @__PURE__ */ new Map();
33876
+ onTurnCompleted;
33877
+ constructor(onTurnCompleted) {
33878
+ this.onTurnCompleted = onTurnCompleted;
33879
+ }
33880
+ record(sessionId, status, workspace) {
33881
+ const prev = this.lastStatus.get(sessionId);
33882
+ this.lastStatus.set(sessionId, status);
33883
+ if (workspace && prev && BUSY_STATUSES.has(prev) && TERMINAL_STATUSES.has(status)) {
33884
+ this.onTurnCompleted({ sessionId, workspace });
33885
+ }
33886
+ }
33887
+ forget(sessionId) {
33888
+ this.lastStatus.delete(sessionId);
33889
+ }
33890
+ };
33676
33891
  init_config();
33677
33892
  var fs5 = __toESM2(require("fs"));
33678
33893
  var os6 = __toESM2(require("os"));
@@ -42463,6 +42678,16 @@ ${effect.notification.body || ""}`.trim();
42463
42678
  return result;
42464
42679
  }
42465
42680
  }
42681
+ if (cmd === "send_chat" && this._ctx.onBeforeSendChat) {
42682
+ const sessionId = this._currentRoute.session?.sessionId;
42683
+ const workspace = sessionId ? this._ctx.instanceManager?.getInstance(sessionId)?.getState?.()?.workspace : void 0;
42684
+ if (workspace && sessionId) {
42685
+ try {
42686
+ this._ctx.onBeforeSendChat({ workspace, sessionId });
42687
+ } catch {
42688
+ }
42689
+ }
42690
+ }
42466
42691
  try {
42467
42692
  result = await this.dispatch(cmd, args);
42468
42693
  this.logCommandEnd(cmd, result, startedAt);
@@ -45676,6 +45901,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
45676
45901
  "sendDelayMs",
45677
45902
  "sendKey",
45678
45903
  "submitStrategy",
45904
+ "requirePromptEchoBeforeSubmit",
45679
45905
  "timeouts",
45680
45906
  "disableUpstream"
45681
45907
  ]);
@@ -57123,6 +57349,7 @@ data: ${JSON.stringify(msg.data)}
57123
57349
  providerLoader,
57124
57350
  instanceManager,
57125
57351
  sessionRegistry,
57352
+ gitCommandServices: createDefaultGitCommandServices(),
57126
57353
  onProviderSettingChanged: async (providerType) => {
57127
57354
  await refreshProviderAvailability(providerType);
57128
57355
  config2.onStatusChange?.();
@@ -57130,7 +57357,8 @@ data: ${JSON.stringify(msg.data)}
57130
57357
  onProviderSourceConfigChanged: async () => {
57131
57358
  await refreshProviderAvailability();
57132
57359
  config2.onStatusChange?.();
57133
- }
57360
+ },
57361
+ onBeforeSendChat: config2.onBeforeSendChat
57134
57362
  });
57135
57363
  agentStreamManager = new DaemonAgentStreamManager(
57136
57364
  LOG2.forComponent("AgentStream").asLogFn(),
@@ -59266,7 +59494,8 @@ var StandaloneServer = class {
59266
59494
  })),
59267
59495
  instanceId: `standalone_${machineId}`,
59268
59496
  version: pkgVersion,
59269
- profile
59497
+ profile,
59498
+ getGitSummaryForWorkspace: (workspace) => this.gitWorkspaceMonitor.getCompactSummary(workspace)
59270
59499
  });
59271
59500
  }
59272
59501
  async pushWsRuntimeSnapshots(ws2) {