dsh-agy-link 0.3.3 → 0.3.5

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/CHANGELOG.md CHANGED
@@ -1,6 +1,17 @@
1
1
  # Changelog
2
2
 
3
- ## 0.2.9 (2026-08-19)
3
+ ## 0.3.5 (2026-08-20)
4
+
5
+ - **Sliding activity watchdog for long-running tasks.** Replaced the static
6
+ wall-clock timeout with an activity-based idle watchdog: the timer rearms
7
+ on every chunk of stdout/stderr activity. Long-running tasks (e.g. multi-step
8
+ refactors, extensive test suites, deep searches) can now run indefinitely as
9
+ long as the process is actively working, while deadlocked/silent processes
10
+ are still cleanly terminated after `timeoutMs` of complete inactivity.
11
+ The agy CLI `--print-timeout` is given a generous ceiling (4h) to avoid
12
+ premature termination of active print sessions.
13
+
14
+ ## 0.3.4 (2026-08-19)
4
15
 
5
16
  - **Tool activity moved out of the thinking panel into the reply body.**
6
17
  User feedback on 0.2.8: tool annotations hidden inside the DSH thinking
package/README.md CHANGED
@@ -207,7 +207,7 @@ Config lives in the `agy-link` plugin entry (edit via `/plugin` or the profile p
207
207
  | permissionMode | `DSH_AGY_MODE` | `skip` | `skip` / `plan` / `accept-edits` (below) |
208
208
  | defaultModel | `DSH_AGY_DEFAULT_MODEL` | `(agy default)` | model slug |
209
209
  | defaultEffort | `DSH_AGY_DEFAULT_EFFORT` | `(model default)` | `low` / `medium` / `high` |
210
- | timeoutMs | `DSH_AGY_TIMEOUT_MS` | `600000` | per-turn watchdog |
210
+ | timeoutMs | `DSH_AGY_TIMEOUT_MS` | `600000` | sliding activity watchdog (inactivity timeout; active long tasks run indefinitely) |
211
211
  | extraArgs | `DSH_AGY_EXTRA_ARGS` | — | extra agy flags, space-separated |
212
212
  | workspaceRoot | `DSH_AGY_WORKSPACE_ROOT` | session cwd | agy workspace; explicit config wins, otherwise the DSH session's cwd is used |
213
213
 
package/dist/index.js CHANGED
@@ -786,6 +786,12 @@ var EventMapper = class {
786
786
  text: delta
787
787
  };
788
788
  }
