@timurproko/a1 0.2.6-dev.727 → 0.2.6-dev.736

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.
Files changed (116) hide show
  1. package/dist/app/session-shell/clipboard-services.d.ts +19 -0
  2. package/dist/app/session-shell/clipboard-services.js +7 -0
  3. package/dist/app/session-shell/exit-notice.d.ts +9 -5
  4. package/dist/app/session-shell/exit-notice.js +5 -5
  5. package/dist/app/session-shell/index.d.ts +4 -2
  6. package/dist/app/session-shell/index.js +2 -1
  7. package/dist/app/session-shell/paste-preparation-client.d.ts +3 -0
  8. package/dist/app/session-shell/paste-preparation-client.js +5 -2
  9. package/dist/app/session-shell/path-chip-presentation.d.ts +10 -3
  10. package/dist/app/session-shell/path-chip-presentation.js +48 -6
  11. package/dist/app/session-shell/prompt-chips.js +30 -4
  12. package/dist/app/session-shell/quit-outro.d.ts +3 -1
  13. package/dist/app/session-shell/quit-outro.js +23 -8
  14. package/dist/app/session-shell/response-copy-transport.d.ts +6 -1
  15. package/dist/app/session-shell/response-copy-transport.js +8 -2
  16. package/dist/app/session-shell/session-shell-root.d.ts +29 -11
  17. package/dist/app/session-shell/session-shell-root.js +62 -53
  18. package/dist/app/session-shell/session-shell.d.ts +55 -29
  19. package/dist/app/session-shell/session-shell.js +748 -1132
  20. package/dist/app/session-shell/shell-host.d.ts +105 -0
  21. package/dist/app/session-shell/shell-host.js +523 -0
  22. package/dist/cli/session-context.js +6 -3
  23. package/dist/composition/owned-ui.d.ts +20 -2
  24. package/dist/composition/owned-ui.js +107 -56
  25. package/dist/composition/session-info-reference.d.ts +2 -2
  26. package/dist/composition/session-info-reference.js +2 -2
  27. package/dist/contracts/agent-engine/capability-ports.d.ts +1 -85
  28. package/dist/contracts/agent-engine/capability-ports.js +1 -35
  29. package/dist/contracts/agent-engine/index.d.ts +1 -7
  30. package/dist/contracts/agent-engine/index.js +0 -4
  31. package/dist/contracts/owned-ui/index.d.ts +5 -1
  32. package/dist/contracts/owned-ui/index.js +1 -0
  33. package/dist/contracts/owned-ui/model.d.ts +6 -0
  34. package/dist/contracts/owned-ui/session-backend.d.ts +119 -0
  35. package/dist/contracts/owned-ui/session-presenters.d.ts +82 -0
  36. package/dist/contracts/owned-ui/session-presenters.js +1 -0
  37. package/dist/contracts/owned-ui/session-workflows.d.ts +342 -0
  38. package/dist/contracts/owned-ui/session-workflows.js +30 -0
  39. package/dist/features/launch/index.d.ts +1 -1
  40. package/dist/features/launch/index.js +1 -1
  41. package/dist/features/launch/session-context.d.ts +1 -0
  42. package/dist/features/launch/session-context.js +1 -0
  43. package/dist/features/owned-ui/settings-app.js +35 -15
  44. package/dist/foundation/lifecycle/index.d.ts +1 -1
  45. package/dist/foundation/lifecycle/index.js +1 -1
  46. package/dist/foundation/lifecycle/session-repository-context.d.ts +8 -2
  47. package/dist/foundation/lifecycle/session-repository-context.js +200 -65
  48. package/dist/foundation/release/bootstrap.js +1 -2
  49. package/dist/foundation/release/release-gc.js +1 -1
  50. package/dist/foundation/release/update.js +0 -4
  51. package/dist/foundation/storage/control-store.js +0 -12
  52. package/dist/integrations/pi/components/components.js +0 -16
  53. package/dist/integrations/pi/components/index.d.ts +3 -3
  54. package/dist/integrations/pi/components/index.js +2 -2
  55. package/dist/integrations/pi/components/models-dialog.js +1 -30
  56. package/dist/integrations/pi/components/shell-editor-autocomplete.js +11 -9
  57. package/dist/integrations/pi/components/shell-extension-ui.d.ts +3 -3
  58. package/dist/integrations/pi/components/shell-extension-ui.js +6 -2
  59. package/dist/integrations/pi/components/shell-presenters-transcript.js +4 -4
  60. package/dist/integrations/pi/components/shell-shared-facade.d.ts +21 -1
  61. package/dist/integrations/pi/components/shell-shared-facade.js +18 -2
  62. package/dist/integrations/pi/components/upstream/theme/theme.d.ts +5 -1
  63. package/dist/integrations/pi/components/upstream/theme/theme.js +20 -2
  64. package/dist/integrations/pi/engine/adapter.d.ts +44 -24
  65. package/dist/integrations/pi/engine/adapter.js +130 -22
  66. package/dist/integrations/pi/engine/command-dispatch.d.ts +2 -5
  67. package/dist/integrations/pi/engine/extension-ui-binding.d.ts +2 -11
  68. package/dist/integrations/pi/engine/host-ports.d.ts +20 -0
  69. package/dist/integrations/pi/engine/host-ports.js +13 -0
  70. package/dist/integrations/pi/engine/host.d.ts +70 -0
  71. package/dist/integrations/pi/engine/host.js +147 -0
  72. package/dist/integrations/pi/engine/index.d.ts +8 -4
  73. package/dist/integrations/pi/engine/index.js +3 -1
  74. package/dist/integrations/pi/engine/resource-catalog.d.ts +4 -23
  75. package/dist/integrations/pi/engine/runtime-integration.d.ts +8 -2
  76. package/dist/integrations/pi/engine/runtime-integration.js +12 -7
  77. package/dist/integrations/pi/engine/session-integration.d.ts +3 -8
  78. package/dist/integrations/pi/engine/session-integration.js +0 -49
  79. package/dist/integrations/pi/engine/session-runtime.d.ts +18 -3
  80. package/dist/integrations/pi/engine/session-runtime.js +18 -7
  81. package/dist/integrations/pi/engine/settings-bridge.d.ts +2 -2
  82. package/dist/integrations/pi/engine/settings-bridge.js +0 -2
  83. package/dist/integrations/pi/engine/settings-port.d.ts +2 -0
  84. package/dist/integrations/pi/engine/settings-port.js +3 -5
  85. package/dist/integrations/pi/engine/workflows.d.ts +33 -260
  86. package/dist/integrations/pi/engine/workflows.js +6 -28
  87. package/dist/integrations/pi/session-presenters/index.d.ts +2 -0
  88. package/dist/integrations/pi/session-presenters/index.js +1 -0
  89. package/dist/integrations/pi/session-presenters/presenters.d.ts +16 -0
  90. package/dist/integrations/pi/session-presenters/presenters.js +341 -0
  91. package/dist/integrations/pi/tui-runtime/adapter.js +0 -2
  92. package/dist/integrations/pi/tui-runtime/damage-aware-terminal.d.ts +18 -0
  93. package/dist/integrations/pi/tui-runtime/damage-aware-terminal.js +84 -3
  94. package/dist/integrations/pi/tui-runtime/index.d.ts +1 -1
  95. package/dist/integrations/pi/tui-runtime/index.js +1 -1
  96. package/dist/native/darwin-arm64/manifest.json +1 -1
  97. package/dist/native/linux-x64/manifest.json +1 -1
  98. package/dist/native/win32-x64/manifest.json +2 -2
  99. package/dist/native/win32-x64/process-guardian.exe +0 -0
  100. package/dist/ui/settings/declarations.d.ts +13 -1
  101. package/dist/ui/settings/declarations.js +12 -1
  102. package/dist/ui/settings/migrations.js +7 -0
  103. package/docs/architecture/boundaries.md +9 -1
  104. package/docs/architecture/project-structure.md +3 -2
  105. package/docs/architecture/ui-reference-provenance.md +1 -1
  106. package/package.json +1 -1
  107. package/dist/contracts/agent-engine/model.d.ts +0 -78
  108. package/dist/contracts/agent-engine/model.js +0 -1
  109. package/dist/contracts/agent-engine/ports.d.ts +0 -18
  110. package/dist/contracts/agent-engine/serialization.d.ts +0 -7
  111. package/dist/contracts/agent-engine/serialization.js +0 -58
  112. package/dist/contracts/agent-engine/validation.d.ts +0 -5
  113. package/dist/contracts/agent-engine/validation.js +0 -128
  114. package/dist/integrations/pi/components/upstream/theme/system-theme.d.ts +0 -61
  115. package/dist/integrations/pi/components/upstream/theme/system-theme.js +0 -709
  116. /package/dist/contracts/{agent-engine/ports.js → owned-ui/session-backend.js} +0 -0
