@adhdev/daemon-standalone 1.0.58-rc.53 → 1.0.58-rc.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
@@ -36911,10 +36911,10 @@ var require_dist3 = __commonJS({
36911
36911
  }
36912
36912
  function getDaemonBuildInfo() {
36913
36913
  if (cached2) return cached2;
36914
- const commit = readInjected(true ? "7335576b38c7efe574df77aa232271dca8221f88" : void 0) ?? "unknown";
36915
- const commitShort = readInjected(true ? "7335576b" : void 0) ?? (commit !== "unknown" ? commit.slice(0, 7) : "unknown");
36916
- const version2 = readInjected(true ? "1.0.58-rc.53" : void 0) ?? readInjected(typeof process !== "undefined" ? process.env?.ADHDEV_PKG_VERSION : void 0) ?? "unknown";
36917
- const builtAt = readInjected(true ? "2026-08-30T19:29:33.228Z" : void 0);
36914
+ const commit = readInjected(true ? "f6e2e8552cb27f341450b69d2f6c5c0bdc511003" : void 0) ?? "unknown";
36915
+ const commitShort = readInjected(true ? "f6e2e855" : void 0) ?? (commit !== "unknown" ? commit.slice(0, 7) : "unknown");
36916
+ const version2 = readInjected(true ? "1.0.58-rc.55" : void 0) ?? readInjected(typeof process !== "undefined" ? process.env?.ADHDEV_PKG_VERSION : void 0) ?? "unknown";
36917
+ const builtAt = readInjected(true ? "2026-08-31T13:05:59.798Z" : void 0);
36918
36918
  cached2 = builtAt ? { commit, commitShort, version: version2, builtAt } : { commit, commitShort, version: version2 };
36919
36919
  return cached2;
36920
36920
  }
@@ -48823,8 +48823,26 @@ ${blocks.join("\n\n")}`;
48823
48823
  {
48824
48824
  providerType: "antigravity-cli",
48825
48825
  imports: [
48826
+ // Security.framework resolves the default keychain through HOME.
48827
+ // Keep the worker-private HOME while linking macOS's keychain
48828
+ // directory back to the real home. This stays optional and
48829
+ // platform-agnostic: hosts without this path use the generic
48830
+ // missing-import skip contract below.
48831
+ { relativePath: path222.join("Library", "Keychains"), mode: "symlink" },
48826
48832
  { relativePath: path222.join(".gemini", "antigravity-cli", "antigravity-oauth-token"), mode: "symlink", required: true, requireOwnerOnly: true },
48827
48833
  { relativePath: path222.join(".gemini", "antigravity-cli", "settings.json"), mode: "symlink", requireOwnerOnly: true },
48834
+ // First-run onboarding completion — COPIED, never symlinked. Without
48835
+ // it the CLI opens its colour-scheme picker and then the Terms of
48836
+ // Service screen inside the worker PTY, where nobody is there to
48837
+ // answer: the session sits in `starting` making zero model calls
48838
+ // until it is reaped. Private HOMEs are keyed per TASK, so every
48839
+ // task would re-onboard without this.
48840
+ // Copy rather than symlink because the worker has no reason to
48841
+ // rewrite it, and a symlink would let a worker's write land in the
48842
+ // real user config. Not `required`: a host that has never run agy
48843
+ // (or any non-mac host laid out differently) must still launch, and
48844
+ // the generic missing-import skip contract covers it.
48845
+ { relativePath: path222.join(".gemini", "antigravity-cli", "cache", "onboarding.json"), mode: "copy" },
48828
48846
  // Transcript surfaces — linked THROUGH so the daemon's
48829
48847
  // os.homedir()-rooted reader still finds what the worker writes.
48830
48848
  // Not `required`: a fresh machine may not have them yet, and the
@@ -123940,7 +123958,7 @@ ${text}` : text;
123940
123958
  LOG2.warn("SpecAdapter", `[${this.cliType}] send_keys refused (actionable_modal): keys=${encoded.keys.join(",")} \u2014 use mesh_approve`);
123941
123959
  return { ok: false, refused: "actionable_modal", keys: encoded.keys, hasDestructive: encoded.hasDestructive };
123942
123960
  }
