dsh-agy-link 0.4.22 → 0.4.24
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 +17 -0
- package/dist/index.js +251 -76
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,22 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.4.24 (2026-08-28)
|
|
4
|
+
|
|
5
|
+
- **Fixed: Antigravity Models Missing From Picker When Logged In (已登录/显示余量但模型列表不显示 — issue #1).**
|
|
6
|
+
- **Decoupled Adapter Registration from Synchronous Binary Discovery**: `registerAdapter` now executes regardless of initial `bin()` probe results (using resilient fallback model catalog), ensuring the Antigravity provider is never dropped during startup even if CLI path resolution is deferred.
|
|
7
|
+
- **Expanded macOS / Linux GUI App Path Discovery**: extended `resolveAgyBin` search candidates to include `~/.bun/bin`, `~/.cargo/bin`, `~/.local/share/pnpm`, `~/Library/pnpm`, `~/.yarn/bin`, `~/.npm-global/bin`, NVM (`~/.nvm/versions/node/*/bin`), FNM, Volta, ASDF shims, Linuxbrew, etc., fixing GUI desktop apps starting with minimal default system PATH.
|
|
8
|
+
- **Account-Aware Model Discovery & Environment Isolation**: model discovery now inherits current active/primary account isolated environment and proxy settings, falling back across ready pool accounts if default system HOME is unauthenticated.
|
|
9
|
+
- **Defensive Model & Effort Sanitization**: defensive catalog cleaning against empty IDs, blank names, empty reasoning effort arrays, and out-of-bounds `defaultEffort` to strictly satisfy DSH host validation and prevent fail-all provider group drops (`INVALID_CATALOG` / `INVALID_MODEL_*`).
|
|
10
|
+
- **Cross-Platform & Unit Tests**: added defensive catalog normalization and explicit binary path resolution tests across test suites.
|
|
11
|
+
|
|
12
|
+
## 0.4.23 (2026-08-27)
|
|
13
|
+
|
|
14
|
+
- **Enhanced: Antigravity Tool Mirroring with Native Git +/- Diff Cards & Full Tool Vocabulary.**
|
|
15
|
+
- **Tool Vocabulary & Parameter Mapping**: mapped agy's official editing tool `replace_file_content` (`TargetFile`, `TargetContent`, `ReplacementContent`, `Description`, `Instruction`) and write tool `write_to_file` (`TargetFile`, `CodeContent`, `Overwrite`, `Description`) to DSH native `DiffCallView` / `DiffResultView` cards.
|
|
16
|
+
- **Git Head Base Line Diffing**: added cross-platform `getGitHeadContent` to retrieve committed file content for full-file writes (`write_to_file`), allowing DSH to render line-by-line git `+`/`-` additions and deletions rather than treating existing modified files as blank new files.
|
|
17
|
+
- **Expanded Tool Support**: mapped `view_file` (with `AbsolutePath`/`StartLine` line location navigation), `grep_search`, `find_by_name`, `ask_question`, `read_url_content`, and `generate_image` onto their respective native/generic tool cards with descriptive titles.
|
|
18
|
+
- **Cross-Platform Hardened**: path normalization with forward-slash compatibility across Windows/macOS/Linux, `windowsHide: true`, strict subprocess timeout, and safe error fallback.
|
|
19
|
+
|
|
3
20
|
## 0.4.22 (2026-08-27)
|
|
4
21
|
|
|
5
22
|
- **Fixed: `registration.adapter.prepareCall is not a function` on new DSH hosts (本轮运行失败 UNKNOWN).**
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { createRequire } from "node:module";
|
|
2
2
|
import { execFile, execFileSync, spawn } from "node:child_process";
|
|
3
|
-
import { delimiter, dirname, isAbsolute, join, resolve } from "node:path";
|
|
3
|
+
import path, { delimiter, dirname, isAbsolute, join, resolve } from "node:path";
|
|
4
4
|
import { accessSync, chmodSync, constants, existsSync, mkdirSync, readFileSync, readdirSync, renameSync, rmSync, statSync, unlinkSync, writeFileSync } from "node:fs";
|
|
5
5
|
import { homedir, tmpdir } from "node:os";
|
|
6
6
|
import { CallId, LlmAdapter, LlmError } from "@deepseek-ai/dsh-llm";
|
|
@@ -549,6 +549,48 @@ const MIRROR_TOOL_NAME = "agy_tool";
|
|
|
549
549
|
/** The only tool this DSH deployment lets a model call directly. */
|
|
550
550
|
const WRAPPER_TOOL_NAME = "run_code";
|
|
551
551
|
/**
|
|
552
|
+
* Retrieve the committed HEAD content of a file via git, for computing
|
|
553
|
+
* line diffs on full-file writes. Pure & safe: catches all failures (not in git,
|
|
554
|
+
* untracked, git missing, binary) and returns null in <=500ms.
|
|
555
|
+
*/
|
|
556
|
+
function getGitHeadContent(filePath, execFn = execFileSync) {
|
|
557
|
+
if (!filePath || typeof filePath !== "string" || filePath === "file") return null;
|
|
558
|
+
try {
|
|
559
|
+
const resolved = path.resolve(filePath);
|
|
560
|
+
const toplevel = execFn("git", ["rev-parse", "--show-toplevel"], {
|
|
561
|
+
cwd: path.dirname(resolved),
|
|
562
|
+
encoding: "utf-8",
|
|
563
|
+
stdio: [
|
|
564
|
+
"ignore",
|
|
565
|
+
"pipe",
|
|
566
|
+
"ignore"
|
|
567
|
+
],
|
|
568
|
+
timeout: 500,
|
|
569
|
+
windowsHide: true
|
|
570
|
+
});
|
|
571
|
+
const root = typeof toplevel === "string" ? toplevel.trim() : "";
|
|
572
|
+
if (!root) return null;
|
|
573
|
+
const relPath = path.relative(root, resolved).replace(/\\/g, "/");
|
|
574
|
+
if (relPath.startsWith("..")) return null;
|
|
575
|
+
const content = execFn("git", ["show", `HEAD:${relPath}`], {
|
|
576
|
+
cwd: root,
|
|
577
|
+
encoding: "utf-8",
|
|
578
|
+
stdio: [
|
|
579
|
+
"ignore",
|
|
580
|
+
"pipe",
|
|
581
|
+
"ignore"
|
|
582
|
+
],
|
|
583
|
+
timeout: 500,
|
|
584
|
+
windowsHide: true
|
|
585
|
+
});
|
|
586
|
+
const str = typeof content === "string" ? content : "";
|
|
587
|
+
if (str.includes("\0")) return null;
|
|
588
|
+
return str;
|
|
589
|
+
} catch {
|
|
590
|
+
return null;
|
|
591
|
+
}
|
|
592
|
+
}
|
|
593
|
+
/**
|
|
552
594
|
* Build the run_code tool-call arguments that replay one recorded agy tool
|
|
553
595
|
* step. The deployment's tool-dispatch policy only allows `run_code` as a
|
|
554
596
|
* direct model call (everything else must be invoked from inside a
|
|
@@ -581,8 +623,9 @@ function toolInput(args) {
|
|
|
581
623
|
}
|
|
582
624
|
/**
|
|
583
625
|
* agy serializes tool args with PascalCase keys (CommandLine, AbsolutePath,
|
|
584
|
-
* SearchDirectory, …);
|
|
585
|
-
*
|
|
626
|
+
* SearchDirectory, TargetFile, TargetContent, ReplacementContent, CodeContent…);
|
|
627
|
+
* pick() accepts all casing spellings so cards always read the real field
|
|
628
|
+
* instead of falling back to raw JSON.
|
|
586
629
|
*/
|
|
587
630
|
function pick$1(input, ...keys) {
|
|
588
631
|
for (const k of keys) {
|
|
@@ -598,41 +641,50 @@ function presentMirrorCall(args) {
|
|
|
598
641
|
switch (name) {
|
|
599
642
|
case "run_command":
|
|
600
643
|
case "bash":
|
|
601
|
-
case "execute_command":
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
644
|
+
case "execute_command": {
|
|
645
|
+
const command = pick$1(input, "CommandLine", "command_line", "command", "cmd", "Cmd") ?? JSON.stringify(input);
|
|
646
|
+
const desc = pick$1(input, "Description", "description", "toolAction", "toolSummary");
|
|
647
|
+
const cwd = pick$1(input, "Cwd", "cwd", "WorkingDirectory", "working_directory");
|
|
648
|
+
return {
|
|
649
|
+
card: "terminal",
|
|
650
|
+
title: command,
|
|
651
|
+
...desc !== void 0 ? { description: desc } : {},
|
|
652
|
+
...cwd !== void 0 ? { cwd } : {}
|
|
653
|
+
};
|
|
654
|
+
}
|
|
655
|
+
case "replace_file_content":
|
|
656
|
+
case "edit_file":
|
|
657
|
+
case "replace_in_file":
|
|
658
|
+
case "edit": {
|
|
659
|
+
const path = pick$1(input, "TargetFile", "target_file", "path", "file_path", "Path", "FilePath", "AbsolutePath", "targetFile") ?? "file";
|
|
660
|
+
const oldText = pick$1(input, "TargetContent", "target_content", "old_string", "oldText", "OldString", "OldText", "targetContent") ?? null;
|
|
661
|
+
const newText = pick$1(input, "ReplacementContent", "replacement_content", "new_string", "newText", "content", "NewString", "NewText", "Content", "replacementContent") ?? "";
|
|
662
|
+
const desc = pick$1(input, "Description", "description", "Instruction", "instruction", "toolAction", "toolSummary");
|
|
612
663
|
return {
|
|
613
664
|
card: "diff",
|
|
614
|
-
title: "
|
|
665
|
+
title: desc ? `${desc} · ${path}` : "Edit " + path,
|
|
615
666
|
diffs: [{
|
|
616
667
|
path,
|
|
617
|
-
oldText
|
|
618
|
-
newText
|
|
668
|
+
oldText,
|
|
669
|
+
newText
|
|
619
670
|
}],
|
|
620
671
|
locations: [{ path }]
|
|
621
672
|
};
|
|
622
673
|
}
|
|
623
|
-
case "
|
|
624
|
-
case "
|
|
625
|
-
case "
|
|
626
|
-
const path = pick$1(input, "path", "file_path", "Path", "FilePath", "AbsolutePath") ?? "file";
|
|
627
|
-
const
|
|
628
|
-
const
|
|
674
|
+
case "write_to_file":
|
|
675
|
+
case "write_file":
|
|
676
|
+
case "create_file": {
|
|
677
|
+
const path = pick$1(input, "TargetFile", "target_file", "path", "file_path", "filename", "Path", "FilePath", "FileName", "AbsolutePath", "targetFile") ?? "file";
|
|
678
|
+
const content = pick$1(input, "CodeContent", "code_content", "content", "Content", "FileContents", "contents", "codeContent") ?? "";
|
|
679
|
+
const desc = pick$1(input, "Description", "description", "toolAction", "toolSummary");
|
|
680
|
+
const oldText = pick$1(input, "old_string", "oldText", "OldString", "OldText") ?? getGitHeadContent(path);
|
|
629
681
|
return {
|
|
630
682
|
card: "diff",
|
|
631
|
-
title: "
|
|
683
|
+
title: desc ? `${desc} · ${path}` : "Write " + path,
|
|
632
684
|
diffs: [{
|
|
633
685
|
path,
|
|
634
686
|
oldText,
|
|
635
|
-
newText
|
|
687
|
+
newText: content
|
|
636
688
|
}],
|
|
637
689
|
locations: [{ path }]
|
|
638
690
|
};
|
|
@@ -641,11 +693,12 @@ function presentMirrorCall(args) {
|
|
|
641
693
|
case "view_file":
|
|
642
694
|
case "read":
|
|
643
695
|
case "open_file": {
|
|
644
|
-
const path = pick$1(input, "path", "file_path", "filename", "Path", "FilePath", "FileName", "
|
|
645
|
-
const offset = typeof input.offset === "number" ? input.offset : typeof input.Offset === "number" ? input.Offset : void 0;
|
|
696
|
+
const path = pick$1(input, "AbsolutePath", "absolute_path", "TargetFile", "target_file", "path", "file_path", "filename", "Path", "FilePath", "FileName", "targetFile") ?? "";
|
|
697
|
+
const offset = typeof input.offset === "number" ? input.offset : typeof input.Offset === "number" ? input.Offset : typeof input.StartLine === "number" ? input.StartLine - 1 : typeof input.start_line === "number" ? input.start_line - 1 : void 0;
|
|
698
|
+
const desc = pick$1(input, "Description", "description", "toolAction", "toolSummary");
|
|
646
699
|
return {
|
|
647
700
|
card: "generic",
|
|
648
|
-
title: "Read " + path,
|
|
701
|
+
title: desc ? `${desc} · ${path}` : "Read " + path,
|
|
649
702
|
kind: "read",
|
|
650
703
|
...path !== "" ? { locations: [{
|
|
651
704
|
path,
|
|
@@ -655,35 +708,70 @@ function presentMirrorCall(args) {
|
|
|
655
708
|
}
|
|
656
709
|
case "find_by_name":
|
|
657
710
|
case "glob":
|
|
658
|
-
case "search_files":
|
|
711
|
+
case "search_files": {
|
|
712
|
+
const q = pick$1(input, "pattern", "Pattern", "query", "Query", "regex", "Regex", "QueryString") ?? "";
|
|
713
|
+
return {
|
|
714
|
+
card: "generic",
|
|
715
|
+
title: pick$1(input, "Description", "description", "toolAction", "toolSummary") ?? (q !== "" ? "Search " + q : "Search"),
|
|
716
|
+
kind: "search"
|
|
717
|
+
};
|
|
718
|
+
}
|
|
719
|
+
case "grep_search":
|
|
659
720
|
case "search":
|
|
660
721
|
case "search_file_content":
|
|
661
722
|
case "grep": {
|
|
662
|
-
const q = pick$1(input, "
|
|
723
|
+
const q = pick$1(input, "query", "Query", "pattern", "Pattern", "regex", "Regex", "QueryString") ?? "";
|
|
663
724
|
return {
|
|
664
725
|
card: "generic",
|
|
665
|
-
title: q !== "" ? "Search " + q : "Search",
|
|
726
|
+
title: pick$1(input, "Description", "description", "toolAction", "toolSummary") ?? (q !== "" ? "Search " + q : "Search"),
|
|
666
727
|
kind: "search"
|
|
667
728
|
};
|
|
668
729
|
}
|
|
669
730
|
case "list_dir":
|
|
670
731
|
case "ls": {
|
|
671
|
-
const path = pick$1(input, "path", "directory", "Path", "Directory", "SearchDirectory", "AbsolutePath") ?? "";
|
|
732
|
+
const path = pick$1(input, "DirectoryPath", "directory_path", "path", "directory", "Path", "Directory", "SearchDirectory", "search_directory", "AbsolutePath") ?? "";
|
|
672
733
|
return {
|
|
673
734
|
card: "generic",
|
|
674
|
-
title: path !== "" ? "List " + path : "List directory"
|
|
735
|
+
title: pick$1(input, "Description", "description", "toolAction", "toolSummary") ?? (path !== "" ? "List " + path : "List directory")
|
|
675
736
|
};
|
|
676
737
|
}
|
|
677
738
|
case "delete_file":
|
|
678
739
|
case "remove_file":
|
|
679
|
-
case "rm":
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
740
|
+
case "rm": {
|
|
741
|
+
const path = pick$1(input, "TargetFile", "target_file", "path", "file_path", "Path", "FilePath", "AbsolutePath") ?? "";
|
|
742
|
+
return {
|
|
743
|
+
card: "generic",
|
|
744
|
+
title: pick$1(input, "Description", "description", "toolAction", "toolSummary") ?? "Delete " + path,
|
|
745
|
+
kind: "delete"
|
|
746
|
+
};
|
|
747
|
+
}
|
|
748
|
+
case "ask_question": {
|
|
749
|
+
const questions = input.questions;
|
|
750
|
+
const firstQ = Array.isArray(questions) && questions.length > 0 && typeof questions[0].question === "string" ? questions[0].question : void 0;
|
|
751
|
+
return {
|
|
752
|
+
card: "generic",
|
|
753
|
+
title: firstQ ? `Ask Question: ${firstQ}` : "Ask Question",
|
|
754
|
+
rawInput: input
|
|
755
|
+
};
|
|
756
|
+
}
|
|
757
|
+
case "read_url_content": {
|
|
758
|
+
const url = pick$1(input, "Url", "url") ?? "";
|
|
759
|
+
return {
|
|
760
|
+
card: "generic",
|
|
761
|
+
title: pick$1(input, "Description", "description", "toolAction", "toolSummary") ?? (url ? `Fetch ${url}` : "Fetch URL"),
|
|
762
|
+
kind: "fetch"
|
|
763
|
+
};
|
|
764
|
+
}
|
|
765
|
+
case "generate_image": {
|
|
766
|
+
const prompt = pick$1(input, "Prompt", "prompt", "ImageName", "image_name") ?? "";
|
|
767
|
+
return {
|
|
768
|
+
card: "generic",
|
|
769
|
+
title: prompt ? `Generate Image: ${prompt}` : "Generate Image"
|
|
770
|
+
};
|
|
771
|
+
}
|
|
684
772
|
default: return {
|
|
685
773
|
card: "generic",
|
|
686
|
-
title: name !== "" ? name : "agy tool",
|
|
774
|
+
title: pick$1(input, "Description", "description", "toolAction", "toolSummary") ?? (name !== "" ? name : "agy tool"),
|
|
687
775
|
rawInput: input
|
|
688
776
|
};
|
|
689
777
|
}
|
|
@@ -700,6 +788,7 @@ function presentMirrorResult(args, result) {
|
|
|
700
788
|
card: "terminal",
|
|
701
789
|
output: text
|
|
702
790
|
};
|
|
791
|
+
case "replace_file_content":
|
|
703
792
|
case "write_to_file":
|
|
704
793
|
case "write_file":
|
|
705
794
|
case "create_file":
|
|
@@ -1079,7 +1168,7 @@ function parseModelsOutput(stdout) {
|
|
|
1079
1168
|
const out = [];
|
|
1080
1169
|
for (const line of text.split(/\n/)) {
|
|
1081
1170
|
const t = line.trim();
|
|
1082
|
-
if (t === "" || t.startsWith("Fetching") || t.startsWith("Error")) continue;
|
|
1171
|
+
if (t === "" || t.startsWith("Fetching") || t.startsWith("Error") || /^(please sign in|warning|tip:)/i.test(t)) continue;
|
|
1083
1172
|
const m = t.match(/^(\S+)(?:\t+|\s{2,})(.+)$/);
|
|
1084
1173
|
if (m && m[1] !== void 0 && m[2] !== void 0) out.push({
|
|
1085
1174
|
slug: m[1],
|
|
@@ -1097,9 +1186,14 @@ function dedupeBySlug(raw) {
|
|
|
1097
1186
|
const seen = /* @__PURE__ */ new Set();
|
|
1098
1187
|
const out = [];
|
|
1099
1188
|
for (const r of raw) {
|
|
1100
|
-
if (
|
|
1101
|
-
|
|
1102
|
-
|
|
1189
|
+
if (!r.slug || typeof r.slug !== "string") continue;
|
|
1190
|
+
const slug = r.slug.trim();
|
|
1191
|
+
if (slug === "" || seen.has(slug)) continue;
|
|
1192
|
+
seen.add(slug);
|
|
1193
|
+
out.push({
|
|
1194
|
+
slug,
|
|
1195
|
+
label: typeof r.label === "string" && r.label.trim() !== "" ? r.label.trim() : slug
|
|
1196
|
+
});
|
|
1103
1197
|
}
|
|
1104
1198
|
return out;
|
|
1105
1199
|
}
|
|
@@ -1207,10 +1301,10 @@ function stripEffortLabel(label, eff) {
|
|
|
1207
1301
|
return label.replace(re, "").trim();
|
|
1208
1302
|
}
|
|
1209
1303
|
function buildFallbackCatalog(defs) {
|
|
1210
|
-
return defs.map((d) => ({
|
|
1211
|
-
id: d.id,
|
|
1212
|
-
name: d.name,
|
|
1213
|
-
efforts: d.efforts
|
|
1304
|
+
return defs.filter((d) => Boolean(d && typeof d.id === "string" && d.id.trim() !== "")).map((d) => ({
|
|
1305
|
+
id: d.id.trim(),
|
|
1306
|
+
name: typeof d.name === "string" && d.name.trim() !== "" ? d.name.trim() : d.id.trim(),
|
|
1307
|
+
efforts: Array.isArray(d.efforts) && d.efforts.length > 0 ? d.efforts.filter((e) => typeof e === "string" && e.trim() !== "") : null
|
|
1214
1308
|
}));
|
|
1215
1309
|
}
|
|
1216
1310
|
var ModelCatalog = class {
|
|
@@ -1288,7 +1382,7 @@ function findEntry(catalog, id) {
|
|
|
1288
1382
|
if (resolved !== id) return catalog.models.find((m) => m.id === resolved);
|
|
1289
1383
|
}
|
|
1290
1384
|
function defaultEffortFor(entry, cfg) {
|
|
1291
|
-
if (!entry.efforts) return void 0;
|
|
1385
|
+
if (!entry.efforts || entry.efforts.length === 0) return void 0;
|
|
1292
1386
|
if (cfg.defaultEffort !== "" && entry.efforts.includes(cfg.defaultEffort)) return cfg.defaultEffort;
|
|
1293
1387
|
for (const pref of [
|
|
1294
1388
|
"high",
|
|
@@ -1790,15 +1884,47 @@ function resolveAgyBin(cfg) {
|
|
|
1790
1884
|
if (cfg.agyBin !== "") candidates.push(cfg.agyBin);
|
|
1791
1885
|
const pathEnv = process.env.PATH ?? "";
|
|
1792
1886
|
for (const dir of pathEnv.split(delimiter)) if (dir !== "") candidates.push(...binCandidates(dir));
|
|
1887
|
+
const home = homedir();
|
|
1793
1888
|
if (IS_WIN) {
|
|
1794
1889
|
const local = process.env.LOCALAPPDATA ?? "";
|
|
1795
|
-
|
|
1796
|
-
|
|
1797
|
-
|
|
1890
|
+
const appData = process.env.APPDATA ?? "";
|
|
1891
|
+
if (local !== "") {
|
|
1892
|
+
candidates.push(join(local, "Programs", "agy", "agy.exe"));
|
|
1893
|
+
candidates.push(join(local, "pnpm", "agy.cmd"));
|
|
1894
|
+
candidates.push(join(local, "pnpm", "agy.exe"));
|
|
1895
|
+
}
|
|
1896
|
+
if (appData !== "") {
|
|
1897
|
+
candidates.push(join(appData, "npm", "agy.cmd"));
|
|
1898
|
+
candidates.push(join(appData, "Roaming", "npm", "agy.cmd"));
|
|
1899
|
+
}
|
|
1900
|
+
candidates.push(join(home, ".local", "bin", "agy.exe"));
|
|
1901
|
+
candidates.push(join(home, ".local", "bin", "agy.cmd"));
|
|
1902
|
+
candidates.push(join(home, ".bun", "bin", "agy.exe"));
|
|
1903
|
+
candidates.push(join(home, ".cargo", "bin", "agy.exe"));
|
|
1904
|
+
candidates.push(join(home, "scoop", "shims", "agy.exe"));
|
|
1798
1905
|
} else {
|
|
1799
|
-
candidates.push(join(
|
|
1906
|
+
candidates.push(join(home, ".local", "bin", "agy"));
|
|
1800
1907
|
candidates.push("/usr/local/bin/agy");
|
|
1801
1908
|
candidates.push("/opt/homebrew/bin/agy");
|
|
1909
|
+
candidates.push("/opt/homebrew/sbin/agy");
|
|
1910
|
+
candidates.push("/home/linuxbrew/.linuxbrew/bin/agy");
|
|
1911
|
+
candidates.push(join(home, ".bun", "bin", "agy"));
|
|
1912
|
+
candidates.push(join(home, ".cargo", "bin", "agy"));
|
|
1913
|
+
candidates.push(join(home, ".local", "share", "pnpm", "agy"));
|
|
1914
|
+
candidates.push(join(home, "Library", "pnpm", "agy"));
|
|
1915
|
+
candidates.push(join(home, ".yarn", "bin", "agy"));
|
|
1916
|
+
candidates.push(join(home, ".npm-global", "bin", "agy"));
|
|
1917
|
+
candidates.push(join(home, ".volta", "bin", "agy"));
|
|
1918
|
+
candidates.push(join(home, ".asdf", "shims", "agy"));
|
|
1919
|
+
candidates.push(join(home, ".nix-profile", "bin", "agy"));
|
|
1920
|
+
candidates.push("/run/current-system/sw/bin/agy");
|
|
1921
|
+
try {
|
|
1922
|
+
const nvmNodeDir = join(home, ".nvm", "versions", "node");
|
|
1923
|
+
if (existsSync(nvmNodeDir)) for (const v of readdirSync(nvmNodeDir)) candidates.push(join(nvmNodeDir, v, "bin", "agy"));
|
|
1924
|
+
} catch {}
|
|
1925
|
+
candidates.push(join(home, ".local", "share", "fnm", "current", "bin", "agy"));
|
|
1926
|
+
candidates.push(join(home, ".fnm", "current", "bin", "agy"));
|
|
1927
|
+
candidates.push(join(home, "Library", "Application Support", "fnm", "current", "bin", "agy"));
|
|
1802
1928
|
}
|
|
1803
1929
|
const hits = [];
|
|
1804
1930
|
for (const c of candidates) try {
|
|
@@ -2087,15 +2213,19 @@ var AgyAdapter = class extends LlmAdapter {
|
|
|
2087
2213
|
const models = [];
|
|
2088
2214
|
const dropped = [];
|
|
2089
2215
|
for (const m of cat.models) {
|
|
2090
|
-
if (
|
|
2091
|
-
|
|
2216
|
+
if (!m || typeof m.id !== "string") continue;
|
|
2217
|
+
const id = m.id.trim();
|
|
2218
|
+
if (id === "") continue;
|
|
2219
|
+
if (seen.has(id)) {
|
|
2220
|
+
dropped.push(id);
|
|
2092
2221
|
continue;
|
|
2093
2222
|
}
|
|
2094
|
-
seen.add(
|
|
2223
|
+
seen.add(id);
|
|
2224
|
+
const name = typeof m.name === "string" && m.name.trim() !== "" ? m.name.trim() : id;
|
|
2095
2225
|
models.push({
|
|
2096
2226
|
provider: PROVIDER_ID,
|
|
2097
|
-
id
|
|
2098
|
-
name
|
|
2227
|
+
id,
|
|
2228
|
+
name,
|
|
2099
2229
|
inputModalities: ["text", "image"]
|
|
2100
2230
|
});
|
|
2101
2231
|
}
|
|
@@ -2104,26 +2234,37 @@ var AgyAdapter = class extends LlmAdapter {
|
|
|
2104
2234
|
}
|
|
2105
2235
|
async resolveModel(_provider, model, _signal) {
|
|
2106
2236
|
const cfg = this.deps.getConfig();
|
|
2107
|
-
const
|
|
2108
|
-
const
|
|
2109
|
-
const
|
|
2237
|
+
const cat = this.deps.catalog.get();
|
|
2238
|
+
const rawModel = typeof model === "string" ? model.trim() : "";
|
|
2239
|
+
const cleanId = rawModel !== "" ? rawModel : cfg.defaultModel;
|
|
2240
|
+
const entry = findEntry(cat, cleanId);
|
|
2241
|
+
const rawName = entry ? entry.name : cleanId;
|
|
2242
|
+
const name = typeof rawName === "string" && rawName.trim() !== "" ? rawName.trim() : cleanId;
|
|
2243
|
+
const contextWindow = typeof cfg.contextWindowDefault === "number" && cfg.contextWindowDefault > 0 ? cfg.contextWindowDefault : 2e5;
|
|
2110
2244
|
const resolved = {
|
|
2111
2245
|
provider: PROVIDER_ID,
|
|
2112
|
-
id:
|
|
2246
|
+
id: cleanId,
|
|
2113
2247
|
name,
|
|
2114
2248
|
inputModalities: ["text", "image"],
|
|
2115
2249
|
context: { contextWindow },
|
|
2116
|
-
defaultMaxTokens: cfg.maxTokensDefault
|
|
2250
|
+
defaultMaxTokens: typeof cfg.maxTokensDefault === "number" && cfg.maxTokensDefault > 0 ? cfg.maxTokensDefault : 8192
|
|
2117
2251
|
};
|
|
2118
|
-
if (entry && entry.efforts) {
|
|
2119
|
-
const
|
|
2120
|
-
|
|
2121
|
-
|
|
2122
|
-
|
|
2123
|
-
|
|
2124
|
-
})
|
|
2125
|
-
|
|
2126
|
-
|
|
2252
|
+
if (entry && Array.isArray(entry.efforts) && entry.efforts.length > 0) {
|
|
2253
|
+
const cleanEfforts = Array.from(new Set(entry.efforts.filter((e) => typeof e === "string" && e.trim() !== "")));
|
|
2254
|
+
if (cleanEfforts.length > 0) {
|
|
2255
|
+
const def = defaultEffortFor({
|
|
2256
|
+
...entry,
|
|
2257
|
+
efforts: cleanEfforts
|
|
2258
|
+
}, cfg);
|
|
2259
|
+
const validDef = def && cleanEfforts.includes(def) ? def : cleanEfforts[0];
|
|
2260
|
+
resolved.reasoning = {
|
|
2261
|
+
efforts: cleanEfforts.map((e) => ({
|
|
2262
|
+
id: e,
|
|
2263
|
+
name: e
|
|
2264
|
+
})),
|
|
2265
|
+
...validDef ? { defaultEffort: validDef } : {}
|
|
2266
|
+
};
|
|
2267
|
+
}
|
|
2127
2268
|
}
|
|
2128
2269
|
return resolved;
|
|
2129
2270
|
}
|
|
@@ -28346,7 +28487,7 @@ function apply(ctx, entryConfig = {}) {
|
|
|
28346
28487
|
let lastParser = new StreamJsonParser();
|
|
28347
28488
|
const getConfig = () => resolveConfig(entryConfig);
|
|
28348
28489
|
const bin = () => {
|
|
28349
|
-
if (binCache === void 0) binCache = resolveAgyBin(getConfig());
|
|
28490
|
+
if (binCache === void 0 || binCache === null) binCache = resolveAgyBin(getConfig());
|
|
28350
28491
|
return binCache;
|
|
28351
28492
|
};
|
|
28352
28493
|
const version = () => versionCache;
|
|
@@ -28354,10 +28495,41 @@ function apply(ctx, entryConfig = {}) {
|
|
|
28354
28495
|
const pool = new AccountPoolManager();
|
|
28355
28496
|
const quota = new QuotaService(pool);
|
|
28356
28497
|
const semaphore = new Semaphore(() => getConfig().maxConcurrent);
|
|
28498
|
+
const getDiscoveryEnv = (account) => {
|
|
28499
|
+
const cfg = getConfig();
|
|
28500
|
+
return {
|
|
28501
|
+
...process.env,
|
|
28502
|
+
...cfg.disableTelemetry ? {
|
|
28503
|
+
DO_NOT_TRACK: "1",
|
|
28504
|
+
DISABLE_TELEMETRY: "1",
|
|
28505
|
+
GOOGLE_CLOUD_DISABLE_TELEMETRY: "1",
|
|
28506
|
+
ANTIGRAVITY_DISABLE_TELEMETRY: "1"
|
|
28507
|
+
} : {},
|
|
28508
|
+
...account && account.dir ? isolatedHomeEnv(account.dir) : {},
|
|
28509
|
+
...account?.proxyUrl ? {
|
|
28510
|
+
ALL_PROXY: account.proxyUrl,
|
|
28511
|
+
HTTPS_PROXY: account.proxyUrl,
|
|
28512
|
+
HTTP_PROXY: account.proxyUrl,
|
|
28513
|
+
all_proxy: account.proxyUrl,
|
|
28514
|
+
https_proxy: account.proxyUrl,
|
|
28515
|
+
http_proxy: account.proxyUrl
|
|
28516
|
+
} : {}
|
|
28517
|
+
};
|
|
28518
|
+
};
|
|
28357
28519
|
const catalog = new ModelCatalog(async (signal) => {
|
|
28358
28520
|
const b = bin();
|
|
28359
28521
|
if (!b) throw new Error("agy binary not found");
|
|
28360
|
-
const
|
|
28522
|
+
const poolData = pool.getPoolData();
|
|
28523
|
+
const primaryAcc = poolData.primaryAccountId ? pool.getAccount(poolData.primaryAccountId) : void 0;
|
|
28524
|
+
const candidateAccount = primaryAcc && primaryAcc.enabled && !primaryAcc.authRequired ? primaryAcc : pool.getAccounts().find((a) => a.enabled && !a.authRequired);
|
|
28525
|
+
let out = await probeProcess(b, ["models"], 3e4, signal, getDiscoveryEnv(candidateAccount));
|
|
28526
|
+
if ((out.code !== 0 || out.stdout.includes("Please sign in") || /sign in|auth|not logged in/i.test(out.stderrTail)) && (!candidateAccount || !candidateAccount.dir)) {
|
|
28527
|
+
const secondary = pool.getAccounts().find((a) => a.enabled && !a.authRequired && a.dir);
|
|
28528
|
+
if (secondary) {
|
|
28529
|
+
const secondaryOut = await probeProcess(b, ["models"], 3e4, signal, getDiscoveryEnv(secondary));
|
|
28530
|
+
if (secondaryOut.code === 0 && secondaryOut.stdout.trim() !== "") out = secondaryOut;
|
|
28531
|
+
}
|
|
28532
|
+
}
|
|
28361
28533
|
if (out.code !== 0 && out.stdout.trim() === "") throw new Error("agy models failed: " + (out.stderrTail.trim() !== "" ? out.stderrTail.trim().slice(-200) : "exit " + String(out.code)));
|
|
28362
28534
|
return {
|
|
28363
28535
|
stdout: out.stdout,
|
|
@@ -28411,6 +28583,7 @@ function apply(ctx, entryConfig = {}) {
|
|
|
28411
28583
|
const file = overridesPath();
|
|
28412
28584
|
const current = readOverrides(file);
|
|
28413
28585
|
current[key] = value;
|
|
28586
|
+
binCache = void 0;
|
|
28414
28587
|
try {
|
|
28415
28588
|
mkdirSync(stateDir(), { recursive: true });
|
|
28416
28589
|
writeFileSync(file, JSON.stringify(current, null, 2), "utf8");
|
|
@@ -28424,25 +28597,27 @@ function apply(ctx, entryConfig = {}) {
|
|
|
28424
28597
|
log("dormant: disabled by config");
|
|
28425
28598
|
return;
|
|
28426
28599
|
}
|
|
28427
|
-
|
|
28600
|
+
const currentBin = bin();
|
|
28601
|
+
if (!currentBin) {
|
|
28428
28602
|
dormantReason = "agy binary not found — install via https://antigravity.google/docs/cli/install";
|
|
28429
28603
|
log("dormant: agy binary not found");
|
|
28430
28604
|
return;
|
|
28431
28605
|
}
|
|
28432
28606
|
try {
|
|
28433
|
-
versionCache = parseVersion((await probeProcess(
|
|
28607
|
+
versionCache = parseVersion((await probeProcess(currentBin, ["--version"], 1e4)).stdout);
|
|
28434
28608
|
if (versionCache && compareVersions(versionCache, "1.1.8") < 0) {
|
|
28435
28609
|
dormantReason = "agy " + versionCache + " is older than 1.1.8 — run: agy update";
|
|
28436
28610
|
log("dormant: " + dormantReason);
|
|
28437
28611
|
return;
|
|
28438
28612
|
}
|
|
28613
|
+
dormantReason = null;
|
|
28439
28614
|
log("agy detected: " + (versionCache ?? "unknown version"));
|
|
28440
28615
|
} catch {
|
|
28441
28616
|
log("version probe failed — continuing with fallback catalog");
|
|
28442
28617
|
}
|
|
28443
28618
|
await catalog.refreshIfNeeded().catch(() => void 0);
|
|
28444
28619
|
})();
|
|
28445
|
-
if (getConfig().enabled
|
|
28620
|
+
if (getConfig().enabled) try {
|
|
28446
28621
|
ctx.llm.registerAdapter([PROVIDER_ID], adapter);
|
|
28447
28622
|
log("registered provider route: antigravity");
|
|
28448
28623
|
} catch (e) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-agy-link",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.24",
|
|
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",
|