@shardworks/spider-apparatus 0.1.226 → 0.1.228
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 +20 -4
- package/dist/default-template.d.ts +23 -0
- package/dist/default-template.d.ts.map +1 -0
- package/dist/default-template.js +60 -0
- package/dist/default-template.js.map +1 -0
- package/dist/engines/implement.d.ts +15 -5
- package/dist/engines/implement.d.ts.map +1 -1
- package/dist/engines/implement.js +24 -6
- package/dist/engines/implement.js.map +1 -1
- package/dist/oculus-routes.d.ts +17 -2
- package/dist/oculus-routes.d.ts.map +1 -1
- package/dist/oculus-routes.js +9 -79
- package/dist/oculus-routes.js.map +1 -1
- package/dist/spider.d.ts.map +1 -1
- package/dist/spider.js +58 -15
- package/dist/spider.js.map +1 -1
- package/dist/tools/input-request-list.d.ts +1 -1
- package/dist/tools/rig-list.d.ts +2 -2
- package/package.json +9 -9
- package/src/static/spider-ui.test.ts +241 -67
- package/src/static/spider.js +151 -188
package/README.md
CHANGED
|
@@ -125,7 +125,21 @@ Return the merged effective writ-type → template-name mapping. Config mappings
|
|
|
125
125
|
|
|
126
126
|
## Configuration
|
|
127
127
|
|
|
128
|
-
The Spider reads its config from `guild.json["spider"]`:
|
|
128
|
+
The Spider reads its config from `guild.json["spider"]`. Zero-config works out of the box for mandate dispatch — Spider's apparatus contributes a plugin-default rig template (`default`: draft → implement → review → revise → seal) and a default mapping (`mandate → default`) via its own supportKit. A minimal guild only needs to declare `spider.variables` so the default template can interpolate role / build command / test command:
|
|
129
|
+
|
|
130
|
+
```json
|
|
131
|
+
{
|
|
132
|
+
"spider": {
|
|
133
|
+
"variables": {
|
|
134
|
+
"role": "artificer",
|
|
135
|
+
"buildCommand": "pnpm -w build",
|
|
136
|
+
"testCommand": "pnpm -w test"
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
Guilds that need a custom pipeline can override the plugin defaults by declaring their own `rigTemplates` and/or `rigTemplateMappings`:
|
|
129
143
|
|
|
130
144
|
```json
|
|
131
145
|
{
|
|
@@ -166,14 +180,16 @@ The Spider reads its config from `guild.json["spider"]`:
|
|
|
166
180
|
}
|
|
167
181
|
```
|
|
168
182
|
|
|
183
|
+
A config-level template named `default` overrides the plugin-contributed `spider.default` for the `mandate → default` lookup: the registry resolves the kit mapping against the bare name first, then falls back to `${pluginId}.${templateName}` when the bare name is not claimed.
|
|
184
|
+
|
|
169
185
|
| Field | Type | Default | Description |
|
|
170
186
|
|---|---|---|---|
|
|
171
187
|
| `pollIntervalMs` | `number` | `5000` | Polling interval for the `crawl-continual` tool (ms). |
|
|
172
188
|
| `buildCommand` | `string` | — | Build command forwarded to quick engines. |
|
|
173
189
|
| `testCommand` | `string` | — | Test command forwarded to quick engines. |
|
|
174
|
-
| `variables` | `Record<string, unknown>` | — | Named values available in rig template givens via `${vars.<path>}`. |
|
|
175
|
-
| `rigTemplates` | `Record<string, RigTemplate>` |
|
|
176
|
-
| `rigTemplateMappings` | `Record<string, string>` |
|
|
190
|
+
| `variables` | `Record<string, unknown>` | — | Named values available in rig template givens via `${vars.<path>}`. The plugin-default template requires `role`, `buildCommand`, and `testCommand`. |
|
|
191
|
+
| `rigTemplates` | `Record<string, RigTemplate>` | plugin default `default` (draft → seal) | Named rig template definitions. Config-level entries override plugin-contributed templates of the same name. |
|
|
192
|
+
| `rigTemplateMappings` | `Record<string, string>` | plugin default `{ mandate: 'default' }` | Writ type → template name. Config-level entries override plugin-contributed mappings for the same writ type. |
|
|
177
193
|
| `maxConcurrentEngines` | `number` | `3` | Maximum number of engines running concurrently across all rigs. When the limit is reached, runnable engines stay in `pending` and new rigs are not spawned until a slot frees. |
|
|
178
194
|
| `maxConcurrentEnginesPerRig` | `number` | `1` | Maximum number of engines running concurrently within a single rig. Prevents race conditions with rig-local resources. |
|
|
179
195
|
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Spider's plugin-default rig template (`default`).
|
|
3
|
+
*
|
|
4
|
+
* This is the canonical draft → implement → review → revise → seal
|
|
5
|
+
* pipeline that every guild used to declare inline under
|
|
6
|
+
* `spider.rigTemplates.default` in its `guild.json`. It is now
|
|
7
|
+
* contributed as a plugin default so mandate dispatch works out of the
|
|
8
|
+
* box with zero guild configuration — an operator only needs to declare
|
|
9
|
+
* `spider.variables` for the role and build/test commands.
|
|
10
|
+
*
|
|
11
|
+
* Guilds may still override this template by declaring their own
|
|
12
|
+
* `spider.rigTemplates.default` in guild.json; config entries win over
|
|
13
|
+
* plugin-contributed defaults via the RigTemplateRegistry's precedence
|
|
14
|
+
* rules.
|
|
15
|
+
*
|
|
16
|
+
* Per D7 in the plan-and-ship commission, this template has no fallback
|
|
17
|
+
* defaults for `${vars.role}`, `${vars.buildCommand}`, or
|
|
18
|
+
* `${vars.testCommand}` — a missing variable raises at dispatch time so
|
|
19
|
+
* misconfiguration is surfaced loudly rather than masked.
|
|
20
|
+
*/
|
|
21
|
+
import type { RigTemplate } from './types.ts';
|
|
22
|
+
export declare const defaultRigTemplate: RigTemplate;
|
|
23
|
+
//# sourceMappingURL=default-template.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"default-template.d.ts","sourceRoot":"","sources":["../src/default-template.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAE9C,eAAO,MAAM,kBAAkB,EAAE,WAsChC,CAAC"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Spider's plugin-default rig template (`default`).
|
|
3
|
+
*
|
|
4
|
+
* This is the canonical draft → implement → review → revise → seal
|
|
5
|
+
* pipeline that every guild used to declare inline under
|
|
6
|
+
* `spider.rigTemplates.default` in its `guild.json`. It is now
|
|
7
|
+
* contributed as a plugin default so mandate dispatch works out of the
|
|
8
|
+
* box with zero guild configuration — an operator only needs to declare
|
|
9
|
+
* `spider.variables` for the role and build/test commands.
|
|
10
|
+
*
|
|
11
|
+
* Guilds may still override this template by declaring their own
|
|
12
|
+
* `spider.rigTemplates.default` in guild.json; config entries win over
|
|
13
|
+
* plugin-contributed defaults via the RigTemplateRegistry's precedence
|
|
14
|
+
* rules.
|
|
15
|
+
*
|
|
16
|
+
* Per D7 in the plan-and-ship commission, this template has no fallback
|
|
17
|
+
* defaults for `${vars.role}`, `${vars.buildCommand}`, or
|
|
18
|
+
* `${vars.testCommand}` — a missing variable raises at dispatch time so
|
|
19
|
+
* misconfiguration is surfaced loudly rather than masked.
|
|
20
|
+
*/
|
|
21
|
+
export const defaultRigTemplate = {
|
|
22
|
+
engines: [
|
|
23
|
+
{
|
|
24
|
+
id: 'draft',
|
|
25
|
+
designId: 'draft',
|
|
26
|
+
givens: { writ: '${writ}' },
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
id: 'implement',
|
|
30
|
+
designId: 'implement',
|
|
31
|
+
upstream: ['draft'],
|
|
32
|
+
givens: { writ: '${writ}', role: '${vars.role}' },
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
id: 'review',
|
|
36
|
+
designId: 'review',
|
|
37
|
+
upstream: ['implement'],
|
|
38
|
+
givens: {
|
|
39
|
+
writ: '${writ}',
|
|
40
|
+
role: 'reviewer',
|
|
41
|
+
buildCommand: '${vars.buildCommand}',
|
|
42
|
+
testCommand: '${vars.testCommand}',
|
|
43
|
+
},
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
id: 'revise',
|
|
47
|
+
designId: 'revise',
|
|
48
|
+
upstream: ['review'],
|
|
49
|
+
givens: { writ: '${writ}', role: '${vars.role}' },
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
id: 'seal',
|
|
53
|
+
designId: 'seal',
|
|
54
|
+
upstream: ['revise'],
|
|
55
|
+
givens: {},
|
|
56
|
+
},
|
|
57
|
+
],
|
|
58
|
+
resolutionEngine: 'seal',
|
|
59
|
+
};
|
|
60
|
+
//# sourceMappingURL=default-template.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"default-template.js","sourceRoot":"","sources":["../src/default-template.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAIH,MAAM,CAAC,MAAM,kBAAkB,GAAgB;IAC7C,OAAO,EAAE;QACP;YACE,EAAE,EAAE,OAAO;YACX,QAAQ,EAAE,OAAO;YACjB,MAAM,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE;SAC5B;QACD;YACE,EAAE,EAAE,WAAW;YACf,QAAQ,EAAE,WAAW;YACrB,QAAQ,EAAE,CAAC,OAAO,CAAC;YACnB,MAAM,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,cAAc,EAAE;SAClD;QACD;YACE,EAAE,EAAE,QAAQ;YACZ,QAAQ,EAAE,QAAQ;YAClB,QAAQ,EAAE,CAAC,WAAW,CAAC;YACvB,MAAM,EAAE;gBACN,IAAI,EAAE,SAAS;gBACf,IAAI,EAAE,UAAU;gBAChB,YAAY,EAAE,sBAAsB;gBACpC,WAAW,EAAE,qBAAqB;aACnC;SACF;QACD;YACE,EAAE,EAAE,QAAQ;YACZ,QAAQ,EAAE,QAAQ;YAClB,QAAQ,EAAE,CAAC,QAAQ,CAAC;YACpB,MAAM,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,cAAc,EAAE;SAClD;QACD;YACE,EAAE,EAAE,MAAM;YACV,QAAQ,EAAE,MAAM;YAChB,QAAQ,EAAE,CAAC,QAAQ,CAAC;YACpB,MAAM,EAAE,EAAE;SACX;KACF;IACD,gBAAgB,EAAE,MAAM;CACzB,CAAC"}
|
|
@@ -1,11 +1,21 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Implement engine — quick (Animator-backed).
|
|
3
3
|
*
|
|
4
|
-
* Summons an anima to do the commissioned work. Wraps the writ body
|
|
5
|
-
* task-manifest-aware execution
|
|
6
|
-
* with the draft worktree as
|
|
7
|
-
* `{ status: 'launched', sessionId }` so the
|
|
8
|
-
* for completion on subsequent walks.
|
|
4
|
+
* Summons an anima to do the commissioned work. Wraps the writ body (or
|
|
5
|
+
* the optional `prompt` override given) with task-manifest-aware execution
|
|
6
|
+
* instructions, then calls animator.summon() with the draft worktree as
|
|
7
|
+
* the working directory. Returns `{ status: 'launched', sessionId }` so the
|
|
8
|
+
* Spider's collect step can poll for completion on subsequent walks.
|
|
9
|
+
*
|
|
10
|
+
* Givens:
|
|
11
|
+
* - writ (required) — the WritDoc for this rig.
|
|
12
|
+
* - role (required) — the anima role to summon.
|
|
13
|
+
* - prompt (optional) — a prompt string that replaces `writ.body` as
|
|
14
|
+
* the body of the execution prompt. The
|
|
15
|
+
* EXECUTION_EPILOGUE is still appended. Used by
|
|
16
|
+
* the combined plan-and-ship rig to hand the
|
|
17
|
+
* planning spec to the implementing anima;
|
|
18
|
+
* absent on the vanilla mandate path.
|
|
9
19
|
*/
|
|
10
20
|
import type { EngineDesign } from '@shardworks/fabricator-apparatus';
|
|
11
21
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"implement.d.ts","sourceRoot":"","sources":["../../src/engines/implement.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"implement.d.ts","sourceRoot":"","sources":["../../src/engines/implement.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAGH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,kCAAkC,CAAC;AAKrE;;;;;GAKG;AACH,QAAA,MAAM,kBAAkB,usBASuB,CAAC;AAEhD,QAAA,MAAM,eAAe,EAAE,YA4BtB,CAAC;AAEF,OAAO,EAAE,kBAAkB,EAAE,CAAC;AAC9B,eAAe,eAAe,CAAC"}
|
|
@@ -1,11 +1,21 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Implement engine — quick (Animator-backed).
|
|
3
3
|
*
|
|
4
|
-
* Summons an anima to do the commissioned work. Wraps the writ body
|
|
5
|
-
* task-manifest-aware execution
|
|
6
|
-
* with the draft worktree as
|
|
7
|
-
* `{ status: 'launched', sessionId }` so the
|
|
8
|
-
* for completion on subsequent walks.
|
|
4
|
+
* Summons an anima to do the commissioned work. Wraps the writ body (or
|
|
5
|
+
* the optional `prompt` override given) with task-manifest-aware execution
|
|
6
|
+
* instructions, then calls animator.summon() with the draft worktree as
|
|
7
|
+
* the working directory. Returns `{ status: 'launched', sessionId }` so the
|
|
8
|
+
* Spider's collect step can poll for completion on subsequent walks.
|
|
9
|
+
*
|
|
10
|
+
* Givens:
|
|
11
|
+
* - writ (required) — the WritDoc for this rig.
|
|
12
|
+
* - role (required) — the anima role to summon.
|
|
13
|
+
* - prompt (optional) — a prompt string that replaces `writ.body` as
|
|
14
|
+
* the body of the execution prompt. The
|
|
15
|
+
* EXECUTION_EPILOGUE is still appended. Used by
|
|
16
|
+
* the combined plan-and-ship rig to hand the
|
|
17
|
+
* planning spec to the implementing anima;
|
|
18
|
+
* absent on the vanilla mandate path.
|
|
9
19
|
*/
|
|
10
20
|
import { guild } from '@shardworks/nexus-core';
|
|
11
21
|
/**
|
|
@@ -30,7 +40,15 @@ const implementEngine = {
|
|
|
30
40
|
const animator = guild().apparatus('animator');
|
|
31
41
|
const writ = givens.writ;
|
|
32
42
|
const draft = context.upstream['draft'];
|
|
33
|
-
|
|
43
|
+
// The `prompt` given, when supplied by the rig template, overrides
|
|
44
|
+
// `writ.body` as the execution body. The EXECUTION_EPILOGUE is appended
|
|
45
|
+
// either way so task-manifest-aware execution instructions travel with
|
|
46
|
+
// both paths. When `prompt` is omitted the engine's behaviour is
|
|
47
|
+
// byte-identical to the pre-refactor version.
|
|
48
|
+
const body = typeof givens.prompt === 'string' && givens.prompt.length > 0
|
|
49
|
+
? givens.prompt
|
|
50
|
+
: writ.body;
|
|
51
|
+
const prompt = `${body}\n${EXECUTION_EPILOGUE}`;
|
|
34
52
|
const handle = animator.summon({
|
|
35
53
|
role: givens.role,
|
|
36
54
|
prompt,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"implement.js","sourceRoot":"","sources":["../../src/engines/implement.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"implement.js","sourceRoot":"","sources":["../../src/engines/implement.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,EAAE,KAAK,EAAE,MAAM,wBAAwB,CAAC;AAM/C;;;;;GAKG;AACH,MAAM,kBAAkB,GAAG;;;;;;;;;+CASoB,CAAC;AAEhD,MAAM,eAAe,GAAiB;IACpC,EAAE,EAAE,WAAW;IAEf,KAAK,CAAC,GAAG,CAAC,MAAM,EAAE,OAAO;QACvB,MAAM,QAAQ,GAAG,KAAK,EAAE,CAAC,SAAS,CAAc,UAAU,CAAC,CAAC;QAC5D,MAAM,IAAI,GAAG,MAAM,CAAC,IAAe,CAAC;QACpC,MAAM,KAAK,GAAG,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAgB,CAAC;QAEvD,mEAAmE;QACnE,wEAAwE;QACxE,uEAAuE;QACvE,iEAAiE;QACjE,8CAA8C;QAC9C,MAAM,IAAI,GAAG,OAAO,MAAM,CAAC,MAAM,KAAK,QAAQ,IAAI,MAAM,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC;YACxE,CAAC,CAAC,MAAM,CAAC,MAAM;YACf,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC;QACd,MAAM,MAAM,GAAG,GAAG,IAAI,KAAK,kBAAkB,EAAE,CAAC;QAEhD,MAAM,MAAM,GAAG,QAAQ,CAAC,MAAM,CAAC;YAC7B,IAAI,EAAE,MAAM,CAAC,IAAc;YAC3B,MAAM;YACN,GAAG,EAAE,KAAK,CAAC,IAAI;YACf,WAAW,EAAE,EAAE,gBAAgB,EAAE,GAAG,IAAI,CAAC,EAAE,cAAc,EAAE;YAC3D,QAAQ,EAAE,EAAE,QAAQ,EAAE,OAAO,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,EAAE;SAC1D,CAAC,CAAC;QAEH,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,CAAC,SAAS,EAAE,CAAC;IAC7D,CAAC;CACF,CAAC;AAEF,OAAO,EAAE,kBAAkB,EAAE,CAAC;AAC9B,eAAe,eAAe,CAAC"}
|
package/dist/oculus-routes.d.ts
CHANGED
|
@@ -4,11 +4,17 @@
|
|
|
4
4
|
* Contributes:
|
|
5
5
|
* - GET /api/spider/config — aggregated snapshot of Spider config
|
|
6
6
|
* - GET /api/spider/session-transcript — session transcript and status
|
|
7
|
-
* - GET /api/spider/session-stream — SSE stream of real-time session chunks
|
|
8
7
|
*
|
|
9
8
|
* Does NOT import from @shardworks/oculus-apparatus to avoid a circular
|
|
10
9
|
* package dependency. The route shape is compatible with RouteContribution
|
|
11
10
|
* from the Oculus types.
|
|
11
|
+
*
|
|
12
|
+
* The former /api/spider/session-stream (SSE) route was removed when the
|
|
13
|
+
* Spider UI switched to uniform 2 s polling of /api/spider/session-transcript.
|
|
14
|
+
* The SSE path only worked for in-process (attached) sessions and silently
|
|
15
|
+
* dropped data for detached (cross-process) sessions because the Animator's
|
|
16
|
+
* subscribeToSession cannot bridge processes. Polling the Stacks-backed
|
|
17
|
+
* transcript works uniformly for both attached and detached sessions.
|
|
12
18
|
*/
|
|
13
19
|
import type { Context } from 'hono';
|
|
14
20
|
export declare const spiderRoutes: ({
|
|
@@ -48,6 +54,15 @@ export declare const spiderRoutes: ({
|
|
|
48
54
|
} | {
|
|
49
55
|
method: string;
|
|
50
56
|
path: string;
|
|
51
|
-
handler: (c: Context) => Promise<Response
|
|
57
|
+
handler: (c: Context) => Promise<(Response & import("hono").TypedResponse<{
|
|
58
|
+
error: string;
|
|
59
|
+
}, 400, "json">) | (Response & import("hono").TypedResponse<{
|
|
60
|
+
error: string;
|
|
61
|
+
}, 404, "json">) | (Response & import("hono").TypedResponse<{
|
|
62
|
+
messages: {
|
|
63
|
+
[x: string]: import("hono/utils/types").JSONValue;
|
|
64
|
+
}[];
|
|
65
|
+
sessionStatus: "pending" | "running" | "completed" | "failed" | "cancelled" | "timeout";
|
|
66
|
+
}, import("hono/utils/http-status").ContentfulStatusCode, "json">)>;
|
|
52
67
|
})[];
|
|
53
68
|
//# sourceMappingURL=oculus-routes.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"oculus-routes.d.ts","sourceRoot":"","sources":["../src/oculus-routes.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"oculus-routes.d.ts","sourceRoot":"","sources":["../src/oculus-routes.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AAcpC,eAAO,MAAM,YAAY;;;iBAIR,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAgBD,OAAO;;;;;;;;;;IA8B7B,CAAC"}
|
package/dist/oculus-routes.js
CHANGED
|
@@ -4,13 +4,18 @@
|
|
|
4
4
|
* Contributes:
|
|
5
5
|
* - GET /api/spider/config — aggregated snapshot of Spider config
|
|
6
6
|
* - GET /api/spider/session-transcript — session transcript and status
|
|
7
|
-
* - GET /api/spider/session-stream — SSE stream of real-time session chunks
|
|
8
7
|
*
|
|
9
8
|
* Does NOT import from @shardworks/oculus-apparatus to avoid a circular
|
|
10
9
|
* package dependency. The route shape is compatible with RouteContribution
|
|
11
10
|
* from the Oculus types.
|
|
11
|
+
*
|
|
12
|
+
* The former /api/spider/session-stream (SSE) route was removed when the
|
|
13
|
+
* Spider UI switched to uniform 2 s polling of /api/spider/session-transcript.
|
|
14
|
+
* The SSE path only worked for in-process (attached) sessions and silently
|
|
15
|
+
* dropped data for detached (cross-process) sessions because the Animator's
|
|
16
|
+
* subscribeToSession cannot bridge processes. Polling the Stacks-backed
|
|
17
|
+
* transcript works uniformly for both attached and detached sessions.
|
|
12
18
|
*/
|
|
13
|
-
import { streamSSE } from 'hono/streaming';
|
|
14
19
|
import { guild } from '@shardworks/nexus-core';
|
|
15
20
|
export const spiderRoutes = [
|
|
16
21
|
{
|
|
@@ -45,8 +50,8 @@ export const spiderRoutes = [
|
|
|
45
50
|
}
|
|
46
51
|
// Read transcript regardless of status. Detached sessions (babysitter)
|
|
47
52
|
// write transcript chunks to SQLite incrementally while the session is
|
|
48
|
-
// still 'running' or 'pending'; the client polls this endpoint
|
|
49
|
-
// refresh the engine view's session log in flight.
|
|
53
|
+
// still 'running' or 'pending'; the client polls this endpoint every
|
|
54
|
+
// 2 s to refresh the engine view's session log in flight.
|
|
50
55
|
const transcriptsBook = stacks.readBook('animator', 'transcripts');
|
|
51
56
|
const transcript = await transcriptsBook.get(sessionId);
|
|
52
57
|
return c.json({
|
|
@@ -55,80 +60,5 @@ export const spiderRoutes = [
|
|
|
55
60
|
});
|
|
56
61
|
},
|
|
57
62
|
},
|
|
58
|
-
{
|
|
59
|
-
method: 'GET',
|
|
60
|
-
path: '/api/spider/session-stream',
|
|
61
|
-
handler: async (c) => {
|
|
62
|
-
const sessionId = c.req.query('sessionId');
|
|
63
|
-
if (!sessionId) {
|
|
64
|
-
return c.json({ error: 'sessionId is required' }, 400);
|
|
65
|
-
}
|
|
66
|
-
const g = guild();
|
|
67
|
-
const stacks = g.apparatus('stacks');
|
|
68
|
-
const sessionsBook = stacks.readBook('animator', 'sessions');
|
|
69
|
-
const session = await sessionsBook.get(sessionId);
|
|
70
|
-
if (!session) {
|
|
71
|
-
return c.json({ error: 'Session not found' }, 404);
|
|
72
|
-
}
|
|
73
|
-
// For already-completed sessions, stream the full transcript and close.
|
|
74
|
-
if (session.status !== 'running') {
|
|
75
|
-
const transcriptsBook = stacks.readBook('animator', 'transcripts');
|
|
76
|
-
const transcript = await transcriptsBook.get(sessionId);
|
|
77
|
-
return streamSSE(c, async (stream) => {
|
|
78
|
-
await stream.writeSSE({
|
|
79
|
-
event: 'transcript',
|
|
80
|
-
data: JSON.stringify({ messages: transcript?.messages ?? [] }),
|
|
81
|
-
});
|
|
82
|
-
await stream.writeSSE({
|
|
83
|
-
event: 'done',
|
|
84
|
-
data: JSON.stringify({ status: session.status }),
|
|
85
|
-
});
|
|
86
|
-
});
|
|
87
|
-
}
|
|
88
|
-
// For running sessions, subscribe to the Animator's in-process broadcaster.
|
|
89
|
-
const animator = g.apparatus('animator');
|
|
90
|
-
const chunkStream = animator.subscribeToSession(sessionId);
|
|
91
|
-
if (!chunkStream) {
|
|
92
|
-
// The session is marked running in Stacks but has no in-memory broadcaster
|
|
93
|
-
// (e.g. a server restart happened). Return an empty stream so the UI can
|
|
94
|
-
// show a meaningful "no data" state and fall back gracefully.
|
|
95
|
-
return streamSSE(c, async (stream) => {
|
|
96
|
-
await stream.writeSSE({
|
|
97
|
-
event: 'done',
|
|
98
|
-
data: JSON.stringify({ status: 'running', noStream: true }),
|
|
99
|
-
});
|
|
100
|
-
});
|
|
101
|
-
}
|
|
102
|
-
return streamSSE(c, async (stream) => {
|
|
103
|
-
try {
|
|
104
|
-
for await (const chunk of chunkStream) {
|
|
105
|
-
await stream.writeSSE({
|
|
106
|
-
event: 'chunk',
|
|
107
|
-
data: JSON.stringify(chunk),
|
|
108
|
-
});
|
|
109
|
-
}
|
|
110
|
-
// All chunks consumed — session has ended. Fetch and emit final transcript.
|
|
111
|
-
const transcriptsBook = stacks.readBook('animator', 'transcripts');
|
|
112
|
-
const transcript = await transcriptsBook.get(sessionId);
|
|
113
|
-
await stream.writeSSE({
|
|
114
|
-
event: 'transcript',
|
|
115
|
-
data: JSON.stringify({ messages: transcript?.messages ?? [] }),
|
|
116
|
-
});
|
|
117
|
-
const finalSession = await sessionsBook.get(sessionId);
|
|
118
|
-
await stream.writeSSE({
|
|
119
|
-
event: 'done',
|
|
120
|
-
data: JSON.stringify({ status: finalSession?.status ?? 'completed' }),
|
|
121
|
-
});
|
|
122
|
-
}
|
|
123
|
-
catch (err) {
|
|
124
|
-
const message = err instanceof Error ? err.message : String(err);
|
|
125
|
-
await stream.writeSSE({
|
|
126
|
-
event: 'error',
|
|
127
|
-
data: JSON.stringify({ error: message }),
|
|
128
|
-
});
|
|
129
|
-
}
|
|
130
|
-
});
|
|
131
|
-
},
|
|
132
|
-
},
|
|
133
63
|
];
|
|
134
64
|
//# sourceMappingURL=oculus-routes.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"oculus-routes.js","sourceRoot":"","sources":["../src/oculus-routes.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"oculus-routes.js","sourceRoot":"","sources":["../src/oculus-routes.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAGH,OAAO,EAAE,KAAK,EAAE,MAAM,wBAAwB,CAAC;AAa/C,MAAM,CAAC,MAAM,YAAY,GAAG;IAC1B;QACE,MAAM,EAAE,KAAK;QACb,IAAI,EAAE,oBAAoB;QAC1B,OAAO,EAAE,CAAC,CAAU,EAAE,EAAE;YACtB,MAAM,CAAC,GAAG,KAAK,EAAE,CAAC;YAClB,MAAM,UAAU,GAAG,CAAC,CAAC,SAAS,CAAgB,YAAY,CAAC,CAAC;YAC5D,MAAM,MAAM,GAAG,CAAC,CAAC,SAAS,CAAY,QAAQ,CAAC,CAAC;YAEhD,OAAO,CAAC,CAAC,IAAI,CAAC;gBACZ,SAAS,EAAE,MAAM,CAAC,aAAa,EAAE;gBACjC,gBAAgB,EAAE,MAAM,CAAC,oBAAoB,EAAE;gBAC/C,aAAa,EAAE,UAAU,CAAC,iBAAiB,EAAE;gBAC7C,UAAU,EAAE,MAAM,CAAC,cAAc,EAAE;aACpC,CAAC,CAAC;QACL,CAAC;KACF;IACD;QACE,MAAM,EAAE,KAAK;QACb,IAAI,EAAE,gCAAgC;QACtC,OAAO,EAAE,KAAK,EAAE,CAAU,EAAE,EAAE;YAC5B,MAAM,SAAS,GAAG,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC;YAE3C,IAAI,CAAC,SAAS,EAAE,CAAC;gBACf,OAAO,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,uBAAuB,EAAE,EAAE,GAAG,CAAC,CAAC;YACzD,CAAC;YAED,MAAM,CAAC,GAAG,KAAK,EAAE,CAAC;YAClB,MAAM,MAAM,GAAG,CAAC,CAAC,SAAS,CAAY,QAAQ,CAAC,CAAC;YAEhD,MAAM,YAAY,GAAG,MAAM,CAAC,QAAQ,CAAa,UAAU,EAAE,UAAU,CAAC,CAAC;YACzE,MAAM,OAAO,GAAG,MAAM,YAAY,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;YAElD,IAAI,CAAC,OAAO,EAAE,CAAC;gBACb,OAAO,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,mBAAmB,EAAE,EAAE,GAAG,CAAC,CAAC;YACrD,CAAC;YAED,uEAAuE;YACvE,uEAAuE;YACvE,qEAAqE;YACrE,0DAA0D;YAC1D,MAAM,eAAe,GAAG,MAAM,CAAC,QAAQ,CAAkB,UAAU,EAAE,aAAa,CAAC,CAAC;YACpF,MAAM,UAAU,GAAG,MAAM,eAAe,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;YAExD,OAAO,CAAC,CAAC,IAAI,CAAC;gBACZ,QAAQ,EAAE,UAAU,EAAE,QAAQ,IAAI,EAAE;gBACpC,aAAa,EAAE,OAAO,CAAC,MAAM;aAC9B,CAAC,CAAC;QACL,CAAC;KACF;CACF,CAAC"}
|
package/dist/spider.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"spider.d.ts","sourceRoot":"","sources":["../src/spider.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAwD,MAAM,wBAAwB,CAAC;AAQ3G,OAAO,KAAK,EACV,MAAM,EAUN,WAAW,EAOZ,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"spider.d.ts","sourceRoot":"","sources":["../src/spider.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAwD,MAAM,wBAAwB,CAAC;AAQ3G,OAAO,KAAK,EACV,MAAM,EAUN,WAAW,EAOZ,MAAM,YAAY,CAAC;AAqDpB,uEAAuE;AACvE,MAAM,WAAW,SAAS;IACxB,6EAA6E;IAC7E,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;IAC3C,oFAAoF;IACpF,mBAAmB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC9C;AAyDD;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,MAAM,CAQ1D;AAED;;GAEG;AACH,wBAAgB,wBAAwB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAM5D;AA0hCD,wBAAgB,YAAY,IAAI,MAAM,CAm1CrC"}
|
package/dist/spider.js
CHANGED
|
@@ -30,6 +30,7 @@ import { animaSessionEngine, draftEngine, implementEngine, implementLoopEngine,
|
|
|
30
30
|
import { writPhaseBlockType, scheduledTimeBlockType, bookUpdatedBlockType, patronInputBlockType, } from "./block-types/index.js";
|
|
31
31
|
import { crawlOneTool, crawlContinualTool, rigShowTool, rigListTool, rigForWritTool, rigResumeTool, inputRequestListTool, inputRequestShowTool, inputRequestAnswerTool, inputRequestCompleteTool, inputRequestRejectTool, inputRequestExportTool, inputRequestImportTool, engineDesignsTool, blockTypesTool, rigCancelTool, } from "./tools/index.js";
|
|
32
32
|
import { spiderRoutes } from "./oculus-routes.js";
|
|
33
|
+
import { defaultRigTemplate } from "./default-template.js";
|
|
33
34
|
import { interpolateTemplate, extractExpressions, resolveDotPath, SKIP, } from "./template.js";
|
|
34
35
|
// ── Helpers ────────────────────────────────────────────────────────────
|
|
35
36
|
/**
|
|
@@ -633,12 +634,33 @@ class RigTemplateRegistry {
|
|
|
633
634
|
templates = new Map();
|
|
634
635
|
/** Config writ-type-to-template-name mappings */
|
|
635
636
|
configMappings = new Map();
|
|
636
|
-
/**
|
|
637
|
+
/**
|
|
638
|
+
* Kit-contributed mappings (first-registered wins). Each entry records
|
|
639
|
+
* the contributing pluginId so the registry can fall back from an
|
|
640
|
+
* unqualified templateName to the kit's own qualified `${pluginId}.${name}`
|
|
641
|
+
* when no config-level template has claimed the unqualified slot.
|
|
642
|
+
*/
|
|
637
643
|
kitMappings = new Map();
|
|
638
644
|
/** Config-declared template names (for override checking) */
|
|
639
645
|
configTemplateNames = new Set();
|
|
640
646
|
/** designId → pluginId that contributed it */
|
|
641
647
|
designSourceMap = new Map();
|
|
648
|
+
/**
|
|
649
|
+
* Resolve the actual template name stored in `templates` for a kit
|
|
650
|
+
* mapping entry. Prefer the literal value (so config-level overrides
|
|
651
|
+
* with the same name win); otherwise fall back to the kit's own
|
|
652
|
+
* qualified name. Returns undefined when neither form resolves.
|
|
653
|
+
*/
|
|
654
|
+
resolveKitMappedName(entry) {
|
|
655
|
+
if (this.templates.has(entry.templateName))
|
|
656
|
+
return entry.templateName;
|
|
657
|
+
if (!entry.templateName.includes('.')) {
|
|
658
|
+
const qualified = `${entry.pluginId}.${entry.templateName}`;
|
|
659
|
+
if (this.templates.has(qualified))
|
|
660
|
+
return qualified;
|
|
661
|
+
}
|
|
662
|
+
return undefined;
|
|
663
|
+
}
|
|
642
664
|
/**
|
|
643
665
|
* Build the designId → pluginId map from all engine KitEntries.
|
|
644
666
|
* Called once at startup before any kit registration.
|
|
@@ -895,7 +917,7 @@ class RigTemplateRegistry {
|
|
|
895
917
|
console.warn(`[spider] Kit "${pluginId}" rigTemplateMappings.${writType}: mapping for "${writType}" already registered by another kit — skipped`);
|
|
896
918
|
continue;
|
|
897
919
|
}
|
|
898
|
-
this.kitMappings.set(writType, templateName);
|
|
920
|
+
this.kitMappings.set(writType, { templateName, pluginId });
|
|
899
921
|
}
|
|
900
922
|
}
|
|
901
923
|
/**
|
|
@@ -909,10 +931,12 @@ class RigTemplateRegistry {
|
|
|
909
931
|
throw new Error(`[spider] rigTemplateMappings.${writType}: references unknown template "${templateName}"`);
|
|
910
932
|
}
|
|
911
933
|
}
|
|
912
|
-
// Kit mappings — warn and remove on dangling
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
934
|
+
// Kit mappings — warn and remove on dangling. An unqualified templateName
|
|
935
|
+
// is considered resolved if either the bare name or the kit's own
|
|
936
|
+
// `${pluginId}.${templateName}` exists in the template registry.
|
|
937
|
+
for (const [writType, entry] of [...this.kitMappings]) {
|
|
938
|
+
if (this.resolveKitMappedName(entry) === undefined) {
|
|
939
|
+
console.warn(`[spider] Kit mapping "${writType}" → "${entry.templateName}": template not found — removed`);
|
|
916
940
|
this.kitMappings.delete(writType);
|
|
917
941
|
}
|
|
918
942
|
}
|
|
@@ -922,9 +946,9 @@ class RigTemplateRegistry {
|
|
|
922
946
|
* Since deferred validation already ran, validate immediately.
|
|
923
947
|
*/
|
|
924
948
|
validateIncrementalMappings() {
|
|
925
|
-
for (const [writType,
|
|
926
|
-
if (
|
|
927
|
-
console.warn(`[spider] Kit mapping "${writType}" → "${templateName}": template not found — removed`);
|
|
949
|
+
for (const [writType, entry] of [...this.kitMappings]) {
|
|
950
|
+
if (this.resolveKitMappedName(entry) === undefined) {
|
|
951
|
+
console.warn(`[spider] Kit mapping "${writType}" → "${entry.templateName}": template not found — removed`);
|
|
928
952
|
this.kitMappings.delete(writType);
|
|
929
953
|
}
|
|
930
954
|
}
|
|
@@ -949,12 +973,18 @@ class RigTemplateRegistry {
|
|
|
949
973
|
return t;
|
|
950
974
|
// Config points to nonexistent template — validated at startup, should not happen at runtime
|
|
951
975
|
}
|
|
952
|
-
// Step 2: Kit mapping for this specific writ type
|
|
976
|
+
// Step 2: Kit mapping for this specific writ type. Unqualified
|
|
977
|
+
// templateName values resolve against the bare name first (so a
|
|
978
|
+
// config-level template of the same name wins), then fall back to the
|
|
979
|
+
// kit's own `${pluginId}.${templateName}` qualified form.
|
|
953
980
|
const kitMapped = this.kitMappings.get(writType);
|
|
954
981
|
if (kitMapped !== undefined) {
|
|
955
|
-
const
|
|
956
|
-
if (
|
|
957
|
-
|
|
982
|
+
const resolved = this.resolveKitMappedName(kitMapped);
|
|
983
|
+
if (resolved !== undefined) {
|
|
984
|
+
const t = this.templates.get(resolved);
|
|
985
|
+
if (t)
|
|
986
|
+
return t;
|
|
987
|
+
}
|
|
958
988
|
}
|
|
959
989
|
// No explicit mapping — writ type is inert by configuration, skip dispatch.
|
|
960
990
|
return undefined;
|
|
@@ -984,8 +1014,11 @@ class RigTemplateRegistry {
|
|
|
984
1014
|
*/
|
|
985
1015
|
listTemplateMappings() {
|
|
986
1016
|
const result = {};
|
|
987
|
-
for (const [writType,
|
|
988
|
-
|
|
1017
|
+
for (const [writType, entry] of this.kitMappings) {
|
|
1018
|
+
// Report the resolved template name so callers can look it up
|
|
1019
|
+
// directly in listTemplates() without re-implementing the
|
|
1020
|
+
// bare-name-to-qualified-name fallback.
|
|
1021
|
+
result[writType] = this.resolveKitMappedName(entry) ?? entry.templateName;
|
|
989
1022
|
}
|
|
990
1023
|
for (const [writType, templateName] of this.configMappings) {
|
|
991
1024
|
result[writType] = templateName;
|
|
@@ -1981,6 +2014,16 @@ export function createSpider() {
|
|
|
1981
2014
|
'book-updated': bookUpdatedBlockType,
|
|
1982
2015
|
'patron-input': patronInputBlockType,
|
|
1983
2016
|
},
|
|
2017
|
+
rigTemplates: {
|
|
2018
|
+
default: defaultRigTemplate,
|
|
2019
|
+
},
|
|
2020
|
+
rigTemplateMappings: {
|
|
2021
|
+
// Unqualified reference — resolved via the registry's
|
|
2022
|
+
// config-overrides-kit fallback. If the guild declares its own
|
|
2023
|
+
// config-level `default` template, that value wins; otherwise the
|
|
2024
|
+
// registry falls back to Spider's own kit-qualified `spider.default`.
|
|
2025
|
+
mandate: 'default',
|
|
2026
|
+
},
|
|
1984
2027
|
pages: [
|
|
1985
2028
|
{ id: 'spider', title: 'Spider', dir: 'src/static' },
|
|
1986
2029
|
{ id: 'feedback', title: 'Feedback', dir: 'src/static/feedback' },
|