@llblab/pi-kit 0.1.13 → 0.2.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/CHANGELOG.md +5 -0
- package/README.md +2 -2
- package/node_modules/@llblab/pi-actors/AGENTS.md +5 -3
- package/node_modules/@llblab/pi-actors/BACKLOG.md +1 -1
- package/node_modules/@llblab/pi-actors/CHANGELOG.md +15 -0
- package/node_modules/@llblab/pi-actors/README.md +5 -3
- package/node_modules/@llblab/pi-actors/dist/index.js +4 -1
- package/node_modules/@llblab/pi-actors/dist/lib/async-runs.d.ts +2 -2
- package/node_modules/@llblab/pi-actors/dist/lib/async-runs.js +42 -19
- package/node_modules/@llblab/pi-actors/dist/lib/extension-runtime.d.ts +2 -1
- package/node_modules/@llblab/pi-actors/dist/lib/extension-runtime.js +7 -2
- package/node_modules/@llblab/pi-actors/dist/lib/limits.d.ts +9 -0
- package/node_modules/@llblab/pi-actors/dist/lib/limits.js +9 -0
- package/node_modules/@llblab/pi-actors/dist/lib/observability.d.ts +10 -11
- package/node_modules/@llblab/pi-actors/dist/lib/observability.js +81 -56
- package/node_modules/@llblab/pi-actors/dist/lib/pi.d.ts +31 -0
- package/node_modules/@llblab/pi-actors/dist/lib/pi.js +180 -0
- package/node_modules/@llblab/pi-actors/dist/lib/run-delivery.d.ts +115 -0
- package/node_modules/@llblab/pi-actors/dist/lib/run-delivery.js +623 -0
- package/node_modules/@llblab/pi-actors/dist/lib/run-ui-runtime.d.ts +3 -0
- package/node_modules/@llblab/pi-actors/dist/lib/run-ui-runtime.js +341 -13
- package/node_modules/@llblab/pi-actors/dist/lib/runs-trace.d.ts +1 -1
- package/node_modules/@llblab/pi-actors/dist/lib/runs-trace.js +5 -3
- package/node_modules/@llblab/pi-actors/dist/lib/session-evidence.d.ts +16 -0
- package/node_modules/@llblab/pi-actors/dist/lib/session-evidence.js +143 -0
- package/node_modules/@llblab/pi-actors/dist/lib/temp.js +1 -1
- package/node_modules/@llblab/pi-actors/dist/lib/tools-inspect.js +3 -1
- package/node_modules/@llblab/pi-actors/dist/scripts/async-runner.mjs +5 -19
- package/node_modules/@llblab/pi-actors/dist/skills/actors/SKILL.md +2 -2
- package/node_modules/@llblab/pi-actors/dist/skills/actors/references/runs.md +1 -1
- package/node_modules/@llblab/pi-actors/dist/skills/swarm/SKILL.md +1 -1
- package/node_modules/@llblab/pi-actors/docs/README.md +1 -0
- package/node_modules/@llblab/pi-actors/docs/async-runs.md +8 -4
- package/node_modules/@llblab/pi-actors/docs/coordinator-delivery.md +207 -0
- package/node_modules/@llblab/pi-actors/index.ts +4 -1
- package/node_modules/@llblab/pi-actors/lib/async-runs.ts +42 -21
- package/node_modules/@llblab/pi-actors/lib/extension-runtime.ts +8 -3
- package/node_modules/@llblab/pi-actors/lib/limits.ts +9 -0
- package/node_modules/@llblab/pi-actors/lib/observability.ts +97 -78
- package/node_modules/@llblab/pi-actors/lib/pi.ts +210 -0
- package/node_modules/@llblab/pi-actors/lib/run-delivery.ts +800 -0
- package/node_modules/@llblab/pi-actors/lib/run-ui-runtime.ts +370 -18
- package/node_modules/@llblab/pi-actors/lib/runs-trace.ts +6 -4
- package/node_modules/@llblab/pi-actors/lib/session-evidence.ts +153 -0
- package/node_modules/@llblab/pi-actors/lib/temp.ts +1 -1
- package/node_modules/@llblab/pi-actors/lib/tools-inspect.ts +4 -1
- package/node_modules/@llblab/pi-actors/package.json +3 -3
- package/node_modules/@llblab/pi-actors/scripts/async-runner.mjs +5 -19
- package/node_modules/@llblab/pi-actors/skills/actors/SKILL.md +2 -2
- package/node_modules/@llblab/pi-actors/skills/actors/references/runs.md +1 -1
- package/node_modules/@llblab/pi-actors/skills/swarm/SKILL.md +1 -1
- package/node_modules/@llblab/pi-telegram/AGENTS.md +4 -4
- package/node_modules/@llblab/pi-telegram/CHANGELOG.md +11 -0
- package/node_modules/@llblab/pi-telegram/README.md +1 -1
- package/node_modules/@llblab/pi-telegram/docs/activity.md +4 -4
- package/node_modules/@llblab/pi-telegram/docs/architecture.md +5 -5
- package/node_modules/@llblab/pi-telegram/docs/outbound.md +2 -2
- package/node_modules/@llblab/pi-telegram/docs/public-api.md +3 -4
- package/node_modules/@llblab/pi-telegram/docs/ui-style.md +4 -5
- package/node_modules/@llblab/pi-telegram/docs/voice.md +12 -2
- package/node_modules/@llblab/pi-telegram/index.ts +0 -1
- package/node_modules/@llblab/pi-telegram/lib/activity.ts +3 -5
- package/node_modules/@llblab/pi-telegram/lib/bindings.ts +13 -17
- package/node_modules/@llblab/pi-telegram/lib/bus-leader.ts +1 -1
- package/node_modules/@llblab/pi-telegram/lib/config.ts +25 -25
- package/node_modules/@llblab/pi-telegram/lib/menu-settings.ts +10 -73
- package/node_modules/@llblab/pi-telegram/lib/status.ts +11 -1
- package/node_modules/@llblab/pi-telegram/package.json +1 -1
- package/node_modules/@llblab/pi-telegram/skills/generated-control-surface/SKILL.md +5 -3
- package/package.json +3 -3
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,11 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to `@llblab/pi-kit` are documented here.
|
|
4
4
|
|
|
5
|
+
## 0.2.0 - 2026-08-31
|
|
6
|
+
|
|
7
|
+
- `Actors Minor Releases`: Advances `@llblab/pi-actors` to `0.52.0`, bringing root-owned follow-ups, durable completion epochs, presentation acknowledgment, recovery-safe scheduling, explicit urgent steering, and settled packed-package parity into the bundled kit.
|
|
8
|
+
- `Telegram Minor Release`: Advances `@llblab/pi-telegram` to `0.41.0`, keeping typing active through settled work and compaction, making connected companion projection always-on, and updating generated controls, connection notices, token telemetry, and voice setup guidance.
|
|
9
|
+
|
|
5
10
|
## 0.1.13 - 2026-08-30
|
|
6
11
|
|
|
7
12
|
- `Telegram Minor Release`: Advances `@llblab/pi-telegram` to `0.40.0`, requiring Pi 0.84.4 and adopting native compaction-failure, mid-run compaction, terminal-message, and local UI-prompt lifecycle contracts while increasing bounded inbound text output to 24,000 characters.
|
package/README.md
CHANGED
|
@@ -6,10 +6,10 @@
|
|
|
6
6
|
|
|
7
7
|
| Package | Version | Resources |
|
|
8
8
|
| --- | ---: | --- |
|
|
9
|
-
| `@llblab/pi-actors` | `0.
|
|
9
|
+
| `@llblab/pi-actors` | `0.52.0` | Extension and Skills |
|
|
10
10
|
| `@llblab/pi-codex-usage` | `0.9.4` | Extension |
|
|
11
11
|
| `@llblab/pi-grow-loop` | `0.7.3` | Extension and Skills |
|
|
12
|
-
| `@llblab/pi-telegram` | `0.
|
|
12
|
+
| `@llblab/pi-telegram` | `0.41.0` | Extension and Skills |
|
|
13
13
|
|
|
14
14
|
Versions are exact by design. Updating an extension does not change an installed kit until this repository explicitly advances that dependency and publishes a new kit version.
|
|
15
15
|
|
|
@@ -84,7 +84,7 @@ Canonical event:
|
|
|
84
84
|
{"id":"…","ts":"…","kind":"…","summary":"…","data":{},"level":"info","attention":"notify"}
|
|
85
85
|
```
|
|
86
86
|
|
|
87
|
-
Trace is a bounded retained suffix, not an audit archive. Every first-party writer must call `appendRunTraceEvent`; under the canonical token-owned lock it appends within both fixed bounds or atomically retains the newest suffix plus one cumulative warning-only `runtime.trace_compacted` marker. The marker means older history was discarded; terminal/result/execution/artifact files remain authoritative independently. Reads are newline-safe and order equal timestamps by same-source ordinal, fixed source rank, then stable id without exposing ordering metadata. Never write `trace.jsonl` directly.
|
|
87
|
+
Trace is a bounded retained suffix, not an audit archive. Every first-party writer must call `appendRunTraceEvent`; under the canonical token-owned lock it appends within both fixed bounds or atomically retains the newest suffix plus one cumulative warning-only `runtime.trace_compacted` marker. The marker means older history was discarded; terminal/result/execution/artifact files remain authoritative independently. Reads are newline-safe and order equal timestamps by same-source ordinal, fixed source rank, then stable id without exposing ordering metadata. Never write `trace.jsonl` directly. Generic command lifecycle is Trace-only: `command.done` preserves complete bounded execution evidence but never requests or projects any attention value, and Recipe grammar has no command-completion delivery switch. Semantic attention is explicit: `notify` is visible status, `followup` is an ordinary checkpoint hint, and actor-authored `steer` is durable urgent delivery at Pi's next safe boundary. Never infer attention from status or exit code. Admit steer by exact event and Run generation before `deliverAs: "steer"`; acknowledge only its exact model-bound context envelope, and preserve the later root-terminal completion batch. Sequence, parallel, repeat, and import branches remain internal, while each separately launched Run owns a separate generation.
|
|
88
88
|
|
|
89
89
|
### Control
|
|
90
90
|
|
|
@@ -134,9 +134,11 @@ Automatic review receives value-free structural projections, not executable cont
|
|
|
134
134
|
|
|
135
135
|
Tool result/error text contributes exactly one leading line break. Keep model-facing responses compact and state-backed. Preserve complete byte-exact command streams in bounded spill files while returning bounded tails; never feed truncated tails into pipeline stdin.
|
|
136
136
|
|
|
137
|
-
File watchers accelerate reconciliation; a bounded interval recovers missed terminal and retained-attention events. Canonical attention observation uses stable retained ids
|
|
137
|
+
File watchers accelerate reconciliation; a bounded interval recovers missed terminal and retained-attention events. Canonical attention observation uses stable retained ids and bounds seen memory to the current suffix across compaction; only allowlisted legacy outbox fallback uses line offsets. Ordinary `notify` and `followup` hints prime at startup without replay and require durable state or artifacts for recovery. Explicit `steer` instead re-enters through the owner journal until exact presentation records its newer generation-fenced Trace marker.
|
|
138
138
|
|
|
139
|
-
|
|
139
|
+
Ordinary root terminals remain authoritative in Run state until the owner-scoped completion scheduler snapshots an immutable batch at a settled or idle boundary. Batch delivery is generation-fenced and bounded at 256 durable members, 64 model-facing rows, 16 KiB of context, and a 1 MiB journal. `sendMessage()` acceptance advances only to queued; only the exact batch id and content appearing in model-bound `context` advances to presented and authorizes exact-generation handled markers. Restart recovery walks the bounded active Pi session parent chain: exact queued evidence waits without resend, proven absence returns the envelope to pending, and incomplete or conflicting evidence remains queued with diagnostics. Retry duplicates collapse before presentation, malformed envelopes fail closed, and automatic review waits behind an active completion batch.
|
|
140
|
+
|
|
141
|
+
When deferred Run results gate the next step, wait for their completion batch. Inspect early only for operator request, meaningful attention, or diagnosis of an overdue Run.
|
|
140
142
|
|
|
141
143
|
## Documentation and Release Discipline
|
|
142
144
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Project Backlog
|
|
2
2
|
|
|
3
|
-
- [ ] `
|
|
3
|
+
- [ ] `Next minor — Linux MPRIS media integration`: Expose the active `music-player/playback` singleton as one optional generation-fenced MPRIS2 player so GNOME and compatible desktop shells can show current media and native controls without making D-Bus a second playback authority.
|
|
4
4
|
- [ ] Publish `PlaybackStatus`, track metadata, duration, read-time position, volume, and supported capabilities under one stable session-scoped bus identity; disappear cleanly when the Run stops or its generation is replaced, and fail soft when the user D-Bus session is unavailable.
|
|
5
5
|
- [ ] Map `Play`, `Pause`, `PlayPause`, `Next`, `Previous`, `Stop`, `Seek`, `SetPosition`, and `Volume` back into the existing generation-fenced music-player Control/helper contract rather than signaling the backend or editing Run state directly.
|
|
6
6
|
- [ ] Validate deterministic D-Bus contract behavior plus a live GNOME smoke showing the media surface, metadata, progress, volume, and controls while preserving backend independence and exact Actor ownership.
|
|
@@ -2,6 +2,21 @@
|
|
|
2
2
|
|
|
3
3
|
> Each release keeps at most 8 outcome records of at most 512 characters.
|
|
4
4
|
|
|
5
|
+
## 0.52.0: Durable Coordinator Delivery
|
|
6
|
+
|
|
7
|
+
- `Completion Epochs`: Replaces per-Run terminal turns with one immutable owner-fenced completion batch per idle/settled epoch. Batches retain exact Run generations and terminal timestamps, bound durable and model-facing members, preserve silent and synchronous-stop semantics, and remain eligible after urgent steering.
|
|
8
|
+
- `Presentation Acknowledgment`: Persists completion delivery through `pending`, `queued`, and `presented`; Pi transport acceptance advances only to `queued`, while exact model-bound `context` presentation authorizes generation-fenced terminal handled markers. Duplicate envelopes collapse and altered or conflicting content fails closed.
|
|
9
|
+
- `Recovery-Safe Scheduling`: Stores owner-hashed atomic delivery journals with bounded receipts, attempts, and errors. Restart recovery inspects only the bounded active Pi session chain, retries proven-absent envelopes, preserves uncertain queued evidence, rejects malformed, oversized, duplicate, and symlinked state, and keeps the scheduler directory through stale-temp cleanup.
|
|
10
|
+
- `Explicit Urgent Steering`: Adds durable actor-authored Trace `attention: "steer"` envelopes delivered only through Pi's safe steer boundary. Exact presentation writes generation-fenced `delivery.steer_presented` evidence, suppresses historical replay, and never suppresses the later root-terminal completion batch; `command.done` remains Trace-only regardless of legacy attention fields.
|
|
11
|
+
- `Settled Packed Parity`: Exercises the compiled package against the Pi 0.84.4 lifecycle contract, proving urgent steer presentation precedes its exact completion epoch, with `agent_settled`, follow-up/steer delivery modes, model-bound context acknowledgment, terminal fencing, and durable steer evidence.
|
|
12
|
+
|
|
13
|
+
## 0.51.0: Monotonic Run Follow-Ups
|
|
14
|
+
|
|
15
|
+
- `Root-Owned Follow-Up`: A normal finite Run now produces one automatic agent turn from its root terminal result. Sequence, parallel, repeat, and imported branches remain internal execution topology; each separately launched Run still owns a separate generation and terminal lifecycle.
|
|
16
|
+
- `Trace-Only Command Lifecycle`: Consolidates each command completion into one complete bounded `command.done` observation with level, captures, session provenance, artifacts, and execution evidence, but no attention. Legacy `command.done` attention remains non-projectable, and the removed Recipe-level delivery grammar stays removed.
|
|
17
|
+
- `Monotonic Reconciliation`: Delivers terminal transitions before explicit semantic attention, preserves silent Runs, synchronous stop behavior, generation fencing, terminal retry evidence, and semantic checkpoints, and removes branch exit-code heuristics that could wake the coordinator from stale process-level events.
|
|
18
|
+
- `Settled Pi Baseline`: Requires Pi and Pi TUI 0.84.4 or newer and schedules automatic Recipe review on `agent_settled`, after queued follow-ups, retries, and compaction complete. Source and packed-package regressions pin the lifecycle and minimum peer contract.
|
|
19
|
+
|
|
5
20
|
## 0.50.0: Hardened Actor Baseline
|
|
6
21
|
|
|
7
22
|
- `Template Recipe Standard`: Rebuilt the Recipe authoring guide around one current-state contract: formats, identity, uniformly detailed file-level and command-node field tables, resolution precedence, imports, async/singleton lifecycle, Control, artifacts, runtime origins, provenance, authoring workflow, and validation. Removed migration history and legacy-reference narration from the normative document.
|
|
@@ -15,11 +15,11 @@ An **actor** is any runnable local capability: a script, tool, service, pipeline
|
|
|
15
15
|
|
|
16
16
|
Multi-instance systems commonly put instance creation and routing in an external gateway. pi-actors supports a different topology: the current Pi instance remains the coordinator, companion extensions such as Telegram provide presence, and explicit Runs perform bounded delegated work. The coordinator receives high-level outcomes, decomposes them, stays available for decisions, and owns integration plus final validation instead of becoming another undifferentiated worker.
|
|
17
17
|
|
|
18
|
-
This topology does not require every task to become a subagent. Short work with one natural validation boundary stays inline; delegation pays when clean context, asynchronous execution, independent judgement, parallel ownership, or coordinator availability exceeds its coordination cost. Bounded implementation can run with reasoning off while the coordinator selectively launches clean-context reasoning-enabled reviewers; several independent reviews can provide broader evidence than one author self-review.
|
|
18
|
+
This topology does not require every task to become a subagent. Short work with one natural validation boundary stays inline; delegation pays when clean context, asynchronous execution, independent judgement, parallel ownership, or coordinator availability exceeds its coordination cost. Bounded implementation can run with reasoning off while the coordinator selectively launches clean-context reasoning-enabled reviewers; several independent reviews can provide broader evidence than one author self-review. Settled completion batches, durable Trace, and declared artifacts replace tight polling loops.
|
|
19
19
|
|
|
20
20
|
## Install
|
|
21
21
|
|
|
22
|
-
Requires Node.js 22.19.0 or newer.
|
|
22
|
+
Requires Node.js 22.19.0 or newer and Pi 0.84.4 or newer.
|
|
23
23
|
|
|
24
24
|
```bash
|
|
25
25
|
pi install npm:@llblab/pi-actors
|
|
@@ -151,7 +151,9 @@ String command-template leaves execute directly without shell interpretation. Us
|
|
|
151
151
|
|
|
152
152
|
Trace fields are exact: `id`, `ts`, `kind`, and optional `summary`, `data`, `level`, `attention`. Address, sender, recipient, reply, and routing fields fail validation. Trace is a bounded retained suffix, not an audit archive: the canonical authority appends within 2,048 events and 4 MiB or atomically keeps the newest suffix plus one warning-only `runtime.trace_compacted` marker. That marker means older history was discarded; `result.json`, `execution.json`, terminal state, and declared artifacts retain their own authority. `inspect view=trace` reports whether retained history is complete. Reads are newline-safe and deterministic; first-party scripts never write this file directly.
|
|
153
153
|
|
|
154
|
-
|
|
154
|
+
Generic command lifecycle is Trace-only: runner-owned `command.done` records preserve completion and execution evidence but never request or project attention, including malformed legacy records carrying `steer`. There is no Recipe-level command-completion delivery switch. Semantic attention is explicit: `notify` shows visible status without a model turn, `followup` supplies ordinary checkpoint context, and `steer` requests urgent delivery at Pi's next safe assistant/tool boundary. `notify` and `followup` remain retained wake hints that may compact away, so persist recovery state or an artifact first. `steer` is admitted to the bounded owner delivery journal before `deliverAs: "steer"`, acknowledged only in exact model-bound context, and never suppresses the eventual root-terminal batch. Store large evidence in artifacts or bounded execution captures.
|
|
155
|
+
|
|
156
|
+
Ordinary finite Runs project root terminal results through one owner-fenced completion scheduler. Completions that accumulate while Pi is active or inside the idle debounce window enter one immutable bounded batch and cause one automatic agent turn after Pi settles; terminal generations are acknowledged only when that exact batch reaches model-bound context. Sequence, parallel, repeat, and imported branches remain internal and never create branch-level turns, while separately launched Runs retain exact independent generations. Silent Runs and synchronous stop acknowledgments remain non-projecting.
|
|
155
157
|
|
|
156
158
|
## Control
|
|
157
159
|
|
|
@@ -9,7 +9,10 @@ export default function toolRegistryExtension(pi) {
|
|
|
9
9
|
const runtime = ExtensionRuntime.createActorExtensionRuntime(pi);
|
|
10
10
|
pi.on("resources_discover", async () => runtime.discoverResources(import.meta.url));
|
|
11
11
|
pi.on("session_start", async (_event, ctx) => runtime.onSessionStart(ctx));
|
|
12
|
-
pi.on("
|
|
12
|
+
pi.on("agent_settled", async (_event, ctx) => runtime.onAgentSettled(ctx));
|
|
13
|
+
pi.on("context", async (event, ctx) => ({
|
|
14
|
+
messages: runtime.onContext(event.messages, ctx),
|
|
15
|
+
}));
|
|
13
16
|
pi.on("session_shutdown", async (event, ctx) => runtime.onSessionShutdown(event.reason, ctx));
|
|
14
17
|
pi.on("before_agent_start", async (event, ctx) => runtime.beforeAgentStart(event.systemPrompt, event.systemPromptOptions.skills ?? [], ctx));
|
|
15
18
|
InspectorCommand.registerActorInspectorCommand(pi, runtime.getRunOwnerId);
|
|
@@ -136,8 +136,8 @@ export interface RunControlExpectation {
|
|
|
136
136
|
ownerId?: string;
|
|
137
137
|
runInstanceId?: string;
|
|
138
138
|
}
|
|
139
|
-
export declare function markRunTerminalNotificationHandled(stateDir: string, status: string):
|
|
140
|
-
export declare function
|
|
139
|
+
export declare function markRunTerminalNotificationHandled(stateDir: string, status: string, expectedRunInstanceId: string): boolean;
|
|
140
|
+
export declare function markRunSteerPresentationHandled(stateDir: string, expectedRunInstanceId: string, eventId: string, steerId: string): boolean;
|
|
141
141
|
export declare function cancelRun(runOrDir: string, expected?: RunControlExpectation): Record<string, unknown>;
|
|
142
142
|
export declare function archiveRun(runOrDir: string, expected?: RunControlExpectation): Record<string, unknown>;
|
|
143
143
|
export declare function pruneRun(runOrDir: string, options?: {
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
*/
|
|
5
5
|
import { spawn } from "node:child_process";
|
|
6
6
|
import { randomUUID } from "node:crypto";
|
|
7
|
-
import { closeSync, existsSync, mkdirSync, openSync, readdirSync, statSync, } from "node:fs";
|
|
7
|
+
import { closeSync, existsSync, mkdirSync, openSync, readdirSync, rmSync, statSync, } from "node:fs";
|
|
8
8
|
import { basename, dirname, extname, isAbsolute, join, relative, resolve } from "node:path";
|
|
9
9
|
import { fileURLToPath } from "node:url";
|
|
10
10
|
import { isDeepStrictEqual } from "node:util";
|
|
@@ -719,25 +719,48 @@ function stopRun(runOrDir, signal, event, expected = {}) {
|
|
|
719
719
|
releaseControlLock();
|
|
720
720
|
}
|
|
721
721
|
}
|
|
722
|
-
export function markRunTerminalNotificationHandled(stateDir, status) {
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
722
|
+
export function markRunTerminalNotificationHandled(stateDir, status, expectedRunInstanceId) {
|
|
723
|
+
const releaseLock = RunsStart.acquireStateStartLock(stateDir);
|
|
724
|
+
try {
|
|
725
|
+
if (!existsSync(join(stateDir, "run.json")))
|
|
726
|
+
return false;
|
|
727
|
+
const current = getRunStatus(stateDir);
|
|
728
|
+
if (current.run_instance_id !== expectedRunInstanceId ||
|
|
729
|
+
current.status !== status)
|
|
730
|
+
return false;
|
|
731
|
+
markTerminalHandled(stateDir, {
|
|
732
|
+
event: "run.notification",
|
|
733
|
+
run_instance_id: expectedRunInstanceId,
|
|
734
|
+
status,
|
|
735
|
+
});
|
|
736
|
+
rmSync(join(stateDir, "terminal-delivery-failure.json"), { force: true });
|
|
737
|
+
return true;
|
|
738
|
+
}
|
|
739
|
+
finally {
|
|
740
|
+
releaseLock();
|
|
741
|
+
}
|
|
727
742
|
}
|
|
728
|
-
export function
|
|
729
|
-
const
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
.
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
743
|
+
export function markRunSteerPresentationHandled(stateDir, expectedRunInstanceId, eventId, steerId) {
|
|
744
|
+
const releaseLock = RunsStart.acquireStateStartLock(stateDir);
|
|
745
|
+
try {
|
|
746
|
+
if (!existsSync(join(stateDir, "run.json")))
|
|
747
|
+
return false;
|
|
748
|
+
const current = getRunStatus(stateDir);
|
|
749
|
+
if (current.run_instance_id !== expectedRunInstanceId)
|
|
750
|
+
return false;
|
|
751
|
+
appendRunTraceEvent(stateDir, {
|
|
752
|
+
data: {
|
|
753
|
+
event_id: eventId,
|
|
754
|
+
run_instance_id: expectedRunInstanceId,
|
|
755
|
+
steer_id: steerId,
|
|
756
|
+
},
|
|
757
|
+
kind: "delivery.steer_presented",
|
|
758
|
+
});
|
|
759
|
+
return true;
|
|
760
|
+
}
|
|
761
|
+
finally {
|
|
762
|
+
releaseLock();
|
|
763
|
+
}
|
|
741
764
|
}
|
|
742
765
|
export function cancelRun(runOrDir, expected = {}) {
|
|
743
766
|
const result = stopRun(runOrDir, "SIGTERM", "run.cancel", expected);
|
|
@@ -13,7 +13,8 @@ export interface ActorExtensionRuntime {
|
|
|
13
13
|
skillPaths: string[];
|
|
14
14
|
} | undefined;
|
|
15
15
|
getRunOwnerId(ctx: Pi.ExtensionContext): string;
|
|
16
|
-
|
|
16
|
+
onAgentSettled(ctx: Pi.ExtensionContext): void;
|
|
17
|
+
onContext(messages: unknown[], ctx: Pi.ExtensionContext): unknown[];
|
|
17
18
|
onSessionShutdown(reason: string, ctx: Pi.ExtensionContext): void;
|
|
18
19
|
onSessionStart(ctx: Pi.ExtensionContext): Promise<void>;
|
|
19
20
|
registerCoreTools(): void;
|
|
@@ -112,10 +112,15 @@ export function createActorExtensionRuntime(pi) {
|
|
|
112
112
|
return skillPaths.length > 0 ? { skillPaths } : undefined;
|
|
113
113
|
},
|
|
114
114
|
getRunOwnerId,
|
|
115
|
-
|
|
116
|
-
if (activeRunContext
|
|
115
|
+
onAgentSettled(ctx) {
|
|
116
|
+
if (activeRunContext !== ctx)
|
|
117
|
+
return;
|
|
118
|
+
if (!runUiRuntime.flushCompletionBatch(ctx))
|
|
117
119
|
automaticReview.schedule();
|
|
118
120
|
},
|
|
121
|
+
onContext(messages, ctx) {
|
|
122
|
+
return runUiRuntime.projectContext(messages, ctx);
|
|
123
|
+
},
|
|
119
124
|
onSessionShutdown(reason, ctx) {
|
|
120
125
|
const ownerId = runOwnerIdsByContext.get(ctx);
|
|
121
126
|
runOwnerIdsByContext.delete(ctx);
|
|
@@ -27,3 +27,12 @@ export declare const RUN_CONTROL_ERROR_MAX_BYTES: number;
|
|
|
27
27
|
export declare const RUN_CONTROL_JOURNAL_MAX_BYTES: number;
|
|
28
28
|
export declare const RUN_RETENTION_MAX_RECORDS = 256;
|
|
29
29
|
export declare const RUN_RETENTION_MAX_BYTES: number;
|
|
30
|
+
export declare const RUN_DELIVERY_BATCH_MAX_MEMBERS = 256;
|
|
31
|
+
export declare const RUN_DELIVERY_MODEL_MAX_MEMBERS = 64;
|
|
32
|
+
export declare const RUN_DELIVERY_MODEL_MAX_BYTES: number;
|
|
33
|
+
export declare const RUN_DELIVERY_RECEIPT_LIMIT = 128;
|
|
34
|
+
export declare const RUN_DELIVERY_SESSION_MAX_ENTRIES = 256;
|
|
35
|
+
export declare const RUN_DELIVERY_SESSION_MAX_BYTES: number;
|
|
36
|
+
export declare const RUN_DELIVERY_STEER_MAX_ENVELOPES = 64;
|
|
37
|
+
export declare const RUN_DELIVERY_STEER_MAX_BYTES: number;
|
|
38
|
+
export declare const RUN_DELIVERY_JOURNAL_MAX_BYTES: number;
|
|
@@ -27,3 +27,12 @@ export const RUN_CONTROL_ERROR_MAX_BYTES = 4 * 1024;
|
|
|
27
27
|
export const RUN_CONTROL_JOURNAL_MAX_BYTES = 1024 * 1024;
|
|
28
28
|
export const RUN_RETENTION_MAX_RECORDS = 256;
|
|
29
29
|
export const RUN_RETENTION_MAX_BYTES = 1024 * 1024;
|
|
30
|
+
export const RUN_DELIVERY_BATCH_MAX_MEMBERS = 256;
|
|
31
|
+
export const RUN_DELIVERY_MODEL_MAX_MEMBERS = 64;
|
|
32
|
+
export const RUN_DELIVERY_MODEL_MAX_BYTES = 16 * 1024;
|
|
33
|
+
export const RUN_DELIVERY_RECEIPT_LIMIT = 128;
|
|
34
|
+
export const RUN_DELIVERY_SESSION_MAX_ENTRIES = 256;
|
|
35
|
+
export const RUN_DELIVERY_SESSION_MAX_BYTES = 1024 * 1024;
|
|
36
|
+
export const RUN_DELIVERY_STEER_MAX_ENVELOPES = 64;
|
|
37
|
+
export const RUN_DELIVERY_STEER_MAX_BYTES = 16 * 1024;
|
|
38
|
+
export const RUN_DELIVERY_JOURNAL_MAX_BYTES = 1024 * 1024;
|
|
@@ -5,8 +5,9 @@
|
|
|
5
5
|
*/
|
|
6
6
|
import { type FSWatcher } from "node:fs";
|
|
7
7
|
import * as AsyncRuns from "./async-runs.ts";
|
|
8
|
+
import type { RunCompletionBatchMember } from "./run-delivery.ts";
|
|
8
9
|
export type RunObservedStatus = "running" | "done" | "failed" | "exited" | "cancelled" | "killed";
|
|
9
|
-
export type RunTraceAttention = "log" | "notify" | "followup";
|
|
10
|
+
export type RunTraceAttention = "log" | "notify" | "followup" | "steer";
|
|
10
11
|
export type RunTraceLevel = "info" | "warning" | "error";
|
|
11
12
|
export interface RunObservation {
|
|
12
13
|
activeSubagents?: number;
|
|
@@ -23,6 +24,7 @@ export interface RunObservation {
|
|
|
23
24
|
terminalHandled?: boolean;
|
|
24
25
|
retireWhen?: string;
|
|
25
26
|
run: string;
|
|
27
|
+
runInstanceId?: string;
|
|
26
28
|
semanticResult?: RunTerminalSemanticResult;
|
|
27
29
|
tool?: string;
|
|
28
30
|
stateDir?: string;
|
|
@@ -68,15 +70,6 @@ export declare function readRunUiSnapshot(state: RunUiObservationState, ownerId:
|
|
|
68
70
|
stateRoot?: string;
|
|
69
71
|
}): RunUiSnapshot;
|
|
70
72
|
export declare function pruneRunUiObservationState(state: RunUiObservationState, snapshot: Pick<RunUiSnapshot, "summary" | "transitions">): void;
|
|
71
|
-
export declare function deliverRunTransitionNotifications(transitions: RunTransition[], sink: RunUiNotificationSink, inFlight?: Set<string>): void;
|
|
72
|
-
export declare function reconcileRunTerminalNotifications(input: {
|
|
73
|
-
inFlight?: Set<string>;
|
|
74
|
-
ownerId: string;
|
|
75
|
-
sink: RunUiNotificationSink;
|
|
76
|
-
state: RunUiObservationState;
|
|
77
|
-
stateRoot?: string;
|
|
78
|
-
includeAttention?: boolean;
|
|
79
|
-
}): RunUiSnapshot;
|
|
80
73
|
export declare function deliverRunAttentionNotifications(events: RunAttentionEvent[], sink: RunUiNotificationSink): void;
|
|
81
74
|
export interface RunRetirementCandidate {
|
|
82
75
|
activeSubagents: number;
|
|
@@ -133,7 +126,9 @@ export interface RunRetirementExecutorOptions {
|
|
|
133
126
|
export interface RunTransition {
|
|
134
127
|
from: RunObservedStatus;
|
|
135
128
|
run: string;
|
|
129
|
+
runInstanceId?: string;
|
|
136
130
|
stateDir?: string;
|
|
131
|
+
terminalAt?: string;
|
|
137
132
|
artifacts?: Record<string, string>;
|
|
138
133
|
launchCorrelation?: Record<string, string>;
|
|
139
134
|
launchSource?: AsyncRuns.AsyncRunLaunchSource;
|
|
@@ -161,6 +156,7 @@ export interface RunAttentionEvent {
|
|
|
161
156
|
level: RunTraceLevel;
|
|
162
157
|
metadata?: Record<string, unknown>;
|
|
163
158
|
run: string;
|
|
159
|
+
runInstanceId?: string;
|
|
164
160
|
stateDir: string;
|
|
165
161
|
summary: string;
|
|
166
162
|
ts: string;
|
|
@@ -178,9 +174,12 @@ export declare function pruneRunObservationState(previousStatuses: Map<string, R
|
|
|
178
174
|
export declare function detectRunAttentionEvents(legacyLineCounts: Map<string, number>, summary: RunSummary, seenEventIds?: Map<string, Set<string>>, prime?: boolean): RunAttentionEvent[];
|
|
179
175
|
export declare function getRunAttentionNotificationType(event: RunAttentionEvent): RunTransitionNotificationType;
|
|
180
176
|
export declare function shouldNotifyRunAttentionEvent(event: RunAttentionEvent): boolean;
|
|
177
|
+
export declare function isRunSteerAttentionEvent(event: RunAttentionEvent): boolean;
|
|
178
|
+
export declare function retryRunAttentionEvent(state: RunUiObservationState, event: Pick<RunAttentionEvent, "id" | "stateDir">): void;
|
|
181
179
|
export declare function shouldSendRunAttentionFollowUp(event: RunAttentionEvent): boolean;
|
|
182
180
|
export declare function formatRunAttentionMessage(event: RunAttentionEvent): string;
|
|
183
181
|
export declare function getRunTransitionNotificationType(transition: RunTransition): RunTransitionNotificationType;
|
|
184
182
|
export declare function shouldNotifyRunTransition(transition: RunTransition): boolean;
|
|
185
|
-
|
|
183
|
+
/** Build exact immutable generation members for owner-journal admission. */
|
|
184
|
+
export declare function collectRunCompletionBatchMembers(transitions: RunTransition[]): RunCompletionBatchMember[];
|
|
186
185
|
export declare function formatRunTransitionMessage(transition: RunTransition): string;
|
|
@@ -35,52 +35,6 @@ export function readRunUiSnapshot(state, ownerId, options = {}) {
|
|
|
35
35
|
export function pruneRunUiObservationState(state, snapshot) {
|
|
36
36
|
pruneRunObservationState(state.observed, state.legacyEventLines, snapshot.summary, snapshot.transitions.map((transition) => transition.stateDir ?? transition.run), state.attentionEventIds);
|
|
37
37
|
}
|
|
38
|
-
export function deliverRunTransitionNotifications(transitions, sink, inFlight = new Set()) {
|
|
39
|
-
for (const transition of transitions) {
|
|
40
|
-
if (!shouldNotifyRunTransition(transition))
|
|
41
|
-
continue;
|
|
42
|
-
const key = transition.stateDir ?? transition.run;
|
|
43
|
-
if (inFlight.has(key))
|
|
44
|
-
continue;
|
|
45
|
-
inFlight.add(key);
|
|
46
|
-
try {
|
|
47
|
-
const text = formatRunTransitionMessage(transition);
|
|
48
|
-
sink.notify(text, getRunTransitionNotificationType(transition));
|
|
49
|
-
if (!shouldSendRunTransitionFollowUp(transition))
|
|
50
|
-
continue;
|
|
51
|
-
sink.sendFollowUp({
|
|
52
|
-
customType: "pi-actors-run",
|
|
53
|
-
content: text,
|
|
54
|
-
display: false,
|
|
55
|
-
details: transition,
|
|
56
|
-
});
|
|
57
|
-
if (transition.stateDir) {
|
|
58
|
-
AsyncRuns.markRunTerminalNotificationHandled(transition.stateDir, transition.to);
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
catch (error) {
|
|
62
|
-
if (transition.stateDir) {
|
|
63
|
-
AsyncRuns.recordRunTerminalDeliveryFailure(transition.stateDir, transition.to, error);
|
|
64
|
-
}
|
|
65
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
66
|
-
sink.notify(`Actor terminal delivery failed for run:${transition.run}: ${message.replaceAll(/\s+/g, " ").slice(0, 240)}`, "error");
|
|
67
|
-
}
|
|
68
|
-
finally {
|
|
69
|
-
inFlight.delete(key);
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
export function reconcileRunTerminalNotifications(input) {
|
|
74
|
-
const snapshot = readRunUiSnapshot(input.state, input.ownerId, {
|
|
75
|
-
includeAttention: input.includeAttention,
|
|
76
|
-
stateRoot: input.stateRoot,
|
|
77
|
-
});
|
|
78
|
-
if (input.includeAttention)
|
|
79
|
-
deliverRunAttentionNotifications(snapshot.attentionEvents, input.sink);
|
|
80
|
-
deliverRunTransitionNotifications(snapshot.transitions, input.sink, input.inFlight);
|
|
81
|
-
pruneRunUiObservationState(input.state, snapshot);
|
|
82
|
-
return snapshot;
|
|
83
|
-
}
|
|
84
38
|
export function deliverRunAttentionNotifications(events, sink) {
|
|
85
39
|
for (const event of events) {
|
|
86
40
|
if (!shouldNotifyRunAttentionEvent(event))
|
|
@@ -271,11 +225,18 @@ function getProgress(status) {
|
|
|
271
225
|
}
|
|
272
226
|
function getUpdatedAt(status) {
|
|
273
227
|
const progress = getProgress(status);
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
228
|
+
const result = status.result &&
|
|
229
|
+
typeof status.result === "object" &&
|
|
230
|
+
!Array.isArray(status.result)
|
|
231
|
+
? status.result
|
|
232
|
+
: {};
|
|
233
|
+
return typeof result.completed_at === "string"
|
|
234
|
+
? result.completed_at
|
|
235
|
+
: typeof progress.updatedAt === "string"
|
|
236
|
+
? progress.updatedAt
|
|
237
|
+
: typeof status.createdAt === "string"
|
|
238
|
+
? status.createdAt
|
|
239
|
+
: undefined;
|
|
279
240
|
}
|
|
280
241
|
function scanRunStateDirs(stateRoot, depth = 0, seen = new Set()) {
|
|
281
242
|
if (!existsSync(stateRoot) || seen.has(stateRoot))
|
|
@@ -409,6 +370,9 @@ function observeRun(stateDir) {
|
|
|
409
370
|
...(typeof status.recipe_file === "string"
|
|
410
371
|
? { recipeFile: status.recipe_file }
|
|
411
372
|
: {}),
|
|
373
|
+
...(typeof status.run_instance_id === "string"
|
|
374
|
+
? { runInstanceId: status.run_instance_id }
|
|
375
|
+
: {}),
|
|
412
376
|
...(status.terminal_handled ? { terminalHandled: true } : {}),
|
|
413
377
|
...(typeof status.retire_when === "string"
|
|
414
378
|
? { retireWhen: status.retire_when }
|
|
@@ -725,8 +689,10 @@ export function detectRunTransitions(previous, summary) {
|
|
|
725
689
|
...(run.launchSource ? { launchSource: run.launchSource } : {}),
|
|
726
690
|
...(run.modelPolicy ? { modelPolicy: run.modelPolicy } : {}),
|
|
727
691
|
...(run.recipeFile ? { recipeFile: run.recipeFile } : {}),
|
|
692
|
+
...(run.runInstanceId ? { runInstanceId: run.runInstanceId } : {}),
|
|
728
693
|
...(run.semanticResult ? { semanticResult: run.semanticResult } : {}),
|
|
729
694
|
...(run.terminalHandled ? { terminalHandled: true } : {}),
|
|
695
|
+
...(run.updatedAt ? { terminalAt: run.updatedAt } : {}),
|
|
730
696
|
to: run.status,
|
|
731
697
|
...(run.tool ? { tool: run.tool } : {}),
|
|
732
698
|
});
|
|
@@ -761,7 +727,9 @@ function parseAttentionRecord(raw, run, index) {
|
|
|
761
727
|
return {
|
|
762
728
|
...(raw.body !== undefined ? { body: raw.body } : {}),
|
|
763
729
|
...(raw.data !== undefined ? { data: raw.data } : {}),
|
|
764
|
-
attention: raw.attention === "notify" ||
|
|
730
|
+
attention: raw.attention === "notify" ||
|
|
731
|
+
raw.attention === "followup" ||
|
|
732
|
+
raw.attention === "steer"
|
|
765
733
|
? raw.attention
|
|
766
734
|
: normalizeTraceAttention(raw.delivery),
|
|
767
735
|
id,
|
|
@@ -773,6 +741,7 @@ function parseAttentionRecord(raw, run, index) {
|
|
|
773
741
|
? { metadata: raw.metadata }
|
|
774
742
|
: {}),
|
|
775
743
|
run: run.run,
|
|
744
|
+
...(run.runInstanceId ? { runInstanceId: run.runInstanceId } : {}),
|
|
776
745
|
stateDir: run.stateDir,
|
|
777
746
|
summary,
|
|
778
747
|
ts,
|
|
@@ -811,6 +780,15 @@ export function detectRunAttentionEvents(legacyLineCounts, summary, seenEventIds
|
|
|
811
780
|
const read = readTraceAttentionRecords(run);
|
|
812
781
|
const retained = new Set();
|
|
813
782
|
const seen = seenEventIds.get(key) ?? new Set();
|
|
783
|
+
const presentedSteerIds = new Set(read.records.flatMap((record) => {
|
|
784
|
+
if (record.kind !== "delivery.steer_presented" ||
|
|
785
|
+
!record.data ||
|
|
786
|
+
typeof record.data !== "object" ||
|
|
787
|
+
Array.isArray(record.data))
|
|
788
|
+
return [];
|
|
789
|
+
const eventId = record.data.event_id;
|
|
790
|
+
return typeof eventId === "string" && eventId ? [eventId] : [];
|
|
791
|
+
}));
|
|
814
792
|
const start = read.canonical ? 0
|
|
815
793
|
: Math.min(legacyLineCounts.get(key) ?? 0, read.records.length);
|
|
816
794
|
for (const [index, record] of read.records.entries()) {
|
|
@@ -819,8 +797,16 @@ export function detectRunAttentionEvents(legacyLineCounts, summary, seenEventIds
|
|
|
819
797
|
event.kind === "runtime.trace_compacted")
|
|
820
798
|
continue;
|
|
821
799
|
retained.add(event.id);
|
|
822
|
-
if (
|
|
800
|
+
if (isRunSteerAttentionEvent(event) && presentedSteerIds.has(event.id)) {
|
|
823
801
|
seen.add(event.id);
|
|
802
|
+
continue;
|
|
803
|
+
}
|
|
804
|
+
if (run.notificationPolicy === "silent")
|
|
805
|
+
seen.add(event.id);
|
|
806
|
+
else if (prime) {
|
|
807
|
+
if (!isRunSteerAttentionEvent(event))
|
|
808
|
+
seen.add(event.id);
|
|
809
|
+
}
|
|
824
810
|
else if (index >= start && !seen.has(event.id)) {
|
|
825
811
|
events.push(event);
|
|
826
812
|
seen.add(event.id);
|
|
@@ -838,7 +824,17 @@ export function getRunAttentionNotificationType(event) {
|
|
|
838
824
|
return event.level;
|
|
839
825
|
}
|
|
840
826
|
export function shouldNotifyRunAttentionEvent(event) {
|
|
841
|
-
|
|
827
|
+
if (event.kind === "command.done")
|
|
828
|
+
return false;
|
|
829
|
+
return event.attention === "notify" ||
|
|
830
|
+
event.attention === "followup" ||
|
|
831
|
+
event.attention === "steer";
|
|
832
|
+
}
|
|
833
|
+
export function isRunSteerAttentionEvent(event) {
|
|
834
|
+
return event.kind !== "command.done" && event.attention === "steer";
|
|
835
|
+
}
|
|
836
|
+
export function retryRunAttentionEvent(state, event) {
|
|
837
|
+
state.attentionEventIds.get(event.stateDir)?.delete(event.id);
|
|
842
838
|
}
|
|
843
839
|
export function shouldSendRunAttentionFollowUp(event) {
|
|
844
840
|
return event.attention === "followup";
|
|
@@ -925,8 +921,37 @@ export function shouldNotifyRunTransition(transition) {
|
|
|
925
921
|
transition.to === "killed" ||
|
|
926
922
|
transition.to === "exited");
|
|
927
923
|
}
|
|
928
|
-
|
|
929
|
-
|
|
924
|
+
/** Build exact immutable generation members for owner-journal admission. */
|
|
925
|
+
export function collectRunCompletionBatchMembers(transitions) {
|
|
926
|
+
return transitions.flatMap((transition) => {
|
|
927
|
+
if (!shouldNotifyRunTransition(transition) ||
|
|
928
|
+
!transition.stateDir ||
|
|
929
|
+
!transition.runInstanceId ||
|
|
930
|
+
!transition.terminalAt ||
|
|
931
|
+
Number.isNaN(Date.parse(transition.terminalAt)))
|
|
932
|
+
return [];
|
|
933
|
+
const artifactEntries = Object.entries(transition.artifacts ?? {})
|
|
934
|
+
.filter((entry) => typeof entry[1] === "string" && Boolean(entry[1]))
|
|
935
|
+
.slice(0, 4);
|
|
936
|
+
const rawSummary = transition.semanticResult?.summary.trim() ||
|
|
937
|
+
`Run ${transition.to}.`;
|
|
938
|
+
return [{
|
|
939
|
+
...(artifactEntries.length > 0
|
|
940
|
+
? { artifacts: Object.fromEntries(artifactEntries) }
|
|
941
|
+
: {}),
|
|
942
|
+
run: transition.run,
|
|
943
|
+
run_instance_id: transition.runInstanceId,
|
|
944
|
+
state_dir: transition.stateDir,
|
|
945
|
+
status: transition.to,
|
|
946
|
+
summary: rawSummary.length > 1_000
|
|
947
|
+
? `${rawSummary.slice(0, 999)}…`
|
|
948
|
+
: rawSummary,
|
|
949
|
+
terminal_at: transition.terminalAt,
|
|
950
|
+
}];
|
|
951
|
+
}).sort((left, right) => left.terminal_at.localeCompare(right.terminal_at) ||
|
|
952
|
+
left.run.localeCompare(right.run) ||
|
|
953
|
+
left.run_instance_id.localeCompare(right.run_instance_id) ||
|
|
954
|
+
left.state_dir.localeCompare(right.state_dir));
|
|
930
955
|
}
|
|
931
956
|
const TERMINAL_FOLLOW_UP_ARTIFACT_LIMIT = 4;
|
|
932
957
|
const TERMINAL_FOLLOW_UP_IDENTIFIER_CHARS = 120;
|
|
@@ -4,7 +4,10 @@
|
|
|
4
4
|
* Owns direct pi SDK imports and exposes narrow pi-actors-facing helpers/types for the composition root.
|
|
5
5
|
*/
|
|
6
6
|
import type { ExtensionAPI, ExtensionContext } from "@earendil-works/pi-coding-agent";
|
|
7
|
+
import * as SessionEvidence from "./session-evidence.ts";
|
|
7
8
|
export type { ExtensionAPI, ExtensionContext };
|
|
9
|
+
export declare const RUN_COMPLETION_BATCH_CUSTOM_TYPE = "pi-actors-run-batch";
|
|
10
|
+
export declare const RUN_STEER_CUSTOM_TYPE = "pi-actors-run-steer";
|
|
8
11
|
export interface PiNotificationSink {
|
|
9
12
|
notify(message: string, level: "info" | "warning" | "error"): void;
|
|
10
13
|
sendFollowUp(message: {
|
|
@@ -16,4 +19,32 @@ export interface PiNotificationSink {
|
|
|
16
19
|
}
|
|
17
20
|
export declare function getSessionId(ctx: ExtensionContext): string;
|
|
18
21
|
export declare function createNotificationSink(pi: ExtensionAPI, ctx: ExtensionContext): PiNotificationSink;
|
|
22
|
+
export declare function sendRunCompletionBatch(pi: ExtensionAPI, batchId: string, content: string): void;
|
|
23
|
+
export declare function sendRunSteer(pi: ExtensionAPI, input: {
|
|
24
|
+
content: string;
|
|
25
|
+
eventId: string;
|
|
26
|
+
steerId: string;
|
|
27
|
+
}): void;
|
|
28
|
+
/** Collapse exact retry duplicates and remove conflicting delivery envelopes. */
|
|
29
|
+
export declare function dedupeRunCompletionBatchContext(messages: unknown[]): {
|
|
30
|
+
batches: Map<string, string>;
|
|
31
|
+
conflicts: Set<string>;
|
|
32
|
+
messages: unknown[];
|
|
33
|
+
};
|
|
34
|
+
export declare function removeRunCompletionBatchFromContext(messages: unknown[], batchId: string): unknown[];
|
|
35
|
+
export declare function dedupeRunSteerContext(messages: unknown[]): {
|
|
36
|
+
conflicts: Set<string>;
|
|
37
|
+
messages: unknown[];
|
|
38
|
+
steers: Map<string, {
|
|
39
|
+
content: string;
|
|
40
|
+
eventId: string;
|
|
41
|
+
}>;
|
|
42
|
+
};
|
|
43
|
+
export declare function removeRunSteerFromContext(messages: unknown[], steerId: string): unknown[];
|
|
44
|
+
export declare function inspectRunSteerSessionEvidence(ctx: ExtensionContext, input: {
|
|
45
|
+
content: string;
|
|
46
|
+
eventId: string;
|
|
47
|
+
steerId: string;
|
|
48
|
+
}): SessionEvidence.ActiveSessionEntryEvidence;
|
|
49
|
+
export declare function inspectRunCompletionBatchSessionEvidence(ctx: ExtensionContext, batchId: string, content: string): SessionEvidence.ActiveSessionEntryEvidence;
|
|
19
50
|
export declare function registerToolDefinitions(pi: ExtensionAPI, definitions: Iterable<unknown>): void;
|