@@ -30,7 +30,7 @@ The owned Pi-backed surface is not an arbitrary-CLI terminal multiplexer. A feat
30
30
  - `prompt-suggestions`: opt-in bounded diagnostic snapshots of neutral suggestion lifecycle metadata. Composition supplies an explicit local destination; this feature never imports Pi, generates suggestions, stores conversation text, or owns the editor. See [prompt suggestion diagnostics](prompt-suggestions.md).
31
31
  - `storage`: SQLite migrations, prior-boot reconciliation, and plural launch-instance persistence. Legacy foreground rows are historical migration input and never authorize current ownership.
32
32
  - `supervisor`: endpoint identity, plural cohort ownership, per-instance reconciliation, and aggregate release shutdown coordination. It owns no terminal surface.
33
- - `pi-engine-adapter`, `pi-component-adapter`, and `pi-tui-runtime-adapter`: isolate pinned Pi engine and presentation knowledge behind neutral contracts; product features do not import them directly.
33
+ - `pi-engine-adapter`, `pi-component-adapter`, and `pi-tui-runtime-adapter`: isolate pinned Pi engine and presentation knowledge behind neutral contracts; product features do not import them directly. Inside the engine adapter, one process-level engine host owns what is process-wide (the HTTP dispatcher, the theme singletons, the one-time changelog and package-update announcements, the startup trace) and is the only place sessions are created, so every session id is unique per process.
34
34
  - `session-shell` (`src/app/session-shell`): the application layer that composes the feature owners, the UI foundations, and the three Pi adapters into the interactive session; only composition imports it. Its render root assembles semantic document and dock rows, while its focused viewport controller owns follow state, pointer routing, selection, and interaction timers. Owned-app route lifecycle belongs to the neutral `ui-apps` owner and is only hosted by the session shell.
