dsh-agy-link 0.4.33 → 0.4.34

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,5 +1,16 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.4.34 (2026-09-18)
4
+
5
+ ### English
6
+
7
+ - **UI: cleaner tool cards in Code Mode.** When DSH registers `agy_tool`, the bridge now emits native tool-call blocks instead of `run_code` wrappers. Code Mode titles use a human preview (`$ ls · run_command`) instead of `replay agy tool step N`. A `run_code` toolview renders Antigravity cards when the program is still a mirror wrapper.
8
+ - **UI: less thinking spam.** Banner-only `[agy thinking turn · N tokens]` chips (no prose) emit at most once per run; turns that extract thought prose still show full reasoning.
9
+
10
+ ### 中文 (Chinese)
11
+
12
+ - **界面:** Code Mode 下工具卡片更干净;有 prose 的思考仍完整展示,无正文的 token 横幅每轮最多一条。
13
+
3
14
  ## 0.4.33 (2026-09-18)
4
15
 
5
16
  ### English
package/dist/client.js CHANGED
@@ -664,13 +664,83 @@ window.__ModuleLoader__.load({
664
664
  inspect
665
665
  }))] : []);
666
666
  }
667
+ /** Extract the agy mirror cursor (and tool name) from a run_code program. */
668
+ function parseAgyMirrorFromCode(argsRaw) {
669
+ try {
670
+ const parsed = JSON.parse(argsRaw);
671
+ const code = typeof parsed?.code === "string" ? parsed.code : "";
672
+ const m = /tools\['agy_tool'\]\((\{.*?"step":\d+\})\)/.exec(code);
673
+ if (!m) return null;
674
+ const v = JSON.parse(m[1]);
675
+ if (typeof v.run !== "string" || typeof v.step !== "number") return null;
676
+ const tm = /replay recorded agy tool step \d+ \(([^)]+)\)/.exec(code);
677
+ return {
678
+ run: v.run,
679
+ step: v.step,
680
+ tool: tm?.[1]
681
+ };
682
+ } catch {}
683
+ return null;
684
+ }
685
+ /**
686
+ * run_code toolview: when the program is an agy mirror wrapper, render the
687
+ * native Antigravity card instead of a raw code row. Other run_code calls
688
+ * fall through to the host renderer via a minimal wrapper that still shows
689
+ * something useful.
690
+ */
691
+ function AgyRunCodeToolView(props) {
692
+ const block = props?.block;
693
+ const raw = block !== void 0 ? parsedArgsRaw(block) : "{}";
694
+ const mirror = parseAgyMirrorFromCode(raw);
695
+ if (mirror === null) {
696
+ let code = "";
697
+ try {
698
+ const parsed = JSON.parse(raw);
699
+ code = typeof parsed?.code === "string" ? parsed.code : raw;
700
+ } catch {
701
+ code = raw;
702
+ }
703
+ return hx("div", { className: cls("agy-tv-root") }, hx("div", { className: "agy-tv-header" }, hx("span", { className: "agy-tv-title" }, "run_code"), hx("span", { className: "agy-tv-badge" }, "code")), hx("pre", {
704
+ className: "agy-tv-pre",
705
+ style: {
706
+ margin: 0,
707
+ whiteSpace: "pre-wrap",
708
+ fontSize: "12px"
709
+ }
710
+ }, code.slice(0, 400)));
711
+ }
712
+ return AgyMirrorToolView({ block: {
713
+ ...block,
714
+ call: {
715
+ ...block?.call ?? {},
716
+ name: "agy_tool",
717
+ argsRaw: JSON.stringify({
718
+ run: mirror.run,
719
+ step: mirror.step,
720
+ ...mirror.tool !== void 0 ? { tool: mirror.tool } : {}
721
+ })
722
+ }
723
+ } });
724
+ }
667
725
  function installAgyToolView(ctx) {
668
- ctx.slots.inject("tool.call.toolview", () => ctx.slots.register({
669
- name: "tool.call.toolview",
670
- key: "agy_tool",
671
- id: "agy-tool-view",
672
- label: "Antigravity tool"
673
- }, AgyMirrorToolView));
726
+ ctx.slots.inject("tool.call.toolview", () => {
727
+ const d1 = ctx.slots.register({
728
+ name: "tool.call.toolview",
729
+ key: "agy_tool",
730
+ id: "agy-tool-view",
731
+ label: "Antigravity tool"
732
+ }, AgyMirrorToolView);
733
+ const d2 = ctx.slots.register({
734
+ name: "tool.call.toolview",
735
+ key: "run_code",
736
+ id: "agy-run-code-view",
737
+ label: "Antigravity (code mode)"
738
+ }, AgyRunCodeToolView);
739
+ return () => {
740
+ d2();
741
+ d1();
742
+ };
743
+ });
674
744
  }
