@sema-agent/sdk 4.1.0 → 4.3.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/README.md +34 -1
- package/dist/client.d.ts +10 -1
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +7 -2
- package/dist/client.js.map +1 -1
- package/dist/control-types.d.ts +22 -4
- package/dist/control-types.d.ts.map +1 -1
- package/dist/control-types.js +3 -1
- package/dist/control-types.js.map +1 -1
- package/dist/errors.d.ts +42 -5
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +81 -7
- package/dist/errors.js.map +1 -1
- package/dist/events.d.ts +63 -1
- package/dist/events.d.ts.map +1 -1
- package/dist/events.js.map +1 -1
- package/dist/health.d.ts +76 -7
- package/dist/health.d.ts.map +1 -1
- package/dist/health.js +40 -2
- package/dist/health.js.map +1 -1
- package/dist/idempotency.d.ts +11 -1
- package/dist/idempotency.d.ts.map +1 -1
- package/dist/idempotency.js +11 -1
- package/dist/idempotency.js.map +1 -1
- package/dist/index.d.ts +18 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +11 -2
- package/dist/index.js.map +1 -1
- package/dist/registry/health.d.ts +6 -1
- package/dist/registry/health.d.ts.map +1 -1
- package/dist/registry/health.js +6 -4
- package/dist/registry/health.js.map +1 -1
- package/dist/registry/index.d.ts +7 -1
- package/dist/registry/index.d.ts.map +1 -1
- package/dist/registry/index.js +7 -1
- package/dist/registry/index.js.map +1 -1
- package/dist/resources/approvals.d.ts +43 -13
- package/dist/resources/approvals.d.ts.map +1 -1
- package/dist/resources/approvals.js +35 -12
- package/dist/resources/approvals.js.map +1 -1
- package/dist/resources/assistant.d.ts +21 -4
- package/dist/resources/assistant.d.ts.map +1 -1
- package/dist/resources/assistant.js +10 -3
- package/dist/resources/assistant.js.map +1 -1
- package/dist/resources/attachments.d.ts +9 -2
- package/dist/resources/attachments.d.ts.map +1 -1
- package/dist/resources/attachments.js.map +1 -1
- package/dist/resources/control/secrets.d.ts +10 -1
- package/dist/resources/control/secrets.d.ts.map +1 -1
- package/dist/resources/control/secrets.js +10 -1
- package/dist/resources/control/secrets.js.map +1 -1
- package/dist/resources/fleet.d.ts +11 -5
- package/dist/resources/fleet.d.ts.map +1 -1
- package/dist/resources/fleet.js +2 -1
- package/dist/resources/fleet.js.map +1 -1
- package/dist/resources/images.d.ts +10 -1
- package/dist/resources/images.d.ts.map +1 -1
- package/dist/resources/images.js +20 -5
- package/dist/resources/images.js.map +1 -1
- package/dist/resources/leader.d.ts +7 -3
- package/dist/resources/leader.d.ts.map +1 -1
- package/dist/resources/leader.js +7 -3
- package/dist/resources/leader.js.map +1 -1
- package/dist/resources/ops.d.ts +29 -2
- package/dist/resources/ops.d.ts.map +1 -1
- package/dist/resources/ops.js +6 -1
- package/dist/resources/ops.js.map +1 -1
- package/dist/resources/runs.d.ts +89 -18
- package/dist/resources/runs.d.ts.map +1 -1
- package/dist/resources/runs.js +53 -17
- package/dist/resources/runs.js.map +1 -1
- package/dist/resources/session-sync.d.ts +77 -17
- package/dist/resources/session-sync.d.ts.map +1 -1
- package/dist/resources/session-sync.js +81 -20
- package/dist/resources/session-sync.js.map +1 -1
- package/dist/resources/sessions.d.ts +82 -13
- package/dist/resources/sessions.d.ts.map +1 -1
- package/dist/resources/sessions.js +39 -7
- package/dist/resources/sessions.js.map +1 -1
- package/dist/resources/tool-approvals.d.ts +8 -5
- package/dist/resources/tool-approvals.d.ts.map +1 -1
- package/dist/resources/tool-approvals.js +2 -1
- package/dist/resources/tool-approvals.js.map +1 -1
- package/dist/resources/trace.d.ts +17 -3
- package/dist/resources/trace.d.ts.map +1 -1
- package/dist/resources/trace.js +25 -5
- package/dist/resources/trace.js.map +1 -1
- package/dist/resources/workflows.d.ts +42 -10
- package/dist/resources/workflows.d.ts.map +1 -1
- package/dist/resources/workflows.js +46 -9
- package/dist/resources/workflows.js.map +1 -1
- package/dist/resources/workspace.d.ts +36 -11
- package/dist/resources/workspace.d.ts.map +1 -1
- package/dist/resources/workspace.js.map +1 -1
- package/dist/sse.d.ts +58 -14
- package/dist/sse.d.ts.map +1 -1
- package/dist/sse.js +88 -15
- package/dist/sse.js.map +1 -1
- package/dist/sync.d.ts +37 -8
- package/dist/sync.d.ts.map +1 -1
- package/dist/sync.js +24 -8
- package/dist/sync.js.map +1 -1
- package/dist/transport.d.ts +31 -4
- package/dist/transport.d.ts.map +1 -1
- package/dist/transport.js +38 -6
- package/dist/transport.js.map +1 -1
- package/dist/types.d.ts +156 -51
- package/dist/types.d.ts.map +1 -1
- package/openapi.yaml +377 -59
- package/package.json +2 -2
- package/registry-openapi.yaml +34 -3
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,iGAAiG;AACjG,OAAO,EAAE,WAAW,EAA+C,MAAM,aAAa,CAAC;AACvF;qEACqE;AACrE,OAAO,EAAE,aAAa,EAA4B,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,iGAAiG;AACjG,OAAO,EAAE,WAAW,EAA+C,MAAM,aAAa,CAAC;AACvF;qEACqE;AACrE,OAAO,EAAE,aAAa,EAA4B,MAAM,qBAAqB,CAAC;AA2B9E,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,wEAAwE;AACxE,OAAO,EAAE,eAAe,EAAE,gBAAgB,EAAE,qBAAqB,EAAyC,MAAM,oBAAoB,CAAC;AACrI,OAAO,EAAE,aAAa,EAAkB,MAAM,uBAAuB,CAAC;AAEtE,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,uBAAuB,EAAE,mBAAmB,EAAE,aAAa,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,4BAA4B,EAAE,iCAAiC,EAAE,uBAAuB,EAAE,2BAA2B,EAAE,oBAAoB,EAAE,qBAAqB,EAAE,wBAAwB,EAAE,qBAAqB,EAAE,wBAAwB,EAAE,uBAAuB,EAAE,qBAAqB,EAAE,sBAAsB,EAAE,0BAA0B,EAAE,2BAA2B,EAAE,oBAAoB,EAAE,eAAe;AAC5jB,6EAA6E;AAC7E,2FAA2F;AAC3F,iCAAiC;AACjC,aAAa;AACb,2FAA2F;AAC3F,yBAAyB,EAAE,0BAA0B,EACrD,WAAW,EAAE,oBAAoB,EAAE,sBAAsB,EAAE,2BAA2B;AACtF,2EAA2E;AAC3E,4EAA4E;AAC5E,eAAe,EAAE,aAAa,EAAE,kBAAkB,EAAE,0BAA0B,EAAE,oBAAoB,EACpG,mBAAmB,EAAE,iBAAiB;AACtC,kEAAkE;AAClE,aAAa,EAAE,4BAA4B,EAAE,yBAAyB;AACtE,+DAA+D;AAC/D,wBAAwB,EAAE,MAAM,aAAa,CAAC;AAGhD;yDACyD;AACzD,OAAO,EAAE,kBAAkB,EAAE,MAAM,UAAU,CAAC;AAC9C;6GAC6G;AAC7G,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AACxC;;sGAEsG;AACtG,OAAO,EAAE,+BAA+B,EAAE,MAAM,UAAU,CAAC;AAC3D;6GAC6G;AAC7G,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,6BAA6B,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,MAAM,WAAW,CAAC;AAGrH,OAAO,EAAE,mBAAmB,EAAE,MAAM,6BAA6B,CAAC;AAClE,OAAO,EAAE,iBAAiB,EAA+C,MAAM,2BAA2B,CAAC;AAe3G,qGAAqG;AACrG,OAAO,EAAE,YAAY,EAAE,gBAAgB,EAAE,qBAAqB,EAAE,oBAAoB,EAAE,sBAAsB,EAAE,oBAAoB,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAaxK;oDACoD;AACpD,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AACrD;6FAC6F;AAC7F,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAOhE;iHACiH;AACjH,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAErD,qEAAqE;AACrE,sEAAsE;AACtE,OAAO,EAAE,qBAAqB,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,qBAAqB,EAAE,gBAAgB,EAAiB,MAAM,gBAAgB,CAAC;AACvJ,qDAAqD;AACrD,OAAO,EACL,iBAAiB,GAKlB,MAAM,0BAA0B,CAAC"}
|
|
@@ -2,10 +2,15 @@
|
|
|
2
2
|
* probeRegistryHealth(G18 顺并进 R1):zero-throw 健康探针——`/api/healthz` 唯一探活口
|
|
3
3
|
* ([2354] 兼容面全清:旧 `/healthz` 回落腿与 `legacy` 提示字段已删)。与 worker 面的 probeAuth
|
|
4
4
|
* 同族姿势:judgement-typed,永不抛。
|
|
5
|
+
*
|
|
6
|
+
* 4.3.0 措辞除锈(RC-12):本文件残留过三处双腿时代的化石 —— `reason` 的「**末次** HTTP status」(只剩一次
|
|
7
|
+
* 探测,没有「末次」)、辅助函数名 `tryOne`(为多路探测而设)、变量名 `modern`(`modern`/`legacy` 配对的残半)。
|
|
8
|
+
* 零行为影响,纯可读性。⚠️ 这段说明**只能待在模块头**:`test/breaking-4.0.0-removals.test.ts` 有一道门盯着
|
|
9
|
+
* `RegistryHealthResult` 接口体内不许再出现描述已删腿的字眼(孤儿注就是那么长出来的),把理由写进字段注会红。
|
|
5
10
|
*/
|
|
6
11
|
export interface RegistryHealthResult {
|
|
7
12
|
ok: boolean;
|
|
8
|
-
/** ok:false 时的原因(网络错文本 /
|
|
13
|
+
/** ok:false 时的原因(网络错文本 / HTTP status)。 */
|
|
9
14
|
reason?: string;
|
|
10
15
|
}
|
|
11
16
|
export declare function probeRegistryHealth(baseUrl: string, opts?: {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"health.d.ts","sourceRoot":"","sources":["../../src/registry/health.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"health.d.ts","sourceRoot":"","sources":["../../src/registry/health.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,MAAM,WAAW,oBAAoB;IACnC,EAAE,EAAE,OAAO,CAAC;IACZ,0CAA0C;IAC1C,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,wBAAsB,mBAAmB,CACvC,OAAO,EAAE,MAAM,EACf,IAAI,GAAE;IAAE,KAAK,CAAC,EAAE,OAAO,KAAK,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAO,GACtD,OAAO,CAAC,oBAAoB,CAAC,CAqB/B"}
|
package/dist/registry/health.js
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
export async function probeRegistryHealth(baseUrl, opts = {}) {
|
|
2
2
|
const f = opts.fetch ?? fetch;
|
|
3
3
|
const base = baseUrl.replace(/\/+$/, "");
|
|
4
|
-
|
|
4
|
+
// 4.3.0 除锈:此函数原名 `tryOne` —— 「try ONE (of several)」是为多路探测起的名字,双腿退役后只被调用一次。
|
|
5
|
+
const probeOnce = async (path) => {
|
|
5
6
|
const ac = new AbortController();
|
|
6
7
|
const timer = setTimeout(() => ac.abort(), opts.timeoutMs ?? 5_000);
|
|
7
8
|
try {
|
|
@@ -16,9 +17,10 @@ export async function probeRegistryHealth(baseUrl, opts = {}) {
|
|
|
16
17
|
}
|
|
17
18
|
};
|
|
18
19
|
// [2354] 兼容面全清:旧 `/healthz` 回落腿与 `legacy` 提示字段已删——registry 现代部署唯一探活口=/api/healthz。
|
|
19
|
-
|
|
20
|
-
|
|
20
|
+
// 4.3.0 除锈:变量原名 `modern` —— 它是 `modern`/`legacy` 配对的残半,配对的另一半早已删除。
|
|
21
|
+
const probed = await probeOnce("/api/healthz");
|
|
22
|
+
if (probed.ok)
|
|
21
23
|
return { ok: true };
|
|
22
|
-
return { ok: false, reason:
|
|
24
|
+
return { ok: false, reason: probed.reason ?? `HTTP ${probed.status ?? "?"} (/api/healthz)` };
|
|
23
25
|
}
|
|
24
26
|
//# sourceMappingURL=health.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"health.js","sourceRoot":"","sources":["../../src/registry/health.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"health.js","sourceRoot":"","sources":["../../src/registry/health.ts"],"names":[],"mappings":"AAgBA,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACvC,OAAe,EACf,OAAqD,EAAE;IAEvD,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,IAAI,KAAK,CAAC;IAC9B,MAAM,IAAI,GAAG,OAAO,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;IACzC,2EAA2E;IAC3E,MAAM,SAAS,GAAG,KAAK,EAAE,IAAY,EAA8D,EAAE;QACnG,MAAM,EAAE,GAAG,IAAI,eAAe,EAAE,CAAC;QACjC,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,KAAK,EAAE,EAAE,IAAI,CAAC,SAAS,IAAI,KAAK,CAAC,CAAC;QACpE,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,MAAM,CAAC,CAAC,IAAI,GAAG,IAAI,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,CAAC,MAAM,EAAE,CAAC,CAAC;YACvE,OAAO,EAAE,EAAE,EAAE,GAAG,CAAC,MAAM,KAAK,GAAG,EAAE,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,CAAC;QACxD,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC;QACjF,CAAC;gBAAS,CAAC;YACT,YAAY,CAAC,KAAK,CAAC,CAAC;QACtB,CAAC;IACH,CAAC,CAAC;IACF,mFAAmF;IACnF,mEAAmE;IACnE,MAAM,MAAM,GAAG,MAAM,SAAS,CAAC,cAAc,CAAC,CAAC;IAC/C,IAAI,MAAM,CAAC,EAAE;QAAE,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC;IACnC,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,IAAI,QAAQ,MAAM,CAAC,MAAM,IAAI,GAAG,iBAAiB,EAAE,CAAC;AAC/F,CAAC"}
|
package/dist/registry/index.d.ts
CHANGED
|
@@ -14,7 +14,13 @@ export { InMemoryTokenProvider, type TokenProvider, type RegistryTokens } from "
|
|
|
14
14
|
export { requestDeviceCode, pollUntilApproved, refreshTokens, logoutRegistry, REGISTRY_AUTH_PATHS, REGISTRY_DEVICE_GRANT_TYPE, type DeviceCodeResponse, type TokenGrantResponse, } from "./auth.js";
|
|
15
15
|
export { probeRegistryHealth, type RegistryHealthResult } from "./health.js";
|
|
16
16
|
export { listScopes, switchScope, getEffective, REGISTRY_SCOPES_PATHS, type ScopesListResponse, type ScopeSwitchResponse, type EffectiveResult, } from "./scopes-effective.js";
|
|
17
|
-
export { RegistryApiError, OAuthFlowError, type OAuthFlowErrorCode
|
|
17
|
+
export { RegistryApiError, OAuthFlowError, type OAuthFlowErrorCode,
|
|
18
|
+
/** 🔴 RC-13(4.3.0):这个**值**此前没出去 —— re-export 只带了两个类 + 一个 type,而
|
|
19
|
+
* `REGISTRY_OAUTH_ERROR_CODES` 恰恰是同源锚测试对账的那个数组。上游把它当**值**导出
|
|
20
|
+
* (`registry-core` 的 `OAUTH_ERROR_CODES`)正是因为消费端需要在运行时枚举:渲染错误码表、
|
|
21
|
+
* 给 exhaustive switch 的 `default` 写断言、校验一个外来字符串是不是合法码 —— 三件事都拿不到它,
|
|
22
|
+
* 只能再手抄一份,而那正是这条常量存在要消除的东西。纯 additive。 */
|
|
23
|
+
REGISTRY_OAUTH_ERROR_CODES, } from "./errors.js";
|
|
18
24
|
export { getMeConfig, putMeConfig, ConfigCasConflictError, type PersonalConfigDomain, type MeConfigValue, type MeConfigPut, type MeConfigPutResult, } from "./me-config.js";
|
|
19
25
|
export { RegistryAdmin, ADMIN_ENDPOINTS } from "./admin.js";
|
|
20
26
|
export { ScopeConfigCasConflictError, getScopeConfigDraft, getScopeConfigPublished, putScopeConfigDraft, getPublishState, requestPublish, postFeedback, skillContentAddress, } from "./scope-config-feedback.js";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/registry/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,OAAO,EAAE,cAAc,EAAE,KAAK,oBAAoB,EAAE,KAAK,sBAAsB,EAAE,MAAM,aAAa,CAAC;AACrG,OAAO,EAAE,qBAAqB,EAAE,KAAK,aAAa,EAAE,KAAK,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACrG,OAAO,EACL,iBAAiB,EACjB,iBAAiB,EACjB,aAAa,EACb,cAAc,EACd,mBAAmB,EACnB,0BAA0B,EAC1B,KAAK,kBAAkB,EACvB,KAAK,kBAAkB,GACxB,MAAM,WAAW,CAAC;AACnB,OAAO,EAAE,mBAAmB,EAAE,KAAK,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAC7E,OAAO,EACL,UAAU,EACV,WAAW,EACX,YAAY,EACZ,qBAAqB,EACrB,KAAK,kBAAkB,EACvB,KAAK,mBAAmB,EACxB,KAAK,eAAe,GACrB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/registry/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,OAAO,EAAE,cAAc,EAAE,KAAK,oBAAoB,EAAE,KAAK,sBAAsB,EAAE,MAAM,aAAa,CAAC;AACrG,OAAO,EAAE,qBAAqB,EAAE,KAAK,aAAa,EAAE,KAAK,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACrG,OAAO,EACL,iBAAiB,EACjB,iBAAiB,EACjB,aAAa,EACb,cAAc,EACd,mBAAmB,EACnB,0BAA0B,EAC1B,KAAK,kBAAkB,EACvB,KAAK,kBAAkB,GACxB,MAAM,WAAW,CAAC;AACnB,OAAO,EAAE,mBAAmB,EAAE,KAAK,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAC7E,OAAO,EACL,UAAU,EACV,WAAW,EACX,YAAY,EACZ,qBAAqB,EACrB,KAAK,kBAAkB,EACvB,KAAK,mBAAmB,EACxB,KAAK,eAAe,GACrB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EACL,gBAAgB,EAChB,cAAc,EACd,KAAK,kBAAkB;AACvB;;;;2CAI2C;AAC3C,0BAA0B,GAC3B,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,WAAW,EACX,WAAW,EACX,sBAAsB,EACtB,KAAK,oBAAoB,EACzB,KAAK,aAAa,EAClB,KAAK,WAAW,EAChB,KAAK,iBAAiB,GACvB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAC5D,OAAO,EACL,2BAA2B,EAC3B,mBAAmB,EACnB,uBAAuB,EACvB,mBAAmB,EACnB,eAAe,EACf,cAAc,EACd,YAAY,EACZ,mBAAmB,GACpB,MAAM,4BAA4B,CAAC"}
|
package/dist/registry/index.js
CHANGED
|
@@ -14,7 +14,13 @@ export { InMemoryTokenProvider } from "./token-provider.js";
|
|
|
14
14
|
export { requestDeviceCode, pollUntilApproved, refreshTokens, logoutRegistry, REGISTRY_AUTH_PATHS, REGISTRY_DEVICE_GRANT_TYPE, } from "./auth.js";
|
|
15
15
|
export { probeRegistryHealth } from "./health.js";
|
|
16
16
|
export { listScopes, switchScope, getEffective, REGISTRY_SCOPES_PATHS, } from "./scopes-effective.js";
|
|
17
|
-
export { RegistryApiError, OAuthFlowError
|
|
17
|
+
export { RegistryApiError, OAuthFlowError,
|
|
18
|
+
/** 🔴 RC-13(4.3.0):这个**值**此前没出去 —— re-export 只带了两个类 + 一个 type,而
|
|
19
|
+
* `REGISTRY_OAUTH_ERROR_CODES` 恰恰是同源锚测试对账的那个数组。上游把它当**值**导出
|
|
20
|
+
* (`registry-core` 的 `OAUTH_ERROR_CODES`)正是因为消费端需要在运行时枚举:渲染错误码表、
|
|
21
|
+
* 给 exhaustive switch 的 `default` 写断言、校验一个外来字符串是不是合法码 —— 三件事都拿不到它,
|
|
22
|
+
* 只能再手抄一份,而那正是这条常量存在要消除的东西。纯 additive。 */
|
|
23
|
+
REGISTRY_OAUTH_ERROR_CODES, } from "./errors.js";
|
|
18
24
|
export { getMeConfig, putMeConfig, ConfigCasConflictError, } from "./me-config.js";
|
|
19
25
|
export { RegistryAdmin, ADMIN_ENDPOINTS } from "./admin.js";
|
|
20
26
|
export { ScopeConfigCasConflictError, getScopeConfigDraft, getScopeConfigPublished, putScopeConfigDraft, getPublishState, requestPublish, postFeedback, skillContentAddress, } from "./scope-config-feedback.js";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/registry/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,OAAO,EAAE,cAAc,EAA0D,MAAM,aAAa,CAAC;AACrG,OAAO,EAAE,qBAAqB,EAA2C,MAAM,qBAAqB,CAAC;AACrG,OAAO,EACL,iBAAiB,EACjB,iBAAiB,EACjB,aAAa,EACb,cAAc,EACd,mBAAmB,EACnB,0BAA0B,GAG3B,MAAM,WAAW,CAAC;AACnB,OAAO,EAAE,mBAAmB,EAA6B,MAAM,aAAa,CAAC;AAC7E,OAAO,EACL,UAAU,EACV,WAAW,EACX,YAAY,EACZ,qBAAqB,GAItB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/registry/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,OAAO,EAAE,cAAc,EAA0D,MAAM,aAAa,CAAC;AACrG,OAAO,EAAE,qBAAqB,EAA2C,MAAM,qBAAqB,CAAC;AACrG,OAAO,EACL,iBAAiB,EACjB,iBAAiB,EACjB,aAAa,EACb,cAAc,EACd,mBAAmB,EACnB,0BAA0B,GAG3B,MAAM,WAAW,CAAC;AACnB,OAAO,EAAE,mBAAmB,EAA6B,MAAM,aAAa,CAAC;AAC7E,OAAO,EACL,UAAU,EACV,WAAW,EACX,YAAY,EACZ,qBAAqB,GAItB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EACL,gBAAgB,EAChB,cAAc;AAEd;;;;2CAI2C;AAC3C,0BAA0B,GAC3B,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,WAAW,EACX,WAAW,EACX,sBAAsB,GAKvB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAC5D,OAAO,EACL,2BAA2B,EAC3B,mBAAmB,EACnB,uBAAuB,EACvB,mBAAmB,EACnB,eAAe,EACf,cAAc,EACd,YAAY,EACZ,mBAAmB,GACpB,MAAM,4BAA4B,CAAC"}
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
* (web-native, non-expert users authorizing/answering); also usable by door A. */
|
|
4
4
|
import type { Transport } from "../transport.js";
|
|
5
5
|
import type { PendingCheckpoint } from "../types.js";
|
|
6
|
+
import type { QuestionAnswer } from "./questions.js";
|
|
6
7
|
/** One per-session approval exemption ("本会话不再询问", service exemptions ruling — an APPROVAL MEMORY, not a
|
|
7
8
|
* policy loosen: deny/neverAuto always outrank it). Keyed in CANONICAL tool-name space (service
|
|
8
9
|
* `ApprovalExemptionRow`, approval-exemption-store.ts). */
|
|
@@ -13,18 +14,36 @@ export interface ApprovalExemption {
|
|
|
13
14
|
/** Epoch MS of the FIRST grant (a re-grant refreshes grantedBy, not this). */
|
|
14
15
|
createdAt: number;
|
|
15
16
|
}
|
|
16
|
-
/** A delta event from `GET /v1/approvals/stream` (native push, service [83]).
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
17
|
+
/** A delta event from `GET /v1/approvals/stream` (native push, service [83]).
|
|
18
|
+
*
|
|
19
|
+
* 🔴 [2400] HITL-9 —— 形状**已实核**(server `streamApprovals`,`src/http/routes/approvals-assistant.ts:650-698`),
|
|
20
|
+
* 「FORWARD-DRAFT pending service's shape confirmation」那句已删:它写在核对之前,而核对结果是既有的四个
|
|
21
|
+
* `type` 值漏了**两个**真发的帧。每条 `data:` 载荷都回声一个 `type`(与 SSE `event:` 名同值),所以剥了
|
|
22
|
+
* 事件名的中继也能分派。六个真值:
|
|
23
|
+
* · `meta` — 开流第一帧,`{version, mode:"approvals-delta", pollMs}`(服务端 diff 轮询周期,3000ms)。
|
|
24
|
+
* · `pending` — 一条新挂起(首帧快照期逐条发一遍,随后才是增量)。载荷 = 富行 {@link PendingCheckpoint} 展开。
|
|
25
|
+
* · `synced` — 首帧快照发完,`{count}`。**这之后**才是真增量。
|
|
26
|
+
* · `resolved` — 一条挂起消失(被决/过期/GC),`{sessionId, toolCallId}`。
|
|
27
|
+
* · `heartbeat` — 15s 保活;注意它是**真帧**(`data:{"type":"heartbeat"}`),不是裸 `:` 注释行。
|
|
28
|
+
* · `error` — 15 分钟帽:`{errorCode:"STREAM_MAX_DURATION", message}`,之后 server 主动收流 ⇒ **重连**。
|
|
29
|
+
* 仍是**开集**(`(string & {})`):不解析增量的消费方可以把任何非 heartbeat 事件当「变了」信号,回头拉
|
|
30
|
+
* 权威列表(`list()`)—— 那条兜底路子一直有效,只是不再是「因为形状没确认」。 */
|
|
20
31
|
export interface ApprovalStreamEvent {
|
|
21
|
-
type: "pending" | "resolved" | "synced" | "heartbeat" | (string & {});
|
|
32
|
+
type: "meta" | "pending" | "resolved" | "synced" | "heartbeat" | "error" | (string & {});
|
|
22
33
|
[k: string]: unknown;
|
|
23
34
|
}
|
|
24
35
|
export interface ApprovalDecision {
|
|
25
36
|
decision: "approve" | "deny";
|
|
26
|
-
/** For AskUserQuestion: the operator's answer. Omit for a plain F4 approve/deny.
|
|
27
|
-
|
|
37
|
+
/** For AskUserQuestion: the operator's answer. Omit for a plain F4 approve/deny.
|
|
38
|
+
*
|
|
39
|
+
* 🔴 [2400] HITL-8 —— 从 `unknown` 收成 {@link QuestionAnswer}(与 `client.questions.respond` **同一个**类型,
|
|
40
|
+
* 单源)。server 侧 `isQuestionAnswer`(`routes/approvals-assistant.ts:36-50`)按这个结构严校,坏形 400。
|
|
41
|
+
* ⚠️ **两腿严格度不同**,别把 live 腿的宽松当契约:
|
|
42
|
+
* · DURABLE 腿(本 verb)`answers[]` 必须**非空**,每项 `selected` 也必须非空 —— 空数组是 400。
|
|
43
|
+
* · LIVE 腿(`POST /v1/questions/:id/respond`,`src/question.ts:95`)只校 `Array.isArray(answers)` ⇒
|
|
44
|
+
* **空数组被接受**(它有 headless-default 的语义位置)。
|
|
45
|
+
* 语义栅栏在 core:`selected ⊆ options`,`note` 走 untrusted-DATA fence —— 客户端不必也不该自己重算。 */
|
|
46
|
+
answer?: QuestionAnswer;
|
|
28
47
|
reason?: string;
|
|
29
48
|
/** design/80 D-1 — action binding (TOCTOU guard). Read these TWO off the `PendingCheckpoint` the human saw
|
|
30
49
|
* and pass them back VERBATIM; the server resolves THIS exact checkpoint, fail-closed on mismatch
|
|
@@ -74,8 +93,14 @@ export declare class ApprovalsResource {
|
|
|
74
93
|
signal?: AbortSignal;
|
|
75
94
|
}): Promise<Record<string, unknown>>;
|
|
76
95
|
/** GET /v1/approvals — pending checkpoints (operator-scoped; envelope key `pending`).
|
|
77
|
-
* NEVER returns the capability token. ⚠️ item createdAt/deadline are epoch MS.
|
|
96
|
+
* NEVER returns the capability token. ⚠️ item createdAt/deadline are epoch MS.
|
|
97
|
+
*
|
|
98
|
+
* 🔴 [2400] HITL-5 `opts.owner` —— **OPERATOR 语义**,不是过滤器(server
|
|
99
|
+
* `src/http/routes/approvals-assistant.ts:88-92`):调用方是 operator 时 `?owner=` 把队列切到**那个 owner**
|
|
100
|
+
* 的 scope(不传 = 全租户视图,这是本面与 per-user 的 `assistant.inbox` 的分野);调用方**不是** operator
|
|
101
|
+
* 时,server 无条件用它自己的 principal —— 传了也**静默无效**,绝不是越权入口。 */
|
|
78
102
|
list(opts?: {
|
|
103
|
+
owner?: string;
|
|
79
104
|
signal?: AbortSignal;
|
|
80
105
|
}): Promise<{
|
|
81
106
|
pending: PendingCheckpoint[];
|
|
@@ -110,13 +135,18 @@ export declare class ApprovalsResource {
|
|
|
110
135
|
revokeExemption(sessionId: string, toolName: string, opts?: {
|
|
111
136
|
signal?: AbortSignal;
|
|
112
137
|
}): Promise<boolean>;
|
|
113
|
-
/** GET /v1/approvals/stream — native push (SSE delta, meta
|
|
114
|
-
* BFF-side polling of `list()`. LONG-LIVED
|
|
115
|
-
*
|
|
138
|
+
/** GET /v1/approvals/stream — native push (SSE delta, `meta.mode:"approvals-delta"`, service [83]). Replaces
|
|
139
|
+
* BFF-side polling of `list()`. LONG-LIVED: there is NO terminal event — this reconnects on drops /
|
|
140
|
+
* heartbeat-silence and tails on (uses `readSseFrames`, NOT `parseSse`, which would end on done/failed).
|
|
116
141
|
* A non-`ok` first response (e.g. 404 on a worker without the endpoint) throws → caller falls back to polling.
|
|
117
|
-
*
|
|
118
|
-
*
|
|
142
|
+
* Frame vocabulary + scoping: see {@link ApprovalStreamEvent} (six real `type` values, shape实核 2026-08-02)
|
|
143
|
+
* and {@link ApprovalsResource.list} for the operator `owner` semantics — `?owner=` is honored identically here
|
|
144
|
+
* (`routes/approvals-assistant.ts:81-86`).
|
|
145
|
+
* ⚠️ The server ends the stream itself at its 15-minute cap, announcing it with an `error` frame
|
|
146
|
+
* (`errorCode: "STREAM_MAX_DURATION"`); this loop simply reconnects — but a consumer that mirrors frames
|
|
147
|
+
* onward should not forward that one as a failure. */
|
|
119
148
|
stream(opts?: {
|
|
149
|
+
owner?: string;
|
|
120
150
|
signal?: AbortSignal;
|
|
121
151
|
}): AsyncGenerator<ApprovalStreamEvent>;
|
|
122
152
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"approvals.d.ts","sourceRoot":"","sources":["../../src/resources/approvals.ts"],"names":[],"mappings":"AAAA;;mFAEmF;AACnF,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AACjD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAIrD;;4DAE4D;AAC5D,MAAM,WAAW,iBAAiB;IAChC,QAAQ,EAAE,MAAM,CAAC;IACjB,mEAAmE;IACnE,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,8EAA8E;IAC9E,SAAS,EAAE,MAAM,CAAC;CACnB;AAED
|
|
1
|
+
{"version":3,"file":"approvals.d.ts","sourceRoot":"","sources":["../../src/resources/approvals.ts"],"names":[],"mappings":"AAAA;;mFAEmF;AACnF,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AACjD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AACrD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAIrD;;4DAE4D;AAC5D,MAAM,WAAW,iBAAiB;IAChC,QAAQ,EAAE,MAAM,CAAC;IACjB,mEAAmE;IACnE,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,8EAA8E;IAC9E,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;;;;;;;;;;;;kDAakD;AAClD,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,UAAU,GAAG,QAAQ,GAAG,WAAW,GAAG,OAAO,GAAG,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC;IACzF,CAAC,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;CACtB;AAED,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,SAAS,GAAG,MAAM,CAAC;IAC7B;;;;;;;;yFAQqF;IACrF,MAAM,CAAC,EAAE,cAAc,CAAC;IACxB,MAAM,CAAC,EAAE,MAAM,CAAC;IAKhB;;;uEAGmE;IACnE,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,6GAA6G;IAC7G,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB;4GACwG;IACxG,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB;;;;;wFAKoF;IACpF,QAAQ,CAAC,EAAE,SAAS,CAAC;CACtB;AAED;;;wFAGwF;AACxF,MAAM,WAAW,oBAAoB;IACnC,0CAA0C;IAC1C,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,UAAU,CAAC;IACnB,QAAQ,EAAE,SAAS,GAAG,MAAM,CAAC;CAC9B;AAED,qBAAa,iBAAiB;IAChB,OAAO,CAAC,QAAQ,CAAC,CAAC;gBAAD,CAAC,EAAE,SAAS;IAEzC;;;;;;;;;;;;oCAYgC;IAC1B,GAAG,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,WAAW,CAAA;KAAE,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAOxF;;;;;;8DAM0D;IACpD,IAAI,CAAC,IAAI,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,WAAW,CAAA;KAAE,GAAG,OAAO,CAAC;QAAE,OAAO,EAAE,iBAAiB,EAAE,CAAA;KAAE,CAAC;IAQtG;;;;;;;;;;;;2CAYuC;IACjC,MAAM,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,gBAAgB,EAAE,IAAI,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,WAAW,CAAA;KAAE,GAAG,OAAO,CAAC,OAAO,CAAC;IAS9G;+EAC2E;IACrE,cAAc,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,WAAW,CAAA;KAAE,GAAG,OAAO,CAAC;QAAE,UAAU,EAAE,iBAAiB,EAAE,CAAA;KAAE,CAAC;IAStH;;;uHAGmH;IAC7G,eAAe,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,WAAW,CAAA;KAAE,GAAG,OAAO,CAAC,OAAO,CAAC;IAc7G;;;;;;;;;2DASuD;IAChD,MAAM,CAAC,IAAI,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,WAAW,CAAA;KAAE,GAAG,cAAc,CAAC,mBAAmB,CAAC;CA0CpG"}
|
|
@@ -26,12 +26,18 @@ export class ApprovalsResource {
|
|
|
26
26
|
throw new APIError(404, "not_found", `no pending approval for session ${id}`);
|
|
27
27
|
}
|
|
28
28
|
/** GET /v1/approvals — pending checkpoints (operator-scoped; envelope key `pending`).
|
|
29
|
-
* NEVER returns the capability token. ⚠️ item createdAt/deadline are epoch MS.
|
|
29
|
+
* NEVER returns the capability token. ⚠️ item createdAt/deadline are epoch MS.
|
|
30
|
+
*
|
|
31
|
+
* 🔴 [2400] HITL-5 `opts.owner` —— **OPERATOR 语义**,不是过滤器(server
|
|
32
|
+
* `src/http/routes/approvals-assistant.ts:88-92`):调用方是 operator 时 `?owner=` 把队列切到**那个 owner**
|
|
33
|
+
* 的 scope(不传 = 全租户视图,这是本面与 per-user 的 `assistant.inbox` 的分野);调用方**不是** operator
|
|
34
|
+
* 时,server 无条件用它自己的 principal —— 传了也**静默无效**,绝不是越权入口。 */
|
|
30
35
|
async list(opts) {
|
|
31
36
|
// 🔴 BREAKING(clay 拍 2026-07-28,list() 归一):返回 wire 信封原样 `{pending}`,不再拆封——
|
|
32
37
|
// 全 SDK 规约=verbs 返回 wire body VERBATIM(拆封会丢未来 additive 元数据,且 13 个 list 站点
|
|
33
38
|
// 此前 7 信封 6 拆封各行其是)。迁移:`await approvals.list()` → `(await approvals.list()).pending`。
|
|
34
|
-
|
|
39
|
+
const q = opts?.owner ? `?owner=${encodeURIComponent(opts.owner)}` : ""; // 手拼(同 assistant.inbox 的既有拼法)
|
|
40
|
+
return this.t.request({ method: "GET", path: `/v1/approvals${q}`, signal: opts?.signal });
|
|
35
41
|
}
|
|
36
42
|
/** POST /v1/approvals/:sessionId/decide — resolve a suspend; the resumed run continues its stream.
|
|
37
43
|
* Not a submit → no SDK retry (a decide must not double-act).
|
|
@@ -83,20 +89,25 @@ export class ApprovalsResource {
|
|
|
83
89
|
throw e;
|
|
84
90
|
}
|
|
85
91
|
}
|
|
86
|
-
/** GET /v1/approvals/stream — native push (SSE delta, meta
|
|
87
|
-
* BFF-side polling of `list()`. LONG-LIVED
|
|
88
|
-
*
|
|
92
|
+
/** GET /v1/approvals/stream — native push (SSE delta, `meta.mode:"approvals-delta"`, service [83]). Replaces
|
|
93
|
+
* BFF-side polling of `list()`. LONG-LIVED: there is NO terminal event — this reconnects on drops /
|
|
94
|
+
* heartbeat-silence and tails on (uses `readSseFrames`, NOT `parseSse`, which would end on done/failed).
|
|
89
95
|
* A non-`ok` first response (e.g. 404 on a worker without the endpoint) throws → caller falls back to polling.
|
|
90
|
-
*
|
|
91
|
-
*
|
|
96
|
+
* Frame vocabulary + scoping: see {@link ApprovalStreamEvent} (six real `type` values, shape实核 2026-08-02)
|
|
97
|
+
* and {@link ApprovalsResource.list} for the operator `owner` semantics — `?owner=` is honored identically here
|
|
98
|
+
* (`routes/approvals-assistant.ts:81-86`).
|
|
99
|
+
* ⚠️ The server ends the stream itself at its 15-minute cap, announcing it with an `error` frame
|
|
100
|
+
* (`errorCode: "STREAM_MAX_DURATION"`); this loop simply reconnects — but a consumer that mirrors frames
|
|
101
|
+
* onward should not forward that one as a failure. */
|
|
92
102
|
async *stream(opts) {
|
|
93
103
|
let failures = 0;
|
|
104
|
+
const q = opts?.owner ? `?owner=${encodeURIComponent(opts.owner)}` : "";
|
|
94
105
|
for (;;) {
|
|
95
106
|
if (opts?.signal?.aborted)
|
|
96
107
|
return;
|
|
97
108
|
let res;
|
|
98
109
|
try {
|
|
99
|
-
const o = { method: "GET", path:
|
|
110
|
+
const o = { method: "GET", path: `/v1/approvals/stream${q}` };
|
|
100
111
|
if (opts?.signal)
|
|
101
112
|
o.signal = opts.signal;
|
|
102
113
|
res = await this.t.openStream(o);
|
|
@@ -111,13 +122,25 @@ export class ApprovalsResource {
|
|
|
111
122
|
throw await this.t.errorFrom(res); // 404/4xx → caller polls
|
|
112
123
|
try {
|
|
113
124
|
for await (const frame of readSseFrames(res, HEARTBEAT_GRACE_MS, opts?.signal)) {
|
|
114
|
-
|
|
125
|
+
// 🔴 [2400] CB-8:`!frame.data` **不是**在滤心跳 —— 这条流的心跳是真帧
|
|
126
|
+
// (`event: heartbeat\ndata: {"type":"heartbeat"}`,`routes/approvals-assistant.ts:675/694`),
|
|
127
|
+
// `data` 是非空串,所以它**照常被 yield**(`heartbeat` 是文档化的一个臂)。这一行挡的是没有
|
|
128
|
+
// `data` 行的帧(裸注释/协议噪声)。旧注释「heartbeat comment」两处都错。
|
|
115
129
|
if (!frame.data)
|
|
116
|
-
continue;
|
|
117
|
-
|
|
130
|
+
continue;
|
|
131
|
+
// 🔴 [2400] HITL-14:坏 JSON = **契约违约,上抛**(照 parseSse:85 形——同一个 SyntaxError 判别,
|
|
132
|
+
// 不靠文案分支)。此前它被下面那个裸 `catch` 吞掉,变成一次静默重连 —— 于是「对端在发我们解不了
|
|
133
|
+
// 的东西」这件事永远测不出来,消费方看到的只是一条一直在重连、一帧不出的流。
|
|
134
|
+
const ev = JSON.parse(frame.data); // SyntaxError = contract breach → rethrown below
|
|
135
|
+
// 🔴 [2400] HITL-14:`failures` 归零挪到**解析成功之后**。放在帧到达处 = 把「收到了看不懂的字节」
|
|
136
|
+
// 当成 progress,一条持续吐坏帧的流会把重连预算永远清零、无限空转。
|
|
137
|
+
failures = 0;
|
|
138
|
+
yield ev;
|
|
118
139
|
}
|
|
119
140
|
}
|
|
120
|
-
catch {
|
|
141
|
+
catch (e) {
|
|
142
|
+
if (e instanceof SyntaxError)
|
|
143
|
+
throw new Error(`approvals.stream: malformed event data (contract breach): ${e.message}`);
|
|
121
144
|
// mid-stream drop or heartbeat silence → reconnect (long-lived stream has no terminal event)
|
|
122
145
|
}
|
|
123
146
|
finally {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"approvals.js","sourceRoot":"","sources":["../../src/resources/approvals.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"approvals.js","sourceRoot":"","sources":["../../src/resources/approvals.ts"],"names":[],"mappings":"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"}
|
|
@@ -5,7 +5,17 @@
|
|
|
5
5
|
* SDK 服务端用, 不进浏览器/CLI。withPrincipal 自动重建本 resource —— BFF 的 sdk(principal).assistant.* 天然成立。
|
|
6
6
|
*
|
|
7
7
|
* 🔴 D-G 边界(§6): 这 5 个 verb **不需要**签名证明 —— 走 owner 门(principal header, transport 已注入 x-agent-principal)。
|
|
8
|
-
* 只 /decide 要签名(approvals.decide + BFF 签, 不在本 resource)。owner 非属 → 404(无存在性 oracle)不是 403。
|
|
8
|
+
* 只 /decide 要签名(approvals.decide + BFF 签, 不在本 resource)。owner 非属 → 404(无存在性 oracle)不是 403。
|
|
9
|
+
*
|
|
10
|
+
* 🔴 [2400] HITL-13 挂载前置 —— **先读 `capabilities().approvals`,别 trial-by-error**:
|
|
11
|
+
* server 的整条 `/v1/assistant/*` 车道与 `/v1/approvals` 共用同一个挂载条件,分支头逐字是
|
|
12
|
+
* `if (deps.checkpointStore && (url.startsWith("/v1/approvals") || url.startsWith("/v1/assistant")))`
|
|
13
|
+
* (`src/http/routes/approvals-assistant.ts`),而 `capabilities.approvals = Boolean(deps.checkpointStore)`
|
|
14
|
+
* (`routes/capabilities.ts:65`)—— 所以那一位就是本 resource 全部 5 个 verb 的挂载位,尽管名字只提 approvals。
|
|
15
|
+
* ⚠️ 名字窄、谓词宽:**别用 `capabilities.scheduler` 判本 resource**(那位说的是 host 腿的自唤醒 cron 工具,
|
|
16
|
+
* 与调度视图无关;web 曾按名字猜,在 local 部署形上永久渲「不可达」)。
|
|
17
|
+
* ⚠️ 没接 checkpointStore 的部署上,这条车道**根本不匹配**,请求落到域尾的 404 `not_found.route` —— 那是
|
|
18
|
+
* 「面不在」不是「东西没找到」;下面三个写 verb 各自另有更细的 501(见各条)。 */
|
|
9
19
|
import type { Transport } from "../transport.js";
|
|
10
20
|
import type { InboxRow, AssistantTask, PlanReviewRequest, AssistantTaskStatus } from "../types.js";
|
|
11
21
|
export declare class AssistantResource {
|
|
@@ -33,20 +43,27 @@ export declare class AssistantResource {
|
|
|
33
43
|
}>;
|
|
34
44
|
/** §4b POST /v1/assistant/tasks/:id/resume(:id = taskId)—— resource_limit CONTINUE。**无 body**。
|
|
35
45
|
* 非 submit → 不重试(一次决策不重放)。🔴 GATE-KIND GUARD: human/policy_ask 门 → 409 gate_not_resumable
|
|
36
|
-
* ("continue" 绝不绕过人审, 那条路是 /decide)。owner 非属 → 404。
|
|
46
|
+
* ("continue" 绝不绕过人审, 那条路是 /decide)。owner 非属 → 404。
|
|
47
|
+
* 🔴 [2400] HITL-13 前置:**checkpointStore 必须挂着** —— 先读 `capabilities().approvals`(见本文件顶注)。
|
|
48
|
+
* 另需 durable run store:无则 501 `capability.run_store_required`(`routes/approvals-assistant.ts:341`)。 */
|
|
37
49
|
resume(taskId: string, opts?: {
|
|
38
50
|
signal?: AbortSignal;
|
|
39
51
|
}): Promise<AssistantTaskStatus>;
|
|
40
52
|
/** §4c POST /v1/assistant/tasks/:id/plan_review(:id = taskId)—— PRE-ACTION plan_review 门的 3-state 决策。
|
|
41
53
|
* body = {decision, editedPlan?, reason?}。approve/edit/reject 全跑模型 → 计费。非 submit → 不重试。
|
|
42
54
|
* 🔴 GATE-KIND GUARD: 非 plan_review 门 → 409 gate_not_plan_review。400: 坏/缺 decision; edit 缺非空 editedPlan;
|
|
43
|
-
* approve/reject 带 editedPlan; reason 非串。owner 非属 → 404。
|
|
55
|
+
* approve/reject 带 editedPlan; reason 非串。owner 非属 → 404。
|
|
56
|
+
* 🔴 [2400] HITL-13 前置:同 {@link AssistantResource.resume} —— checkpointStore(先读 `capabilities().approvals`)
|
|
57
|
+
* + durable run store(无则 501 `capability.run_store_required`,`routes/approvals-assistant.ts:362`)。 */
|
|
44
58
|
planReview(taskId: string, req: PlanReviewRequest, opts?: {
|
|
45
59
|
signal?: AbortSignal;
|
|
46
60
|
}): Promise<AssistantTaskStatus>;
|
|
47
61
|
/** §4d POST /v1/assistant/tasks/:id/preempt(:id = taskId)—— 优雅 YIELD(跨副本让位, 与 runs.cancel 的 kill 相反)。
|
|
48
62
|
* **无 body**。202 {status}(terminal → 202 no-op)。非 submit → 不重试。NOT billable。
|
|
49
|
-
* suspended → 409
|
|
63
|
+
* suspended → 409 `conflict.already_suspended`; owner 非属 → 404。
|
|
64
|
+
* 🔴 [2400] HITL-13 前置:本 verb 的 501 是**两与** —— `RESOURCE_SUSPEND=true` **且** checkpointStore 挂着
|
|
65
|
+
* (`routes/approvals-assistant.ts:297`,`feature.preemption_disabled`;缺 run store 另有
|
|
66
|
+
* `capability.run_store_required`)。先读 `capabilities().approvals` 判 store 那一半(见本文件顶注)。 */
|
|
50
67
|
preempt(taskId: string, opts?: {
|
|
51
68
|
signal?: AbortSignal;
|
|
52
69
|
}): Promise<AssistantTaskStatus>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"assistant.d.ts","sourceRoot":"","sources":["../../src/resources/assistant.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"assistant.d.ts","sourceRoot":"","sources":["../../src/resources/assistant.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;kDAiBkD;AAClD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AACjD,OAAO,KAAK,EAAE,QAAQ,EAAE,aAAa,EAAiB,iBAAiB,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAyBlH,qBAAa,iBAAiB;IAChB,OAAO,CAAC,QAAQ,CAAC,CAAC;gBAAD,CAAC,EAAE,SAAS;IAEzC;;wGAEoG;IAC9F,KAAK,CAAC,IAAI,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,WAAW,CAAA;KAAE,GAAG,OAAO,CAAC;QAAE,KAAK,EAAE,QAAQ,EAAE,CAAA;KAAE,CAAC;IAU5F;;;;sFAIkF;IAC5E,KAAK,CAAC,IAAI,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,WAAW,CAAA;KAAE,GAAG,OAAO,CAAC;QAAE,KAAK,EAAE,aAAa,EAAE,CAAA;KAAE,CAAC;IAiBjG;;;;4GAIwG;IAClG,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,WAAW,CAAA;KAAE,GAAG,OAAO,CAAC,mBAAmB,CAAC;IAQ3F;;;;;2GAKuG;IACjG,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,iBAAiB,EAAE,IAAI,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,WAAW,CAAA;KAAE,GAAG,OAAO,CAAC,mBAAmB,CAAC;IASvH;;;;;8FAK0F;IACpF,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,WAAW,CAAA;KAAE,GAAG,OAAO,CAAC,mBAAmB,CAAC;CAO7F"}
|
|
@@ -50,7 +50,9 @@ export class AssistantResource {
|
|
|
50
50
|
}
|
|
51
51
|
/** §4b POST /v1/assistant/tasks/:id/resume(:id = taskId)—— resource_limit CONTINUE。**无 body**。
|
|
52
52
|
* 非 submit → 不重试(一次决策不重放)。🔴 GATE-KIND GUARD: human/policy_ask 门 → 409 gate_not_resumable
|
|
53
|
-
* ("continue" 绝不绕过人审, 那条路是 /decide)。owner 非属 → 404。
|
|
53
|
+
* ("continue" 绝不绕过人审, 那条路是 /decide)。owner 非属 → 404。
|
|
54
|
+
* 🔴 [2400] HITL-13 前置:**checkpointStore 必须挂着** —— 先读 `capabilities().approvals`(见本文件顶注)。
|
|
55
|
+
* 另需 durable run store:无则 501 `capability.run_store_required`(`routes/approvals-assistant.ts:341`)。 */
|
|
54
56
|
async resume(taskId, opts) {
|
|
55
57
|
return this.t.request({
|
|
56
58
|
method: "POST",
|
|
@@ -61,7 +63,9 @@ export class AssistantResource {
|
|
|
61
63
|
/** §4c POST /v1/assistant/tasks/:id/plan_review(:id = taskId)—— PRE-ACTION plan_review 门的 3-state 决策。
|
|
62
64
|
* body = {decision, editedPlan?, reason?}。approve/edit/reject 全跑模型 → 计费。非 submit → 不重试。
|
|
63
65
|
* 🔴 GATE-KIND GUARD: 非 plan_review 门 → 409 gate_not_plan_review。400: 坏/缺 decision; edit 缺非空 editedPlan;
|
|
64
|
-
* approve/reject 带 editedPlan; reason 非串。owner 非属 → 404。
|
|
66
|
+
* approve/reject 带 editedPlan; reason 非串。owner 非属 → 404。
|
|
67
|
+
* 🔴 [2400] HITL-13 前置:同 {@link AssistantResource.resume} —— checkpointStore(先读 `capabilities().approvals`)
|
|
68
|
+
* + durable run store(无则 501 `capability.run_store_required`,`routes/approvals-assistant.ts:362`)。 */
|
|
65
69
|
async planReview(taskId, req, opts) {
|
|
66
70
|
return this.t.request({
|
|
67
71
|
method: "POST",
|
|
@@ -72,7 +76,10 @@ export class AssistantResource {
|
|
|
72
76
|
}
|
|
73
77
|
/** §4d POST /v1/assistant/tasks/:id/preempt(:id = taskId)—— 优雅 YIELD(跨副本让位, 与 runs.cancel 的 kill 相反)。
|
|
74
78
|
* **无 body**。202 {status}(terminal → 202 no-op)。非 submit → 不重试。NOT billable。
|
|
75
|
-
* suspended → 409
|
|
79
|
+
* suspended → 409 `conflict.already_suspended`; owner 非属 → 404。
|
|
80
|
+
* 🔴 [2400] HITL-13 前置:本 verb 的 501 是**两与** —— `RESOURCE_SUSPEND=true` **且** checkpointStore 挂着
|
|
81
|
+
* (`routes/approvals-assistant.ts:297`,`feature.preemption_disabled`;缺 run store 另有
|
|
82
|
+
* `capability.run_store_required`)。先读 `capabilities().approvals` 判 store 那一半(见本文件顶注)。 */
|
|
76
83
|
async preempt(taskId, opts) {
|
|
77
84
|
return this.t.request({
|
|
78
85
|
method: "POST",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"assistant.js","sourceRoot":"","sources":["../../src/resources/assistant.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"assistant.js","sourceRoot":"","sources":["../../src/resources/assistant.ts"],"names":[],"mappings":"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"}
|
|
@@ -9,8 +9,15 @@
|
|
|
9
9
|
* 单任务 ≤16 个 id → 提交时 400。
|
|
10
10
|
* - mime:客户端自述(不可验证,非安全边界);部署配了 allowlist 时不合 → 415
|
|
11
11
|
* `attachment.mime_not_allowed`(响应 `allowed` 列出允许集)。
|
|
12
|
-
* -
|
|
13
|
-
*
|
|
12
|
+
* - 文件名:**一半消毒、一半拒收**(4.3.0 更正,FW-13 —— 此前这里整句写的是「消毒」,对字符集不成立)。
|
|
13
|
+
* server `routes/attachments.ts:52-56` 的真序是:① 先按 `/[/\\]/` 取**末段**(穿越形路径确实被压成末段
|
|
14
|
+
* = 这一半是真消毒)→ ② 再 `.slice(0,128)` 截长 → ③ 然后
|
|
15
|
+
* `!/^[A-Za-z0-9][A-Za-z0-9._-]*$/.test(base)` ⇒ **400 `request.query_invalid` 拒收**,**不是**把非法字符
|
|
16
|
+
* 替换掉。(`sanitizePathComponent` 在这一行之后,server 自注「不合法=上面已 400,这里恒过」= 双保险,
|
|
17
|
+
* 不承担消毒职责。)
|
|
18
|
+
* ⇒ `季度报告.pdf`、`my report.pdf`(带空格)这类名字会 **400**。因为老文案说「server 会消毒」,消费方
|
|
19
|
+
* 不会在客户端先做规范化,这个 400 会一路暴露给终端用户。**请在上传前自行规范化文件名**;
|
|
20
|
+
* 响应里的 `name` 是①②之后的真名(物化路径用它)。
|
|
14
21
|
* - owner 门无 oracle:他人/未知 id 一律 404。
|
|
15
22
|
* - 生命周期:上传后**从未被任何 task 引用**的附件按部署 TTL(缺省 24h)收割——上传后尽快提交;
|
|
16
23
|
* 绑定后随会话 E21 删除级联。
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"attachments.d.ts","sourceRoot":"","sources":["../../src/resources/attachments.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"attachments.d.ts","sourceRoot":"","sources":["../../src/resources/attachments.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAEjD,+CAA+C;AAC/C,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,MAAM,CAAC;IACX,yEAAyE;IACzE,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,qBAAa,mBAAmB;IAClB,OAAO,CAAC,QAAQ,CAAC,CAAC;gBAAD,CAAC,EAAE,SAAS;IAEzC;wEACoE;IAC9D,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,UAAU,EAAE,IAAI,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,WAAW,CAAA;KAAE,GAAG,OAAO,CAAC,cAAc,CAAC;IAYtH,uFAAuF;IACjF,GAAG,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,WAAW,CAAA;KAAE,GAAG,OAAO,CAAC;QAAE,KAAK,EAAE,UAAU,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;IAWpG,mEAAmE;IAC7D,MAAM,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,WAAW,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC;CASzE"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"attachments.js","sourceRoot":"","sources":["../../src/resources/attachments.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"attachments.js","sourceRoot":"","sources":["../../src/resources/attachments.ts"],"names":[],"mappings":"AAqCA,MAAM,OAAO,mBAAmB;IACD;IAA7B,YAA6B,CAAY;QAAZ,MAAC,GAAD,CAAC,CAAW;IAAG,CAAC;IAE7C;wEACoE;IACpE,KAAK,CAAC,MAAM,CAAC,IAAY,EAAE,KAAiB,EAAE,IAA8C;QAC1F,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC;YAC/B,MAAM,EAAE,MAAM;YACd,IAAI,EAAE,wBAAwB,kBAAkB,CAAC,IAAI,CAAC,EAAE;YACxD,OAAO,EAAE,KAAK;YACd,WAAW,EAAE,IAAI,EAAE,IAAI,IAAI,0BAA0B;YACrD,GAAG,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SACjD,CAAC,CAAC;QACH,IAAI,CAAC,GAAG,CAAC,EAAE;YAAE,MAAM,MAAM,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;QAC/C,OAAO,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAAmB,CAAC;IAC9C,CAAC;IAED,uFAAuF;IACvF,KAAK,CAAC,GAAG,CAAC,EAAU,EAAE,IAA+B;QACnD,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC;YAC/B,MAAM,EAAE,KAAK;YACb,IAAI,EAAE,mBAAmB,kBAAkB,CAAC,EAAE,CAAC,EAAE;YACjD,MAAM,EAAE,KAAK;YACb,GAAG,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SACjD,CAAC,CAAC;QACH,IAAI,CAAC,GAAG,CAAC,EAAE;YAAE,MAAM,MAAM,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;QAC/C,OAAO,EAAE,KAAK,EAAE,IAAI,UAAU,CAAC,MAAM,GAAG,CAAC,WAAW,EAAE,CAAC,EAAE,IAAI,EAAE,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,IAAI,0BAA0B,EAAE,CAAC;IACjI,CAAC;IAED,mEAAmE;IACnE,KAAK,CAAC,MAAM,CAAC,EAAU,EAAE,IAA+B;QACtD,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC;YAC/B,MAAM,EAAE,QAAQ;YAChB,IAAI,EAAE,mBAAmB,kBAAkB,CAAC,EAAE,CAAC,EAAE;YACjD,GAAG,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SACjD,CAAC,CAAC;QACH,IAAI,GAAG,CAAC,MAAM,KAAK,GAAG;YAAE,OAAO;QAC/B,MAAM,MAAM,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;IACpC,CAAC;CACF"}
|
|
@@ -26,7 +26,16 @@ export declare class ControlSecretsResource {
|
|
|
26
26
|
* 🔴 The `value` goes up in the body ONCE and is NEVER returned/logged (I1) — the result carries only `name`
|
|
27
27
|
* + advisory next-steps. A collision with a DIFFERENT existing value → 409 ControlConflictError unless
|
|
28
28
|
* `overwrite`. publisher+. NOT submit-class (no idempotency key — a re-PUT of the same name/value is a
|
|
29
|
-
* server-side no-op; a key would not change the value-overwrite semantics).
|
|
29
|
+
* server-side no-op; a key would not change the value-overwrite semantics).
|
|
30
|
+
*
|
|
31
|
+
* 🔴 **`value` 不能含换行 —— registry 直接拒**(4.3.0 补,RC-10;此前这里对 value 的字符集零文档)。
|
|
32
|
+
* 这不是推测:sema-server 已经为它建了规避形并把理由写在码里(`src/config.ts:410-412` 逐字:
|
|
33
|
+
* 「A PEM key is multi-line, but **sema-registry's `POST /api/config/secrets` rejects newlines** — so let the
|
|
34
|
+
* value arrive base64-encoded (the recommended self-serve form) or with escaped `\n`, and reconstruct the real
|
|
35
|
+
* PEM here」,实现即 `normalizeSshPrivateKey`,`:414-425`)。
|
|
36
|
+
* ⇒ 多行密钥(PEM / SSH 私钥 / 证书链)**请先 base64 编码再送**(上游推荐的自助形),或送转义过的 `\n`;
|
|
37
|
+
* 消费端在使用处还原。直接 `set({name:"SSH_KEY", value: pemString})` 会拿到 400 ⇒ `ControlValidationError`,
|
|
38
|
+
* 而在这段话存在之前,操作者只能自己再踩一遍 server 早就写进注释的坑。 */
|
|
30
39
|
set(body: {
|
|
31
40
|
name: string;
|
|
32
41
|
value: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"secrets.d.ts","sourceRoot":"","sources":["../../../src/resources/control/secrets.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;6CAY6C;AAC7C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AACpD,OAAO,KAAK,EACV,eAAe,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,gBAAgB,EAC7F,MAAM,wBAAwB,CAAC;AAEhC,qBAAa,sBAAsB;IACrB,OAAO,CAAC,QAAQ,CAAC,CAAC;gBAAD,CAAC,EAAE,SAAS;IAEzC;qGACiG;IAC3F,SAAS,CAAC,IAAI,CAAC,EAAE;QAAE,OAAO,CAAC,EAAE,OAAO,CAAC;QAAC,MAAM,CAAC,EAAE,WAAW,CAAA;KAAE,GAAG,OAAO,CAAC,eAAe,CAAC;IAK7F
|
|
1
|
+
{"version":3,"file":"secrets.d.ts","sourceRoot":"","sources":["../../../src/resources/control/secrets.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;6CAY6C;AAC7C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AACpD,OAAO,KAAK,EACV,eAAe,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,gBAAgB,EAC7F,MAAM,wBAAwB,CAAC;AAEhC,qBAAa,sBAAsB;IACrB,OAAO,CAAC,QAAQ,CAAC,CAAC;gBAAD,CAAC,EAAE,SAAS;IAEzC;qGACiG;IAC3F,SAAS,CAAC,IAAI,CAAC,EAAE;QAAE,OAAO,CAAC,EAAE,OAAO,CAAC;QAAC,MAAM,CAAC,EAAE,WAAW,CAAA;KAAE,GAAG,OAAO,CAAC,eAAe,CAAC;IAK7F;;;;;;;;;;;;;iDAa6C;IACvC,GAAG,CAAC,IAAI,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,SAAS,CAAC,EAAE,OAAO,CAAC;QAAC,MAAM,CAAC,EAAE,WAAW,CAAA;KAAE,GAAG,OAAO,CAAC,iBAAiB,CAAC;IAOvH;;uFAEmF;IAC7E,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,WAAW,CAAA;KAAE,GAAG,OAAO,CAAC,kBAAkB,CAAC;IAIxF;;2DAEuD;IACjD,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,OAAO,CAAC;QAAC,MAAM,CAAC,EAAE,WAAW,CAAA;KAAE,GAAG,OAAO,CAAC,kBAAkB,CAAC;IAKzG;4GACwG;IAClG,IAAI,CAAC,IAAI,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,WAAW,CAAA;KAAE,GAAG,OAAO,CAAC,gBAAgB,CAAC;CAGvE"}
|
|
@@ -13,7 +13,16 @@ export class ControlSecretsResource {
|
|
|
13
13
|
* 🔴 The `value` goes up in the body ONCE and is NEVER returned/logged (I1) — the result carries only `name`
|
|
14
14
|
* + advisory next-steps. A collision with a DIFFERENT existing value → 409 ControlConflictError unless
|
|
15
15
|
* `overwrite`. publisher+. NOT submit-class (no idempotency key — a re-PUT of the same name/value is a
|
|
16
|
-
* server-side no-op; a key would not change the value-overwrite semantics).
|
|
16
|
+
* server-side no-op; a key would not change the value-overwrite semantics).
|
|
17
|
+
*
|
|
18
|
+
* 🔴 **`value` 不能含换行 —— registry 直接拒**(4.3.0 补,RC-10;此前这里对 value 的字符集零文档)。
|
|
19
|
+
* 这不是推测:sema-server 已经为它建了规避形并把理由写在码里(`src/config.ts:410-412` 逐字:
|
|
20
|
+
* 「A PEM key is multi-line, but **sema-registry's `POST /api/config/secrets` rejects newlines** — so let the
|
|
21
|
+
* value arrive base64-encoded (the recommended self-serve form) or with escaped `\n`, and reconstruct the real
|
|
22
|
+
* PEM here」,实现即 `normalizeSshPrivateKey`,`:414-425`)。
|
|
23
|
+
* ⇒ 多行密钥(PEM / SSH 私钥 / 证书链)**请先 base64 编码再送**(上游推荐的自助形),或送转义过的 `\n`;
|
|
24
|
+
* 消费端在使用处还原。直接 `set({name:"SSH_KEY", value: pemString})` 会拿到 400 ⇒ `ControlValidationError`,
|
|
25
|
+
* 而在这段话存在之前,操作者只能自己再踩一遍 server 早就写进注释的坑。 */
|
|
17
26
|
async set(body) {
|
|
18
27
|
const { signal, overwrite, name, value } = body;
|
|
19
28
|
const qs = overwrite ? "?overwrite=true" : "";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"secrets.js","sourceRoot":"","sources":["../../../src/resources/control/secrets.ts"],"names":[],"mappings":"AAkBA,MAAM,OAAO,sBAAsB;IACJ;IAA7B,YAA6B,CAAY;QAAZ,MAAC,GAAD,CAAC,CAAW;IAAG,CAAC;IAE7C;qGACiG;IACjG,KAAK,CAAC,SAAS,CAAC,IAAkD;QAChE,MAAM,EAAE,GAAG,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,EAAE,CAAC;QAChD,OAAO,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,sBAAsB,EAAE,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC;IACnG,CAAC;IAED
|
|
1
|
+
{"version":3,"file":"secrets.js","sourceRoot":"","sources":["../../../src/resources/control/secrets.ts"],"names":[],"mappings":"AAkBA,MAAM,OAAO,sBAAsB;IACJ;IAA7B,YAA6B,CAAY;QAAZ,MAAC,GAAD,CAAC,CAAW;IAAG,CAAC;IAE7C;qGACiG;IACjG,KAAK,CAAC,SAAS,CAAC,IAAkD;QAChE,MAAM,EAAE,GAAG,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,EAAE,CAAC;QAChD,OAAO,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,sBAAsB,EAAE,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC;IACnG,CAAC;IAED;;;;;;;;;;;;;iDAa6C;IAC7C,KAAK,CAAC,GAAG,CAAC,IAAgF;QACxF,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,IAAI,CAAC;QAChD,MAAM,EAAE,GAAG,SAAS,CAAC,CAAC,CAAC,iBAAiB,CAAC,CAAC,CAAC,EAAE,CAAC;QAC9C,mEAAmE;QACnE,OAAO,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,sBAAsB,EAAE,EAAE,EAAE,IAAI,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC;IAC7G,CAAC;IAED;;uFAEmF;IACnF,KAAK,CAAC,MAAM,CAAC,IAAY,EAAE,IAA+B;QACxD,OAAO,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,uBAAuB,kBAAkB,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,EAAE,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC;IAC5I,CAAC;IAED;;2DAEuD;IACvD,KAAK,CAAC,MAAM,CAAC,IAAY,EAAE,IAAgD;QACzE,MAAM,EAAE,GAAG,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,EAAE,CAAC;QAC5C,OAAO,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,uBAAuB,kBAAkB,CAAC,IAAI,CAAC,GAAG,EAAE,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC;IAClI,CAAC;IAED;4GACwG;IACxG,KAAK,CAAC,IAAI,CAAC,IAA+B;QACxC,OAAO,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,0BAA0B,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC;IACnG,CAAC;CACF"}
|
|
@@ -27,7 +27,9 @@
|
|
|
27
27
|
* agnostic `readSseFrames` (NOT `parseSse`, which is hardcoded to the AgentEvent union + auto-reconnect).
|
|
28
28
|
* Gated off (no `fleetBus` wired) → 501 (typed error) before any frame.
|
|
29
29
|
*
|
|
30
|
-
* Verified against
|
|
30
|
+
* Verified against sema-server **5.3.0** (2026-08-02 亲读): handler `streamFleet` (`src/http/routes/fleet.ts`)
|
|
31
|
+
* + `src/fleet/fleet-bus.ts` types. (4.3.0 坐标刷新:此前钉的是 commit `1bf7a5c`,在 server 仓已不可定位为
|
|
32
|
+
* 近期点 —— 版本号比 commit 短哈希更能被下一个人重放。)
|
|
31
33
|
*/
|
|
32
34
|
import type { Transport } from "../transport.js";
|
|
33
35
|
/** The fleet vocabulary the shell renders (MF-Fleet `FleetTask.status`, byte-aligned to service `FleetTaskStatus`
|
|
@@ -146,8 +148,12 @@ export interface FleetWorkflowRow {
|
|
|
146
148
|
* - `task_remove` — the task row left the active set (terminal + swept) → delete `id` from the Map.
|
|
147
149
|
* - `workflow` — a single workflow-row UPSERT (FULL row) → replace by `row.id`.
|
|
148
150
|
* - `workflow_remove` — the workflow row left the active set → delete `id`.
|
|
149
|
-
* OPEN set — branch on `type`, ignore an unknown future frame
|
|
150
|
-
*
|
|
151
|
+
* OPEN set — branch on `type`, ignore an unknown future frame.
|
|
152
|
+
* 🔴 [2400] CB-8/CB-9 keep-alive 真形:fleet 的心跳是**命名真帧** `event: heartbeat\ndata: {}` 每 **15s**
|
|
153
|
+
* (server `routes/fleet.ts:223` — `setInterval(…, 15_000)`),NOT a bare `: hb` comment line (that shape belongs
|
|
154
|
+
* to `GET /v1/sessions/:id/events` alone, `routes/sessions.ts:359`, and beats at a tunable ~25s). The reader
|
|
155
|
+
* swallows it by NAME (`frame.event === "heartbeat"`), so it is never yielded — a `!frame.data` test alone would
|
|
156
|
+
* NOT catch it (`data` is the non-empty string `"{}"`).
|
|
151
157
|
*/
|
|
152
158
|
export type FleetFrame = {
|
|
153
159
|
type: "meta";
|
|
@@ -157,7 +163,6 @@ export type FleetFrame = {
|
|
|
157
163
|
sessionScoped?: boolean;
|
|
158
164
|
/** [1833] G2:bg 通知投递姿态恒 fail-closed 的如实自述(server 恒 true;老版缺席)。 */
|
|
159
165
|
bgNotifyFailClosed?: boolean;
|
|
160
|
-
ts?: number;
|
|
161
166
|
} | {
|
|
162
167
|
type: "snapshot";
|
|
163
168
|
tasks: FleetTaskRow[];
|
|
@@ -288,7 +293,8 @@ export declare class FleetResource {
|
|
|
288
293
|
*
|
|
289
294
|
* Emit order: `meta` (`{version, scoped}`) → `snapshot` (full visible set) → then a `task`/`workflow` upsert
|
|
290
295
|
* per transition + `task_remove`/`workflow_remove` per departure. Each `task`/`workflow` frame is the POST-MERGE
|
|
291
|
-
* FULL row (NOT a sparse patch) → replace by `row.id`.
|
|
296
|
+
* FULL row (NOT a sparse patch) → replace by `row.id`. The named `heartbeat` frames (real frames @15s, not
|
|
297
|
+
* `:`-comments — see the FleetFrame header) are swallowed by name and never yielded.
|
|
292
298
|
*
|
|
293
299
|
* 🔁 SNAPSHOT-RESUME: a drop ends the generator and re-calling IS the resume — the opening `snapshot` frame
|
|
294
300
|
* carries the complete visible state (no last-event-id cursor exists or is needed; see the module header).
|