123943
- if (this.latestState?.status === "generating") {
123961
+ if (this.latestState?.status === "generating" && !encoded.hasDestructive) {
123944
123962
  const message = "session is generating; mesh_send_keys cannot write during an active turn. Use mesh_send_task with delivery_mode: 'interrupt' to interrupt it.";
123945
123963
  LOG2.warn("SpecAdapter", `[${this.cliType}] send_keys refused (generating): keys=${encoded.keys.join(",")} \u2014 use mesh_send_task delivery_mode=interrupt`);
123946
123964
  return { ok: false, refused: "generating", keys: encoded.keys, hasDestructive: encoded.hasDestructive, message };
@@ -124036,6 +124054,10 @@ ${text}` : text;
124036
124054
  }
124037
124055
  }
124038
124056
  await this.assertFocusedClaudeTuiReview(prompt, allowsFreeform);
124057
+ if (!this.activeInteractivePrompt) return;
124058
+ if (this.activeInteractivePrompt.promptId !== prompt.promptId) {
124059
+ throw new Error("Claude TUI active interactive prompt changed before review submission");
124060
+ }
124039
124061
  this.driver.dispatch({ kind: "pty_write", data: "\r" });
124040
124062
  await new Promise((resolve32) => setTimeout(resolve32, 180));
124041
124063
  } else {
@@ -124591,27 +124613,101 @@ ${text}` : text;
124591
124613
  * When the held question text is absent for
124592
124614
  * INTERACTIVE_PROMPT_LOST_GRACE_MS the prompt is genuinely resolved.
124593
124615
  */
124594
- maybeClearResolvedClaudeTuiPrompt() {
124595
- if (this.interactivePromptScheme() !== "claude_tui" || !this.activeInteractivePrompt) return;
124596
- let screenText = "";
124597
- try {
124598
- screenText = this.driver.snapshot();
124599
- } catch {
124600
- return;
124616
+ maybeClearResolvedClaudeTuiPrompt(options = {}) {
124617
+ if (this.interactivePromptScheme() !== "claude_tui" || !this.activeInteractivePrompt) return "unavailable";
124618
+ let screenText = options.screenText;
124619
+ if (screenText === void 0) {
124620
+ try {
124621
+ screenText = this.driver.snapshot();
124622
+ } catch {
124623
+ return "unavailable";
124624
+ }
124601
124625
  }
124602
124626
  const identifiableQuestions = this.activeInteractivePrompt.questions.filter((q) => !!q.question?.trim());
124603
124627
  const stillOnScreen = identifiableQuestions.length > 0 ? identifiableQuestions.some((q) => this.claudeTuiQuestionTextAppears(q, screenText)) : screenText.includes("Enter to select");
124604
124628
  if (stillOnScreen) {
124605
124629
  this.interactivePromptLostAt = null;
124606
- return;
124630
+ return "held";
124607
124631
  }
124632
+ const resolvedByBusyAdvance = options.resolveImmediatelyWhenBusy === true && this.latestState?.status === "generating";
124633
+ const resolvedByBoundToolResult = options.resolvedByBoundToolResult === true;
124608
124634
  const lostAt = this.interactivePromptLostAt ?? Date.now();
124609
- if (this.interactivePromptLostAt === null) this.interactivePromptLostAt = lostAt;
124610
- if (Date.now() - lostAt < _SpecCliAdapter.INTERACTIVE_PROMPT_LOST_GRACE_MS) return;
124635
+ if (this.interactivePromptLostAt == null) this.interactivePromptLostAt = lostAt;
124636
+ if (!resolvedByBusyAdvance && !resolvedByBoundToolResult && Date.now() - lostAt < _SpecCliAdapter.INTERACTIVE_PROMPT_LOST_GRACE_MS) return "missing";
124611
124637
  this.activeInteractivePrompt = null;
124612
124638
  this.interactivePromptTransport = null;
124613
124639
  this.interactivePromptLostAt = null;
124614
124640
  this.statusCallback?.();
124641
+ return "cleared";
124642
+ }
124643
+ /**
124644
+ * True only when the native Claude JSONL contains a tool_result for the
124645
+ * AskUserQuestion bound to `prompt`. TUI-captured prompts use a stable
124646
+ * content-derived id rather than Claude's tool_use id, so bind the native
124647
+ * call by its exact question/header/option identity first (ignoring only
124648
+ * Claude's synthetic freeform/chat rows) and only then accept its matching
124649
+ * tool_use_id. A later identical unresolved call resets the result, keeping
124650
+ * latest-call-wins semantics.
124651
+ */
124652
+ hasBoundClaudeAskUserQuestionToolResult(prompt) {
124653
+ if (this.cliType !== "claude-cli" || this.spec.native_history?.source?.kind !== "jsonl") return false;
124654
+ try {
124655
+ const history = executeNativeHistory(this.spec.native_history, {
124656
+ agentType: this.cliType,
124657
+ providerSessionId: this.providerSessionId,
124658
+ sessionStartedAtMs: this.spawnedAtMs,
124659
+ envOverrides: this.spawnedEnv,
124660
+ workspace: this.workingDir,
124661
+ instanceId: this.owningSessionId
124662
+ });
124663
+ if (!history?.sourcePath) return false;
124664
+ let boundToolUseId = null;
124665
+ let resolved = false;
124666
+ for (const record2 of readJsonlLines(history.sourcePath)) {
124667
+ const observedPrompt = detectClaudeAskUserQuestionPromptFromJson(record2, this.cliType);
124668
+ if (observedPrompt && (observedPrompt.promptId === prompt.promptId || this.claudeAskUserQuestionPromptsMatch(prompt, observedPrompt))) {
124669
+ boundToolUseId = observedPrompt.promptId;
124670
+ resolved = false;
124671
+ }
124672
+ if (!boundToolUseId) continue;
124673
+ if (this.readClaudeToolResultIds(record2).includes(boundToolUseId)) resolved = true;
124674
+ }
124675
+ return resolved;
124676
+ } catch {
124677
+ return false;
124678
+ }
124679
+ }
124680
+ claudeAskUserQuestionPromptsMatch(expected, observed) {
124681
+ if (expected.questions.length !== observed.questions.length) return false;
124682
+ return expected.questions.every((expectedQuestion, index) => {
124683
+ const observedQuestion = observed.questions[index];
124684
+ if (!observedQuestion || this.normalizeClaudeTuiIdentity(expectedQuestion.question) !== this.normalizeClaudeTuiIdentity(observedQuestion.question)) return false;
124685
+ const observedHeader = this.normalizeClaudeTuiIdentity(observedQuestion.header || "");
124686
+ if (observedHeader && this.normalizeClaudeTuiIdentity(expectedQuestion.header || "") !== observedHeader) return false;
124687
+ const expectedLabels = expectedQuestion.options.map((option) => this.normalizeClaudeTuiIdentity(option.label)).filter((label) => !/^(?:Type something\.?|Chat about this)$/i.test(label));
124688
+ const observedLabels = observedQuestion.options.map((option) => this.normalizeClaudeTuiIdentity(option.label));
124689
+ return expectedLabels.length === observedLabels.length && expectedLabels.every((label, optionIndex) => label === observedLabels[optionIndex]);
124690
+ });
124691
+ }
124692
+ readClaudeToolResultIds(value) {
124693
+ if (!value || typeof value !== "object") return [];
124694
+ const record2 = value;
124695
+ const blocks = [];
124696
+ if (Array.isArray(record2.content)) blocks.push(...record2.content);
124697
+ const message = record2.message;
124698
+ if (message && typeof message === "object" && Array.isArray(message.content)) {
124699
+ blocks.push(...message.content);
124700
+ }
124701
+ if (record2.type === "tool_result") blocks.push(record2);
124702
+ const ids = [];
124703
+ for (const block2 of blocks) {
124704
+ if (!block2 || typeof block2 !== "object") continue;
124705
+ const candidate = block2;
124706
+ if (candidate.type !== "tool_result") continue;
124707
+ const id = typeof candidate.tool_use_id === "string" ? candidate.tool_use_id.trim() : "";
124708
+ if (id) ids.push(id);
124709
+ }
124710
+ return ids;
124615
124711
  }
124616
124712
  maybeCaptureClaudeTuiPrompt() {
124617
124713
  if (this.interactivePromptScheme() !== "claude_tui" || this.activeInteractivePrompt || this.claudeTuiPromptCaptureInFlight) return;
@@ -124747,19 +124843,51 @@ ${text}` : text;
124747
124843
  * the user selects a standard option. The wider budget accounts for this
124748
124844
  * extra layout time when validating the review echo screen.
124749
124845
  */
124750
- async snapshotSettledClaudeTuiReview(allowsFreeform) {
124846
+ async snapshotSettledClaudeTuiReview(prompt, allowsFreeform) {
124751
124847
  let screenText = this.readClaudeTuiSnapshotForAnswer();
124752
124848
  const budgetMs = allowsFreeform ? _SpecCliAdapter.CLAUDE_TUI_REVIEW_SETTLE_TIMEOUT_MS : _SpecCliAdapter.CLAUDE_TUI_PAGE_SETTLE_TIMEOUT_MS;
124753
124849
  const deadline = Date.now() + budgetMs;
124754
- while (Date.now() < deadline) {
124755
- if (!readFocusedClaudeTuiQuestion(screenText) && isClaudeTuiReviewScreen(screenText)) return screenText;
124850
+ let poll = 0;
124851
+ while (true) {
124852
+ poll += 1;
124853
+ const focused = readFocusedClaudeTuiQuestion(screenText);
124854
+ const review = !focused && isClaudeTuiReviewScreen(screenText);
124855
+ let classification;
124856
+ let directSubmitted = false;
124857
+ if (focused) {
124858
+ const boundQuestion = prompt.questions.some((question) => this.claudeTuiQuestionMatches(question, focused));
124859
+ classification = boundQuestion ? "bound_question" : "foreign_question";
124860
+ } else if (review) {
124861
+ classification = "review";
124862
+ } else if (!this.activeInteractivePrompt) {
124863
+ classification = "direct_submit_already_cleared";
124864
+ directSubmitted = true;
124865
+ } else if (this.activeInteractivePrompt.promptId !== prompt.promptId) {
124866
+ classification = "active_prompt_changed";
124867
+ } else {
124868
+ const resolvedByBoundToolResult = this.hasBoundClaudeAskUserQuestionToolResult(prompt);
124869
+ const resolution = this.maybeClearResolvedClaudeTuiPrompt({
124870
+ screenText,
124871
+ resolveImmediatelyWhenBusy: true,
124872
+ resolvedByBoundToolResult
124873
+ });
124874
+ classification = resolution === "cleared" ? resolvedByBoundToolResult ? "direct_submit_tool_result" : "direct_submit_busy" : resolution === "held" ? "bound_question_unparsed" : resolution === "missing" ? "bound_question_missing" : "snapshot_unavailable";
124875
+ directSubmitted = resolution === "cleared";
124876
+ }
124877
+ LOG2.debug(
124878
+ "SpecAdapter",
124879
+ `[${this.cliType}] Claude TUI answer poll=${poll} classification=${classification} screenBytes=${Buffer.byteLength(screenText, "utf8")} providerState=${this.latestState?.id ?? "unknown"} providerStatus=${this.latestState?.status ?? "unknown"} allowsFreeform=${allowsFreeform}`
124880
+ );
124881
+ if (review) return screenText;
124882
+ if (directSubmitted) return null;
124883
+ if (Date.now() >= deadline) return screenText;
124756
124884
  await new Promise((resolve32) => setTimeout(resolve32, _SpecCliAdapter.CLAUDE_TUI_PAGE_POLL_INTERVAL_MS));
124757
124885
  screenText = this.readClaudeTuiSnapshotForAnswer();
124758
124886
  }
124759
- return screenText;
124760
124887
  }
124761
124888
  async assertFocusedClaudeTuiReview(prompt, allowsFreeform) {
124762
- const screenText = await this.snapshotSettledClaudeTuiReview(allowsFreeform);
124889
+ const screenText = await this.snapshotSettledClaudeTuiReview(prompt, allowsFreeform);
124890
+ if (screenText === null) return;
124763
124891
  const focused = readFocusedClaudeTuiQuestion(screenText);
124764
124892
  if (focused || !isClaudeTuiReviewScreen(screenText)) {
124765
124893
  const observed = focused?.question ? `; focused question is "${focused.question}"` : "";