@plurnk/plurnk-service 0.2.0 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/SPEC.md +98 -112
- package/dist/core/ChannelWrite.d.ts +10 -0
- package/dist/core/ChannelWrite.d.ts.map +1 -1
- package/dist/core/ChannelWrite.js.map +1 -1
- package/dist/core/Engine.d.ts +10 -2
- package/dist/core/Engine.d.ts.map +1 -1
- package/dist/core/Engine.js +410 -113
- package/dist/core/Engine.js.map +1 -1
- package/dist/core/ProviderRegistry.d.ts +1 -1
- package/dist/core/ProviderRegistry.d.ts.map +1 -1
- package/dist/core/ProviderRegistry.js.map +1 -1
- package/dist/core/line-marker.d.ts +23 -0
- package/dist/core/line-marker.d.ts.map +1 -0
- package/dist/core/line-marker.js +321 -0
- package/dist/core/line-marker.js.map +1 -0
- package/dist/core/matcher.d.ts +14 -0
- package/dist/core/matcher.d.ts.map +1 -0
- package/dist/core/matcher.js +195 -0
- package/dist/core/matcher.js.map +1 -0
- package/dist/core/mimetype-binary.d.ts +6 -0
- package/dist/core/mimetype-binary.d.ts.map +1 -0
- package/dist/core/mimetype-binary.js +82 -0
- package/dist/core/mimetype-binary.js.map +1 -0
- package/dist/core/packet-wire.d.ts.map +1 -1
- package/dist/core/packet-wire.js +174 -33
- package/dist/core/packet-wire.js.map +1 -1
- package/dist/core/path-mimetype.d.ts +3 -0
- package/dist/core/path-mimetype.d.ts.map +1 -0
- package/dist/core/path-mimetype.js +47 -0
- package/dist/core/path-mimetype.js.map +1 -0
- package/dist/core/scheme-types.d.ts +5 -0
- package/dist/core/scheme-types.d.ts.map +1 -1
- package/dist/core/scheme-types.js.map +1 -1
- package/dist/providers/Mock.d.ts +2 -2
- package/dist/providers/Mock.d.ts.map +1 -1
- package/dist/providers/Mock.js.map +1 -1
- package/dist/schemes/Exec.d.ts +30 -1
- package/dist/schemes/Exec.d.ts.map +1 -1
- package/dist/schemes/Exec.js +229 -6
- package/dist/schemes/Exec.js.map +1 -1
- package/dist/schemes/File.d.ts +8 -4
- package/dist/schemes/File.d.ts.map +1 -1
- package/dist/schemes/File.js +184 -68
- package/dist/schemes/File.js.map +1 -1
- package/dist/schemes/Known.js +1 -1
- package/dist/schemes/Known.js.map +1 -1
- package/dist/schemes/Log.d.ts +9 -1
- package/dist/schemes/Log.d.ts.map +1 -1
- package/dist/schemes/Log.js +120 -19
- package/dist/schemes/Log.js.map +1 -1
- package/dist/schemes/Plurnk.d.ts +15 -1
- package/dist/schemes/Plurnk.d.ts.map +1 -1
- package/dist/schemes/Plurnk.js +50 -8
- package/dist/schemes/Plurnk.js.map +1 -1
- package/dist/schemes/Skill.js +1 -1
- package/dist/schemes/Skill.js.map +1 -1
- package/dist/schemes/Unknown.js +1 -1
- package/dist/schemes/Unknown.js.map +1 -1
- package/dist/schemes/_entry-crud.d.ts +5 -3
- package/dist/schemes/_entry-crud.d.ts.map +1 -1
- package/dist/schemes/_entry-crud.js +1 -0
- package/dist/schemes/_entry-crud.js.map +1 -1
- package/dist/schemes/_entry-find.d.ts.map +1 -1
- package/dist/schemes/_entry-find.js +64 -15
- package/dist/schemes/_entry-find.js.map +1 -1
- package/dist/schemes/_entry-ops.d.ts +3 -0
- package/dist/schemes/_entry-ops.d.ts.map +1 -1
- package/dist/schemes/_entry-ops.js +269 -72
- package/dist/schemes/_entry-ops.js.map +1 -1
- package/dist/schemes/_entry-send.d.ts.map +1 -1
- package/dist/schemes/_entry-send.js +14 -7
- package/dist/schemes/_entry-send.js.map +1 -1
- package/dist/server/ClientConnection.d.ts +3 -2
- package/dist/server/ClientConnection.d.ts.map +1 -1
- package/dist/server/ClientConnection.js +10 -2
- package/dist/server/ClientConnection.js.map +1 -1
- package/dist/server/Daemon.d.ts +40 -1
- package/dist/server/Daemon.d.ts.map +1 -1
- package/dist/server/Daemon.js +319 -1
- package/dist/server/Daemon.js.map +1 -1
- package/dist/server/MethodRegistry.d.ts +29 -0
- package/dist/server/MethodRegistry.d.ts.map +1 -1
- package/dist/server/MethodRegistry.js.map +1 -1
- package/dist/server/dsl.d.ts +2 -2
- package/dist/server/dsl.d.ts.map +1 -1
- package/dist/server/dsl.js +10 -10
- package/dist/server/dsl.js.map +1 -1
- package/dist/server/envelope.d.ts +2 -1
- package/dist/server/envelope.d.ts.map +1 -1
- package/dist/server/envelope.js +11 -8
- package/dist/server/envelope.js.map +1 -1
- package/dist/server/logEntry.d.ts +9 -9
- package/dist/server/logEntry.d.ts.map +1 -1
- package/dist/server/logEntry.js +10 -10
- package/dist/server/logEntry.js.map +1 -1
- package/dist/server/methods/_dispatchAsClient.d.ts.map +1 -1
- package/dist/server/methods/_dispatchAsClient.js +7 -2
- package/dist/server/methods/_dispatchAsClient.js.map +1 -1
- package/dist/server/methods/entry_read.js +5 -5
- package/dist/server/methods/entry_read.js.map +1 -1
- package/dist/server/methods/loop_cancel.d.ts +3 -0
- package/dist/server/methods/loop_cancel.d.ts.map +1 -0
- package/dist/server/methods/loop_cancel.js +27 -0
- package/dist/server/methods/loop_cancel.js.map +1 -0
- package/dist/server/methods/loop_run.d.ts.map +1 -1
- package/dist/server/methods/loop_run.js +53 -49
- package/dist/server/methods/loop_run.js.map +1 -1
- package/dist/server/methods/op_edit.js +3 -3
- package/dist/server/methods/op_edit.js.map +1 -1
- package/dist/server/methods/op_hide.js +3 -3
- package/dist/server/methods/op_hide.js.map +1 -1
- package/dist/server/methods/op_read.js +3 -3
- package/dist/server/methods/op_read.js.map +1 -1
- package/dist/server/methods/op_show.js +3 -3
- package/dist/server/methods/op_show.js.map +1 -1
- package/migrations/001_schema.sql +324 -0
- package/package.json +19 -12
- package/migrations/001_sessions.sql +0 -11
- package/migrations/002_runs.sql +0 -16
- package/migrations/003_loops.sql +0 -12
- package/migrations/004_turns.sql +0 -18
- package/migrations/005_entries.sql +0 -44
- package/migrations/006_log_entries.sql +0 -51
- package/migrations/007_visibility.sql +0 -10
- package/migrations/008_schemes_providers.sql +0 -25
- package/migrations/009_cost_rollups.sql +0 -44
- package/migrations/010_subscriptions.sql +0 -36
- package/migrations/011_turn_call_metadata.sql +0 -7
- package/migrations/012_proposal_lifecycle.sql +0 -22
- package/migrations/013_log_entries_lifecycle_columns.sql +0 -22
- package/migrations/014_loop_flags.sql +0 -9
- package/migrations/015_sessions_project_root.sql +0 -6
- package/migrations/016_persona_columns.sql +0 -11
package/SPEC.md
CHANGED
|
@@ -2,9 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
Single source of truth for what plurnk-service IS — the contracts it exposes, the architecture it implements, the promises it makes to the rest of the constellation (`plurnk-grammar`, `plurnk-providers-*`, `plurnk-schemes-*`, `plurnk-mimetypes-*`, the user-facing `plurnk` CLI). `AGENTS.md` covers how we work on it; this file covers what we're working on.
|
|
4
4
|
|
|
5
|
-
Section numbers are stable.
|
|
6
|
-
|
|
7
|
-
Floor scope is green (capstone intg test exercises every non-EXEC DSL op end-to-end). Post-floor work landed in #123: PlurnkSchemeContext (#33), the engine rails (#38–#41), packet shape (§15), single-cap constraint (§7.8), ProviderRegistry (#58), and first sibling-package extraction (#47). This document evolves with each phase; the next refinements will come from Phase C (mimetype integration story) and Phase F (exec + streams).
|
|
5
|
+
Section numbers are stable. Anchor-to-test wiring binds individual promises here to integration / live / demo tests, giving semi-deterministic specification-testing alignment.
|
|
8
6
|
|
|
9
7
|
**Promise anchors.** Individual contract assertions in this document carry a trailing `{§<id>}` marker. Tests reference these anchors in their names (`test("[§<id>] description", ...)`). An alignment test (`test/intg/spec-anchors.test.ts`) fails if a test cites a nonexistent anchor (orphan — typo or stale reference) and surfaces gaps (anchored promises with no test) informationally. The anchors are **grounding against drift**, not a forcing function on development — write the spec, write the test, jot the link, move on. Coverage grows organically.
|
|
10
8
|
|
|
@@ -86,7 +84,7 @@ Three independent axes on entries and channels. Confusion across them is a recur
|
|
|
86
84
|
| Tier | Location | LLM | Substrate |
|
|
87
85
|
|---|---|---|---|
|
|
88
86
|
| **unit** | `src/**/*.test.ts` | No | Isolated logic, mocked boundaries |
|
|
89
|
-
| **intg** | `test/intg/` | No (mock provider) | Real
|
|
87
|
+
| **intg** | `test/intg/` | No (mock provider) | Real file-backed SqlRite (per-test DB under `test/intg/.tmp/`), real engine |
|
|
90
88
|
| **live** | `test/live/` | Real | Wire-level assertions |
|
|
91
89
|
| **demo** | `test/demo/` | Real | Holistic outcome assertions |
|
|
92
90
|
|
|
@@ -342,20 +340,7 @@ Promises:
|
|
|
342
340
|
|
|
343
341
|
### §4.4 Bundled vs sibling handlers
|
|
344
342
|
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
The first such extraction is `@plurnk/plurnk-mimetypes-text-markdown`, separate repo since #47. Validates the "bundle minimally" pattern. `application/json` and the DSL mimetype (`text/vnd.plurnk` — grammar #6 closed in favor of this id) follow the same pattern when they have consumers.
|
|
348
|
-
|
|
349
|
-
Locked glyph assignments for the standard set:
|
|
350
|
-
|
|
351
|
-
| Mimetype | Glyph | Where |
|
|
352
|
-
|-----------------------------------|-------|------------------------------------|
|
|
353
|
-
| `text/plain` | 📄 | bundled (`src/mimetypes/`) |
|
|
354
|
-
| `text/markdown` | 📝 | sibling (`@plurnk/plurnk-mimetypes-text-markdown`) |
|
|
355
|
-
| `application/json` *(deferred)* | 🗂 | future sibling |
|
|
356
|
-
| `text/vnd.plurnk` *(deferred)* | 📜 | future sibling |
|
|
357
|
-
|
|
358
|
-
Deferred handlers reserve their glyphs now so external packages don't collide.
|
|
343
|
+
No mimetype handlers ship in-tree. Every handler is a sibling `@plurnk/plurnk-mimetypes-*` package; the framework (`@plurnk/plurnk-mimetypes`) is also a sibling and is the surface plurnk-service consumes via `Mimetypes.process()`. Handlers register at boot via plugin discovery (§9). The in-tree set is empty by design — the framework is responsible for the universal fallback, not us.
|
|
359
344
|
|
|
360
345
|
---
|
|
361
346
|
|
|
@@ -365,14 +350,11 @@ Every entry has named channels. **Channels are append-only content stores** keye
|
|
|
365
350
|
|
|
366
351
|
### §5.1 Per-entry channels
|
|
367
352
|
|
|
368
|
-
EDIT writes
|
|
369
|
-
|
|
370
|
-
- **`body`** — the raw content.
|
|
371
|
-
- **`preview`** — the render-time structural summary. The stored content here is the result of `mimetype.preview(body, budget)` for the body's mimetype. When the mimetype handler is unsophisticated (text/plain head-truncation), the preview is short. As handlers mature (markdown heading outline, JSON key tree, DSL op summary), the preview becomes structural. {§5.1-preview-is-handler-output}
|
|
353
|
+
EDIT writes one channel per call — the channel resolved from the path's fragment (or the scheme's `defaultChannel` when no fragment). {§5.1-edit-writes-only-body}
|
|
372
354
|
|
|
373
|
-
|
|
355
|
+
There is no stored `preview` channel. Preview is a **render-time output**, computed by passing the channel's content through `Mimetypes.process()` at packet-build time. The result lands in `packet.system.index[].channels[name].content`. {§5.1-preview-is-handler-output} The mimetype framework owns the preview pipeline; plurnk-service consumes the returned preview and never inspects the framework's internals.
|
|
374
356
|
|
|
375
|
-
Schemes MAY declare
|
|
357
|
+
Schemes MAY declare multiple channels (exec will declare `stdout`/`stderr`/`stdin`; http will declare `body`/`header`; SSE may declare per-event-type channels). Each channel goes in the scheme's `channels` manifest (§3.1) and has its mimetype pinned there. Each channel is rendered independently at packet-build time.
|
|
376
358
|
|
|
377
359
|
### §5.2 Visibility lattice
|
|
378
360
|
|
|
@@ -387,10 +369,6 @@ The mimetype of a channel is declared by the scheme's manifest (§3.1) or — fo
|
|
|
387
369
|
Implications:
|
|
388
370
|
- Cross-mimetype COPY/MOVE crashes (`415 Unsupported Media Type`) — never coerces. See §6.4.
|
|
389
371
|
|
|
390
|
-
### §5.4 Orientation hint
|
|
391
|
-
|
|
392
|
-
The grammar's `SchemeRegistration.channel_orientations` declares each scheme's channels as `head` or `tail` — "which end of the content matters for preview." Mimetype handlers consult this hint when truncating. Channels not listed default to `head`.
|
|
393
|
-
|
|
394
372
|
### §5.5 Channel selection in the DSL
|
|
395
373
|
|
|
396
374
|
The DSL targets a specific channel of an entry via the URL **fragment** — the `#name` segment of the path. Per the grammar's `UrlPath` shape (0.3.0+), every parsed path has a nullable `fragment` field; this section defines its semantic for the engine.
|
|
@@ -422,7 +400,16 @@ Implications for operations:
|
|
|
422
400
|
- **SHOW / HIDE** flip visibility for the resolved channel only — channel-specific visibility is achievable via fragments. Fragment-less SHOW/HIDE flips ALL channels of the entry per §5.2 (existing behavior).
|
|
423
401
|
- **COPY / MOVE** with a fragment is a per-channel operation; deferred design pass needed before specifying (out of scope for v0).
|
|
424
402
|
|
|
425
|
-
The clean-shape RPC params (§13.5) carry the fragment naturally inside the `
|
|
403
|
+
The clean-shape RPC params (§13.5) carry the fragment naturally inside the `target` string: `{ target: "known://x#stderr" }` works as expected. No new RPC parameter needed; the URL surface handles it.
|
|
404
|
+
|
|
405
|
+
**Wire-rendering inverse: default channel is path-only.** When the engine projects entries to the model's view, the heredoc fence omits `#channel` whenever the channel name matches the scheme's `defaultChannel`. Single-channel entries (the channel IS the default) render path-only; multi-channel entries render the default channel path-only and only non-default channels carry `#name` in the fence. {§5.5-wire-omits-suffix-on-default-channel} Examples:
|
|
406
|
+
|
|
407
|
+
- `<<notes.md:...:notes.md` — file scheme renders bare (see §10 file note)
|
|
408
|
+
- `<<exec://run:...:exec://run` — exec's default (`stdout`)
|
|
409
|
+
- `<<exec://run#stderr:...:exec://run#stderr` — explicit non-default
|
|
410
|
+
- `<<log://1/1/0:...:log://1/1/0` — log responses (single-payload; no channel concept)
|
|
411
|
+
|
|
412
|
+
The absence of `#channel` IS the addressing of the default. This matches what models naturally emit and removes `#body` / `#rx` clutter from every packet.
|
|
426
413
|
|
|
427
414
|
### §5.6 Channel state — metadata, not gating
|
|
428
415
|
|
|
@@ -445,20 +432,19 @@ Per-op semantics for `FIND | READ | EDIT | COPY | MOVE | SHOW | HIDE | SEND | EX
|
|
|
445
432
|
|
|
446
433
|
### §6.1 EDIT
|
|
447
434
|
|
|
448
|
-
AST: `{ op: "EDIT",
|
|
435
|
+
AST: `{ op: "EDIT", target: ParsedPath, body: string | null, signal: tags | null, lineMarker?: LineMarker }`.
|
|
449
436
|
|
|
450
437
|
Engine dispatches to `scheme.edit(statement, ctx)`. Scheme:
|
|
451
438
|
- Resolves the target channel from the path's fragment (§5.5). Fragment absent → scheme's `manifest.defaultChannel`. Unknown channel → 400. Channel manifest-undeclared → engine crashes per §5.3.
|
|
452
439
|
- Writes the body to the resolved channel.
|
|
453
|
-
-
|
|
454
|
-
- Indexes the written channels in the current run (visibility = 1).
|
|
440
|
+
- Indexes the written channel in the current run (visibility = 1).
|
|
455
441
|
- Returns `{ status: 201, entryId }` for new entries; `{ status: 200, entryId }` for updates.
|
|
456
442
|
- `body: null` clears the content (writes empty string).
|
|
457
443
|
- Tags from `signal[]` are applied via `entry_tags` (additive on update for the v0 entry schemes; final policy may vary by scheme).
|
|
458
444
|
|
|
459
445
|
### §6.2 READ
|
|
460
446
|
|
|
461
|
-
AST: `{ op: "READ",
|
|
447
|
+
AST: `{ op: "READ", target: ParsedPath, body: MatcherBody | null, signal: tags | null, lineMarker?: LineMarker }`.
|
|
462
448
|
|
|
463
449
|
Engine dispatches to `scheme.read(statement, ctx)`. Scheme:
|
|
464
450
|
- Returns the body channel content + mimetype for `path`, or `{ status: 404 }`.
|
|
@@ -467,7 +453,7 @@ Engine dispatches to `scheme.read(statement, ctx)`. Scheme:
|
|
|
467
453
|
|
|
468
454
|
### §6.3 SHOW / HIDE
|
|
469
455
|
|
|
470
|
-
AST: `{ op: "SHOW"|"HIDE",
|
|
456
|
+
AST: `{ op: "SHOW"|"HIDE", target: ParsedPath, body: MatcherBody | null, signal: tags | null, lineMarker?: LineMarker }`.
|
|
471
457
|
|
|
472
458
|
Engine dispatches to `scheme.show(statement, ctx)` / `scheme.hide(statement, ctx)`. Scheme:
|
|
473
459
|
- Flips `visibility.indexed` for every channel of the targeted entry to 1 (SHOW) or 0 (HIDE).
|
|
@@ -476,7 +462,7 @@ Engine dispatches to `scheme.show(statement, ctx)` / `scheme.hide(statement, ctx
|
|
|
476
462
|
|
|
477
463
|
### §6.4 COPY (engine-orchestrated)
|
|
478
464
|
|
|
479
|
-
AST: `{ op: "COPY",
|
|
465
|
+
AST: `{ op: "COPY", target: ParsedPath (source), body: ParsedPath (destination), signal: tags | null, lineMarker?: LineMarker }`.
|
|
480
466
|
|
|
481
467
|
Engine orchestrates over CRUD primitives (§3.2, §3.4):
|
|
482
468
|
|
|
@@ -493,7 +479,7 @@ Same- and cross-scheme COPY both go through this orchestrator. {§6.4-cross-sche
|
|
|
493
479
|
|
|
494
480
|
### §6.5 MOVE (engine-orchestrated)
|
|
495
481
|
|
|
496
|
-
AST: `{ op: "MOVE",
|
|
482
|
+
AST: `{ op: "MOVE", target: ParsedPath (source), body: ParsedPath | null (destination), signal: tags | null, lineMarker?: LineMarker }`.
|
|
497
483
|
|
|
498
484
|
Two modes:
|
|
499
485
|
|
|
@@ -501,11 +487,11 @@ Two modes:
|
|
|
501
487
|
|
|
502
488
|
**Deletion** (`body` is null): engine runs `src_scheme.deleteEntry(source_pathname, ctx)` directly. The null-body MOVE expresses "relocate to nowhere" = delete. {§6.5-null-body-deletes} Returns 200 on success, 404 if source absent. {§6.5-missing-source-404}
|
|
503
489
|
|
|
504
|
-
Log history is preserved through MOVE because `log_entries
|
|
490
|
+
Log history is preserved through MOVE because `log_entries`' URI-bit columns (`scheme`, `pathname`, etc.) store the path tuple as text, not FK to `entries.id`.
|
|
505
491
|
|
|
506
492
|
### §6.6 FIND
|
|
507
493
|
|
|
508
|
-
AST: `{ op: "FIND",
|
|
494
|
+
AST: `{ op: "FIND", target: ParsedPath (scope), body: MatcherBody | null (predicate), signal: tags | null (tag filter), lineMarker?: LineMarker }`.
|
|
509
495
|
|
|
510
496
|
Engine dispatches to `scheme.find(statement, ctx)`. Scheme:
|
|
511
497
|
- Filters entries within the path's scope (scheme + pathname prefix). {§6.6-scope-prefix-filter}
|
|
@@ -516,7 +502,7 @@ Engine dispatches to `scheme.find(statement, ctx)`. Scheme:
|
|
|
516
502
|
|
|
517
503
|
### §6.7 SEND
|
|
518
504
|
|
|
519
|
-
AST: `{ op: "SEND",
|
|
505
|
+
AST: `{ op: "SEND", target: ParsedPath | null, body: SendBody | null, signal: number | null }`.
|
|
520
506
|
|
|
521
507
|
Two modes:
|
|
522
508
|
|
|
@@ -530,7 +516,7 @@ Two modes:
|
|
|
530
516
|
|
|
531
517
|
### §6.8 EXEC
|
|
532
518
|
|
|
533
|
-
AST: `{ op: "EXEC",
|
|
519
|
+
AST: `{ op: "EXEC", target: ParsedPath (cwd), body: string | null (command), signal: string | null (runtime tag) }`.
|
|
534
520
|
|
|
535
521
|
Deferred. The `exec` scheme is in §10's bundled set but lacks a working handler; calls return 501. Sandboxing design and process-lifecycle semantics are the substance to figure out, drawing on rummy's exec plugin as prior art.
|
|
536
522
|
|
|
@@ -647,40 +633,31 @@ Versioning: a `plurnkContractVersion` field on each plugin's `plurnk` manifest d
|
|
|
647
633
|
|
|
648
634
|
## §10 Bundled Set
|
|
649
635
|
|
|
650
|
-
|
|
636
|
+
What ships in-tree vs. in sibling `@plurnk/*` packages. Plugin discovery (§9) finds every installed `@plurnk/*` package at boot and registers what they declare; the system runs against whatever is present in `node_modules`.
|
|
651
637
|
|
|
652
|
-
**Providers:**
|
|
653
|
-
- `
|
|
638
|
+
**Providers in-tree (`src/providers/`):**
|
|
639
|
+
- `Mock` — fake provider used exclusively in `intg` for deterministic engine tests. Also serves as a minimal worked example for authors of external provider packages.
|
|
654
640
|
|
|
655
|
-
|
|
656
|
-
- `text/plain` — universal fallback. Identity validate; head-truncated preview. Stays bundled because every deployment needs it and it has no external dependency.
|
|
641
|
+
All real providers are siblings, registered via plugin discovery.
|
|
657
642
|
|
|
658
|
-
**
|
|
659
|
-
|
|
660
|
-
- `
|
|
643
|
+
**Mimetypes in-tree:** none. The framework (`@plurnk/plurnk-mimetypes`) and every handler are siblings.
|
|
644
|
+
|
|
645
|
+
**Schemes in-tree (`src/schemes/`):**
|
|
646
|
+
- `plurnk` — indexable scheme for internal model-interactions. Current use: `plurnk://prompt/<loop_id>` carries each loop's prompt as a body-channel entry written on loop start. Manifest-level writability is open (any origin); model-origin writes to `plurnk://prompt/*` are rejected in-handler (engine + client own those paths).
|
|
647
|
+
- `log` — coordinate-addressed log entries. Read returns a summary of the action at `log://<loop_seq>/<turn_seq>/<sequence>`; SHOW/HIDE toggle the row's `indexed` flag (log entries are not entries-table entries, but participate in the model's curation surface via URI dispatch). Each entry renders in the packet as a single JSON meta line — no fence, no body — with `path` = the log entry's own URI (`log://<L>/<T>/<S>/<op>`) and `target` = the URI the action acted on. Errors mirror to `packet.user.telemetry.errors[]` per §15.1; status ≥ 400 in the meta signals "look in telemetry."
|
|
661
648
|
- `known` — primary narrative entries.
|
|
662
649
|
- `unknown` — decomposition / open questions.
|
|
663
650
|
- `skill` — sibling of known/unknown; semantics provisional.
|
|
664
|
-
- `exec` — manifest only; subprocess invocation
|
|
665
|
-
- `file` —
|
|
666
|
-
|
|
667
|
-
**Sibling repos** (live `@plurnk/*` packages we own):
|
|
668
|
-
- **Mimetypes:** `@plurnk/plurnk-mimetypes-text-markdown` — first extraction (#47). Validates the "bundle minimally" pattern.
|
|
669
|
-
- **Providers:** `@plurnk/plurnk-providers-openai` — talks to any OpenAI-compatible endpoint (OpenAI proper, llama-server, Ollama OpenAI-compat, etc.).
|
|
670
|
-
- **Client:** `@plurnk/plurnk` — user-facing CLI/TUI (independent agent ownership since #57).
|
|
671
|
-
|
|
672
|
-
**Future external** (separate repos, separate npm packages, optional install when written):
|
|
673
|
-
- **Providers:** `openrouter`, `xai`, `google`, `ollama` (native API), `anthropic`, `cf` (Cloudflare). Phase D.
|
|
674
|
-
- **Schemes:** `http(s)`, `ws(s)`, `sse`, `graphql`, `openapi`, `grpc`, `mailto`, `mcp`, `sftp`, `rest`, `search`. Streaming schemes land in Phase F.
|
|
675
|
-
- **Mimetypes:** `application/json`, `text/vnd.plurnk`, anything beyond. Phase C.
|
|
651
|
+
- `exec` — manifest only; subprocess invocation not yet implemented.
|
|
652
|
+
- `file` — in-tree; extraction to a sibling repo is planned once the workspace + exec/streams work shapes the scheme's full surface. **The model is never trained on `file://` and never sees it in any rendered output.** Bare paths (`README.md`, `/abs/path.txt`) are the model-facing form; `file://` is accepted as an explicit input for absolute root paths but renders bare in the index, log, and every other model-facing surface.
|
|
676
653
|
|
|
677
|
-
|
|
654
|
+
In-tree schemes will move to siblings as their surfaces stabilize.
|
|
678
655
|
|
|
679
656
|
---
|
|
680
657
|
|
|
681
658
|
## §11 Grammar Dependency
|
|
682
659
|
|
|
683
|
-
`@plurnk/plurnk-grammar
|
|
660
|
+
`@plurnk/plurnk-grammar` is the contract. Treat it as authoritative; surface gaps to the user, don't redesign from this side. When a gap surfaces, file an issue upstream and adopt whatever lands.
|
|
684
661
|
|
|
685
662
|
### §11.1 What grammar provides
|
|
686
663
|
|
|
@@ -691,23 +668,13 @@ Plugin discovery (§9) finds every installed `@plurnk/*` package at boot and reg
|
|
|
691
668
|
|
|
692
669
|
### §11.2 What plurnk-service tracks in its own runtime state (NOT in the grammar)
|
|
693
670
|
|
|
694
|
-
- Channel lifecycle (`active` / `closed` / `errored`) — subscription registry, not on `ChannelContent`.
|
|
695
|
-
- Render budget per channel
|
|
671
|
+
- Channel lifecycle (`active` / `closed` / `errored`) — subscription registry, not on `ChannelContent`. Streams are not a distinct paradigm at the contract layer; they're a runtime relationship between an entry and an open connection.
|
|
672
|
+
- Render budget per channel — `PLURNK_ENTRY_SIZE_DEFAULT_TOKENS` operator config (§12); character-count today (§14.2).
|
|
696
673
|
- Backpressure caps — none in v0 (§7.8). Providers/schemes/mimetypes own their own throttling.
|
|
697
674
|
- Stream cancel verb — no dedicated cancel op or signal in the grammar. SEND[499] to the URI is the pattern (§7.7).
|
|
698
675
|
- Delete verb — no dedicated DELETE op. SEND[410] to the URI is the pattern (§3.5, §6.5).
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
All grammar issues filed against the upstream contract have closed and shipped. Service tracks the resolution:
|
|
703
|
-
|
|
704
|
-
- **#6 `text/vnd.plurnk`** — closed; DSL mimetype identifier confirmed.
|
|
705
|
-
- **#7 public `parsePath` helper** — closed; landed in grammar 0.3.2.
|
|
706
|
-
- **#8 SEND broadcast vs directed clarification** — closed; grammar plurnk.md docs tightened.
|
|
707
|
-
- **#9 packet contract + parse-error surface** — closed; grammar 0.4.0 renamed `packet.user.turn` → `packet.user.telemetry` and shipped the `{budget, errors}` shape. Service aligned in #123.
|
|
708
|
-
- **#10 Run.name + dual-handle** — closed; grammar 0.5.0 added required `Run.name`. Service aligned in #123.
|
|
709
|
-
|
|
710
|
-
When future gaps surface, they get filed as grammar issues (not redesigned in plurnk-service), and the relevant SPEC.md section notes the pending request.
|
|
676
|
+
- Per-loop flag plumbing — `loops.flags` JSON column. Engine plumbs the grammar's `LoopFlags` shape (yolo, mode, noWeb, noInteraction, noProposals) per-loop; today `yolo` is end-to-end, others are scheduled.
|
|
677
|
+
- Wire-rendering conventions on top of grammar fences — see §5.5 default-channel addressing.
|
|
711
678
|
|
|
712
679
|
---
|
|
713
680
|
|
|
@@ -729,8 +696,10 @@ Model selection uses a separate alias cascade managed by `ProviderRegistry` (`sr
|
|
|
729
696
|
| `PLURNK_MAX_STRIKES` | `3` | enforced | Strike threshold + sudden-death lead time (§0.5). |
|
|
730
697
|
| `PLURNK_MIN_CYCLES` | `3` | enforced | Min repetitions before cycle detection fires (§0.5). |
|
|
731
698
|
| `PLURNK_MAX_CYCLE_PERIOD` | `4` | enforced | Max period length cycle detection examines (§0.5). |
|
|
732
|
-
| `
|
|
733
|
-
| `
|
|
699
|
+
| `PLURNK_PERSONA` | `persona.md` | enforced | Path to the default persona file. Tail of the persona cascade: loops.persona > runs.persona > sessions.persona > this file. |
|
|
700
|
+
| `PLURNK_PROPOSAL_TIMEOUT_MS` | `300000` | enforced | ms wait for a proposed entry (status=202) to be resolved before timing out. |
|
|
701
|
+
| `PLURNK_REASON` | `0` | enforced | Reasoning-token budget. 0 = disabled. Positive = budget in tokens; provider modules translate to wire format. |
|
|
702
|
+
| `PLURNK_FETCH_TIMEOUT` | `600000` | enforced | Service-wide ms ceiling on any outbound request (providers, future http schemes). Module-specific overrides are allowed below the ceiling. |
|
|
734
703
|
| `PLURNK_ENTRY_SIZE_DEFAULT_TOKENS` | `256` | enforced | Per-channel preview budget for index tiles (characters; §14.2). |
|
|
735
704
|
| `PLURNK_DEBUG` | `0` | reserved | Schema-validation toggle. Not yet enforced. |
|
|
736
705
|
| `PLURNK_LOG_LEVEL` | `info` | reserved | Stdout banner verbosity. Not yet enforced. |
|
|
@@ -838,21 +807,31 @@ The minimum v0 surface. Methods are grouped by concern.
|
|
|
838
807
|
|
|
839
808
|
**Sessions**
|
|
840
809
|
|
|
841
|
-
| Method
|
|
842
|
-
|
|
843
|
-
| `session.create`
|
|
844
|
-
| `session.list`
|
|
845
|
-
| `session.attach`
|
|
846
|
-
| `session.runs`
|
|
810
|
+
| Method | Params | Result | Notes |
|
|
811
|
+
|------------------------|---------------------|-------------------|-------|
|
|
812
|
+
| `session.create` | `name?: string`, `projectRoot?: string`, `persona?: string` | `{ id, name, projectRoot, persona }` | Creates new session; auto-name if unprovided. Optional `projectRoot` pins the workspace (null/omitted = headless). Optional `persona` sets the session-level persona override. |
|
|
813
|
+
| `session.list` | none | `{ sessions: Session[] }` | Lists all sessions. |
|
|
814
|
+
| `session.attach` | `id: number`, `runId?: number`, `runName?: string`, `persona?: string` | `{ id, name, runId, runName }` | Binds this connection to an existing session. Optional `runId` resumes that specific run (must belong to the session). Optional `runName` reuses-or-creates by name within the session. Both omitted → new auto-named run. Optional `persona` sets run-level persona only when a NEW run is created. |
|
|
815
|
+
| `session.runs` | `id?: number` | `{ runs: Run[] }` | Lists runs in a session (defaults to attached session); most-recent first. |
|
|
816
|
+
| `session.set_root` | `projectRoot: string \| null` | `{ projectRoot }` | Update the workspace pointer on the attached session. Null reverts to headless. |
|
|
817
|
+
| `session.set_persona` | `persona: string \| null` | `{ persona }` | Update the session-level persona. Null clears the override (falls through to PLURNK_PERSONA file). |
|
|
847
818
|
|
|
848
819
|
If a client issues a method requiring init (`requiresInit: true`) without first calling `session.attach` or `session.create`, the daemon auto-creates the envelope on demand: session → run → client loop, all persisted normally. Auto-creation is a convenience for one-off invocations (Telegram quick-queries, neovim ad-hoc dispatches, `plurnk "prompt"` CLI shots); the records carry through the same way explicitly-created ones do. **Auto-created ≠ auto-deleted.** Records persist for the log's forensic value. If a client wants active cleanup, that's a future `session.delete` / `session.archive` endpoint, opt-in.
|
|
849
820
|
|
|
850
821
|
**Loops (model-driven)**
|
|
851
822
|
|
|
823
|
+
| Method | Params | Result | Notes |
|
|
824
|
+
|-------------------|-------------------------------------|------------------------|-------|
|
|
825
|
+
| `loop.run` | `prompt: string`, `maxTurns?: number`, `alias?: string`, `flags?: LoopFlags`, `persona?: string` | `{ loopId, turnIds, finalStatus, hitMaxTurns, reason }` | Model-driven loop. Optional `alias` overrides the boot-time `PLURNK_MODEL`. Optional `flags` carries per-loop flags (currently `{yolo?: boolean}`; more arrive as wired — see §0.5). Optional `persona` sets the loop-level persona (highest precedence in the cascade). Streams `log/entry` and `loop/proposal` notifications during. `longRunning: true`. |
|
|
826
|
+
| `loop.resolve` | `logEntryId: number`, `decision: "accept" \| "reject" \| "cancel"`, `body?: string`, `outcome?: string` | `{ status, logEntryId }` | Resolve a pending proposal (status=202 log entry). Engine.dispatch unpauses on resolution. |
|
|
827
|
+
| `providers.list` | none | `{ aliases: ProviderAlias[] }` | Lists configured `PLURNK_MODEL_<alias>` entries with `{alias, provider, model, active}`. Clients use to populate model-selection UI. |
|
|
828
|
+
|
|
829
|
+
**Reads**
|
|
830
|
+
|
|
852
831
|
| Method | Params | Result | Notes |
|
|
853
832
|
|---------------|-------------------------------------|------------------------|-------|
|
|
854
|
-
| `
|
|
855
|
-
| `
|
|
833
|
+
| `entry.read` | `target: string` | `{ status, entry }` | Read the full entry shape (channels + tags + metadata) at the given URI. |
|
|
834
|
+
| `log.read` | `loopId?: number`, … | `{ entries: LogEntry[] }` | Read recent log entries from the attached session, optionally filtered by loop. |
|
|
856
835
|
|
|
857
836
|
**DSL operations (client-driven, mirror the grammar)**
|
|
858
837
|
|
|
@@ -860,15 +839,17 @@ Per the **Speak in DSL, not plumbing** rule (AGENTS.md Standing Rules): RPC meth
|
|
|
860
839
|
|
|
861
840
|
Each `op.*` call creates a turn in the connection's client loop (§13.7) with the constructed statement as a single action, dispatches it, fires a `log/entry` notification to attached clients of the session, returns the dispatch result.
|
|
862
841
|
|
|
842
|
+
Naming follows the uniform principle: `target` is the URI the op acts on (the operand); `scope` for FIND (the search root); `source`/`destination` for COPY/MOVE; `recipient` for SEND (or null = broadcast); `cwd` for EXEC. `path` is never an RPC operand here — that word is reserved for *identity* throughout plurnk (the URI of *this thing*).
|
|
843
|
+
|
|
863
844
|
| Method | Params | Notes |
|
|
864
845
|
|---------------|---------------------------------------------------------|-------|
|
|
865
846
|
| `op.find` | `scope: string`, `matcher?: string`, `tags?: string[]`, `lineRange?: LineMarker` | Mirrors `<<FIND>>`. |
|
|
866
|
-
| `op.read` | `
|
|
867
|
-
| `op.edit` | `
|
|
847
|
+
| `op.read` | `target: string`, `matcher?: string`, `lineRange?: LineMarker`, `tags?: string[]` | Mirrors `<<READ>>`. |
|
|
848
|
+
| `op.edit` | `target: string`, `content?: string`, `tags?: string[]`, `lineRange?: LineMarker` | Mirrors `<<EDIT>>`. |
|
|
868
849
|
| `op.copy` | `source: string`, `destination: string`, `tags?: string[]`, `lineRange?: LineMarker` | Mirrors `<<COPY>>`. |
|
|
869
850
|
| `op.move` | `source: string`, `destination?: string`, `tags?: string[]`, `lineRange?: LineMarker` | Mirrors `<<MOVE>>`. Missing `destination` = delete (null-body MOVE). |
|
|
870
|
-
| `op.show` | `
|
|
871
|
-
| `op.hide` | `
|
|
851
|
+
| `op.show` | `target: string`, `matcher?: string`, `tags?: string[]`, `lineRange?: LineMarker` | Mirrors `<<SHOW>>`. |
|
|
852
|
+
| `op.hide` | `target: string`, `matcher?: string`, `tags?: string[]`, `lineRange?: LineMarker` | Mirrors `<<HIDE>>`. |
|
|
872
853
|
| `op.send` | `status: number`, `recipient?: string`, `body?: string` | Mirrors `<<SEND>>`. |
|
|
873
854
|
| `op.exec` | `cwd?: string`, `runtime?: string`, `command?: string` | Mirrors `<<EXEC>>`. |
|
|
874
855
|
| `op.dispatch` | `statement: PlurnkStatement` | Low-level path for clients that have a parsed AST already (e.g. the TUI when the user types raw HEREDOC at the prompt). |
|
|
@@ -879,7 +860,7 @@ All `op.*` methods return `{ status: number, ...op-specific-extras }`. They are
|
|
|
879
860
|
Future-reserved (post-v0):
|
|
880
861
|
|
|
881
862
|
- `subscription.list` — list active streaming subscriptions (§7).
|
|
882
|
-
- `subscription.cancel` — analog of `SEND[499]` over RPC, though `op.send({status: 499, recipient
|
|
863
|
+
- `subscription.cancel` — analog of `SEND[499]` over RPC, though `op.send({status: 499, recipient})` does the same thing today.
|
|
883
864
|
|
|
884
865
|
### §13.6 Notifications
|
|
885
866
|
|
|
@@ -889,10 +870,11 @@ Server-initiated events streamed to the client over the same WebSocket. Critical
|
|
|
889
870
|
|--------------------|-------------------------------------|------------|
|
|
890
871
|
| `log/entry` | `{ entry: LogEntry }` | Every time a `log_entries` row is written. |
|
|
891
872
|
| `loop/terminated` | `{ loopId, finalStatus, hitMaxTurns }` | When a loop reaches a terminal status. |
|
|
892
|
-
| `
|
|
873
|
+
| `loop/proposal` | `{ logEntryId, sessionId, runId, loopId, turnId, op, target, body, attrs, flags }` | Fired when dispatch pauses on a status=202 proposed entry. Carries the proposal payload + the loop's `flags` so a client connected to a server-YOLO loop can suppress its review UI. Client responds with `loop.resolve` (or ignores, in which case the daemon's `PLURNK_PROPOSAL_TIMEOUT_MS` fires). |
|
|
874
|
+
| `session/created` | `{ id, name, projectRoot, persona }` | When a session is created (any client's action; gives multi-client awareness). |
|
|
893
875
|
| `stream/event` | `{ entryId, channel, state, contentLength }` | When a channel's content grows or its state transitions. For clients rendering live; the model only sees state at turn boundaries. {§13.6-stream-event-on-channel-change} |
|
|
894
876
|
|
|
895
|
-
The `stream/event` payload deliberately carries metadata, NOT content. Clients that want the new content call `entry.read({
|
|
877
|
+
The `stream/event` payload deliberately carries metadata, NOT content. Clients that want the new content call `entry.read({target})` to fetch — this avoids large notification payloads and gives the client agency over whether to refresh. Sample-driven (notifications include `contentLength` so clients can dedupe / batch).
|
|
896
878
|
|
|
897
879
|
Notifications are scoped to the connection's attached session — a client attached to session A does NOT receive `log/entry` notifications for actions on session B. (Cross-session observation is a future feature; v0 keeps the scope tight.)
|
|
898
880
|
|
|
@@ -958,9 +940,7 @@ Error responses MAY include `data: { ... }` with structured context (the path th
|
|
|
958
940
|
|
|
959
941
|
### §13.9 Versioning
|
|
960
942
|
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
Current: `protocolVersion: "0.1.0"`. The floor is green and the daemon has been exercised end-to-end via the `plurnk` TUI client (which now graduates to its own agent). Promotes to `1.0.0` when an independent external client (neovim plugin or Telegram bot) lands AND the mimetype/channel/transaction work below has settled.
|
|
943
|
+
Pre-interface-stabilization. The RPC surface evolves freely; clients track HEAD. No semver promises until we have an actual interface worth committing to.
|
|
964
944
|
|
|
965
945
|
---
|
|
966
946
|
|
|
@@ -982,24 +962,21 @@ Each entry: the question, the answer, the rationale, the migration path if revis
|
|
|
982
962
|
|
|
983
963
|
**Migration path if revisited.** If a future plugin needs to inject a packet section (e.g., a `<turn>` metadata table per rummy SPEC §packet_structure), the engine grows a single `packet.augment` filter hook called after `#buildIndex` returns. Plugins subscribe with a priority; each returns a `system` and/or `user` augmentation object that gets merged into the packet shape. This is additive — the engine-direct base case stays; plugins augment.
|
|
984
964
|
|
|
985
|
-
### §14.2 Budget unit: character count
|
|
965
|
+
### §14.2 Budget unit: character count
|
|
986
966
|
|
|
987
|
-
**Question.** `PLURNK_ENTRY_SIZE_DEFAULT_TOKENS` is named for tokens;
|
|
967
|
+
**Question.** `PLURNK_ENTRY_SIZE_DEFAULT_TOKENS` is named for tokens; the engine passes it as a character-count budget to mimetype processing. Env var name and implementation disagree.
|
|
988
968
|
|
|
989
|
-
**Decision.**
|
|
969
|
+
**Decision.** Budget is character count. The env var name is a forward-naming placeholder for an eventual token unit; today it means characters. {§14.2-budget-is-characters-v0}
|
|
990
970
|
|
|
991
|
-
**Rationale.**
|
|
992
|
-
- Token counts require a per-provider tokenizer. PROVIDERS.md §11 marks `countTokens` as out of v0 contract; no provider currently exposes it.
|
|
993
|
-
- Character count is a tokenizer-independent first approximation. Wrong by a factor of ~3-4× for English (1 token ≈ 3-4 chars), but consistent and zero-config.
|
|
994
|
-
- Switching the unit later requires: (a) `countTokens` lands on the provider contract, (b) engine caches token counts per `(provider_id, content_hash)`, (c) mimetype.preview gets a tokenizer reference or returns content for engine to tokenize-and-truncate. Out of v0 scope.
|
|
971
|
+
**Rationale.** Mimetype handlers operate on strings. They have no tokenizer reference and shouldn't — tokenization is provider-bound (§2.3). Character-count is the tokenizer-independent budget that fits the handler's domain. Engine *could* post-tokenize the resulting preview for accounting (the provider's `countTokens` is available), but the budget passed *into* the handler is characters by design.
|
|
995
972
|
|
|
996
|
-
**Migration path if revisited.**
|
|
973
|
+
**Migration path if revisited.** Either rename the env var to reflect characters, or change the budget semantic to tokens by handing handlers a tokenizer reference (`preview(content, budget, countTokens?)`). The latter conflates concerns and isn't appealing.
|
|
997
974
|
|
|
998
975
|
---
|
|
999
976
|
|
|
1000
977
|
## §15 Packet shape
|
|
1001
978
|
|
|
1002
|
-
The canonical packet shape is defined by `@plurnk/plurnk-grammar` (`schema/Packet.json
|
|
979
|
+
The canonical packet shape is defined by `@plurnk/plurnk-grammar` (`schema/Packet.json`). Engine assembles in `Engine.#buildRequestPacket`; plugins do not augment in v0 (§14.1). This section describes plurnk-service's responsibilities under that contract — see grammar for the authoritative schema.
|
|
1003
980
|
|
|
1004
981
|
```ts
|
|
1005
982
|
type Packet = {
|
|
@@ -1022,6 +999,8 @@ type Packet = {
|
|
|
1022
999
|
};
|
|
1023
1000
|
```
|
|
1024
1001
|
|
|
1002
|
+
**Prompt as a first-class entry.** Each loop's prompt is written on loop start as a system-origin `EDIT` against `plurnk://prompt/<loop_id>` (indexable entry, body channel, text/markdown). The corresponding log row renders as `* {"op":"EDIT","origin":"system","path":"log://<L>/1/1/EDIT","status":201,"target":"plurnk://prompt/<L>"}` — `path` is the log row's own URI, `target` is the plurnk entry that got written. At render time, the *current* loop's `plurnk://prompt/<loop_id>` entry is foisted out of `packet.system.index` and materialized in `packet.user.prompt` — one section, one mechanism, no duplicate content rendering. Previous loops' prompt entries remain in the index and are addressable for the model to READ or HIDE. {§15-current-prompt-foist}
|
|
1003
|
+
|
|
1025
1004
|
### §15.1 user.telemetry — model-facing runtime telemetry
|
|
1026
1005
|
|
|
1027
1006
|
The slot for telemetry the model MUST react to right now: budget pressure and last-turn failures that didn't produce an action-entry. Rendered prominently at the bottom of the user section so the model cannot ignore it. Errors here are transient — they appear on the turn AFTER the failure and clear once the model has seen them. The action-entries (`packet.system.log[]`) are the durable audit; `telemetry.errors[]` is the **alert**.
|
|
@@ -1034,12 +1013,19 @@ The slot for telemetry the model MUST react to right now: budget pressure and la
|
|
|
1034
1013
|
**Plurnk-service rendering (v0):**
|
|
1035
1014
|
|
|
1036
1015
|
- `budget` is rendered as a short markdown line. Unit follows §14.2 (character count); the exact rendering is engine-internal and may evolve without a schema change.
|
|
1037
|
-
- `errors[]` carries
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1016
|
+
- `errors[]` carries telemetry from the previous turn's dispatch + rail evaluation. Each element has a required `kind` discriminator and a required `message` string (human-readable, model-actionable). Additional kind-specific fields are flat on the element — there is NO nested `detail` envelope; canonical-JSON serialization sorts keys for prefix-cache friendliness.
|
|
1017
|
+
- Wire format: one `* {canonical-JSON}` line per error under `# Plurnk System Errors`, in push order. Buffer drains on read — each error appears in exactly one packet. {§15.1-drain-on-read}
|
|
1018
|
+
|
|
1019
|
+
**Kinds emitted by plurnk-service v0:**
|
|
1020
|
+
|
|
1021
|
+
| `kind` | Source | Required fields | Additional fields |
|
|
1022
|
+
|---|---|---|---|
|
|
1023
|
+
| `action_failure` | Log entry with `status_rx ≥ 400` from previous turn | `kind`, `message`, `coordinate` (`<L>/<T>/<S>`), `op`, `status` | `target` (URI or null) |
|
|
1024
|
+
| `no_ops` | Rail #41 — turn ended with zero ops | `kind`, `message` | — |
|
|
1025
|
+
| `strike` | Rail #38 — strike streak bumped (no_ops / recorded_failure / rail) | `kind`, `message`, `streak`, `maxStrikes`, `reason` | — |
|
|
1026
|
+
| `cycle` | Rail #39 — repeating turn fingerprint pattern detected | `kind`, `message`, `period`, `cycles` | — |
|
|
1027
|
+
| `sudden_death` | Rail #40 — entering the last `maxStrikes`-sized window before `maxTurns` | `kind`, `message`, `remaining` | — |
|
|
1028
|
+
|
|
1029
|
+
Action-bound failures (handler returned 4xx/5xx or threw) are mirrored as the `action_failure` kind on the next packet — same forced-confrontation pattern. Full detail stays queryable via `log://`. {§15.1-no-error-scheme}
|
|
1044
1030
|
|
|
1045
1031
|
**No `error://` scheme.** Actionless failures route to telemetry, not to a queryable scheme namespace.
|
|
@@ -7,6 +7,16 @@ export interface StreamEventPayload {
|
|
|
7
7
|
contentLength: number;
|
|
8
8
|
}
|
|
9
9
|
export type StreamEventNotify = (sessionId: number, event: StreamEventPayload) => void;
|
|
10
|
+
export interface WakeRunPayload {
|
|
11
|
+
sessionId: number;
|
|
12
|
+
runId: number;
|
|
13
|
+
entryId: number;
|
|
14
|
+
subscriptionId: number;
|
|
15
|
+
closeStatus: number;
|
|
16
|
+
scheme: string;
|
|
17
|
+
summary: string;
|
|
18
|
+
}
|
|
19
|
+
export type WakeRunNotify = (payload: WakeRunPayload) => void;
|
|
10
20
|
export declare const appendToChannel: (db: Db, { entryId, channel, chunk, notify }: {
|
|
11
21
|
entryId: number;
|
|
12
22
|
channel: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ChannelWrite.d.ts","sourceRoot":"","sources":["../../src/core/ChannelWrite.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,EAAE,EAAc,MAAM,SAAS,CAAC;AAE9C,MAAM,MAAM,YAAY,GAAG,QAAQ,GAAG,QAAQ,GAAG,QAAQ,GAAG,SAAS,CAAC;AAEtE,MAAM,WAAW,kBAAkB;IAC/B,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,YAAY,CAAC;IACpB,aAAa,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,MAAM,iBAAiB,GAAG,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,kBAAkB,KAAK,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"ChannelWrite.d.ts","sourceRoot":"","sources":["../../src/core/ChannelWrite.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,EAAE,EAAc,MAAM,SAAS,CAAC;AAE9C,MAAM,MAAM,YAAY,GAAG,QAAQ,GAAG,QAAQ,GAAG,QAAQ,GAAG,SAAS,CAAC;AAEtE,MAAM,WAAW,kBAAkB;IAC/B,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,YAAY,CAAC;IACpB,aAAa,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,MAAM,iBAAiB,GAAG,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,kBAAkB,KAAK,IAAI,CAAC;AAQvF,MAAM,WAAW,cAAc;IAC3B,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,cAAc,EAAE,MAAM,CAAC;IACvB,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,MAAM,aAAa,GAAG,CAAC,OAAO,EAAE,cAAc,KAAK,IAAI,CAAC;AAe9D,eAAO,MAAM,eAAe,GACxB,IAAI,EAAE,EACN,qCAAqC;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,iBAAiB,CAAA;CAAE,KACrH,OAAO,CAAC,IAAI,CAOd,CAAC;AAEF,eAAO,MAAM,eAAe,GACxB,IAAI,EAAE,EACN,qCAAqC;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,YAAY,CAAC;IAAC,MAAM,CAAC,EAAE,iBAAiB,CAAA;CAAE,KAC3H,OAAO,CAAC,IAAI,CAOd,CAAC;AAEF,eAAO,MAAM,gBAAgB,GACzB,IAAI,EAAE,EACN,oCAAoC;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,KACvG,OAAO,CAAC,MAAM,CAIhB,CAAC;AAEF,eAAO,MAAM,iBAAiB,GAC1B,IAAI,EAAE,EACN,4BAA4B;IAAE,cAAc,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,KACvE,OAAO,CAAC,IAAI,CAEd,CAAC;AAEF,eAAO,MAAM,sBAAsB,GAC/B,IAAI,EAAE,EACN,oBAAoB;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,KACvD,OAAO,CAAC;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAG/D,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ChannelWrite.js","sourceRoot":"","sources":["../../src/core/ChannelWrite.ts"],"names":[],"mappings":"AAAA,0EAA0E;AAC1E,mEAAmE;AACnE,EAAE;AACF,+EAA+E;AAC/E,8EAA8E;AAC9E,2EAA2E;AAC3E,gCAAgC;
|
|
1
|
+
{"version":3,"file":"ChannelWrite.js","sourceRoot":"","sources":["../../src/core/ChannelWrite.ts"],"names":[],"mappings":"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"}
|
package/dist/core/Engine.d.ts
CHANGED
|
@@ -3,6 +3,7 @@ import type SchemeRegistry from "./SchemeRegistry.ts";
|
|
|
3
3
|
import { Mimetypes } from "@plurnk/plurnk-mimetypes";
|
|
4
4
|
import type { Db } from "./Db.ts";
|
|
5
5
|
import type { LoopFlags } from "./scheme-types.ts";
|
|
6
|
+
import type { StreamEventNotify, WakeRunNotify } from "./ChannelWrite.ts";
|
|
6
7
|
type Origin = "model" | "client" | "system" | "plugin";
|
|
7
8
|
type ChatMessage = {
|
|
8
9
|
role: "system" | "user" | "assistant";
|
|
@@ -15,7 +16,7 @@ type DispatchContext = {
|
|
|
15
16
|
runId: number;
|
|
16
17
|
loopId: number;
|
|
17
18
|
turnId: number;
|
|
18
|
-
|
|
19
|
+
sequence: number;
|
|
19
20
|
origin: Origin;
|
|
20
21
|
onDispatch?: (logEntryId: number) => void;
|
|
21
22
|
};
|
|
@@ -55,10 +56,12 @@ export declare const detectCycle: (history: ReadonlyArray<string>, minCycles: nu
|
|
|
55
56
|
};
|
|
56
57
|
export default class Engine {
|
|
57
58
|
#private;
|
|
58
|
-
constructor({ db, schemes, mimetypes }: {
|
|
59
|
+
constructor({ db, schemes, mimetypes, streamEventNotify, wakeRunNotify }: {
|
|
59
60
|
db: Db;
|
|
60
61
|
schemes: SchemeRegistry;
|
|
61
62
|
mimetypes?: Mimetypes;
|
|
63
|
+
streamEventNotify?: StreamEventNotify;
|
|
64
|
+
wakeRunNotify?: WakeRunNotify;
|
|
62
65
|
});
|
|
63
66
|
runLoop({ provider, messages, persona, sessionId, runId, loopId, maxTurns, maxStrikes, minCycles, maxCyclePeriod, origin, signal, onDispatch, }: {
|
|
64
67
|
provider: Provider;
|
|
@@ -101,6 +104,11 @@ export default class Engine {
|
|
|
101
104
|
dispatch(context: DispatchContext): Promise<DispatchResult>;
|
|
102
105
|
resolveProposal(logEntryId: number, resolution: ProposalResolution): void;
|
|
103
106
|
pendingProposalIds(): number[];
|
|
107
|
+
hasActiveLoopForRun(runId: number): Promise<boolean>;
|
|
108
|
+
inject(runId: number, prompt: string): Promise<{
|
|
109
|
+
loopId: number;
|
|
110
|
+
turnSeq: number;
|
|
111
|
+
} | null>;
|
|
104
112
|
onProposalPending(listener: (event: ProposalPendingEvent) => void): void;
|
|
105
113
|
}
|
|
106
114
|
export {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Engine.d.ts","sourceRoot":"","sources":["../../src/core/Engine.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,
|
|
1
|
+
{"version":3,"file":"Engine.d.ts","sourceRoot":"","sources":["../../src/core/Engine.ts"],"names":[],"mappings":"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"}
|