35
35
  - release/update/bootstrap: package-derived immutable release identity, process-guardian integrity, cohort selection, durable update transactions, rollback, and dependency-light command entry. After an unsuccessful bare-A1 child exit, the bootstrap restores owned terminal modes; neither guardian emits terminal controls.
36
36
  - `terminal-cleanup`: bounded, idempotent emergency restoration and fatal-exit diagnostics for an explicitly owned terminal. It does not inspect commands, relay terminal input/output, or emulate terminal state. The owned UI installs its fatal boundary before terminal activation; packaged bootstrap and checkout launch provide the surviving-owner fallback. Fatal records retain at most ten 16 KiB records with trusted classifications and code locations, never prompts, attachments, raw input, credentials, or arbitrary exception messages.
@@ -43,6 +43,14 @@ The JavaScript product path has no PTY or terminal-emulator dependency. Reintrod
43
43
 
44
44
  `scripts/governance/check-architecture.mjs` enforces the structural parts of these boundaries. Cross-cutting rationale belongs here; implementation history belongs in Git and archived OpenSpec changes.
45
45
 
46
+ ## Multi-session limits of the pinned engine
47
+
48
+ The engine host removes A1's own obstacles to several Pi sessions in one process, but three remain in the pinned Pi SDK and must be planned around, not discovered:
49
+
50
+ - The extension cache is keyed by one working directory and cleared on reload (`core/extensions/loader.js`), so sessions in different directories reload each other's extensions.
51
+ - `SettingsManager` writes under a lockfile but never re-reads the file, so a second in-memory copy goes stale after another session writes a setting (`core/settings-manager.js`). The host keeps the one process-wide effect, the HTTP dispatcher, consistent itself.
52
+ - `AgentSessionRuntime.dispose()` releases the session but not the model runtime or the resource loader it was created with (`core/agent-session-runtime.js`), so a session's services outlive it until the process ends.
53
+
46
54
  ## Planned multi-agent boundaries
47
55
 
48
56
  The multi-agent workspace feature, its dependency-free contracts, the structured-agent runtime, and the Node side of the terminal-host protocol were removed from `develop` while the multi-agent plan is on hold; their last state is preserved on the `archive/multi-agent-workspace` branch. A future implementation starts from the current codebase rather than from that copy. The boundary rules below remain the design intent for that work.
@@ -18,13 +18,14 @@ src/
18
18
  prompt-history/ profile-isolated prompt retention and bounded SQLite worker lifecycle
19
19
  prompt-suggestions/ opt-in bounded metadata capture and local diagnostic snapshots
20
20
  contracts/
21
- agent-engine/ dependency-free agent engine, session, package, and capability ports
21
+ agent-engine/ dependency-free agent settings and package contracts
22
22
  owned-ui/ dependency-free owned-session and extension UI contracts
23
23
  presentation/ dependency-free component, terminal, and runtime ports
24
24
  integrations/
25
25
  pi/
26
26
  components/ pinned Pi component and theme adaptation
27
27
  engine/ pinned Pi engine, settings, resource, package, and workflow integration
28
+ session-presenters/ pinned Pi selectors and transcript renderers built from engine objects
28
29
  tui-runtime/ neutral presentation runtime over pinned Pi TUI
29
30
  foundation/
30
31
  launch-guardian/ authenticated launch-instance coordination
@@ -42,7 +43,7 @@ src/
42
43
 
43
44
  Each directory owner exposes `index.ts`, which lists its named exports; `export *` is rejected there so a public contract is readable in one place. Imports within one owner may use private files. Imports crossing owners must use the provider's public entry and follow the dependency DAG declared by `PROJECT_OWNERS`. Two exceptions exist: `src/composition` is the dependency-injection root and may reach past any public entry, and a module on the eager startup path may import a leaf of a provider whose public entry is a prohibited startup entry (`PROHIBITED_STARTUP_ENTRIES` in `startup-graph-policy.mjs`), because loading that barrel would pull the provider's whole graph into startup. `product-identity` is the sole exception to the directory-entry convention because its public entry is `src/product-identity.ts`.
44
45
 
