wicked-crew 0.7.32 → 0.7.34
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 +2 -1
- package/dist/api/chat-turns.d.ts +87 -0
- package/dist/api/chat-turns.d.ts.map +1 -0
- package/dist/api/chat-turns.js +147 -0
- package/dist/api/chat-turns.js.map +1 -0
- package/dist/api/eval-sample.d.ts +18 -18
- package/dist/api/governance-steering.d.ts +4 -4
- package/dist/api/roster-standing.d.ts +42 -0
- package/dist/api/roster-standing.d.ts.map +1 -0
- package/dist/api/roster-standing.js +54 -0
- package/dist/api/roster-standing.js.map +1 -0
- package/dist/api/routes.d.ts +61 -3
- package/dist/api/routes.d.ts.map +1 -1
- package/dist/api/routes.js +171 -42
- package/dist/api/routes.js.map +1 -1
- package/dist/api/server.d.ts.map +1 -1
- package/dist/api/server.js +89 -1
- package/dist/api/server.js.map +1 -1
- package/dist/api/skills.d.ts.map +1 -1
- package/dist/api/skills.js +12 -3
- package/dist/api/skills.js.map +1 -1
- package/dist/api/testing.d.ts +4 -4
- package/dist/campaigns/routes.d.ts +14 -14
- package/dist/cli/index.js +23 -3
- package/dist/cli/index.js.map +1 -1
- package/dist/core/adapter.d.ts +30 -0
- package/dist/core/adapter.d.ts.map +1 -1
- package/dist/core/adapter.js +66 -2
- package/dist/core/adapter.js.map +1 -1
- package/dist/core/engine-roster.d.ts +28 -0
- package/dist/core/engine-roster.d.ts.map +1 -1
- package/dist/core/engine-roster.js +28 -0
- package/dist/core/engine-roster.js.map +1 -1
- package/dist/core/types.d.ts +9 -0
- package/dist/core/types.d.ts.map +1 -1
- package/dist/core/types.js +6 -0
- package/dist/core/types.js.map +1 -1
- package/dist/interactive/bridge-pool.d.ts +2 -2
- package/dist/interactive/bridge-pool.d.ts.map +1 -1
- package/dist/interactive/bridge-pool.js +19 -4
- package/dist/interactive/bridge-pool.js.map +1 -1
- package/dist/interactive/bus-subscriber-errors.d.ts +61 -0
- package/dist/interactive/bus-subscriber-errors.d.ts.map +1 -0
- package/dist/interactive/bus-subscriber-errors.js +85 -0
- package/dist/interactive/bus-subscriber-errors.js.map +1 -0
- package/dist/interactive/chat-events.d.ts +16 -0
- package/dist/interactive/chat-events.d.ts.map +1 -1
- package/dist/interactive/chat-events.js +59 -10
- package/dist/interactive/chat-events.js.map +1 -1
- package/dist/interactive/demo-events.d.ts +66 -0
- package/dist/interactive/demo-events.d.ts.map +1 -1
- package/dist/interactive/demo-events.js +154 -10
- package/dist/interactive/demo-events.js.map +1 -1
- package/dist/interactive/doc-delete-routes.js +2 -2
- package/dist/interactive/doc-delete-routes.js.map +1 -1
- package/dist/interactive/draft-events.d.ts +13 -0
- package/dist/interactive/draft-events.d.ts.map +1 -1
- package/dist/interactive/draft-events.js +34 -9
- package/dist/interactive/draft-events.js.map +1 -1
- package/dist/interactive/draft-skill.d.ts +68 -0
- package/dist/interactive/draft-skill.d.ts.map +1 -0
- package/dist/interactive/draft-skill.js +127 -0
- package/dist/interactive/draft-skill.js.map +1 -0
- package/dist/interactive/edit-events.d.ts +13 -0
- package/dist/interactive/edit-events.d.ts.map +1 -1
- package/dist/interactive/edit-events.js +35 -9
- package/dist/interactive/edit-events.js.map +1 -1
- package/dist/interactive/proxy-routes.d.ts +36 -0
- package/dist/interactive/proxy-routes.d.ts.map +1 -1
- package/dist/interactive/proxy-routes.js +90 -3
- package/dist/interactive/proxy-routes.js.map +1 -1
- package/dist/interactive/ws-relay.d.ts +2 -0
- package/dist/interactive/ws-relay.d.ts.map +1 -1
- package/dist/interactive/ws-relay.js +7 -3
- package/dist/interactive/ws-relay.js.map +1 -1
- package/dist/projects/activity.d.ts +17 -3
- package/dist/projects/activity.d.ts.map +1 -1
- package/dist/projects/activity.js +34 -13
- package/dist/projects/activity.js.map +1 -1
- package/dist/projects/events.d.ts +2 -0
- package/dist/projects/events.d.ts.map +1 -1
- package/dist/projects/events.js +7 -3
- package/dist/projects/events.js.map +1 -1
- package/dist/projects/state-home-preflight.d.ts +163 -0
- package/dist/projects/state-home-preflight.d.ts.map +1 -0
- package/dist/projects/state-home-preflight.js +310 -0
- package/dist/projects/state-home-preflight.js.map +1 -0
- package/dist/projects/state-home-registry.d.ts +25 -0
- package/dist/projects/state-home-registry.d.ts.map +1 -0
- package/dist/projects/state-home-registry.js +50 -0
- package/dist/projects/state-home-registry.js.map +1 -0
- package/dist/qe/gate-events.d.ts +2 -0
- package/dist/qe/gate-events.d.ts.map +1 -1
- package/dist/qe/gate-events.js +7 -3
- package/dist/qe/gate-events.js.map +1 -1
- package/dist/skills/base-skill.d.ts +92 -0
- package/dist/skills/base-skill.d.ts.map +1 -0
- package/dist/skills/base-skill.js +105 -0
- package/dist/skills/base-skill.js.map +1 -0
- package/dist/skills/runtime.d.ts +43 -1
- package/dist/skills/runtime.d.ts.map +1 -1
- package/dist/skills/runtime.js +110 -5
- package/dist/skills/runtime.js.map +1 -1
- package/dist/skills/store.d.ts +11 -0
- package/dist/skills/store.d.ts.map +1 -1
- package/dist/skills/store.js +16 -0
- package/dist/skills/store.js.map +1 -1
- package/dist/studio/assets/{index-Clm0MXDF.js → index-DhojBZ1T.js} +91 -91
- package/dist/studio/index.html +1 -1
- package/dist/studio/testid-inventory.json +51 -3
- package/endpoint-manifest.json +2 -1
- package/package.json +4 -4
package/README.md
CHANGED
|
@@ -39,7 +39,8 @@ engine cannot store dead-letter to
|
|
|
39
39
|
`WICKED_APPS_EMIT_DEADLETTER` is honoured), are counted on
|
|
40
40
|
`GET /api/v1/diagnostics` → `governance` (a `governance.deadletter` finding), and are drained back
|
|
41
41
|
with `wicked-crew governance replay <outbox>`. The interactive document bridge is spawned on demand
|
|
42
|
-
as `npx wicked-interactive@^0.9.
|
|
42
|
+
as `npx wicked-interactive@^0.9.2` (0.9.2: recorder browser preflight + provisioning, typed `RecorderError`
|
|
43
|
+
frames); `WICKED_INTERACTIVE_SPEC` overrides the range (semver range
|
|
43
44
|
only, validated; invalid values are named on the boot line and ignored, a floor below crew's need
|
|
44
45
|
is warned about).
|
|
45
46
|
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Per-chat TURN tracking for `POST /chats/:id/messages` (F-RECON-017).
|
|
3
|
+
*
|
|
4
|
+
* The engine queues a message sent to a seat that is still answering the previous one — silently:
|
|
5
|
+
* `chatSend` answers the seats it accepted, the worker receives the text the instant the previous
|
|
6
|
+
* turn's final block lands, and the reply frames (`chatDelta` / `chatReply`) carry chat + seat but
|
|
7
|
+
* NO message correlation. The recon saw exactly that: Q3 sent 58 s into Q2's turn got a 202, and
|
|
8
|
+
* Q2's reply then rendered under Q3's bubble. Neither the daemon nor the skin could tell.
|
|
9
|
+
*
|
|
10
|
+
* This index is the daemon's own record of which seats are mid-turn in which chat:
|
|
11
|
+
*
|
|
12
|
+
* - `begin` opens a turn for the seats a send actually reached (the engine's answer) and mints a
|
|
13
|
+
* `turnId` the 202 returns;
|
|
14
|
+
* - `inFlight` is the refusal predicate the route consults FIRST: a send that targets a seat still
|
|
15
|
+
* mid-turn is refused (409 `turn_in_flight`, naming the turn and the busy seats) — targeting
|
|
16
|
+
* only idle seats passes, so a stalled seat (opencode 0 bytes for 300 s) never blocks a
|
|
17
|
+
* follow-up to the one that answered;
|
|
18
|
+
* - `observe` folds the engine's frames: a seat's `chatReply` (ok or not) or `chatSessionFailed`
|
|
19
|
+
* ends its part of the turn, `chatClosed` drops the chat's turns;
|
|
20
|
+
* - `decorate` stamps `turn_id` onto the chat frames of a seat mid-turn, so a skin can file a
|
|
21
|
+
* delta/reply under the message it answers instead of the newest bubble.
|
|
22
|
+
*
|
|
23
|
+
* A turn whose frames were lost (an engine restart, a seat reaped without a frame) must never wedge
|
|
24
|
+
* the chat: a turn older than `staleAfterMs` (default 15 min — three engine turn budgets) is treated
|
|
25
|
+
* as ended by every read, and reported in the 409's `stale` reason when it is what let a send pass.
|
|
26
|
+
*/
|
|
27
|
+
import type { CoreEvent } from '../core/types.js';
|
|
28
|
+
/** One live turn: the message a set of seats is answering. */
|
|
29
|
+
export interface ChatTurn {
|
|
30
|
+
turnId: string;
|
|
31
|
+
chatId: string;
|
|
32
|
+
/** Every seat the send reached (the engine's `chatSend` answer). */
|
|
33
|
+
seats: string[];
|
|
34
|
+
/** The seats that have not ended their part yet. */
|
|
35
|
+
pending: string[];
|
|
36
|
+
/** Epoch ms of the accepted send. */
|
|
37
|
+
startedAt: number;
|
|
38
|
+
/** A bounded excerpt of the message, for the 409 body and diagnostics. */
|
|
39
|
+
excerpt: string;
|
|
40
|
+
}
|
|
41
|
+
/** What a refused send is told (the 409 body's `turn`). */
|
|
42
|
+
export interface ChatTurnInFlight {
|
|
43
|
+
turnId: string;
|
|
44
|
+
chatId: string;
|
|
45
|
+
seats: string[];
|
|
46
|
+
/** The targeted seats still answering — the reason for the refusal. */
|
|
47
|
+
busy: string[];
|
|
48
|
+
startedAt: number;
|
|
49
|
+
ageMs: number;
|
|
50
|
+
excerpt: string;
|
|
51
|
+
}
|
|
52
|
+
export declare const CHAT_TURN_EXCERPT_CHARS = 120;
|
|
53
|
+
/** Three engine turn budgets (300 s each): a turn this old with no closing frame is lost, not live. */
|
|
54
|
+
export declare const CHAT_TURN_STALE_AFTER_MS: number;
|
|
55
|
+
export declare class ChatTurnIndex {
|
|
56
|
+
/** chatId → live turns (a seat is in at most one — `inFlight` refuses the second). */
|
|
57
|
+
private readonly turns;
|
|
58
|
+
private readonly now;
|
|
59
|
+
private readonly staleAfterMs;
|
|
60
|
+
constructor(opts?: {
|
|
61
|
+
now?: () => number;
|
|
62
|
+
staleAfterMs?: number;
|
|
63
|
+
});
|
|
64
|
+
/** Drop turns whose frames were lost (see the module doc); returns the survivors. */
|
|
65
|
+
private live;
|
|
66
|
+
/**
|
|
67
|
+
* The turn that makes a send to `targets` (every seat of the chat when omitted) refusable: one
|
|
68
|
+
* whose pending seats intersect the targets. `null` when every targeted seat is idle.
|
|
69
|
+
*/
|
|
70
|
+
inFlight(chatId: string, targets?: readonly string[]): ChatTurnInFlight | null;
|
|
71
|
+
/** Open a turn for the seats a send reached. An empty seat list opens nothing (nothing to wait for). */
|
|
72
|
+
begin(chatId: string, seats: readonly string[], text: string): ChatTurn | null;
|
|
73
|
+
/** The live turn a seat of a chat is answering, if any. */
|
|
74
|
+
turnOf(chatId: string, cliKey: string): ChatTurn | undefined;
|
|
75
|
+
/** Every live turn of a chat (diagnostics / tests). */
|
|
76
|
+
turnsOf(chatId: string): ChatTurn[];
|
|
77
|
+
/** Fold one engine frame. Safe on every event type; non-chat frames are ignored. */
|
|
78
|
+
observe(event: CoreEvent): void;
|
|
79
|
+
/**
|
|
80
|
+
* The frame with `turn_id` stamped when it is a seat's progress on a live turn; the frame itself
|
|
81
|
+
* otherwise. Call BEFORE `observe` — the closing `chatReply` is the one most worth correlating.
|
|
82
|
+
*/
|
|
83
|
+
decorate(event: CoreEvent): CoreEvent;
|
|
84
|
+
/** The chat is gone (a `DELETE` or an engine reclaim) — nothing left to wait for. */
|
|
85
|
+
closed(chatId: string): void;
|
|
86
|
+
}
|
|
87
|
+
//# sourceMappingURL=chat-turns.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chat-turns.d.ts","sourceRoot":"","sources":["../../src/api/chat-turns.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAGH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAElD,8DAA8D;AAC9D,MAAM,WAAW,QAAQ;IACvB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,oEAAoE;IACpE,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,oDAAoD;IACpD,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,qCAAqC;IACrC,SAAS,EAAE,MAAM,CAAC;IAClB,0EAA0E;IAC1E,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,2DAA2D;AAC3D,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,uEAAuE;IACvE,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,eAAO,MAAM,uBAAuB,MAAM,CAAC;AAC3C,uGAAuG;AACvG,eAAO,MAAM,wBAAwB,QAAc,CAAC;AAYpD,qBAAa,aAAa;IACxB,sFAAsF;IACtF,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAiC;IACvD,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAe;IACnC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAS;gBAE1B,IAAI,GAAE;QAAE,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;QAAC,YAAY,CAAC,EAAE,MAAM,CAAA;KAAO;IAKpE,qFAAqF;IACrF,OAAO,CAAC,IAAI;IAUZ;;;OAGG;IACH,QAAQ,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,SAAS,MAAM,EAAE,GAAG,gBAAgB,GAAG,IAAI;IAiB9E,wGAAwG;IACxG,KAAK,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,MAAM,EAAE,EAAE,IAAI,EAAE,MAAM,GAAG,QAAQ,GAAG,IAAI;IAiB9E,2DAA2D;IAC3D,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,QAAQ,GAAG,SAAS;IAI5D,uDAAuD;IACvD,OAAO,CAAC,MAAM,EAAE,MAAM,GAAG,QAAQ,EAAE;IAInC,oFAAoF;IACpF,OAAO,CAAC,KAAK,EAAE,SAAS,GAAG,IAAI;IAgB/B;;;OAGG;IACH,QAAQ,CAAC,KAAK,EAAE,SAAS,GAAG,SAAS;IASrC,qFAAqF;IACrF,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;CAG7B"}
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Per-chat TURN tracking for `POST /chats/:id/messages` (F-RECON-017).
|
|
3
|
+
*
|
|
4
|
+
* The engine queues a message sent to a seat that is still answering the previous one — silently:
|
|
5
|
+
* `chatSend` answers the seats it accepted, the worker receives the text the instant the previous
|
|
6
|
+
* turn's final block lands, and the reply frames (`chatDelta` / `chatReply`) carry chat + seat but
|
|
7
|
+
* NO message correlation. The recon saw exactly that: Q3 sent 58 s into Q2's turn got a 202, and
|
|
8
|
+
* Q2's reply then rendered under Q3's bubble. Neither the daemon nor the skin could tell.
|
|
9
|
+
*
|
|
10
|
+
* This index is the daemon's own record of which seats are mid-turn in which chat:
|
|
11
|
+
*
|
|
12
|
+
* - `begin` opens a turn for the seats a send actually reached (the engine's answer) and mints a
|
|
13
|
+
* `turnId` the 202 returns;
|
|
14
|
+
* - `inFlight` is the refusal predicate the route consults FIRST: a send that targets a seat still
|
|
15
|
+
* mid-turn is refused (409 `turn_in_flight`, naming the turn and the busy seats) — targeting
|
|
16
|
+
* only idle seats passes, so a stalled seat (opencode 0 bytes for 300 s) never blocks a
|
|
17
|
+
* follow-up to the one that answered;
|
|
18
|
+
* - `observe` folds the engine's frames: a seat's `chatReply` (ok or not) or `chatSessionFailed`
|
|
19
|
+
* ends its part of the turn, `chatClosed` drops the chat's turns;
|
|
20
|
+
* - `decorate` stamps `turn_id` onto the chat frames of a seat mid-turn, so a skin can file a
|
|
21
|
+
* delta/reply under the message it answers instead of the newest bubble.
|
|
22
|
+
*
|
|
23
|
+
* A turn whose frames were lost (an engine restart, a seat reaped without a frame) must never wedge
|
|
24
|
+
* the chat: a turn older than `staleAfterMs` (default 15 min — three engine turn budgets) is treated
|
|
25
|
+
* as ended by every read, and reported in the 409's `stale` reason when it is what let a send pass.
|
|
26
|
+
*/
|
|
27
|
+
import { randomUUID } from 'node:crypto';
|
|
28
|
+
export const CHAT_TURN_EXCERPT_CHARS = 120;
|
|
29
|
+
/** Three engine turn budgets (300 s each): a turn this old with no closing frame is lost, not live. */
|
|
30
|
+
export const CHAT_TURN_STALE_AFTER_MS = 15 * 60_000;
|
|
31
|
+
/** The frame kinds that carry a seat's progress on a turn (`chat` + `cliKey` fields). */
|
|
32
|
+
const SEAT_PROGRESS_FRAMES = new Set(['chatDelta', 'chatReply', 'chatSessionFailed']);
|
|
33
|
+
/** The frame kinds that END a seat's part of its turn. */
|
|
34
|
+
const SEAT_DONE_FRAMES = new Set(['chatReply', 'chatSessionFailed']);
|
|
35
|
+
function excerptOf(text) {
|
|
36
|
+
const one = text.replace(/\s+/g, ' ').trim();
|
|
37
|
+
return one.length > CHAT_TURN_EXCERPT_CHARS ? `${one.slice(0, CHAT_TURN_EXCERPT_CHARS)}…` : one;
|
|
38
|
+
}
|
|
39
|
+
export class ChatTurnIndex {
|
|
40
|
+
/** chatId → live turns (a seat is in at most one — `inFlight` refuses the second). */
|
|
41
|
+
turns = new Map();
|
|
42
|
+
now;
|
|
43
|
+
staleAfterMs;
|
|
44
|
+
constructor(opts = {}) {
|
|
45
|
+
this.now = opts.now ?? Date.now;
|
|
46
|
+
this.staleAfterMs = opts.staleAfterMs ?? CHAT_TURN_STALE_AFTER_MS;
|
|
47
|
+
}
|
|
48
|
+
/** Drop turns whose frames were lost (see the module doc); returns the survivors. */
|
|
49
|
+
live(chatId) {
|
|
50
|
+
const list = this.turns.get(chatId);
|
|
51
|
+
if (list === undefined)
|
|
52
|
+
return [];
|
|
53
|
+
const now = this.now();
|
|
54
|
+
const kept = list.filter((t) => t.pending.length > 0 && now - t.startedAt < this.staleAfterMs);
|
|
55
|
+
if (kept.length === 0)
|
|
56
|
+
this.turns.delete(chatId);
|
|
57
|
+
else if (kept.length !== list.length)
|
|
58
|
+
this.turns.set(chatId, kept);
|
|
59
|
+
return kept;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* The turn that makes a send to `targets` (every seat of the chat when omitted) refusable: one
|
|
63
|
+
* whose pending seats intersect the targets. `null` when every targeted seat is idle.
|
|
64
|
+
*/
|
|
65
|
+
inFlight(chatId, targets) {
|
|
66
|
+
for (const turn of this.live(chatId)) {
|
|
67
|
+
const busy = targets === undefined ? [...turn.pending] : turn.pending.filter((s) => targets.includes(s));
|
|
68
|
+
if (busy.length === 0)
|
|
69
|
+
continue;
|
|
70
|
+
return {
|
|
71
|
+
turnId: turn.turnId,
|
|
72
|
+
chatId,
|
|
73
|
+
seats: [...turn.seats],
|
|
74
|
+
busy,
|
|
75
|
+
startedAt: turn.startedAt,
|
|
76
|
+
ageMs: Math.max(0, this.now() - turn.startedAt),
|
|
77
|
+
excerpt: turn.excerpt,
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
return null;
|
|
81
|
+
}
|
|
82
|
+
/** Open a turn for the seats a send reached. An empty seat list opens nothing (nothing to wait for). */
|
|
83
|
+
begin(chatId, seats, text) {
|
|
84
|
+
const unique = [...new Set(seats)];
|
|
85
|
+
if (unique.length === 0)
|
|
86
|
+
return null;
|
|
87
|
+
const turn = {
|
|
88
|
+
turnId: randomUUID(),
|
|
89
|
+
chatId,
|
|
90
|
+
seats: unique,
|
|
91
|
+
pending: [...unique],
|
|
92
|
+
startedAt: this.now(),
|
|
93
|
+
excerpt: excerptOf(text),
|
|
94
|
+
};
|
|
95
|
+
const list = this.live(chatId);
|
|
96
|
+
list.push(turn);
|
|
97
|
+
this.turns.set(chatId, list);
|
|
98
|
+
return turn;
|
|
99
|
+
}
|
|
100
|
+
/** The live turn a seat of a chat is answering, if any. */
|
|
101
|
+
turnOf(chatId, cliKey) {
|
|
102
|
+
return this.live(chatId).find((t) => t.pending.includes(cliKey));
|
|
103
|
+
}
|
|
104
|
+
/** Every live turn of a chat (diagnostics / tests). */
|
|
105
|
+
turnsOf(chatId) {
|
|
106
|
+
return this.live(chatId).map((t) => ({ ...t, seats: [...t.seats], pending: [...t.pending] }));
|
|
107
|
+
}
|
|
108
|
+
/** Fold one engine frame. Safe on every event type; non-chat frames are ignored. */
|
|
109
|
+
observe(event) {
|
|
110
|
+
const chatId = typeof event.chat === 'string' ? event.chat : undefined;
|
|
111
|
+
if (chatId === undefined)
|
|
112
|
+
return;
|
|
113
|
+
if (event.type === 'chatClosed') {
|
|
114
|
+
this.turns.delete(chatId);
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
117
|
+
if (!SEAT_DONE_FRAMES.has(event.type))
|
|
118
|
+
return;
|
|
119
|
+
const cliKey = typeof event.cliKey === 'string' ? event.cliKey : undefined;
|
|
120
|
+
if (cliKey === undefined)
|
|
121
|
+
return;
|
|
122
|
+
const turn = this.turnOf(chatId, cliKey);
|
|
123
|
+
if (turn === undefined)
|
|
124
|
+
return;
|
|
125
|
+
turn.pending = turn.pending.filter((s) => s !== cliKey);
|
|
126
|
+
this.live(chatId); // prunes the turn once its last seat ended
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* The frame with `turn_id` stamped when it is a seat's progress on a live turn; the frame itself
|
|
130
|
+
* otherwise. Call BEFORE `observe` — the closing `chatReply` is the one most worth correlating.
|
|
131
|
+
*/
|
|
132
|
+
decorate(event) {
|
|
133
|
+
if (!SEAT_PROGRESS_FRAMES.has(event.type))
|
|
134
|
+
return event;
|
|
135
|
+
const chatId = typeof event.chat === 'string' ? event.chat : undefined;
|
|
136
|
+
const cliKey = typeof event.cliKey === 'string' ? event.cliKey : undefined;
|
|
137
|
+
if (chatId === undefined || cliKey === undefined)
|
|
138
|
+
return event;
|
|
139
|
+
const turn = this.turnOf(chatId, cliKey);
|
|
140
|
+
return turn === undefined ? event : { ...event, turn_id: turn.turnId };
|
|
141
|
+
}
|
|
142
|
+
/** The chat is gone (a `DELETE` or an engine reclaim) — nothing left to wait for. */
|
|
143
|
+
closed(chatId) {
|
|
144
|
+
this.turns.delete(chatId);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
//# sourceMappingURL=chat-turns.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chat-turns.js","sourceRoot":"","sources":["../../src/api/chat-turns.ts"],"names":[],"mappings":"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"}
|
|
@@ -23,14 +23,14 @@ export const EvalSignalsSchema: z.ZodObject<{
|
|
|
23
23
|
files: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
24
24
|
content: z.ZodOptional<z.ZodString>;
|
|
25
25
|
}, "strict", z.ZodTypeAny, {
|
|
26
|
-
content?: string | undefined;
|
|
27
26
|
tool?: string | undefined;
|
|
28
27
|
files?: string[] | undefined;
|
|
28
|
+
content?: string | undefined;
|
|
29
29
|
phase?: string | undefined;
|
|
30
30
|
}, {
|
|
31
|
-
content?: string | undefined;
|
|
32
31
|
tool?: string | undefined;
|
|
33
32
|
files?: string[] | undefined;
|
|
33
|
+
content?: string | undefined;
|
|
34
34
|
phase?: string | undefined;
|
|
35
35
|
}>;
|
|
36
36
|
export const EvalSampleSchema: z.ZodObject<{
|
|
@@ -44,36 +44,36 @@ export const EvalSampleSchema: z.ZodObject<{
|
|
|
44
44
|
files: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
45
45
|
content: z.ZodOptional<z.ZodString>;
|
|
46
46
|
}, "strict", z.ZodTypeAny, {
|
|
47
|
-
content?: string | undefined;
|
|
48
47
|
tool?: string | undefined;
|
|
49
48
|
files?: string[] | undefined;
|
|
49
|
+
content?: string | undefined;
|
|
50
50
|
phase?: string | undefined;
|
|
51
51
|
}, {
|
|
52
|
-
content?: string | undefined;
|
|
53
52
|
tool?: string | undefined;
|
|
54
53
|
files?: string[] | undefined;
|
|
54
|
+
content?: string | undefined;
|
|
55
55
|
phase?: string | undefined;
|
|
56
56
|
}>;
|
|
57
57
|
}, "strict", z.ZodTypeAny, {
|
|
58
|
-
id: string;
|
|
59
58
|
kind: "good" | "bad";
|
|
59
|
+
id: string;
|
|
60
60
|
description: string;
|
|
61
61
|
steering_type: string;
|
|
62
62
|
signals: {
|
|
63
|
-
content?: string | undefined;
|
|
64
63
|
tool?: string | undefined;
|
|
65
64
|
files?: string[] | undefined;
|
|
65
|
+
content?: string | undefined;
|
|
66
66
|
phase?: string | undefined;
|
|
67
67
|
};
|
|
68
68
|
}, {
|
|
69
|
-
id: string;
|
|
70
69
|
kind: "good" | "bad";
|
|
70
|
+
id: string;
|
|
71
71
|
description: string;
|
|
72
72
|
steering_type: string;
|
|
73
73
|
signals: {
|
|
74
|
-
content?: string | undefined;
|
|
75
74
|
tool?: string | undefined;
|
|
76
75
|
files?: string[] | undefined;
|
|
76
|
+
content?: string | undefined;
|
|
77
77
|
phase?: string | undefined;
|
|
78
78
|
};
|
|
79
79
|
}>;
|
|
@@ -90,64 +90,64 @@ export const ImportEvalCorpusSchema: z.ZodObject<{
|
|
|
90
90
|
files: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
91
91
|
content: z.ZodOptional<z.ZodString>;
|
|
92
92
|
}, "strict", z.ZodTypeAny, {
|
|
93
|
-
content?: string | undefined;
|
|
94
93
|
tool?: string | undefined;
|
|
95
94
|
files?: string[] | undefined;
|
|
95
|
+
content?: string | undefined;
|
|
96
96
|
phase?: string | undefined;
|
|
97
97
|
}, {
|
|
98
|
-
content?: string | undefined;
|
|
99
98
|
tool?: string | undefined;
|
|
100
99
|
files?: string[] | undefined;
|
|
100
|
+
content?: string | undefined;
|
|
101
101
|
phase?: string | undefined;
|
|
102
102
|
}>;
|
|
103
103
|
}, "strict", z.ZodTypeAny, {
|
|
104
|
-
id: string;
|
|
105
104
|
kind: "good" | "bad";
|
|
105
|
+
id: string;
|
|
106
106
|
description: string;
|
|
107
107
|
steering_type: string;
|
|
108
108
|
signals: {
|
|
109
|
-
content?: string | undefined;
|
|
110
109
|
tool?: string | undefined;
|
|
111
110
|
files?: string[] | undefined;
|
|
111
|
+
content?: string | undefined;
|
|
112
112
|
phase?: string | undefined;
|
|
113
113
|
};
|
|
114
114
|
}, {
|
|
115
|
-
id: string;
|
|
116
115
|
kind: "good" | "bad";
|
|
116
|
+
id: string;
|
|
117
117
|
description: string;
|
|
118
118
|
steering_type: string;
|
|
119
119
|
signals: {
|
|
120
|
-
content?: string | undefined;
|
|
121
120
|
tool?: string | undefined;
|
|
122
121
|
files?: string[] | undefined;
|
|
122
|
+
content?: string | undefined;
|
|
123
123
|
phase?: string | undefined;
|
|
124
124
|
};
|
|
125
125
|
}>, "many">;
|
|
126
126
|
}, "strict", z.ZodTypeAny, {
|
|
127
127
|
name: string;
|
|
128
128
|
samples: {
|
|
129
|
-
id: string;
|
|
130
129
|
kind: "good" | "bad";
|
|
130
|
+
id: string;
|
|
131
131
|
description: string;
|
|
132
132
|
steering_type: string;
|
|
133
133
|
signals: {
|
|
134
|
-
content?: string | undefined;
|
|
135
134
|
tool?: string | undefined;
|
|
136
135
|
files?: string[] | undefined;
|
|
136
|
+
content?: string | undefined;
|
|
137
137
|
phase?: string | undefined;
|
|
138
138
|
};
|
|
139
139
|
}[];
|
|
140
140
|
}, {
|
|
141
141
|
name: string;
|
|
142
142
|
samples: {
|
|
143
|
-
id: string;
|
|
144
143
|
kind: "good" | "bad";
|
|
144
|
+
id: string;
|
|
145
145
|
description: string;
|
|
146
146
|
steering_type: string;
|
|
147
147
|
signals: {
|
|
148
|
-
content?: string | undefined;
|
|
149
148
|
tool?: string | undefined;
|
|
150
149
|
files?: string[] | undefined;
|
|
150
|
+
content?: string | undefined;
|
|
151
151
|
phase?: string | undefined;
|
|
152
152
|
};
|
|
153
153
|
}[];
|
|
@@ -93,11 +93,11 @@ export declare const SteeringAuthorSchema: z.ZodObject<{
|
|
|
93
93
|
name: z.ZodString;
|
|
94
94
|
content: z.ZodString;
|
|
95
95
|
}, "strict", z.ZodTypeAny, {
|
|
96
|
-
content: string;
|
|
97
96
|
name: string;
|
|
98
|
-
}, {
|
|
99
97
|
content: string;
|
|
98
|
+
}, {
|
|
100
99
|
name: string;
|
|
100
|
+
content: string;
|
|
101
101
|
}>, "many">>;
|
|
102
102
|
repoRef: z.ZodOptional<z.ZodString>;
|
|
103
103
|
sessionId: z.ZodOptional<z.ZodString>;
|
|
@@ -107,8 +107,8 @@ export declare const SteeringAuthorSchema: z.ZodObject<{
|
|
|
107
107
|
repoRef?: string | undefined;
|
|
108
108
|
paths?: string[] | undefined;
|
|
109
109
|
documents?: {
|
|
110
|
-
content: string;
|
|
111
110
|
name: string;
|
|
111
|
+
content: string;
|
|
112
112
|
}[] | undefined;
|
|
113
113
|
sessionId?: string | undefined;
|
|
114
114
|
}, {
|
|
@@ -117,8 +117,8 @@ export declare const SteeringAuthorSchema: z.ZodObject<{
|
|
|
117
117
|
repoRef?: string | undefined;
|
|
118
118
|
paths?: string[] | undefined;
|
|
119
119
|
documents?: {
|
|
120
|
-
content: string;
|
|
121
120
|
name: string;
|
|
121
|
+
content: string;
|
|
122
122
|
}[] | undefined;
|
|
123
123
|
sessionId?: string | undefined;
|
|
124
124
|
}>;
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The ONE roster accessor every launch path shares: the registry roster decorated with crew's
|
|
3
|
+
* STANDING (F-2R2-009) — runtime `health`, `signed_in`, `auth`, `council_eligible` + its reason,
|
|
4
|
+
* the council bench — so `engineRosterJson` (core/engine-roster.ts) can bench a seat the daemon
|
|
5
|
+
* already knows is unusable before the engine convenes it.
|
|
6
|
+
*
|
|
7
|
+
* F-RECON-002 / F-RECON-003: this used to be a closure inside `registerRoutes`, so ONLY the routes
|
|
8
|
+
* (`POST /runs`, `/testing/*`, campaigns, steering) launched with standing. The interactive seams
|
|
9
|
+
* (draft/edit/chat/demo subscribers), the adapter's onboarding launch (`seatsForWorkflow`) and
|
|
10
|
+
* `wicked-crew start` handed the engine `CoreAdapter.roster()` RAW — every interactive council
|
|
11
|
+
* convened codex/pi/copilot although the roster reported them `signed_out` (9–19 councilSeatFailed,
|
|
12
|
+
* 57–112 s of dead ballots per run), and one council ELECTED signed-out pi, which then failed its
|
|
13
|
+
* unit and fell over to claude. The factory below is what all of those now call; `createServer`
|
|
14
|
+
* builds exactly one over its `SeatHealthTracker` and hands the same function everywhere.
|
|
15
|
+
*
|
|
16
|
+
* Standing is read at CALL time (the tracker's live state, the LIVE `WICKED_WORKER_HOME`), never
|
|
17
|
+
* captured — a seat signed in from the System page is eligible on the very next launch.
|
|
18
|
+
*/
|
|
19
|
+
import type { RosterSeat } from '../core/types.js';
|
|
20
|
+
import type { SeatHealthTracker } from './seat-health.js';
|
|
21
|
+
/** The accessor: the registry roster WITH crew's standing, freshly read on every call. */
|
|
22
|
+
export type RosterWithStanding = () => RosterSeat[];
|
|
23
|
+
export interface RosterStandingDeps {
|
|
24
|
+
/** The daemon's per-seat runtime health + council evidence (councilSeatFailed, auth refusals). */
|
|
25
|
+
seatHealth: SeatHealthTracker;
|
|
26
|
+
/** Seat sign-in presence probe — injectable so tests never read the developer's dotfiles.
|
|
27
|
+
* Defaults to the file/env heuristic in seat-signin.ts. */
|
|
28
|
+
signedIn?: (seatKey: string, workerConfigRoot?: string) => boolean | null;
|
|
29
|
+
/** The registry roster (default: the engine's production roster via `CoreAdapter.roster()`).
|
|
30
|
+
* Injectable so a test decorates its own seats without the native addon. */
|
|
31
|
+
registry?: () => unknown[];
|
|
32
|
+
/** Where `WICKED_WORKER_HOME` is read from at call time (default `process.env`). */
|
|
33
|
+
env?: NodeJS.ProcessEnv;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Build the accessor. Each seat's registry fields ride through verbatim — the spread is
|
|
37
|
+
* deliberately NOT a field whitelist, which is what lets the engine's `login_invocation` pass
|
|
38
|
+
* untouched — and gains `health`, `signed_in`, and the standing readings (`auth`, `free_tier*`,
|
|
39
|
+
* `council_eligible`, `council_ineligible_reason`, `council_bench`, `auth_source/evidence`).
|
|
40
|
+
*/
|
|
41
|
+
export declare function rosterWithStandingFactory(deps: RosterStandingDeps): RosterWithStanding;
|
|
42
|
+
//# sourceMappingURL=roster-standing.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"roster-standing.d.ts","sourceRoot":"","sources":["../../src/api/roster-standing.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAGH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AACnD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAI1D,0FAA0F;AAC1F,MAAM,MAAM,kBAAkB,GAAG,MAAM,UAAU,EAAE,CAAC;AAEpD,MAAM,WAAW,kBAAkB;IACjC,kGAAkG;IAClG,UAAU,EAAE,iBAAiB,CAAC;IAC9B;gEAC4D;IAC5D,QAAQ,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,gBAAgB,CAAC,EAAE,MAAM,KAAK,OAAO,GAAG,IAAI,CAAC;IAC1E;iFAC6E;IAC7E,QAAQ,CAAC,EAAE,MAAM,OAAO,EAAE,CAAC;IAC3B,oFAAoF;IACpF,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;CACzB;AAED;;;;;GAKG;AACH,wBAAgB,yBAAyB,CAAC,IAAI,EAAE,kBAAkB,GAAG,kBAAkB,CA8BtF"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The ONE roster accessor every launch path shares: the registry roster decorated with crew's
|
|
3
|
+
* STANDING (F-2R2-009) — runtime `health`, `signed_in`, `auth`, `council_eligible` + its reason,
|
|
4
|
+
* the council bench — so `engineRosterJson` (core/engine-roster.ts) can bench a seat the daemon
|
|
5
|
+
* already knows is unusable before the engine convenes it.
|
|
6
|
+
*
|
|
7
|
+
* F-RECON-002 / F-RECON-003: this used to be a closure inside `registerRoutes`, so ONLY the routes
|
|
8
|
+
* (`POST /runs`, `/testing/*`, campaigns, steering) launched with standing. The interactive seams
|
|
9
|
+
* (draft/edit/chat/demo subscribers), the adapter's onboarding launch (`seatsForWorkflow`) and
|
|
10
|
+
* `wicked-crew start` handed the engine `CoreAdapter.roster()` RAW — every interactive council
|
|
11
|
+
* convened codex/pi/copilot although the roster reported them `signed_out` (9–19 councilSeatFailed,
|
|
12
|
+
* 57–112 s of dead ballots per run), and one council ELECTED signed-out pi, which then failed its
|
|
13
|
+
* unit and fell over to claude. The factory below is what all of those now call; `createServer`
|
|
14
|
+
* builds exactly one over its `SeatHealthTracker` and hands the same function everywhere.
|
|
15
|
+
*
|
|
16
|
+
* Standing is read at CALL time (the tracker's live state, the LIVE `WICKED_WORKER_HOME`), never
|
|
17
|
+
* captured — a seat signed in from the System page is eligible on the very next launch.
|
|
18
|
+
*/
|
|
19
|
+
import { CoreAdapter } from '../core/adapter.js';
|
|
20
|
+
import { signedInHeuristic } from './seat-signin.js';
|
|
21
|
+
import { seatStanding } from './seat-standing.js';
|
|
22
|
+
/**
|
|
23
|
+
* Build the accessor. Each seat's registry fields ride through verbatim — the spread is
|
|
24
|
+
* deliberately NOT a field whitelist, which is what lets the engine's `login_invocation` pass
|
|
25
|
+
* untouched — and gains `health`, `signed_in`, and the standing readings (`auth`, `free_tier*`,
|
|
26
|
+
* `council_eligible`, `council_ineligible_reason`, `council_bench`, `auth_source/evidence`).
|
|
27
|
+
*/
|
|
28
|
+
export function rosterWithStandingFactory(deps) {
|
|
29
|
+
const { seatHealth } = deps;
|
|
30
|
+
const signedIn = deps.signedIn ?? signedInHeuristic;
|
|
31
|
+
const registry = deps.registry ?? (() => CoreAdapter.roster());
|
|
32
|
+
const env = deps.env ?? process.env;
|
|
33
|
+
return () => {
|
|
34
|
+
const workerRoot = env['WICKED_WORKER_HOME'];
|
|
35
|
+
return registry().map((seat) => {
|
|
36
|
+
const key = String(seat.key);
|
|
37
|
+
const health = seatHealth.healthFor(key);
|
|
38
|
+
const signed = signedIn(key, workerRoot === '' ? undefined : workerRoot);
|
|
39
|
+
return {
|
|
40
|
+
...seat,
|
|
41
|
+
health,
|
|
42
|
+
signed_in: signed,
|
|
43
|
+
// The bench is THIS daemon's council evidence (councilSeatFailed, bounded window) — the
|
|
44
|
+
// prediction learns from what the engine actually did with the seat (#533 review, F-1).
|
|
45
|
+
...seatStanding(seat, signed, health, seatHealth.councilBenchFor(key),
|
|
46
|
+
// F-A45-006: the seat's OWN "no credential" report (a ballot's "No API key found", a
|
|
47
|
+
// worker's 401, an auth ACP fallback) overrides the file probe — `auth` flips, not only
|
|
48
|
+
// `council_eligible`, and the evidence rides on the wire.
|
|
49
|
+
seatHealth.authFailureFor(key)),
|
|
50
|
+
};
|
|
51
|
+
});
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
//# sourceMappingURL=roster-standing.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"roster-standing.js","sourceRoot":"","sources":["../../src/api/roster-standing.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAGjD,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAkBlD;;;;;GAKG;AACH,MAAM,UAAU,yBAAyB,CAAC,IAAwB;IAChE,MAAM,EAAE,UAAU,EAAE,GAAG,IAAI,CAAC;IAC5B,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,IAAI,iBAAiB,CAAC;IACpD,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,IAAI,CAAC,GAAG,EAAE,CAAC,WAAW,CAAC,MAAM,EAAE,CAAC,CAAC;IAC/D,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,IAAI,OAAO,CAAC,GAAG,CAAC;IACpC,OAAO,GAAiB,EAAE;QACxB,MAAM,UAAU,GAAG,GAAG,CAAC,oBAAoB,CAAC,CAAC;QAC7C,OAAQ,QAAQ,EAAmB,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE;YAC/C,MAAM,GAAG,GAAG,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YAC7B,MAAM,MAAM,GAAG,UAAU,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;YACzC,MAAM,MAAM,GAAG,QAAQ,CAAC,GAAG,EAAE,UAAU,KAAK,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC;YACzE,OAAO;gBACL,GAAG,IAAI;gBACP,MAAM;gBACN,SAAS,EAAE,MAAM;gBACjB,wFAAwF;gBACxF,wFAAwF;gBACxF,GAAG,YAAY,CACb,IAA+F,EAC/F,MAAM,EACN,MAAM,EACN,UAAU,CAAC,eAAe,CAAC,GAAG,CAAC;gBAC/B,qFAAqF;gBACrF,wFAAwF;gBACxF,0DAA0D;gBAC1D,UAAU,CAAC,cAAc,CAAC,GAAG,CAAC,CAC/B;aACF,CAAC;QACJ,CAAC,CAAC,CAAC;IACL,CAAC,CAAC;AACJ,CAAC"}
|