dsh-agy-cli 0.12.3 → 0.12.4
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/README.md +1 -1
- package/bin/win32-x64/agy-launcher.exe +0 -0
- package/bin/win32-x64/agy-launcher.old.161676.exe +0 -0
- package/lib/agy/experimental-transport.js +12 -4
- package/lib/agy/keepalive.js +41 -40
- package/lib/agy/persistent-transport.js +12 -8
- package/lib/provider/agy.js +4 -4
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
|
|
31
31
|
- **双工具路线**:MCP 桥把 DSH 工具交给 AGY(真工具事件、过程流可视化,推荐),失败自动降级为 prompt 契约
|
|
32
32
|
- **DSH 主导 harness**:工作区、审批、沙箱、上下文预算全在 DSH;AGY 只出模型
|
|
33
|
-
- **流式 + 状态机**:`stdinMode: hold`
|
|
33
|
+
- **流式 + 状态机**:`stdinMode: hold` 防回滚、工具步骤折叠显示(只列执行了哪些工具,不显示模型的内部思考内容)、尾流交付、断连保文本
|
|
34
34
|
- **会话管理 + 历史指纹链**:resume / full 双模式,每轮成功后记录 DSH 历史指纹;resume 前本地比对前缀,检出历史被编辑/压缩/截断即废弃旧会话并从完整历史重建,delta prompt 不会落在过期上下文上;死亡会话自动重放,会话映射落盘可迁移
|
|
35
35
|
- **图片输入**(experimental):附件经图片桥落盘,由最小权限的 view_file Agent 查看
|
|
36
36
|
- **配额面板与凭据保活**:loopback-only;面板显示真实双窗口配额,令牌临近过期时自动拉起官方 CLI 续期
|
|
Binary file
|
|
Binary file
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { spawn } from 'node:child_process';
|
|
2
|
+
import { buildWindowsNoConsoleLaunch } from './windows-launcher.js';
|
|
2
3
|
import { randomUUID } from 'node:crypto';
|
|
3
4
|
export class PersistentTransportError extends Error {
|
|
4
5
|
code;
|
|
@@ -200,8 +201,9 @@ class PersistentAgyWorker {
|
|
|
200
201
|
await this.stop('reset');
|
|
201
202
|
throw new PersistentTransportError('Persistent AGY request aborted before write', 'ABORTED');
|
|
202
203
|
}
|
|
203
|
-
const timeoutMs = input.timeoutMs
|
|
204
|
-
|
|
204
|
+
const timeoutMs = input.timeoutMs !== undefined
|
|
205
|
+
? validateInteger('timeoutMs', input.timeoutMs, 1, 3_600_000)
|
|
206
|
+
: undefined;
|
|
205
207
|
const maxOutputBytes = Math.min(input.maxOutputBytes ?? this.options.maxOutputBytes, this.options.maxOutputBytes);
|
|
206
208
|
validateInteger('maxOutputBytes', maxOutputBytes, 1, this.options.maxOutputBytes);
|
|
207
209
|
this.clearIdleTimer();
|
|
@@ -225,7 +227,9 @@ class PersistentAgyWorker {
|
|
|
225
227
|
this.active = active;
|
|
226
228
|
active.abortListener = () => this.failActiveAndReset(new PersistentTransportError('Persistent AGY request aborted', 'ABORTED'));
|
|
227
229
|
input.signal?.addEventListener('abort', active.abortListener, { once: true });
|
|
228
|
-
|
|
230
|
+
if (timeoutMs !== undefined) {
|
|
231
|
+
active.timer = setTimeout(() => this.failActiveAndReset(new PersistentTransportError('Persistent AGY request exceeded its timeout', 'TIMEOUT')), timeoutMs);
|
|
232
|
+
}
|
|
229
233
|
void this.sendRequest(active, input.payload);
|
|
230
234
|
});
|
|
231
235
|
}
|
|
@@ -279,7 +283,11 @@ class PersistentAgyWorker {
|
|
|
279
283
|
this.readyReject = reject;
|
|
280
284
|
});
|
|
281
285
|
try {
|
|
282
|
-
const
|
|
286
|
+
const args = [...this.options.args];
|
|
287
|
+
const launch = process.platform === 'win32'
|
|
288
|
+
? buildWindowsNoConsoleLaunch(this.options.executable, args)
|
|
289
|
+
: { executable: this.options.executable, args };
|
|
290
|
+
const child = spawn(launch.executable, [...launch.args], {
|
|
283
291
|
cwd: this.options.cwd,
|
|
284
292
|
env: {
|
|
285
293
|
...process.env,
|
package/lib/agy/keepalive.js
CHANGED
|
@@ -56,46 +56,46 @@ export const AGY_KEYRING_TARGET = 'gemini:antigravity';
|
|
|
56
56
|
* 2026-10-22. Duplicated rather than imported so the keep-alive path has no
|
|
57
57
|
* dependency on the HTTP layer.
|
|
58
58
|
*/
|
|
59
|
-
const WIN_CRED_SCRIPT = `
|
|
60
|
-
param($target)
|
|
61
|
-
$sig = @'
|
|
62
|
-
using System;
|
|
63
|
-
using System.Runtime.InteropServices;
|
|
64
|
-
public class WinCredKeepalive {
|
|
65
|
-
[DllImport("advapi32.dll", SetLastError=true, CharSet=CharSet.Unicode)]
|
|
66
|
-
public static extern bool CredRead(string target, int type, int flags, out IntPtr credential);
|
|
67
|
-
[DllImport("advapi32.dll", SetLastError=true)]
|
|
68
|
-
public static extern void CredFree(IntPtr cred);
|
|
69
|
-
[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)]
|
|
70
|
-
public struct CREDENTIAL {
|
|
71
|
-
public int Flags;
|
|
72
|
-
public int Type;
|
|
73
|
-
public string TargetName;
|
|
74
|
-
public string Comment;
|
|
75
|
-
public long LastWritten;
|
|
76
|
-
public int CredentialBlobSize;
|
|
77
|
-
public IntPtr CredentialBlob;
|
|
78
|
-
public int Persist;
|
|
79
|
-
public int AttributeCount;
|
|
80
|
-
public IntPtr Attributes;
|
|
81
|
-
public string TargetAlias;
|
|
82
|
-
public string UserName;
|
|
83
|
-
}
|
|
84
|
-
public static string Read(string target) {
|
|
85
|
-
IntPtr ptr;
|
|
86
|
-
if (CredRead(target, 1, 0, out ptr)) {
|
|
87
|
-
CREDENTIAL c = (CREDENTIAL)Marshal.PtrToStructure(ptr, typeof(CREDENTIAL));
|
|
88
|
-
byte[] b = new byte[c.CredentialBlobSize];
|
|
89
|
-
Marshal.Copy(c.CredentialBlob, b, 0, c.CredentialBlobSize);
|
|
90
|
-
CredFree(ptr);
|
|
91
|
-
return System.Convert.ToBase64String(b);
|
|
92
|
-
}
|
|
93
|
-
return null;
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
'@
|
|
97
|
-
Add-Type -TypeDefinition $sig -ErrorAction SilentlyContinue
|
|
98
|
-
[Console]::Out.Write([WinCredKeepalive]::Read($target))
|
|
59
|
+
const WIN_CRED_SCRIPT = `
|
|
60
|
+
param($target)
|
|
61
|
+
$sig = @'
|
|
62
|
+
using System;
|
|
63
|
+
using System.Runtime.InteropServices;
|
|
64
|
+
public class WinCredKeepalive {
|
|
65
|
+
[DllImport("advapi32.dll", SetLastError=true, CharSet=CharSet.Unicode)]
|
|
66
|
+
public static extern bool CredRead(string target, int type, int flags, out IntPtr credential);
|
|
67
|
+
[DllImport("advapi32.dll", SetLastError=true)]
|
|
68
|
+
public static extern void CredFree(IntPtr cred);
|
|
69
|
+
[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)]
|
|
70
|
+
public struct CREDENTIAL {
|
|
71
|
+
public int Flags;
|
|
72
|
+
public int Type;
|
|
73
|
+
public string TargetName;
|
|
74
|
+
public string Comment;
|
|
75
|
+
public long LastWritten;
|
|
76
|
+
public int CredentialBlobSize;
|
|
77
|
+
public IntPtr CredentialBlob;
|
|
78
|
+
public int Persist;
|
|
79
|
+
public int AttributeCount;
|
|
80
|
+
public IntPtr Attributes;
|
|
81
|
+
public string TargetAlias;
|
|
82
|
+
public string UserName;
|
|
83
|
+
}
|
|
84
|
+
public static string Read(string target) {
|
|
85
|
+
IntPtr ptr;
|
|
86
|
+
if (CredRead(target, 1, 0, out ptr)) {
|
|
87
|
+
CREDENTIAL c = (CREDENTIAL)Marshal.PtrToStructure(ptr, typeof(CREDENTIAL));
|
|
88
|
+
byte[] b = new byte[c.CredentialBlobSize];
|
|
89
|
+
Marshal.Copy(c.CredentialBlob, b, 0, c.CredentialBlobSize);
|
|
90
|
+
CredFree(ptr);
|
|
91
|
+
return System.Convert.ToBase64String(b);
|
|
92
|
+
}
|
|
93
|
+
return null;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
'@
|
|
97
|
+
Add-Type -TypeDefinition $sig -ErrorAction SilentlyContinue
|
|
98
|
+
[Console]::Out.Write([WinCredKeepalive]::Read($target))
|
|
99
99
|
`;
|
|
100
100
|
/** macOS/Linux read path: untouched, never part of the Windows hot path. */
|
|
101
101
|
function readKeyringTokenStateSyncImpl() {
|
|
@@ -401,6 +401,7 @@ export async function startAgyKeepaliveRun(input) {
|
|
|
401
401
|
executable: input.executable,
|
|
402
402
|
args: buildKeepaliveArgs(input.model),
|
|
403
403
|
stdinMode: 'close',
|
|
404
|
+
windowsNoConsole: true,
|
|
404
405
|
...(home === undefined ? {} : { cwd: home }),
|
|
405
406
|
timeoutMs: input.timeoutMs ?? 45_000,
|
|
406
407
|
});
|
|
@@ -276,10 +276,12 @@ class PersistentAgyWorker {
|
|
|
276
276
|
await this.stop('reset');
|
|
277
277
|
throw new PersistentTransportError('Persistent AGY request aborted before write', 'ABORTED');
|
|
278
278
|
}
|
|
279
|
-
const timeoutMs = input.timeoutMs
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
279
|
+
const timeoutMs = input.timeoutMs !== undefined
|
|
280
|
+
? validateInteger('timeoutMs', input.timeoutMs, 1, 3_600_000)
|
|
281
|
+
: undefined;
|
|
282
|
+
const idleTimeoutMs = input.idleTimeoutMs !== undefined
|
|
283
|
+
? validateInteger('idleTimeoutMs', input.idleTimeoutMs, 1, 3_600_000)
|
|
284
|
+
: this.options.defaultRequestTimeoutMs;
|
|
283
285
|
const maxOutputBytes = Math.min(input.maxOutputBytes ?? this.options.maxOutputBytes, this.options.maxOutputBytes);
|
|
284
286
|
validateInteger('maxOutputBytes', maxOutputBytes, 1, this.options.maxOutputBytes);
|
|
285
287
|
this.clearIdleTimer();
|
|
@@ -305,10 +307,12 @@ class PersistentAgyWorker {
|
|
|
305
307
|
this.active = active;
|
|
306
308
|
active.abortListener = () => this.failActiveAndReset(new PersistentTransportError('Persistent AGY request aborted', 'ABORTED'));
|
|
307
309
|
input.signal?.addEventListener('abort', active.abortListener, { once: true });
|
|
308
|
-
//
|
|
309
|
-
//
|
|
310
|
-
|
|
311
|
-
|
|
310
|
+
// Idle watchdog is re-armed by every frame so a long thinking or tool pause is not a kill.
|
|
311
|
+
// Wall clock is an optional ceiling only armed when an explicit timeoutMs is requested.
|
|
312
|
+
if (timeoutMs !== undefined) {
|
|
313
|
+
const wallClock = setTimeout(() => this.failActiveAndReset(new PersistentTransportError('Persistent AGY request exceeded its wall-clock timeout', 'TIMEOUT')), timeoutMs);
|
|
314
|
+
active.timer = wallClock;
|
|
315
|
+
}
|
|
312
316
|
this.touchActive(active);
|
|
313
317
|
void this.sendRequest(active, input.text);
|
|
314
318
|
});
|
package/lib/provider/agy.js
CHANGED
|
@@ -914,7 +914,7 @@ export class AgyAdapter extends LlmAdapter {
|
|
|
914
914
|
const envTimeout = process.env.DSH_AGY_TIMEOUT_MS ? Number(process.env.DSH_AGY_TIMEOUT_MS) : undefined;
|
|
915
915
|
this.timeoutMs = envTimeout !== undefined && Number.isFinite(envTimeout) && envTimeout > 0
|
|
916
916
|
? envTimeout
|
|
917
|
-
:
|
|
917
|
+
: undefined;
|
|
918
918
|
const envIdleTimeout = process.env.DSH_AGY_IDLE_TIMEOUT_MS ? Number(process.env.DSH_AGY_IDLE_TIMEOUT_MS) : undefined;
|
|
919
919
|
this.idleTimeoutMs = envIdleTimeout !== undefined && Number.isFinite(envIdleTimeout) && envIdleTimeout > 0
|
|
920
920
|
? envIdleTimeout
|
|
@@ -1048,7 +1048,7 @@ export class AgyAdapter extends LlmAdapter {
|
|
|
1048
1048
|
...(this.agyPath === undefined ? {} : { executable: this.agyPath }),
|
|
1049
1049
|
expectedAgent: this.agent,
|
|
1050
1050
|
minimumVersion: this.minimumAgyVersion,
|
|
1051
|
-
timeoutMs: Math.min(this.timeoutMs, 10_000),
|
|
1051
|
+
timeoutMs: Math.min(this.timeoutMs ?? 10_000, 10_000),
|
|
1052
1052
|
});
|
|
1053
1053
|
}
|
|
1054
1054
|
providerInfo(provider) {
|
|
@@ -1168,7 +1168,7 @@ export class AgyAdapter extends LlmAdapter {
|
|
|
1168
1168
|
...(persistentExtraArgsOf(this.mode).length === 0
|
|
1169
1169
|
? {}
|
|
1170
1170
|
: { extraArgs: persistentExtraArgsOf(this.mode) }),
|
|
1171
|
-
timeoutMs: this.timeoutMs,
|
|
1171
|
+
...(this.timeoutMs === undefined ? {} : { timeoutMs: this.timeoutMs }),
|
|
1172
1172
|
idleTimeoutMs: this.idleTimeoutMs,
|
|
1173
1173
|
maxOutputBytes: this.maxOutputBytes,
|
|
1174
1174
|
...(options.signal === undefined ? {} : { signal: options.signal }),
|
|
@@ -1799,7 +1799,7 @@ export class AgyAdapter extends LlmAdapter {
|
|
|
1799
1799
|
prompt,
|
|
1800
1800
|
agent: imageRuntime?.agent ?? route.agent,
|
|
1801
1801
|
model: route.model,
|
|
1802
|
-
timeoutMs: this.timeoutMs,
|
|
1802
|
+
...(this.timeoutMs === undefined ? {} : { timeoutMs: this.timeoutMs }),
|
|
1803
1803
|
idleTimeoutMs: this.idleTimeoutMs,
|
|
1804
1804
|
maxStdoutBytes: this.maxOutputBytes,
|
|
1805
1805
|
maxStderrBytes: this.maxOutputBytes,
|