@sema-agent/sdk 0.0.75 → 0.0.77
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/client.d.ts +48 -0
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +55 -2
- package/dist/client.js.map +1 -1
- package/dist/control-client.d.ts +21 -0
- package/dist/control-client.d.ts.map +1 -1
- package/dist/control-client.js +42 -1
- package/dist/control-client.js.map +1 -1
- package/dist/control-types.d.ts +108 -0
- package/dist/control-types.d.ts.map +1 -1
- package/dist/control-types.js +15 -0
- package/dist/control-types.js.map +1 -1
- package/dist/errors.d.ts +88 -2
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +105 -8
- package/dist/errors.js.map +1 -1
- package/dist/events.d.ts +214 -20
- package/dist/events.d.ts.map +1 -1
- package/dist/events.js +5 -0
- package/dist/events.js.map +1 -1
- package/dist/health.d.ts +44 -0
- package/dist/health.d.ts.map +1 -1
- package/dist/health.js +32 -0
- package/dist/health.js.map +1 -1
- package/dist/idempotency.d.ts +8 -0
- package/dist/idempotency.d.ts.map +1 -1
- package/dist/idempotency.js +8 -0
- package/dist/idempotency.js.map +1 -1
- package/dist/index.d.ts +19 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +13 -0
- package/dist/index.js.map +1 -1
- package/dist/resources/approvals.d.ts +43 -0
- package/dist/resources/approvals.d.ts.map +1 -1
- package/dist/resources/approvals.js +23 -3
- package/dist/resources/approvals.js.map +1 -1
- package/dist/resources/assistant.d.ts +23 -0
- package/dist/resources/assistant.d.ts.map +1 -1
- package/dist/resources/assistant.js +22 -0
- package/dist/resources/assistant.js.map +1 -1
- package/dist/resources/control/auth-providers.d.ts +17 -0
- package/dist/resources/control/auth-providers.d.ts.map +1 -1
- package/dist/resources/control/auth-providers.js +6 -0
- package/dist/resources/control/auth-providers.js.map +1 -1
- package/dist/resources/control/config.d.ts +22 -0
- package/dist/resources/control/config.d.ts.map +1 -1
- package/dist/resources/control/config.js +12 -0
- package/dist/resources/control/config.js.map +1 -1
- package/dist/resources/control/fleet.d.ts +15 -0
- package/dist/resources/control/fleet.d.ts.map +1 -1
- package/dist/resources/control/fleet.js +8 -0
- package/dist/resources/control/fleet.js.map +1 -1
- package/dist/resources/control/images.d.ts +20 -0
- package/dist/resources/control/images.d.ts.map +1 -1
- package/dist/resources/control/images.js +10 -0
- package/dist/resources/control/images.js.map +1 -1
- package/dist/resources/control/lifecycle.d.ts +8 -0
- package/dist/resources/control/lifecycle.d.ts.map +1 -1
- package/dist/resources/control/lifecycle.js +3 -0
- package/dist/resources/control/lifecycle.js.map +1 -1
- package/dist/resources/control/publish.d.ts +12 -0
- package/dist/resources/control/publish.d.ts.map +1 -1
- package/dist/resources/control/publish.js +6 -0
- package/dist/resources/control/publish.js.map +1 -1
- package/dist/resources/control/secrets.d.ts +28 -0
- package/dist/resources/control/secrets.d.ts.map +1 -1
- package/dist/resources/control/secrets.js +16 -0
- package/dist/resources/control/secrets.js.map +1 -1
- package/dist/resources/control/users.d.ts +22 -0
- package/dist/resources/control/users.d.ts.map +1 -1
- package/dist/resources/control/users.js +12 -0
- package/dist/resources/control/users.js.map +1 -1
- package/dist/resources/control/versioning.d.ts +12 -0
- package/dist/resources/control/versioning.d.ts.map +1 -1
- package/dist/resources/control/versioning.js +6 -0
- package/dist/resources/control/versioning.js.map +1 -1
- package/dist/resources/control/workers.d.ts +14 -0
- package/dist/resources/control/workers.d.ts.map +1 -1
- package/dist/resources/control/workers.js +7 -0
- package/dist/resources/control/workers.js.map +1 -1
- package/dist/resources/elicitations.d.ts +43 -0
- package/dist/resources/elicitations.d.ts.map +1 -1
- package/dist/resources/elicitations.js +8 -0
- package/dist/resources/elicitations.js.map +1 -1
- package/dist/resources/fleet.d.ts +101 -0
- package/dist/resources/fleet.d.ts.map +1 -1
- package/dist/resources/fleet.js +27 -4
- package/dist/resources/fleet.js.map +1 -1
- package/dist/resources/images.d.ts +34 -0
- package/dist/resources/images.d.ts.map +1 -1
- package/dist/resources/images.js +29 -3
- package/dist/resources/images.js.map +1 -1
- package/dist/resources/leader.d.ts +10 -0
- package/dist/resources/leader.d.ts.map +1 -1
- package/dist/resources/leader.js +4 -0
- package/dist/resources/leader.js.map +1 -1
- package/dist/resources/memory.d.ts +37 -0
- package/dist/resources/memory.d.ts.map +1 -1
- package/dist/resources/memory.js +28 -0
- package/dist/resources/memory.js.map +1 -1
- package/dist/resources/models.d.ts +12 -0
- package/dist/resources/models.d.ts.map +1 -1
- package/dist/resources/models.js +4 -0
- package/dist/resources/models.js.map +1 -1
- package/dist/resources/ops.d.ts +16 -0
- package/dist/resources/ops.d.ts.map +1 -1
- package/dist/resources/ops.js +6 -0
- package/dist/resources/ops.js.map +1 -1
- package/dist/resources/policy.d.ts +8 -0
- package/dist/resources/policy.d.ts.map +1 -1
- package/dist/resources/policy.js +1 -0
- package/dist/resources/policy.js.map +1 -1
- package/dist/resources/questions.d.ts +57 -0
- package/dist/resources/questions.d.ts.map +1 -1
- package/dist/resources/questions.js +9 -0
- package/dist/resources/questions.js.map +1 -1
- package/dist/resources/runs.d.ts +147 -0
- package/dist/resources/runs.d.ts.map +1 -1
- package/dist/resources/runs.js +129 -2
- package/dist/resources/runs.js.map +1 -1
- package/dist/resources/session-sync.d.ts +61 -0
- package/dist/resources/session-sync.d.ts.map +1 -1
- package/dist/resources/session-sync.js +54 -1
- package/dist/resources/session-sync.js.map +1 -1
- package/dist/resources/sessions.d.ts +74 -0
- package/dist/resources/sessions.d.ts.map +1 -1
- package/dist/resources/sessions.js +64 -2
- package/dist/resources/sessions.js.map +1 -1
- package/dist/resources/side-query.d.ts +18 -0
- package/dist/resources/side-query.d.ts.map +1 -1
- package/dist/resources/side-query.js +1 -0
- package/dist/resources/side-query.js.map +1 -1
- package/dist/resources/tasks.d.ts +19 -0
- package/dist/resources/tasks.d.ts.map +1 -1
- package/dist/resources/tasks.js +21 -2
- package/dist/resources/tasks.js.map +1 -1
- package/dist/resources/tool-approvals.d.ts +60 -0
- package/dist/resources/tool-approvals.d.ts.map +1 -1
- package/dist/resources/tool-approvals.js +10 -0
- package/dist/resources/tool-approvals.js.map +1 -1
- package/dist/resources/trace.d.ts +23 -0
- package/dist/resources/trace.d.ts.map +1 -1
- package/dist/resources/trace.js +27 -2
- package/dist/resources/trace.js.map +1 -1
- package/dist/resources/usage.d.ts +21 -0
- package/dist/resources/usage.d.ts.map +1 -1
- package/dist/resources/usage.js +8 -0
- package/dist/resources/usage.js.map +1 -1
- package/dist/resources/workflows.d.ts +48 -0
- package/dist/resources/workflows.d.ts.map +1 -1
- package/dist/resources/workflows.js +40 -3
- package/dist/resources/workflows.js.map +1 -1
- package/dist/settings.d.ts +90 -0
- package/dist/settings.d.ts.map +1 -1
- package/dist/settings.js +24 -0
- package/dist/settings.js.map +1 -1
- package/dist/sse.d.ts +36 -0
- package/dist/sse.d.ts.map +1 -1
- package/dist/sse.js +53 -8
- package/dist/sse.js.map +1 -1
- package/dist/sync.d.ts +56 -0
- package/dist/sync.d.ts.map +1 -1
- package/dist/sync.js +48 -4
- package/dist/sync.js.map +1 -1
- package/dist/transport.d.ts +32 -0
- package/dist/transport.d.ts.map +1 -1
- package/dist/transport.js +40 -8
- package/dist/transport.js.map +1 -1
- package/dist/types.d.ts +709 -1
- package/dist/types.d.ts.map +1 -1
- package/package.json +1 -1
|
@@ -1,25 +1,53 @@
|
|
|
1
|
+
/** control.secrets — worker app-secret write-through + inventory + batch-rotate + reclaim. Backend: sema-registry
|
|
2
|
+
* GET/POST /api/config/secrets, DELETE /api/config/secrets/<name>, POST /api/config/secrets/<name>/rotate,
|
|
3
|
+
* GET /api/config/secrets/refs.
|
|
4
|
+
*
|
|
5
|
+
* 🔴 INVARIANT I1 (registry-enforced AND mirrored here): a secret VALUE is never persisted, returned, logged, or
|
|
6
|
+
* audited — only the NAME. There is NO value-read endpoint by design. The SDK upholds it structurally:
|
|
7
|
+
* - set() sends the value ONCE (in the request body) and the result type carries NO value field.
|
|
8
|
+
* - The value is NEVER placed in a URL/query/log; the result echoes only the name + advisory next-steps.
|
|
9
|
+
* - inventory()/rotate()/delete()/refs() touch NAMES only.
|
|
10
|
+
*
|
|
11
|
+
* inventory/set/rotate/delete are publisher+ (injecting/recreating credentials). refs() is admin. A name a
|
|
12
|
+
* worker references → 409 on delete unless force (ControlConflictError); a write colliding with a DIFFERENT
|
|
13
|
+
* existing value → 409 unless overwrite. */
|
|
1
14
|
import type { Transport } from "../../transport.js";
|
|
2
15
|
import type { SecretInventory, SecretWriteResult, SecretRotateResult, SecretDeleteResult, SecretRefsResult } from "../../control-types.js";
|
|
3
16
|
export declare class ControlSecretsResource {
|
|
4
17
|
private readonly t;
|
|
5
18
|
constructor(t: Transport);
|
|
19
|
+
/** GET /api/config/secrets[?orphans=true] → the env-NAMEs in the secret source (NEVER values), each tagged
|
|
20
|
+
* referenced/orphan. `orphans` returns only the unreferenced (reclaimable) ones. publisher+. */
|
|
6
21
|
inventory(opts?: {
|
|
7
22
|
orphans?: boolean;
|
|
8
23
|
signal?: AbortSignal;
|
|
9
24
|
}): Promise<SecretInventory>;
|
|
25
|
+
/** POST /api/config/secrets {name, value} → write-through ONE secret value to the orchestrator secret source.
|
|
26
|
+
* 🔴 The `value` goes up in the body ONCE and is NEVER returned/logged (I1) — the result carries only `name`
|
|
27
|
+
* + advisory next-steps. A collision with a DIFFERENT existing value → 409 ControlConflictError unless
|
|
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). */
|
|
10
30
|
set(body: {
|
|
11
31
|
name: string;
|
|
12
32
|
value: string;
|
|
13
33
|
overwrite?: boolean;
|
|
14
34
|
signal?: AbortSignal;
|
|
15
35
|
}): Promise<SecretWriteResult>;
|
|
36
|
+
/** POST /api/config/secrets/<name>/rotate → draft a recreate of EVERY worker referencing this env-NAME (one
|
|
37
|
+
* atomic draft; publish to apply). `workers:[]` (200) when nothing references it — not an error. A name
|
|
38
|
+
* referenced by nobody → 404 ControlNotFoundError (likely a typo). publisher+. */
|
|
16
39
|
rotate(name: string, opts?: {
|
|
17
40
|
signal?: AbortSignal;
|
|
18
41
|
}): Promise<SecretRotateResult>;
|
|
42
|
+
/** DELETE /api/config/secrets/<name>[?force=true] → reclaim an orphan name from the secret source.
|
|
43
|
+
* `removed:false` is an idempotent no-op (the name wasn't present). A name a worker references → 409
|
|
44
|
+
* ControlConflictError unless `force`. publisher+. */
|
|
19
45
|
delete(name: string, opts?: {
|
|
20
46
|
force?: boolean;
|
|
21
47
|
signal?: AbortSignal;
|
|
22
48
|
}): Promise<SecretDeleteResult>;
|
|
49
|
+
/** GET /api/config/secrets/refs → every env-NAME the effective config references, grouped by name with where
|
|
50
|
+
* it's used (audit which env vars each host/service must provide). NAMES only, never values. admin. */
|
|
23
51
|
refs(opts?: {
|
|
24
52
|
signal?: AbortSignal;
|
|
25
53
|
}): Promise<SecretRefsResult>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"secrets.d.ts","sourceRoot":"","sources":["../../../src/resources/control/secrets.ts"],"names":[],"mappings":"
|
|
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;;;;oFAIgF;IAC1E,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"}
|
|
@@ -3,22 +3,38 @@ export class ControlSecretsResource {
|
|
|
3
3
|
constructor(t) {
|
|
4
4
|
this.t = t;
|
|
5
5
|
}
|
|
6
|
+
/** GET /api/config/secrets[?orphans=true] → the env-NAMEs in the secret source (NEVER values), each tagged
|
|
7
|
+
* referenced/orphan. `orphans` returns only the unreferenced (reclaimable) ones. publisher+. */
|
|
6
8
|
async inventory(opts) {
|
|
7
9
|
const qs = opts?.orphans ? "?orphans=true" : "";
|
|
8
10
|
return this.t.request({ method: "GET", path: `/api/config/secrets${qs}`, signal: opts?.signal });
|
|
9
11
|
}
|
|
12
|
+
/** POST /api/config/secrets {name, value} → write-through ONE secret value to the orchestrator secret source.
|
|
13
|
+
* 🔴 The `value` goes up in the body ONCE and is NEVER returned/logged (I1) — the result carries only `name`
|
|
14
|
+
* + advisory next-steps. A collision with a DIFFERENT existing value → 409 ControlConflictError unless
|
|
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). */
|
|
10
17
|
async set(body) {
|
|
11
18
|
const { signal, overwrite, name, value } = body;
|
|
12
19
|
const qs = overwrite ? "?overwrite=true" : "";
|
|
20
|
+
// value lives ONLY in the request body — never the path/query/log.
|
|
13
21
|
return this.t.request({ method: "POST", path: `/api/config/secrets${qs}`, body: { name, value }, signal });
|
|
14
22
|
}
|
|
23
|
+
/** POST /api/config/secrets/<name>/rotate → draft a recreate of EVERY worker referencing this env-NAME (one
|
|
24
|
+
* atomic draft; publish to apply). `workers:[]` (200) when nothing references it — not an error. A name
|
|
25
|
+
* referenced by nobody → 404 ControlNotFoundError (likely a typo). publisher+. */
|
|
15
26
|
async rotate(name, opts) {
|
|
16
27
|
return this.t.request({ method: "POST", path: `/api/config/secrets/${encodeURIComponent(name)}/rotate`, body: {}, signal: opts?.signal });
|
|
17
28
|
}
|
|
29
|
+
/** DELETE /api/config/secrets/<name>[?force=true] → reclaim an orphan name from the secret source.
|
|
30
|
+
* `removed:false` is an idempotent no-op (the name wasn't present). A name a worker references → 409
|
|
31
|
+
* ControlConflictError unless `force`. publisher+. */
|
|
18
32
|
async delete(name, opts) {
|
|
19
33
|
const qs = opts?.force ? "?force=true" : "";
|
|
20
34
|
return this.t.request({ method: "DELETE", path: `/api/config/secrets/${encodeURIComponent(name)}${qs}`, signal: opts?.signal });
|
|
21
35
|
}
|
|
36
|
+
/** GET /api/config/secrets/refs → every env-NAME the effective config references, grouped by name with where
|
|
37
|
+
* it's used (audit which env vars each host/service must provide). NAMES only, never values. admin. */
|
|
22
38
|
async refs(opts) {
|
|
23
39
|
return this.t.request({ method: "GET", path: "/api/config/secrets/refs", signal: opts?.signal });
|
|
24
40
|
}
|
|
@@ -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;
|
|
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;;;;oFAIgF;IAChF,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"}
|
|
@@ -1,25 +1,47 @@
|
|
|
1
|
+
/** control.users — console user (RBAC) management + per-user scoped API tokens. Backend: sema-registry
|
|
2
|
+
* GET/PUT/DELETE /api/config/users, POST/DELETE /api/config/users/<name>/token. admin-only.
|
|
3
|
+
*
|
|
4
|
+
* These are least-privilege credentials so an external AI/system gets a scoped token instead of the god
|
|
5
|
+
* registry admin token. The env bootstrap admin is NOT here (a recovery cred). Self-demotion / self-delete are
|
|
6
|
+
* refused server-side (400 ControlValidationError) so the last admin can't lock itself out.
|
|
7
|
+
*
|
|
8
|
+
* 🔴 SECRET DISCIPLINE: passwords are write-only (a NEW user needs one; omit on a role-only update — never read
|
|
9
|
+
* back; GET never returns hashes). mintToken() returns a PLAINTEXT token ONCE (the registry stores only its
|
|
10
|
+
* hash, response is no-store) — treat it like any secret: surface it to the operator once, never log/persist. */
|
|
1
11
|
import type { Transport } from "../../transport.js";
|
|
2
12
|
import type { UsersResult, UserUpsertResult, ControlRole, UserTokenMintResult, UserTokenRevokeResult } from "../../control-types.js";
|
|
3
13
|
export declare class ControlUsersResource {
|
|
4
14
|
private readonly t;
|
|
5
15
|
constructor(t: Transport);
|
|
16
|
+
/** GET /api/config/users → console users (NO password hashes). admin. */
|
|
6
17
|
list(opts?: {
|
|
7
18
|
signal?: AbortSignal;
|
|
8
19
|
}): Promise<UsersResult>;
|
|
20
|
+
/** PUT /api/config/users {username, role, password?} → upsert. `password` is REQUIRED for a NEW user (≥8
|
|
21
|
+
* chars), OMIT on a role-only update (keeps the existing hash) — it is write-only, never read back. Demoting
|
|
22
|
+
* your own account → 400 ControlValidationError. admin. NOT submit-class (idempotent on username). */
|
|
9
23
|
upsert(body: {
|
|
10
24
|
username: string;
|
|
11
25
|
role: ControlRole;
|
|
12
26
|
password?: string;
|
|
13
27
|
signal?: AbortSignal;
|
|
14
28
|
}): Promise<UserUpsertResult>;
|
|
29
|
+
/** DELETE /api/config/users?username=<u> → delete a user. Deleting your own logged-in account → 400
|
|
30
|
+
* ControlValidationError. admin. */
|
|
15
31
|
delete(username: string, opts?: {
|
|
16
32
|
signal?: AbortSignal;
|
|
17
33
|
}): Promise<{
|
|
18
34
|
ok: true;
|
|
19
35
|
}>;
|
|
36
|
+
/** POST /api/config/users/<name>/token → mint/rotate (replaces any existing) a user's scoped API token.
|
|
37
|
+
* 🔴 The returned `token` is PLAINTEXT, shown ONCE — the registry stores only its hash and never returns it
|
|
38
|
+
* again. Treat it like a secret: surface once, never log/persist. Unknown user → 404 ControlNotFoundError.
|
|
39
|
+
* admin. NOT submit-class (a retry would mint a DIFFERENT token — never auto-retried). */
|
|
20
40
|
mintToken(name: string, opts?: {
|
|
21
41
|
signal?: AbortSignal;
|
|
22
42
|
}): Promise<UserTokenMintResult>;
|
|
43
|
+
/** DELETE /api/config/users/<name>/token → revoke a user's scoped token. Unknown user → 404
|
|
44
|
+
* ControlNotFoundError (distinct from already-revoked). admin. */
|
|
23
45
|
revokeToken(name: string, opts?: {
|
|
24
46
|
signal?: AbortSignal;
|
|
25
47
|
}): Promise<UserTokenRevokeResult>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"users.d.ts","sourceRoot":"","sources":["../../../src/resources/control/users.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"users.d.ts","sourceRoot":"","sources":["../../../src/resources/control/users.ts"],"names":[],"mappings":"AAAA;;;;;;;;;qHASqH;AACrH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AACpD,OAAO,KAAK,EACV,WAAW,EAAE,gBAAgB,EAAE,WAAW,EAAE,mBAAmB,EAAE,qBAAqB,EACvF,MAAM,wBAAwB,CAAC;AAEhC,qBAAa,oBAAoB;IACnB,OAAO,CAAC,QAAQ,CAAC,CAAC;gBAAD,CAAC,EAAE,SAAS;IAEzC,yEAAyE;IACnE,IAAI,CAAC,IAAI,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,WAAW,CAAA;KAAE,GAAG,OAAO,CAAC,WAAW,CAAC;IAIjE;;2GAEuG;IACjG,MAAM,CAAC,IAAI,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,WAAW,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,WAAW,CAAA;KAAE,GAAG,OAAO,CAAC,gBAAgB,CAAC;IAK/H;yCACqC;IAC/B,MAAM,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,WAAW,CAAA;KAAE,GAAG,OAAO,CAAC;QAAE,EAAE,EAAE,IAAI,CAAA;KAAE,CAAC;IAItF;;;+FAG2F;IACrF,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,WAAW,CAAA;KAAE,GAAG,OAAO,CAAC,mBAAmB,CAAC;IAI5F;uEACmE;IAC7D,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,WAAW,CAAA;KAAE,GAAG,OAAO,CAAC,qBAAqB,CAAC;CAGjG"}
|
|
@@ -3,19 +3,31 @@ export class ControlUsersResource {
|
|
|
3
3
|
constructor(t) {
|
|
4
4
|
this.t = t;
|
|
5
5
|
}
|
|
6
|
+
/** GET /api/config/users → console users (NO password hashes). admin. */
|
|
6
7
|
async list(opts) {
|
|
7
8
|
return this.t.request({ method: "GET", path: "/api/config/users", signal: opts?.signal });
|
|
8
9
|
}
|
|
10
|
+
/** PUT /api/config/users {username, role, password?} → upsert. `password` is REQUIRED for a NEW user (≥8
|
|
11
|
+
* chars), OMIT on a role-only update (keeps the existing hash) — it is write-only, never read back. Demoting
|
|
12
|
+
* your own account → 400 ControlValidationError. admin. NOT submit-class (idempotent on username). */
|
|
9
13
|
async upsert(body) {
|
|
10
14
|
const { signal, ...rest } = body;
|
|
11
15
|
return this.t.request({ method: "PUT", path: "/api/config/users", body: rest, signal });
|
|
12
16
|
}
|
|
17
|
+
/** DELETE /api/config/users?username=<u> → delete a user. Deleting your own logged-in account → 400
|
|
18
|
+
* ControlValidationError. admin. */
|
|
13
19
|
async delete(username, opts) {
|
|
14
20
|
return this.t.request({ method: "DELETE", path: `/api/config/users?username=${encodeURIComponent(username)}`, signal: opts?.signal });
|
|
15
21
|
}
|
|
22
|
+
/** POST /api/config/users/<name>/token → mint/rotate (replaces any existing) a user's scoped API token.
|
|
23
|
+
* 🔴 The returned `token` is PLAINTEXT, shown ONCE — the registry stores only its hash and never returns it
|
|
24
|
+
* again. Treat it like a secret: surface once, never log/persist. Unknown user → 404 ControlNotFoundError.
|
|
25
|
+
* admin. NOT submit-class (a retry would mint a DIFFERENT token — never auto-retried). */
|
|
16
26
|
async mintToken(name, opts) {
|
|
17
27
|
return this.t.request({ method: "POST", path: `/api/config/users/${encodeURIComponent(name)}/token`, body: {}, signal: opts?.signal });
|
|
18
28
|
}
|
|
29
|
+
/** DELETE /api/config/users/<name>/token → revoke a user's scoped token. Unknown user → 404
|
|
30
|
+
* ControlNotFoundError (distinct from already-revoked). admin. */
|
|
19
31
|
async revokeToken(name, opts) {
|
|
20
32
|
return this.t.request({ method: "DELETE", path: `/api/config/users/${encodeURIComponent(name)}/token`, signal: opts?.signal });
|
|
21
33
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"users.js","sourceRoot":"","sources":["../../../src/resources/control/users.ts"],"names":[],"mappings":"AAeA,MAAM,OAAO,oBAAoB;IACF;IAA7B,YAA6B,CAAY;QAAZ,MAAC,GAAD,CAAC,CAAW;IAAG,CAAC;
|
|
1
|
+
{"version":3,"file":"users.js","sourceRoot":"","sources":["../../../src/resources/control/users.ts"],"names":[],"mappings":"AAeA,MAAM,OAAO,oBAAoB;IACF;IAA7B,YAA6B,CAAY;QAAZ,MAAC,GAAD,CAAC,CAAW;IAAG,CAAC;IAE7C,yEAAyE;IACzE,KAAK,CAAC,IAAI,CAAC,IAA+B;QACxC,OAAO,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,mBAAmB,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC;IAC5F,CAAC;IAED;;2GAEuG;IACvG,KAAK,CAAC,MAAM,CAAC,IAAsF;QACjG,MAAM,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,CAAC;QACjC,OAAO,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,mBAAmB,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC;IAC1F,CAAC;IAED;yCACqC;IACrC,KAAK,CAAC,MAAM,CAAC,QAAgB,EAAE,IAA+B;QAC5D,OAAO,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,8BAA8B,kBAAkB,CAAC,QAAQ,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC;IACxI,CAAC;IAED;;;+FAG2F;IAC3F,KAAK,CAAC,SAAS,CAAC,IAAY,EAAE,IAA+B;QAC3D,OAAO,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,qBAAqB,kBAAkB,CAAC,IAAI,CAAC,QAAQ,EAAE,IAAI,EAAE,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC;IACzI,CAAC;IAED;uEACmE;IACnE,KAAK,CAAC,WAAW,CAAC,IAAY,EAAE,IAA+B;QAC7D,OAAO,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,qBAAqB,kBAAkB,CAAC,IAAI,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC;IACjI,CAAC;CACF"}
|
|
@@ -1,8 +1,16 @@
|
|
|
1
|
+
/** control.versioning — config audit trail: list changes, diff one change, rollback to a past snapshot.
|
|
2
|
+
* Backend: sema-registry GET /api/config/changes, GET /api/config/changes/<id>/diff, POST /api/config/rollback.
|
|
3
|
+
*
|
|
4
|
+
* list/diff are viewer+ (read-only, no version bump). rollback is publisher+ and is itself a validated write
|
|
5
|
+
* (re-checks the historical snapshot against the CURRENT schema + cross-domain integrity + quota), appended as
|
|
6
|
+
* a NEW change (forward-only history). A stale base / concurrent edit → 409 ControlConflictError. */
|
|
1
7
|
import type { Transport } from "../../transport.js";
|
|
2
8
|
import type { ConfigDomain, ConfigChange, ChangeDiff, RollbackResult } from "../../control-types.js";
|
|
3
9
|
export declare class ControlVersioningResource {
|
|
4
10
|
private readonly t;
|
|
5
11
|
constructor(t: Transport);
|
|
12
|
+
/** GET /api/config/changes[?domain=&limit=] → recent ConfigChange metadata (newest-first). `limit` is capped
|
|
13
|
+
* server-side (≤500). viewer+. */
|
|
6
14
|
changes(opts?: {
|
|
7
15
|
domain?: ConfigDomain;
|
|
8
16
|
limit?: number;
|
|
@@ -10,9 +18,13 @@ export declare class ControlVersioningResource {
|
|
|
10
18
|
}): Promise<{
|
|
11
19
|
changes: ConfigChange[];
|
|
12
20
|
}>;
|
|
21
|
+
/** GET /api/config/changes/<id>/diff → the domain payload before/after a change (404 → ControlNotFoundError). */
|
|
13
22
|
diff(changeId: string, opts?: {
|
|
14
23
|
signal?: AbortSignal;
|
|
15
24
|
}): Promise<ChangeDiff>;
|
|
25
|
+
/** POST /api/config/rollback {changeId} → re-apply that change's snapshot as a new change. publisher+. NOT
|
|
26
|
+
* submit-class (no idempotency key — a rollback is a CAS write, surfaced 409 on a concurrent edit). A snapshot
|
|
27
|
+
* that no longer validates / would break references → 409 ControlConflictError. */
|
|
16
28
|
rollback(body: {
|
|
17
29
|
changeId: string;
|
|
18
30
|
signal?: AbortSignal;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"versioning.d.ts","sourceRoot":"","sources":["../../../src/resources/control/versioning.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"versioning.d.ts","sourceRoot":"","sources":["../../../src/resources/control/versioning.ts"],"names":[],"mappings":"AAAA;;;;;sGAKsG;AACtG,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AACpD,OAAO,KAAK,EAAE,YAAY,EAAE,YAAY,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAErG,qBAAa,yBAAyB;IACxB,OAAO,CAAC,QAAQ,CAAC,CAAC;gBAAD,CAAC,EAAE,SAAS;IAEzC;uCACmC;IAC7B,OAAO,CAAC,IAAI,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,YAAY,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,WAAW,CAAA;KAAE,GAAG,OAAO,CAAC;QAAE,OAAO,EAAE,YAAY,EAAE,CAAA;KAAE,CAAC;IAQ3H,iHAAiH;IAC3G,IAAI,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,WAAW,CAAA;KAAE,GAAG,OAAO,CAAC,UAAU,CAAC;IAIlF;;wFAEoF;IAC9E,QAAQ,CAAC,IAAI,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,WAAW,CAAA;KAAE,GAAG,OAAO,CAAC,cAAc,CAAC;CAI1F"}
|
|
@@ -3,6 +3,8 @@ export class ControlVersioningResource {
|
|
|
3
3
|
constructor(t) {
|
|
4
4
|
this.t = t;
|
|
5
5
|
}
|
|
6
|
+
/** GET /api/config/changes[?domain=&limit=] → recent ConfigChange metadata (newest-first). `limit` is capped
|
|
7
|
+
* server-side (≤500). viewer+. */
|
|
6
8
|
async changes(opts) {
|
|
7
9
|
const q = new URLSearchParams();
|
|
8
10
|
if (opts?.domain)
|
|
@@ -12,9 +14,13 @@ export class ControlVersioningResource {
|
|
|
12
14
|
const qs = q.toString();
|
|
13
15
|
return this.t.request({ method: "GET", path: `/api/config/changes${qs ? `?${qs}` : ""}`, signal: opts?.signal });
|
|
14
16
|
}
|
|
17
|
+
/** GET /api/config/changes/<id>/diff → the domain payload before/after a change (404 → ControlNotFoundError). */
|
|
15
18
|
async diff(changeId, opts) {
|
|
16
19
|
return this.t.request({ method: "GET", path: `/api/config/changes/${encodeURIComponent(changeId)}/diff`, signal: opts?.signal });
|
|
17
20
|
}
|
|
21
|
+
/** POST /api/config/rollback {changeId} → re-apply that change's snapshot as a new change. publisher+. NOT
|
|
22
|
+
* submit-class (no idempotency key — a rollback is a CAS write, surfaced 409 on a concurrent edit). A snapshot
|
|
23
|
+
* that no longer validates / would break references → 409 ControlConflictError. */
|
|
18
24
|
async rollback(body) {
|
|
19
25
|
const { signal, ...rest } = body;
|
|
20
26
|
return this.t.request({ method: "POST", path: "/api/config/rollback", body: rest, signal });
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"versioning.js","sourceRoot":"","sources":["../../../src/resources/control/versioning.ts"],"names":[],"mappings":"AASA,MAAM,OAAO,yBAAyB;IACP;IAA7B,YAA6B,CAAY;QAAZ,MAAC,GAAD,CAAC,CAAW;IAAG,CAAC;
|
|
1
|
+
{"version":3,"file":"versioning.js","sourceRoot":"","sources":["../../../src/resources/control/versioning.ts"],"names":[],"mappings":"AASA,MAAM,OAAO,yBAAyB;IACP;IAA7B,YAA6B,CAAY;QAAZ,MAAC,GAAD,CAAC,CAAW;IAAG,CAAC;IAE7C;uCACmC;IACnC,KAAK,CAAC,OAAO,CAAC,IAAsE;QAClF,MAAM,CAAC,GAAG,IAAI,eAAe,EAAE,CAAC;QAChC,IAAI,IAAI,EAAE,MAAM;YAAE,CAAC,CAAC,GAAG,CAAC,QAAQ,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;QAC/C,IAAI,IAAI,EAAE,KAAK,KAAK,SAAS;YAAE,CAAC,CAAC,GAAG,CAAC,OAAO,EAAE,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;QAClE,MAAM,EAAE,GAAG,CAAC,CAAC,QAAQ,EAAE,CAAC;QACxB,OAAO,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,sBAAsB,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC;IACnH,CAAC;IAED,iHAAiH;IACjH,KAAK,CAAC,IAAI,CAAC,QAAgB,EAAE,IAA+B;QAC1D,OAAO,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,uBAAuB,kBAAkB,CAAC,QAAQ,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC;IACnI,CAAC;IAED;;wFAEoF;IACpF,KAAK,CAAC,QAAQ,CAAC,IAAgD;QAC7D,MAAM,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,CAAC;QACjC,OAAO,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,sBAAsB,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC;IAC9F,CAAC;CACF"}
|
|
@@ -1,16 +1,30 @@
|
|
|
1
|
+
/** control.workers — per-worker operations: read reconciler-reported health, roll the image (full-auto CD),
|
|
2
|
+
* rotate (force recreate). Backend: sema-registry GET /api/config/workers/status, POST
|
|
3
|
+
* /api/config/workers/roll, POST /api/config/workers/<name>/rotate.
|
|
4
|
+
*
|
|
5
|
+
* status() is admin-readable (viewer+ via the admin path). roll()/rotate() are publisher+ (publishing /
|
|
6
|
+
* recreating production). The reconciler-only POST/DELETE on workers/status (SERVICE_PULL_TOKEN, NOT the
|
|
7
|
+
* editor Bearer) is DELIBERATELY out of scope — it's a service-token write, a different auth plane. */
|
|
1
8
|
import type { Transport } from "../../transport.js";
|
|
2
9
|
import type { WorkerStatuses, RollResult, RotateResult } from "../../control-types.js";
|
|
3
10
|
export declare class ControlWorkersResource {
|
|
4
11
|
private readonly t;
|
|
5
12
|
constructor(t: Transport);
|
|
13
|
+
/** GET /api/config/workers/status → reconciler-reported worker health rows. Admin-readable (viewer+). */
|
|
6
14
|
status(opts?: {
|
|
7
15
|
signal?: AbortSignal;
|
|
8
16
|
}): Promise<WorkerStatuses>;
|
|
17
|
+
/** POST /api/config/workers/roll {sha, repo?} → re-tag matching workers to <base>:<sha> and PUBLISH (full-auto
|
|
18
|
+
* CD; bypasses the human approval gate by design). publisher+. No matching worker → clean 200 no-op
|
|
19
|
+
* `{rolled:[], published:false}`. NOT submit-class (re-rolling the same sha is an idempotent no-op-publish
|
|
20
|
+
* server-side; no client idempotency key needed). */
|
|
9
21
|
roll(body: {
|
|
10
22
|
sha: string;
|
|
11
23
|
repo?: string;
|
|
12
24
|
signal?: AbortSignal;
|
|
13
25
|
}): Promise<RollResult>;
|
|
26
|
+
/** POST /api/config/workers/<name>/rotate → bump the worker's recreateNonce so the reconciler recreates it +
|
|
27
|
+
* re-projects its secrets (drafted; publish to apply). publisher+. Unknown worker → 404 ControlNotFoundError. */
|
|
14
28
|
rotate(name: string, opts?: {
|
|
15
29
|
signal?: AbortSignal;
|
|
16
30
|
}): Promise<RotateResult>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"workers.d.ts","sourceRoot":"","sources":["../../../src/resources/control/workers.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"workers.d.ts","sourceRoot":"","sources":["../../../src/resources/control/workers.ts"],"names":[],"mappings":"AAAA;;;;;;wGAMwG;AACxG,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AACpD,OAAO,KAAK,EAAE,cAAc,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAEvF,qBAAa,sBAAsB;IACrB,OAAO,CAAC,QAAQ,CAAC,CAAC;gBAAD,CAAC,EAAE,SAAS;IAEzC,yGAAyG;IACnG,MAAM,CAAC,IAAI,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,WAAW,CAAA;KAAE,GAAG,OAAO,CAAC,cAAc,CAAC;IAItE;;;0DAGsD;IAChD,IAAI,CAAC,IAAI,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,WAAW,CAAA;KAAE,GAAG,OAAO,CAAC,UAAU,CAAC;IAK3F;sHACkH;IAC5G,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,WAAW,CAAA;KAAE,GAAG,OAAO,CAAC,YAAY,CAAC;CAGnF"}
|
|
@@ -3,13 +3,20 @@ export class ControlWorkersResource {
|
|
|
3
3
|
constructor(t) {
|
|
4
4
|
this.t = t;
|
|
5
5
|
}
|
|
6
|
+
/** GET /api/config/workers/status → reconciler-reported worker health rows. Admin-readable (viewer+). */
|
|
6
7
|
async status(opts) {
|
|
7
8
|
return this.t.request({ method: "GET", path: "/api/config/workers/status", signal: opts?.signal });
|
|
8
9
|
}
|
|
10
|
+
/** POST /api/config/workers/roll {sha, repo?} → re-tag matching workers to <base>:<sha> and PUBLISH (full-auto
|
|
11
|
+
* CD; bypasses the human approval gate by design). publisher+. No matching worker → clean 200 no-op
|
|
12
|
+
* `{rolled:[], published:false}`. NOT submit-class (re-rolling the same sha is an idempotent no-op-publish
|
|
13
|
+
* server-side; no client idempotency key needed). */
|
|
9
14
|
async roll(body) {
|
|
10
15
|
const { signal, ...rest } = body;
|
|
11
16
|
return this.t.request({ method: "POST", path: "/api/config/workers/roll", body: rest, signal });
|
|
12
17
|
}
|
|
18
|
+
/** POST /api/config/workers/<name>/rotate → bump the worker's recreateNonce so the reconciler recreates it +
|
|
19
|
+
* re-projects its secrets (drafted; publish to apply). publisher+. Unknown worker → 404 ControlNotFoundError. */
|
|
13
20
|
async rotate(name, opts) {
|
|
14
21
|
return this.t.request({ method: "POST", path: `/api/config/workers/${encodeURIComponent(name)}/rotate`, body: {}, signal: opts?.signal });
|
|
15
22
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"workers.js","sourceRoot":"","sources":["../../../src/resources/control/workers.ts"],"names":[],"mappings":"AAUA,MAAM,OAAO,sBAAsB;IACJ;IAA7B,YAA6B,CAAY;QAAZ,MAAC,GAAD,CAAC,CAAW;IAAG,CAAC;
|
|
1
|
+
{"version":3,"file":"workers.js","sourceRoot":"","sources":["../../../src/resources/control/workers.ts"],"names":[],"mappings":"AAUA,MAAM,OAAO,sBAAsB;IACJ;IAA7B,YAA6B,CAAY;QAAZ,MAAC,GAAD,CAAC,CAAW;IAAG,CAAC;IAE7C,yGAAyG;IACzG,KAAK,CAAC,MAAM,CAAC,IAA+B;QAC1C,OAAO,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,4BAA4B,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC;IACrG,CAAC;IAED;;;0DAGsD;IACtD,KAAK,CAAC,IAAI,CAAC,IAA0D;QACnE,MAAM,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,CAAC;QACjC,OAAO,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,0BAA0B,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC;IAClG,CAAC;IAED;sHACkH;IAClH,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;CACF"}
|
|
@@ -1,18 +1,53 @@
|
|
|
1
|
+
/** elicitations — design/99 §E23 (core 1.124.0 `onElicit` seam; service `elicitation.ts`, SHIPPED behind
|
|
2
|
+
* `MCP_ELICITATION_ENABLED`). The INBOUND-MCP-elicitation HITL flow: an opted-in MCP server may, MID-tool-call,
|
|
3
|
+
* ask the END USER for input. The request rides the SAME open live stream (`POST /v1/tasks/stream`) as a NAMED
|
|
4
|
+
* SSE frame (`event: elicitation` / `event: elicitation_complete`), and the shell answers it out-of-band via
|
|
5
|
+
* `POST /v1/elicitations/:id/respond`.
|
|
6
|
+
*
|
|
7
|
+
* 🔴 LIVE-ONLY + SAME-REPLICA (the `steer()`-class of HITL, NOT the durable approval/checkpoint class): the
|
|
8
|
+
* parked promise is in-memory, so a respond that lands on another replica / after answer / after the TTL finds
|
|
9
|
+
* nothing → 404. There is NO durable suspend — a crash loses an in-flight elicitation (acceptable for an
|
|
10
|
+
* interactive shell; the durable variant waits on the deferred E22 seam).
|
|
11
|
+
*
|
|
12
|
+
* 🔴 The `elicitation`/`elicitation_complete` FRAMES are NOT delivered as `AgentEvent` arms — they are a DISTINCT
|
|
13
|
+
* vocabulary that interleaves on the live token stream. Tail them off `tasks.streamRaw` and dispatch on the SSE
|
|
14
|
+
* `event:` name (the payload also carries `type`, so a name-stripping proxy still works); parse the `data:` with
|
|
15
|
+
* this resource's {@link ElicitationFrame} type. Then resolve via {@link ElicitationsResource.respond}.
|
|
16
|
+
*
|
|
17
|
+
* 🔴 UNTRUSTED: `message` is service-FENCED (`delimitUntrusted`) + secret-redacted; `requestedSchema` is an
|
|
18
|
+
* OPAQUE passthrough (redacted+size-bounded, never interpreted) — the shell MUST still fence it on display.
|
|
19
|
+
* v1 is FORM-MODE only (url-mode is rejected upstream as a phishing surface). */
|
|
1
20
|
import type { Transport } from "../transport.js";
|
|
21
|
+
/** A live elicitation frame interleaved on the run's `tasks.streamRaw` connection (service `ElicitationFrame`
|
|
22
|
+
* elicitation.ts:41-54). `type` IS the SSE `event:` name AND is echoed in the payload. The shell renders the
|
|
23
|
+
* `elicitation` frame as a form dialog and dismisses it on `elicitation_complete`. */
|
|
2
24
|
export interface ElicitationFrame {
|
|
3
25
|
type: "elicitation" | "elicitation_complete";
|
|
26
|
+
/** The id to echo back to {@link ElicitationsResource.respond}. */
|
|
4
27
|
elicitationId: string;
|
|
28
|
+
/** Which opted-in MCP server asked (also the trust label core fences `message` against). */
|
|
5
29
|
mcpServerName: string;
|
|
30
|
+
/** "elicitation" only: the FENCED + secret-redacted human-facing prompt. UNTRUSTED — never re-feed to a model. */
|
|
6
31
|
message?: string;
|
|
32
|
+
/** "elicitation" only: the server's requested input schema. OPAQUE passthrough — never interpreted/validated;
|
|
33
|
+
* still server-controlled UNTRUSTED, so the shell MUST fence it on display. */
|
|
7
34
|
requestedSchema?: unknown;
|
|
35
|
+
/** "elicitation" only: always "form" in v1 (url-mode is rejected upstream). */
|
|
8
36
|
mode?: "form";
|
|
37
|
+
/** "elicitation_complete" only: how it resolved (the dialog dismiss reason). */
|
|
9
38
|
action?: "accept" | "decline" | "cancel";
|
|
10
39
|
[k: string]: unknown;
|
|
11
40
|
}
|
|
41
|
+
/** The shell's answer to an {@link ElicitationFrame} (= core's `McpElicitResponse`, types.ts:314-318). On
|
|
42
|
+
* `accept`, `content` is a flat record of scalars / string[] — an OPAQUE passthrough core NEVER validates
|
|
43
|
+
* against `requestedSchema`. A non-accept (`decline`/`cancel`) carries no content. */
|
|
12
44
|
export interface ElicitResponse {
|
|
13
45
|
action: "accept" | "decline" | "cancel";
|
|
46
|
+
/** accept only — the submitted form values (flat scalars). The service validates only this OUTER shape, never
|
|
47
|
+
* the schema; values must be `string | number | boolean | string[]` (service `parseElicitResponse`). */
|
|
14
48
|
content?: Record<string, string | number | boolean | string[]>;
|
|
15
49
|
}
|
|
50
|
+
/** The 200 ack from a successful respond (service `respond` elicitation.ts:267). */
|
|
16
51
|
export interface ElicitRespondAck {
|
|
17
52
|
elicitationId: string;
|
|
18
53
|
delivery: "applied";
|
|
@@ -21,6 +56,14 @@ export interface ElicitRespondAck {
|
|
|
21
56
|
export declare class ElicitationsResource {
|
|
22
57
|
private readonly t;
|
|
23
58
|
constructor(t: Transport);
|
|
59
|
+
/** POST /v1/elicitations/:id/respond — resolve a parked inbound-MCP elicitation with the user's form answer.
|
|
60
|
+
* The resolved value flows back to the MCP server on the still-open task connection.
|
|
61
|
+
*
|
|
62
|
+
* 🔴 OWNER-GATED with a 404 (NO existence oracle): a non-owner AND an unknown/answered/expired/wrong-replica id
|
|
63
|
+
* both get 404 — never branch a "does this id exist" decision off the status. A malformed body is a 400
|
|
64
|
+
* (existence-independent, like steer). A worker without `MCP_ELICITATION_ENABLED` → 501.
|
|
65
|
+
*
|
|
66
|
+
* Not a submit / not idempotent (it resolves an in-flight promise exactly once) → NO SDK retry. */
|
|
24
67
|
respond(id: string, response: ElicitResponse, opts?: {
|
|
25
68
|
signal?: AbortSignal;
|
|
26
69
|
}): Promise<ElicitRespondAck>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"elicitations.d.ts","sourceRoot":"","sources":["../../src/resources/elicitations.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"elicitations.d.ts","sourceRoot":"","sources":["../../src/resources/elicitations.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;kFAkBkF;AAClF,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAEjD;;uFAEuF;AACvF,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,aAAa,GAAG,sBAAsB,CAAC;IAC7C,mEAAmE;IACnE,aAAa,EAAE,MAAM,CAAC;IACtB,4FAA4F;IAC5F,aAAa,EAAE,MAAM,CAAC;IACtB,kHAAkH;IAClH,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;oFACgF;IAChF,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,+EAA+E;IAC/E,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,gFAAgF;IAChF,MAAM,CAAC,EAAE,QAAQ,GAAG,SAAS,GAAG,QAAQ,CAAC;IACzC,CAAC,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;CACtB;AAED;;uFAEuF;AACvF,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,QAAQ,GAAG,SAAS,GAAG,QAAQ,CAAC;IACxC;6GACyG;IACzG,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,MAAM,EAAE,CAAC,CAAC;CAChE;AAED,oFAAoF;AACpF,MAAM,WAAW,gBAAgB;IAC/B,aAAa,EAAE,MAAM,CAAC;IACtB,QAAQ,EAAE,SAAS,CAAC;IACpB,MAAM,EAAE,QAAQ,GAAG,SAAS,GAAG,QAAQ,CAAC;CACzC;AAED,qBAAa,oBAAoB;IACnB,OAAO,CAAC,QAAQ,CAAC,CAAC;gBAAD,CAAC,EAAE,SAAS;IAEzC;;;;;;;wGAOoG;IAC9F,OAAO,CAAC,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,cAAc,EAAE,IAAI,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,WAAW,CAAA;KAAE,GAAG,OAAO,CAAC,gBAAgB,CAAC;CAQhH"}
|
|
@@ -3,6 +3,14 @@ export class ElicitationsResource {
|
|
|
3
3
|
constructor(t) {
|
|
4
4
|
this.t = t;
|
|
5
5
|
}
|
|
6
|
+
/** POST /v1/elicitations/:id/respond — resolve a parked inbound-MCP elicitation with the user's form answer.
|
|
7
|
+
* The resolved value flows back to the MCP server on the still-open task connection.
|
|
8
|
+
*
|
|
9
|
+
* 🔴 OWNER-GATED with a 404 (NO existence oracle): a non-owner AND an unknown/answered/expired/wrong-replica id
|
|
10
|
+
* both get 404 — never branch a "does this id exist" decision off the status. A malformed body is a 400
|
|
11
|
+
* (existence-independent, like steer). A worker without `MCP_ELICITATION_ENABLED` → 501.
|
|
12
|
+
*
|
|
13
|
+
* Not a submit / not idempotent (it resolves an in-flight promise exactly once) → NO SDK retry. */
|
|
6
14
|
async respond(id, response, opts) {
|
|
7
15
|
return this.t.request({
|
|
8
16
|
method: "POST",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"elicitations.js","sourceRoot":"","sources":["../../src/resources/elicitations.ts"],"names":[],"mappings":"AA2DA,MAAM,OAAO,oBAAoB;IACF;IAA7B,YAA6B,CAAY;QAAZ,MAAC,GAAD,CAAC,CAAW;IAAG,CAAC;
|
|
1
|
+
{"version":3,"file":"elicitations.js","sourceRoot":"","sources":["../../src/resources/elicitations.ts"],"names":[],"mappings":"AA2DA,MAAM,OAAO,oBAAoB;IACF;IAA7B,YAA6B,CAAY;QAAZ,MAAC,GAAD,CAAC,CAAW;IAAG,CAAC;IAE7C;;;;;;;wGAOoG;IACpG,KAAK,CAAC,OAAO,CAAC,EAAU,EAAE,QAAwB,EAAE,IAA+B;QACjF,OAAO,IAAI,CAAC,CAAC,CAAC,OAAO,CAAmB;YACtC,MAAM,EAAE,MAAM;YACd,IAAI,EAAE,oBAAoB,kBAAkB,CAAC,EAAE,CAAC,UAAU;YAC1D,IAAI,EAAE,QAAQ;YACd,MAAM,EAAE,IAAI,EAAE,MAAM;SACrB,CAAC,CAAC;IACL,CAAC;CACF"}
|
|
@@ -1,20 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MF-Fleet (shell-host data contract) — `GET /v1/fleet/stream` LIVE multi-row fleet view as an SSE PUSH stream.
|
|
3
|
+
*
|
|
4
|
+
* The fleet view animates a MULTI-ROW tree: every active task's `status/elapsedMs/tokens/queuedCount` and every
|
|
5
|
+
* workflow's `doneCount N/M · failedCount` TRANSITION over time. This is a *push* stream, not a one-shot read —
|
|
6
|
+
* the service sends a SNAPSHOT on connect, then a per-row delta for every transition, with STABLE per-row
|
|
7
|
+
* identity (`row.id`) so the consumer updates the right row in place.
|
|
8
|
+
*
|
|
9
|
+
* 🔴 THE SDK PRODUCES FRAMES, IT DOES NOT MAINTAIN STATE. `stream()` yields each decoded {@link FleetFrame}; the
|
|
10
|
+
* consumer (the shell renderer) owns the active-set Map and does the update-in-place / remove. The shell-local
|
|
11
|
+
* render state (`main`/tree-`selection`/`timeline`/`depth`/`viewed`/`bulletColor`, MF-Fleet.md) is NOT on the
|
|
12
|
+
* wire and the SDK does NOT synthesize it — only the data that transitions rides the frames.
|
|
13
|
+
*
|
|
14
|
+
* 🔒 owner-scoped: the route filters to the caller's own active runs (by the credential-derived principal — NOT a
|
|
15
|
+
* spoofable header) UNLESS the caller is fleet-wide (an operator / deployment trace token sees every tenant's
|
|
16
|
+
* rows, like the trace API). The `scope` field is wire-STRIPPED by the service after the owner-gate — it never
|
|
17
|
+
* reaches this SDK, so {@link FleetTaskRow}/{@link FleetWorkflowRow} carry NO `scope`. The connect-time `meta`
|
|
18
|
+
* frame's `scoped` flag tells the consumer whether this view is owner-scoped (true) or fleet-wide (false).
|
|
19
|
+
*
|
|
20
|
+
* 🔴 NOT RESUMABLE / replica-local + in-process: a drop ends the iterator (re-`stream()` for a fresh snapshot).
|
|
21
|
+
* Mirrors `workflows.stream`/`trace.stream` framing but with the fleet vocabulary
|
|
22
|
+
* (`meta`/`snapshot`/`task`/`task_remove`/`workflow`/`workflow_remove`). Deliberately uses the vocabulary-
|
|
23
|
+
* agnostic `readSseFrames` (NOT `parseSse`, which is hardcoded to the AgentEvent union + auto-reconnect).
|
|
24
|
+
* Gated off (no `fleetBus` wired) → 501 (typed error) before any frame.
|
|
25
|
+
*
|
|
26
|
+
* Verified against service `1bf7a5c`: handler `streamFleet` (http/server.ts:4874) + `fleet/fleet-bus.ts` types.
|
|
27
|
+
*/
|
|
1
28
|
import type { Transport } from "../transport.js";
|
|
29
|
+
/** The fleet vocabulary the shell renders (MF-Fleet `FleetTask.status`, byte-aligned to service `FleetTaskStatus`
|
|
30
|
+
* fleet-bus.ts:27-36). The service maps its run/workflow status onto this NEUTRAL set:
|
|
31
|
+
* `awaiting approval` = a needs-review / plan-approval park, `waiting` = a durable suspend. CLOSED on the wire,
|
|
32
|
+
* but render open (branch known, fall back to a generic row for any future value). */
|
|
2
33
|
export type FleetTaskStatus = "queued" | "running" | "waiting" | "stopping" | "awaiting approval" | "idle" | "completed" | "failed" | "killed";
|
|
34
|
+
/** One active task row (service `FleetTaskRow` fleet-bus.ts:40-54, MINUS the wire-stripped `scope`). Each frame
|
|
35
|
+
* carries the POST-MERGE FULL row (the service merges deltas onto the existing row before emitting), so the
|
|
36
|
+
* consumer replaces its row by `id` — NEVER a sparse patch to apply field-by-field. */
|
|
3
37
|
export interface FleetTaskRow {
|
|
38
|
+
/** Stable identity — the durable runId/taskId (subagent child rows are `"<runId> <taskId>"`). Update/remove by this. */
|
|
4
39
|
id: string;
|
|
5
40
|
name: string;
|
|
6
41
|
description?: string;
|
|
42
|
+
/** 🔴 §K-7 agent IDENTITY(shell ASK 2026-06-28)—— 短类型 label,让 picker 像 187 显示,而非整段 objective-preview。
|
|
43
|
+
* `agentType` = subagent_type/teammate 类型名(如 "Explore"/"general-purpose");`agentName` = in-process
|
|
44
|
+
* teammate 的实例名。**值由 core/service 在 fleet 行发**(今天可能缺,缺则 consumer fallback 到 `name`)。additive/tolerate-absent。 */
|
|
7
45
|
agentType?: string;
|
|
8
46
|
agentName?: string;
|
|
47
|
+
/** Subagent nesting (E2 `parentToolCallId`) — top-level when absent; a child row hangs under its parent's row. */
|
|
9
48
|
parentId?: string;
|
|
49
|
+
/** design/149(server 1.240):wa\* 行的 workflow 归属附注位(w\* runId)——面板按此分组;footer 树按
|
|
50
|
+
* taskId 前缀过滤 wa\*(CC 锚 [1433]),不按此嵌套。ADDITIVE / tolerate-absent。 */
|
|
10
51
|
workflowRunId?: string;
|
|
11
52
|
status: FleetTaskStatus;
|
|
53
|
+
/** server 1.250(core 1.367 δ):launch 时刻 epoch ms(revive 行=本 revive 周期 wake 时刻)——elapsed
|
|
54
|
+
* 锚直出,消费方自算不漂(elapsedMs 是服务端快照,保留兼容)。ADDITIVE / tolerate-absent。 */
|
|
12
55
|
startedAt?: number;
|
|
13
56
|
elapsedMs?: number;
|
|
14
57
|
tokens?: number;
|
|
58
|
+
/** 🔴 `tokenDir` REMOVED(core 裁定,2026-06-28)—— 死字段(0 producer/0 consumer)+ 错 shape
|
|
59
|
+
* (`"down"` 因 token 单调递增永不可达)。日后若要 token **速率**指示器 = 全新正确 shape(一个 rate 数),非复活此枚举。 */
|
|
15
60
|
queuedCount?: number;
|
|
16
61
|
awaitingPlanApproval?: boolean;
|
|
17
62
|
}
|
|
63
|
+
/** One workflow row (service `FleetWorkflowRow` fleet-bus.ts:57-69, MINUS the wire-stripped `scope`). `status` is
|
|
64
|
+
* the NEUTRAL workflow run status (`running`|`completed`|`failed`), open on read. */
|
|
18
65
|
export interface FleetWorkflowRow {
|
|
19
66
|
id: string;
|
|
20
67
|
name: string;
|
|
@@ -26,6 +73,18 @@ export interface FleetWorkflowRow {
|
|
|
26
73
|
elapsedMs?: number;
|
|
27
74
|
tokens?: number;
|
|
28
75
|
}
|
|
76
|
+
/**
|
|
77
|
+
* One decoded frame off the fleet stream (service `streamFleet` emit set, http/server.ts:4877-4908). The SDK
|
|
78
|
+
* yields these in arrival order; the consumer applies them to its own active-set Map:
|
|
79
|
+
* - `meta` — FIRST frame: `{ version, scoped }`. `scoped:true` ⇒ owner-scoped view; `false` ⇒ fleet-wide.
|
|
80
|
+
* - `snapshot` — connect-time FULL state (the visible, scope-stripped rows). Seed the Map from this.
|
|
81
|
+
* - `task` — a single task-row UPSERT (POST-MERGE FULL row) → replace the Map entry by `row.id`.
|
|
82
|
+
* - `task_remove` — the task row left the active set (terminal + swept) → delete `id` from the Map.
|
|
83
|
+
* - `workflow` — a single workflow-row UPSERT (FULL row) → replace by `row.id`.
|
|
84
|
+
* - `workflow_remove` — the workflow row left the active set → delete `id`.
|
|
85
|
+
* OPEN set — branch on `type`, ignore an unknown future frame (heartbeat `: hb` comment frames are swallowed by
|
|
86
|
+
* the reader and never yielded).
|
|
87
|
+
*/
|
|
29
88
|
export type FleetFrame = {
|
|
30
89
|
type: "meta";
|
|
31
90
|
version: number;
|
|
@@ -61,12 +120,23 @@ export type FleetFrame = {
|
|
|
61
120
|
event: string;
|
|
62
121
|
data: Record<string, unknown>;
|
|
63
122
|
};
|
|
123
|
+
/** design/129-B 缺口②(帧契约,[446]/[1338]⑥)— a background child's COMPLETION notification pushed on the
|
|
124
|
+
* ALWAYS-OPEN fleet stream (the only server-push lane an idle shell keeps subscribed): a session-scoped bg
|
|
125
|
+
* child finishing while the host sits idle notifies IMMEDIATELY. EVENT semantics, not state — never in the
|
|
126
|
+
* snapshot; the consumer's own task_notification queue dedups by (taskId,status). The service filters by
|
|
127
|
+
* tenant/`?session=` before send and strips the owner keys — this is the post-strip wire shape
|
|
128
|
+
* (fleet-bus.ts `BgNotification` minus `ownerScope`/`ownerSessionId`). */
|
|
64
129
|
export interface FleetBgNotification {
|
|
130
|
+
/** Registry handle (`a*` domain — the TaskOutput/TaskStop key). */
|
|
65
131
|
taskId: string;
|
|
132
|
+
/** The child RUN's session id (uuid domain — the a*↔uuid dual anchor), when known. */
|
|
66
133
|
sessionId?: string;
|
|
134
|
+
/** Stop-cycle counter(server 1.239 起透传 core terminal 帧的 seq;revive 第二周期=更高 seq)——
|
|
135
|
+
* consumers fold it into the dedup key ((taskId,status,seq));absent on older engines = 旧键形。 */
|
|
67
136
|
seq?: number;
|
|
68
137
|
status: "completed" | "failed" | "killed";
|
|
69
138
|
summary?: string;
|
|
139
|
+
/** Background lifetime scope (design/129), NOT the tenant scope. */
|
|
70
140
|
scope: "task" | "session";
|
|
71
141
|
parentTaskId?: string;
|
|
72
142
|
stoppedBy?: string;
|
|
@@ -80,17 +150,48 @@ export interface FleetBgNotification {
|
|
|
80
150
|
path: string;
|
|
81
151
|
edits: number;
|
|
82
152
|
}>;
|
|
153
|
+
/** server 1.250(core 1.367 δ):委托树 root 宿主会话(固定点语义,嵌套孙代恒锚 root shell)——跨壳
|
|
154
|
+
* 重启按宿主会话归组的键。ADDITIVE / tolerate-absent。 */
|
|
83
155
|
rootSessionId?: string;
|
|
156
|
+
/** server 1.258:完成通知的花费汇总(数值 verbatim,fields picked)——完成卡的花费显示。ADDITIVE。 */
|
|
157
|
+
usage?: {
|
|
158
|
+
totalTokens?: number;
|
|
159
|
+
toolUses?: number;
|
|
160
|
+
durationMs?: number;
|
|
161
|
+
tokens?: number;
|
|
162
|
+
turns?: number;
|
|
163
|
+
costMicroUsd?: number;
|
|
164
|
+
};
|
|
165
|
+
/** server 1.258:子代转录锚(引擎铸的 transcript id)——转录跳转键。ADDITIVE / tolerate-absent。 */
|
|
166
|
+
transcriptId?: string;
|
|
84
167
|
}
|
|
168
|
+
/** The connect-time `meta` frame payload (service http/server.ts:4877). */
|
|
85
169
|
export interface FleetMeta {
|
|
86
170
|
version: number;
|
|
171
|
+
/** `true` ⇒ this connection is OWNER-SCOPED (the caller's own rows); `false` ⇒ FLEET-WIDE (operator/trace token). */
|
|
87
172
|
scoped: boolean;
|
|
173
|
+
/** server 1.247+:`true` ⇒ 本连接带 `?session=`(行/通知都按宿主会话过滤)。ADDITIVE / tolerate-absent。 */
|
|
88
174
|
sessionScoped?: boolean;
|
|
175
|
+
/** server 1.247+ 代际标([1508]):`true` ⇒ 本 server 的 bg_notification 注入路对 scoped 订阅者
|
|
176
|
+
* fail-CLOSED——新代际壳可撤帧级 own/foreign 判别(🔴 仅 session-bound 连接;unscoped 连接按设计
|
|
177
|
+
* 收到同 principal 全部完成帧)。缺键=老 server,保留判别。 */
|
|
89
178
|
bgNotifyFailClosed?: boolean;
|
|
90
179
|
}
|
|
91
180
|
export declare class FleetResource {
|
|
92
181
|
private readonly t;
|
|
93
182
|
constructor(t: Transport);
|
|
183
|
+
/**
|
|
184
|
+
* GET /v1/fleet/stream — the LIVE fleet (active task + workflow rows). SSE; the SDK PRODUCES frames, the
|
|
185
|
+
* consumer maintains the active-set state (update-in-place / remove by `id`).
|
|
186
|
+
*
|
|
187
|
+
* Emit order: `meta` (`{version, scoped}`) → `snapshot` (full visible set) → then a `task`/`workflow` upsert
|
|
188
|
+
* per transition + `task_remove`/`workflow_remove` per departure. Each `task`/`workflow` frame is the POST-MERGE
|
|
189
|
+
* FULL row (NOT a sparse patch) → replace by `row.id`. Heartbeat comment frames are swallowed.
|
|
190
|
+
*
|
|
191
|
+
* 🔴 NOT RESUMABLE: a drop just ends the generator (re-call for a fresh snapshot). Owner-scoped by the
|
|
192
|
+
* credential principal unless fleet-wide; `scope` is wire-stripped (never appears on a row). 501 (typed) before
|
|
193
|
+
* any frame when fleet wiring is absent.
|
|
194
|
+
*/
|
|
94
195
|
stream(opts?: {
|
|
95
196
|
signal?: AbortSignal;
|
|
96
197
|
}): AsyncGenerator<FleetFrame>;
|