@turri-dev/cli 0.1.6 → 0.1.7-next.ccadaa0

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 (226) hide show
  1. package/assets/jellyfish/dark-00.png +0 -0
  2. package/assets/jellyfish/dark-01.png +0 -0
  3. package/assets/jellyfish/dark-02.png +0 -0
  4. package/assets/jellyfish/dark-03.png +0 -0
  5. package/assets/jellyfish/dark-04.png +0 -0
  6. package/assets/jellyfish/dark-05.png +0 -0
  7. package/assets/jellyfish/dark-06.png +0 -0
  8. package/assets/jellyfish/dark-07.png +0 -0
  9. package/assets/jellyfish/dark-08.png +0 -0
  10. package/assets/jellyfish/dark-09.png +0 -0
  11. package/assets/jellyfish/dark-10.png +0 -0
  12. package/assets/jellyfish/dark-11.png +0 -0
  13. package/assets/jellyfish/dark-12.png +0 -0
  14. package/assets/jellyfish/dark-13.png +0 -0
  15. package/assets/jellyfish/dark-14.png +0 -0
  16. package/assets/jellyfish/dark-15.png +0 -0
  17. package/assets/jellyfish/dark-16.png +0 -0
  18. package/assets/jellyfish/dark-17.png +0 -0
  19. package/assets/jellyfish/dark-18.png +0 -0
  20. package/assets/jellyfish/dark-19.png +0 -0
  21. package/assets/jellyfish/dark-20.png +0 -0
  22. package/assets/jellyfish/dark-21.png +0 -0
  23. package/assets/jellyfish/dark-22.png +0 -0
  24. package/assets/jellyfish/dark-23.png +0 -0
  25. package/assets/jellyfish/dark-24.png +0 -0
  26. package/assets/jellyfish/dark-25.png +0 -0
  27. package/assets/jellyfish/dark-26.png +0 -0
  28. package/assets/jellyfish/dark-27.png +0 -0
  29. package/assets/jellyfish/dark-28.png +0 -0
  30. package/assets/jellyfish/dark-29.png +0 -0
  31. package/assets/jellyfish/dark-30.png +0 -0
  32. package/assets/jellyfish/dark-31.png +0 -0
  33. package/assets/jellyfish/dark-32.png +0 -0
  34. package/assets/jellyfish/dark-33.png +0 -0
  35. package/assets/jellyfish/dark-34.png +0 -0
  36. package/assets/jellyfish/dark-35.png +0 -0
  37. package/assets/jellyfish/dark-36.png +0 -0
  38. package/assets/jellyfish/dark-37.png +0 -0
  39. package/assets/jellyfish/dark-38.png +0 -0
  40. package/assets/jellyfish/dark-39.png +0 -0
  41. package/assets/jellyfish/dark-40.png +0 -0
  42. package/assets/jellyfish/light-00.png +0 -0
  43. package/assets/jellyfish/light-01.png +0 -0
  44. package/assets/jellyfish/light-02.png +0 -0
  45. package/assets/jellyfish/light-03.png +0 -0
  46. package/assets/jellyfish/light-04.png +0 -0
  47. package/assets/jellyfish/light-05.png +0 -0
  48. package/assets/jellyfish/light-06.png +0 -0
  49. package/assets/jellyfish/light-07.png +0 -0
  50. package/assets/jellyfish/light-08.png +0 -0
  51. package/assets/jellyfish/light-09.png +0 -0
  52. package/assets/jellyfish/light-10.png +0 -0
  53. package/assets/jellyfish/light-11.png +0 -0
  54. package/assets/jellyfish/light-12.png +0 -0
  55. package/assets/jellyfish/light-13.png +0 -0
  56. package/assets/jellyfish/light-14.png +0 -0
  57. package/assets/jellyfish/light-15.png +0 -0
  58. package/assets/jellyfish/light-16.png +0 -0
  59. package/assets/jellyfish/light-17.png +0 -0
  60. package/assets/jellyfish/light-18.png +0 -0
  61. package/assets/jellyfish/light-19.png +0 -0
  62. package/assets/jellyfish/light-20.png +0 -0
  63. package/assets/jellyfish/light-21.png +0 -0
  64. package/assets/jellyfish/light-22.png +0 -0
  65. package/assets/jellyfish/light-23.png +0 -0
  66. package/assets/jellyfish/light-24.png +0 -0
  67. package/assets/jellyfish/light-25.png +0 -0
  68. package/assets/jellyfish/light-26.png +0 -0
  69. package/assets/jellyfish/light-27.png +0 -0
  70. package/assets/jellyfish/light-28.png +0 -0
  71. package/assets/jellyfish/light-29.png +0 -0
  72. package/assets/jellyfish/light-30.png +0 -0
  73. package/assets/jellyfish/light-31.png +0 -0
  74. package/assets/jellyfish/light-32.png +0 -0
  75. package/assets/jellyfish/light-33.png +0 -0
  76. package/assets/jellyfish/light-34.png +0 -0
  77. package/assets/jellyfish/light-35.png +0 -0
  78. package/assets/jellyfish/light-36.png +0 -0
  79. package/assets/jellyfish/light-37.png +0 -0
  80. package/assets/jellyfish/light-38.png +0 -0
  81. package/assets/jellyfish/light-39.png +0 -0
  82. package/assets/jellyfish/light-40.png +0 -0
  83. package/dist/ask.d.ts +83 -0
  84. package/dist/brand.d.ts +13 -0
  85. package/dist/btw.d.ts +67 -0
  86. package/dist/chat-models.d.ts +22 -0
  87. package/dist/chat-skills.d.ts +17 -0
  88. package/dist/cli-options.d.ts +25 -0
  89. package/dist/cli.d.ts +9 -0
  90. package/dist/config-command.d.ts +26 -0
  91. package/dist/config-edit.d.ts +69 -0
  92. package/dist/config.d.ts +321 -0
  93. package/dist/conform-cli.d.ts +1 -0
  94. package/dist/cultivate-cli.d.ts +1 -0
  95. package/dist/drift-cli.d.ts +1 -0
  96. package/dist/environment.d.ts +39 -0
  97. package/dist/extension.d.ts +147 -0
  98. package/dist/extension.js +49 -18
  99. package/dist/genome.d.ts +62 -0
  100. package/dist/graph.d.ts +52 -0
  101. package/dist/host.d.ts +21 -0
  102. package/dist/host.js +25 -0
  103. package/dist/identity.d.ts +2 -0
  104. package/dist/init-config.d.ts +106 -0
  105. package/dist/jellyfish.d.ts +35 -0
  106. package/dist/jellyfish.js +230 -97
  107. package/dist/judge.d.ts +25 -0
  108. package/dist/lineage-cli.d.ts +1 -0
  109. package/dist/loop-cli.d.ts +34 -0
  110. package/dist/loop-tools.d.ts +80 -0
  111. package/dist/mature-tools.d.ts +53 -0
  112. package/dist/model-check.d.ts +42 -0
  113. package/dist/module-report.d.ts +9 -0
  114. package/dist/pi-launch.d.ts +1 -0
  115. package/dist/pi.d.ts +246 -0
  116. package/dist/picture-row.d.ts +10 -0
  117. package/dist/plain/check.d.ts +23 -0
  118. package/dist/plain/concepts.d.ts +11 -0
  119. package/dist/plain/errors.d.ts +22 -0
  120. package/dist/plain/files.d.ts +12 -0
  121. package/dist/plain/highlight.d.ts +42 -0
  122. package/dist/plain/index.d.ts +15 -0
  123. package/dist/plain/liquid.d.ts +22 -0
  124. package/dist/plain/markdown.d.ts +74 -0
  125. package/dist/plain/parser.d.ts +87 -0
  126. package/dist/plain/spec.d.ts +90 -0
  127. package/dist/plain/stdlib.d.ts +14 -0
  128. package/dist/question-dialog.d.ts +51 -0
  129. package/dist/questioning.d.ts +55 -0
  130. package/dist/quiet.d.ts +34 -0
  131. package/dist/regenerate/activity.d.ts +207 -0
  132. package/dist/regenerate/agent-env.d.ts +44 -0
  133. package/dist/regenerate/agent-shell.d.ts +49 -0
  134. package/dist/regenerate/arbiter.d.ts +68 -0
  135. package/dist/regenerate/audit.d.ts +69 -0
  136. package/dist/regenerate/cases.d.ts +9 -0
  137. package/dist/regenerate/change-view.d.ts +18 -0
  138. package/dist/regenerate/choose-conformance.d.ts +32 -0
  139. package/dist/regenerate/chunk-plan.d.ts +164 -0
  140. package/dist/regenerate/codebase.d.ts +21 -0
  141. package/dist/regenerate/command-check.d.ts +40 -0
  142. package/dist/regenerate/compaction.d.ts +13 -0
  143. package/dist/regenerate/confine.d.ts +62 -0
  144. package/dist/regenerate/conform.d.ts +63 -0
  145. package/dist/regenerate/conformance-agents.d.ts +405 -0
  146. package/dist/regenerate/conformance.d.ts +189 -0
  147. package/dist/regenerate/conversation-writes.d.ts +10 -0
  148. package/dist/regenerate/credentials.d.ts +18 -0
  149. package/dist/regenerate/debug-log.d.ts +54 -0
  150. package/dist/regenerate/debugger.d.ts +31 -0
  151. package/dist/regenerate/delivery.d.ts +6 -0
  152. package/dist/regenerate/diagnose-job.d.ts +2 -0
  153. package/dist/regenerate/diagnose.d.ts +46 -0
  154. package/dist/regenerate/diff-view.d.ts +61 -0
  155. package/dist/regenerate/drift.d.ts +84 -0
  156. package/dist/regenerate/engine.d.ts +52 -0
  157. package/dist/regenerate/environment-error.d.ts +136 -0
  158. package/dist/regenerate/job-log.d.ts +28 -0
  159. package/dist/regenerate/job-panel.d.ts +122 -0
  160. package/dist/regenerate/jobs-tree.d.ts +71 -0
  161. package/dist/regenerate/jobs.d.ts +186 -0
  162. package/dist/regenerate/lanes.d.ts +16 -0
  163. package/dist/regenerate/lineage.d.ts +95 -0
  164. package/dist/regenerate/list-arguments.d.ts +21 -0
  165. package/dist/regenerate/loop.d.ts +392 -0
  166. package/dist/regenerate/masking.d.ts +19 -0
  167. package/dist/regenerate/notes.d.ts +159 -0
  168. package/dist/regenerate/os-sandbox.d.ts +89 -0
  169. package/dist/regenerate/panel-dock.d.ts +23 -0
  170. package/dist/regenerate/paths.d.ts +92 -0
  171. package/dist/regenerate/plain-palette.d.ts +34 -0
  172. package/dist/regenerate/prompt.d.ts +192 -0
  173. package/dist/regenerate/records.d.ts +88 -0
  174. package/dist/regenerate/regenerate.d.ts +108 -0
  175. package/dist/regenerate/regression.d.ts +58 -0
  176. package/dist/regenerate/release.d.ts +123 -0
  177. package/dist/regenerate/requires.d.ts +96 -0
  178. package/dist/regenerate/resources.d.ts +53 -0
  179. package/dist/regenerate/self-check.d.ts +29 -0
  180. package/dist/regenerate/services.d.ts +28 -0
  181. package/dist/regenerate/shell.d.ts +91 -0
  182. package/dist/regenerate/side-panel.d.ts +57 -0
  183. package/dist/regenerate/spec-map-view.d.ts +139 -0
  184. package/dist/regenerate/spec-map.d.ts +138 -0
  185. package/dist/regenerate/spec-steps.d.ts +137 -0
  186. package/dist/regenerate/state.d.ts +20 -0
  187. package/dist/regenerate/steer.d.ts +34 -0
  188. package/dist/regenerate/steering.d.ts +56 -0
  189. package/dist/regenerate/stop-report.d.ts +43 -0
  190. package/dist/regenerate/submit-work.d.ts +42 -0
  191. package/dist/regenerate/test-kinds.d.ts +42 -0
  192. package/dist/regenerate/test-scripts.d.ts +221 -0
  193. package/dist/regenerate/testing.d.ts +141 -0
  194. package/dist/regenerate/transcript-view.d.ts +21 -0
  195. package/dist/regenerate/unit-gate.d.ts +27 -0
  196. package/dist/regenerate/unit-review.d.ts +152 -0
  197. package/dist/regenerate/web.d.ts +61 -0
  198. package/dist/regenerate/workspace.d.ts +12 -0
  199. package/dist/regenerate-cli.d.ts +1 -0
  200. package/dist/release-agent.d.ts +26 -0
  201. package/dist/release-cli.d.ts +1 -0
  202. package/dist/release-tools.d.ts +38 -0
  203. package/dist/resume-line.d.ts +2 -0
  204. package/dist/review/live.d.ts +72 -0
  205. package/dist/rules.d.ts +20 -0
  206. package/dist/run-report.d.ts +88 -0
  207. package/dist/screen-padding.d.ts +28 -0
  208. package/dist/self-invocation.d.ts +25 -0
  209. package/dist/setup.d.ts +43 -0
  210. package/dist/skill-progress.d.ts +46 -0
  211. package/dist/skill.d.ts +98 -0
  212. package/dist/skills.d.ts +30 -0
  213. package/dist/spec-diff-cli.d.ts +1 -0
  214. package/dist/spec-tools.d.ts +36 -0
  215. package/dist/stack.d.ts +58 -0
  216. package/dist/stacks.d.ts +12 -0
  217. package/dist/stdlib.d.ts +27 -0
  218. package/dist/terminal-images.d.ts +2 -0
  219. package/dist/tools.d.ts +101 -0
  220. package/dist/validate-cli.d.ts +1 -0
  221. package/docs/README.md +2 -0
  222. package/docs/hosting.md +52 -0
  223. package/docs/images/turri-banner.png +0 -0
  224. package/docs/theming.md +6 -4
  225. package/docs/using.md +1 -1
  226. package/package.json +8 -1
