dsh-agy-acp 0.1.2 → 0.1.3
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/client.js +37 -11
- package/docs/changelog.md +11 -0
- package/package.json +1 -1
- package/src/acp-client.js +1 -1
package/client.js
CHANGED
|
@@ -101,6 +101,22 @@
|
|
|
101
101
|
return value !== null && typeof value === 'object' && !Array.isArray(value);
|
|
102
102
|
}
|
|
103
103
|
|
|
104
|
+
/**
|
|
105
|
+
* 解包真实宿主 @deepseek-ai/dsh-api-gateway 的一元 Remote 结果信封。
|
|
106
|
+
*
|
|
107
|
+
* 网关客户端 invoke() 的成功返回是 { ok: true, value: <payload> }(失败是
|
|
108
|
+
* { ok: false, error }),并不是裸 payload;离线的远程替身与旧宿主则直接返回
|
|
109
|
+
* payload。这里只剥一层、且只剥「成功信封」:
|
|
110
|
+
* - ok:false 的失败信封原样返回,交给调用方既有的错误分支处理;
|
|
111
|
+
* - 裸 payload 原样返回,绝不误剥业务字段里自带的 ok/value 组合。
|
|
112
|
+
*/
|
|
113
|
+
function unwrapRemoteResult(response) {
|
|
114
|
+
if (isPlainObject(response) && response.ok === true && 'value' in response && response.value !== undefined) {
|
|
115
|
+
return response.value;
|
|
116
|
+
}
|
|
117
|
+
return response;
|
|
118
|
+
}
|
|
119
|
+
|
|
104
120
|
function resolveService(ctx, name) {
|
|
105
121
|
if (!ctx || typeof ctx !== 'object') return null;
|
|
106
122
|
try {
|
|
@@ -960,7 +976,7 @@
|
|
|
960
976
|
if (!api || typeof api.getAcpSnapshot !== 'function') {
|
|
961
977
|
throw new Error('Host 端 dsh-agy-acp.getAcpSnapshot 服务未就绪');
|
|
962
978
|
}
|
|
963
|
-
const response = await api.getAcpSnapshot({ sessionId: focusSessionId || GLOBAL });
|
|
979
|
+
const response = unwrapRemoteResult(await api.getAcpSnapshot({ sessionId: focusSessionId || GLOBAL }));
|
|
964
980
|
if (isPlainObject(response) && response.ok === false) {
|
|
965
981
|
throw new Error(formatErrorMessage(response.error || response));
|
|
966
982
|
}
|
|
@@ -974,7 +990,7 @@
|
|
|
974
990
|
if (!api || typeof api.stopAcpRun !== 'function') {
|
|
975
991
|
return { ok: false, stopped: false, runId, phase: '', reason: 'host-unavailable' };
|
|
976
992
|
}
|
|
977
|
-
const response = await api.stopAcpRun({ runId });
|
|
993
|
+
const response = unwrapRemoteResult(await api.stopAcpRun({ runId }));
|
|
978
994
|
if (isPlainObject(response) && response.ok === false && response.error) {
|
|
979
995
|
throw new Error(formatErrorMessage(response.error));
|
|
980
996
|
}
|
|
@@ -1008,7 +1024,9 @@
|
|
|
1008
1024
|
if (!remoteApi || typeof remoteApi.getAcpQuota !== 'function') {
|
|
1009
1025
|
throw new Error('Host 端 dsh-agy-acp.getAcpQuota 服务未就绪');
|
|
1010
1026
|
}
|
|
1011
|
-
const response =
|
|
1027
|
+
const response = unwrapRemoteResult(
|
|
1028
|
+
await remoteApi.getAcpQuota(isPlainObject(options) ? options : { force: true })
|
|
1029
|
+
);
|
|
1012
1030
|
if (isPlainObject(response) && response.ok === false && response.error) {
|
|
1013
1031
|
throw new Error(formatErrorMessage(response.error));
|
|
1014
1032
|
}
|
|
@@ -1187,9 +1205,10 @@
|
|
|
1187
1205
|
order: PATCH_ORDER,
|
|
1188
1206
|
label: () => (locale && typeof locale.bind === 'function' ? locale.bind(SETTINGS_NS)('title') : 'Antigravity ACP'),
|
|
1189
1207
|
locale: SETTINGS_NS,
|
|
1190
|
-
// api
|
|
1191
|
-
//
|
|
1192
|
-
|
|
1208
|
+
// api 是上面构造好的客户端封装(fetchSnapshot 已解包宿主网关信封),
|
|
1209
|
+
// 传入后设置页能真正拉到宿主实测 snapshot.models;拿不到时组件自动降级到
|
|
1210
|
+
// 内置静态目录,绝不阻塞渲染、也绝不让离线单测崩掉。
|
|
1211
|
+
inject: () => ({ form, api }),
|
|
1193
1212
|
}, AcpSettingsView))
|
|
1194
1213
|
));
|
|
1195
1214
|
return () => {
|
|
@@ -1309,6 +1328,7 @@
|
|
|
1309
1328
|
DEFAULT_SETTINGS,
|
|
1310
1329
|
DEFAULT_MODEL_OPTIONS,
|
|
1311
1330
|
MODEL_ACCESS_VALUES,
|
|
1331
|
+
unwrapRemoteResult,
|
|
1312
1332
|
normalizeModelCatalog,
|
|
1313
1333
|
normalizeStringList,
|
|
1314
1334
|
mergeModelCatalog,
|
|
@@ -1406,14 +1426,20 @@
|
|
|
1406
1426
|
|
|
1407
1427
|
// 连接就绪后再补一次真实模型目录;任何异常(远程未挂载 / 未注入 api)都静默
|
|
1408
1428
|
// 降级到内置静态目录,绝不阻塞渲染、也绝不让离线单测崩掉。
|
|
1409
|
-
|
|
1410
|
-
|
|
1429
|
+
// 两种注入形态都支持:本插件客户端封装 api.fetchSnapshot(已解包宿主网关
|
|
1430
|
+
// { ok: true, value } 信封),以及宿主远程命名空间 api.getAcpSnapshot(这里再解一次)。
|
|
1431
|
+
const snapshotApi = props && props.api ? props.api : null;
|
|
1432
|
+
const useApiFetch = Boolean(snapshotApi && typeof snapshotApi.fetchSnapshot === 'function');
|
|
1433
|
+
const canPullSnapshot =
|
|
1434
|
+
useApiFetch || Boolean(snapshotApi && typeof snapshotApi.getAcpSnapshot === 'function');
|
|
1411
1435
|
React.useEffect(() => {
|
|
1412
|
-
if (!snapshotApi) return undefined;
|
|
1436
|
+
if (!canPullSnapshot || !snapshotApi) return undefined;
|
|
1413
1437
|
let cancelled = false;
|
|
1414
1438
|
const pull = async () => {
|
|
1415
1439
|
try {
|
|
1416
|
-
const snap =
|
|
1440
|
+
const snap = useApiFetch
|
|
1441
|
+
? await snapshotApi.fetchSnapshot(GLOBAL)
|
|
1442
|
+
: unwrapRemoteResult(await snapshotApi.getAcpSnapshot({ sessionId: GLOBAL }));
|
|
1417
1443
|
if (cancelled) return;
|
|
1418
1444
|
const models = normalizeModelCatalog(snap && snap.models);
|
|
1419
1445
|
if (models.length > 0) setCatalogModels(models);
|
|
@@ -1425,7 +1451,7 @@
|
|
|
1425
1451
|
return () => {
|
|
1426
1452
|
cancelled = true;
|
|
1427
1453
|
};
|
|
1428
|
-
}, [snapshotApi]);
|
|
1454
|
+
}, [canPullSnapshot, snapshotApi, useApiFetch]);
|
|
1429
1455
|
|
|
1430
1456
|
const val = (state && state.value) || {};
|
|
1431
1457
|
const isReady = state && state.status === 'ready';
|
package/docs/changelog.md
CHANGED
|
@@ -2,6 +2,17 @@
|
|
|
2
2
|
|
|
3
3
|
[返回主页](../README.md) · [配置参考](configuration.md) · [接口参考](reference.md) · [开发与发布](development.md)
|
|
4
4
|
|
|
5
|
+
## [0.1.3] - 2026-11-15
|
|
6
|
+
|
|
7
|
+
### 修复
|
|
8
|
+
- 修复真实宿主 `@deepseek-ai/dsh-api-gateway` 的一元 Remote 结果信封 `{ ok: true, value: <payload> }` 未解包的问题:`client.js` 新增 `unwrapRemoteResult()`(只剥成功信封;`ok: false` 失败信封与离线替身/旧宿主的裸 payload 一律原样返回),并接入 `fetchSnapshotOnce` / `stopRun` / `fetchQuotaOnce` 三处。
|
|
9
|
+
- 症状:面板快照恒为空、停止运行恒报 `stopped: false`、额度卡片读不到 `groups`,设置页也拿不到宿主实测模型列表。
|
|
10
|
+
- 设置页 `settings.section` 槽位的 `inject` 改为传入已构造好的客户端封装 `api`(原为远程命名空间),并把 `AcpSettingsView` 的快照拉取改走 `api.fetchSnapshot`(仍兼容 `api.getAcpSnapshot` 形态并同样解包信封),真实桌面打开设置页即可把宿主实测模型合并进权限矩阵;离线测试只传 `{ form }` 时仍安全降级、绝不报错。
|
|
11
|
+
|
|
12
|
+
### 测试
|
|
13
|
+
- `test/acp-panel.test.mjs`:新增 `unwrapRemoteResult` 边界用例(成功信封 / 失败信封 / 裸 payload / `value: undefined`)、三处远程调用解包回归(`models`、`stopped: true`、`quota.groups`)、以及挂载后设置页注入 `api` 解包拉取 `models` 并合并进权限矩阵的回归。
|
|
14
|
+
- `test/acp-quota.test.mjs`:新增 `api.fetchQuota` 解包网关信封后额度卡片读到 `groups`(0 余额精确保留)与失败信封继续抛错的回归。
|
|
15
|
+
|
|
5
16
|
## [0.1.2] - 2026-11-15
|
|
6
17
|
|
|
7
18
|
### 新增
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-agy-acp",
|
|
3
3
|
"displayName": "Antigravity ACP Worker",
|
|
4
|
-
"version": "0.1.
|
|
4
|
+
"version": "0.1.3",
|
|
5
5
|
"description": "Antigravity CLI (agy) ACP bridge for DeepSeek Harness: resumable worker turns, background job wakeup, semaphore queuing, four-tier permission gating, zero-sidecar SQLite token ledger, and on-demand quota inspection.",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"author": "higekibaka",
|
package/src/acp-client.js
CHANGED
|
@@ -22,7 +22,7 @@ const executableMod = require('./executable.js');
|
|
|
22
22
|
const imagesMod = require('./images.js');
|
|
23
23
|
|
|
24
24
|
const PLUGIN_NAME = 'dsh-agy-acp';
|
|
25
|
-
const PLUGIN_VERSION = '0.1.
|
|
25
|
+
const PLUGIN_VERSION = '0.1.3';
|
|
26
26
|
const PROTOCOL_VERSION = 1;
|
|
27
27
|
const MAX_LINE_BYTES = 8 * 1024 * 1024;
|
|
28
28
|
|