dsh-agy-cli 0.0.0-stage → 0.12.0
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/LICENSE +30 -0
- package/README.en.md +27 -0
- package/README.md +94 -2
- package/agents/dsh-agy-image-view.md +17 -0
- package/agents/dsh-agy-mcp-executor.md +32 -0
- package/agents/dsh-agy-read-only.md +20 -0
- package/agents/dsh-agy-tool-free.md +16 -0
- package/agents/dsh-agy-workspace-write.md +23 -0
- package/bin/dsh-agy-cli.js +9 -0
- package/bin/win32-x64/agy-launcher.exe +0 -0
- package/cordis.patch.yml +16 -0
- package/dist/client.js +4259 -0
- package/lib/agent-installer.d.ts +66 -0
- package/lib/agent-installer.js +147 -0
- package/lib/agent-presets.d.ts +42 -0
- package/lib/agent-presets.js +130 -0
- package/lib/agents-cli.d.ts +3 -0
- package/lib/agents-cli.js +110 -0
- package/lib/agy/diagnostics.d.ts +29 -0
- package/lib/agy/diagnostics.js +109 -0
- package/lib/agy/errors.d.ts +20 -0
- package/lib/agy/errors.js +77 -0
- package/lib/agy/experimental-transport.d.ts +79 -0
- package/lib/agy/experimental-transport.js +612 -0
- package/lib/agy/keepalive.d.ts +140 -0
- package/lib/agy/keepalive.js +424 -0
- package/lib/agy/limiter.d.ts +32 -0
- package/lib/agy/limiter.js +111 -0
- package/lib/agy/log.d.ts +214 -0
- package/lib/agy/log.js +503 -0
- package/lib/agy/models.d.ts +49 -0
- package/lib/agy/models.js +203 -0
- package/lib/agy/overrides.d.ts +17 -0
- package/lib/agy/overrides.js +73 -0
- package/lib/agy/parser.d.ts +102 -0
- package/lib/agy/parser.js +492 -0
- package/lib/agy/persistent-transport.d.ts +101 -0
- package/lib/agy/persistent-transport.js +753 -0
- package/lib/agy/process.d.ts +144 -0
- package/lib/agy/process.js +452 -0
- package/lib/agy/redact.d.ts +3 -0
- package/lib/agy/redact.js +24 -0
- package/lib/agy/stream-protocol.d.ts +50 -0
- package/lib/agy/stream-protocol.js +156 -0
- package/lib/agy/windows-launcher.d.ts +21 -0
- package/lib/agy/windows-launcher.js +76 -0
- package/lib/diagnostics.d.ts +78 -0
- package/lib/diagnostics.js +162 -0
- package/lib/doctor.d.ts +138 -0
- package/lib/doctor.js +923 -0
- package/lib/dsh/context.d.ts +133 -0
- package/lib/dsh/context.js +352 -0
- package/lib/dsh-home.d.ts +6 -0
- package/lib/dsh-home.js +11 -0
- package/lib/index.d.ts +43 -0
- package/lib/index.js +256 -0
- package/lib/mcp/agy-registration.d.ts +70 -0
- package/lib/mcp/agy-registration.js +245 -0
- package/lib/mcp/bridge.d.ts +73 -0
- package/lib/mcp/bridge.js +295 -0
- package/lib/mcp/endpoint.d.ts +41 -0
- package/lib/mcp/endpoint.js +142 -0
- package/lib/mcp/protocol.d.ts +107 -0
- package/lib/mcp/protocol.js +197 -0
- package/lib/mcp/tool-projection.d.ts +64 -0
- package/lib/mcp/tool-projection.js +168 -0
- package/lib/provider/agy.d.ts +153 -0
- package/lib/provider/agy.js +2159 -0
- package/lib/provider/config.d.ts +226 -0
- package/lib/provider/config.js +294 -0
- package/lib/provider/error-codes.d.ts +22 -0
- package/lib/provider/error-codes.js +29 -0
- package/lib/provider/image-bridge.d.ts +60 -0
- package/lib/provider/image-bridge.js +290 -0
- package/lib/provider/mock.d.ts +15 -0
- package/lib/provider/mock.js +78 -0
- package/lib/provider/prompt-budget.d.ts +45 -0
- package/lib/provider/prompt-budget.js +596 -0
- package/lib/provider/serialize.d.ts +15 -0
- package/lib/provider/serialize.js +82 -0
- package/lib/provider/tool-protocol.d.ts +80 -0
- package/lib/provider/tool-protocol.js +848 -0
- package/lib/provider/tool-schema-file.d.ts +11 -0
- package/lib/provider/tool-schema-file.js +27 -0
- package/lib/session/file-store.d.ts +56 -0
- package/lib/session/file-store.js +186 -0
- package/lib/session/store.d.ts +49 -0
- package/lib/session/store.js +62 -0
- package/lib/web/router.d.ts +19 -0
- package/lib/web/router.js +906 -0
- package/package.json +112 -4
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
import { resolveAgyExecutable, runProcess } from './process.js';
|
|
2
|
+
import { normalizeModelId } from '../provider/config.js';
|
|
3
|
+
import { MODEL_DISCOVERY_EMPTY_CODE, MODEL_DISCOVERY_FAILED_CODE, MODEL_DISCOVERY_OUTPUT_LIMIT_CODE, MODEL_DISCOVERY_TIMEOUT_CODE, } from '../provider/error-codes.js';
|
|
4
|
+
export const DEFAULT_MODEL_DISCOVERY_TTL_MS = 5 * 60_000;
|
|
5
|
+
export const DEFAULT_MODEL_DISCOVERY_TIMEOUT_MS = 10_000;
|
|
6
|
+
export const MAX_MODEL_DISCOVERY_OUTPUT_BYTES = 1 * 1024 * 1024;
|
|
7
|
+
const MODEL_ID_PATTERN = /^[A-Za-z0-9][A-Za-z0-9._:+@/-]{0,255}$/;
|
|
8
|
+
const MAX_MODEL_DISPLAY_LENGTH = 512;
|
|
9
|
+
class ModelDiscoveryFailure extends Error {
|
|
10
|
+
code;
|
|
11
|
+
constructor(message, code) {
|
|
12
|
+
super(message);
|
|
13
|
+
this.code = code;
|
|
14
|
+
this.name = 'ModelDiscoveryFailure';
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
function isSuccessful(result) {
|
|
18
|
+
return result.termination === 'completed' && result.exitCode === 0;
|
|
19
|
+
}
|
|
20
|
+
function warningOf(error) {
|
|
21
|
+
if (error instanceof ModelDiscoveryFailure)
|
|
22
|
+
return { message: error.message, code: error.code };
|
|
23
|
+
return { message: 'AGY model discovery failed', code: MODEL_DISCOVERY_FAILED_CODE };
|
|
24
|
+
}
|
|
25
|
+
function metadataValue(preferred, fallback, key) {
|
|
26
|
+
const preferredValue = preferred[key];
|
|
27
|
+
if (preferredValue !== undefined)
|
|
28
|
+
return preferredValue;
|
|
29
|
+
return fallback?.[key];
|
|
30
|
+
}
|
|
31
|
+
/** Merge explicit configuration first, then add AGY-discovered models. Normalizes base ids and dedupes. */
|
|
32
|
+
export function mergeModelCatalog(configured, discovered) {
|
|
33
|
+
const normalizedDiscovered = discovered.map(m => ({ ...m, id: normalizeModelId(m.id) }));
|
|
34
|
+
const discoveredById = new Map(normalizedDiscovered.map(model => [model.id.toLowerCase(), model]));
|
|
35
|
+
const merged = [];
|
|
36
|
+
const seen = new Set();
|
|
37
|
+
for (const configuredModel of configured) {
|
|
38
|
+
const baseId = normalizeModelId(configuredModel.id);
|
|
39
|
+
const key = baseId.toLowerCase();
|
|
40
|
+
if (seen.has(key))
|
|
41
|
+
continue;
|
|
42
|
+
seen.add(key);
|
|
43
|
+
const discoveredModel = discoveredById.get(baseId.toLowerCase());
|
|
44
|
+
const model = { id: baseId };
|
|
45
|
+
const name = metadataValue(configuredModel, discoveredModel, 'name');
|
|
46
|
+
const description = metadataValue(configuredModel, discoveredModel, 'description');
|
|
47
|
+
const contextWindow = metadataValue(configuredModel, discoveredModel, 'contextWindow');
|
|
48
|
+
if (name !== undefined)
|
|
49
|
+
model.name = name;
|
|
50
|
+
if (description !== undefined)
|
|
51
|
+
model.description = description;
|
|
52
|
+
if (contextWindow !== undefined)
|
|
53
|
+
model.contextWindow = contextWindow;
|
|
54
|
+
merged.push(model);
|
|
55
|
+
}
|
|
56
|
+
for (const discoveredModel of normalizedDiscovered) {
|
|
57
|
+
const key = discoveredModel.id.toLowerCase();
|
|
58
|
+
if (seen.has(key))
|
|
59
|
+
continue;
|
|
60
|
+
seen.add(key);
|
|
61
|
+
merged.push({ ...discoveredModel });
|
|
62
|
+
}
|
|
63
|
+
return merged;
|
|
64
|
+
}
|
|
65
|
+
/** @deprecated Use normalizeModelId/extractModelEffort for effort-split handling. */
|
|
66
|
+
export const MODEL_EFFORT_SUFFIX_RE = /-(?:low|medium|high)$/i;
|
|
67
|
+
/** Parse the tab-separated, non-interactive output of `agy models`. Normalizes -high/-medium/-low suffix to base id and dedupes base. */
|
|
68
|
+
export function parseAgyModels(output) {
|
|
69
|
+
const models = [];
|
|
70
|
+
const seen = new Set();
|
|
71
|
+
const baseSeen = new Set();
|
|
72
|
+
for (const rawLine of output.split(/\r?\n/)) {
|
|
73
|
+
const line = rawLine.trim();
|
|
74
|
+
if (line.length === 0)
|
|
75
|
+
continue;
|
|
76
|
+
const fields = line.split(/\t+/);
|
|
77
|
+
const id = fields.shift()?.trim() ?? '';
|
|
78
|
+
const display = fields.join(' ').trim();
|
|
79
|
+
if (!MODEL_ID_PATTERN.test(id) || seen.has(id))
|
|
80
|
+
continue;
|
|
81
|
+
const baseId = normalizeModelId(id);
|
|
82
|
+
if (baseSeen.has(baseId.toLowerCase()))
|
|
83
|
+
continue;
|
|
84
|
+
// Header rows: "ID\tDisplay Name" and any case/column-naming variant of it
|
|
85
|
+
// must not become a phantom catalog entry. A real model id carries a dot
|
|
86
|
+
// or a digit-bearing version segment; a header word like MODEL does not.
|
|
87
|
+
const headerRow = /display|name/i.test(display)
|
|
88
|
+
&& (id.toLowerCase() === 'id' || !/[.\d]/.test(id));
|
|
89
|
+
if (headerRow)
|
|
90
|
+
continue;
|
|
91
|
+
if (display.length > MAX_MODEL_DISPLAY_LENGTH || /[\u0000-\u001f\u007f]/.test(display))
|
|
92
|
+
continue;
|
|
93
|
+
seen.add(id);
|
|
94
|
+
baseSeen.add(baseId.toLowerCase());
|
|
95
|
+
// Preserve display but normalize id to base for DSH reasoningEffort split
|
|
96
|
+
// Handle displays like "Gemini 3.1 Pro (High)" or "Gemini 3.7 Flash - High"
|
|
97
|
+
const strippedDisplay = display
|
|
98
|
+
.replace(/\s*[\(\[]\s*(?:low|medium|high)\s*[\)\]]\s*$/i, '')
|
|
99
|
+
.replace(/(?:\s+|-)(?:low|medium|high)\s*$/i, '')
|
|
100
|
+
.trim();
|
|
101
|
+
const normalized = display.length === 0 ? { id: baseId } : { id: baseId, name: strippedDisplay.length === 0 ? baseId : strippedDisplay };
|
|
102
|
+
models.push(normalized);
|
|
103
|
+
}
|
|
104
|
+
return models;
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Discover AGY models without invoking a model request. Results are kept in
|
|
108
|
+
* memory only. A refresh is single-flight and all failures fail open to the
|
|
109
|
+
* last successful catalog or the caller's static catalog.
|
|
110
|
+
*/
|
|
111
|
+
export class AgyModelDiscovery {
|
|
112
|
+
executable;
|
|
113
|
+
ttlMs;
|
|
114
|
+
timeoutMs;
|
|
115
|
+
maxOutputBytes;
|
|
116
|
+
runCommand;
|
|
117
|
+
now;
|
|
118
|
+
cache;
|
|
119
|
+
inFlight;
|
|
120
|
+
constructor(options = {}) {
|
|
121
|
+
this.executable = options.executable?.trim() === '' ? undefined : options.executable?.trim();
|
|
122
|
+
this.ttlMs = options.ttlMs ?? DEFAULT_MODEL_DISCOVERY_TTL_MS;
|
|
123
|
+
this.timeoutMs = options.timeoutMs ?? DEFAULT_MODEL_DISCOVERY_TIMEOUT_MS;
|
|
124
|
+
this.maxOutputBytes = Math.min(options.maxOutputBytes ?? MAX_MODEL_DISCOVERY_OUTPUT_BYTES, MAX_MODEL_DISCOVERY_OUTPUT_BYTES);
|
|
125
|
+
this.runCommand = options.runCommand ?? runProcess;
|
|
126
|
+
this.now = options.now ?? Date.now;
|
|
127
|
+
}
|
|
128
|
+
async discover(configured) {
|
|
129
|
+
const currentTime = this.now();
|
|
130
|
+
if (this.cache !== undefined && this.cache.expiresAt > currentTime) {
|
|
131
|
+
return { models: this.cache.models, source: 'cache', stale: false };
|
|
132
|
+
}
|
|
133
|
+
if (this.inFlight !== undefined)
|
|
134
|
+
return this.inFlight;
|
|
135
|
+
const refresh = this.refresh(configured);
|
|
136
|
+
this.inFlight = refresh;
|
|
137
|
+
try {
|
|
138
|
+
return await refresh;
|
|
139
|
+
}
|
|
140
|
+
finally {
|
|
141
|
+
if (this.inFlight === refresh)
|
|
142
|
+
this.inFlight = undefined;
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
async refresh(configured) {
|
|
146
|
+
try {
|
|
147
|
+
const request = {
|
|
148
|
+
executable: resolveAgyExecutable(this.executable),
|
|
149
|
+
args: ['models'],
|
|
150
|
+
timeoutMs: this.timeoutMs,
|
|
151
|
+
maxStdoutBytes: this.maxOutputBytes,
|
|
152
|
+
maxStderrBytes: this.maxOutputBytes,
|
|
153
|
+
windowsNoConsole: true,
|
|
154
|
+
};
|
|
155
|
+
const result = await this.runCommand(request);
|
|
156
|
+
if (!isSuccessful(result)) {
|
|
157
|
+
const code = result.termination === 'timeout'
|
|
158
|
+
? MODEL_DISCOVERY_TIMEOUT_CODE
|
|
159
|
+
: result.termination === 'output-limit'
|
|
160
|
+
? MODEL_DISCOVERY_OUTPUT_LIMIT_CODE
|
|
161
|
+
: MODEL_DISCOVERY_FAILED_CODE;
|
|
162
|
+
throw new ModelDiscoveryFailure(code === MODEL_DISCOVERY_TIMEOUT_CODE
|
|
163
|
+
? 'AGY model discovery command timed out'
|
|
164
|
+
: code === MODEL_DISCOVERY_OUTPUT_LIMIT_CODE
|
|
165
|
+
? 'AGY model discovery output exceeded its limit'
|
|
166
|
+
: 'AGY model discovery command failed', code);
|
|
167
|
+
}
|
|
168
|
+
const discovered = parseAgyModels(result.stdoutLines.join('\n'));
|
|
169
|
+
if (discovered.length === 0)
|
|
170
|
+
throw new ModelDiscoveryFailure('AGY model discovery returned no usable models', MODEL_DISCOVERY_EMPTY_CODE);
|
|
171
|
+
const models = mergeModelCatalog(configured, discovered);
|
|
172
|
+
this.cache = {
|
|
173
|
+
models,
|
|
174
|
+
expiresAt: this.now() + this.ttlMs,
|
|
175
|
+
};
|
|
176
|
+
return {
|
|
177
|
+
models,
|
|
178
|
+
source: configured.length === 0 ? 'discovered' : 'merged',
|
|
179
|
+
stale: false,
|
|
180
|
+
};
|
|
181
|
+
}
|
|
182
|
+
catch (error) {
|
|
183
|
+
const warning = warningOf(error);
|
|
184
|
+
if (this.cache !== undefined) {
|
|
185
|
+
return {
|
|
186
|
+
models: this.cache.models,
|
|
187
|
+
source: 'cache',
|
|
188
|
+
stale: true,
|
|
189
|
+
warning: warning.message,
|
|
190
|
+
warningCode: warning.code,
|
|
191
|
+
};
|
|
192
|
+
}
|
|
193
|
+
return {
|
|
194
|
+
models: configured,
|
|
195
|
+
source: 'fallback',
|
|
196
|
+
stale: true,
|
|
197
|
+
warning: warning.message,
|
|
198
|
+
warningCode: warning.code,
|
|
199
|
+
};
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
//# sourceMappingURL=models.js.map
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { type AgyReasoningEffort } from './process.js';
|
|
2
|
+
export interface AgyRuntimeOverrides {
|
|
3
|
+
hiddenModels: string[];
|
|
4
|
+
defaultEffort?: AgyReasoningEffort;
|
|
5
|
+
defaultModel?: string;
|
|
6
|
+
}
|
|
7
|
+
export declare function readAgyRuntimeOverrides(): AgyRuntimeOverrides | undefined;
|
|
8
|
+
export declare function saveAgyRuntimeOverrides(updates: {
|
|
9
|
+
hiddenModels?: string[];
|
|
10
|
+
defaultEffort?: string;
|
|
11
|
+
defaultModel?: string;
|
|
12
|
+
}): void;
|
|
13
|
+
export declare function agyRuntimeOverridesPath(): string;
|
|
14
|
+
/** Test-only: point the reader/writer at an alternate file. */
|
|
15
|
+
export declare function __setAgyOverridesPathForTest(path: string | undefined): void;
|
|
16
|
+
export declare function agyRuntimeOverridesMtimeMs(): number | undefined;
|
|
17
|
+
//# sourceMappingURL=overrides.d.ts.map
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { existsSync, mkdirSync, readFileSync, statSync, writeFileSync } from 'node:fs';
|
|
2
|
+
import { dirname, join } from 'node:path';
|
|
3
|
+
import { dshHome } from '../dsh-home.js';
|
|
4
|
+
import { isAgyReasoningEffort } from './process.js';
|
|
5
|
+
const RUNTIME_OVERRIDES_PATH = join(dshHome(), 'agy-cli', 'runtime-overrides.json');
|
|
6
|
+
// Indirection so tests (and the panel, if it ever runs in-process) can point the
|
|
7
|
+
// reader at a different location without touching the user's real file.
|
|
8
|
+
let _overridesPathOverride;
|
|
9
|
+
// The panel and the generation path are two processes that must agree on the
|
|
10
|
+
// default effort, so both read this one file (the panel writes it, see
|
|
11
|
+
// src/web/router.ts). If the file is absent or unreadable the caller falls back
|
|
12
|
+
// to its built-in default.
|
|
13
|
+
export function readAgyRuntimeOverrides() {
|
|
14
|
+
const p = _overridesPathOverride ?? RUNTIME_OVERRIDES_PATH;
|
|
15
|
+
if (!existsSync(p))
|
|
16
|
+
return undefined;
|
|
17
|
+
let data;
|
|
18
|
+
try {
|
|
19
|
+
data = JSON.parse(readFileSync(p, 'utf8'));
|
|
20
|
+
}
|
|
21
|
+
catch {
|
|
22
|
+
return undefined;
|
|
23
|
+
}
|
|
24
|
+
const record = data;
|
|
25
|
+
if (record === null || typeof record !== 'object')
|
|
26
|
+
return undefined;
|
|
27
|
+
const hiddenModels = Array.isArray(record.hiddenModels)
|
|
28
|
+
? record.hiddenModels.filter((value) => typeof value === 'string')
|
|
29
|
+
: [];
|
|
30
|
+
const parsed = { hiddenModels };
|
|
31
|
+
if (isAgyReasoningEffort(record.defaultEffort))
|
|
32
|
+
parsed.defaultEffort = record.defaultEffort;
|
|
33
|
+
if (typeof record.defaultModel === 'string' && record.defaultModel !== '')
|
|
34
|
+
parsed.defaultModel = record.defaultModel;
|
|
35
|
+
return parsed;
|
|
36
|
+
}
|
|
37
|
+
// Write half of the same file. Preserves the keys the caller did not touch
|
|
38
|
+
// (the panel updates one field at a time; a plain overwrite would wipe
|
|
39
|
+
// sibling keys) and atomically-ish replaces the whole file so a reader never
|
|
40
|
+
// sees a half-written document. Effort is re-validated on write because the
|
|
41
|
+
// panel posts a raw string; an unknown value must not persist.
|
|
42
|
+
export function saveAgyRuntimeOverrides(updates) {
|
|
43
|
+
const p = _overridesPathOverride ?? RUNTIME_OVERRIDES_PATH;
|
|
44
|
+
const current = readAgyRuntimeOverrides() ?? { hiddenModels: [] };
|
|
45
|
+
const merged = { ...current };
|
|
46
|
+
if (updates.hiddenModels !== undefined)
|
|
47
|
+
merged.hiddenModels = updates.hiddenModels.filter((value) => typeof value === 'string');
|
|
48
|
+
if (updates.defaultEffort !== undefined) {
|
|
49
|
+
if (isAgyReasoningEffort(updates.defaultEffort))
|
|
50
|
+
merged.defaultEffort = updates.defaultEffort;
|
|
51
|
+
}
|
|
52
|
+
if (updates.defaultModel !== undefined)
|
|
53
|
+
merged.defaultModel = updates.defaultModel;
|
|
54
|
+
const dir = dirname(p);
|
|
55
|
+
mkdirSync(dir, { recursive: true });
|
|
56
|
+
writeFileSync(p, JSON.stringify(merged, null, 2) + '\n', 'utf8');
|
|
57
|
+
}
|
|
58
|
+
export function agyRuntimeOverridesPath() {
|
|
59
|
+
return _overridesPathOverride ?? RUNTIME_OVERRIDES_PATH;
|
|
60
|
+
}
|
|
61
|
+
/** Test-only: point the reader/writer at an alternate file. */
|
|
62
|
+
export function __setAgyOverridesPathForTest(path) {
|
|
63
|
+
_overridesPathOverride = path;
|
|
64
|
+
}
|
|
65
|
+
export function agyRuntimeOverridesMtimeMs() {
|
|
66
|
+
try {
|
|
67
|
+
return statSync(RUNTIME_OVERRIDES_PATH).mtimeMs;
|
|
68
|
+
}
|
|
69
|
+
catch {
|
|
70
|
+
return undefined;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
//# sourceMappingURL=overrides.js.map
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
export interface AgyJsonEvent {
|
|
2
|
+
event: string;
|
|
3
|
+
[key: string]: unknown;
|
|
4
|
+
}
|
|
5
|
+
export type AgyParserErrorCode = 'INVALID_JSON_LINE' | 'INVALID_EVENT' | 'LINE_TOO_LONG';
|
|
6
|
+
export declare const DEFAULT_MAX_LINE_LENGTH = 1048576;
|
|
7
|
+
export interface AgyParserOptions {
|
|
8
|
+
/** Maximum UTF-16 code units accepted for one NDJSON line. */
|
|
9
|
+
maxLineLength?: number;
|
|
10
|
+
}
|
|
11
|
+
export declare class AgyParserError extends Error {
|
|
12
|
+
readonly code: AgyParserErrorCode;
|
|
13
|
+
readonly lineNumber: number;
|
|
14
|
+
readonly rawLine: string;
|
|
15
|
+
constructor(message: string, code: AgyParserErrorCode, lineNumber: number, rawLine: string, options?: ErrorOptions);
|
|
16
|
+
}
|
|
17
|
+
export type AgyEventCategory = 'init' | 'step_update' | 'checkpoint' | 'agent_response' | 'result' | 'tool' | 'permission' | 'error' | 'unknown';
|
|
18
|
+
export type AgyEventCategoryCounts = Record<AgyEventCategory, number>;
|
|
19
|
+
export type AgyToolEventKind = 'event-tool-call' | 'event-tool-result' | 'step-type-tool' | 'explicit-tool-name';
|
|
20
|
+
export type AgyToolEventCarrierShape = 'not-send-message' | 'missing-recipient' | 'missing-message' | 'unreadable-recipient' | 'unreadable-message' | 'complete';
|
|
21
|
+
export type AgyToolEventRecipientClass = 'not-applicable' | 'missing' | 'default-api' | 'dsh-recipient' | 'self-conversation' | 'other-conversation' | 'other';
|
|
22
|
+
/** Safe structural metadata for diagnosing AGY tool events without logging payload values. */
|
|
23
|
+
export interface AgyToolEventDiagnostic {
|
|
24
|
+
readonly eventName: string;
|
|
25
|
+
readonly kind: AgyToolEventKind;
|
|
26
|
+
readonly stepType?: string;
|
|
27
|
+
readonly toolName?: string;
|
|
28
|
+
readonly carrierShape: AgyToolEventCarrierShape;
|
|
29
|
+
readonly recipientClass: AgyToolEventRecipientClass;
|
|
30
|
+
readonly topLevelKeys: readonly string[];
|
|
31
|
+
readonly stepKeys: readonly string[];
|
|
32
|
+
readonly toolInputKeys: readonly string[];
|
|
33
|
+
}
|
|
34
|
+
export declare function isDshCarrierRecipient(value: string): boolean;
|
|
35
|
+
export declare function isAgyToolEventKind(value: unknown): value is AgyToolEventKind;
|
|
36
|
+
export declare function emptyAgyEventCategoryCounts(): AgyEventCategoryCounts;
|
|
37
|
+
/** Parse one complete NDJSON line and require only the stable event envelope. */
|
|
38
|
+
export declare function parseAgyJsonLine(rawLine: string, lineNumber?: number, maxLineLength?: number): AgyJsonEvent;
|
|
39
|
+
/** Incremental parser for arbitrary stdout chunks, including CRLF streams. */
|
|
40
|
+
export declare class AgyStreamParser {
|
|
41
|
+
private buffer;
|
|
42
|
+
private lineNumber;
|
|
43
|
+
private readonly maxLineLength;
|
|
44
|
+
constructor(options?: AgyParserOptions);
|
|
45
|
+
push(chunk: string): AgyJsonEvent[];
|
|
46
|
+
end(): AgyJsonEvent[];
|
|
47
|
+
private parseLine;
|
|
48
|
+
}
|
|
49
|
+
/** Parse an async sequence of stdout chunks without buffering the full stream. */
|
|
50
|
+
export declare function parseAgyChunks(chunks: AsyncIterable<string>): AsyncIterable<AgyJsonEvent>;
|
|
51
|
+
/** Extract the AGY conversation identity emitted by an init event. */
|
|
52
|
+
export declare function conversationIdOf(event: AgyJsonEvent): string | undefined;
|
|
53
|
+
/** Return AGY's step type without constraining future event payloads. */
|
|
54
|
+
export declare function stepTypeOf(event: AgyJsonEvent): string | undefined;
|
|
55
|
+
/** Extract an explicit AGY tool name from a step update, when present. */
|
|
56
|
+
export declare function toolNameOf(event: AgyJsonEvent): string | undefined;
|
|
57
|
+
export interface AgySendMessagePayload {
|
|
58
|
+
readonly recipient: string;
|
|
59
|
+
readonly message: string;
|
|
60
|
+
}
|
|
61
|
+
/** Extract the narrowly-scoped AGY send_message carrier used by DSH-owned mode. */
|
|
62
|
+
export declare function sendMessageOf(event: AgyJsonEvent): AgySendMessagePayload | undefined;
|
|
63
|
+
/** Classify only explicit AGY tool lifecycle signals. */
|
|
64
|
+
export declare function toolEventKindOf(event: AgyJsonEvent): AgyToolEventKind | undefined;
|
|
65
|
+
/** Recognize internal AGY tool lifecycle events without mapping them to DSH tools. */
|
|
66
|
+
export declare function isToolEvent(event: AgyJsonEvent): boolean;
|
|
67
|
+
/** Classify a tool event's carrier shape without retaining any payload values. */
|
|
68
|
+
export declare function toolEventDiagnosticOf(event: AgyJsonEvent, activeConversationId?: string): AgyToolEventDiagnostic | undefined;
|
|
69
|
+
/** Recognize permission checkpoints that cannot be answered by a headless Provider. */
|
|
70
|
+
export declare function isPermissionEvent(event: AgyJsonEvent): boolean;
|
|
71
|
+
/**
|
|
72
|
+
* Classify only stable event categories; unknown event names remain forward-compatible.
|
|
73
|
+
*
|
|
74
|
+
* A step_update carries its own step_type, so a nested `agent_response` update is
|
|
75
|
+
* counted as `agent_response` rather than being swallowed by the outer `step_update`
|
|
76
|
+
* case. Counts must reflect what the model actually emitted: reading `agent_response`
|
|
77
|
+
* as `step_update` made telemetry report zero streamed text on every turn, even
|
|
78
|
+
* though AGY streams text deltas natively.
|
|
79
|
+
*/
|
|
80
|
+
export declare function eventCategoryOf(event: AgyJsonEvent): AgyEventCategory;
|
|
81
|
+
/**
|
|
82
|
+
* Bounded JSON of AGY's own `result` frame.
|
|
83
|
+
*
|
|
84
|
+
* `status: "ERROR"` is the only signal the adapter gets on the long-context
|
|
85
|
+
* failures this provider sees, and AGY omits `error` on those frames, so the
|
|
86
|
+
* `response` text and the remaining keys are the sole surviving diagnosis.
|
|
87
|
+
* Keys that carry bulk are truncated rather than dropped: a missing key and a
|
|
88
|
+
* truncated key look identical in telemetry and would be indistinguishable from
|
|
89
|
+
* "AGY said nothing".
|
|
90
|
+
*/
|
|
91
|
+
export declare function finalResultRawOf(event: AgyJsonEvent): string | undefined;
|
|
92
|
+
/** Extract bounded classification detail from AGY error events without exposing the payload. */
|
|
93
|
+
export declare function errorDetailOf(event: AgyJsonEvent): string | undefined;
|
|
94
|
+
/** Extract a text delta from the observed AGY step_update envelope. */
|
|
95
|
+
export declare function textDeltaOf(event: AgyJsonEvent): string | undefined;
|
|
96
|
+
/** Extract the final response text from a result event. */
|
|
97
|
+
export declare function responseOf(event: AgyJsonEvent): string | undefined;
|
|
98
|
+
/** Extract the final AGY result status without constraining future statuses. */
|
|
99
|
+
export declare function statusOf(event: AgyJsonEvent): string | undefined;
|
|
100
|
+
/** Extract usage as an opaque object; AGY may add fields across versions. */
|
|
101
|
+
export declare function usageOf(event: AgyJsonEvent): Record<string, unknown> | undefined;
|
|
102
|
+
//# sourceMappingURL=parser.d.ts.map
|