@turri-dev/cli 0.1.6 → 0.1.7-next.8f13f3a
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 +1 -3
- package/assets/jellyfish/dark-00.png +0 -0
- package/assets/jellyfish/dark-01.png +0 -0
- package/assets/jellyfish/dark-02.png +0 -0
- package/assets/jellyfish/dark-03.png +0 -0
- package/assets/jellyfish/dark-04.png +0 -0
- package/assets/jellyfish/dark-05.png +0 -0
- package/assets/jellyfish/dark-06.png +0 -0
- package/assets/jellyfish/dark-07.png +0 -0
- package/assets/jellyfish/dark-08.png +0 -0
- package/assets/jellyfish/dark-09.png +0 -0
- package/assets/jellyfish/dark-10.png +0 -0
- package/assets/jellyfish/dark-11.png +0 -0
- package/assets/jellyfish/dark-12.png +0 -0
- package/assets/jellyfish/dark-13.png +0 -0
- package/assets/jellyfish/dark-14.png +0 -0
- package/assets/jellyfish/dark-15.png +0 -0
- package/assets/jellyfish/dark-16.png +0 -0
- package/assets/jellyfish/dark-17.png +0 -0
- package/assets/jellyfish/dark-18.png +0 -0
- package/assets/jellyfish/dark-19.png +0 -0
- package/assets/jellyfish/dark-20.png +0 -0
- package/assets/jellyfish/dark-21.png +0 -0
- package/assets/jellyfish/dark-22.png +0 -0
- package/assets/jellyfish/dark-23.png +0 -0
- package/assets/jellyfish/dark-24.png +0 -0
- package/assets/jellyfish/dark-25.png +0 -0
- package/assets/jellyfish/dark-26.png +0 -0
- package/assets/jellyfish/dark-27.png +0 -0
- package/assets/jellyfish/dark-28.png +0 -0
- package/assets/jellyfish/dark-29.png +0 -0
- package/assets/jellyfish/dark-30.png +0 -0
- package/assets/jellyfish/dark-31.png +0 -0
- package/assets/jellyfish/dark-32.png +0 -0
- package/assets/jellyfish/dark-33.png +0 -0
- package/assets/jellyfish/dark-34.png +0 -0
- package/assets/jellyfish/dark-35.png +0 -0
- package/assets/jellyfish/dark-36.png +0 -0
- package/assets/jellyfish/dark-37.png +0 -0
- package/assets/jellyfish/dark-38.png +0 -0
- package/assets/jellyfish/dark-39.png +0 -0
- package/assets/jellyfish/dark-40.png +0 -0
- package/assets/jellyfish/light-00.png +0 -0
- package/assets/jellyfish/light-01.png +0 -0
- package/assets/jellyfish/light-02.png +0 -0
- package/assets/jellyfish/light-03.png +0 -0
- package/assets/jellyfish/light-04.png +0 -0
- package/assets/jellyfish/light-05.png +0 -0
- package/assets/jellyfish/light-06.png +0 -0
- package/assets/jellyfish/light-07.png +0 -0
- package/assets/jellyfish/light-08.png +0 -0
- package/assets/jellyfish/light-09.png +0 -0
- package/assets/jellyfish/light-10.png +0 -0
- package/assets/jellyfish/light-11.png +0 -0
- package/assets/jellyfish/light-12.png +0 -0
- package/assets/jellyfish/light-13.png +0 -0
- package/assets/jellyfish/light-14.png +0 -0
- package/assets/jellyfish/light-15.png +0 -0
- package/assets/jellyfish/light-16.png +0 -0
- package/assets/jellyfish/light-17.png +0 -0
- package/assets/jellyfish/light-18.png +0 -0
- package/assets/jellyfish/light-19.png +0 -0
- package/assets/jellyfish/light-20.png +0 -0
- package/assets/jellyfish/light-21.png +0 -0
- package/assets/jellyfish/light-22.png +0 -0
- package/assets/jellyfish/light-23.png +0 -0
- package/assets/jellyfish/light-24.png +0 -0
- package/assets/jellyfish/light-25.png +0 -0
- package/assets/jellyfish/light-26.png +0 -0
- package/assets/jellyfish/light-27.png +0 -0
- package/assets/jellyfish/light-28.png +0 -0
- package/assets/jellyfish/light-29.png +0 -0
- package/assets/jellyfish/light-30.png +0 -0
- package/assets/jellyfish/light-31.png +0 -0
- package/assets/jellyfish/light-32.png +0 -0
- package/assets/jellyfish/light-33.png +0 -0
- package/assets/jellyfish/light-34.png +0 -0
- package/assets/jellyfish/light-35.png +0 -0
- package/assets/jellyfish/light-36.png +0 -0
- package/assets/jellyfish/light-37.png +0 -0
- package/assets/jellyfish/light-38.png +0 -0
- package/assets/jellyfish/light-39.png +0 -0
- package/assets/jellyfish/light-40.png +0 -0
- package/dist/ask.d.ts +83 -0
- package/dist/brand.d.ts +13 -0
- package/dist/btw.d.ts +67 -0
- package/dist/chat-models.d.ts +22 -0
- package/dist/chat-skills.d.ts +17 -0
- package/dist/cli-options.d.ts +25 -0
- package/dist/cli.d.ts +9 -0
- package/dist/config-command.d.ts +26 -0
- package/dist/config-edit.d.ts +69 -0
- package/dist/config.d.ts +321 -0
- package/dist/conform-cli.d.ts +1 -0
- package/dist/cultivate-cli.d.ts +1 -0
- package/dist/drift-cli.d.ts +1 -0
- package/dist/environment.d.ts +39 -0
- package/dist/extension.d.ts +147 -0
- package/dist/extension.js +49 -18
- package/dist/genome.d.ts +62 -0
- package/dist/graph.d.ts +52 -0
- package/dist/host.d.ts +21 -0
- package/dist/host.js +25 -0
- package/dist/identity.d.ts +2 -0
- package/dist/init-config.d.ts +106 -0
- package/dist/jellyfish.d.ts +35 -0
- package/dist/jellyfish.js +230 -97
- package/dist/judge.d.ts +25 -0
- package/dist/lineage-cli.d.ts +1 -0
- package/dist/loop-cli.d.ts +34 -0
- package/dist/loop-tools.d.ts +80 -0
- package/dist/mature-tools.d.ts +53 -0
- package/dist/model-check.d.ts +42 -0
- package/dist/module-report.d.ts +9 -0
- package/dist/pi-launch.d.ts +1 -0
- package/dist/pi.d.ts +246 -0
- package/dist/picture-row.d.ts +10 -0
- package/dist/plain/check.d.ts +23 -0
- package/dist/plain/concepts.d.ts +11 -0
- package/dist/plain/errors.d.ts +22 -0
- package/dist/plain/files.d.ts +12 -0
- package/dist/plain/highlight.d.ts +42 -0
- package/dist/plain/index.d.ts +15 -0
- package/dist/plain/liquid.d.ts +22 -0
- package/dist/plain/markdown.d.ts +74 -0
- package/dist/plain/parser.d.ts +87 -0
- package/dist/plain/spec.d.ts +90 -0
- package/dist/plain/stdlib.d.ts +14 -0
- package/dist/question-dialog.d.ts +51 -0
- package/dist/questioning.d.ts +55 -0
- package/dist/quiet.d.ts +34 -0
- package/dist/regenerate/activity.d.ts +207 -0
- package/dist/regenerate/agent-env.d.ts +44 -0
- package/dist/regenerate/agent-shell.d.ts +49 -0
- package/dist/regenerate/arbiter.d.ts +68 -0
- package/dist/regenerate/audit.d.ts +69 -0
- package/dist/regenerate/cases.d.ts +9 -0
- package/dist/regenerate/change-view.d.ts +18 -0
- package/dist/regenerate/choose-conformance.d.ts +32 -0
- package/dist/regenerate/chunk-plan.d.ts +164 -0
- package/dist/regenerate/codebase.d.ts +21 -0
- package/dist/regenerate/command-check.d.ts +40 -0
- package/dist/regenerate/compaction.d.ts +13 -0
- package/dist/regenerate/confine.d.ts +62 -0
- package/dist/regenerate/conform.d.ts +63 -0
- package/dist/regenerate/conformance-agents.d.ts +405 -0
- package/dist/regenerate/conformance.d.ts +189 -0
- package/dist/regenerate/conversation-writes.d.ts +10 -0
- package/dist/regenerate/credentials.d.ts +18 -0
- package/dist/regenerate/debug-log.d.ts +54 -0
- package/dist/regenerate/debugger.d.ts +31 -0
- package/dist/regenerate/delivery.d.ts +6 -0
- package/dist/regenerate/diagnose-job.d.ts +2 -0
- package/dist/regenerate/diagnose.d.ts +46 -0
- package/dist/regenerate/diff-view.d.ts +61 -0
- package/dist/regenerate/drift.d.ts +84 -0
- package/dist/regenerate/engine.d.ts +52 -0
- package/dist/regenerate/environment-error.d.ts +136 -0
- package/dist/regenerate/job-log.d.ts +28 -0
- package/dist/regenerate/job-panel.d.ts +122 -0
- package/dist/regenerate/jobs-tree.d.ts +71 -0
- package/dist/regenerate/jobs.d.ts +186 -0
- package/dist/regenerate/lanes.d.ts +16 -0
- package/dist/regenerate/lineage.d.ts +95 -0
- package/dist/regenerate/list-arguments.d.ts +21 -0
- package/dist/regenerate/loop.d.ts +392 -0
- package/dist/regenerate/masking.d.ts +19 -0
- package/dist/regenerate/notes.d.ts +159 -0
- package/dist/regenerate/os-sandbox.d.ts +89 -0
- package/dist/regenerate/panel-dock.d.ts +23 -0
- package/dist/regenerate/paths.d.ts +92 -0
- package/dist/regenerate/plain-palette.d.ts +34 -0
- package/dist/regenerate/prompt.d.ts +192 -0
- package/dist/regenerate/records.d.ts +88 -0
- package/dist/regenerate/regenerate.d.ts +108 -0
- package/dist/regenerate/regression.d.ts +58 -0
- package/dist/regenerate/release.d.ts +123 -0
- package/dist/regenerate/requires.d.ts +96 -0
- package/dist/regenerate/resources.d.ts +53 -0
- package/dist/regenerate/self-check.d.ts +29 -0
- package/dist/regenerate/services.d.ts +28 -0
- package/dist/regenerate/shell.d.ts +91 -0
- package/dist/regenerate/side-panel.d.ts +57 -0
- package/dist/regenerate/spec-map-view.d.ts +139 -0
- package/dist/regenerate/spec-map.d.ts +138 -0
- package/dist/regenerate/spec-steps.d.ts +137 -0
- package/dist/regenerate/state.d.ts +20 -0
- package/dist/regenerate/steer.d.ts +34 -0
- package/dist/regenerate/steering.d.ts +56 -0
- package/dist/regenerate/stop-report.d.ts +43 -0
- package/dist/regenerate/submit-work.d.ts +42 -0
- package/dist/regenerate/test-kinds.d.ts +42 -0
- package/dist/regenerate/test-scripts.d.ts +221 -0
- package/dist/regenerate/testing.d.ts +141 -0
- package/dist/regenerate/transcript-view.d.ts +21 -0
- package/dist/regenerate/unit-gate.d.ts +27 -0
- package/dist/regenerate/unit-review.d.ts +152 -0
- package/dist/regenerate/web.d.ts +61 -0
- package/dist/regenerate/workspace.d.ts +12 -0
- package/dist/regenerate-cli.d.ts +1 -0
- package/dist/release-agent.d.ts +26 -0
- package/dist/release-cli.d.ts +1 -0
- package/dist/release-tools.d.ts +38 -0
- package/dist/resume-line.d.ts +2 -0
- package/dist/review/live.d.ts +72 -0
- package/dist/rules.d.ts +20 -0
- package/dist/run-report.d.ts +88 -0
- package/dist/screen-padding.d.ts +28 -0
- package/dist/self-invocation.d.ts +25 -0
- package/dist/setup.d.ts +43 -0
- package/dist/skill-progress.d.ts +46 -0
- package/dist/skill.d.ts +98 -0
- package/dist/skills.d.ts +30 -0
- package/dist/spec-diff-cli.d.ts +1 -0
- package/dist/spec-tools.d.ts +36 -0
- package/dist/stack.d.ts +58 -0
- package/dist/stacks.d.ts +12 -0
- package/dist/stdlib.d.ts +27 -0
- package/dist/terminal-images.d.ts +2 -0
- package/dist/tools.d.ts +101 -0
- package/dist/validate-cli.d.ts +1 -0
- package/docs/README.md +2 -0
- package/docs/hosting.md +52 -0
- package/docs/images/turri-banner.gif +0 -0
- package/docs/theming.md +6 -4
- package/docs/using.md +1 -1
- package/package.json +8 -1
- package/docs/images/turri-banner.png +0 -0
- package/docs/images/turri-screenshot.png +0 -0
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
import { Type } from "typebox";
|
|
2
|
+
import { type TestRun } from "./testing.ts";
|
|
3
|
+
/**
|
|
4
|
+
* The project's testing scripts, and the harness's runs of them.
|
|
5
|
+
*
|
|
6
|
+
* An agent runs whatever it likes while it works. Whether the work is done is decided by the
|
|
7
|
+
* project's own scripts - the ones the `implement-unit-testing-script` and
|
|
8
|
+
* `implement-conformance-testing-script` skills write into `test_scripts/` and link from the spec -
|
|
9
|
+
* run by the harness, never by the agent. The same script, the same way, every time: done is a
|
|
10
|
+
* decision the project made, not one an agent makes about its own work.
|
|
11
|
+
*
|
|
12
|
+
* The scripts live beside the specs, outside `plain_modules`, so no agent can reach them. The harness's runs and the
|
|
13
|
+
* agents' run_unit_tests and run_conformance_tests are the only ways they are ever run. They are the person's: they run
|
|
14
|
+
* on this machine as the person would run them - unfenced, in the person's own environment (turri's model provider
|
|
15
|
+
* keys left out) - through the host runner (shell.ts), which gives them a time limit and a stop. What they run on is the
|
|
16
|
+
* project's choice (`testing-scripts-run-on:` in its config):
|
|
17
|
+
*
|
|
18
|
+
* - `in-place`, the default: the project's own script at its own path, from the project, on the real build and tests
|
|
19
|
+
* folders - so a script that finds things from its own path (a host codebase it merges the code into) finds them.
|
|
20
|
+
* - `copy`: a fresh copy of the code, staged in the project's scratch with the script copied beside it - build output
|
|
21
|
+
* stays out of the code, two modules testing at once never share a folder, and nothing a test writes reaches the
|
|
22
|
+
* code.
|
|
23
|
+
*
|
|
24
|
+
* A copy is named for its module and the run: the scripts work in `/tmp/<lang>_<basename of the build>`, and every
|
|
25
|
+
* module's build is called `code`.
|
|
26
|
+
*/
|
|
27
|
+
export type ScriptKind = "unit" | "conformance";
|
|
28
|
+
export interface TestScripts {
|
|
29
|
+
/** `run_unittests_<lang>.sh <build>` */
|
|
30
|
+
unit?: string;
|
|
31
|
+
/** `run_conformance_tests_<lang>.sh <build> <conformance tests>` - the whole suite, at once. */
|
|
32
|
+
conformance?: string;
|
|
33
|
+
/**
|
|
34
|
+
* `prepare_environment_<lang>.sh <build>` - optional: run on the build before every run of the
|
|
35
|
+
* conformance testing script, which runs only once it passes. turri never writes one.
|
|
36
|
+
*/
|
|
37
|
+
prepare?: string;
|
|
38
|
+
/** Why a script was not found where one was looked for: a name in config.turri.yaml, two in a folder. */
|
|
39
|
+
notes?: Partial<Record<ScriptKind | "prepare", string>>;
|
|
40
|
+
/** Conformance was turned off: the conformance testing script is not run, found or not. */
|
|
41
|
+
conformanceOff?: boolean;
|
|
42
|
+
/** What the config has them run on: the code in place (the default, unset), or a fresh copy of the code. */
|
|
43
|
+
runOn?: "copy" | "in-place";
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* The scripts, with the conformance testing script set aside because conformance was turned
|
|
47
|
+
* off: no conformance tests are written or run - not even those already in the codebase - and
|
|
48
|
+
* no agent is shown it.
|
|
49
|
+
*/
|
|
50
|
+
export declare function withoutConformance(scripts: TestScripts): TestScripts;
|
|
51
|
+
export declare function scriptKind(name: string): ScriptKind | undefined;
|
|
52
|
+
export declare const SCRIPTS_DIR = "test_scripts";
|
|
53
|
+
/**
|
|
54
|
+
* The project a build belongs to: the folder that holds its plain_modules. A build folder
|
|
55
|
+
* elsewhere belongs to the folder of its spec.
|
|
56
|
+
*/
|
|
57
|
+
export declare function projectRootFor(plainFile: string, buildDir: string): string;
|
|
58
|
+
/**
|
|
59
|
+
* The project's testing scripts, looked for in this order:
|
|
60
|
+
*
|
|
61
|
+
* 1. `config.turri.yaml` at the project root, with the chosen stack's `config.turri.<stack>.yaml` over it -
|
|
62
|
+
* `unittests-script:` and `conformance-tests-script:`, paths from the root;
|
|
63
|
+
* 2. the project root itself - the one `run_unittests*.sh` / `run_conformance_tests*.sh` there;
|
|
64
|
+
* 3. `test_scripts/` - the one of each there.
|
|
65
|
+
*
|
|
66
|
+
* The prepare script - `prepare-environment-script:`, else the one `prepare_environment*.sh` - is looked for the same
|
|
67
|
+
* way, and is optional: without one, the conformance testing script runs alone.
|
|
68
|
+
*
|
|
69
|
+
* A folder holding two of a kind does not say which is meant: it is skipped, and noted, so the
|
|
70
|
+
* error that stops the build can say to name one in config.turri.yaml.
|
|
71
|
+
*/
|
|
72
|
+
export declare function findTestScripts(root: string, plainFile?: string, buildDir?: string): TestScripts;
|
|
73
|
+
/**
|
|
74
|
+
* The exit code a testing script ends with when the tests passed and only its static checks - the formatter in check
|
|
75
|
+
* mode, the linter, the type checker - did not. Every other failure is the script's own exit code. The harness tells the
|
|
76
|
+
* two apart: a unit run says it was the static checks, and a conformance run sends its tests' findings straight to the
|
|
77
|
+
* conformance agent, with no judge asked whether the code or the tests are wrong.
|
|
78
|
+
*/
|
|
79
|
+
export declare const STATIC_CHECKS_FAILED = 80;
|
|
80
|
+
/** Whether a failed run of a testing script failed on its static checks alone: the tests passed. */
|
|
81
|
+
export declare function staticChecksOnly(run: {
|
|
82
|
+
exitCode: number;
|
|
83
|
+
timedOut?: boolean;
|
|
84
|
+
}): boolean;
|
|
85
|
+
/** Raised before a build starts when the script that would decide it is done is missing. */
|
|
86
|
+
export declare class MissingTestScriptError extends Error {
|
|
87
|
+
readonly moduleName: string;
|
|
88
|
+
readonly kind: ScriptKind;
|
|
89
|
+
constructor(moduleName: string, kind: ScriptKind, note?: string);
|
|
90
|
+
}
|
|
91
|
+
/** The scripts a build needs, or the error that stops it before it starts. */
|
|
92
|
+
export declare function requireTestScripts(moduleName: string, scripts: TestScripts, needs: {
|
|
93
|
+
conformance: boolean;
|
|
94
|
+
}): asserts scripts is TestScripts & {
|
|
95
|
+
unit: string;
|
|
96
|
+
};
|
|
97
|
+
/**
|
|
98
|
+
* The scripts that decide an agent's work, in its prompt - only those that will be run on it: a
|
|
99
|
+
* conformance testing script an agent's work is never judged by is left out. The whole script,
|
|
100
|
+
* read from the project as it is now.
|
|
101
|
+
*/
|
|
102
|
+
export declare function withTestingScripts(prompt: string, scripts: TestScripts, kinds: ScriptKind[], root: string): string;
|
|
103
|
+
export interface ScriptRun {
|
|
104
|
+
/** How the run is shown: the script's name, as the project calls it. */
|
|
105
|
+
command: string;
|
|
106
|
+
exitCode: number;
|
|
107
|
+
output: string;
|
|
108
|
+
/** Stopped by the time limit: counted as failed. */
|
|
109
|
+
timedOut?: boolean;
|
|
110
|
+
/** The time limit it ran under. */
|
|
111
|
+
timeoutMs: number;
|
|
112
|
+
/** How long it ran, from start to end - or to the limit that stopped it. */
|
|
113
|
+
elapsedMs?: number;
|
|
114
|
+
/** Where the whole output is, when it was too long to be shown whole. */
|
|
115
|
+
log?: string;
|
|
116
|
+
}
|
|
117
|
+
/** For tests: a shorter limit than two minutes. */
|
|
118
|
+
export declare function setScriptTimeoutForTests(ms: number | undefined): void;
|
|
119
|
+
/**
|
|
120
|
+
* The project a build belongs to - the folder above its `plain_modules`, where the testing scripts'
|
|
121
|
+
* own paths start - and whether they run on the code in place (the default), rather than on a fresh copy
|
|
122
|
+
* (`testing-scripts-run-on: copy`).
|
|
123
|
+
*/
|
|
124
|
+
/** Whether the testing scripts run on the code in `buildDir` itself, not on a copy of it. */
|
|
125
|
+
export declare function scriptsRunInPlace(buildDir: string): boolean;
|
|
126
|
+
/**
|
|
127
|
+
* The harness's run of the unit testing script on the code as it is now - and run_unit_tests'.
|
|
128
|
+
*
|
|
129
|
+
* On this machine, on the code in place, or - `testing-scripts-run-on: copy` - on a fresh copy of the code
|
|
130
|
+
* (see the top of this file). This and runConformanceScript are the only ways the testing
|
|
131
|
+
* scripts are ever run.
|
|
132
|
+
*/
|
|
133
|
+
export declare function runUnitScript(buildDir: string, script: string): Promise<ScriptRun>;
|
|
134
|
+
/** How long the last passing run of `script` on the code in `buildDir` took, in this process - undefined before one has. */
|
|
135
|
+
export declare function lastPassingMs(buildDir: string, script: string): number | undefined;
|
|
136
|
+
/** A change to one code file for a run: the file, relative to the code folder, and the text it holds for the run. */
|
|
137
|
+
export interface CodeChange {
|
|
138
|
+
file: string;
|
|
139
|
+
text: string;
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* A script that takes the code folder - the unit testing script - run where the testing scripts run. `change`: one file
|
|
143
|
+
* as it is for this run - made to the fresh copy, or, in place, to the code itself and undone once the run ends.
|
|
144
|
+
*/
|
|
145
|
+
export declare function runOnCode(buildDir: string, script: string, what: string, change?: CodeChange,
|
|
146
|
+
/** A time limit of its own, in place of a test run's. */
|
|
147
|
+
limitMs?: number): Promise<ScriptRun>;
|
|
148
|
+
/**
|
|
149
|
+
* The harness's run of the conformance testing script - and run_conformance_tests': the code, and
|
|
150
|
+
* the codebase's whole conformance suite - every functionality's tests, and those carried up from
|
|
151
|
+
* the modules below - in one folder, run at once. As runUnitScript runs: on a copy of the code staged beside the tests,
|
|
152
|
+
* or in place.
|
|
153
|
+
*/
|
|
154
|
+
export declare function runConformanceScript(buildDir: string, testsDirs: string[], scripts: TestScripts): Promise<ScriptRun>;
|
|
155
|
+
/**
|
|
156
|
+
* `run_unit_tests` / `run_conformance_tests`: the agent's final check before it finishes - the
|
|
157
|
+
* project's testing script, run exactly as the harness will run it to decide whether the work is
|
|
158
|
+
* done. It takes no command. Everything else - one test, one file, another configuration, while
|
|
159
|
+
* the agent works - is what bash is for.
|
|
160
|
+
*/
|
|
161
|
+
export declare function createScriptTool(options: {
|
|
162
|
+
kind: ScriptKind;
|
|
163
|
+
script: string | undefined;
|
|
164
|
+
run: () => Promise<ScriptRun>;
|
|
165
|
+
runs: TestRun[];
|
|
166
|
+
onRun?: (command: string, exitCode: number) => void;
|
|
167
|
+
/** Watches the agent's runs for a loop: told once, then its turn is ended. */
|
|
168
|
+
watch?: LoopWatch;
|
|
169
|
+
}): import("@earendil-works/pi-coding-agent").ToolDefinition<Type.TObject<{}>, {
|
|
170
|
+
loop?: "warn" | "stop" | undefined;
|
|
171
|
+
command: string;
|
|
172
|
+
exitCode: number;
|
|
173
|
+
}, any> & import("@earendil-works/pi-coding-agent").ToolDefinition<any, any, any>;
|
|
174
|
+
/** How many of the agent's own runs failing the same way, one after another, are a loop. */
|
|
175
|
+
export declare const LOOP_RUNS = 6;
|
|
176
|
+
/**
|
|
177
|
+
* The agent's own test runs, watched for a loop: an agent stuck on a failure tends to try the same few changes in turn -
|
|
178
|
+
* three signatures of a stand-in function, say - running the tests after each, dozens of times in one turn, and never
|
|
179
|
+
* reads what would tell it the cause. Two things say it is circling: the code folder back exactly as it was at an
|
|
180
|
+
* earlier failing run (its notes aside), or LOOP_RUNS failing runs in a row the same way. The first time, it is told
|
|
181
|
+
* so with the run; the second, its turn is ended, and `stuck` says so until the harness has dealt with it. A passing
|
|
182
|
+
* run clears it all.
|
|
183
|
+
*/
|
|
184
|
+
export interface LoopWatch {
|
|
185
|
+
/** A run of the agent's: undefined, or "warn" the first time it is circling, "stop" the second. */
|
|
186
|
+
see(run: ScriptRun): "warn" | "stop" | undefined;
|
|
187
|
+
/** It was stopped for going round in circles, and the harness has not dealt with it yet. */
|
|
188
|
+
readonly stuck: boolean;
|
|
189
|
+
/** How many failing runs since its last passing one. */
|
|
190
|
+
readonly failing: number;
|
|
191
|
+
/** Dealt with: it starts counting again - the states it has failed in still remembered. */
|
|
192
|
+
reset(): void;
|
|
193
|
+
}
|
|
194
|
+
export declare function createLoopWatch(dir: string): LoopWatch;
|
|
195
|
+
/**
|
|
196
|
+
* How long a run took against its time limit, in a line: for whoever judges it or works out its cause - so a run that
|
|
197
|
+
* ended on its own is never taken for one the limit stopped, nor the other way.
|
|
198
|
+
*/
|
|
199
|
+
export declare function runTiming(run: Pick<ScriptRun, "exitCode" | "timedOut" | "timeoutMs" | "elapsedMs">): string;
|
|
200
|
+
/**
|
|
201
|
+
* What a failed run says is not installed where it ran - the command, when its output names it - or undefined when
|
|
202
|
+
* the run failed for another reason. A missing command is the cause only on evidence that it ended the run: exit 69,
|
|
203
|
+
* the testing scripts' own way to say a toolchain is missing, or 127, what a shell or `timeout` gives for a command it
|
|
204
|
+
* could not find - else a command not found on the last line the run printed, nothing having run after it. Earlier in
|
|
205
|
+
* the output it is a warning, not the failure: a shell profile's, an optional tool probed for, a fallback taken - and a
|
|
206
|
+
* run that failed for its own reasons is the agent's to fix, not a stop for the person.
|
|
207
|
+
*/
|
|
208
|
+
export declare function missingToolchain(run: Pick<ScriptRun, "exitCode" | "output">): {
|
|
209
|
+
command?: string;
|
|
210
|
+
} | undefined;
|
|
211
|
+
/** Where `command` is on this machine's PATH, or undefined when it is not there. */
|
|
212
|
+
export declare function onThisMachine(command: string): string | undefined;
|
|
213
|
+
/** What a failed script run means, for the agent that has to fix it. */
|
|
214
|
+
export declare function scriptFailure(run: ScriptRun, what: string): string;
|
|
215
|
+
/** How many rounds running the same failure, taken the same way, is nothing changing. */
|
|
216
|
+
export declare const STUCK_ROUNDS = 3;
|
|
217
|
+
/**
|
|
218
|
+
* A failing run, as a fingerprint: the lines that say what went wrong, without what changes from run
|
|
219
|
+
* to run - numbers, times, paths, ids. Two runs failing the same way have the same one.
|
|
220
|
+
*/
|
|
221
|
+
export declare function failureSignature(run: ScriptRun): string;
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
import { Type } from "typebox";
|
|
2
|
+
import { type ScriptRun } from "./test-scripts.ts";
|
|
3
|
+
/** Shared test-running and test-preservation machinery for both render tools. */
|
|
4
|
+
export interface TestRun {
|
|
5
|
+
command: string;
|
|
6
|
+
exitCode: number;
|
|
7
|
+
}
|
|
8
|
+
/** A test run has the same time limit as any command: see COMMAND_TIMEOUT_MS. */
|
|
9
|
+
export declare const RUN_TIMEOUT_MS: number;
|
|
10
|
+
/**
|
|
11
|
+
* Output as an agent is shown it: whole when it fits, otherwise its last MAX_OUTPUT_CHARS - where a
|
|
12
|
+
* test run says what failed and why. With `log` the whole output is kept in that file too, and the
|
|
13
|
+
* cut says how to read it: through read_output, by the file's name - never by a path, which would
|
|
14
|
+
* point the agent outside its walls.
|
|
15
|
+
*/
|
|
16
|
+
export declare function truncateOutput(text: string, log?: string): string;
|
|
17
|
+
/**
|
|
18
|
+
* A test run's output as an agent is shown it: whole when it is short; otherwise its failures with the trace after each,
|
|
19
|
+
* its counts and its end - DEBUG and TRACE logging left out - with the whole kept and one read_output away. Most of what
|
|
20
|
+
* agents carried in their context was a failing run's logging; what they act on is which test failed, where, and why.
|
|
21
|
+
*/
|
|
22
|
+
export declare function shownTestOutput(text: string, log?: string): string;
|
|
23
|
+
/** Where the whole outputs are kept: the project's scratch area, read only through read_output. */
|
|
24
|
+
export declare function outputsDir(dir: string): string;
|
|
25
|
+
/** Keep `output` whole, whatever its length, in the outputs folder. Returns the file, or nothing when it could not be written. */
|
|
26
|
+
export declare function keepOutput(dir: string, label: string, output: string | Buffer): string | undefined;
|
|
27
|
+
/**
|
|
28
|
+
* Keep a run's whole output where an agent can read it, when it is too long to be shown whole:
|
|
29
|
+
* in the project's scratch area, inside plain_modules. Returns the file, or nothing when the
|
|
30
|
+
* output fits.
|
|
31
|
+
*/
|
|
32
|
+
export declare function keepFullOutput(dir: string, label: string, output: string): string | undefined;
|
|
33
|
+
/** Keep a test run's whole output for read_output when it is too long to be shown whole - past TEST_OUTPUT_WHOLE. */
|
|
34
|
+
export declare function keepTestOutput(dir: string, label: string, output: string): string | undefined;
|
|
35
|
+
/**
|
|
36
|
+
* A shell's output as the agent is shown it: when pi cut it and kept the whole in a temporary file of its own, the file
|
|
37
|
+
* is taken into the outputs folder, and the agent pointed at read_output instead of at the file.
|
|
38
|
+
*/
|
|
39
|
+
export declare function keptShellOutput(dir: string, text: string): string;
|
|
40
|
+
/**
|
|
41
|
+
* `read_output`: the whole of an output that was cut - a test run's, a command's - read by the id the cut gave, a range
|
|
42
|
+
* of lines or the lines matching a pattern. It reads the kept outputs and nothing else.
|
|
43
|
+
*/
|
|
44
|
+
export declare function readOutputTool(dir: string): import("@earendil-works/pi-coding-agent").ToolDefinition<Type.TObject<{
|
|
45
|
+
id: Type.TString;
|
|
46
|
+
offset: Type.TOptional<Type.TNumber>;
|
|
47
|
+
limit: Type.TOptional<Type.TNumber>;
|
|
48
|
+
pattern: Type.TOptional<Type.TString>;
|
|
49
|
+
}>, {
|
|
50
|
+
id: string;
|
|
51
|
+
}, any> & import("@earendil-works/pi-coding-agent").ToolDefinition<any, any, any>;
|
|
52
|
+
/** Output as an agent is shown it, with the whole of it kept in a file when it had to be cut. */
|
|
53
|
+
export declare function shownOutput(dir: string, label: string, output: string): string;
|
|
54
|
+
/**
|
|
55
|
+
* Never part of the codebase: version control, installed dependencies, tool caches, and the
|
|
56
|
+
* harness's own bookkeeping. Installed dependencies alone can be tens of thousands of files.
|
|
57
|
+
*/
|
|
58
|
+
export declare const NOT_CODE: Set<string>;
|
|
59
|
+
export declare function listFiles(root: string): string[];
|
|
60
|
+
/** A tool that runs the tests and lets the harness see the result, rather than taking the agent's word. */
|
|
61
|
+
export declare const TEST_FILE_PATTERN: RegExp;
|
|
62
|
+
/**
|
|
63
|
+
* Which files look like tests, and roughly how many cases each holds.
|
|
64
|
+
*
|
|
65
|
+
* The count is a heuristic over common test idioms across languages. It is not a parser -
|
|
66
|
+
* it exists to notice that tests went missing between one turn and the next, which is a
|
|
67
|
+
* question worth asking even when the estimate is a case or two off.
|
|
68
|
+
*/
|
|
69
|
+
export declare function inventoryTests(root: string): Map<string, number>;
|
|
70
|
+
export interface TestRemoval {
|
|
71
|
+
file: string;
|
|
72
|
+
before: number;
|
|
73
|
+
after: number;
|
|
74
|
+
deleted: boolean;
|
|
75
|
+
}
|
|
76
|
+
/** Test files that disappeared, or lost cases, between two inventories. */
|
|
77
|
+
export declare function findTestRemovals(before: Map<string, number>, after: Map<string, number>): TestRemoval[];
|
|
78
|
+
export declare function describeRemovals(removals: TestRemoval[]): string;
|
|
79
|
+
/**
|
|
80
|
+
* A deleted test is a silent way to make a suite pass. The rule is narrow on purpose:
|
|
81
|
+
* a test may go only when it asserts nothing meaningful, never because it is failing.
|
|
82
|
+
*/
|
|
83
|
+
export declare function removalChallengePrompt(removals: TestRemoval[], subject: string): string;
|
|
84
|
+
/**
|
|
85
|
+
* How many times a coding agent that ended its turn having written nothing is asked for a draft: once. Thinking a
|
|
86
|
+
* problem through and ending the turn with nothing written leaves nothing to test or review; a best guess does. A
|
|
87
|
+
* change that only rewords or describes may need no code, and the agent says so.
|
|
88
|
+
*/
|
|
89
|
+
export declare const DRAFT_ASKS = 1;
|
|
90
|
+
/** For a coding agent that has written nothing yet: write a best-guess draft now, or say why no code is needed. */
|
|
91
|
+
export declare function draftPrompt(): string;
|
|
92
|
+
export type UnitVerdict = {
|
|
93
|
+
ok: true;
|
|
94
|
+
command: string;
|
|
95
|
+
} | {
|
|
96
|
+
ok: false;
|
|
97
|
+
command?: string;
|
|
98
|
+
prompt: string;
|
|
99
|
+
missing?: MissingToolchain;
|
|
100
|
+
run?: ScriptRun;
|
|
101
|
+
};
|
|
102
|
+
/** A toolchain the testing script needs and does not find on this machine: no change to the code can pass it. */
|
|
103
|
+
export interface MissingToolchain {
|
|
104
|
+
command?: string;
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* The harness's own run of the unit tests, which is what "the tests pass" rests on.
|
|
108
|
+
*
|
|
109
|
+
* The agent runs whatever commands it likes while it works. Whether the code is done is the
|
|
110
|
+
* project's unit testing script, run by the harness on the code as it now is - the same script,
|
|
111
|
+
* the same way, every time (see test-scripts.ts).
|
|
112
|
+
*/
|
|
113
|
+
export declare function verifyUnitSuite(buildDir: string, runs: TestRun[], script: string): Promise<UnitVerdict>;
|
|
114
|
+
/** Every file of the test code under `dirs`, by path, as it is now. */
|
|
115
|
+
export declare function snapshotFiles(dirs: string[]): Map<string, Buffer>;
|
|
116
|
+
/** The files under `dirs` that differ from the snapshot: changed, added or deleted. */
|
|
117
|
+
export declare function changedSince(snapshot: Map<string, Buffer>, dirs: string[]): string[];
|
|
118
|
+
/** Put the files under `dirs` back to the snapshot: its files restored, any others removed. */
|
|
119
|
+
export declare function restoreSnapshot(snapshot: Map<string, Buffer>, dirs: string[]): void;
|
|
120
|
+
/**
|
|
121
|
+
* Run an agent that fixes code with the conformance tests out of its reach - by the harness,
|
|
122
|
+
* not by its file access, which covers the whole of `plain_modules`.
|
|
123
|
+
*
|
|
124
|
+
* The tests say what the specification requires; an agent told to make them pass could
|
|
125
|
+
* otherwise do it by changing a test. So they are photographed before it starts and compared
|
|
126
|
+
* when it finishes. Anything it changed is put back, and it is sent to fix the code instead,
|
|
127
|
+
* until it leaves the tests alone or the rounds run out - after which the tests are put back
|
|
128
|
+
* all the same. Returns the agent's last report and every test file it had to have restored.
|
|
129
|
+
*/
|
|
130
|
+
export declare function keepingTestsUnchanged(input: {
|
|
131
|
+
dirs: string[];
|
|
132
|
+
/** The agent's first turn. */
|
|
133
|
+
start: () => Promise<string>;
|
|
134
|
+
/** Another turn, with this prompt. */
|
|
135
|
+
again: (prompt: string) => Promise<string>;
|
|
136
|
+
/** For the activity line: whose code is being fixed. */
|
|
137
|
+
label: string;
|
|
138
|
+
}): Promise<{
|
|
139
|
+
report: string;
|
|
140
|
+
restored: string[];
|
|
141
|
+
}>;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { DiffPaint } from "./diff-view.ts";
|
|
2
|
+
import type { DiffStyle } from "./job-panel.ts";
|
|
3
|
+
/**
|
|
4
|
+
* How the side panel colours things. Plain text when there is no theme, as in tests.
|
|
5
|
+
*
|
|
6
|
+
* The panel no longer shows a job's agents at work - every prompt, reply, thought and tool call: that is in each
|
|
7
|
+
* pulse's log (job-log.ts), streamed as it happens.
|
|
8
|
+
*/
|
|
9
|
+
export interface TranscriptStyle extends DiffStyle {
|
|
10
|
+
heading(text: string): string;
|
|
11
|
+
muted(text: string): string;
|
|
12
|
+
accent(text: string): string;
|
|
13
|
+
error(text: string): string;
|
|
14
|
+
/** A pulse that passed, and one stopped: not given, the added colour and the accent. */
|
|
15
|
+
success?(text: string): string;
|
|
16
|
+
warning?(text: string): string;
|
|
17
|
+
/** How a spec diff is painted - ***plain highlighted, added and removed lines filled (`plain-palette.ts`). Not given: the +/- coloured alone. */
|
|
18
|
+
diff?: DiffPaint;
|
|
19
|
+
/** A functional spec its conformance tests pass for - regen's ◆: neon. */
|
|
20
|
+
conforms?: (text: string) => string;
|
|
21
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { MissingToolchain, TestRun } from "./testing.ts";
|
|
2
|
+
import { type ScriptRun } from "./test-scripts.ts";
|
|
3
|
+
/**
|
|
4
|
+
* The coding agent's unit tests: the project's unit testing script, run by the harness. The script is the whole of it -
|
|
5
|
+
* its static checks, when it runs any, included - and its exit code says which failed: `STATIC_CHECKS_FAILED` is the
|
|
6
|
+
* tests passing and only the checks not.
|
|
7
|
+
*/
|
|
8
|
+
export type WorkVerdict = {
|
|
9
|
+
ok: true;
|
|
10
|
+
} | {
|
|
11
|
+
ok: false;
|
|
12
|
+
/** What the agent is sent back with. */
|
|
13
|
+
prompt: string;
|
|
14
|
+
/** The run that failed, for the fingerprint and the debugger. */
|
|
15
|
+
run: ScriptRun;
|
|
16
|
+
/** The script that run was of. */
|
|
17
|
+
script: string;
|
|
18
|
+
/** Only the script's static checks failed: the tests passed. */
|
|
19
|
+
staticOnly: boolean;
|
|
20
|
+
/** A toolchain the script needs and this machine lacks. */
|
|
21
|
+
missing?: MissingToolchain;
|
|
22
|
+
};
|
|
23
|
+
export interface UnitGate {
|
|
24
|
+
/** The unit testing script on the code, recorded in `runs`: passing, or what to send the agent back with. */
|
|
25
|
+
verify(runs: TestRun[]): Promise<WorkVerdict>;
|
|
26
|
+
}
|
|
27
|
+
export declare function createUnitGate(buildDir: string, unit: string): UnitGate;
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
import { type WorkLedger } from "./submit-work.ts";
|
|
2
|
+
import type { JobCases } from "./drift.ts";
|
|
3
|
+
/** How many times the reviewer runs can_it_fail in a review session: each is a run of the unit testing script. */
|
|
4
|
+
export declare const REVIEWER_CAN_IT_FAIL_RUNS = 3;
|
|
5
|
+
/**
|
|
6
|
+
* The review of the work: once its unit tests pass, does the code do what the spec says, and do the tests test it?
|
|
7
|
+
*
|
|
8
|
+
* A passing unit suite proves only what its tests check, and a coding agent is quick to write tests
|
|
9
|
+
* that check next to nothing - that a function exists, that it returns something, that a status is
|
|
10
|
+
* 200 - and pass whatever the code does, or none at all. So once the unit testing script passes, a
|
|
11
|
+
* reviewer reads what the work wrote - the code and the unit tests, as a diff - beside the spec, and says
|
|
12
|
+
* where the code does not do what the spec says, and which tests are missing or weak. It changes nothing. Its problems go back to the coding agent, the unit testing script
|
|
13
|
+
* runs again, and the review looks again. It optimises the tests, it is not a gate: a problem that
|
|
14
|
+
* leaves a behaviour of the spec untested is worked on first, the rest - ways to make tests that
|
|
15
|
+
* already test it better - are let go after UNIT_REVIEW_ROUNDS reviews, and after UNIT_REVIEW_LIMIT
|
|
16
|
+
* whatever is left is let go too, kept in the notes, and the work goes on.
|
|
17
|
+
*/
|
|
18
|
+
/** What the review found wrong with the code or its unit tests. */
|
|
19
|
+
export interface UnitReviewProblem {
|
|
20
|
+
file: string;
|
|
21
|
+
test?: string;
|
|
22
|
+
/** "wrong": the code does not do what the spec says. "missing", "bad": a unit test not there, or weak. */
|
|
23
|
+
kind: "missing" | "bad" | "wrong";
|
|
24
|
+
what: string;
|
|
25
|
+
/**
|
|
26
|
+
* A behaviour the spec states is not implemented, or implemented wrong, or not yet tested: no test for it, or
|
|
27
|
+
* one that cannot fail - it only checks that something exists, asserts nothing, mocks the unit it tests, is skipped.
|
|
28
|
+
*/
|
|
29
|
+
blocking?: boolean;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* How many reviews may send the unit tests back before the arbiter weighs them: from this one on, every review that
|
|
33
|
+
* sends them back goes to the arbiter first, and only what it upholds reaches the coding agent.
|
|
34
|
+
*/
|
|
35
|
+
export declare const UNIT_REVIEW_ROUNDS = 1;
|
|
36
|
+
/**
|
|
37
|
+
* How many reviews at most. The review optimises the tests; it does not decide whether the work is done - the
|
|
38
|
+
* unit testing script does. Past this many, whatever it still finds, blocking or not, is let go, kept in the notes,
|
|
39
|
+
* and the work goes on.
|
|
40
|
+
*/
|
|
41
|
+
export declare const UNIT_REVIEW_LIMIT = 2;
|
|
42
|
+
/** The unit test files that differ from what they were when the work started: added or changed. */
|
|
43
|
+
export declare function changedUnitTests(buildDir: string, atStart: Map<string, string>): string[];
|
|
44
|
+
/**
|
|
45
|
+
* The reviewer's task, for its instructions: what it reviews, against which specification, and how. It stays word for
|
|
46
|
+
* word through every review of the loop; what each review is shown comes as a message (`unitReviewRequest`).
|
|
47
|
+
*/
|
|
48
|
+
export declare function unitReviewTask(options: {
|
|
49
|
+
buildDir: string;
|
|
50
|
+
/** What the work built: "functionality 3 of module `m`", "the spec change to module `m`". */
|
|
51
|
+
what: string;
|
|
52
|
+
/** The specification it built, as the coding agent had it, what is new in this work apart (`reviewedSpec`). */
|
|
53
|
+
spec: string;
|
|
54
|
+
/** The work is a spec change, not a functionality. */
|
|
55
|
+
forChange?: boolean;
|
|
56
|
+
/** What the work does to each functional spec (work.ts): each part held to its own case. */
|
|
57
|
+
cases?: JobCases;
|
|
58
|
+
/** It has can_it_fail, to check that a test it doubts can fail. */
|
|
59
|
+
canItFail?: boolean;
|
|
60
|
+
/** The unit testing script, word for word: how the unit tests are run, and so which of them run at all. */
|
|
61
|
+
testingScript?: {
|
|
62
|
+
path: string;
|
|
63
|
+
content: string;
|
|
64
|
+
};
|
|
65
|
+
}): string;
|
|
66
|
+
/** What one review is shown: the whole work the first time; after that, what changed since the last, and the problems it raised. */
|
|
67
|
+
export declare function unitReviewRequest(options: {
|
|
68
|
+
/** First review: the whole work (`workDiff`). After it: the diff since the last review (`diffSinceSnapshot`). */
|
|
69
|
+
diff: string;
|
|
70
|
+
changed: string[];
|
|
71
|
+
/** The coding agent's account of its work since the last review (`describeAccounts`). */
|
|
72
|
+
account: string;
|
|
73
|
+
/** The problems the last review raised that went to the coding agent - given, this is a review after it. */
|
|
74
|
+
earlier?: UnitReviewProblem[];
|
|
75
|
+
/** What the arbiter let go of the last review: not to be raised again. */
|
|
76
|
+
letGo?: UnitReviewProblem[];
|
|
77
|
+
}): string;
|
|
78
|
+
export interface UnitReviewer {
|
|
79
|
+
/** One review: what it is shown (`unitReviewRequest`), and its verdict. No verdict is no pass. */
|
|
80
|
+
review(request: string): Promise<{
|
|
81
|
+
pass: boolean;
|
|
82
|
+
problems: UnitReviewProblem[];
|
|
83
|
+
}>;
|
|
84
|
+
dispose(): void;
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* The reviewer: a read-only agent, on the judge model, that says pass or every problem - one session for the whole
|
|
88
|
+
* loop, so a review after the first starts from what it already read and raised, not from nothing. Its task is its
|
|
89
|
+
* instructions; its work is compacted as it gets longer.
|
|
90
|
+
*/
|
|
91
|
+
export declare function createUnitReviewer(options: {
|
|
92
|
+
/** What the work does to each functional spec (work.ts): the reviewer holds each part to its own case. */
|
|
93
|
+
cases?: JobCases;
|
|
94
|
+
buildDir: string;
|
|
95
|
+
what: string;
|
|
96
|
+
spec: string;
|
|
97
|
+
forChange?: boolean;
|
|
98
|
+
label: string;
|
|
99
|
+
model?: string;
|
|
100
|
+
onDelta?: (delta: string) => void;
|
|
101
|
+
/** The unit testing script: the reviewer checks with can_it_fail that a test it doubts can fail. */
|
|
102
|
+
unitScript?: string;
|
|
103
|
+
/** The unit testing script, word for word, in its task. */
|
|
104
|
+
testingScript?: {
|
|
105
|
+
path: string;
|
|
106
|
+
content: string;
|
|
107
|
+
};
|
|
108
|
+
}): Promise<UnitReviewer>;
|
|
109
|
+
/** The review's problems, for the coding agent. */
|
|
110
|
+
export declare function unitReviewFeedbackPrompt(problems: UnitReviewProblem[]): string;
|
|
111
|
+
/**
|
|
112
|
+
* Review the code and its unit tests until they pass it: each time it finds problems, they go to the coding agent
|
|
113
|
+
* and the unit tests must pass again before the next review. Past UNIT_REVIEW_ROUNDS reviews with
|
|
114
|
+
* nothing blocking, what it still suggests is let go and kept in the notes; past UNIT_REVIEW_LIMIT,
|
|
115
|
+
* whatever is left is let go the same way - the review optimises the tests, it never stops the work.
|
|
116
|
+
* Only unit tests that no longer pass after a round of fixes do.
|
|
117
|
+
*/
|
|
118
|
+
export declare function untilUnitTestsReviewed(options: {
|
|
119
|
+
/** What the work does to each functional spec (work.ts): the reviewer holds each part to its own case. */
|
|
120
|
+
cases?: JobCases;
|
|
121
|
+
buildDir: string;
|
|
122
|
+
/** The code folder's files when the work started, to see which unit tests it added or changed. */
|
|
123
|
+
atStart: Map<string, string>;
|
|
124
|
+
what: string;
|
|
125
|
+
/** The specification it built, what is new in this work apart (`reviewedSpec`). */
|
|
126
|
+
spec: string;
|
|
127
|
+
forChange?: boolean;
|
|
128
|
+
label: string;
|
|
129
|
+
model?: string;
|
|
130
|
+
/** Send the coding agent a prompt. */
|
|
131
|
+
send: (prompt: string) => Promise<void>;
|
|
132
|
+
/** Run the unit tests with the coding agent until they pass: false when they do not. */
|
|
133
|
+
untilPassing: () => Promise<boolean>;
|
|
134
|
+
stage: (label: string) => void;
|
|
135
|
+
onDelta?: (delta: string) => void;
|
|
136
|
+
/** What the coding agent handed over through submit_work: its account, beside the diff, for the reviewer. */
|
|
137
|
+
work?: WorkLedger;
|
|
138
|
+
/** Send the coding agent back once for problems its account left unanswered. Default true when `work` is given. */
|
|
139
|
+
askForAnswers?: boolean;
|
|
140
|
+
/** The unit testing script: the reviewer checks with can_it_fail that a test it doubts can fail. */
|
|
141
|
+
unitScript?: string;
|
|
142
|
+
/** The unit testing script, word for word, for the reviewer to read. */
|
|
143
|
+
testingScript?: {
|
|
144
|
+
path: string;
|
|
145
|
+
content: string;
|
|
146
|
+
};
|
|
147
|
+
}): Promise<{
|
|
148
|
+
passed: boolean;
|
|
149
|
+
waived?: UnitReviewProblem[];
|
|
150
|
+
problems?: UnitReviewProblem[];
|
|
151
|
+
reviews: number;
|
|
152
|
+
}>;
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { Type } from "typebox";
|
|
2
|
+
/**
|
|
3
|
+
* The web, for the agents that build: search it, and read a page.
|
|
4
|
+
*
|
|
5
|
+
* An agent building on a library it half-remembers, or stuck on an error it has not seen, does
|
|
6
|
+
* better reading the documentation or the answer than guessing again. So every rendering agent
|
|
7
|
+
* has two tools: `web_search`, which asks DuckDuckGo and returns the results, and `web_fetch`,
|
|
8
|
+
* which reads one page and returns it as text.
|
|
9
|
+
*
|
|
10
|
+
* Both run here, in turri itself. What reaches the web through them is a request the agent made
|
|
11
|
+
* through a tool, and what comes back is text it reads.
|
|
12
|
+
*
|
|
13
|
+
* Only the public web: `web_fetch` refuses an address on this machine or its network - localhost,
|
|
14
|
+
* the private ranges, the cloud metadata address - so it cannot be used to reach the cloud's
|
|
15
|
+
* credentials or a service inside the person's network by way of turri.
|
|
16
|
+
*/
|
|
17
|
+
export declare const WEB_TOOLS: string[];
|
|
18
|
+
/** How much of a page one call returns; the rest is had with `offset`. */
|
|
19
|
+
export declare const PAGE_CHARS = 20000;
|
|
20
|
+
export interface SearchResult {
|
|
21
|
+
title: string;
|
|
22
|
+
url: string;
|
|
23
|
+
snippet: string;
|
|
24
|
+
}
|
|
25
|
+
export declare function decodeEntities(text: string): string;
|
|
26
|
+
/** The results on a page of DuckDuckGo Lite: each a link, then its snippet. Ads are left out. */
|
|
27
|
+
export declare function parseSearchResults(html: string): SearchResult[];
|
|
28
|
+
export declare function webSearch(query: string, limit?: number): Promise<SearchResult[]>;
|
|
29
|
+
/** Whether an IP address is on this machine or its network, rather than the public internet. */
|
|
30
|
+
export declare function isPrivateAddress(address: string): boolean;
|
|
31
|
+
type Lookup = (host: string) => Promise<string[]>;
|
|
32
|
+
/** Refuse a URL that is not http(s) on the public internet; its parsed form when it is. */
|
|
33
|
+
export declare function checkPublicUrl(raw: string, resolve?: Lookup): Promise<URL>;
|
|
34
|
+
/** A page as readable text: what a person would read, without the markup, scripts and styles. */
|
|
35
|
+
export declare function htmlToText(html: string): string;
|
|
36
|
+
export interface FetchedPage {
|
|
37
|
+
url: string;
|
|
38
|
+
status: number;
|
|
39
|
+
contentType: string;
|
|
40
|
+
text: string;
|
|
41
|
+
}
|
|
42
|
+
/** Fetch a public page, following redirects - each checked - and return it as text. */
|
|
43
|
+
export declare function webFetch(raw: string, opts?: {
|
|
44
|
+
resolve?: Lookup;
|
|
45
|
+
fetchImpl?: typeof fetch;
|
|
46
|
+
}): Promise<FetchedPage>;
|
|
47
|
+
/** One window of a long page, and how to read on. */
|
|
48
|
+
export declare function pageWindow(text: string, offset: number): string;
|
|
49
|
+
export declare function createWebTools(): ((import("@earendil-works/pi-coding-agent").ToolDefinition<Type.TObject<{
|
|
50
|
+
query: Type.TString;
|
|
51
|
+
limit: Type.TOptional<Type.TInteger>;
|
|
52
|
+
}>, {
|
|
53
|
+
results: number;
|
|
54
|
+
}, any> & import("@earendil-works/pi-coding-agent").ToolDefinition<any, any, any>) | (import("@earendil-works/pi-coding-agent").ToolDefinition<Type.TObject<{
|
|
55
|
+
url: Type.TString;
|
|
56
|
+
offset: Type.TOptional<Type.TInteger>;
|
|
57
|
+
}>, {
|
|
58
|
+
characters: number;
|
|
59
|
+
status: number;
|
|
60
|
+
}, any> & import("@earendil-works/pi-coding-agent").ToolDefinition<any, any, any>))[];
|
|
61
|
+
export {};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export interface WorkspaceInput {
|
|
2
|
+
/** The agent's folder. */
|
|
3
|
+
dir: string;
|
|
4
|
+
/** Whether the agent has my_diff, which shows its work. */
|
|
5
|
+
hasMyDiff: boolean;
|
|
6
|
+
/** The module's implementation reqs, which name its stack; read from its spec when not given. */
|
|
7
|
+
implementationReqs?: string[];
|
|
8
|
+
/** For tests: a command's version, in place of asking this machine. */
|
|
9
|
+
probe?: (command: string) => string | undefined;
|
|
10
|
+
}
|
|
11
|
+
/** The block, for the agent's system prompt beside its walls. */
|
|
12
|
+
export declare function workspaceBlock(input: WorkspaceInput): string;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|