45
- Three layer boundaries hold regardless of the DAG: `src/contracts/*` import nothing outside their own contract; `src/ui/components` imports only contracts; only `src/integrations/pi/*` and the shipped `bin/` entries import the pinned Pi packages. The session shell under `src/app` is the application layer: it may import the contracts, the UI foundations, the three Pi adapters, and the feature owners, and only composition imports it.
46
+ Three layer boundaries hold regardless of the DAG: `src/contracts/*` import nothing outside their own contract; `src/ui/components` imports only contracts; only `src/integrations/pi/*` and the shipped `bin/` entries import the pinned Pi packages. The session shell under `src/app` is the application layer: it may import the contracts, the UI foundations, the three Pi adapters, and the feature owners, and only composition imports it. The shell never holds a Pi engine object: selectors and transcript renderers built from one live in `src/integrations/pi/session-presenters`, the only owner besides composition that may import both the engine and the component adapters, and the shell opens them through the `OwnedUiSessionPresenters` contract.
46
47
 
47
48
  `src/cli` contains command policy but delegates runtime work. `src/composition` is the concrete dependency-injection boundary: it may know both neutral contracts and Pi implementations, while product features receive vendor-neutral ports. Foundation modules never import product features. Pi package knowledge remains inside the Pi adapter owners.
48
49
 
@@ -42,7 +42,7 @@ its own `core` facade layer; A1 is a product, so the port adapts imports and kee
42
42
  | `pi-engine/session-integration.ts` and `pi-components/shell-footer-status.ts` — steering queue | pinned Pi interactive mode `onSubmit` and `updatePendingMessagesDisplay` | Steering/follow-up uses `prompt(..., { streamingBehavior })`, allowing Pi to emit the accepted user row, while remaining steering rows preserve Pi's opening spacer, dim `Steering:` labels, dequeue hint, and order before `Working`. |
43
43
  | `ui-components/list-view.ts`, `dialog-panel.ts`, `value-menu.ts`, and `features/owned-ui/settings-app.ts` — setting presentation | pinned Pi `SettingsSelectorComponent`, Pi TUI `SettingsList`, `SelectList`, and `Input` at `0.84.2` | Cursor and selected label accents, unselected muted values, the 30-column label cap, dialog styling, notices, and narrow-width geometry retain pinned semantics. Scalar-menu placement and input remain shared, while the muted, hover-brightened selected value, A1/Agent grouping, pointer steppers, explicit `/` search, ruled shared input, shortcut-derived status hints, suppressed selected descriptions, `scrollbarSpeed`-driven wheel movement, a list rail that follows `scrollbarAppearance` and `scrollbarStyle` with transcript-style hover and drag, `Ctrl+Home`/`Ctrl+End` boundary jumps, and the dark floating menu with lighter active row and effective-value check mark are declared product-owned differences. Independent row evidence: `test/features/owned-ui/pinned-settings-presentation-parity.test.ts`; owned interaction evidence: `test/features/owned-ui/settings-app.test.ts`, `test/ui/components/value-menu.test.ts`, and `test/composition/settings-route-host.test.ts`. |
44
44
  | `features/owned-ui/project-trust-prompt.ts` — pre-resource selector | pinned Pi `cli/startup-ui.ts`, `cli/project-trust.ts`, and `core/project-trust.ts` at commit `914cf1472e715297caa30db4b9535d534a9eb718` | Uses a fixed, dependency-bounded A1 startup selector rather than importing private CLI modules. It preserves selected-option accent, navigation/accept/reject/cancel semantics, fail-closed behavior, raw-mode restoration, clearing, cursor restoration, and parent-screen restoration before diagnostics. |
45
- | `session-shell/session-shell-root.ts` and `session-shell.ts` — fullscreen exit | pinned Pi `InteractiveMode.formatResumeCommand()` and shutdown output at commit `914cf1472e715297caa30db4b9535d534a9eb718` | Re-renders authoritative transcript components with semantic SGR intact, excludes inline-image control payloads and fullscreen-only chrome, restores the terminal first, then emits pinned dim `To resume this session:` wording with `a1`, compact session id, and conditional quoted `--session-dir`. |
45
+ | `session-shell/session-shell-root.ts`, `session-shell.ts`, and `shell-host.ts` — fullscreen exit | pinned Pi `InteractiveMode.formatResumeCommand()` and shutdown output at commit `914cf1472e715297caa30db4b9535d534a9eb718` | Re-renders authoritative transcript components with semantic SGR intact, excludes inline-image control payloads and fullscreen-only chrome, restores the terminal first, then emits pinned dim `To resume this session:` wording with `a1`, compact session id, and conditional quoted `--session-dir`. |
46
46
  | `pi-tui-runtime/input-presentation-coordinator.ts` and custom-viewport dock reuse | pinned Pi TUI `TuiBase` input dispatch and immediate-render pending guard at `0.84.2` | Preserves each original terminal delivery and invokes the existing Pi handlers exactly once in order. Bare A1 alone drains finite-grammar text/edit/navigation bursts in one immediate event-loop opportunity so Pi's existing pending guard paints the newest state once; effectful, unknown, protocol, paste, and extension-owned input remains an immediate barrier. Geometry-stable dock frames reuse A1's established transcript viewport, while uncertain geometry and replacement-surface damage still fail closed. Independent evidence is under `test/support/input-responsiveness/`. |