675
745
  const ROW_CSS = `
676
746
  /* Container */
package/dist/index.js CHANGED
@@ -650,16 +650,37 @@ function getGitHeadContent(filePath, execFn = execFileSync) {
650
650
  * whose single statement calls the registered mirror tool — the inner
651
651
  * dispatch is what renders the native tool card.
652
652
  */
653
- function buildMirrorRunCode(runId, eventIndex, toolName) {
653
+ function buildMirrorRunCode(runId, eventIndex, toolName, brief) {
654
654
  const invocation = JSON.stringify({
655
655
  run: runId,
656
656
  step: eventIndex
657
657
  });
658
658
  return {
659
659
  code: "// dsh-agy-link mirror: replay recorded agy tool step " + eventIndex + " (" + toolName + ")\nreturn await tools['agy_tool'](" + invocation + ")",
660
- description: "replay agy tool step " + eventIndex + " · " + toolName
660
+ description: brief !== void 0 && brief !== "" ? brief + " · " + toolName : toolName
661
661
  };
662
662
  }
663
+ /** Short human preview for a recorded tool step (used in Code Mode titles). */
664
+ function toolStepBrief(toolName, args) {
665
+ const a = args !== null && typeof args === "object" ? args : {};
666
+ const pickStr = (...keys) => {
667
+ for (const k of keys) {
668
+ const v = a[k];
669
+ if (typeof v === "string" && v.trim() !== "") return v.trim();
670
+ }
671
+ return "";
672
+ };
673
+ if (toolName === "run_command" || toolName === "execute_command") {
674
+ const cmd = pickStr("Command", "command", "Cmd", "cmd");
675
+ return cmd !== "" ? "$ " + cmd.slice(0, 80) : "run command";
676
+ }
677
+ if (toolName === "view_file" || toolName === "read_file") return "read " + (pickStr("Path", "path", "TargetFile", "File") || "file");
678
+ if (toolName === "write_to_file" || toolName === "create_file") return "write " + (pickStr("Path", "path", "TargetFile", "File") || "file");
679
+ if (toolName === "replace_file_content" || toolName === "edit_file") return "edit " + (pickStr("Path", "path", "TargetFile", "File") || "file");
680
+ if (toolName === "grep_search" || toolName === "search") return "search " + (pickStr("Query", "query", "SearchPattern") || "");
681
+ if (toolName === "list_dir" || toolName === "list_directory") return "ls " + (pickStr("Path", "path", "DirectoryPath") || ".");
682
+ return toolName;
683
+ }
663
684
  /** agy serializes some tool args as a JSON string; presenters get an object. */
664
685
  function toolInput(args) {
665
686
  const raw = args.input;
@@ -967,6 +988,7 @@ var EventMapper = class {
967
988
  emittedByKey = /* @__PURE__ */ new Map();
968
989
  announcedTools = /* @__PURE__ */ new Set();
969
990
  thinkingAnnounced = /* @__PURE__ */ new Set();
991
+ bannerOnlyThinkingEmitted = false;
970
992
  sawTextStep;
971
993
  finished = false;
972
994
  constructor(opts) {
@@ -1031,6 +1053,7 @@ var EventMapper = class {
1031
1053
  const text = this.opts.resolvedThoughts?.get(absIndex);
1032
1054
  const hasText = text !== void 0 && text.trim() !== "";
1033
1055
  if (!hasText && thoughtTokens <= 0) return;
1056
+ if (!hasText && this.bannerOnlyThinkingEmitted) return;
1034
1057
  yield* this.ensureBlock("reasoning");
1035
1058
  const banner = thoughtTokens > 0 ? "[agy thinking turn · " + thoughtTokens + " thinking tokens]" : "[agy thinking turn]";
1036
1059
  if (hasText) {
@@ -1038,6 +1061,7 @@ var EventMapper = class {
1038
1061
  const d = this.appendDelta(combined);
1039
1062
  if (d) yield d;
1040
1063
  } else {
1064
+ this.bannerOnlyThinkingEmitted = true;
1041
1065
  const d = this.appendDelta(`${banner}\n`);
1042
1066
  if (d) yield d;
1043
1067
  }
@@ -1125,7 +1149,7 @@ var EventMapper = class {
1125
1149
  ...fullArgs,
1126
1150
  ...typeof ev.tool.args === "object" ? ev.tool.args : {}
1127
1151
  } : ev.tool.args;
1128
- const argumentsJson = useCode ? JSON.stringify(buildMirrorRunCode(this.opts.runId, absIndex, ev.tool.name)) : JSON.stringify({
1152
+ const argumentsJson = useCode ? JSON.stringify(buildMirrorRunCode(this.opts.runId, absIndex, ev.tool.name, toolStepBrief(ev.tool.name, effectiveArgs))) : JSON.stringify({
1129
1153
  run: this.opts.runId,
1130
1154
  step: absIndex,
1131
1155
  tool: ev.tool.name,
@@ -2824,7 +2848,8 @@ var AgyAdapter = class extends LlmAdapter {
2824
2848
  if (!bin) throw new LlmError("agy binary not found on PATH — install it via https://antigravity.google/docs/cli/install", Err.AGY_NOT_INSTALLED);
2825
2849
  const isAux = options.purpose === "compaction" || options.purpose === "session-title";
2826
2850
  if (isAux && !cfg.allowAuxiliary) throw new LlmError("auxiliary calls are disabled for the antigravity route (allowAuxiliary: false)", Err.AUX_DISABLED);
2827
- const isCodeMode = options.tools ? options.tools.some((t) => t.name === "run_code") : false;
2851
+ const toolNames = new Set((options.tools ?? []).map((t) => t.name));
2852
+ const isCodeMode = toolNames.has("run_code") && !toolNames.has("agy_tool");
2828
2853
  const sessionKey = options.sessionId !== void 0 ? String(options.sessionId) : "";
2829
2854
  let workspaceRoot = cfg.workspaceRoot;
2830
2855
  if (workspaceRoot === "") {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-agy-link",
3
- "version": "0.4.33",
3
+ "version": "0.4.34",
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",