@tomradex/agent 0.16.2 → 0.17.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.
@@ -0,0 +1,10 @@
1
+ import type { Engine, EngineRegistration } from "./engine.js";
2
+ /**
3
+ * The engine in the grouped shape, whichever shape it was given in: plugins
4
+ * built before the grouping still register flat members. Everything past
5
+ * registration reads only the grouped ones.
6
+ */
7
+ export declare function normalizeEngine(given: EngineRegistration): Engine;
8
+ /** The engine in the flat names plugin scenarios read (`localAgents.engine`), as they were before the grouping. */
9
+ export declare function flatEngineView(engine: Engine): Record<string, unknown>;
10
+ //# sourceMappingURL=engine-shape.d.ts.map
@@ -0,0 +1,332 @@
1
+ import type { z } from "zod";
2
+ import type { Author } from "@tomradex/domain";
3
+ import type { TurnInput, TurnIO, TurnResult } from "./turn.js";
4
+ /**
5
+ * What an engine can be trusted with. `backlog` talks to the app through its
6
+ * tools; `code` also edits files and runs commands in a repository — only a
7
+ * local coding agent (Claude Code, Codex…) declares it, and only such an engine
8
+ * is offered when a ticket is started.
9
+ */
10
+ export type EngineCapability = "backlog" | "code" | "general";
11
+ /**
12
+ * What stands between an engine and its first turn, so the app can say how to fix it in the person's language.
13
+ * `repair`: the CLI is there but does not run.
14
+ */
15
+ export type EngineNeed = "install" | "repair" | "sign-in" | "model" | "service";
16
+ /** Where a local CLI candidate came from, in the order they are tried. */
17
+ export type CliSource = "manual" | "path" | "login-path" | "known";
18
+ export interface CliAttempt {
19
+ path: string;
20
+ source: CliSource;
21
+ ok: boolean;
22
+ /** The version it printed, or why it did not run. */
23
+ detail: string;
24
+ }
25
+ /** How a local agent's CLI was looked for and what was found — enough to show its state and to report it. */
26
+ export interface LocalCliStatus {
27
+ name: string;
28
+ state: "ready" | "missing" | "broken";
29
+ path?: string;
30
+ source?: CliSource;
31
+ version?: string;
32
+ /** Why the best candidate did not run, when none did. */
33
+ error?: string;
34
+ /** A path the person chose that no longer runs; detection carried on without it. */
35
+ manual?: {
36
+ path: string;
37
+ error: string;
38
+ };
39
+ /** Found only inside WSL, where a Windows app cannot run it. */
40
+ wsl?: string;
41
+ /** Not found, but this agent's desktop app is installed — which does not include the CLI. */
42
+ desktopApp?: string;
43
+ /** Not found, and this login shell did not answer in time: the folders its startup files add to PATH went unsearched. */
44
+ shellTimedOut?: string;
45
+ attempts: CliAttempt[];
46
+ /** Directories searched, in order. */
47
+ searched: string[];
48
+ platform: string;
49
+ arch: string;
50
+ /** The PATH the app itself runs with. */
51
+ pathEnv: string;
52
+ }
53
+ export interface EngineAvailability {
54
+ ok: boolean;
55
+ reason?: string;
56
+ need?: EngineNeed;
57
+ /** Present for engines that drive a CLI installed on this machine. */
58
+ cli?: LocalCliStatus;
59
+ /** What it can take on right now, when only part of it is ready; absent means all its capabilities. */
60
+ capabilities?: EngineCapability[];
61
+ /** How it installs on this machine, when that differs from the engine's declared setup — an installer that is not here is left out. */
62
+ setup?: EngineSetup;
63
+ /** The folder a local CLI reads its sign-in from, when it is not signed in (CODEX_HOME, CLAUDE_CONFIG_DIR). */
64
+ configDir?: string;
65
+ }
66
+ /**
67
+ * How a person makes a local agent ready on this machine, as commands: what
68
+ * setup screens show, copy and run in a terminal. Only what an engine declares
69
+ * here can be started in a terminal from the app.
70
+ */
71
+ export interface EngineSetup {
72
+ /** Install commands, the recommended one first. */
73
+ install: string[];
74
+ signIn?: string;
75
+ /** Signing in starts the agent itself, which then asks (`/login`); otherwise the command signs in and returns. */
76
+ signInRuns?: boolean;
77
+ docs?: string;
78
+ /** Offered on setup screens before it is installed. */
79
+ suggested?: boolean;
80
+ }
81
+ /**
82
+ * Tomrade's MCP server in the agent's own user-level configuration, so a
83
+ * session the person opens anywhere outside Tomrade can reach it. Written only
84
+ * when the person asks.
85
+ */
86
+ export interface EngineMcpLink {
87
+ status(): Promise<McpLinkView>;
88
+ /** `profile` names one of `status().profiles`; without it, the agent's own (the first). Answers as `status()` does. */
89
+ connect(profile?: string): Promise<McpLinkView>;
90
+ disconnect(profile?: string): Promise<McpLinkView>;
91
+ /** Whether the agent will load a `tomrade` server a repository's own config declares; some ask once per folder first. */
92
+ projectApproval?(dir: string): "approved" | "rejected" | "pending";
93
+ /** The same, for each of its profiles. */
94
+ projectApprovals?(dir: string): McpProjectApproval[];
95
+ /** A session of the agent started somewhere — its transcript names the profile it ran under. */
96
+ sawTranscript?(file: string): void;
97
+ }
98
+ export interface McpProjectApproval {
99
+ profile: string;
100
+ state: "approved" | "rejected" | "pending";
101
+ /** How to start the agent under that profile, for the person to run in the checkout. */
102
+ command: string;
103
+ }
104
+ export interface McpLinkView {
105
+ /** `stale`: a `tomrade` server is configured but at another address (an old port, the other Tomrade). */
106
+ state: "connected" | "missing" | "stale" | "unavailable";
107
+ /** The address this Tomrade serves; null while its MCP server is not running. */
108
+ url: string | null;
109
+ /** The address the agent's configuration names, when it names one. */
110
+ configuredUrl: string | null;
111
+ /** Where the agent keeps it, for the person to look at. */
112
+ file: string | null;
113
+ /** Commands that do the same by hand, for when the CLI cannot be run from here. */
114
+ manual: {
115
+ connect: string;
116
+ disconnect: string;
117
+ };
118
+ /** Why the last step could not be done or the state could not be read. */
119
+ error?: string;
120
+ /** The configuration folder this describes, for an agent that has several (CLAUDE_CONFIG_DIR per account). */
121
+ profile?: string;
122
+ /** Every profile, this one first, when there is more than one. */
123
+ profiles?: McpLinkView[];
124
+ }
125
+ /** A path the person typed or picked, run once to see whether it is the CLI. */
126
+ export interface CliCheck {
127
+ ok: boolean;
128
+ path: string;
129
+ version?: string;
130
+ error?: string;
131
+ }
132
+ /** Anything that can take one turn on a thread. The conductor seam. */
133
+ export interface Engine {
134
+ /** Actual formats supported by the selected transport/model; absent means text only. */
135
+ media?(options: unknown): {
136
+ input: string[];
137
+ output: string[];
138
+ };
139
+ id: string;
140
+ title: string;
141
+ author: Author;
142
+ /** Absent means `["backlog"]`. */
143
+ capabilities?: EngineCapability[];
144
+ /**
145
+ * Engines this one runs in their place: pickers list it alone, and a thread
146
+ * or setting naming one of them is answered by this engine.
147
+ */
148
+ includes?: string[];
149
+ /**
150
+ * No model judges what the user types: free text while a workflow waits is
151
+ * taken as that workflow's answer. A model engine instead reads the reply with
152
+ * the waiting question in its prompt and resumes or cancels the workflow itself.
153
+ */
154
+ literal?: boolean;
155
+ /**
156
+ * `fresh` looks again instead of answering from a recent probe — after the person installs or points at a CLI.
157
+ * `options`: whether it can run a turn with these engine options, such as the model a thread picked.
158
+ */
159
+ available(opts?: {
160
+ fresh?: boolean;
161
+ options?: unknown;
162
+ }): Promise<EngineAvailability>;
163
+ /** Engine settings, drawn by the settings UI from the schema. */
164
+ options?: z.ZodType<unknown>;
165
+ /** `default` is what a session starts in until the person picks another mode. */
166
+ permissionModes?: {
167
+ default: string;
168
+ choices: {
169
+ value: string;
170
+ label: string;
171
+ }[];
172
+ };
173
+ /** Whether a ticket can be handed to its CLI in a terminal. Absent: `{ mode: "handoff" }`. */
174
+ terminal?: EngineTerminal;
175
+ /** True: it runs on the model profiles set up in Tomrade, so a key or model error is fixed there — not in its own sign-in. */
176
+ usesModels?: boolean;
177
+ /** How it takes messages sent while a turn runs; absent, the panel queues them until the turn ends. */
178
+ steering?: EngineSteering;
179
+ /** The agent's own setup on this machine: its CLI, install, connection, permissions and knobs. */
180
+ local?: EngineLocal;
181
+ turn(input: TurnInput, io: TurnIO): Promise<TurnResult>;
182
+ }
183
+ export interface EngineTerminal {
184
+ /**
185
+ * `none`: it runs only inside Tomrade, with no CLI session a person can be handed in a terminal.
186
+ * `handoff`: a ticket can also be handed to its CLI in a terminal.
187
+ * `only`: a CLI Tomrade starts only in a terminal the person sees — handed the ticket, heard over MCP, never driven turn by turn.
188
+ */
189
+ mode: "none" | "handoff" | "only";
190
+ /** `link`: in a terminal it reaches Tomrade only through its own user-level connection (`local.mcpLink`), so that comes first. Absent: `session`. */
191
+ via?: "session" | "link";
192
+ /** That connection carries no session token, so the session's first act is claim_ticket, which joins it to the session Start made. */
193
+ claims?: boolean;
194
+ }
195
+ /**
196
+ * `queue`: Tomrade holds them and the engine takes them where its model reads next (`io.takeSteers`).
197
+ * `forward`: its agent keeps its own steering queue; each is handed over (`io.steerTo`) and placed when read (`io.steered`).
198
+ */
199
+ export type EngineSteering = "queue" | "forward";
200
+ export interface EngineLocal {
201
+ /** Whether this file is a CLI it can use. */
202
+ checkCli?(file: string): Promise<CliCheck>;
203
+ setup?: EngineSetup;
204
+ /** Quick-pick knobs the panel offers; each writes options[key]. Called per view, so lists can be live. */
205
+ picks?(): EnginePick[];
206
+ /** What the troubleshooter may read about this engine beyond `available()`. */
207
+ diagnostics?: EngineDiagnostics;
208
+ /** What the engine's own configuration lets its agent run; absent when Tomrade cannot read it. */
209
+ commands?: EngineCommands;
210
+ mcpLink?: EngineMcpLink;
211
+ }
212
+ /** The flat members an engine had before they were grouped; `Agent.engine` still maps them once, at registration. */
213
+ export interface FlatEngineMembers {
214
+ /** @deprecated `terminal: { mode: "none" }` for false. */
215
+ terminal?: boolean;
216
+ /** @deprecated `terminal: { mode: "only" }`. */
217
+ terminalOnly?: boolean;
218
+ /** @deprecated `terminal: { via: "link" }`. */
219
+ terminalViaLink?: boolean;
220
+ /** @deprecated `terminal: { claims: true }`. */
221
+ terminalClaims?: boolean;
222
+ /** @deprecated `steering`; read as `"queue"`, and a turn's `io` offers both protocols either way. */
223
+ steers?: boolean;
224
+ /** @deprecated `local.checkCli`. */
225
+ checkCli?(file: string): Promise<CliCheck>;
226
+ /** @deprecated `local.setup`. */
227
+ setup?: EngineSetup;
228
+ /** @deprecated `local.picks`. */
229
+ picks?(): EnginePick[];
230
+ /** @deprecated `local.diagnostics`. */
231
+ diagnostics?: EngineDiagnostics;
232
+ /** @deprecated `local.commands`. */
233
+ commands?: EngineCommands;
234
+ /** @deprecated `local.mcpLink`. */
235
+ mcpLink?: EngineMcpLink;
236
+ }
237
+ /** What `Agent.engine` takes: an engine, or one still in the flat shape. */
238
+ export type EngineRegistration = Engine | (Omit<Engine, "terminal"> & FlatEngineMembers);
239
+ /**
240
+ * An engine's own evidence, for the troubleshooter and a report. Only what is
241
+ * named here is read: an agent investigating a failure gets no other files.
242
+ */
243
+ export interface EngineDiagnostics {
244
+ /** The agent's own log files, newest first; their tails go into a report. */
245
+ logs?(): string[] | Promise<string[]>;
246
+ /** Short facts that tell one setup from another — edition, endpoint, models offered. */
247
+ facts?(): Record<string, string> | Promise<Record<string, string>>;
248
+ }
249
+ /**
250
+ * Whether the engine's own permission settings let one shell command through,
251
+ * read from its config files — not a promise: a safety check or the remote can
252
+ * still refuse it at run time.
253
+ */
254
+ export interface EngineCommands {
255
+ check(command: string, opts: CommandCheckOptions): Promise<CommandCheck>;
256
+ /** Adds `check(...).fix.rule` to `fix.file`, then checks again. */
257
+ allow?(command: string, opts: CommandCheckOptions): Promise<CommandCheck>;
258
+ }
259
+ export interface CommandCheckOptions {
260
+ /** Where the agent will run, for project-level settings; null reads only the user's. */
261
+ cwd: string | null;
262
+ /** The run gets a fresh worktree of `cwd`: only checked-in project files reach it, not untracked local ones. */
263
+ worktree?: boolean;
264
+ /** The permission mode it will run under; absent, the one its settings default to. */
265
+ permissionMode?: string;
266
+ }
267
+ export interface CommandCheck {
268
+ /** `asks`: the person approves it when it comes up; `blocked`: refused, or likely to be, without a change. */
269
+ state: "allowed" | "asks" | "blocked";
270
+ /** Why, in a word a screen can name in its own language. */
271
+ why: "bypass" | "allow-rule" | "ask-rule" | "deny-rule" | "prompts" | "auto-mode" | "plan" | "dont-ask";
272
+ mode: string;
273
+ /** The rule that decided it, and the file it is in. */
274
+ rule?: {
275
+ rule: string;
276
+ file: string;
277
+ };
278
+ /** The one rule `allow` writes; absent when no added rule would help (a deny rule wins over it). */
279
+ fix?: {
280
+ rule: string;
281
+ file: string;
282
+ };
283
+ }
284
+ /** One quick-pick knob: "model" and "effort" keys get localized group labels; other keys show `title`. */
285
+ export interface EnginePick {
286
+ key: string;
287
+ title: string;
288
+ /** `searchesWeb`: the model searches the web on its own, so needs no web search key. */
289
+ choices: {
290
+ value: string;
291
+ label?: string;
292
+ searchesWeb?: boolean;
293
+ }[];
294
+ /** Choices are suggestions only — settings may hold any string (e.g. a model id the CLI knows). */
295
+ freeText?: boolean;
296
+ /** The engine is still asking its agent for the choices; ask again shortly. */
297
+ pending?: boolean;
298
+ }
299
+ /** One real turn on an engine, asked for by the person: does it answer? */
300
+ export interface EngineTry {
301
+ ok: boolean;
302
+ ms: number;
303
+ at: number;
304
+ /** What it said, cut short. */
305
+ reply?: string;
306
+ error?: string;
307
+ details?: string;
308
+ }
309
+ export interface EngineView {
310
+ id: string;
311
+ title: string;
312
+ capabilities: EngineCapability[];
313
+ ok: boolean;
314
+ reason?: string;
315
+ need?: EngineNeed;
316
+ cli?: LocalCliStatus;
317
+ configDir?: string;
318
+ /** The last try with the settings it has now; a change to its settings clears it. */
319
+ tried?: EngineTry;
320
+ picks?: EnginePick[];
321
+ permissionModes?: Engine["permissionModes"];
322
+ terminal?: boolean;
323
+ terminalOnly?: boolean;
324
+ usesModels?: boolean;
325
+ steers?: boolean;
326
+ setup?: EngineSetup;
327
+ /** Engines it answers for: a thread, run or setting may still name one of them. */
328
+ includes?: string[];
329
+ /** It can put Tomrade's MCP server in its own user-level configuration (`agent.mcpLink`). */
330
+ mcpLink?: boolean;
331
+ }
332
+ //# sourceMappingURL=engine.d.ts.map
@@ -1,4 +1,6 @@
1
- import type { Block, Engine, TurnInput, TurnIO, TurnResult } from "./types.js";
1
+ import type { Engine } from "./engine.js";
2
+ import type { Block } from "./thread.js";
3
+ import type { TurnInput, TurnIO, TurnResult } from "./turn.js";
2
4
  /** Provider counters stay separate: cached tokens are context, not free input. */