789
+ /** The honest thinking signal agy exposes: a token-count line. */
790
+ *emitThinkingLine(thoughtTokens) {
791
+ yield* this.ensureBlock("reasoning");
792
+ const d = this.appendDelta("[agy thinking turn · " + thoughtTokens + " thinking tokens]\n");
793
+ if (d) yield d;
794
+ }
789
795
  /**
790
796
  * Map one event. `absIndex` is the event's position in the run recording;
791
797
  * it mints the mirror callId and is what continuation detection parses
@@ -801,11 +807,16 @@ var EventMapper = class {
801
807
  const stepTextEmitted = (this.emittedByKey.get(ev.stepKey) ?? "") !== "";
802
808
  if (thoughtTokens > 0 && !stepTextEmitted && !this.thinkingAnnounced.has(ev.stepKey)) {
803
809
  this.thinkingAnnounced.add(ev.stepKey);
804
- yield* this.ensureBlock("reasoning");
805
- const d = this.appendDelta("[agy thinking turn · " + thoughtTokens + " thinking tokens]\n");
806
- if (d) yield d;
810
+ yield* this.emitThinkingLine(thoughtTokens);
811
+ }
812
+ const deferred = thoughtTokens > 0 && stepTextEmitted && !this.thinkingAnnounced.has(ev.stepKey);
813
+ if (ev.text === "" && !ev.fragment) {
814
+ if (deferred) {
815
+ this.thinkingAnnounced.add(ev.stepKey);
816
+ yield* this.emitThinkingLine(thoughtTokens);
817
+ }
818
+ return;
807
819
  }
808
- if (ev.text === "" && !ev.fragment) return;
809
820
  this.sawTextStep = true;
810
821
  yield* this.ensureBlock("text");
811
822
  let d;
@@ -819,6 +830,10 @@ var EventMapper = class {
819
830
  d = this.appendDelta(delta);
820
831
  }
821
832
  if (d) yield d;
833
+ if (deferred) {
834
+ this.thinkingAnnounced.add(ev.stepKey);
835
+ yield* this.emitThinkingLine(thoughtTokens);
836
+ }
822
837
  return;
823
838
  }
824
839
  if (ev.stepKind === "thinking" || ev.stepKind === "subagent") {
@@ -1726,10 +1741,16 @@ function startAgyProcess(opts) {
1726
1741
  if (!opts.keepStdin) try {
1727
1742
  child.stdin?.end();
1728
1743
  } catch {}
1729
- const watchdog = opts.timeoutMs && opts.timeoutMs > 0 ? setTimeout(() => {
1730
- timedOut = true;
1731
- killTree(child);
1732
- }, opts.timeoutMs) : null;
1744
+ let watchdog = null;
1745
+ const refreshWatchdog = () => {
1746
+ if (!opts.timeoutMs || opts.timeoutMs <= 0 || settled) return;
1747
+ if (watchdog) clearTimeout(watchdog);
1748
+ watchdog = setTimeout(() => {
1749
+ timedOut = true;
1750
+ killTree(child);
1751
+ }, opts.timeoutMs);
1752
+ };
1753
+ refreshWatchdog();
1733
1754
  const onAbort = () => {
1734
1755
  aborted = true;
1735
1756
  killTree(child);
@@ -1739,6 +1760,7 @@ function startAgyProcess(opts) {
1739
1760
  if (child.stderr) child.stderr.setEncoding("utf8");
1740
1761
  let pending = "";
1741
1762
  child.stdout?.on("data", (chunk) => {
1763
+ refreshWatchdog();
1742
1764
  stdout += chunk;
1743
1765
  if (stdout.length > 4e6) stdout = stdout.slice(-2e6);
1744
1766
  pending += chunk;
@@ -1750,6 +1772,7 @@ function startAgyProcess(opts) {
1750
1772
  }
1751
1773
  });
1752
1774
  child.stderr?.on("data", (chunk) => {
1775
+ refreshWatchdog();
1753
1776
  stderr = (stderr + chunk).slice(-4096);
1754
1777
  });
1755
1778
  return {
@@ -1783,6 +1806,7 @@ function startAgyProcess(opts) {
1783
1806
  kill: (reason) => {
1784
1807
  if (reason === "timeout") timedOut = true;
1785
1808
  else aborted = true;
1809
+ if (watchdog) clearTimeout(watchdog);
1786
1810
  killTree(child);
1787
1811
  }
1788
1812
  };
@@ -1932,7 +1956,7 @@ var AgyAdapter = class extends LlmAdapter {
1932
1956
  "--output-format",
1933
1957
  "stream-json",
1934
1958
  "--print-timeout",
1935
- Math.max(1, Math.ceil(opts.timeoutMs / 6e4)) + "m"
1959
+ (opts.printTimeoutMinutes ?? Math.max(1, Math.ceil(opts.timeoutMs / 6e4))) + "m"
1936
1960
  ];
1937
1961
  if (opts.permissionMode === "skip") args.push("--dangerously-skip-permissions");
1938
1962
  else args.push("--mode", opts.permissionMode);
@@ -2058,6 +2082,7 @@ var AgyAdapter = class extends LlmAdapter {
2058
2082
  conversationId: !isAux && binding !== void 0 ? binding.conversationId : void 0,
2059
2083
  permissionMode: isAux ? "plan" : cfg.permissionMode,
2060
2084
  timeoutMs: cfg.timeoutMs,
2085
+ printTimeoutMinutes: Math.max(240, Math.ceil(cfg.timeoutMs / 6e4)),
2061
2086
  extraArgs: cfg.extraArgs,
2062
2087
  addDirs: stagedDirs
2063
2088
  });
@@ -2108,7 +2133,7 @@ var AgyAdapter = class extends LlmAdapter {
2108
2133
  else if (outcome.timedOut) failure = {
2109
2134
  kind: "error",
2110
2135
  code: Err.TIMEOUT,
2111
- message: "agy run exceeded the watchdog budget (" + cfg.timeoutMs + "ms)"
2136
+ message: "agy run was idle for " + cfg.timeoutMs + "ms without output"
2112
2137
  };
2113
2138
  else if (sawAuthFailure(parser, outcome)) failure = {
2114
2139
  kind: "error",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-agy-link",
3
- "version": "0.3.3",
3
+ "version": "0.3.5",
4
4
  "description": "Google Antigravity (agy CLI) models for DeepSeek Harness — stream Gemini/Claude/GPT-OSS subscriptions into DSH with thinking, tool activity, token usage and in-GUI Google OAuth login.",
5
5
  "type": "module",
6
6
  "license": "MIT",