@north-light/crouter 0.3.185 → 0.3.187
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/api/dto/broker.d.ts +0 -32
- package/dist/api/dto/messages.d.ts +0 -5
- package/dist/builtin-memory/internal/agent-shaping.md +1 -1
- package/dist/builtin-memory/internal/plugins.md +9 -0
- package/dist/clients/attach/input/controller.js +3 -4
- package/dist/clients/attach/overlays/mcp.js +1 -3
- package/dist/clients/attach/slash/dispatch.js +0 -2
- package/dist/clients/attach/viewer.js +331 -331
- package/dist/commands/memory/list.js +7 -3
- package/dist/commands/pkg/plugin-manage.js +39 -5
- package/dist/core/__tests__/plugin-kinds.test.d.ts +1 -0
- package/dist/core/__tests__/plugin-kinds.test.js +167 -0
- package/dist/core/__tests__/session-model.test.js +2 -4
- package/dist/core/command-plugins/bundle.d.ts +6 -0
- package/dist/core/command-plugins/bundle.js +29 -7
- package/dist/core/config.d.ts +12 -1
- package/dist/core/config.js +84 -12
- package/dist/core/installed-plugins.d.ts +2 -0
- package/dist/core/installed-plugins.js +42 -0
- package/dist/core/resolver.d.ts +1 -1
- package/dist/core/resolver.js +7 -32
- package/dist/core/runtime/broker/event-projection.d.ts +1 -8
- package/dist/core/runtime/broker/event-projection.js +1 -25
- package/dist/core/runtime/broker/frame-dispatch.d.ts +0 -2
- package/dist/core/runtime/broker/frame-dispatch.js +8 -41
- package/dist/core/runtime/broker-protocol.d.ts +1 -46
- package/dist/core/runtime/broker.js +1 -8
- package/dist/core/runtime/interactive-deliver.d.ts +2 -5
- package/dist/core/runtime/interactive-deliver.js +3 -6
- package/dist/core/session-model/session-state.d.ts +3 -6
- package/dist/core/session-model/session-state.js +1 -5
- package/dist/daemon/api/handlers/messages.js +1 -7
- package/dist/types.d.ts +12 -1
- package/package.json +1 -1
- package/runtime.lock.json +2 -2
- package/dist/core/runtime/broker/message-ledger.d.ts +0 -53
- package/dist/core/runtime/broker/message-ledger.js +0 -143
package/dist/api/dto/broker.d.ts
CHANGED
|
@@ -28,38 +28,6 @@ export interface BrokerWelcomeSnapshot<M = unknown> {
|
|
|
28
28
|
export interface BrokerWelcomeFrame<M = unknown> {
|
|
29
29
|
type: 'welcome';
|
|
30
30
|
snapshot?: BrokerWelcomeSnapshot<M>;
|
|
31
|
-
/** The last few id-bearing user-message dispatches from the broker's message
|
|
32
|
-
* ledger, oldest first — so a reattaching follower can key the snapshot's
|
|
33
|
-
* trailing user wakes by id (the id a sender minted via `message_id` on
|
|
34
|
-
* `POST .../messages`) instead of discarding them heuristically. Live-process
|
|
35
|
-
* memory only: a broker restart loses it. Absent on a broker pinned to an
|
|
36
|
-
* older runtime generation. */
|
|
37
|
-
recentUserMessages?: Array<{
|
|
38
|
-
id: string;
|
|
39
|
-
text: string;
|
|
40
|
-
}>;
|
|
41
|
-
}
|
|
42
|
-
/**
|
|
43
|
-
* The additive identity fields the broker sets on a relayed pi `queue_update`:
|
|
44
|
-
* id arrays PARALLEL to pi's text arrays (`steeringIds[i]` identifies
|
|
45
|
-
* `steering[i]`). Sender-minted when the send carried `message_id`,
|
|
46
|
-
* broker-minted otherwise. Absent on a broker pinned to an older runtime
|
|
47
|
-
* generation — consumers fall back to bare texts. Intersect with the pinned pi
|
|
48
|
-
* `queue_update` event shape to read them typed.
|
|
49
|
-
*/
|
|
50
|
-
export interface RelayedQueueUpdateIdentity {
|
|
51
|
-
steeringIds?: string[];
|
|
52
|
-
followUpIds?: string[];
|
|
53
|
-
}
|
|
54
|
-
/**
|
|
55
|
-
* The additive identity field the broker sets on a relayed USER-role
|
|
56
|
-
* `message_start`: the message's crouter id — the `message_id` its sender
|
|
57
|
-
* minted, or a broker-minted one. Absent when the message carries none (an
|
|
58
|
-
* engine-command expansion, a pre-ledger replay, an older broker). Intersect
|
|
59
|
-
* with the pinned pi `message_start` event shape to read it typed.
|
|
60
|
-
*/
|
|
61
|
-
export interface RelayedUserMessageStartIdentity {
|
|
62
|
-
crtrMessageId?: string;
|
|
63
31
|
}
|
|
64
32
|
/**
|
|
65
33
|
* The broker-control frames a relay consumer reads: `welcome` (catch-up snapshot)
|
|
@@ -26,11 +26,6 @@ export interface SendMessageRequest {
|
|
|
26
26
|
* body only — rejected with fresh/reopen/situational_context/
|
|
27
27
|
* output_schema or tier 'deferred'. Absent → durable inbox (unchanged). */
|
|
28
28
|
delivery?: 'interactive';
|
|
29
|
-
/** Sender-minted message identity for a `delivery:'interactive'` send. The
|
|
30
|
-
* broker mirrors it through pi's queues and echoes it on the relayed user
|
|
31
|
-
* `message_start` (`crtrMessageId`), so an optimistic sender (the gateway)
|
|
32
|
-
* retires its pending entry by exact id. Ignored on the durable-inbox path. */
|
|
33
|
-
message_id?: string;
|
|
34
29
|
}
|
|
35
30
|
/** Result of an immediate message send. */
|
|
36
31
|
export interface MessageResultDTO {
|
|
@@ -47,7 +47,7 @@ Specialist sub-personas hang off a parent kind — `plan/reviewers/*` (architect
|
|
|
47
47
|
|
|
48
48
|
### Custom personas
|
|
49
49
|
|
|
50
|
-
The roster is extensible. Add a `kinds.<name>` entry to a `config.json` at user or project scope (fields: `whenToUse` required, plus optional `model`, `orchestratorModel`, `tools`, `extensions`, `availableTo`) and author the persona prose at `kinds/<name>/00-base.md` (and `01-orchestrator.md`) gated `{kind: <name>, mode: ...}`. A standing personal assistant, for example, is a scope-configured custom `personal-assistant` kind rather than a builtin kind. The registry merges **project > user > builtin**, so a custom kind can add a new role or shadow a builtin one without restating the rest. Reach for a custom kind when a **recurring role** wants its own standing discipline and model/tool defaults that outlast any single task — not for a one-off instruction, which belongs in the spawn prompt.
|
|
50
|
+
The roster is extensible. Add a `kinds.<name>` entry to a `config.json` at user or project scope (fields: `whenToUse` required, plus optional `model`, `orchestratorModel`, `tools`, `extensions`, `availableTo`) and author the persona prose at `kinds/<name>/00-base.md` (and `01-orchestrator.md`) gated `{kind: <name>, mode: ...}`. A standing personal assistant, for example, is a scope-configured custom `personal-assistant` kind rather than a builtin kind. The registry merges **project > user > builtin**, so a custom kind can add a new role or shadow a builtin one without restating the rest. A plugin can ship a kind the same way — a `kinds` block in its manifest plus gated persona docs in its memory tree; an enabled plugin's entries layer directly below its host scope's own `config.json` (see `internal/plugins`). Reach for a custom kind when a **recurring role** wants its own standing discipline and model/tool defaults that outlast any single task — not for a one-off instruction, which belongs in the spawn prompt.
|
|
51
51
|
|
|
52
52
|
## Modes — base vs orchestrator
|
|
53
53
|
|
|
@@ -64,6 +64,15 @@ The `<plugin-name>` directory IS the plugin. The manifest's `name` field must ma
|
|
|
64
64
|
| `owner` | optional | Author info. |
|
|
65
65
|
| `commands` | optional | Plugin-root-relative path to a `commands.json` command manifest. It must appear with `transport`; together they make the plugin contribute `crtr` commands — see [Plugin commands](#plugin-commands). |
|
|
66
66
|
| `transport` | optional | Required exactly when `commands` is present. `{ "kind": "exec", "executable": "bin/cmd.js" }` runs executable leaves; a passthrough-only exec manifest may omit `executable`. `{ "kind": "http", "endpoint": "https://…", "authEnv": "TOKEN_NAME" }` calls a remote HTTP command surface. Archive-installed plugins also carry crouter-synthesized `bundle` provenance; authors do not add it. |
|
|
67
|
+
| `kinds` | optional | Kind-registry contributions, keyed by full kind string — the same two entry shapes a scope `config.json` `kinds` block accepts: a FULL entry (`whenToUse` required, plus optional `model`, `orchestratorModel`, `tools`, `extensions`, `availableTo`) defines or shadows a kind; a sparse PATCH overrides launch knobs of a kind a lower layer defines. See [Plugin kinds](#plugin-kinds). |
|
|
68
|
+
|
|
69
|
+
## Plugin kinds
|
|
70
|
+
|
|
71
|
+
A plugin can ship a complete persona kind: declare the registry entry in the manifest's `kinds` block, and author the persona prose as ordinary plugin memory docs gated `{kind: <name>, mode: base}` (and `{kind: <name>, mode: orchestrator}`) with `system-prompt-visibility: content` — the same shape a builtin kind uses at `kinds/<kind>/00-base.md`. Nothing else is needed: gates evaluate uniformly over plugin docs, so the persona splices into any node launched with that kind.
|
|
72
|
+
|
|
73
|
+
`readMergedLaunchConfig` layers an enabled plugin's `kinds` entries directly above the builtin registry and below its host scope's own `config.json` — full precedence: builtin → user-scope plugins → user config → profile → per project root (that root's plugins → that root's config). So a plugin kind appears in `crtr node new -h` and is launchable like any other, and a user or project `config.json` can still patch or shadow it. Plugins within one scope layer name-sorted; the scope's own config always wins.
|
|
74
|
+
|
|
75
|
+
For archive plugins the declaration lives in the archive's `bundle.json` — `{"bundleVersion": 1, "kinds": {…}}` — and the installer copies the block into the synthesized manifest. Install validates the block strictly (an invalid entry fails the install with per-entry reasons); the read side drops invalid entries silently, so the loud gate is install time.
|
|
67
76
|
|
|
68
77
|
## Scopes
|
|
69
78
|
|
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
// lifetime belongs to InputOverlayOwner; viewer permission belongs to the single
|
|
3
3
|
// ViewerCapabilities value supplied by session/input-wiring.
|
|
4
4
|
import { spawn } from 'node:child_process';
|
|
5
|
-
import { randomUUID } from 'node:crypto';
|
|
6
5
|
import { readFileSync, unlinkSync, writeFileSync } from 'node:fs';
|
|
7
6
|
import { tmpdir } from 'node:os';
|
|
8
7
|
import { join } from 'node:path';
|
|
@@ -46,7 +45,7 @@ export class InputController {
|
|
|
46
45
|
this.emitCommand({ type: 'cycle_ladder', direction });
|
|
47
46
|
}
|
|
48
47
|
sendInterrupting(text) {
|
|
49
|
-
return this.emitDrive({ type: 'prompt', text, interrupt: true
|
|
48
|
+
return this.emitDrive({ type: 'prompt', text, interrupt: true });
|
|
50
49
|
}
|
|
51
50
|
attachDialog(request) {
|
|
52
51
|
this.overlays.attachDialog(request);
|
|
@@ -182,7 +181,7 @@ export class InputController {
|
|
|
182
181
|
if (delivery !== 'steer' && delivery !== 'prompt')
|
|
183
182
|
return;
|
|
184
183
|
const expanded = this.expandImagePlaceholders(classification.kind === 'slash' ? text : classification.text);
|
|
185
|
-
if (!this.emitDrive(delivery === 'steer' ? { type: 'steer', text: expanded
|
|
184
|
+
if (!this.emitDrive(delivery === 'steer' ? { type: 'steer', text: expanded } : { type: 'prompt', text: expanded }))
|
|
186
185
|
return;
|
|
187
186
|
this.editor.addToHistory(classification.trimmed);
|
|
188
187
|
this.editor.setText('');
|
|
@@ -194,7 +193,7 @@ export class InputController {
|
|
|
194
193
|
const trimmed = text.trim();
|
|
195
194
|
if (!trimmed)
|
|
196
195
|
return;
|
|
197
|
-
if (!this.emitDrive({ type: 'follow_up', text: this.expandImagePlaceholders(text)
|
|
196
|
+
if (!this.emitDrive({ type: 'follow_up', text: this.expandImagePlaceholders(text) }))
|
|
198
197
|
return;
|
|
199
198
|
this.editor.addToHistory(trimmed);
|
|
200
199
|
this.editor.setText('');
|
|
@@ -39,7 +39,7 @@
|
|
|
39
39
|
// as cached but fails to reconnect). Action names verified against the
|
|
40
40
|
// installed adapter (pi-mcp-adapter index.ts: "auth-start" / "auth-complete" /
|
|
41
41
|
// "ui-messages"; `connect: <name>`).
|
|
42
|
-
import { createHash
|
|
42
|
+
import { createHash } from 'node:crypto';
|
|
43
43
|
import { existsSync } from 'node:fs';
|
|
44
44
|
import { homedir } from 'node:os';
|
|
45
45
|
import { join, resolve } from 'node:path';
|
|
@@ -257,7 +257,6 @@ export function startMcpServerAction(row, send, notify) {
|
|
|
257
257
|
send({
|
|
258
258
|
type: 'prompt',
|
|
259
259
|
text: `Run mcp({ action: "auth-start", server: ${nameJson} }) and show me the returned OAuth URL verbatim (with any instructions). If the server does not need OAuth, run mcp({ connect: ${nameJson} }) instead and report the result.`,
|
|
260
|
-
message_id: randomUUID(),
|
|
261
260
|
});
|
|
262
261
|
notify(`Asking the engine to start OAuth for ${row.name}…`);
|
|
263
262
|
}
|
|
@@ -265,7 +264,6 @@ export function startMcpServerAction(row, send, notify) {
|
|
|
265
264
|
send({
|
|
266
265
|
type: 'prompt',
|
|
267
266
|
text: `Run mcp({ connect: ${nameJson} }) to reconnect that MCP server and report the result. If it fails with an authentication or authorization error, run mcp({ action: "auth-start", server: ${nameJson} }) and show me the returned OAuth URL verbatim (with any instructions).`,
|
|
268
|
-
message_id: randomUUID(),
|
|
269
267
|
});
|
|
270
268
|
notify(`Asking the engine to reconnect ${row.name}…`);
|
|
271
269
|
}
|
|
@@ -22,7 +22,6 @@
|
|
|
22
22
|
// SCOPED OUT (no engine method): `/login`, `/logout`, `/share`,
|
|
23
23
|
// `/trust` — a brief "not supported in attach" notice, never a frame.
|
|
24
24
|
import { execFile } from 'node:child_process';
|
|
25
|
-
import { randomUUID } from 'node:crypto';
|
|
26
25
|
import { BUILTIN_SLASH_COMMANDS } from '../../../core/runtime/pi-vendored.js';
|
|
27
26
|
import { surfaceTmuxStyleArgs } from '../../../core/runtime/surface-bg.js';
|
|
28
27
|
import { viewerOperationForSlash } from '../input/capabilities.js';
|
|
@@ -452,7 +451,6 @@ function promoteNode(arg, ctx) {
|
|
|
452
451
|
ctx.send({
|
|
453
452
|
type: 'prompt',
|
|
454
453
|
text: 'You have just been promoted to an orchestrator. Your new-role guidance is arriving — read it, author your roadmap, and start delegating.',
|
|
455
|
-
message_id: randomUUID(),
|
|
456
454
|
});
|
|
457
455
|
});
|
|
458
456
|
child.stdin?.end();
|