@adhdev/daemon-standalone 0.9.54 → 0.9.55

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);
@@ -30373,6 +30375,7 @@ var require_dist2 = __commonJS({
30373
30375
  sendDelayMs;
30374
30376
  sendKey;
30375
30377
  submitStrategy;
30378
+ requirePromptEchoBeforeSubmit;
30376
30379
  static SCRIPT_STATUS_DEBOUNCE_MS = 3e3;
30377
30380
  /** Inject CLI scripts after construction (e.g. when resolved by ProviderLoader) */
30378
30381
  setCliScripts(scripts) {
@@ -31893,6 +31896,22 @@ var require_dist2 = __commonJS({
31893
31896
  }
31894
31897
  }
31895
31898
  if (elapsed >= state.maxEchoWaitMs) {
31899
+ const diagnostic = {
31900
+ elapsed,
31901
+ maxEchoWaitMs: state.maxEchoWaitMs,
31902
+ submitDelayMs: state.submitDelayMs,
31903
+ promptSnippet: state.normalizedPromptSnippet,
31904
+ requirePromptEchoBeforeSubmit: this.requirePromptEchoBeforeSubmit,
31905
+ screenText: summarizeCliTraceText(screenText, 1e3)
31906
+ };
31907
+ this.recordTrace("submit_echo_missing", diagnostic);
31908
+ if (this.requirePromptEchoBeforeSubmit) {
31909
+ const message = `${this.cliName} prompt echo was not observed on the PTY screen before submit`;
31910
+ LOG2.warn("CLI", `[${this.cliType}] ${message} elapsed=${elapsed}ms maxEchoWaitMs=${state.maxEchoWaitMs} screen=${JSON.stringify(diagnostic.screenText).slice(0, 240)}`);
31911
+ completion.rejectOnce(new Error(message));
31912
+ return;
31913
+ }
31914
+ LOG2.warn("CLI", `[${this.cliType}] prompt echo was not observed before submit; sending submit key anyway elapsed=${elapsed}ms maxEchoWaitMs=${state.maxEchoWaitMs}`);
31896
31915
  this.submitSendKey(state, completion);
31897
31916
  return;
31898
31917
  }
@@ -32357,6 +32376,7 @@ var require_dist2 = __commonJS({
32357
32376
  sendDelayMs: this.sendDelayMs,
32358
32377
  sendKey: this.sendKey,
32359
32378
  submitStrategy: this.submitStrategy,
32379
+ requirePromptEchoBeforeSubmit: this.requirePromptEchoBeforeSubmit,
32360
32380
  submitPendingUntil: this.submitPendingUntil,
32361
32381
  responseSettleIgnoreUntil: this.responseSettleIgnoreUntil,
32362
32382
  resizeSuppressUntil: this.resizeSuppressUntil,
@@ -32442,6 +32462,7 @@ var require_dist2 = __commonJS({
32442
32462
  ProviderLoader: () => ProviderLoader,
32443
32463
  STANDALONE_CDP_SCAN_INTERVAL_MS: () => STANDALONE_CDP_SCAN_INTERVAL_MS2,
32444
32464
  SessionHostPtyTransportFactory: () => SessionHostPtyTransportFactory2,
32465
+ TurnSnapshotTracker: () => TurnSnapshotTracker,
32445
32466
  VersionArchive: () => VersionArchive,
32446
32467
  appendRecentActivity: () => appendRecentActivity,
32447
32468
  buildAssistantChatMessage: () => buildAssistantChatMessage,
@@ -33439,13 +33460,8 @@ var require_dist2 = __commonJS({
33439
33460
  "git_checkpoint",
33440
33461
  "git_stash_push",
33441
33462
  "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"
33463
+ "git_checkout_files",
33464
+ "git_remote_url"
33449
33465
  ]);
33450
33466
  var SNAPSHOT_REASONS = /* @__PURE__ */ new Set([
33451
33467
  "session_baseline",
@@ -33486,7 +33502,12 @@ var require_dist2 = __commonJS({
33486
33502
  turnId
33487
33503
  }),
33488
33504
  compareSnapshots: ({ beforeSnapshotId, afterSnapshotId }) => defaultSnapshotStore.compare(beforeSnapshotId, afterSnapshotId),
33489
- getLog: ({ workspace, limit, path: filePath, since, until }) => getGitLog(workspace, { limit, path: filePath, since, until })
33505
+ getLog: ({ workspace, limit, path: filePath, since, until }) => getGitLog(workspace, { limit, path: filePath, since, until }),
33506
+ checkpoint: async ({ workspace, message, includeUntracked = false }) => gitCheckpoint(workspace, message, includeUntracked),
33507
+ stashPush: async ({ workspace, message, includeUntracked = false }) => gitStashPush(workspace, message, includeUntracked),
33508
+ stashPop: async ({ workspace, stashRef }) => gitStashPop(workspace, stashRef),
33509
+ checkoutFiles: async ({ workspace, paths }) => gitCheckoutFiles(workspace, paths),
33510
+ getRemoteUrl: async ({ workspace, remote = "origin" }) => gitGetRemoteUrl(workspace, remote)
33490
33511
  };
33491
33512
  }
33492
33513
  var defaultGitCommandServices = createDefaultGitCommandServices();
@@ -33550,9 +33571,6 @@ var require_dist2 = __commonJS({
33550
33571
  if (!isGitCommandName(command)) {
33551
33572
  return failure("invalid_args", `Unknown Git command: ${command}`);
33552
33573
  }
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
33574
  const workspaceResult = validateWorkspace2(args);
33557
33575
  if ("success" in workspaceResult) return workspaceResult;
33558
33576
  const { workspace } = workspaceResult;
@@ -33612,10 +33630,153 @@ var require_dist2 = __commonJS({
33612
33630
  }));
33613
33631
  return "success" in log ? log : { success: true, log };
33614
33632
  }
33633
+ case "git_checkpoint": {
33634
+ if (!services.checkpoint) return serviceNotImplemented(command);
33635
+ const msg = validateMutatingMessage(args?.message);
33636
+ if (typeof msg !== "string") return msg;
33637
+ const includeUntracked = Boolean(args?.includeUntracked);
33638
+ const checkpoint = await runService(() => services.checkpoint({ workspace, message: msg, includeUntracked }));
33639
+ return "success" in checkpoint ? checkpoint : { success: true, checkpoint };
33640
+ }
33641
+ case "git_stash_push": {
33642
+ if (!services.stashPush) return serviceNotImplemented(command);
33643
+ const msg = validateMutatingMessage(args?.message);
33644
+ if (typeof msg !== "string") return msg;
33645
+ const includeUntracked = Boolean(args?.includeUntracked);
33646
+ const stash = await runService(() => services.stashPush({ workspace, message: msg, includeUntracked }));
33647
+ return "success" in stash ? stash : { success: true, stash };
33648
+ }
33649
+ case "git_stash_pop": {
33650
+ if (!services.stashPop) return serviceNotImplemented(command);
33651
+ const stashRef = optionalString(args?.stashRef);
33652
+ if (stashRef !== void 0 && !/^stash@\{\d+\}$/.test(stashRef)) {
33653
+ return failure("invalid_args", "stashRef must match stash@{N} format");
33654
+ }
33655
+ const popResult = await runService(() => services.stashPop({ workspace, stashRef }));
33656
+ if (popResult !== void 0 && "success" in popResult) return popResult;
33657
+ return { success: true, stashPopped: true };
33658
+ }
33659
+ case "git_checkout_files": {
33660
+ if (!services.checkoutFiles) return serviceNotImplemented(command);
33661
+ const paths = args?.paths;
33662
+ if (!Array.isArray(paths) || paths.length === 0) {
33663
+ return failure("invalid_args", "paths must be a non-empty array");
33664
+ }
33665
+ if (paths.length > 50) {
33666
+ return failure("invalid_args", "paths array exceeds maximum of 50 entries");
33667
+ }
33668
+ const checkoutResult = await runService(() => services.checkoutFiles({ workspace, paths }));
33669
+ return "success" in checkoutResult ? checkoutResult : { success: true, checkedOut: checkoutResult.checkedOut };
33670
+ }
33671
+ case "git_remote_url": {
33672
+ if (!services.getRemoteUrl) return serviceNotImplemented(command);
33673
+ const remote = typeof args?.remote === "string" && args.remote.trim() ? args.remote.trim() : "origin";
33674
+ const remoteResult = await runService(() => services.getRemoteUrl({ workspace, remote }));
33675
+ if ("success" in remoteResult) return remoteResult;
33676
+ return { success: true, remoteUrl: remoteResult.remoteUrl, remote: remoteResult.remote };
33677
+ }
33615
33678
  default:
33616
33679
  return failure("invalid_args", `Unknown Git command: ${command}`);
33617
33680
  }
33618
33681
  }
33682
+ function validateMutatingMessage(value) {
33683
+ if (typeof value !== "string" || !value.trim()) {
33684
+ return failure("invalid_args", "message must be a non-empty string");
33685
+ }
33686
+ const msg = value.trim();
33687
+ if (msg.length > 200) {
33688
+ return failure("invalid_args", "message must be 200 characters or fewer");
33689
+ }
33690
+ return msg;
33691
+ }
33692
+ async function gitCheckpoint(workspace, message, includeUntracked) {
33693
+ const repo = await resolveGitRepository(workspace);
33694
+ const repoRoot = repo.repoRoot;
33695
+ const statusResult = await getGitRepoStatus(workspace);
33696
+ if (statusResult.hasConflicts) {
33697
+ throw new GitCommandError("conflict", "Repository has conflicts \u2014 resolve before checkpointing");
33698
+ }
33699
+ const addArgs = includeUntracked ? ["-A"] : ["-u"];
33700
+ await runGit(repo, ["add", ...addArgs], { cwd: repoRoot });
33701
+ const fullMsg = `adhdev: checkpoint ${message}`;
33702
+ let commitSha;
33703
+ try {
33704
+ await runGit(repo, ["commit", "-m", fullMsg], { cwd: repoRoot });
33705
+ const revResult = await runGit(repo, ["rev-parse", "HEAD"], { cwd: repoRoot });
33706
+ commitSha = revResult.stdout.trim();
33707
+ } catch (err) {
33708
+ const output = (err?.stdout || "") + (err?.stderr || "");
33709
+ if (/nothing to commit/i.test(output)) {
33710
+ throw new GitCommandError("git_command_failed", "Nothing to commit");
33711
+ }
33712
+ throw err;
33713
+ }
33714
+ return {
33715
+ workspace: repo.workspace,
33716
+ repoRoot,
33717
+ isGitRepo: true,
33718
+ commit: commitSha,
33719
+ message: fullMsg,
33720
+ lastCheckedAt: Date.now()
33721
+ };
33722
+ }
33723
+ async function gitStashPush(workspace, message, includeUntracked) {
33724
+ const repo = await resolveGitRepository(workspace);
33725
+ const repoRoot = repo.repoRoot;
33726
+ const stashArgs = ["stash", "push", "-m", message];
33727
+ if (includeUntracked) stashArgs.push("--include-untracked");
33728
+ const result = await runGit(repo, stashArgs, { cwd: repoRoot });
33729
+ if (/No local changes to save/i.test(result.stdout + result.stderr)) {
33730
+ throw new GitCommandError("git_command_failed", "Nothing to stash");
33731
+ }
33732
+ return {
33733
+ workspace: repo.workspace,
33734
+ repoRoot,
33735
+ isGitRepo: true,
33736
+ stashRef: "stash@{0}",
33737
+ message,
33738
+ lastCheckedAt: Date.now()
33739
+ };
33740
+ }
33741
+ async function gitStashPop(workspace, stashRef) {
33742
+ const repo = await resolveGitRepository(workspace);
33743
+ const repoRoot = repo.repoRoot;
33744
+ const popArgs = stashRef ? ["stash", "pop", stashRef] : ["stash", "pop"];
33745
+ await runGit(repo, popArgs, { cwd: repoRoot });
33746
+ }
33747
+ async function gitCheckoutFiles(workspace, paths) {
33748
+ const repo = await resolveGitRepository(workspace);
33749
+ const repoRoot = repo.repoRoot;
33750
+ const normalizedPaths = [];
33751
+ for (const p of paths) {
33752
+ if (typeof p !== "string" || !p.trim() || p.includes("\0")) {
33753
+ throw new GitCommandError("invalid_args", `Invalid path: ${String(p)}`);
33754
+ }
33755
+ if (path32.isAbsolute(p)) {
33756
+ throw new GitCommandError("invalid_args", `Path must be repository-relative, not absolute: ${p}`);
33757
+ }
33758
+ const normalized = path32.normalize(p.trim()).split(path32.sep).join("/");
33759
+ if (normalized.startsWith("../") || normalized === "..") {
33760
+ throw new GitCommandError("path_outside_repo", `Path is outside repository root: ${p}`);
33761
+ }
33762
+ const absolutePath = path32.resolve(repoRoot, normalized);
33763
+ if (!isPathInside(repoRoot, absolutePath)) {
33764
+ throw new GitCommandError("path_outside_repo", `Path is outside repository root: ${p}`);
33765
+ }
33766
+ normalizedPaths.push(normalized);
33767
+ }
33768
+ await runGit(repo, ["checkout", "--", ...normalizedPaths], { cwd: repoRoot });
33769
+ return { checkedOut: normalizedPaths };
33770
+ }
33771
+ async function gitGetRemoteUrl(workspace, remote) {
33772
+ const repo = await resolveGitRepository(workspace);
33773
+ const result = await runGit(repo, ["remote", "get-url", remote], { cwd: repo.repoRoot });
33774
+ const remoteUrl = result.stdout.trim();
33775
+ if (!remoteUrl) {
33776
+ throw new GitCommandError("git_command_failed", `Remote '${remote}' has no URL`);
33777
+ }
33778
+ return { remoteUrl, remote };
33779
+ }
33619
33780
  function formatOptionalGitLogRangeArg(flag, value) {
33620
33781
  return value ? [`${flag}=${value}`] : [];
33621
33782
  }
@@ -33673,6 +33834,25 @@ var require_dist2 = __commonJS({
33673
33834
  }
33674
33835
  return normalized;
33675
33836
  }
33837
+ var BUSY_STATUSES = /* @__PURE__ */ new Set(["streaming", "waiting_approval"]);
33838
+ var TERMINAL_STATUSES = /* @__PURE__ */ new Set(["idle", "error"]);
33839
+ var TurnSnapshotTracker = class {
33840
+ lastStatus = /* @__PURE__ */ new Map();
33841
+ onTurnCompleted;
33842
+ constructor(onTurnCompleted) {
33843
+ this.onTurnCompleted = onTurnCompleted;
33844
+ }
33845
+ record(sessionId, status, workspace) {
33846
+ const prev = this.lastStatus.get(sessionId);
33847
+ this.lastStatus.set(sessionId, status);
33848
+ if (workspace && prev && BUSY_STATUSES.has(prev) && TERMINAL_STATUSES.has(status)) {
33849
+ this.onTurnCompleted({ sessionId, workspace });
33850
+ }
33851
+ }
33852
+ forget(sessionId) {
33853
+ this.lastStatus.delete(sessionId);
33854
+ }
33855
+ };
33676
33856
  init_config();
33677
33857
  var fs5 = __toESM2(require("fs"));
33678
33858
  var os6 = __toESM2(require("os"));
@@ -42463,6 +42643,16 @@ ${effect.notification.body || ""}`.trim();
42463
42643
  return result;
42464
42644
  }
42465
42645
  }
42646
+ if (cmd === "send_chat" && this._ctx.onBeforeSendChat) {
42647
+ const sessionId = this._currentRoute.session?.sessionId;
42648
+ const workspace = sessionId ? this._ctx.instanceManager?.getInstance(sessionId)?.getState?.()?.workspace : void 0;
42649
+ if (workspace && sessionId) {
42650
+ try {
42651
+ this._ctx.onBeforeSendChat({ workspace, sessionId });
42652
+ } catch {
42653
+ }
42654
+ }
42655
+ }
42466
42656
  try {
42467
42657
  result = await this.dispatch(cmd, args);
42468
42658
  this.logCommandEnd(cmd, result, startedAt);
@@ -45676,6 +45866,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
45676
45866
  "sendDelayMs",
45677
45867
  "sendKey",
45678
45868
  "submitStrategy",
45869
+ "requirePromptEchoBeforeSubmit",
45679
45870
  "timeouts",
45680
45871
  "disableUpstream"
45681
45872
  ]);
@@ -57123,6 +57314,7 @@ data: ${JSON.stringify(msg.data)}
57123
57314
  providerLoader,
57124
57315
  instanceManager,
57125
57316
  sessionRegistry,
57317
+ gitCommandServices: createDefaultGitCommandServices(),
57126
57318
  onProviderSettingChanged: async (providerType) => {
57127
57319
  await refreshProviderAvailability(providerType);
57128
57320
  config2.onStatusChange?.();
@@ -57130,7 +57322,8 @@ data: ${JSON.stringify(msg.data)}
57130
57322
  onProviderSourceConfigChanged: async () => {
57131
57323
  await refreshProviderAvailability();
57132
57324
  config2.onStatusChange?.();
57133
- }
57325
+ },
57326
+ onBeforeSendChat: config2.onBeforeSendChat
57134
57327
  });
57135
57328
  agentStreamManager = new DaemonAgentStreamManager(
57136
57329
  LOG2.forComponent("AgentStream").asLogFn(),
@@ -59266,7 +59459,8 @@ var StandaloneServer = class {
59266
59459
  })),
59267
59460
  instanceId: `standalone_${machineId}`,
59268
59461
  version: pkgVersion,
59269
- profile
59462
+ profile,
59463
+ getGitSummaryForWorkspace: (workspace) => this.gitWorkspaceMonitor.getCompactSummary(workspace)
59270
59464
  });
59271
59465
  }
59272
59466
  async pushWsRuntimeSnapshots(ws2) {