cli-jaw 2.17.59 → 2.17.60
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/src/agent/agy-models.js +64 -0
- package/dist/src/agent/agy-models.js.map +1 -0
- package/dist/src/agent/copilot-models.js +127 -0
- package/dist/src/agent/copilot-models.js.map +1 -0
- package/dist/src/agent/opencode-models.js +67 -0
- package/dist/src/agent/opencode-models.js.map +1 -0
- package/dist/src/cli/registry-live.js +52 -1
- package/dist/src/cli/registry-live.js.map +1 -1
- package/dist/src/telegram/bot.js +5 -4
- package/dist/src/telegram/bot.js.map +1 -1
- package/dist/src/telegram/callback-query.js +10 -0
- package/dist/src/telegram/callback-query.js.map +1 -0
- package/package.json +1 -1
- package/public/dist/.vite/manifest.json +25 -25
- package/public/dist/assets/{Activity-7WobRx8M.js → Activity-BUrp73Re.js} +1 -1
- package/public/dist/assets/{Developer-B08i7aVh.js → Developer-BdKPcw8Z.js} +1 -1
- package/public/dist/assets/{Display-NrqY_IaN.js → Display-BHGFX3O0.js} +1 -1
- package/public/dist/assets/{Embedding-YNyhSHUj.js → Embedding-DvdTj1BF.js} +1 -1
- package/public/dist/assets/{manager-B7QobNzw.js → manager-BpPiQqP8.js} +2 -2
- package/public/dist/assets/{manager-shortcuts-jsiX-zV6.js → manager-shortcuts-BDOzd8zm.js} +1 -1
- package/public/dist/assets/{settings-Bd6HveOX.js → settings-CUxM2lH7.js} +1 -1
- package/public/dist/assets/{settings-embedding-DeOQX-nw.js → settings-embedding-abQOXHyq.js} +2 -2
- package/public/dist/assets/shared-CiNP20HB.js +1 -0
- package/public/dist/manager/index.html +1 -1
- package/public/dist/settings/index.html +1 -1
- package/public/manager/src/App.tsx +2 -3
- package/public/manager/src/manager-shortcut-runner.ts +9 -2
- package/public/manager/src/manager-shortcuts.ts +32 -0
- package/public/manager/src/settings/pages/manager/shared.tsx +444 -12
- package/public/manager/src/usePreviewShortcutMessages.ts +5 -1
- package/scripts/check-private-boundary.mjs +4 -1
- package/scripts/ci/aggregate-check.sh +20 -3
- package/scripts/ci/macos-unit-manifest.mjs +27 -0
- package/scripts/ci/macos-unit-manifest.txt +29 -0
- package/scripts/require-release-evidence.mjs +4 -5
- package/public/dist/assets/shared-BI-LEt7g.js +0 -1
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Live AGY model inventory, read from `agy models`.
|
|
3
|
+
*
|
|
4
|
+
* The registry list was refreshed by hand against one AGY release, and Google
|
|
5
|
+
* retires the previous Flash generation from Antigravity soon after the next one
|
|
6
|
+
* ships. Reading the binary keeps the picker on models AGY can actually serve.
|
|
7
|
+
*/
|
|
8
|
+
import { execFile } from 'node:child_process';
|
|
9
|
+
import { promisify } from 'node:util';
|
|
10
|
+
import { detectCli } from '../core/cli-detection.js';
|
|
11
|
+
const execFileAsync = promisify(execFile);
|
|
12
|
+
/**
|
|
13
|
+
* Parse `agy models` output.
|
|
14
|
+
*
|
|
15
|
+
* After a `Fetching available models...` banner, each row is two tab-separated
|
|
16
|
+
* columns: the effort-suffixed slug, then the label.
|
|
17
|
+
*
|
|
18
|
+
* gemini-3.8-flash-high Gemini 3.8 Flash (High)
|
|
19
|
+
* claude-sonnet-4-6 Claude Sonnet 4.6 (Thinking)
|
|
20
|
+
*
|
|
21
|
+
* Only the label is kept as the choice. cli-jaw never sends `--effort` for AGY,
|
|
22
|
+
* and AGY rejects a tier-less slug in that shape ("requires --effort"). A line
|
|
23
|
+
* without a tab is banner or noise, never a model.
|
|
24
|
+
*/
|
|
25
|
+
export function parseAgyModelList(stdout) {
|
|
26
|
+
const models = [];
|
|
27
|
+
const slugs = {};
|
|
28
|
+
const seen = new Set();
|
|
29
|
+
for (const rawLine of stdout.split(/\r?\n/)) {
|
|
30
|
+
const tab = rawLine.indexOf('\t');
|
|
31
|
+
if (tab < 0)
|
|
32
|
+
continue;
|
|
33
|
+
const slug = rawLine.slice(0, tab).trim();
|
|
34
|
+
const label = rawLine.slice(tab + 1).trim();
|
|
35
|
+
if (!/^[a-z0-9][a-z0-9._-]*$/i.test(slug) || !label)
|
|
36
|
+
continue;
|
|
37
|
+
if (seen.has(label))
|
|
38
|
+
continue;
|
|
39
|
+
seen.add(label);
|
|
40
|
+
models.push(label);
|
|
41
|
+
slugs[label] = slug;
|
|
42
|
+
}
|
|
43
|
+
if (models.length === 0)
|
|
44
|
+
return null;
|
|
45
|
+
return { models, slugs, source: 'agy models' };
|
|
46
|
+
}
|
|
47
|
+
/** Run the CLI and parse its listing. Any failure answers null. */
|
|
48
|
+
export async function fetchAgyModelInventory(binary) {
|
|
49
|
+
const resolvedBinary = binary || detectCli('agy').path;
|
|
50
|
+
if (!resolvedBinary)
|
|
51
|
+
return null;
|
|
52
|
+
try {
|
|
53
|
+
const { stdout } = await execFileAsync(resolvedBinary, ['models'], {
|
|
54
|
+
encoding: 'utf8',
|
|
55
|
+
timeout: 15000,
|
|
56
|
+
env: { ...process.env, NO_COLOR: '1' },
|
|
57
|
+
});
|
|
58
|
+
return parseAgyModelList(stdout);
|
|
59
|
+
}
|
|
60
|
+
catch {
|
|
61
|
+
return null;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
//# sourceMappingURL=agy-models.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agy-models.js","sourceRoot":"","sources":["../../../src/agent/agy-models.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC9C,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AACtC,OAAO,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAC;AAErD,MAAM,aAAa,GAAG,SAAS,CAAC,QAAQ,CAAC,CAAC;AAU1C;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,iBAAiB,CAAC,MAAc;IAC5C,MAAM,MAAM,GAAa,EAAE,CAAC;IAC5B,MAAM,KAAK,GAA2B,EAAE,CAAC;IACzC,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;IAE/B,KAAK,MAAM,OAAO,IAAI,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC;QAC1C,MAAM,GAAG,GAAG,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;QAClC,IAAI,GAAG,GAAG,CAAC;YAAE,SAAS;QACtB,MAAM,IAAI,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;QAC1C,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;QAC5C,IAAI,CAAC,yBAAyB,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK;YAAE,SAAS;QAC9D,IAAI,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC;YAAE,SAAS;QAC9B,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QAChB,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACnB,KAAK,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC;IACxB,CAAC;IAED,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IACrC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,YAAY,EAAE,CAAC;AACnD,CAAC;AAED,mEAAmE;AACnE,MAAM,CAAC,KAAK,UAAU,sBAAsB,CAAC,MAAe;IACxD,MAAM,cAAc,GAAG,MAAM,IAAI,SAAS,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC;IACvD,IAAI,CAAC,cAAc;QAAE,OAAO,IAAI,CAAC;IACjC,IAAI,CAAC;QACD,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,aAAa,CAAC,cAAc,EAAE,CAAC,QAAQ,CAAC,EAAE;YAC/D,QAAQ,EAAE,MAAM;YAChB,OAAO,EAAE,KAAK;YACd,GAAG,EAAE,EAAE,GAAG,OAAO,CAAC,GAAG,EAAE,QAAQ,EAAE,GAAG,EAAE;SACzC,CAAC,CAAC;QACH,OAAO,iBAAiB,CAAC,MAAM,CAAC,CAAC;IACrC,CAAC;IAAC,MAAM,CAAC;QACL,OAAO,IAAI,CAAC;IAChB,CAAC;AACL,CAAC"}
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Live Copilot model inventory, read from the Copilot CLI's headless server.
|
|
3
|
+
*
|
|
4
|
+
* `copilot` has no listing subcommand and `--acp` does not advertise models, but
|
|
5
|
+
* `copilot --headless --stdio` answers the same `models.list` JSON-RPC the
|
|
6
|
+
* official Copilot SDK uses. That list is per account: it holds exactly the
|
|
7
|
+
* models the signed-in plan is entitled to, which a static list cannot know.
|
|
8
|
+
*/
|
|
9
|
+
import { spawn } from 'node:child_process';
|
|
10
|
+
import { detectCli } from '../core/cli-detection.js';
|
|
11
|
+
const DEFAULT_TIMEOUT_MS = 10000;
|
|
12
|
+
const MAX_RESPONSE_BYTES = 4 * 1024 * 1024;
|
|
13
|
+
const MAX_MODELS = 500;
|
|
14
|
+
function isRecord(value) {
|
|
15
|
+
return !!value && typeof value === 'object' && !Array.isArray(value);
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Parse a `models.list` result.
|
|
19
|
+
*
|
|
20
|
+
* { models: [{ id, policy?: { state }, supportedReasoningEfforts?, defaultReasoningEffort? }] }
|
|
21
|
+
*
|
|
22
|
+
* A model whose policy is anything but `enabled` is left out: Copilot lists
|
|
23
|
+
* models the plan has not enabled or whose terms were not accepted, and those
|
|
24
|
+
* fail when selected. A model without a policy (`auto`) is always selectable.
|
|
25
|
+
* `none` is dropped from effort ladders because cli-jaw spells "no effort" as
|
|
26
|
+
* an empty value.
|
|
27
|
+
*/
|
|
28
|
+
export function parseCopilotModelList(result) {
|
|
29
|
+
if (!isRecord(result) || !Array.isArray(result['models']))
|
|
30
|
+
return null;
|
|
31
|
+
const models = [];
|
|
32
|
+
const effortsByModel = {};
|
|
33
|
+
const defaultEffortByModel = {};
|
|
34
|
+
for (const row of result['models']) {
|
|
35
|
+
if (models.length >= MAX_MODELS)
|
|
36
|
+
break;
|
|
37
|
+
if (!isRecord(row))
|
|
38
|
+
continue;
|
|
39
|
+
const id = row['id'];
|
|
40
|
+
if (typeof id !== 'string' || !/^[A-Za-z0-9][\w.:/-]*$/.test(id))
|
|
41
|
+
continue;
|
|
42
|
+
if (effortsByModel[id])
|
|
43
|
+
continue;
|
|
44
|
+
const policy = row['policy'];
|
|
45
|
+
if (isRecord(policy) && policy['state'] !== 'enabled')
|
|
46
|
+
continue;
|
|
47
|
+
const efforts = Array.isArray(row['supportedReasoningEfforts'])
|
|
48
|
+
? row['supportedReasoningEfforts'].filter((e) => typeof e === 'string' && e !== 'none')
|
|
49
|
+
: [];
|
|
50
|
+
models.push(id);
|
|
51
|
+
effortsByModel[id] = efforts;
|
|
52
|
+
const defaultEffort = row['defaultReasoningEffort'];
|
|
53
|
+
if (typeof defaultEffort === 'string' && efforts.includes(defaultEffort)) {
|
|
54
|
+
defaultEffortByModel[id] = defaultEffort;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
if (models.length === 0)
|
|
58
|
+
return null;
|
|
59
|
+
return { models, effortsByModel, defaultEffortByModel, source: 'copilot models.list' };
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Ask a headless Copilot server for its models, then stop it.
|
|
63
|
+
*
|
|
64
|
+
* The server speaks JSON-RPC with `Content-Length` framing, like LSP. Any
|
|
65
|
+
* failure — no binary, not signed in, timeout, malformed frame — answers null.
|
|
66
|
+
*/
|
|
67
|
+
export async function fetchCopilotModelInventory(binary, timeoutMs = DEFAULT_TIMEOUT_MS) {
|
|
68
|
+
const resolvedBinary = binary || detectCli('copilot').path;
|
|
69
|
+
if (!resolvedBinary)
|
|
70
|
+
return null;
|
|
71
|
+
return new Promise((resolve) => {
|
|
72
|
+
let settled = false;
|
|
73
|
+
let buffered = Buffer.alloc(0);
|
|
74
|
+
const child = spawn(resolvedBinary, ['--headless', '--no-auto-update', '--log-level', 'error', '--stdio'], {
|
|
75
|
+
stdio: ['pipe', 'pipe', 'ignore'],
|
|
76
|
+
env: { ...process.env, NO_COLOR: '1' },
|
|
77
|
+
windowsHide: true,
|
|
78
|
+
});
|
|
79
|
+
const finish = (value) => {
|
|
80
|
+
if (settled)
|
|
81
|
+
return;
|
|
82
|
+
settled = true;
|
|
83
|
+
clearTimeout(timer);
|
|
84
|
+
child.stdout?.removeAllListeners('data');
|
|
85
|
+
if (child.exitCode === null && child.signalCode === null)
|
|
86
|
+
child.kill();
|
|
87
|
+
resolve(value);
|
|
88
|
+
};
|
|
89
|
+
const timer = setTimeout(() => finish(null), timeoutMs);
|
|
90
|
+
child.on('error', () => finish(null));
|
|
91
|
+
child.on('exit', () => finish(null));
|
|
92
|
+
child.stdin?.on('error', () => finish(null));
|
|
93
|
+
child.stdout?.on('data', (chunk) => {
|
|
94
|
+
buffered = Buffer.concat([buffered, chunk]);
|
|
95
|
+
if (buffered.length > MAX_RESPONSE_BYTES)
|
|
96
|
+
return finish(null);
|
|
97
|
+
for (;;) {
|
|
98
|
+
const headerEnd = buffered.indexOf('\r\n\r\n');
|
|
99
|
+
if (headerEnd < 0)
|
|
100
|
+
return;
|
|
101
|
+
const length = /Content-Length:\s*(\d+)/i.exec(buffered.subarray(0, headerEnd).toString('ascii'));
|
|
102
|
+
if (!length)
|
|
103
|
+
return finish(null);
|
|
104
|
+
const bodyStart = headerEnd + 4;
|
|
105
|
+
const bodyEnd = bodyStart + Number(length[1]);
|
|
106
|
+
if (buffered.length < bodyEnd)
|
|
107
|
+
return;
|
|
108
|
+
const body = buffered.subarray(bodyStart, bodyEnd).toString('utf8');
|
|
109
|
+
buffered = buffered.subarray(bodyEnd);
|
|
110
|
+
let message;
|
|
111
|
+
try {
|
|
112
|
+
message = JSON.parse(body);
|
|
113
|
+
}
|
|
114
|
+
catch {
|
|
115
|
+
return finish(null);
|
|
116
|
+
}
|
|
117
|
+
if (isRecord(message) && message['id'] === 1) {
|
|
118
|
+
return finish(message['error'] ? null : parseCopilotModelList(message['result']));
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
});
|
|
122
|
+
const request = Buffer.from(JSON.stringify({ jsonrpc: '2.0', id: 1, method: 'models.list', params: {} }));
|
|
123
|
+
child.stdin?.write(`Content-Length: ${request.length}\r\n\r\n`);
|
|
124
|
+
child.stdin?.write(request);
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
//# sourceMappingURL=copilot-models.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"copilot-models.js","sourceRoot":"","sources":["../../../src/agent/copilot-models.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Live OpenCode model inventory, read from `opencode models`.
|
|
3
|
+
*
|
|
4
|
+
* The registry carried the opencode-go roster by hand, copied from opencodex
|
|
5
|
+
* metadata. The CLI lists every model the user's configured providers serve,
|
|
6
|
+
* including providers no static list could have predicted.
|
|
7
|
+
*/
|
|
8
|
+
import { execFile } from 'node:child_process';
|
|
9
|
+
import { promisify } from 'node:util';
|
|
10
|
+
import { detectCli } from '../core/cli-detection.js';
|
|
11
|
+
const execFileAsync = promisify(execFile);
|
|
12
|
+
/** The provider the static roster and the default model belong to. */
|
|
13
|
+
const PREFERRED_PROVIDER = 'opencode-go';
|
|
14
|
+
/** A sanity bound; a real listing across many providers stays well below it. */
|
|
15
|
+
const MAX_MODELS = 2000;
|
|
16
|
+
/**
|
|
17
|
+
* Parse `opencode models` output.
|
|
18
|
+
*
|
|
19
|
+
* Each line is one `provider/model` id. Model ids may themselves contain slashes
|
|
20
|
+
* (`openrouter/anthropic/claude-x`), so only the first segment is the provider.
|
|
21
|
+
*
|
|
22
|
+
* opencode-go/kimi-k2.7-code
|
|
23
|
+
* google/gemini-3.6-flash
|
|
24
|
+
*
|
|
25
|
+
* Lines without a slash or with whitespace are logs, never models. The
|
|
26
|
+
* opencode-go provider is listed first because the default lives there; the
|
|
27
|
+
* rest keep the CLI's order.
|
|
28
|
+
*/
|
|
29
|
+
export function parseOpencodeModelList(stdout) {
|
|
30
|
+
const preferred = [];
|
|
31
|
+
const rest = [];
|
|
32
|
+
const seen = new Set();
|
|
33
|
+
for (const rawLine of stdout.split(/\r?\n/)) {
|
|
34
|
+
const line = rawLine.trim();
|
|
35
|
+
if (!/^[A-Za-z0-9][\w.@:+-]*\/\S+$/.test(line))
|
|
36
|
+
continue;
|
|
37
|
+
if (seen.has(line))
|
|
38
|
+
continue;
|
|
39
|
+
if (seen.size >= MAX_MODELS)
|
|
40
|
+
break;
|
|
41
|
+
seen.add(line);
|
|
42
|
+
(line.startsWith(`${PREFERRED_PROVIDER}/`) ? preferred : rest).push(line);
|
|
43
|
+
}
|
|
44
|
+
const models = [...preferred, ...rest];
|
|
45
|
+
if (models.length === 0)
|
|
46
|
+
return null;
|
|
47
|
+
return { models, source: 'opencode models' };
|
|
48
|
+
}
|
|
49
|
+
/** Run the CLI and parse its listing. Any failure answers null. */
|
|
50
|
+
export async function fetchOpencodeModelInventory(binary) {
|
|
51
|
+
const resolvedBinary = binary || detectCli('opencode').path;
|
|
52
|
+
if (!resolvedBinary)
|
|
53
|
+
return null;
|
|
54
|
+
try {
|
|
55
|
+
const { stdout } = await execFileAsync(resolvedBinary, ['models'], {
|
|
56
|
+
encoding: 'utf8',
|
|
57
|
+
timeout: 20000,
|
|
58
|
+
maxBuffer: 4 * 1024 * 1024,
|
|
59
|
+
env: { ...process.env, NO_COLOR: '1' },
|
|
60
|
+
});
|
|
61
|
+
return parseOpencodeModelList(stdout);
|
|
62
|
+
}
|
|
63
|
+
catch {
|
|
64
|
+
return null;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
//# sourceMappingURL=opencode-models.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"opencode-models.js","sourceRoot":"","sources":["../../../src/agent/opencode-models.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC9C,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AACtC,OAAO,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAC;AAErD,MAAM,aAAa,GAAG,SAAS,CAAC,QAAQ,CAAC,CAAC;AAE1C,sEAAsE;AACtE,MAAM,kBAAkB,GAAG,aAAa,CAAC;AACzC,gFAAgF;AAChF,MAAM,UAAU,GAAG,IAAI,CAAC;AAQxB;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,sBAAsB,CAAC,MAAc;IACjD,MAAM,SAAS,GAAa,EAAE,CAAC;IAC/B,MAAM,IAAI,GAAa,EAAE,CAAC;IAC1B,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;IAE/B,KAAK,MAAM,OAAO,IAAI,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC;QAC1C,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC;QAC5B,IAAI,CAAC,8BAA8B,CAAC,IAAI,CAAC,IAAI,CAAC;YAAE,SAAS;QACzD,IAAI,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC;YAAE,SAAS;QAC7B,IAAI,IAAI,CAAC,IAAI,IAAI,UAAU;YAAE,MAAM;QACnC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QACf,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,kBAAkB,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC9E,CAAC;IAED,MAAM,MAAM,GAAG,CAAC,GAAG,SAAS,EAAE,GAAG,IAAI,CAAC,CAAC;IACvC,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IACrC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,iBAAiB,EAAE,CAAC;AACjD,CAAC;AAED,mEAAmE;AACnE,MAAM,CAAC,KAAK,UAAU,2BAA2B,CAAC,MAAe;IAC7D,MAAM,cAAc,GAAG,MAAM,IAAI,SAAS,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC;IAC5D,IAAI,CAAC,cAAc;QAAE,OAAO,IAAI,CAAC;IACjC,IAAI,CAAC;QACD,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,aAAa,CAAC,cAAc,EAAE,CAAC,QAAQ,CAAC,EAAE;YAC/D,QAAQ,EAAE,MAAM;YAChB,OAAO,EAAE,KAAK;YACd,SAAS,EAAE,CAAC,GAAG,IAAI,GAAG,IAAI;YAC1B,GAAG,EAAE,EAAE,GAAG,OAAO,CAAC,GAAG,EAAE,QAAQ,EAAE,GAAG,EAAE;SACzC,CAAC,CAAC;QACH,OAAO,sBAAsB,CAAC,MAAM,CAAC,CAAC;IAC1C,CAAC;IAAC,MAAM,CAAC;QACL,OAAO,IAAI,CAAC;IAChB,CAAC;AACL,CAAC"}
|
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
import { fetchKiroModelInventory } from '../agent/kiro-models.js';
|
|
2
|
+
import { fetchAgyModelInventory } from '../agent/agy-models.js';
|
|
3
|
+
import { fetchOpencodeModelInventory } from '../agent/opencode-models.js';
|
|
4
|
+
import { fetchCopilotModelInventory } from '../agent/copilot-models.js';
|
|
2
5
|
import { fetchCursorModelInventory } from '../agent/cursor-model-inventory.js';
|
|
3
6
|
import { fetchGrokModelInventory } from '../agent/grok-models.js';
|
|
4
7
|
import { CLI_REGISTRY } from './registry.js';
|
|
@@ -24,12 +27,15 @@ function unionEfforts(effortsByModel) {
|
|
|
24
27
|
}
|
|
25
28
|
export async function buildLiveCliRegistry() {
|
|
26
29
|
const registry = structuredClone(CLI_REGISTRY);
|
|
27
|
-
const [kiroInventory, openCodexRuntime, claudeCatalog, cursorInventory, grokInventory] = await Promise.all([
|
|
30
|
+
const [kiroInventory, openCodexRuntime, claudeCatalog, cursorInventory, grokInventory, agyInventory, opencodeInventory, copilotInventory] = await Promise.all([
|
|
28
31
|
fetchKiroModelInventory(),
|
|
29
32
|
resolveOpenCodexRuntime(),
|
|
30
33
|
resolveClaudeCatalogForRegistry(),
|
|
31
34
|
fetchCursorModelInventory(),
|
|
32
35
|
fetchGrokModelInventory(),
|
|
36
|
+
fetchAgyModelInventory(),
|
|
37
|
+
fetchOpencodeModelInventory(),
|
|
38
|
+
fetchCopilotModelInventory(),
|
|
33
39
|
]);
|
|
34
40
|
const codexResult = await resolveOpenCodexCodexModelsDetailed(openCodexRuntime);
|
|
35
41
|
const executionCoupling = diagnoseOpenCodexExecution(readCodexRootOpenAiBaseUrl(), openCodexRuntime);
|
|
@@ -102,6 +108,40 @@ export async function buildLiveCliRegistry() {
|
|
|
102
108
|
...(grokInventory.defaultModel ? { observedDefaultModel: grokInventory.defaultModel } : {}),
|
|
103
109
|
};
|
|
104
110
|
}
|
|
111
|
+
if (agyInventory?.models.length) {
|
|
112
|
+
// `defaultModel` stays static for the buildDefaultPerCli() seeding reason,
|
|
113
|
+
// except when AGY no longer offers it: Google retires the previous Flash
|
|
114
|
+
// generation from Antigravity, and a retired default would be unselectable.
|
|
115
|
+
registry['agy'] = {
|
|
116
|
+
...withSelectableDefault(registry['agy'], agyInventory.models),
|
|
117
|
+
models: agyInventory.models,
|
|
118
|
+
modelSource: agyInventory.source,
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
if (opencodeInventory?.models.length) {
|
|
122
|
+
// Every model the configured providers serve, opencode-go first. The
|
|
123
|
+
// static default is kept unless no configured provider serves it.
|
|
124
|
+
registry['opencode'] = {
|
|
125
|
+
...withSelectableDefault(registry['opencode'], opencodeInventory.models),
|
|
126
|
+
models: opencodeInventory.models,
|
|
127
|
+
modelSource: opencodeInventory.source,
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
if (copilotInventory?.models.length) {
|
|
131
|
+
// The list is the signed-in plan's entitlement, so the static default is
|
|
132
|
+
// replaced when the plan does not include it. Efforts are narrowed per
|
|
133
|
+
// model like Codex: Copilot advertises a different ladder per model and
|
|
134
|
+
// none at all for some, and the value is written to ~/.copilot/config.json.
|
|
135
|
+
const merged = unionEfforts(copilotInventory.effortsByModel);
|
|
136
|
+
registry['copilot'] = {
|
|
137
|
+
...withSelectableDefault(registry['copilot'], copilotInventory.models),
|
|
138
|
+
models: copilotInventory.models,
|
|
139
|
+
modelSource: copilotInventory.source,
|
|
140
|
+
effortsByModel: copilotInventory.effortsByModel,
|
|
141
|
+
defaultEffortByModel: copilotInventory.defaultEffortByModel,
|
|
142
|
+
...(merged.length > 0 ? { efforts: merged } : {}),
|
|
143
|
+
};
|
|
144
|
+
}
|
|
105
145
|
if (claudeCatalog) {
|
|
106
146
|
// `defaultModel` stays static for the same reason it does for Codex:
|
|
107
147
|
// buildDefaultPerCli() seeds user settings from it, so a bundle update must
|
|
@@ -133,6 +173,17 @@ export async function buildLiveCliRegistry() {
|
|
|
133
173
|
}
|
|
134
174
|
return registry;
|
|
135
175
|
}
|
|
176
|
+
/**
|
|
177
|
+
* Keep a registry entry's static default unless the live list no longer offers it,
|
|
178
|
+
* in which case the first live model takes its place so the picker stays valid.
|
|
179
|
+
*/
|
|
180
|
+
function withSelectableDefault(entry, models) {
|
|
181
|
+
const base = entry ?? {};
|
|
182
|
+
const staticDefault = base['defaultModel'];
|
|
183
|
+
if (typeof staticDefault === 'string' && models.includes(staticDefault))
|
|
184
|
+
return base;
|
|
185
|
+
return { ...base, defaultModel: models[0] };
|
|
186
|
+
}
|
|
136
187
|
/**
|
|
137
188
|
* Read the installed Claude Code bundle's catalog, if one is installed.
|
|
138
189
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"registry-live.js","sourceRoot":"","sources":["../../../src/cli/registry-live.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,uBAAuB,EAAE,MAAM,yBAAyB,CAAC;AAClE,OAAO,EAAE,yBAAyB,EAAE,MAAM,oCAAoC,CAAC;AAC/E,OAAO,EAAE,uBAAuB,EAAE,MAAM,yBAAyB,CAAC;AAClE,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAC7C,OAAO,EAAE,sBAAsB,EAAE,0BAA0B,EAAE,MAAM,6BAA6B,CAAC;AACjG,OAAO,EAAE,yBAAyB,EAAE,MAAM,oBAAoB,CAAC;AAC/D,OAAO,EAAE,mCAAmC,EAAE,MAAM,uBAAuB,CAAC;AAC5E,OAAO,EAAE,0BAA0B,EAAE,uBAAuB,EAAE,MAAM,wBAAwB,CAAC;AAC7F,OAAO,EAAE,0BAA0B,EAAE,MAAM,yBAAyB,CAAC;AACrE,OAAO,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAC;AAErD,uEAAuE;AACvE,SAAS,YAAY,CAAC,cAAwC;IAC1D,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;IAC/B,MAAM,GAAG,GAAa,EAAE,CAAC;IACzB,KAAK,MAAM,OAAO,IAAI,MAAM,CAAC,MAAM,CAAC,cAAc,CAAC,EAAE,CAAC;QAClD,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;YAC3B,IAAI,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC;gBAAE,SAAS;YAC/B,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;YACjB,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACrB,CAAC;IACL,CAAC;IACD,OAAO,GAAG,CAAC;AACf,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,oBAAoB;IACtC,MAAM,QAAQ,GAAG,eAAe,CAAC,YAAY,CAA4C,CAAC;IAE1F,MAAM,CAAC,aAAa,EAAE,gBAAgB,EAAE,aAAa,EAAE,eAAe,EAAE,aAAa,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;
|
|
1
|
+
{"version":3,"file":"registry-live.js","sourceRoot":"","sources":["../../../src/cli/registry-live.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,uBAAuB,EAAE,MAAM,yBAAyB,CAAC;AAClE,OAAO,EAAE,sBAAsB,EAAE,MAAM,wBAAwB,CAAC;AAChE,OAAO,EAAE,2BAA2B,EAAE,MAAM,6BAA6B,CAAC;AAC1E,OAAO,EAAE,0BAA0B,EAAE,MAAM,4BAA4B,CAAC;AACxE,OAAO,EAAE,yBAAyB,EAAE,MAAM,oCAAoC,CAAC;AAC/E,OAAO,EAAE,uBAAuB,EAAE,MAAM,yBAAyB,CAAC;AAClE,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAC7C,OAAO,EAAE,sBAAsB,EAAE,0BAA0B,EAAE,MAAM,6BAA6B,CAAC;AACjG,OAAO,EAAE,yBAAyB,EAAE,MAAM,oBAAoB,CAAC;AAC/D,OAAO,EAAE,mCAAmC,EAAE,MAAM,uBAAuB,CAAC;AAC5E,OAAO,EAAE,0BAA0B,EAAE,uBAAuB,EAAE,MAAM,wBAAwB,CAAC;AAC7F,OAAO,EAAE,0BAA0B,EAAE,MAAM,yBAAyB,CAAC;AACrE,OAAO,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAC;AAErD,uEAAuE;AACvE,SAAS,YAAY,CAAC,cAAwC;IAC1D,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;IAC/B,MAAM,GAAG,GAAa,EAAE,CAAC;IACzB,KAAK,MAAM,OAAO,IAAI,MAAM,CAAC,MAAM,CAAC,cAAc,CAAC,EAAE,CAAC;QAClD,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;YAC3B,IAAI,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC;gBAAE,SAAS;YAC/B,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;YACjB,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACrB,CAAC;IACL,CAAC;IACD,OAAO,GAAG,CAAC;AACf,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,oBAAoB;IACtC,MAAM,QAAQ,GAAG,eAAe,CAAC,YAAY,CAA4C,CAAC;IAE1F,MAAM,CAAC,aAAa,EAAE,gBAAgB,EAAE,aAAa,EAAE,eAAe,EAAE,aAAa,EAAE,YAAY,EAAE,iBAAiB,EAAE,gBAAgB,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;QAC1J,uBAAuB,EAAE;QACzB,uBAAuB,EAAE;QACzB,+BAA+B,EAAE;QACjC,yBAAyB,EAAE;QAC3B,uBAAuB,EAAE;QACzB,sBAAsB,EAAE;QACxB,2BAA2B,EAAE;QAC7B,0BAA0B,EAAE;KAC/B,CAAC,CAAC;IACH,MAAM,WAAW,GAAG,MAAM,mCAAmC,CAAC,gBAAgB,CAAC,CAAC;IAEhF,MAAM,iBAAiB,GAAG,0BAA0B,CAAC,0BAA0B,EAAE,EAAE,gBAAgB,CAAC,CAAC;IACrG,QAAQ,CAAC,OAAO,CAAC,GAAG,EAAE,GAAG,QAAQ,CAAC,OAAO,CAAC,EAAE,iBAAiB,EAAE,CAAC;IAChE,QAAQ,CAAC,WAAW,CAAC,GAAG,EAAE,GAAG,QAAQ,CAAC,WAAW,CAAC,EAAE,iBAAiB,EAAE,CAAC;IAExE,MAAM,WAAW,GAAG,WAAW,CAAC,MAAM,CAAC;IACvC,IAAI,WAAW,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACzB,yEAAyE;QACzE,uEAAuE;QACvE,yEAAyE;QACzE,iCAAiC;QACjC,uEAAuE;QACvE,sEAAsE;QACtE,MAAM,cAAc,GAA6B,EAAE,CAAC;QACpD,MAAM,oBAAoB,GAA2B,EAAE,CAAC;QACxD,KAAK,MAAM,KAAK,IAAI,WAAW,CAAC,OAAO,EAAE,CAAC;YACtC,cAAc,CAAC,KAAK,CAAC,EAAE,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC,OAAO,CAAC,CAAC;YAC9C,IAAI,KAAK,CAAC,aAAa;gBAAE,oBAAoB,CAAC,KAAK,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,aAAa,CAAC;QAClF,CAAC;QACD,MAAM,MAAM,GAAG,YAAY,CAAC,cAAc,CAAC,CAAC;QAC5C,MAAM,UAAU,GAA4B;YACxC,MAAM,EAAE,WAAW;YACnB,WAAW,EAAE,WAAW,CAAC,MAAM;YAC/B,cAAc;YACd,oBAAoB;YACpB,sEAAsE;YACtE,4CAA4C;YAC5C,GAAG,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SACpD,CAAC;QACF,8EAA8E;QAC9E,yEAAyE;QACzE,oCAAoC;QACpC,QAAQ,CAAC,OAAO,CAAC,GAAG,EAAE,GAAG,QAAQ,CAAC,OAAO,CAAC,EAAE,GAAG,UAAU,EAAE,CAAC;QAC5D,QAAQ,CAAC,WAAW,CAAC,GAAG,EAAE,GAAG,QAAQ,CAAC,WAAW,CAAC,EAAE,GAAG,UAAU,EAAE,CAAC;IACxE,CAAC;IAED,IAAI,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC;QAC/B,QAAQ,CAAC,WAAW,CAAC,GAAG;YACpB,GAAG,QAAQ,CAAC,WAAW,CAAC;YACxB,MAAM,EAAE,aAAa,CAAC,MAAM;YAC5B,YAAY,EAAE,aAAa,CAAC,YAAY;YACxC,WAAW,EAAE,aAAa,CAAC,MAAM;YACjC,YAAY,EAAE,aAAa,CAAC,OAAO;SACtC,CAAC;IACN,CAAC;IAED,IAAI,eAAe,EAAE,UAAU,CAAC,MAAM,EAAE,CAAC;QACrC,4EAA4E;QAC5E,0EAA0E;QAC1E,qCAAqC;QACrC,EAAE;QACF,2EAA2E;QAC3E,2EAA2E;QAC3E,6CAA6C;QAC7C,QAAQ,CAAC,QAAQ,CAAC,GAAG;YACjB,GAAG,QAAQ,CAAC,QAAQ,CAAC;YACrB,MAAM,EAAE,eAAe,CAAC,UAAU;YAClC,WAAW,EAAE,eAAe,CAAC,MAAM;YACnC,cAAc,EAAE,eAAe,CAAC,cAAc;YAC9C,QAAQ,EAAE,eAAe,CAAC,QAAQ;SACrC,CAAC;IACN,CAAC;IAED,IAAI,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC;QAC/B,0EAA0E;QAC1E,uEAAuE;QACvE,kDAAkD;QAClD,QAAQ,CAAC,MAAM,CAAC,GAAG;YACf,GAAG,QAAQ,CAAC,MAAM,CAAC;YACnB,MAAM,EAAE,aAAa,CAAC,MAAM;YAC5B,WAAW,EAAE,aAAa,CAAC,MAAM;YACjC,GAAG,CAAC,aAAa,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE,oBAAoB,EAAE,aAAa,CAAC,YAAY,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SAC9F,CAAC;IACN,CAAC;IAED,IAAI,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC;QAC9B,2EAA2E;QAC3E,yEAAyE;QACzE,4EAA4E;QAC5E,QAAQ,CAAC,KAAK,CAAC,GAAG;YACd,GAAG,qBAAqB,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,YAAY,CAAC,MAAM,CAAC;YAC9D,MAAM,EAAE,YAAY,CAAC,MAAM;YAC3B,WAAW,EAAE,YAAY,CAAC,MAAM;SACnC,CAAC;IACN,CAAC;IAED,IAAI,iBAAiB,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC;QACnC,qEAAqE;QACrE,kEAAkE;QAClE,QAAQ,CAAC,UAAU,CAAC,GAAG;YACnB,GAAG,qBAAqB,CAAC,QAAQ,CAAC,UAAU,CAAC,EAAE,iBAAiB,CAAC,MAAM,CAAC;YACxE,MAAM,EAAE,iBAAiB,CAAC,MAAM;YAChC,WAAW,EAAE,iBAAiB,CAAC,MAAM;SACxC,CAAC;IACN,CAAC;IAED,IAAI,gBAAgB,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC;QAClC,yEAAyE;QACzE,uEAAuE;QACvE,wEAAwE;QACxE,4EAA4E;QAC5E,MAAM,MAAM,GAAG,YAAY,CAAC,gBAAgB,CAAC,cAAc,CAAC,CAAC;QAC7D,QAAQ,CAAC,SAAS,CAAC,GAAG;YAClB,GAAG,qBAAqB,CAAC,QAAQ,CAAC,SAAS,CAAC,EAAE,gBAAgB,CAAC,MAAM,CAAC;YACtE,MAAM,EAAE,gBAAgB,CAAC,MAAM;YAC/B,WAAW,EAAE,gBAAgB,CAAC,MAAM;YACpC,cAAc,EAAE,gBAAgB,CAAC,cAAc;YAC/C,oBAAoB,EAAE,gBAAgB,CAAC,oBAAoB;YAC3D,GAAG,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SACpD,CAAC;IACN,CAAC;IAED,IAAI,aAAa,EAAE,CAAC;QAChB,qEAAqE;QACrE,4EAA4E;QAC5E,4EAA4E;QAC5E,8DAA8D;QAC9D,EAAE;QACF,0EAA0E;QAC1E,uDAAuD;QACvD,MAAM,oBAAoB,GAAG,yBAAyB,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC;QAC7E,MAAM,WAAW,GAA4B;YACzC,MAAM,EAAE,aAAa,CAAC,MAAM;YAC5B,WAAW,EAAE,eAAe;YAC5B,YAAY,EAAE,aAAa,CAAC,OAAO;YACnC,cAAc,EAAE,oBAAoB;SACvC,CAAC;QACF,KAAK,MAAM,GAAG,IAAI,CAAC,QAAQ,CAAU,EAAE,CAAC;YACpC,MAAM,KAAK,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC;YAC5B,IAAI,CAAC,KAAK;gBAAE,SAAS;YACrB,MAAM,aAAa,GAAG,KAAK,CAAC,cAAc,CAAC,CAAC;YAC5C,QAAQ,CAAC,GAAG,CAAC,GAAG;gBACZ,GAAG,KAAK;gBACR,GAAG,WAAW;gBACd,GAAG,CAAC,OAAO,aAAa,KAAK,QAAQ,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC,QAAQ,CAAC,aAAa,CAAC;oBAClF,CAAC,CAAC,EAAE,YAAY,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE;oBAC3C,CAAC,CAAC,EAAE,CAAC;aACZ,CAAC;QACN,CAAC;IACL,CAAC;IAED,OAAO,QAAQ,CAAC;AACpB,CAAC;AAED;;;GAGG;AACH,SAAS,qBAAqB,CAAC,KAA0C,EAAE,MAAgB;IACvF,MAAM,IAAI,GAAG,KAAK,IAAI,EAAE,CAAC;IACzB,MAAM,aAAa,GAAG,IAAI,CAAC,cAAc,CAAC,CAAC;IAC3C,IAAI,OAAO,aAAa,KAAK,QAAQ,IAAI,MAAM,CAAC,QAAQ,CAAC,aAAa,CAAC;QAAE,OAAO,IAAI,CAAC;IACrF,OAAO,EAAE,GAAG,IAAI,EAAE,YAAY,EAAE,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC;AAChD,CAAC;AAED;;;;;;GAMG;AACH,KAAK,UAAU,+BAA+B;IAC1C,MAAM,SAAS,GAAG,SAAS,CAAC,QAAQ,CAAC,CAAC;IACtC,IAAI,CAAC,SAAS,CAAC,SAAS,IAAI,CAAC,SAAS,CAAC,IAAI;QAAE,OAAO,IAAI,CAAC;IACzD,MAAM,OAAO,GAAG,MAAM,0BAA0B,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;IACjE,IAAI,CAAC,OAAO;QAAE,OAAO,IAAI,CAAC;IAC1B,MAAM,MAAM,GAAG,sBAAsB,CAAC,OAAO,CAAC,CAAC;IAC/C,OAAO,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;AAC3E,CAAC"}
|
package/dist/src/telegram/bot.js
CHANGED
|
@@ -56,6 +56,7 @@ import { sendWithRetryPolicy } from '../messaging/retry.js';
|
|
|
56
56
|
import { deliveryFailed, deliverySent } from '../messaging/delivery-outcome.js';
|
|
57
57
|
import { handleApprovalCommand, handleApprovalCallback, registerProductionTransport } from '../core/dispatch-approval-ingress.js';
|
|
58
58
|
import { parseApprovalCallbackData } from '../messaging/approval-presentation.js';
|
|
59
|
+
import { answerCallbackQueryBestEffort } from './callback-query.js';
|
|
59
60
|
// ─── State ───────────────────────────────────────────
|
|
60
61
|
export let telegramBot = null;
|
|
61
62
|
export const telegramActiveChatIds = new Set();
|
|
@@ -672,7 +673,7 @@ async function _initTelegramInner() {
|
|
|
672
673
|
bot.command('id', (ctx) => ctx.reply(`Chat ID: <code>${ctx.chat?.id ?? ''}</code>`, { parse_mode: 'HTML' }));
|
|
673
674
|
// Inline-keyboard elicitation answers (single_select fences → buttons).
|
|
674
675
|
bot.callbackQuery(/^(appr|aprd):/, async (ctx) => {
|
|
675
|
-
await ctx.answerCallbackQuery();
|
|
676
|
+
await answerCallbackQueryBestEffort(() => ctx.answerCallbackQuery());
|
|
676
677
|
const data = ctx.callbackQuery.data ?? '';
|
|
677
678
|
const parsed = parseApprovalCallbackData(data);
|
|
678
679
|
const chatId = ctx.chat?.id !== undefined ? String(ctx.chat.id) : '';
|
|
@@ -686,15 +687,15 @@ async function _initTelegramInner() {
|
|
|
686
687
|
bot.callbackQuery(/^elic:/, async (ctx) => {
|
|
687
688
|
const cbChatId = ctx.chat?.id;
|
|
688
689
|
if (!cbChatId) {
|
|
689
|
-
await ctx.answerCallbackQuery();
|
|
690
|
+
await answerCallbackQueryBestEffort(() => ctx.answerCallbackQuery());
|
|
690
691
|
return;
|
|
691
692
|
}
|
|
692
693
|
const result = handleElicitationCallback(String(cbChatId), ctx.callbackQuery.data ?? '');
|
|
693
694
|
if (result.kind === 'stale') {
|
|
694
|
-
await ctx.answerCallbackQuery({ text: t('tg.elicitationExpired', {}, currentLocale()) });
|
|
695
|
+
await answerCallbackQueryBestEffort(() => ctx.answerCallbackQuery({ text: t('tg.elicitationExpired', {}, currentLocale()) }));
|
|
695
696
|
return;
|
|
696
697
|
}
|
|
697
|
-
await ctx.answerCallbackQuery({ text: redactOutboundText(result.ack) });
|
|
698
|
+
await answerCallbackQueryBestEffort(() => ctx.answerCallbackQuery({ text: redactOutboundText(result.ack) }));
|
|
698
699
|
// Best-effort: freeze the tapped question's keyboard so the choice reads as taken.
|
|
699
700
|
await ctx.editMessageReplyMarkup({ reply_markup: { inline_keyboard: [] } }).catch(() => { });
|
|
700
701
|
if (result.kind === 'complete') {
|