3
5
  export interface TurnMetrics {
4
6
  transport: "sdk" | "app-server" | "rpc" | "acp" | "http";
@@ -0,0 +1,122 @@
1
+ import type { Author } from "@tomradex/domain";
2
+ import type { Message, ToolSpec } from "@tomradex/llm";
3
+ import type { RunHandle } from "@tomradex/tools";
4
+ import type { ParkView, RunView, ThreadSummary } from "./thread.js";
5
+ import type { TurnInput, TurnPurpose } from "./turn.js";
6
+ declare module "cordis" {
7
+ interface Events {
8
+ "agent/prepare-turn"(input: TurnInput): Promise<void> | void;
9
+ /** The brief a CLI agent starts a delivery from, before it is handed over. A plugin may add context an in-app turn would get from `agent/prepare-turn`. */
10
+ "agent/prepare-brief"(brief: {
11
+ projectId: string;
12
+ itemId: string;
13
+ filesIndex?: string;
14
+ }): Promise<void> | void;
15
+ /** A run began driving a thread. */
16
+ "agent/run-started"(run: RunView, thread: ThreadSummary): void;
17
+ /** A run settled, however it stopped; `run.stop` says how. */
18
+ "agent/run-ended"(run: RunView, thread: ThreadSummary): void;
19
+ /** A thread stopped on a usage limit and waits for it to lift. */
20
+ "agent/parked"(park: ParkView, thread: ThreadSummary): void;
21
+ /** A parked thread's limit lifted and nobody continues it on its own: the person may. */
22
+ "agent/limit-lifted"(park: ParkView, thread: ThreadSummary): void;
23
+ /** A project's rules file was written through Tomrade. */
24
+ "agent/rules-changed"(projectId: string): void;
25
+ /**
26
+ * Each model request an in-app engine (`engine-loop`) is about to send: a listener may change its
27
+ * system prompt, tools and messages, before or after `next()`; what comes back is sent. CLI agents
28
+ * run their own loop and send nothing through here.
29
+ */
30
+ "agent/request"(request: AgentRequest, next: () => Promise<AgentRequest>): Promise<AgentRequest>;
31
+ /** A model request an in-app engine sent failed. The first listener to answer decides what to try instead. */
32
+ "agent/request-error"(failure: AgentRequestFailure): Promise<AgentRetry | void> | AgentRetry | void;
33
+ /** An in-app turn is about to end. The first listener to answer keeps it going, with a message to the model. */
34
+ "agent/turn-stopping"(ending: TurnEnding): Promise<{
35
+ continue: string;
36
+ } | void> | {
37
+ continue: string;
38
+ } | void;
39
+ /**
40
+ * A CLI agent's hook reached Tomrade — Claude Code, Codex, dsh and the rest. The first listener to
41
+ * answer decides; the answer reaches the agent only when `answerable` (a session Tomrade started).
42
+ */
43
+ "agent/cli-hook"(call: CliHookCall): Promise<CliHookAnswer | void> | CliHookAnswer | void;
44
+ }
45
+ }
46
+ /** What a CLI agent's hook says happened, in one set of names whichever agent sent it. */
47
+ export type CliHookEvent = "session-start" | "prompt" | "pre-tool" | "post-tool" | "stop" | "session-end";
48
+ export interface CliHookCall {
49
+ event: CliHookEvent;
50
+ /** The agent that sent it: `claude-code`, `codex`, `dsh`, `pi`, `workbuddy`, `cursor`, `opencode`, `hermes`… */
51
+ agent: string;
52
+ /** Whether an answer reaches the agent: true in a session Tomrade started, false for a connected repository's hooks. */
53
+ answerable: boolean;
54
+ projectId: string;
55
+ /** Tomrade's code session the hook belongs to. */
56
+ sessionId: string;
57
+ /** The ticket the session works, when it has one. */
58
+ ticket: string | null;
59
+ cwd: string | null;
60
+ tool?: {
61
+ name: string;
62
+ input: unknown;
63
+ output?: string;
64
+ error?: string;
65
+ };
66
+ /** What the model said last, at `stop`. */
67
+ text?: string;
68
+ /** The hook's own payload, as the agent sent it. */
69
+ raw: Record<string, unknown>;
70
+ }
71
+ /** Refuse the tool (`pre-tool`), add context for the model, or keep the turn going (`stop`). */
72
+ export interface CliHookAnswer {
73
+ deny?: string;
74
+ context?: string;
75
+ continue?: string;
76
+ }
77
+ /** Which turn, step and model profile a request belongs to: read, never changed. */
78
+ export interface AgentTurnInfo {
79
+ runId: string;
80
+ threadId: string;
81
+ projectId: string;
82
+ purpose: TurnPurpose;
83
+ profile: string;
84
+ step: number;
85
+ }
86
+ /** One model request as an in-app engine is about to send it. */
87
+ export interface AgentRequest {
88
+ system: string;
89
+ tools: ToolSpec[];
90
+ messages: Message[];
91
+ turn: AgentTurnInfo;
92
+ }
93
+ export interface AgentRequestFailure {
94
+ error: unknown;
95
+ request: AgentRequest;
96
+ /** How many times this step was already tried again on a listener's answer. */
97
+ attempt: number;
98
+ }
99
+ /** Send the request again: changed, on another model profile, or both. */
100
+ export interface AgentRetry {
101
+ request?: Partial<Pick<AgentRequest, "system" | "tools" | "messages">>;
102
+ profile?: string;
103
+ }
104
+ export interface TurnEnding {
105
+ /** What the model said last. */
106
+ text: string;
107
+ turn: AgentTurnInfo;
108
+ /** How many times this turn was already kept going. */
109
+ continued: number;
110
+ }
111
+ export interface AgentPolicy {
112
+ id: string;
113
+ /** Runs on tools/pre-execute for calls that belong to an agent run. Throw to refuse; the message reaches the model. */
114
+ before(call: {
115
+ name: string;
116
+ args: unknown;
117
+ by: Author;
118
+ projectId?: string;
119
+ run: RunHandle;
120
+ }, next: () => Promise<unknown>): Promise<unknown>;
121
+ }
122
+ //# sourceMappingURL=hooks.d.ts.map
package/dist/index.d.ts CHANGED
@@ -12,5 +12,10 @@ export { HOUSE_RULES, RULES_INSTRUCTIONS_MAX, RULES_MAX_CHARS, rulesInstructions
12
12
  export { evaluateTurn, summarizeEvaluation, type TurnMetrics, type EvaluationObservation } from "./evaluation.js";
13
13
  export { NO_TOKENS, addTokens, runTokens, type TokenBreakdown } from "./tokens.js";
14
14
  export { carriedKits, deferredTools, kitLines } from "./kits.js";
15
- export { isSuspended, PANEL_SURFACES, type AgentEvent, type AgentPolicy, type AgentRequest, type AgentRequestFailure, type AgentRetry, type AgentTurnInfo, type Block, type CardAction, type CardView, type ChecklistCard, type CliAttempt, type CliHookAnswer, type CliHookCall, type CliHookEvent, type CliCheck, type EngineMcpLink, type McpLinkView, type McpProjectApproval, type CliSource, type Engine, type EngineAvailability, type EngineCapability, type EngineDiagnostics, type EngineCommands, type CommandCheck, type CommandCheckOptions, type EngineNeed, type EnginePick, type EngineView, type EngineTry, type EngineSetup, type FindingCard, type FocusRef, type FollowUpStart, type GeneralExecution, type LocalCliStatus, type OpenDependency, type ParkView, type PendingView, type Playbook, type PlaybookIndexEntry, type PlaybookSource, type RunStatus, type RunView, type Suspended, type ThreadMessage, type ThreadSummary, type ThreadSurface, type TurnEnding, type TurnInput, type TurnFollowUp, type TurnIO, type RetryState, type TurnPurpose, type TurnResult, type UserInput, type WorkflowInfo, type WorkflowIO, type WorkflowQuestion, type WorkflowSpec, type WorkflowTransition } from "./types.js";
15
+ export { type AgentEvent, type Block, type CardAction, type CardView, type ChecklistCard, type FindingCard, type FocusRef, PANEL_SURFACES, type ParkView, type PendingView, type RunStatus, type RunView, type ThreadMessage, type ThreadSummary, type ThreadSurface, type UserInput } from "./thread.js";
16
+ export { type OpenDependency, type RetryState, type TurnInput, type TurnIO, type TurnPurpose, type TurnResult } from "./turn.js";
17
+ export { type FollowUpStart, type GeneralExecution, isSuspended, type Playbook, type PlaybookIndexEntry, type PlaybookSource, type Suspended, type TurnFollowUp, type WorkflowInfo, type WorkflowIO, type WorkflowQuestion, type WorkflowSpec, type WorkflowTransition } from "./workflow.js";
18
+ export { type CliAttempt, type CliCheck, type CliSource, type CommandCheck, type CommandCheckOptions, type Engine, type EngineAvailability, type EngineCapability, type EngineCommands, type EngineDiagnostics, type EngineLocal, type EngineMcpLink, type EngineNeed, type EnginePick, type EngineRegistration, type EngineSetup, type EngineSteering, type EngineTerminal, type EngineTry, type EngineView, type FlatEngineMembers, type LocalCliStatus, type McpLinkView, type McpProjectApproval } from "./engine.js";
19
+ export { type AgentPolicy, type AgentRequest, type AgentRequestFailure, type AgentRetry, type AgentTurnInfo, type CliHookAnswer, type CliHookCall, type CliHookEvent, type TurnEnding } from "./hooks.js";
20
+ export { flatEngineView, normalizeEngine } from "./engine-shape.js";
16
21
  //# sourceMappingURL=index.d.ts.map
package/dist/kits.d.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  import type { ToolDescriptor } from "@tomradex/tools";
2
- import type { ThreadMessage, TurnPurpose } from "./types.js";
2
+ import type { ThreadMessage } from "./thread.js";
3
+ import type { TurnPurpose } from "./turn.js";
3
4
  /** Kits a conversation carries from its first request: a coding session needs its ticket's tools; the rest wait until asked for. */
4
5
  export declare function carriedKits(purpose: TurnPurpose): string[];
5
6
  /**
@@ -1,4 +1,4 @@
1
- import type { TurnIO, TurnInput } from "./types.js";
1
+ import type { TurnIO, TurnInput } from "./turn.js";
2
2
  export declare function attachedMedia(input: TurnInput, io: TurnIO): import("./media.js").MediaContent[];
3
3
  export declare function claudeMediaInput(input: TurnInput, io: TurnIO, text: string): ({
4
4
  type: "document" | "image";
@@ -1,4 +1,4 @@
1
- import type { Playbook, PlaybookIndexEntry, PlaybookSource } from "./types.js";
1
+ import type { Playbook, PlaybookIndexEntry, PlaybookSource } from "./workflow.js";
2
2
  /** Missing capabilities are visible to the caller; recommendations never hide a method. */
3
3
  export declare function missingPlaybookCapabilities(playbook: Pick<Playbook, "requires">, available: readonly string[]): string[];
4
4
  export declare const frontmatter: (raw: string) => {
package/dist/prompt.d.ts CHANGED
@@ -1,4 +1,6 @@
1
- import type { FocusRef, GeneralExecution, OpenDependency, TurnInput, TurnIO } from "./types.js";
1
+ import type { FocusRef } from "./thread.js";
2
+ import type { OpenDependency, TurnInput, TurnIO } from "./turn.js";
3
+ import type { GeneralExecution } from "./workflow.js";
2
4
  /**
3
5
  * The house rules every model-driven engine puts in its system prompt. One
4
6
  * copy on the platform, so a rule changed here reaches loop and CLI engines
@@ -52,13 +54,6 @@ export declare function generalPrompt(input: {
52
54
  filesIndex?: string;
53
55
  rules?: string;
54
56
  }): string;
55
- /**
56
- * The shared tail of a system prompt: the playbook index, the project brief,
57
- * the durable cards, and the waiting workflow. Engines prepend their identity
58
- * and the house rules, then join these with blank lines.
59
- */
60
- /** What the main conversation can do with the code, and where that code is, so a limit is named instead of mistaken for an empty folder. */
61
- export declare function mainConversationSection(repositories: TurnInput["repositories"]): string;
62
57
  export declare function promptSections(input: TurnInput, io: TurnIO, opts?: {
63
58
  playbooks?: boolean;
64
59
  filesIndex?: boolean;
package/dist/recap.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import type { ThreadMessage } from "./types.js";
1
+ import type { ThreadMessage } from "./thread.js";
2
2
  /**
3
3
  * The conversation so far, for an engine that keeps its own session and is
4
4
  * starting a new one on a thread that already has history: its old session is
package/dist/service.d.ts CHANGED
@@ -4,8 +4,12 @@ import { type UndoRunResult } from "@tomradex/domain";
4
4
  import type { SettingsSection } from "@tomradex/settings";
5
5
  import { AgentStore } from "./store.js";
6
6
  import { type MediaRef, type MediaUpload, type MediaContent } from "./media.js";
7
- import { type AgentEvent, type AgentPolicy, type CardView, type Engine, type CliCheck, type McpLinkView, type EngineTry, type EngineView, type FocusRef, type GeneralExecution, type ParkView, type PendingView, type Playbook, type PlaybookIndexEntry, type PlaybookSource, type RunView, type ThreadMessage, type ThreadSummary, type TurnFollowUp, type UserInput, type WorkflowSpec, type ThreadSurface } from "./types.js";
7
+ import type { AgentPolicy } from "./hooks.js";
8
+ import type { CliCheck, Engine, EngineRegistration, EngineTry, EngineView, McpLinkView } from "./engine.js";
9
+ import { type AgentEvent, type CardView, type FocusRef, type ParkView, type PendingView, type RunView, type ThreadMessage, type ThreadSummary, type ThreadSurface, type UserInput } from "./thread.js";
10
+ import { type GeneralExecution, type Playbook, type PlaybookIndexEntry, type PlaybookSource, type TurnFollowUp, type WorkflowSpec } from "./workflow.js";
8
11
  import { type TokenBreakdown } from "./tokens.js";
12
+ import { type AgentReader } from "@tomradex/contracts";
9
13
  /** Where a thread's engine would run, or the one reason it cannot yet. `code` is stable for the renderer to translate. */
10
14
  /** Which of these threads a plugin opened, and what to call that: thread id → label. */
11
15
  export type ThreadOrigins = (projectId: string, threads: ThreadSummary[]) => Iterable<[string, string]>;
@@ -200,7 +204,7 @@ export interface AgentSettings {
200
204
  playbookChoices: Record<string, PlaybookSource>;
201
205
  }
202
206
  export declare const AGENT_SECTION: SettingsSection<AgentSettings>;
203
- export declare class Agent extends Service {
207
+ export declare class Agent extends Service implements AgentReader {
204
208
  readonly config: AgentConfig;
205
209
  static provide: string;
206
210
  static inject: string[];
@@ -237,7 +241,7 @@ export declare class Agent extends Service {
237
241
  answering(id: string): string;
238
242
  /** The engines a person chooses between: none that another engine took in. */
239
243
  allEngines(): Engine[];
240
- engine(engine: Engine): () => void;
244
+ engine(given: EngineRegistration): () => void;
241
245
  /** A plugin names the conversations it opened (thread id → a short label in the person's language). */
242
246
  threadOrigins(provider: ThreadOrigins): () => void;
243
247
  /** The threads with what each plugin says opened them. */
package/dist/store.d.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  import type { Db } from "@tomradex/db";
2
2
  import type { Author } from "@tomradex/domain";
3
- import type { Block, CardView, GeneralExecution, ParkView, PendingView, RunStatus, RunView, ThreadMessage, ThreadSummary, ThreadSurface } from "./types.js";
3
+ import type { Block, CardView, ParkView, PendingView, RunStatus, RunView, ThreadMessage, ThreadSummary, ThreadSurface } from "./thread.js";
4
+ import type { GeneralExecution } from "./workflow.js";
4
5
  export declare const MIGRATIONS: {
5
6
  version: number;
6
7
  up: string;