package/dist/pi.d.ts ADDED
@@ -0,0 +1,246 @@
1
+ import { AgentSession, DefaultResourceLoader, ModelRegistry, type ToolDefinition } from "@earendil-works/pi-coding-agent";
2
+ import { type AgentRole } from "./config.ts";
3
+ type ThinkingLevel = Parameters<AgentSession["setThinkingLevel"]>[0];
4
+ /**
5
+ * Where sub-agents take their thinking level from: the conversation that started them.
6
+ *
7
+ * The model is inherited explicitly, by name, all the way down. The thinking level is just
8
+ * as much a choice the person made - and left alone pi falls back to its own default, so a
9
+ * conversation turned down for speed would hand every render agent a slower one. Read at
10
+ * the moment each session starts, so a change mid-conversation applies to the next agent.
11
+ */
12
+ export declare function inheritThinkingLevel(source: () => ThinkingLevel | undefined): void;
13
+ /**
14
+ * How hard an agent thinks: the level the config or the model it is given names; else its role's (ROLE_THINKING) - the
15
+ * work thinks little, the judgement more; else the conversation's, for an agent with no role.
16
+ */
17
+ export declare function agentThinking(named: ThinkingLevel | undefined, role: AgentRole | undefined, conversation: () => ThinkingLevel | undefined): ThinkingLevel | undefined;
18
+ /**
19
+ * Where sub-agents take the providers pi's extensions registered from: the conversation that started them.
20
+ *
21
+ * A sub-agent is started without extensions (see subAgentResources), so its models are only what pi's own
22
+ * configuration has - models.json and auth.json. A provider an extension registers - a company's own LLM
23
+ * gateway, say - is in the conversation's model registry and nowhere else: the conversation could use its
24
+ * models and a render or skill agent told to use them could not find them. So every sub-agent's model
25
+ * runtime is given the providers the conversation's registry holds when the agent starts - the provider,
26
+ * not the extension that registered it.
27
+ */
28
+ export declare function inheritProviders(source: () => ModelRegistry | undefined): void;
29
+ /**
30
+ * What a sub-agent session is made of: pi's resources without any extensions.
31
+ *
32
+ * Left to itself, pi builds every session from the user's configuration - including every
33
+ * installed extension. When turri is installed globally, that means each render agent,
34
+ * judge and skill executor loads a whole second copy of turri inside itself: its
35
+ * tools, its hooks, its job registry, all bound to a session that is thrown away minutes
36
+ * later. That copy then outlives its session in module state and breaks the next one. A
37
+ * sub-agent is given exactly what it needs instead; for agents that work on specs, that
38
+ * includes the ***plain rules, which otherwise only reached them through that stray copy.
39
+ *
40
+ * Nor any context file. pi puts every AGENTS.md / CLAUDE.md from the agent's folder up - the
41
+ * project's, the user's ~/.pi/agent one - into its system prompt; a rendering agent works in
42
+ * plain_modules/<module>/code, so it would be given whatever the project says about itself. An
43
+ * agent turri starts sees only what turri gives it. The conversation still loads
44
+ * them, as pi does.
45
+ *
46
+ * Nor any of pi's skills. pi lists every skill it finds - the user's, the project's - in the system prompt, for the
47
+ * agent to load when one fits; an agent turri starts has one job, and turri runs its gated skills itself,
48
+ * giving each step to an agent as its task. The conversation keeps them.
49
+ */
50
+ export declare function subAgentResources(cwd: string, withRules: boolean, system?: string): Promise<DefaultResourceLoader>;
51
+ /** Raised when the provider itself failed, rather than the agent producing a poor answer. */
52
+ export declare class ProviderError extends Error {
53
+ constructor(message: string);
54
+ }
55
+ /**
56
+ * End the agent's turn, turri's own doing - it is going round in a circle, its time is up. The turn ends as any turn
57
+ * does: what the agent said stands, and the harness goes on from there. Never a provider error.
58
+ */
59
+ export declare function stopTurn(session: AgentSession | undefined, reason: string): void;
60
+ /** A turn with one thing left to do: every tool but these is refused, the tools the session has left as they are. */
61
+ export interface TurnOptions {
62
+ onlyTools?: string[];
63
+ }
64
+ /** How many calls a restricted turn may have refused before it is stopped. */
65
+ export declare const REFUSED_BEFORE_STOP = 3;
66
+ /**
67
+ * `run`, with every tool of the session but `names` refused (guardRepeats refuses them) until it ends. The tools
68
+ * themselves are left as they are, so the tools the model is sent - and its prompt cache - stay the same.
69
+ */
70
+ export declare function withOnlyTools<T>(session: AgentSession, names: string[], run: () => Promise<T>): Promise<T>;
71
+ export declare function ask(session: AgentSession, text: string, onDelta?: (delta: string) => void, turn?: TurnOptions): Promise<string>;
72
+ /**
73
+ * How many times, after pi's own retries, a turn whose provider failed for a moment is tried again; the first wait,
74
+ * doubled each time up to the longest - 15s, 30s, 1m, 2m, 4m, 5m: an outage of about 13 minutes is waited out.
75
+ */
76
+ export declare const PROVIDER_RETRIES = 6;
77
+ export declare const PROVIDER_RETRY_DELAY_MS: number;
78
+ export declare const PROVIDER_RETRY_MAX_DELAY_MS: number;
79
+ /** The wait before try `attempt + 1`: doubled each time, up to the longest, with a tenth either way so parallel jobs do not all come back at once. */
80
+ export declare function providerRetryDelay(attempt: number, random?: () => number): number;
81
+ /** How long a request to the model may go without anything coming back before the provider is said to be stalling; 0 never. */
82
+ export declare const PROVIDER_STALL_MS: number;
83
+ /**
84
+ * How long one turn of an agent a render starts may take: past it, the turn ends where it is and
85
+ * the harness goes on as after any turn - it runs the tests, and judges. The config's `turn-limit:`
86
+ * sets it, in seconds, and each role's in `models:`; 0 turns it off.
87
+ */
88
+ export declare const DEFAULT_TURN_LIMIT_MS: number;
89
+ /** How long past the turn limit what is running then - the model answering, a tool - may take to finish. */
90
+ export declare const TURN_GRACE_MS: number;
91
+ /** An image an agent is sent with a message. */
92
+ export interface AgentImage {
93
+ type: "image";
94
+ data: string;
95
+ mimeType: string;
96
+ }
97
+ /**
98
+ * Refuses, before any agent of a job starts, a named model that reads no images when the job's spec links some -
99
+ * rather than once the work is under way. Unnamed, the model is pi's default: `createExecutor` refuses it then.
100
+ */
101
+ export declare function refuseIfModelIsBlind(modelSpec: string | undefined, count: number): Promise<void>;
102
+ /** A model that cannot read images, given images to read. */
103
+ export declare class ModelCannotReadImagesError extends Error {
104
+ }
105
+ /**
106
+ * Stops an agent whose model reads no images being given some: it would work blind from the spec's images. Says
107
+ * which model, and what to do - a coding model that reads images, or the images described in text instead.
108
+ */
109
+ export declare function refuseIfBlind(model: {
110
+ provider: string;
111
+ id: string;
112
+ input?: readonly string[];
113
+ } | undefined, count: number): void;
114
+ /**
115
+ * What an agent opens with when its task is in its instructions. The task - the spec, how to read it, what to do
116
+ * and the rules - is its system prompt, not its first message: compaction sums up the conversation and never the
117
+ * system prompt, so what the agent works from stays word for word as it was, however long the work runs, and stays
118
+ * in the cached prefix of every call.
119
+ */
120
+ export declare const BEGIN = "Begin. Your task is in your instructions.";
121
+ /** How a session's work is summed up when it gets larger than the threshold: what the summary has to keep, for its role. */
122
+ export interface Compaction {
123
+ instructions: string;
124
+ /** Tokens of conversation - past the system prompt - past which it is compacted. Default: the project's compact-at, else DEFAULT_COMPACT_AT. */
125
+ atTokens?: number;
126
+ }
127
+ /** Tokens of conversation past which a session that keeps working is compacted, when the project does not say. */
128
+ export declare const DEFAULT_COMPACT_AT = 100000;
129
+ /** Have a session compacted between turns, as `compaction` says: what createExecutor does for an agent given one. */
130
+ export declare function keepCompacted(session: object, compaction: Required<Compaction>): void;
131
+ /**
132
+ * Compact a session's work when its conversation - what it has done, not its instructions - has got larger than its
133
+ * threshold. An agent that keeps its session through a job re-reads everything it did on every call: this keeps
134
+ * that bounded, as pi's own compaction does only when the context window is nearly full. The summary keeps what
135
+ * its role needs; its instructions are untouched. A compaction that fails leaves the session as it was.
136
+ */
137
+ export declare function compactIfDue(session: AgentSession): Promise<boolean>;
138
+ /**
139
+ * Have this session's turns timed, as an agent a render starts has: `limitMs` each - its role's in the config - or
140
+ * the default.
141
+ */
142
+ export declare function timeTurns(session: object, limitMs?: number): void;
143
+ /** How many calls to one tool may fail in a row, nothing going through, before the agent's turn is stopped. */
144
+ export declare const FAILURES_BEFORE_STOP = 10;
145
+ /** How many times running the very same tool call is let through before it is refused, and before the turn is stopped. */
146
+ export declare const REPEATS_ALLOWED = 3;
147
+ export declare const REPEATS_BEFORE_STOP = 6;
148
+ /** JSON with every object's keys in order, so two ways of writing the same arguments read the same. */
149
+ export declare function canonicalJson(value: unknown): string;
150
+ /** How many tool calls an agent that has one thing to decide may make before it is told to decide. */
151
+ export interface CallBudget {
152
+ calls: number;
153
+ /** The tools that hand over the decision - still let through past the budget. */
154
+ finish: string[];
155
+ }
156
+ /**
157
+ * Tools that notice an agent going round in a circle. The same call again and again with nothing in
158
+ * between; or a look - read, grep, find, ls - made again with nothing changed since, however many
159
+ * other looks came between: the same answer comes back. The first few go through; after that the
160
+ * call is refused with what is happening, and if the agent carries on regardless its turn is
161
+ * stopped - the harness goes on from there, as after any turn.
162
+ *
163
+ * With a budget, an agent that has one thing to decide - a verdict, a review, an account - is told
164
+ * to decide once it has made that many calls: every tool but the one that hands it over refuses,
165
+ * and past twice the budget its turn is stopped. Handing it over starts the count again, and forgets
166
+ * the looks: a reviewer kept for the next review reads the files as they are by then.
167
+ */
168
+ export declare function guardRepeats(tools: ToolDefinition[], session: () => AgentSession | undefined, budget?: CallBudget): ToolDefinition[];
169
+ /**
170
+ * The executor. One session for the whole skill run, so a retry after a failed
171
+ * gate arrives as a follow-up turn with the critique in it rather than as a cold
172
+ * start that has forgotten what it just wrote.
173
+ */
174
+ export declare function createExecutor(opts: {
175
+ cwd: string;
176
+ customTools: ToolDefinition[];
177
+ tools: string[];
178
+ /**
179
+ * "provider/model-id", with ":level" for how hard it thinks ("google/gemini-3.1-pro:high"), or
180
+ * ":level" alone for pi's default model. Omitted: whatever pi is configured to use.
181
+ */
182
+ model?: string;
183
+ /** Give it the ***plain rules - for agents that write or edit specs, not code. */
184
+ rules?: boolean;
185
+ /** Continue the session saved in this file, instead of starting a new one. */
186
+ resumeFrom?: string;
187
+ /** Added to its system prompt: its sandbox, above all - what it can reach (see confine.ts sandboxNote). */
188
+ system?: string;
189
+ /**
190
+ * Its task - everything its first prompt used to say: the spec, how to read it, what to do, the rules. It goes
191
+ * into its system prompt, after `system`, so compaction never sums it up; open the session with BEGIN.
192
+ */
193
+ task?: string;
194
+ /** Given, the session keeps working through a job and is compacted between turns once its work gets larger than the threshold. */
195
+ compaction?: Compaction;
196
+ /**
197
+ * What the agent is, e.g. "app 3 coding agent". Given, the agent is one a render started: its
198
+ * whole conversation is streamed to a log named after it (see debug-log.ts).
199
+ */
200
+ label?: string;
201
+ /** For an agent with one thing to decide: how many tool calls it has, and the tools that hand the decision over. */
202
+ budget?: CallBudget;
203
+ /**
204
+ * Images its task refers to - the spec's linked images. Sent with its first message, and again after each
205
+ * compaction, which sums them up with the rest. A model that cannot read images is refused, before any work.
206
+ */
207
+ images?: AgentImage[];
208
+ /**
209
+ * For an agent that writes and runs code: the harness's own run of the testing script, which an environment report it
210
+ * makes is checked against before the pulse stops (checkAgainstScript). Only an agent given it has
211
+ * report_environment_error at all.
212
+ */
213
+ checkEnvironment?: {
214
+ run: () => Promise<{
215
+ exitCode: number;
216
+ output: string;
217
+ }>;
218
+ script: string;
219
+ };
220
+ /**
221
+ * What the agent does: its role's model, thinking and turn limit in the config (`models:`) apply - the model over
222
+ * `model`, unless the config names none for the role.
223
+ */
224
+ role?: AgentRole;
225
+ }): Promise<AgentSession>;
226
+ /** A provider request with its thinking level sent as reasoning effort, where the model takes one turri sends itself. */
227
+ export declare function withReasoningEffort(payload: unknown, model: unknown, thinkingLevel: string | undefined): unknown;
228
+ /**
229
+ * A judge. Fresh session, one tool, and - deliberately - no access to the
230
+ * executor's transcript. A judge that inherits the actor's reasoning inherits
231
+ * its rationalisations, so it gets the artifact and the rubric, nothing else.
232
+ */
233
+ export declare function createJudge(opts: {
234
+ cwd: string;
235
+ verdictTool: ToolDefinition;
236
+ modelSpec?: string;
237
+ borrowAuthFrom: AgentSession;
238
+ /** Read-only tools the rubric needs. Empty keeps the judge unable to touch anything. */
239
+ extraTools?: string[];
240
+ /** What it judges and by which rubric: its instructions, as an executor's task is. Open the session with BEGIN. */
241
+ task?: string;
242
+ }): Promise<{
243
+ session: AgentSession;
244
+ modelNote: string;
245
+ }>;
246
+ export {};
@@ -0,0 +1,10 @@
1
+ /** What the banner puts between a row's text and the picture after it: back to the jellyfish's column, a column in from the screen's padding. */
2
+ export declare const PICTURE_AT: string;
3
+ /**
4
+ * The banner's picture row with an overlay drawn over its text, the picture after it - left out while the overlay
5
+ * reaches over the picture, `pictureRight` columns from the left edge. Undefined for a row that holds no picture.
6
+ *
7
+ * What follows the picture - the padding a row narrower than the screen is given, the chat's beside the docked panel -
8
+ * is the row's text: written after the picture, from the picture's column, it would blank the row.
9
+ */
10
+ export declare function overPictureRow(base: string, overlay: string, col: number, width: number, total: number, pictureRight: number): string | undefined;
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Static validation of a .plain file, using this repo's own parser.
3
+ *
4
+ * This is the check that used to mean running the renderer with `--dry-run`: it parses the
5
+ * specification, resolves its imports and required modules, and reports every error the
6
+ * parser can see without generating anything. Nothing is rendered and nothing is spent.
7
+ */
8
+ export interface CheckResult {
9
+ file: string;
10
+ ok: boolean;
11
+ moduleName?: string;
12
+ frids?: string[];
13
+ requiredModules?: string[];
14
+ /** The parser's own message, verbatim - it names the line and the construct. */
15
+ error?: string;
16
+ errorType?: string;
17
+ }
18
+ export declare function checkPlainFile(file: string, templateDirs?: string[]): CheckResult;
19
+ /** Every `.plain` file directly in a directory, or the single file given. */
20
+ export declare function resolvePlainTargets(target: string): string[];
21
+ export declare function checkPlainTargets(target: string, templateDirs?: string[]): CheckResult[];
22
+ /** One line per file, plus the parser's message under any that failed. */
23
+ export declare function formatCheckResults(results: CheckResult[]): string;
@@ -0,0 +1,11 @@
1
+ import { type AnyNode, type Section } from "./markdown.ts";
2
+ import { type MarshalledPlainSource, type SpecificationItem } from "./spec.ts";
3
+ /** Port of concept_utils.py. */
4
+ /** Reserved concept names that must not be redefined in the definitions section. */
5
+ export declare const DEFAULT_CONCEPTS: Set<string>;
6
+ export declare function extractConceptsFromDefinition(text: string): [string[], string[]];
7
+ export declare function extractConceptsFromSpecText(text: string): string[];
8
+ export declare function collectConcepts(plainSource: MarshalledPlainSource): [string[], string[]];
9
+ export declare function validateConcepts(marshalled: MarshalledPlainSource): string[];
10
+ export declare function findConceptDefinitionsInPlainSource(concept: string, definitions: Section | null): AnyNode[];
11
+ export declare function sortDefinitions(definitions: SpecificationItem[]): void;
@@ -0,0 +1,22 @@
1
+ /** Ports of the exception classes of the Python reference implementation that this parser raises. */
2
+ export declare class PlainSyntaxError extends Error {
3
+ constructor(message: string);
4
+ }
5
+ export declare class UnsupportedBase64Content extends Error {
6
+ constructor(message: string);
7
+ }
8
+ export declare class ModuleDoesNotExistError extends Error {
9
+ constructor(message: string);
10
+ }
11
+ export declare class MissingFunctionalitiesError extends Error {
12
+ constructor(message: string);
13
+ }
14
+ export declare class ImportedModuleWithFunctionalitiesError extends Error {
15
+ constructor(message: string);
16
+ }
17
+ export declare class InvalidFridArgument extends Error {
18
+ constructor(message: string);
19
+ }
20
+ export declare class InvalidLiquidVariableName extends Error {
21
+ constructor(message: string);
22
+ }
@@ -0,0 +1,12 @@
1
+ /** Ports of the Python reference implementation's file helpers this parser needs. */
2
+ export declare function openFrom(dirs: string[], fileName: string): string | null;
3
+ /** First contiguous base64 blob at or above the threshold, or null. */
4
+ export declare function findLargeBase64Blob(text: string): string | null;
5
+ /**
6
+ * Render once against the filesystem to discover which templates the source pulls in.
7
+ *
8
+ * The rendered text is discarded by the caller; what matters is the map of template
9
+ * name to raw source, which is what the second (real) render is given so that it does
10
+ * not touch the filesystem again.
11
+ */
12
+ export declare function getLoadedTemplates(templateDirs: string[], plainSource: string): [string, Record<string, string>];
@@ -0,0 +1,42 @@
1
+ /** A rule, read: its expression compiled, its includes followed. */
2
+ type Rule = {
3
+ kind: "match";
4
+ name?: string;
5
+ re: RegExp;
6
+ captures?: Record<string, string | undefined>;
7
+ } | {
8
+ kind: "block";
9
+ name?: string;
10
+ begin: RegExp;
11
+ end: RegExp;
12
+ patterns: Rule[];
13
+ beginCaptures?: Record<string, string | undefined>;
14
+ endCaptures?: Record<string, string | undefined>;
15
+ };
16
+ /** A piece of a line, and the scopes it is in, outermost first. */
17
+ export interface Token {
18
+ text: string;
19
+ scopes: string[];
20
+ }
21
+ /** Where the lines so far leave off: the blocks open at the end of the last one. */
22
+ export type HighlightState = ReadonlyArray<Extract<Rule, {
23
+ kind: "block";
24
+ }>>;
25
+ /**
26
+ * One line of ***plain, highlighted: its tokens, and the state the next line starts from - the blocks
27
+ * still open at its end.
28
+ */
29
+ export declare function highlightLine(line: string, state?: HighlightState): {
30
+ tokens: Token[];
31
+ state: HighlightState;
32
+ };
33
+ /** Lines of ***plain, highlighted one after another - a block opened on one carried to the next. */
34
+ export declare function highlightLines(lines: string[]): Token[][];
35
+ /**
36
+ * What a piece of ***plain is, for its colour: a section's header, a concept, a link, text in quotes or
37
+ * backticks, a front matter key, a module a front matter names, a comment, a list's bullet.
38
+ */
39
+ export type PlainRole = "section" | "concept" | "link" | "literal" | "keyword" | "module" | "comment" | "bullet";
40
+ /** A token's role: its innermost scope that has one. */
41
+ export declare function roleOf(scopes: string[]): PlainRole | undefined;
42
+ export {};
@@ -0,0 +1,15 @@
1
+ /**
2
+ * The ***plain*** parser: a TypeScript port of the reference implementation.
3
+ *
4
+ * Mirrors plain_file.py, plain_spec.py, concept_utils.py and the file_utils.py
5
+ * helpers they depend on. The entry points are `plainFileParser` (a .plain file to a
6
+ * marshalled tree) and `iterateFunctionalSpecs` (the tree to one rendering context per
7
+ * functionality).
8
+ */
9
+ export * from "./errors.ts";
10
+ export * from "./markdown.ts";
11
+ export * from "./concepts.ts";
12
+ export * from "./files.ts";
13
+ export * from "./liquid.ts";
14
+ export * from "./parser.ts";
15
+ export * from "./spec.ts";
@@ -0,0 +1,22 @@
1
+ import { Liquid } from "liquidjs";
2
+ /**
3
+ * The Liquid layer: liquid2's Environment plus the project's customisations
4
+ * (the reference implementation's include tag and the two filters in plain_spec).
5
+ *
6
+ * Two behaviours matter and neither is stock Liquid:
7
+ *
8
+ * - An include inherits the indentation of the line it sits on, so a multi-line
9
+ * template dropped into a nested list item stays inside that item.
10
+ * - An include on a `>` comment line is not expanded; the tag is written back out
11
+ * verbatim, because comment lines are stripped later as block quotes.
12
+ */
13
+ export type LoadTemplateSource = (name: string) => string | null;
14
+ export interface PlainLiquidOptions {
15
+ loadTemplateSource: LoadTemplateSource;
16
+ /** Populated by the code_variable filter; absent means the filter is a pass-through. */
17
+ codeVariables?: Record<string, Record<string, string>>;
18
+ strictVariables?: boolean;
19
+ }
20
+ export declare function createEnvironment(options: PlainLiquidOptions): Liquid;
21
+ /** Port of plain_file.render_plain_source. */
22
+ export declare function renderPlainSource(plainSource: string, loadedTemplates: Record<string, string>, codeVariables: Record<string, Record<string, string>>): string;
@@ -0,0 +1,74 @@
1
+ /**
2
+ * The markdown layer.
3
+ *
4
+ * The Python parser leans on mistletoe for two things: an AST with line numbers,
5
+ * and a MarkdownRenderer that round-trips a token back to markdown. mdast gives
6
+ * us the first. The second is `renderToMarkdown` below - a serializer for the
7
+ * subset of markdown the plain language uses, matching mistletoe's output
8
+ * (source indentation preserved, links rewritten as `[resource]` spans).
9
+ */
10
+ export declare const RESOURCE_MARKER = "[resource]";
11
+ /** Extra fields the parser hangs off AST nodes, as the Python code hangs them off tokens. */
12
+ export interface PlainAnnotations {
13
+ acceptance_tests?: AnyNode[];
14
+ linked_resources?: LinkedResource[];
15
+ /** Set when `value` holds the original source slice rather than mdast's decoded text. */
16
+ raw?: boolean;
17
+ openDelimiter?: string;
18
+ closeDelimiter?: string;
19
+ /** List item geometry, in mistletoe's parent-stripped coordinates. */
20
+ leader?: string;
21
+ indentation?: number;
22
+ prepend?: number;
23
+ }
24
+ export interface LinkedResource {
25
+ text: string;
26
+ target: string;
27
+ }
28
+ /**
29
+ * A structural view of an mdast node. The mdast union types do not narrow well when
30
+ * the parser hangs its own fields off nodes, so the AST is handled structurally -
31
+ * every real mdast node satisfies this shape.
32
+ */
33
+ export interface AnyNode extends PlainAnnotations {
34
+ type: string;
35
+ value?: string;
36
+ children?: AnyNode[];
37
+ position?: {
38
+ start: {
39
+ line: number;
40
+ column: number;
41
+ offset?: number;
42
+ };
43
+ end: {
44
+ line: number;
45
+ column: number;
46
+ offset?: number;
47
+ };
48
+ };
49
+ [key: string]: unknown;
50
+ }
51
+ export type Root = AnyNode;
52
+ /** A parsed specification section: mistletoe's `Document` holding a flat list of list items. */
53
+ export interface Section {
54
+ children: AnyNode[];
55
+ }
56
+ /**
57
+ * Parse markdown, then pin every inline node back to its original source text.
58
+ *
59
+ * mdast decodes inline syntax: `\"` becomes `"`, and an emphasis written with `_`
60
+ * loses the fact that it was not `*`. mistletoe's MarkdownRenderer round-trips the
61
+ * source instead, so re-serialising a decoded tree drifts from the Python output.
62
+ * Recording the raw slice for leaf nodes and the real delimiters for emphasis and
63
+ * strong keeps the two renderers in agreement.
64
+ */
65
+ export declare function parseMarkdown(text: string): Root;
66
+ export declare function lineNumber(node: AnyNode): number;
67
+ /** Port of plain_file.remove_quotes: block quotes are comments and are dropped. */
68
+ export declare function removeQuotes(node: AnyNode): void;
69
+ /** Port of plain_file.get_raw_text. */
70
+ export declare function getRawText(node: AnyNode): string;
71
+ /** Port of mistletoe.utils.traverse restricted to a node type. */
72
+ export declare function traverse(node: AnyNode, type: string): AnyNode[];
73
+ /** Port of PlainRenderer.render. */
74
+ export declare function renderToMarkdown(node: AnyNode): string;
@@ -0,0 +1,87 @@
1
+ import { type AnyNode, type Section } from "./markdown.ts";
2
+ import { type MarshalledPlainSource, type SpecificationItem } from "./spec.ts";
3
+ export declare const IMPORT_DIRECTIVE = "import";
4
+ export declare const REQUIRES_DIRECTIVE = "requires";
5
+ export declare const REQUIRED_CONCEPTS_DIRECTIVE = "required_concepts";
6
+ export declare const EXPORTED_CONCEPTS_DIRECTIVE = "exported_concepts";
7
+ export declare const PLAIN_SOURCE_FILE_EXTENSION = ".plain";
8
+ /** definitions / implementation reqs / test reqs always exist as keys; functional specs does not. */
9
+ export type ParsedPlainSource = Record<string, Section | null | undefined>;
10
+ export interface FrontmatterPost {
11
+ metadata: Record<string, unknown>;
12
+ content: string;
13
+ }
14
+ export interface PlainFileParseResult {
15
+ plainSource: ParsedPlainSource;
16
+ plainSourceObj: FrontmatterPost;
17
+ requiredModules: string[];
18
+ requiredConcepts: string[];
19
+ }
20
+ export declare function getFilenameFromModuleName(moduleName: string): string;
21
+ export declare function getModuleNameFromFilename(filename: string): string;
22
+ export declare function checkSectionForLinkedResources(section: AnyNode, dirs?: string[]): void;
23
+ export declare function checkForLinkedResources(plainSource: ParsedPlainSource, dirs?: string[]): void;
24
+ export declare function processSectionCodeVariables(section: SpecificationItem, codeVariables: Record<string, Record<string, string>>): void;
25
+ export declare function processCodeVariables(marshalled: MarshalledPlainSource, codeVariables: Record<string, Record<string, string>>): void;
26
+ /** Whether the module declares a ***functional specs*** section (even if it is empty). */
27
+ export declare function hasFunctionalSpecsSection(plainSource: ParsedPlainSource): boolean;
28
+ /** Number of functionalities under ***functional specs*** (0 if absent or empty). */
29
+ export declare function countFunctionalities(plainSource: ParsedPlainSource): number;
30
+ export declare function validateFunctionalitiesHaveImplementationReqs(plainSource: ParsedPlainSource, moduleName: string, hasRequires?: boolean): void;
31
+ /**
32
+ * Is this token an `acceptance tests` heading?
33
+ *
34
+ * True only for a paragraph holding exactly one emphasis, holding exactly one strong,
35
+ * holding exactly one text node whose content is the heading. Anything that looks like
36
+ * a heading but reads differently comes back as a problem string rather than false, so
37
+ * the caller can reject a near miss instead of silently keeping it.
38
+ */
39
+ export declare function isAcceptanceTestHeading(token: AnyNode): [boolean, string | null];
40
+ /** Find an acceptance tests heading anywhere in a subtree. */
41
+ export declare function findAcceptanceTestHeading(token: AnyNode): AnyNode | null;
42
+ /**
43
+ * Pull the acceptance tests out of one functionality.
44
+ *
45
+ * A functionality with acceptance tests has three children: its own text, the
46
+ * `***acceptance tests***` heading, and the list of tests. The heading and list are
47
+ * lifted onto `acceptance_tests` and removed from the children.
48
+ */
49
+ export declare function processSingleAcceptanceTestRequirement(functionalRequirement: AnyNode): void;
50
+ export declare function processAcceptanceTests(plainSource: ParsedPlainSource): void;
51
+ export declare function marshallPlainSource(input: ParsedPlainSource): MarshalledPlainSource;
52
+ export declare function normalizeLineEndings(plainSourceText: string): string;
53
+ /**
54
+ * Frontmatter parsing strips leading blank lines, which would shift every reported
55
+ * line number. Put them back so syntax errors point at the real line.
56
+ */
57
+ export declare function restoreStrippedLines(plainSourceText: string, content: string): string;
58
+ export declare function readPlainSourceMetadata(plainSourceText: string): FrontmatterPost;
59
+ export declare function parsePlainSource(plainSourceText: string, codeVariables: Record<string, Record<string, string>>, templateDirs: string[], importedModules: string[], modulesTrace: string[]): PlainFileParseResult;
60
+ export declare function readModulePlainSource(moduleName: string, templateDirs: string[]): string;
61
+ export declare function parsePlainFile(moduleName: string, codeVariables: Record<string, Record<string, string>>, templateDirs: string[], importedModules: string[], modulesTrace: string[]): PlainFileParseResult;
62
+ export declare function processRequiredModules(requiredModules: string[], codeVariables: Record<string, Record<string, string>>, templateDirs: string[], allRequiredModules: string[], modulesTrace: string[]): AnyNode[];
63
+ export declare function processExportedDefinitions(plainSource: ParsedPlainSource, exportedDefinitions: AnyNode[]): void;
64
+ /**
65
+ * Parse a .plain file into the marshalled tree.
66
+ *
67
+ * Returns the module name, the tree, and the modules it requires.
68
+ */
69
+ export interface ParseOptions {
70
+ /**
71
+ * Accept a module with no functional specs yet. Not renderable one functionality at a
72
+ * time - there is none - but a spec change can already be built from it: a module whose
73
+ * product interview has so far given it definitions and reqs.
74
+ */
75
+ allowNoFunctionalities?: boolean;
76
+ }
77
+ export declare function plainFileParser(plainSourceFileName: string, templateDirs: string[], options?: ParseOptions): [string, MarshalledPlainSource, string[]];
78
+ /**
79
+ * One parse per file for the length of `run`, however many times it is asked for.
80
+ *
81
+ * Walking a requires chain parses each module in it, and each parse gathers what it inherits
82
+ * by parsing the modules below - so looking across a project of long chains asks for the
83
+ * same files thousands of times. Inside `run` they are parsed once. Outside it nothing is
84
+ * kept, so an edit made between two calls is always seen: the cache is for one question
85
+ * about the specs, not for the life of the process.
86
+ */
87
+ export declare function withParseCache<T>(run: () => T): T;