pi-orchestrator-config 4.1.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +808 -0
- package/agents/api-documenter.md +32 -0
- package/agents/bash-expert.md +53 -0
- package/agents/code-reviewer-docs.md +145 -0
- package/agents/code-reviewer-guidelines.md +97 -0
- package/agents/code-reviewer-quality.md +142 -0
- package/agents/code-reviewer-security.md +107 -0
- package/agents/code-reviewer-spec.md +164 -0
- package/agents/debugger.md +63 -0
- package/agents/docker-expert.md +40 -0
- package/agents/docs-fetcher.md +48 -0
- package/agents/git-expert.md +63 -0
- package/agents/github-expert.md +83 -0
- package/agents/go-expert.md +62 -0
- package/agents/issue-reviewer-feasibility.md +60 -0
- package/agents/issue-reviewer-scope.md +63 -0
- package/agents/issue-reviewer-spec.md +77 -0
- package/agents/java-expert.md +31 -0
- package/agents/jenkins-expert.md +38 -0
- package/agents/kubernetes-expert.md +40 -0
- package/agents/planner.md +42 -0
- package/agents/python-expert.md +61 -0
- package/agents/reviewer.md +26 -0
- package/agents/scout.md +40 -0
- package/agents/security-auditor.md +254 -0
- package/agents/technical-documentation-writer.md +37 -0
- package/agents/test-automator.md +55 -0
- package/agents/test-runner.md +47 -0
- package/agents/ts-expert.md +23 -0
- package/agents/worker.md +30 -0
- package/extensions/acpx-provider/index.ts +104 -0
- package/extensions/acpx-provider/load-runtime.ts +99 -0
- package/extensions/acpx-provider/runtime-models.ts +40 -0
- package/extensions/cli-provider/agents/claude.ts +128 -0
- package/extensions/cli-provider/agents/cursor.ts +84 -0
- package/extensions/cli-provider/agents/gemini.ts +100 -0
- package/extensions/cli-provider/discover.ts +77 -0
- package/extensions/cli-provider/index.ts +57 -0
- package/extensions/cli-provider/parsers.ts +304 -0
- package/extensions/cli-provider/providers.ts +58 -0
- package/extensions/cli-provider/runner.ts +225 -0
- package/extensions/cli-provider/runtime-models.ts +32 -0
- package/extensions/cli-provider/session-reaper.ts +122 -0
- package/extensions/cli-provider/sessions.ts +533 -0
- package/extensions/cli-provider/shared/discover-cache.ts +235 -0
- package/extensions/cli-provider/types.ts +48 -0
- package/extensions/coms/coms-net-server.ts +1642 -0
- package/extensions/coms/coms-net-wrapper.ts +521 -0
- package/extensions/coms/coms-net.ts +1589 -0
- package/extensions/coms/coms-p2p.ts +1879 -0
- package/extensions/coms/coms-shared.ts +510 -0
- package/extensions/coms/coms-wrapper.ts +138 -0
- package/extensions/coms/index.ts +20 -0
- package/extensions/coms/themeMap.ts +147 -0
- package/extensions/image-gen/image-gen.ts +332 -0
- package/extensions/image-gen/index.ts +14 -0
- package/extensions/orchestrator/agents.ts +134 -0
- package/extensions/orchestrator/ask-user.ts +293 -0
- package/extensions/orchestrator/async-agents.ts +1037 -0
- package/extensions/orchestrator/async-capability.ts +129 -0
- package/extensions/orchestrator/async-runner.ts +324 -0
- package/extensions/orchestrator/async-status-parse.ts +31 -0
- package/extensions/orchestrator/async-status-ui.ts +201 -0
- package/extensions/orchestrator/async-wait.ts +36 -0
- package/extensions/orchestrator/btw.ts +210 -0
- package/extensions/orchestrator/cron-status-format.ts +126 -0
- package/extensions/orchestrator/cron-status-ui.ts +132 -0
- package/extensions/orchestrator/cron.ts +730 -0
- package/extensions/orchestrator/dreaming.ts +355 -0
- package/extensions/orchestrator/enforcement-helpers.ts +530 -0
- package/extensions/orchestrator/enforcement-rules.ts +329 -0
- package/extensions/orchestrator/enforcement.ts +828 -0
- package/extensions/orchestrator/extended-autocomplete.ts +593 -0
- package/extensions/orchestrator/git-helpers.ts +420 -0
- package/extensions/orchestrator/github-autocomplete.ts +250 -0
- package/extensions/orchestrator/icons.ts +17 -0
- package/extensions/orchestrator/index.ts +100 -0
- package/extensions/orchestrator/memory-embeddings.ts +281 -0
- package/extensions/orchestrator/memory-promotion.ts +449 -0
- package/extensions/orchestrator/memory-provenance.ts +80 -0
- package/extensions/orchestrator/memory-query-class.ts +90 -0
- package/extensions/orchestrator/memory-scoring.ts +434 -0
- package/extensions/orchestrator/memory-tools.ts +883 -0
- package/extensions/orchestrator/memory-tree.ts +212 -0
- package/extensions/orchestrator/nvim.ts +169 -0
- package/extensions/orchestrator/overlay-dashboard-utils.ts +25 -0
- package/extensions/orchestrator/overlay-dashboard.ts +512 -0
- package/extensions/orchestrator/pi-config-review-state.ts +303 -0
- package/extensions/orchestrator/preference-extractor.ts +106 -0
- package/extensions/orchestrator/project-settings.ts +468 -0
- package/extensions/orchestrator/promotion-queue.ts +311 -0
- package/extensions/orchestrator/resolve-agent-model.ts +32 -0
- package/extensions/orchestrator/review-ui.ts +204 -0
- package/extensions/orchestrator/rule-placeholders.ts +12 -0
- package/extensions/orchestrator/rules.ts +481 -0
- package/extensions/orchestrator/session-search.ts +243 -0
- package/extensions/orchestrator/session-validation.ts +374 -0
- package/extensions/orchestrator/situation-report.ts +370 -0
- package/extensions/orchestrator/status-bar.ts +31 -0
- package/extensions/orchestrator/status-line.ts +192 -0
- package/extensions/orchestrator/status.ts +110 -0
- package/extensions/orchestrator/subagent-tool.ts +1748 -0
- package/extensions/orchestrator/task-lifecycle.ts +88 -0
- package/extensions/orchestrator/utils.ts +227 -0
- package/extensions/pidash/index.ts +15 -0
- package/extensions/pidash/pidash.ts +941 -0
- package/extensions/pidiff/index.ts +13 -0
- package/extensions/pidiff/pidiff.ts +369 -0
- package/extensions/providers/acpx-driver.ts +479 -0
- package/extensions/providers/built-in-drivers.ts +52 -0
- package/extensions/providers/claude-driver.ts +319 -0
- package/extensions/providers/cursor-acpx-driver.ts +398 -0
- package/extensions/providers/cursor-cli-driver.ts +484 -0
- package/extensions/providers/gemini-driver.ts +302 -0
- package/extensions/providers/index.ts +513 -0
- package/extensions/shared/build-system-prompt.ts +57 -0
- package/extensions/shared/create-runtime-provider.ts +190 -0
- package/extensions/shared/daemon-manager.ts +248 -0
- package/extensions/shared/file-logger.ts +115 -0
- package/extensions/shared/managed-refresh.ts +211 -0
- package/extensions/shared/provider-driver.ts +295 -0
- package/extensions/shared/provider-errors.ts +305 -0
- package/extensions/shared/provider-registry.ts +388 -0
- package/extensions/shared/stream-builder.ts +275 -0
- package/extensions/shared/types.ts +20 -0
- package/extensions/shared/ui/README.md +10 -0
- package/extensions/shared/ui/badge.tsx +52 -0
- package/extensions/shared/ui/button.tsx +58 -0
- package/extensions/shared/ui/collapsible.tsx +21 -0
- package/extensions/shared/ui/dropdown-menu.tsx +266 -0
- package/extensions/shared/ui/input.tsx +20 -0
- package/extensions/shared/ui/popover.tsx +114 -0
- package/extensions/shared/ui/resizable.tsx +48 -0
- package/extensions/shared/ui/scroll-area.tsx +53 -0
- package/extensions/shared/ui/select.tsx +201 -0
- package/extensions/shared/ui/separator.tsx +25 -0
- package/extensions/shared/ui/tooltip.tsx +64 -0
- package/extensions/shared/ws-client.ts +74 -0
- package/package.json +59 -0
- package/prompts/coderabbit-rate-limit.md +95 -0
- package/prompts/create-coms-feature-manager.md +186 -0
- package/prompts/create-skill.md +128 -0
- package/prompts/domain-model.md +109 -0
- package/prompts/external-ai.md +665 -0
- package/prompts/implement-and-review.md +25 -0
- package/prompts/implement.md +26 -0
- package/prompts/issue-review.md +256 -0
- package/prompts/pr-review.md +753 -0
- package/prompts/query-db.md +154 -0
- package/prompts/refine-review.md +208 -0
- package/prompts/release.md +235 -0
- package/prompts/remember.md +33 -0
- package/prompts/review-handler-status.md +27 -0
- package/prompts/review-handler.md +677 -0
- package/prompts/review-local.md +159 -0
- package/prompts/scout-and-plan.md +21 -0
- package/rules/00-orchestrator-core.md +42 -0
- package/rules/05-issue-first-workflow.md +119 -0
- package/rules/10-agent-routing.md +58 -0
- package/rules/15-mcp-launchpad.md +46 -0
- package/rules/20-code-review-loop.md +234 -0
- package/rules/25-documentation-updates.md +15 -0
- package/rules/30-prompt-templates.md +19 -0
- package/rules/35-memory.md +240 -0
- package/rules/40-critical-rules.md +124 -0
- package/rules/45-file-preview.md +29 -0
- package/rules/50-agent-bug-reporting.md +90 -0
- package/rules/55-coms-protocol.md +63 -0
- package/rules/60-task-tracking.md +66 -0
- package/skills/conflict-resolver/SKILL.md +213 -0
- package/skills/skill-creator/SKILL.md +85 -0
- package/skills/systematic-debugging/SKILL.md +353 -0
- package/skills/test-driven-development/SKILL.md +335 -0
- package/skills/update-agents-md/SKILL.md +282 -0
- package/templates/coms-feature-manager-prompt.md +313 -0
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Managed snapshot refresh — periodic re-probe with settings-change detection.
|
|
3
|
+
*
|
|
4
|
+
* Adapted from t3code's `makeManagedServerProvider.ts`. Uses plain
|
|
5
|
+
* TypeScript (setInterval, callbacks) instead of Effect (Fiber, PubSub, Ref).
|
|
6
|
+
*
|
|
7
|
+
* Provides periodic model refresh, settings-change detection, and an
|
|
8
|
+
* enrichment pipeline. All scoped — `dispose()` clears intervals and
|
|
9
|
+
* releases resources.
|
|
10
|
+
*
|
|
11
|
+
* @module shared/managed-refresh
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
import type { ProviderSnapshot, DiscoveredModel } from "./provider-driver.js";
|
|
15
|
+
import { fileLog } from "./file-logger.js";
|
|
16
|
+
|
|
17
|
+
const LOG_DOMAIN = "managed-refresh";
|
|
18
|
+
|
|
19
|
+
// ---------------------------------------------------------------------------
|
|
20
|
+
// Types
|
|
21
|
+
// ---------------------------------------------------------------------------
|
|
22
|
+
|
|
23
|
+
export interface ManagedSnapshotOptions<Settings = unknown> {
|
|
24
|
+
/** Build the initial snapshot from current settings. */
|
|
25
|
+
readonly initialSnapshot: (settings: Settings) => ProviderSnapshot;
|
|
26
|
+
|
|
27
|
+
/** Probe current status (binary version, availability, models). */
|
|
28
|
+
readonly checkProvider: () => Promise<ProviderSnapshot>;
|
|
29
|
+
|
|
30
|
+
/** Optional: enrich a snapshot (e.g. model catalog refresh). */
|
|
31
|
+
readonly enrichSnapshot?: (input: {
|
|
32
|
+
readonly settings: Settings;
|
|
33
|
+
readonly snapshot: ProviderSnapshot;
|
|
34
|
+
readonly getSnapshot: () => ProviderSnapshot;
|
|
35
|
+
readonly publishSnapshot: (snapshot: ProviderSnapshot) => void;
|
|
36
|
+
}) => Promise<void>;
|
|
37
|
+
|
|
38
|
+
/** Get current settings. */
|
|
39
|
+
readonly getSettings: () => Settings;
|
|
40
|
+
|
|
41
|
+
/** Detect meaningful settings changes. */
|
|
42
|
+
readonly haveSettingsChanged: (previous: Settings, next: Settings) => boolean;
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Refresh interval in milliseconds.
|
|
46
|
+
* Default: 300_000 (5 minutes), matching t3code's SNAPSHOT_REFRESH_INTERVAL.
|
|
47
|
+
*/
|
|
48
|
+
readonly refreshIntervalMs?: number;
|
|
49
|
+
|
|
50
|
+
/** Optional callback when snapshot changes. */
|
|
51
|
+
readonly onSnapshotChange?: (snapshot: ProviderSnapshot) => void;
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Skip the fire-and-forget initial probe on create.
|
|
55
|
+
* Use when the caller already discovered models during create() and
|
|
56
|
+
* passed them via initialSnapshot — avoids duplicate discovery on startup.
|
|
57
|
+
*/
|
|
58
|
+
readonly skipInitialRefresh?: boolean;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export interface ManagedSnapshotResult {
|
|
62
|
+
/** Get the current snapshot. */
|
|
63
|
+
readonly getSnapshot: () => ProviderSnapshot;
|
|
64
|
+
/** Force a refresh now. */
|
|
65
|
+
readonly refresh: () => Promise<ProviderSnapshot>;
|
|
66
|
+
/** Stop all refresh timers and release resources. */
|
|
67
|
+
readonly dispose: () => void;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// ---------------------------------------------------------------------------
|
|
71
|
+
// Implementation
|
|
72
|
+
// ---------------------------------------------------------------------------
|
|
73
|
+
|
|
74
|
+
const DEFAULT_REFRESH_INTERVAL_MS = 300_000; // 5 minutes
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Create a managed snapshot with periodic refresh and settings-change detection.
|
|
78
|
+
*
|
|
79
|
+
* Adapted from t3code's `makeManagedServerProvider`:
|
|
80
|
+
* - Periodic refresh via `setInterval` (t3code uses `Effect.forever + Effect.sleep`)
|
|
81
|
+
* - Settings-change detection triggers re-probe (t3code uses `Stream.runForEach`)
|
|
82
|
+
* - Enrichment pipeline for model catalog refresh (t3code uses forked fibers)
|
|
83
|
+
* - Deterministic cleanup via `dispose()` (t3code uses `Scope`)
|
|
84
|
+
*/
|
|
85
|
+
export function makeManagedSnapshot<Settings = unknown>(
|
|
86
|
+
opts: ManagedSnapshotOptions<Settings>,
|
|
87
|
+
): ManagedSnapshotResult {
|
|
88
|
+
const refreshIntervalMs = opts.refreshIntervalMs ?? DEFAULT_REFRESH_INTERVAL_MS;
|
|
89
|
+
|
|
90
|
+
let currentSnapshot = opts.initialSnapshot(opts.getSettings());
|
|
91
|
+
let previousSettings = opts.getSettings();
|
|
92
|
+
let refreshing = false;
|
|
93
|
+
let disposed = false;
|
|
94
|
+
let enrichmentAbort: AbortController | null = null;
|
|
95
|
+
|
|
96
|
+
const publishSnapshot = (snapshot: ProviderSnapshot): void => {
|
|
97
|
+
if (disposed) return;
|
|
98
|
+
currentSnapshot = snapshot;
|
|
99
|
+
opts.onSnapshotChange?.(snapshot);
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
const doRefresh = async (forceRefresh = false): Promise<ProviderSnapshot> => {
|
|
103
|
+
if (disposed) return currentSnapshot;
|
|
104
|
+
if (refreshing) return currentSnapshot;
|
|
105
|
+
refreshing = true;
|
|
106
|
+
|
|
107
|
+
try {
|
|
108
|
+
const nextSettings = opts.getSettings();
|
|
109
|
+
const settingsChanged = opts.haveSettingsChanged(previousSettings, nextSettings);
|
|
110
|
+
|
|
111
|
+
if (!forceRefresh && !settingsChanged) {
|
|
112
|
+
previousSettings = nextSettings;
|
|
113
|
+
return currentSnapshot;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
const nextSnapshot = await opts.checkProvider();
|
|
117
|
+
if (disposed) return currentSnapshot;
|
|
118
|
+
|
|
119
|
+
previousSettings = nextSettings;
|
|
120
|
+
publishSnapshot(nextSnapshot);
|
|
121
|
+
|
|
122
|
+
// Cancel any previous enrichment
|
|
123
|
+
if (enrichmentAbort) {
|
|
124
|
+
enrichmentAbort.abort();
|
|
125
|
+
enrichmentAbort = null;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
// Run enrichment if provided
|
|
129
|
+
if (opts.enrichSnapshot) {
|
|
130
|
+
enrichmentAbort = new AbortController();
|
|
131
|
+
const capturedSnapshot = nextSnapshot;
|
|
132
|
+
// Fire-and-forget enrichment (t3code forks this as a scoped fiber)
|
|
133
|
+
opts.enrichSnapshot({
|
|
134
|
+
settings: nextSettings,
|
|
135
|
+
snapshot: capturedSnapshot,
|
|
136
|
+
getSnapshot: () => currentSnapshot,
|
|
137
|
+
publishSnapshot,
|
|
138
|
+
}).catch((err) => {
|
|
139
|
+
if (!disposed) {
|
|
140
|
+
fileLog(LOG_DOMAIN, "warn", LOG_DOMAIN,
|
|
141
|
+
`enrichment failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
142
|
+
}
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
return nextSnapshot;
|
|
147
|
+
} catch (err) {
|
|
148
|
+
if (!disposed) {
|
|
149
|
+
fileLog(LOG_DOMAIN, "warn", LOG_DOMAIN,
|
|
150
|
+
`refresh failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
151
|
+
}
|
|
152
|
+
return currentSnapshot;
|
|
153
|
+
} finally {
|
|
154
|
+
refreshing = false;
|
|
155
|
+
}
|
|
156
|
+
};
|
|
157
|
+
|
|
158
|
+
// Initial probe (fire-and-forget, matching t3code's forkScoped initial probe)
|
|
159
|
+
// Skip when the caller already discovered models during create() and passed
|
|
160
|
+
// them via initialSnapshot — avoids duplicate discovery on startup.
|
|
161
|
+
if (!opts.skipInitialRefresh) {
|
|
162
|
+
doRefresh(true).catch((err) => {
|
|
163
|
+
fileLog(LOG_DOMAIN, "warn", LOG_DOMAIN,
|
|
164
|
+
`initial refresh failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
165
|
+
});
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
// Periodic refresh
|
|
169
|
+
const timer = setInterval(() => {
|
|
170
|
+
doRefresh(true).catch((err) => {
|
|
171
|
+
fileLog(LOG_DOMAIN, "warn", LOG_DOMAIN,
|
|
172
|
+
`periodic refresh failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
173
|
+
});
|
|
174
|
+
}, refreshIntervalMs);
|
|
175
|
+
|
|
176
|
+
// Unref so it doesn't keep the process alive
|
|
177
|
+
if (timer.unref) timer.unref();
|
|
178
|
+
|
|
179
|
+
return {
|
|
180
|
+
getSnapshot: () => currentSnapshot,
|
|
181
|
+
refresh: () => doRefresh(true),
|
|
182
|
+
dispose: () => {
|
|
183
|
+
if (disposed) return;
|
|
184
|
+
disposed = true;
|
|
185
|
+
clearInterval(timer);
|
|
186
|
+
if (enrichmentAbort) {
|
|
187
|
+
enrichmentAbort.abort();
|
|
188
|
+
enrichmentAbort = null;
|
|
189
|
+
}
|
|
190
|
+
},
|
|
191
|
+
};
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
/**
|
|
195
|
+
* Build a simple initial snapshot from discovered models.
|
|
196
|
+
* Convenience for drivers that discover models during probe.
|
|
197
|
+
*/
|
|
198
|
+
export function buildInitialSnapshot(
|
|
199
|
+
available: boolean,
|
|
200
|
+
models: readonly DiscoveredModel[],
|
|
201
|
+
version?: string,
|
|
202
|
+
message?: string,
|
|
203
|
+
): ProviderSnapshot {
|
|
204
|
+
return {
|
|
205
|
+
available,
|
|
206
|
+
version,
|
|
207
|
+
models,
|
|
208
|
+
message,
|
|
209
|
+
checkedAt: new Date().toISOString(),
|
|
210
|
+
};
|
|
211
|
+
}
|
|
@@ -0,0 +1,295 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ProviderDriver / ProviderInstance — driver SPI as plain values.
|
|
3
|
+
*
|
|
4
|
+
* Adapted from t3code's `ProviderDriver.ts`. Uses plain TypeScript
|
|
5
|
+
* (no Effect dependency) — async functions replace Effect monads,
|
|
6
|
+
* try/finally replaces scoped lifecycle.
|
|
7
|
+
*
|
|
8
|
+
* `ProviderDriver` is a record, not a class. The thing it produces
|
|
9
|
+
* (`ProviderInstance`) is also a record — captured closures
|
|
10
|
+
* (`snapshot`, `adapter`), an id, and a driver kind. There are
|
|
11
|
+
* intentionally no singletons because we need many instances of the
|
|
12
|
+
* same driver.
|
|
13
|
+
*
|
|
14
|
+
* Driver factories are functions of `(typed config, env)` where:
|
|
15
|
+
* - `typed config` is validated once by the registry via `configSchema`,
|
|
16
|
+
* so drivers never deal with raw `unknown`.
|
|
17
|
+
* - Cleanup is deterministic: `dispose()` releases every resource the
|
|
18
|
+
* driver opened (child processes, intervals, pubsub channels).
|
|
19
|
+
*
|
|
20
|
+
* @module shared/provider-driver
|
|
21
|
+
*/
|
|
22
|
+
|
|
23
|
+
// ---------------------------------------------------------------------------
|
|
24
|
+
// Stream Events (unified across CLI + ACPX)
|
|
25
|
+
// ---------------------------------------------------------------------------
|
|
26
|
+
|
|
27
|
+
/** Normalized event emitted by driver adapters during a turn. */
|
|
28
|
+
export type DriverStreamEvent =
|
|
29
|
+
| { readonly kind: "text_delta"; readonly text: string }
|
|
30
|
+
| { readonly kind: "thinking_delta"; readonly text: string }
|
|
31
|
+
| { readonly kind: "session"; readonly sessionId: string }
|
|
32
|
+
| { readonly kind: "turn_complete"; readonly stopReason?: string };
|
|
33
|
+
|
|
34
|
+
// ---------------------------------------------------------------------------
|
|
35
|
+
// ProviderDriver Metadata
|
|
36
|
+
// ---------------------------------------------------------------------------
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Static metadata advertised by a driver. Used for default presentation
|
|
40
|
+
* and (later) settings UI. Drivers are registered at startup — nothing
|
|
41
|
+
* here is dynamic.
|
|
42
|
+
*/
|
|
43
|
+
export interface ProviderDriverMetadata {
|
|
44
|
+
/** Human-readable name for the driver itself (e.g. "Cursor CLI"). */
|
|
45
|
+
readonly displayName: string;
|
|
46
|
+
/**
|
|
47
|
+
* Whether the driver may be instantiated more than once concurrently.
|
|
48
|
+
* Defaults to `true`. Set to `false` for drivers that wrap a global
|
|
49
|
+
* resource (e.g. a single desktop app socket) — the registry then
|
|
50
|
+
* rejects multi-instance configurations with a clear error.
|
|
51
|
+
*/
|
|
52
|
+
readonly supportsMultipleInstances?: boolean;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// ---------------------------------------------------------------------------
|
|
56
|
+
// Probe Result
|
|
57
|
+
// ---------------------------------------------------------------------------
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Result of a driver's binary/runtime probe. Returned by `driver.probe()`.
|
|
61
|
+
* When `available` is false, the registry creates an "unavailable" shadow
|
|
62
|
+
* snapshot instead of calling `create()`.
|
|
63
|
+
*/
|
|
64
|
+
export interface ProviderProbeResult {
|
|
65
|
+
readonly available: boolean;
|
|
66
|
+
readonly version?: string;
|
|
67
|
+
/** Human-readable reason when unavailable (e.g. "binary not on PATH"). */
|
|
68
|
+
readonly reason?: string;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// ---------------------------------------------------------------------------
|
|
72
|
+
// Provider Snapshot Shape
|
|
73
|
+
// ---------------------------------------------------------------------------
|
|
74
|
+
|
|
75
|
+
/** A point-in-time snapshot of a provider's status and models. */
|
|
76
|
+
export interface ProviderSnapshot {
|
|
77
|
+
readonly available: boolean;
|
|
78
|
+
readonly version?: string;
|
|
79
|
+
readonly models: readonly DiscoveredModel[];
|
|
80
|
+
/** Human-readable message (error detail, status, etc.). */
|
|
81
|
+
readonly message?: string;
|
|
82
|
+
readonly checkedAt: string;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/** Model discovered by a driver (used in snapshots). */
|
|
86
|
+
export interface DiscoveredModel {
|
|
87
|
+
readonly id: string;
|
|
88
|
+
readonly name: string;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Live snapshot accessor for a provider instance. The registry reads
|
|
93
|
+
* `getSnapshot()` for current state, calls `refresh()` to force a
|
|
94
|
+
* re-probe, and optionally subscribes to `onChange` for push updates.
|
|
95
|
+
*/
|
|
96
|
+
export interface ProviderSnapshotShape {
|
|
97
|
+
readonly getSnapshot: () => ProviderSnapshot;
|
|
98
|
+
readonly refresh: () => Promise<ProviderSnapshot>;
|
|
99
|
+
/** Optional callback-based change notification. */
|
|
100
|
+
readonly onChange?: (listener: (snapshot: ProviderSnapshot) => void) => () => void;
|
|
101
|
+
/** Cleanup — stop refresh intervals, release resources. */
|
|
102
|
+
readonly dispose: () => void;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// ---------------------------------------------------------------------------
|
|
106
|
+
// Provider Adapter Shape (Session / Turn runtime)
|
|
107
|
+
// ---------------------------------------------------------------------------
|
|
108
|
+
|
|
109
|
+
/** Options for starting a session via the adapter. */
|
|
110
|
+
export interface SessionStartOptions {
|
|
111
|
+
readonly model?: string;
|
|
112
|
+
readonly systemPrompt?: string;
|
|
113
|
+
readonly cwd: string;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/** Opaque handle to an active adapter session. */
|
|
117
|
+
export interface SessionHandle {
|
|
118
|
+
readonly sessionId: string;
|
|
119
|
+
readonly model: string;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/** Options for sending a turn. */
|
|
123
|
+
export interface TurnOptions {
|
|
124
|
+
readonly signal?: AbortSignal;
|
|
125
|
+
/** Pi conversation context — used by drivers that seed history into fresh CLI sessions. */
|
|
126
|
+
readonly context?: { messages: Array<{ role: string; content: any }> };
|
|
127
|
+
readonly onEvent?: (event: DriverStreamEvent) => void;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/** Per-turn token usage and cost breakdown. */
|
|
131
|
+
export interface DriverUsage {
|
|
132
|
+
readonly inputTokens?: number;
|
|
133
|
+
readonly outputTokens?: number;
|
|
134
|
+
readonly cachedReadTokens?: number;
|
|
135
|
+
readonly cachedWriteTokens?: number;
|
|
136
|
+
readonly thoughtTokens?: number;
|
|
137
|
+
readonly totalTokens?: number;
|
|
138
|
+
/** USD cost when the provider reports it (Claude CLI, ACPX). */
|
|
139
|
+
readonly costUsd?: number;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/** Result of a completed turn. */
|
|
143
|
+
export interface TurnResult {
|
|
144
|
+
readonly text: string;
|
|
145
|
+
readonly thinking?: string;
|
|
146
|
+
readonly sessionId?: string;
|
|
147
|
+
readonly stopReason?: string;
|
|
148
|
+
readonly usage?: DriverUsage;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* Provider-specific runtime adapter contract — session/turn operations.
|
|
153
|
+
*
|
|
154
|
+
* Adapted from t3code's `ProviderAdapterShape`. Simplified to async
|
|
155
|
+
* functions (no Effect monads). Drivers own session state; the registry
|
|
156
|
+
* owns instance lifecycle.
|
|
157
|
+
*/
|
|
158
|
+
export interface ProviderAdapterShape {
|
|
159
|
+
/** Start a new session or resume an existing one. */
|
|
160
|
+
readonly startSession: (opts: SessionStartOptions) => Promise<SessionHandle>;
|
|
161
|
+
|
|
162
|
+
/** Send a turn (prompt) to an active session. */
|
|
163
|
+
readonly sendTurn: (
|
|
164
|
+
handle: SessionHandle,
|
|
165
|
+
prompt: string,
|
|
166
|
+
opts?: TurnOptions,
|
|
167
|
+
) => Promise<TurnResult>;
|
|
168
|
+
|
|
169
|
+
/** Stop one session. */
|
|
170
|
+
readonly stopSession: (handle: SessionHandle) => Promise<void>;
|
|
171
|
+
|
|
172
|
+
/** Stop all sessions owned by this adapter. */
|
|
173
|
+
readonly stopAll: () => Promise<void>;
|
|
174
|
+
|
|
175
|
+
/** Check whether this adapter owns an active session id. */
|
|
176
|
+
readonly hasSession: (sessionId: string) => boolean;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
// ---------------------------------------------------------------------------
|
|
180
|
+
// Provider Instance
|
|
181
|
+
// ---------------------------------------------------------------------------
|
|
182
|
+
|
|
183
|
+
/**
|
|
184
|
+
* One materialized provider instance. Held by the registry, looked up by
|
|
185
|
+
* `instanceId`, torn down by calling `dispose()`.
|
|
186
|
+
*
|
|
187
|
+
* The two "shape" fields are captured closures owned by this instance —
|
|
188
|
+
* stopping one instance cannot affect another, and starting a second
|
|
189
|
+
* instance of the same driver does not reach into the first instance's
|
|
190
|
+
* state.
|
|
191
|
+
*/
|
|
192
|
+
export interface ProviderInstance {
|
|
193
|
+
readonly instanceId: string;
|
|
194
|
+
readonly driverKind: string;
|
|
195
|
+
readonly displayName?: string;
|
|
196
|
+
readonly enabled: boolean;
|
|
197
|
+
/** Status/models/health — refreshable. */
|
|
198
|
+
readonly snapshot: ProviderSnapshotShape;
|
|
199
|
+
/** Session/turn runtime. */
|
|
200
|
+
readonly adapter: ProviderAdapterShape;
|
|
201
|
+
/** Cleanup — called when instance is torn down. Releases all resources. */
|
|
202
|
+
readonly dispose: () => Promise<void>;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
// ---------------------------------------------------------------------------
|
|
206
|
+
// Provider Driver Create Input
|
|
207
|
+
// ---------------------------------------------------------------------------
|
|
208
|
+
|
|
209
|
+
/**
|
|
210
|
+
* Inputs the registry passes to a driver's `create` function.
|
|
211
|
+
*
|
|
212
|
+
* `config` is the typed payload — already validated by the registry through
|
|
213
|
+
* `driver.configSchema`. Drivers never validate their own raw envelope.
|
|
214
|
+
*/
|
|
215
|
+
export interface ProviderDriverCreateInput<Config> {
|
|
216
|
+
readonly instanceId: string;
|
|
217
|
+
readonly displayName?: string;
|
|
218
|
+
readonly enabled: boolean;
|
|
219
|
+
readonly config: Config;
|
|
220
|
+
readonly cwd: string;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
// ---------------------------------------------------------------------------
|
|
224
|
+
// Config Schema (validation interface)
|
|
225
|
+
// ---------------------------------------------------------------------------
|
|
226
|
+
|
|
227
|
+
/**
|
|
228
|
+
* Minimal config validation interface. Drivers provide a `parse(unknown)`
|
|
229
|
+
* that either returns a typed config or throws. Works with zod schemas
|
|
230
|
+
* or any hand-rolled validator.
|
|
231
|
+
*
|
|
232
|
+
* ```ts
|
|
233
|
+
* const schema: ConfigSchema<MyConfig> = {
|
|
234
|
+
* parse: (raw) => { ... validate and return MyConfig ... },
|
|
235
|
+
* };
|
|
236
|
+
* ```
|
|
237
|
+
*/
|
|
238
|
+
export interface ConfigSchema<Config> {
|
|
239
|
+
/** Decode unknown input into typed Config. Throws on validation failure. */
|
|
240
|
+
readonly parse: (raw: unknown) => Config;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
// ---------------------------------------------------------------------------
|
|
244
|
+
// Provider Driver SPI
|
|
245
|
+
// ---------------------------------------------------------------------------
|
|
246
|
+
|
|
247
|
+
/**
|
|
248
|
+
* Driver SPI — registered as a plain value, not a class.
|
|
249
|
+
*
|
|
250
|
+
* `Config` is whatever the driver decoded from settings. `create` is
|
|
251
|
+
* responsible for *all* per-instance state — process handles, intervals,
|
|
252
|
+
* file watchers — and must release them when `dispose()` is called on the
|
|
253
|
+
* returned instance. Two calls to `create` with different `instanceId` /
|
|
254
|
+
* `config` MUST yield instances with no shared mutable state.
|
|
255
|
+
*/
|
|
256
|
+
export interface ProviderDriver<Config> {
|
|
257
|
+
readonly driverKind: string;
|
|
258
|
+
readonly metadata: ProviderDriverMetadata;
|
|
259
|
+
/**
|
|
260
|
+
* Validator for the opaque config envelope. The registry runs this
|
|
261
|
+
* exactly once per (re)load of an instance; a validation failure is
|
|
262
|
+
* surfaced as `ProviderDriverError` and downgraded to an unavailable
|
|
263
|
+
* shadow snapshot.
|
|
264
|
+
*/
|
|
265
|
+
readonly configSchema: ConfigSchema<Config>;
|
|
266
|
+
/**
|
|
267
|
+
* Default config payload used when settings are empty or when the driver
|
|
268
|
+
* is auto-bootstrapped without user configuration.
|
|
269
|
+
*/
|
|
270
|
+
readonly defaultConfig: () => Config;
|
|
271
|
+
/**
|
|
272
|
+
* Probe binary/runtime availability + basic status. Called before
|
|
273
|
+
* `create()` — when `available` is false, the registry synthesizes an
|
|
274
|
+
* "unavailable" shadow snapshot.
|
|
275
|
+
*/
|
|
276
|
+
readonly probe: (config: Config) => Promise<ProviderProbeResult>;
|
|
277
|
+
/**
|
|
278
|
+
* Materialize one instance. The returned instance owns all per-instance
|
|
279
|
+
* state. Failures throw `ProviderDriverError` — the registry catches
|
|
280
|
+
* them and downgrades to an unavailable shadow snapshot.
|
|
281
|
+
*
|
|
282
|
+
* Two calls to `create` with different `instanceId` / `config` MUST
|
|
283
|
+
* yield instances with no shared mutable state.
|
|
284
|
+
*/
|
|
285
|
+
readonly create: (
|
|
286
|
+
input: ProviderDriverCreateInput<Config>,
|
|
287
|
+
) => Promise<ProviderInstance>;
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
/**
|
|
291
|
+
* Heterogeneous-array convenience: the registry stores drivers as
|
|
292
|
+
* `AnyProviderDriver[]` where the per-driver Config is erased.
|
|
293
|
+
*/
|
|
294
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
295
|
+
export type AnyProviderDriver = ProviderDriver<any>;
|