47
47
  | `test/features/owned-ui/pi-raw-terminal-parity.ts` — parity normalization | pinned Pi public components/runtime at `0.84.2` | Only synchronized-output envelopes, absolute hyperlink targets, declared product/path substitutions, and nondeterministic timing may normalize. SGR roles/reset boundaries, rows, cursor operations, clearing, restoration, and write order remain authoritative; A1-generated JSON captures are diagnostics and cannot serve as pinned evidence. |
48
48
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@timurproko/a1",
3
- "version": "0.2.6-dev.727",
3
+ "version": "0.2.6-dev.736",
4
4
  "description": "Standalone terminal workspace for supervised native and managed agents",
5
5
  "type": "module",
6
6
  "privateLaunchContract": "neutral-launch-v1",
@@ -1,78 +0,0 @@
1
- import type { AgentMessage } from "./domain.js";
2
- export declare const AGENT_ENGINE_CONTRACT_VERSION: 1;
3
- export type AgentSessionId = string;
4
- export type AgentCommandId = string;
5
- export type AgentEventSequence = number;
6
- export type AgentSessionLifecycle = "starting" | "ready" | "busy" | "stopping" | "stopped" | "failed";
7
- export type AgentCommandCapability = "prompt" | "steer" | "follow-up" | "abort" | "retry" | "compact" | "bash" | "replace-session";
8
- export type AgentEventCapability = "lifecycle" | "content" | "command-outcome" | "snapshot-invalidated" | "diagnostic";
9
- export interface AgentCapabilityContract {
10
- readonly contractVersion: typeof AGENT_ENGINE_CONTRACT_VERSION;
11
- readonly commands: readonly AgentCommandCapability[];
12
- readonly events: readonly AgentEventCapability[];
13
- readonly snapshots: {
14
- readonly supported: boolean;
15
- readonly maxBytes: number;
16
- };
17
- }
18
- interface AgentCommandEnvelope {
19
- readonly contractVersion: typeof AGENT_ENGINE_CONTRACT_VERSION;
20
- readonly commandId: AgentCommandId;
21
- readonly sessionId: AgentSessionId;
22
- }
23
- export type AgentCommand = (AgentCommandEnvelope & {
24
- readonly type: "prompt" | "steer" | "follow-up";
25
- readonly text: string;
26
- }) | (AgentCommandEnvelope & {
27
- readonly type: "abort" | "retry" | "compact";
28
- }) | (AgentCommandEnvelope & {
29
- readonly type: "bash";
30
- readonly command: string;
31
- }) | (AgentCommandEnvelope & {
32
- readonly type: "replace-session";
33
- readonly source: {
34
- readonly kind: "new";
35
- } | {
36
- readonly kind: "resume";
37
- readonly sessionPath: string;
38
- };
39
- });
40
- export type AgentCommandOutcome = "accepted" | "completed" | "rejected" | "failed" | "cancelled";
41
- interface AgentEventEnvelope {
42
- readonly contractVersion: typeof AGENT_ENGINE_CONTRACT_VERSION;
43
- readonly sessionId: AgentSessionId;
44
- readonly sequence: AgentEventSequence;
45
- }
46
- export type AgentEvent = (AgentEventEnvelope & {
47
- readonly type: "lifecycle";
48
- readonly lifecycle: AgentSessionLifecycle;
49
- readonly reason: string | null;
50
- }) | (AgentEventEnvelope & {
51
- readonly type: "content";
52
- readonly content: AgentMessage;
53
- }) | (AgentEventEnvelope & {
54
- readonly type: "command-outcome";
55
- readonly commandId: AgentCommandId;
56
- readonly outcome: AgentCommandOutcome;
57
- readonly diagnostic: string | null;
58
- }) | (AgentEventEnvelope & {
59
- readonly type: "snapshot-invalidated";
60
- readonly expectedRevision: number;
61
- }) | (AgentEventEnvelope & {
62
- readonly type: "diagnostic";
63
- readonly code: string;
64
- readonly message: string;
65
- readonly recoverable: boolean;
66
- });
67
- export interface AgentSnapshot {
68
- readonly contractVersion: typeof AGENT_ENGINE_CONTRACT_VERSION;
69
- readonly snapshotId: string;
70
- readonly sessionId: AgentSessionId;
71
- readonly revision: number;
72
- readonly sequence: AgentEventSequence;
73
- readonly lifecycle: AgentSessionLifecycle;
74
- readonly content: readonly AgentMessage[];
75
- readonly activeCommandIds: readonly AgentCommandId[];
76
- readonly capabilities: AgentCapabilityContract;
77
- }
78
- export {};
@@ -1 +0,0 @@
1
- export const AGENT_ENGINE_CONTRACT_VERSION = 1;
@@ -1,18 +0,0 @@
1
- import type { AgentCapabilityContract, AgentCommand, AgentCommandOutcome, AgentEvent, AgentSessionId, AgentSessionLifecycle, AgentSnapshot } from "./model.js";
2
- export interface AgentSessionPort {
3
- readonly sessionId: AgentSessionId;
4
- readonly lifecycle: AgentSessionLifecycle;
5
- readonly capabilities: AgentCapabilityContract;
6
- execute(command: AgentCommand): Promise<AgentCommandOutcome>;
7
- subscribe(listener: (event: AgentEvent) => void): () => void;
8
- snapshot(): Promise<AgentSnapshot>;
9
- dispose(): Promise<void>;
10
- }
11
- export interface AgentEnginePort {
12
- readonly capabilities: AgentCapabilityContract;
13
- createSession(input: {
14
- readonly sessionId: AgentSessionId;
15
- readonly cwd: string;
16
- }): Promise<AgentSessionPort>;
17
- dispose(): Promise<void>;
18
- }
@@ -1,7 +0,0 @@
1
- import type { AgentCapabilityContract, AgentCommand, AgentEvent, AgentSnapshot } from "./model.js";
2
- export declare function encodeAgentCommand(command: AgentCommand, capabilities?: AgentCapabilityContract): string;
3
- export declare function decodeAgentCommand(source: string, capabilities?: AgentCapabilityContract): AgentCommand;
4
- export declare function encodeAgentEvent(event: AgentEvent, capabilities?: AgentCapabilityContract): string;
5
- export declare function decodeAgentEvent(source: string, capabilities?: AgentCapabilityContract): AgentEvent;
6
- export declare function encodeAgentSnapshot(snapshot: AgentSnapshot): string;
7
- export declare function decodeAgentSnapshot(source: string): AgentSnapshot;
@@ -1,58 +0,0 @@
1
- import { assertAgentCommand, assertAgentEvent, assertAgentSnapshot } from "./validation.js";
2
- const MAX_ENVELOPE_BYTES = 1024 * 1024;
3
- export function encodeAgentCommand(command, capabilities) {
4
- assertAgentCommand(command, capabilities);
5
- return encode(command);
6
- }
7
- export function decodeAgentCommand(source, capabilities) {
8
- const value = decode(source);
9
- assertAgentCommand(value, capabilities);
10
- return value;
11
- }
12
- export function encodeAgentEvent(event, capabilities) {
13
- assertAgentEvent(event, capabilities);
14
- return encode(event);
15
- }
16
- export function decodeAgentEvent(source, capabilities) {
17
- const value = decode(source);
18
- assertAgentEvent(value, capabilities);
19
- return value;
20
- }
21
- export function encodeAgentSnapshot(snapshot) {
22
- assertAgentSnapshot(snapshot);
23
- const encoded = encode(snapshot);
24
- if (Buffer.byteLength(encoded, "utf8") > snapshot.capabilities.snapshots.maxBytes)
25
- throw new RangeError("agent snapshot exceeds negotiated byte limit");
26
- return encoded;
27
- }
28
- export function decodeAgentSnapshot(source) {
29
- const value = decode(source);
30
- assertAgentSnapshot(value);
31
- if (Buffer.byteLength(source, "utf8") > value.capabilities.snapshots.maxBytes)
32
- throw new RangeError("agent snapshot exceeds negotiated byte limit");
33
- return value;
34
- }
35
- function encode(value) {
36
- let encoded;
37
- try {
38
- encoded = JSON.stringify(value);
39
- }
40
- catch (error) {
41
- throw new TypeError("agent contract value must be JSON serializable", { cause: error });
42
- }
43
- if (encoded === undefined)
44
- throw new TypeError("agent contract value must be JSON serializable");
45
- if (Buffer.byteLength(encoded, "utf8") > MAX_ENVELOPE_BYTES)
46
- throw new RangeError("agent contract envelope exceeds its byte limit");
47
- return encoded;
48
- }
49
- function decode(source) {
50
- if (typeof source !== "string" || Buffer.byteLength(source, "utf8") > MAX_ENVELOPE_BYTES)
51
- throw new RangeError("agent contract envelope exceeds its byte limit");
52
- try {
53
- return JSON.parse(source);
54
- }
55
- catch (error) {
56
- throw new TypeError("agent contract envelope is invalid JSON", { cause: error });
57
- }
58
- }
@@ -1,5 +0,0 @@
1
- import { type AgentCapabilityContract, type AgentCommand, type AgentEvent, type AgentSnapshot } from "./model.js";
2
- export declare function assertAgentCapabilityContract(value: AgentCapabilityContract): void;
3
- export declare function assertAgentCommand(command: AgentCommand, capabilities?: AgentCapabilityContract): void;
4
- export declare function assertAgentEvent(event: AgentEvent, capabilities?: AgentCapabilityContract): void;
5
- export declare function assertAgentSnapshot(snapshot: AgentSnapshot): void;
@@ -1,128 +0,0 @@
1
- import { AGENT_ENGINE_CONTRACT_VERSION, } from "./model.js";
2
- import { assertAgentMessage } from "./domain-validation.js";
3
- const COMMANDS = new Set(["prompt", "steer", "follow-up", "abort", "retry", "compact", "bash", "replace-session"]);
4
- const EVENTS = new Set(["lifecycle", "content", "command-outcome", "snapshot-invalidated", "diagnostic"]);
5
- const LIFECYCLES = new Set(["starting", "ready", "busy", "stopping", "stopped", "failed"]);
6
- const OUTCOMES = new Set(["accepted", "completed", "rejected", "failed", "cancelled"]);
7
- const MAX_TEXT_BYTES = 256 * 1024;
8
- const MAX_COLLECTION = 10_000;
9
- export function assertAgentCapabilityContract(value) {
10
- assertVersion(value.contractVersion);
11
- assertUniqueEnum(value.commands, COMMANDS, "agent command capabilities");
12
- assertUniqueEnum(value.events, EVENTS, "agent event capabilities");
13
- if (typeof value.snapshots?.supported !== "boolean" || !Number.isSafeInteger(value.snapshots.maxBytes) || value.snapshots.maxBytes < 1024) {
14
- throw new TypeError("agent snapshot capability is invalid");
15
- }
16
- }
17
- export function assertAgentCommand(command, capabilities) {
18
- assertVersion(command.contractVersion);
19
- assertId(command.commandId, "agent command id");
20
- assertId(command.sessionId, "agent command session id");
21
- if (!COMMANDS.has(command.type))
22
- throw new TypeError("agent command type is unknown");
23
- if (capabilities !== undefined) {
24
- assertAgentCapabilityContract(capabilities);
25
- if (!capabilities.commands.includes(command.type))
26
- throw new TypeError(`agent command capability is unavailable: ${command.type}`);
27
- }
28
- if (command.type === "prompt" || command.type === "steer" || command.type === "follow-up")
29
- assertText(command.text, "agent command text");
30
- if (command.type === "bash")
31
- assertText(command.command, "agent bash command");
32
- if (command.type === "replace-session" && command.source.kind === "resume")
33
- assertText(command.source.sessionPath, "agent resume path");
34
- }
35
- export function assertAgentEvent(event, capabilities) {
36
- assertVersion(event.contractVersion);
37
- assertId(event.sessionId, "agent event session id");
38
- assertNonNegative(event.sequence, "agent event sequence");
39
- if (!EVENTS.has(event.type))
40
- throw new TypeError("agent event type is unknown");
41
- if (capabilities !== undefined) {
42
- assertAgentCapabilityContract(capabilities);
43
- if (!capabilities.events.includes(event.type))
44
- throw new TypeError(`agent event capability is unavailable: ${event.type}`);
45
- }
46
- switch (event.type) {
47
- case "lifecycle":
48
- if (!LIFECYCLES.has(event.lifecycle))
49
- throw new TypeError("agent lifecycle is invalid");
50
- if (event.reason !== null)
51
- assertText(event.reason, "agent lifecycle reason");
52
- return;
53
- case "content":
54
- assertAgentMessage(event.content);
55
- return;
56
- case "command-outcome":
57
- assertId(event.commandId, "agent outcome command id");
58
- if (!OUTCOMES.has(event.outcome))
59
- throw new TypeError("agent command outcome is invalid");
60
- if (event.diagnostic !== null)
61
- assertText(event.diagnostic, "agent outcome diagnostic");
62
- return;
63
- case "snapshot-invalidated":
64
- assertNonNegative(event.expectedRevision, "agent expected snapshot revision");
65
- return;
66
- case "diagnostic":
67
- assertId(event.code, "agent diagnostic code");
68
- assertText(event.message, "agent diagnostic message");
69
- if (typeof event.recoverable !== "boolean")
70
- throw new TypeError("agent diagnostic recovery flag is invalid");
71
- }
72
- }
73
- export function assertAgentSnapshot(snapshot) {
74
- assertVersion(snapshot.contractVersion);
75
- assertId(snapshot.snapshotId, "agent snapshot id");
76
- assertId(snapshot.sessionId, "agent snapshot session id");
77
- assertNonNegative(snapshot.revision, "agent snapshot revision");
78
- assertNonNegative(snapshot.sequence, "agent snapshot sequence");
79
- if (!LIFECYCLES.has(snapshot.lifecycle))
80
- throw new TypeError("agent snapshot lifecycle is invalid");
81
- assertAgentCapabilityContract(snapshot.capabilities);
82
- if (!Array.isArray(snapshot.content) || snapshot.content.length > MAX_COLLECTION)
83
- throw new RangeError("agent snapshot content collection is invalid");
84
- for (const content of snapshot.content)
85
- assertAgentEvent({ contractVersion: AGENT_ENGINE_CONTRACT_VERSION, sessionId: snapshot.sessionId, sequence: snapshot.sequence, type: "content", content });
86
- if (!Array.isArray(snapshot.activeCommandIds) || snapshot.activeCommandIds.length > MAX_COLLECTION)
87
- throw new RangeError("agent active command collection is invalid");
88
- const ids = new Set();
89
- for (const id of snapshot.activeCommandIds) {
90
- assertId(id, "agent active command id");
91
- if (ids.has(id))
92
- throw new TypeError(`duplicate agent active command id: ${id}`);
93
- ids.add(id);
94
- }
95
- }
96
- function assertVersion(version) {
97
- if (version !== AGENT_ENGINE_CONTRACT_VERSION)
98
- throw new TypeError("unsupported agent engine contract version");
99
- }
100
- function assertUniqueEnum(values, allowed, label) {
101
- if (!Array.isArray(values))
102
- throw new TypeError(`${label} must be an array`);
103
- const unique = new Set();
104
- for (const value of values) {
105
- if (!allowed.has(value))
106
- throw new TypeError(`${label} contains an unknown value: ${String(value)}`);
107
- if (unique.has(value))
108
- throw new TypeError(`${label} contains a duplicate value: ${String(value)}`);
109
- unique.add(value);
110
- }
111
- }
112
- function assertId(value, label) {
113
- if (typeof value !== "string" || !/^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$/.test(value))
114
- throw new TypeError(`${label} is invalid`);
115
- }
116
- function assertText(value, label) {
117
- if (typeof value !== "string" || value.length === 0)
118
- throw new TypeError(`${label} is invalid`);
119
- assertPossiblyEmptyText(value, label);
120
- }
121
- function assertPossiblyEmptyText(value, label) {
122
- if (typeof value !== "string" || Buffer.byteLength(value, "utf8") > MAX_TEXT_BYTES)
123
- throw new RangeError(`${label} exceeds its byte limit`);
124
- }
125
- function assertNonNegative(value, label) {
126
- if (!Number.isSafeInteger(value) || value < 0)
127
- throw new TypeError(`${label} is invalid`);
128
- }
@@ -1,61 +0,0 @@
1
- /**
2
- * Provenance: @earendil-works/pi-coding-agent 1.1.0 (MIT), commit abe508e1b89912adde45528136c3221eb69acdd7,
3
- * packages/coding-agent/src/modes/interactive/theme/system-theme.ts.
4
- * Modifications: Copied the system palette generator with ESM import remapping and strict
5
- * indexed-access assertions; A1 retains explicit owned theme selection.
6
- * Deviations: none.
7
- */
8
- /**
9
- * The `system` theme: pi's colors derived from the terminal's own theme.
10
- *
11
- * Every token belongs to a color family (its hue) and has contrast rules: it must reach a contrast level
12
- * on the background and on the panels it is drawn on. Hue and saturation come from the terminal's palette
13
- * color for the family's ANSI slot, or from the family's own hue when the terminal reports no palette.
14
- * Lightness comes from the rules alone. Colors are built in OKHSL, whose saturation is relative to the
15
- * sRGB gamut, and fade toward gray near black and white. A palette color never gains OKLCH chroma when it
16
- * moves to another lightness, so pastel palettes stay pastel.
17
- *
18
- * A contrast level is a target-lightness curve: the OKLab lightness a token needs, given the lightness of
19
- * the surface below it. The curves were fitted to the reference theme design from the "Pi themes: system
20
- * and light/dark" review. On dark backgrounds they aim for nearly fixed lightness; on light backgrounds the
21
- * required difference grows as the background darkens.
22
- *
23
- * Depending on what the terminal reports, the theme is generated in one of three tiers:
24
- * - background and palette: hues from the palette, lightness from the background;
25
- * - background only: the families' own hues, lightness from the background;
26
- * - nothing: ANSI palette indices and the default colors, which the terminal renders itself.
27
- */
28
- import { type RgbColor } from "@earendil-works/pi-tui";
29
- import type { ThemeAppearance, ThemeColor, ThemeToken } from "./theme.js";
30
- export declare const SYSTEM_THEME_NAME = "system";
31
- export interface SystemThemeInput {
32
- foreground?: RgbColor;
33
- background?: RgbColor;
34
- /** ANSI colors 0-15. */
35
- palette?: RgbColor[];
36
- /** Saturation multiplier from 0 (grayscale) to 1. The first frame renders in grayscale until colors arrive. */
37
- saturation?: number;
38
- /** Appearance when the terminal did not report its background, e.g. from its light/dark report or COLORFGBG. */
39
- appearanceHint?: ThemeAppearance;
40
- }
41
- export interface SystemThemeColors {
42
- /** Hex colors, ANSI palette indices, or "" for the terminal default. */
43
- colors: Record<ThemeToken, string | number>;
44
- /** Foreground tokens rendered faint (SGR 2), for terminals that did not report colors. */
45
- dim: ThemeColor[];
46
- appearance: ThemeAppearance | undefined;
47
- }
48
- /** WCAG 2 relative luminance. */
49
- export declare function relativeLuminance({ r, g, b }: RgbColor): number;
50
- /** WCAG 2 contrast ratio, 1-21. */
51
- export declare function wcagContrast(first: RgbColor, second: RgbColor): number;
52
- /**
53
- * Whether a terminal is dark or light, from its reported colors: the direction of its own foreground
54
- * when text can be readable that way, otherwise dark when white text has more contrast on the
55
- * background than black text.
56
- */
57
- export declare function terminalAppearance(background: RgbColor, foreground?: RgbColor): ThemeAppearance;
58
- /**
59
- * Generate the system theme's colors from the terminal's reported colors.
60
- */
61
- export declare function generateSystemThemeColors(input: SystemThemeInput): SystemThemeColors;