@turri-dev/cli 0.1.27-next.763d091 → 0.1.28-next.d5f2680
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 +6 -6
- package/dist/advisor-chat.d.ts +63 -0
- package/dist/advisor-chat.js +290 -0
- package/dist/background-skills.d.ts +53 -0
- package/dist/background-skills.js +121 -0
- package/dist/bedrock-region.d.ts +66 -0
- package/dist/bedrock-region.js +144 -0
- package/dist/btw.d.ts +1 -1
- package/dist/btw.js +1 -1
- package/dist/change-plain-cli.js +20 -13
- package/dist/chat-idle.d.ts +7 -0
- package/dist/chat-idle.js +20 -0
- package/dist/chats.d.ts +10 -0
- package/dist/chats.js +23 -0
- package/dist/cli-options.d.ts +1 -2
- package/dist/cli-options.js +2 -7
- package/dist/cli.js +11 -3
- package/dist/config-command.d.ts +14 -0
- package/dist/config-command.js +35 -15
- package/dist/config-edit.d.ts +3 -3
- package/dist/config-edit.js +16 -12
- package/dist/config.d.ts +54 -34
- package/dist/config.js +40 -44
- package/dist/conform-cli.js +12 -10
- package/dist/conformance-switch.d.ts +34 -0
- package/dist/conformance-switch.js +108 -0
- package/dist/cultivate-cli.js +15 -5
- package/dist/drift-cli.js +2 -0
- package/dist/extension.d.ts +15 -0
- package/dist/extension.js +260 -83
- package/dist/host-session.d.ts +26 -0
- package/dist/host-session.js +30 -2
- package/dist/host.d.ts +5 -2
- package/dist/host.js +7 -1
- package/dist/init-config.d.ts +1 -1
- package/dist/init-config.js +20 -11
- package/dist/loop-cli.d.ts +3 -3
- package/dist/loop-cli.js +13 -16
- package/dist/loop-tools.js +18 -10
- package/dist/model-check.d.ts +8 -3
- package/dist/model-check.js +13 -8
- package/dist/new-project.js +12 -8
- package/dist/{validate-cli.js → parse-cli.js} +11 -5
- package/dist/parse-tool.d.ts +9 -0
- package/dist/parse-tool.js +33 -0
- package/dist/pi-launch.js +1 -1
- package/dist/plain/check.d.ts +53 -6
- package/dist/plain/check.js +217 -24
- package/dist/plain/concepts.d.ts +8 -0
- package/dist/plain/concepts.js +66 -23
- package/dist/plain/cycles.d.ts +21 -0
- package/dist/plain/cycles.js +190 -0
- package/dist/plain/errors.d.ts +4 -0
- package/dist/plain/errors.js +7 -0
- package/dist/plain/files.d.ts +18 -1
- package/dist/plain/files.js +39 -2
- package/dist/plain/graph.d.ts +33 -4
- package/dist/plain/graph.js +60 -12
- package/dist/plain/highlight.d.ts +3 -2
- package/dist/plain/highlight.js +4 -3
- package/dist/plain/index.d.ts +8 -5
- package/dist/plain/index.js +8 -5
- package/dist/plain/liquid.js +1 -6
- package/dist/plain/markdown.d.ts +32 -3
- package/dist/plain/markdown.js +146 -24
- package/dist/plain/module-concepts.js +2 -2
- package/dist/plain/parser.d.ts +83 -28
- package/dist/plain/parser.js +381 -260
- package/dist/plain/plain.tmLanguage.json +29 -3
- package/dist/plain/project.d.ts +48 -0
- package/dist/plain/project.js +155 -0
- package/dist/plain/spec.d.ts +90 -28
- package/dist/plain/spec.js +107 -133
- package/dist/plain/test-plain-file.d.ts +59 -0
- package/dist/plain/test-plain-file.js +232 -0
- package/dist/regenerate/activity.d.ts +20 -9
- package/dist/regenerate/activity.js +11 -4
- package/dist/regenerate/advisor-records.d.ts +93 -0
- package/dist/regenerate/advisor-records.js +110 -0
- package/dist/regenerate/advisor-runs.d.ts +87 -0
- package/dist/regenerate/advisor-runs.js +327 -0
- package/dist/regenerate/base-folder.d.ts +68 -0
- package/dist/regenerate/base-folder.js +168 -0
- package/dist/regenerate/cases.d.ts +9 -6
- package/dist/regenerate/cases.js +71 -15
- package/dist/regenerate/change-view.d.ts +8 -3
- package/dist/regenerate/change-view.js +71 -22
- package/dist/regenerate/chunk-plan.d.ts +36 -15
- package/dist/regenerate/chunk-plan.js +165 -59
- package/dist/regenerate/conform.d.ts +3 -0
- package/dist/regenerate/conform.js +6 -5
- package/dist/regenerate/conformance-agents.d.ts +18 -39
- package/dist/regenerate/conformance-agents.js +60 -88
- package/dist/regenerate/conformance.d.ts +23 -20
- package/dist/regenerate/conformance.js +118 -121
- package/dist/regenerate/diff-view.d.ts +1 -1
- package/dist/regenerate/diff-view.js +20 -4
- package/dist/regenerate/drift.d.ts +47 -15
- package/dist/regenerate/drift.js +101 -30
- package/dist/regenerate/jobs.d.ts +2 -2
- package/dist/regenerate/jobs.js +1 -1
- package/dist/regenerate/ledger.d.ts +19 -0
- package/dist/regenerate/loop.d.ts +61 -49
- package/dist/regenerate/loop.js +473 -340
- package/dist/regenerate/paths.d.ts +4 -0
- package/dist/regenerate/paths.js +7 -1
- package/dist/regenerate/plain-palette.js +2 -0
- package/dist/regenerate/prompt.d.ts +57 -19
- package/dist/regenerate/prompt.js +157 -122
- package/dist/regenerate/records.d.ts +43 -12
- package/dist/regenerate/records.js +102 -88
- package/dist/regenerate/regenerate.js +29 -11
- package/dist/regenerate/regression.d.ts +4 -4
- package/dist/regenerate/regression.js +14 -10
- package/dist/regenerate/renames.d.ts +42 -0
- package/dist/regenerate/renames.js +185 -0
- package/dist/regenerate/requires.d.ts +1 -1
- package/dist/regenerate/requires.js +10 -3
- package/dist/regenerate/resources.d.ts +5 -3
- package/dist/regenerate/resources.js +4 -4
- package/dist/regenerate/scripts-being-written.d.ts +19 -0
- package/dist/regenerate/scripts-being-written.js +30 -0
- package/dist/regenerate/spec-map-view.d.ts +2 -2
- package/dist/regenerate/spec-map-view.js +46 -15
- package/dist/regenerate/spec-map.d.ts +27 -5
- package/dist/regenerate/spec-map.js +92 -60
- package/dist/regenerate/spec-steps.d.ts +48 -5
- package/dist/regenerate/spec-steps.js +213 -28
- package/dist/regenerate/state.d.ts +4 -3
- package/dist/regenerate/stop-report.d.ts +1 -1
- package/dist/regenerate/stop-report.js +10 -10
- package/dist/regenerate/test-advisor.d.ts +101 -0
- package/dist/regenerate/test-advisor.js +379 -0
- package/dist/regenerate/test-kinds.d.ts +69 -31
- package/dist/regenerate/test-kinds.js +109 -80
- package/dist/regenerate/test-scripts.d.ts +2 -0
- package/dist/regenerate/test-scripts.js +4 -0
- package/dist/regenerate/testing-steps.d.ts +41 -0
- package/dist/regenerate/testing-steps.js +110 -0
- package/dist/regenerate/testing.d.ts +1 -1
- package/dist/regenerate/testing.js +5 -4
- package/dist/regenerate/unit-review.d.ts +1 -1
- package/dist/regenerate/unit-review.js +3 -3
- package/dist/regenerate-cli.js +11 -12
- package/dist/release-agent.js +4 -0
- package/dist/release-cli.js +2 -0
- package/dist/release-tools.js +2 -0
- package/dist/run-report.d.ts +2 -2
- package/dist/run-report.js +4 -3
- package/dist/self-invocation.d.ts +1 -1
- package/dist/self-invocation.js +1 -1
- package/dist/sentinel.js +1 -1
- package/dist/setup.d.ts +10 -0
- package/dist/setup.js +52 -4
- package/dist/skill.d.ts +10 -0
- package/dist/skill.js +6 -0
- package/dist/skills.js +3 -1
- package/dist/spec-tools.js +21 -31
- package/dist/test-plain-files.d.ts +41 -0
- package/dist/test-plain-files.js +177 -0
- package/docs/README.md +3 -1
- package/docs/authoring-plain.md +46 -13
- package/docs/chats.md +3 -1
- package/docs/config.md +20 -15
- package/docs/deploy.md +1 -1
- package/docs/development.md +2 -1
- package/docs/headless.md +15 -18
- package/docs/hosting.md +28 -12
- package/docs/installation.md +1 -0
- package/docs/parser.md +88 -27
- package/docs/regenerating.md +89 -54
- package/docs/sentinel.md +1 -1
- package/docs/skills-and-gates.md +3 -1
- package/docs/test-advisor.md +110 -0
- package/docs/theming.md +1 -1
- package/docs/using.md +17 -15
- package/genome/rules/bullet-continuation.md +8 -8
- package/genome/rules/concise-specs-examples.md +111 -80
- package/genome/rules/concise-specs-integration-examples.md +56 -41
- package/genome/rules/concise-specs.md +17 -16
- package/genome/rules/definitions.md +5 -5
- package/genome/rules/examples/integration-embedded-testing/run_conformance_tests_java.sh +1 -1
- package/genome/rules/func-specs.md +69 -74
- package/genome/rules/impl-reqs.md +4 -4
- package/genome/rules/integration-embedded-testing.md +20 -20
- package/genome/rules/integration-embedded.md +31 -31
- package/genome/rules/integration-standalone.md +9 -9
- package/genome/rules/integrations.md +18 -18
- package/genome/rules/linked-resources.md +19 -16
- package/genome/rules/module-structure.md +21 -14
- package/genome/rules/project-model.md +18 -17
- package/genome/rules/required-concepts.md +1 -1
- package/genome/rules/requires-modules.md +6 -5
- package/genome/rules/semantic-ids.md +49 -0
- package/genome/rules/stdlib.md +4 -5
- package/genome/rules/test-plain-files.md +130 -0
- package/genome/rules/test-reqs.md +8 -8
- package/genome/rules/turri-regeneration.md +24 -8
- package/genome/skills/analyze-2-func-specs/SKILL.md +36 -21
- package/genome/skills/analyze-func-specs/SKILL.md +46 -32
- package/genome/skills/break-down-func-spec/SKILL.md +91 -67
- package/genome/skills/consolidate-concepts/SKILL.md +10 -10
- package/genome/skills/convert-old-syntax/SKILL.md +68 -0
- package/genome/skills/convert-old-syntax/references/rubric.md +11 -0
- package/genome/skills/debug-specs/SKILL.md +62 -56
- package/genome/skills/implement-conformance-testing-script/SKILL.md +19 -15
- package/genome/skills/implement-conformance-testing-script/assets/run_conformance_tests_java.sh +2 -2
- package/genome/skills/implement-conformance-testing-script/assets/run_conformance_tests_python.sh +2 -2
- package/genome/skills/implement-unit-testing-script/SKILL.md +14 -10
- package/genome/skills/refactor-module/SKILL.md +35 -35
- package/genome/skills/resolve-section-ownership/SKILL.md +9 -9
- package/genome/skills/resolve-spec-conflict/SKILL.md +35 -29
- package/package.json +7 -6
- package/dist/regenerate/choose-conformance.d.ts +0 -32
- package/dist/regenerate/choose-conformance.js +0 -117
- /package/dist/{validate-cli.d.ts → parse-cli.d.ts} +0 -0
package/dist/host-session.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { type AgentSession, type ExtensionFactory, type ExtensionUIContext } from "@earendil-works/pi-coding-agent";
|
|
2
2
|
import type { AskUserIO } from "./ask.ts";
|
|
3
3
|
import { type ChatInfo, type TurriHost } from "./chats.ts";
|
|
4
|
+
import { type EvaluateOutcome } from "./advisor-chat.ts";
|
|
4
5
|
import type { JobRegistry } from "./regenerate/jobs.ts";
|
|
5
6
|
import type { WorkLoop } from "./regenerate/loop.ts";
|
|
6
7
|
import type { Notice, NoticeAnswer } from "./notice.ts";
|
|
@@ -66,6 +67,31 @@ export interface Turri {
|
|
|
66
67
|
* hears each as it is put (`onNotice`) and as it ends (`onNoticeOver`).
|
|
67
68
|
*/
|
|
68
69
|
notices(): Notice[];
|
|
70
|
+
/**
|
|
71
|
+
* The test advisor asked to evaluate functional specs, as the chat's `evaluate_tests` does - for a host's own way in,
|
|
72
|
+
* a button on a functional spec: `module:func-id`s, or func-ids of `plainFile`'s module, even a text judged already and
|
|
73
|
+
* whatever `test-advisor` says, `reason` given to it as context. It returns at once; each verdict comes to the chat the
|
|
74
|
+
* person looks at, as the advisor's verdicts do - a yes starting a turn that writes the scenarios, a no a line.
|
|
75
|
+
*/
|
|
76
|
+
evaluateTests(funcIds: string[], options?: {
|
|
77
|
+
plainFile?: string;
|
|
78
|
+
reason?: string;
|
|
79
|
+
}): EvaluateOutcome;
|
|
80
|
+
/**
|
|
81
|
+
* Every value /turri-config offers for a setting after `typed` - what its completions compute, in their order, but
|
|
82
|
+
* whole: uncapped, and without "unset", which a host draws itself; the values alone, not `<key> <value>`. A model
|
|
83
|
+
* setting's are every model of every provider signed in to, from the model registry the chats use - and after a colon,
|
|
84
|
+
* `harness-model amazon-bedrock/global.anthropic.claude-opus-5-5:`, that model's thinking levels. An unknown key gives none.
|
|
85
|
+
*/
|
|
86
|
+
settingChoices(key: string, typed?: string): string[];
|
|
87
|
+
/**
|
|
88
|
+
* Conformance tests turned on, as the chat's turn_on_conformance_tests does: `conformance-tests: true` written where
|
|
89
|
+
* the module's value comes from - its stack's `config.turri.<stack>.yaml` when that sets the key, else
|
|
90
|
+
* `config.turri.yaml` - and every open chat's tools switched (conform and evaluate_tests in, turn_on_conformance_tests
|
|
91
|
+
* out), the test advisor starting at its next look. `plainFile`, absolute or from the project, picks the module; omitted,
|
|
92
|
+
* the project's. Returns the file written, from the project. Starts no conformance pulse: that is `conform`'s.
|
|
93
|
+
*/
|
|
94
|
+
turnOnConformanceTests(plainFile?: string): string;
|
|
69
95
|
/**
|
|
70
96
|
* A notice answered: one of its actions (by index or label) - the chat it is in started on it - the person's own words
|
|
71
97
|
* about it, dismissed, or - `ignorable: true` - ignored for good: left as the build has it, the sentinel told not to
|
package/dist/host-session.js
CHANGED
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
import { createAgentSession, DefaultResourceLoader, getAgentDir, SessionManager } from "@earendil-works/pi-coding-agent";
|
|
2
2
|
import { lastRun } from "./chat-records.js";
|
|
3
3
|
import { interruptChat } from "./chats.js";
|
|
4
|
-
import {
|
|
4
|
+
import { evaluateTests } from "./advisor-chat.js";
|
|
5
|
+
import { reachable, ruleNames, settingCandidates } from "./config-command.js";
|
|
6
|
+
import { settingOf } from "./config-edit.js";
|
|
7
|
+
import { createTurriCore, sessionAdvisor, sessionLoop, turnOnConformance } from "./extension.js";
|
|
5
8
|
import { stopDeployed } from "./regenerate/release.js";
|
|
6
9
|
/** turri's session in a host, in the process's working folder - the project's. */
|
|
7
10
|
export async function createTurri(options = {}) {
|
|
8
11
|
const { dialogs, uiContext, extensions = [], agentDir = getAgentDir(), sessionDir, restore, ...host } = options;
|
|
9
|
-
const core = createTurriCore(host, { persist: true, ...(dialogs !== undefined ? { dialogs } : {}) });
|
|
12
|
+
const core = createTurriCore(host, { persist: true, advisor: true, ...(dialogs !== undefined ? { dialogs } : {}) });
|
|
10
13
|
const cwd = core.cwd;
|
|
11
14
|
core.setDriver({
|
|
12
15
|
async create(chat, sessionFile) {
|
|
@@ -68,6 +71,31 @@ export async function createTurri(options = {}) {
|
|
|
68
71
|
},
|
|
69
72
|
decline: async (id) => core.decline(id),
|
|
70
73
|
notices: () => core.notices(),
|
|
74
|
+
evaluateTests: (funcIds, options) => evaluateTests(cwd, sessionAdvisor(core), funcIds, options),
|
|
75
|
+
turnOnConformanceTests: (plainFile) => turnOnConformance(core, plainFile),
|
|
76
|
+
settingChoices: (key, typed = "") => {
|
|
77
|
+
const setting = settingOf(key, ruleNames());
|
|
78
|
+
if (setting === undefined)
|
|
79
|
+
return [];
|
|
80
|
+
// The models from a chat's own context - the one shown, else any open: the registry the chats use, whether or not one
|
|
81
|
+
// has run /turri-config.
|
|
82
|
+
const context = () => {
|
|
83
|
+
const shown = core.shownChat();
|
|
84
|
+
const states = [shown, ...core.chats().map((chat) => core.session(chat.id)).map((session) => (session !== undefined ? core.chatOfSession(session) : undefined))];
|
|
85
|
+
for (const state of states) {
|
|
86
|
+
try {
|
|
87
|
+
const context = state?.instance?.context();
|
|
88
|
+
if (context !== undefined)
|
|
89
|
+
return context;
|
|
90
|
+
}
|
|
91
|
+
catch {
|
|
92
|
+
/* a context let go: the next one */
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
return undefined;
|
|
96
|
+
};
|
|
97
|
+
return settingCandidates(setting, typed, { cwd, models: () => reachable(context()) });
|
|
98
|
+
},
|
|
71
99
|
answer: async (id, answer) => core.answer(id, answer),
|
|
72
100
|
onChats: (listener) => core.onChats(() => listener(core.chats())),
|
|
73
101
|
dispose,
|
package/dist/host.d.ts
CHANGED
|
@@ -10,9 +10,10 @@ export { SENTINEL, SENTINEL_START, type Conclusion, type Notice, type NoticeActi
|
|
|
10
10
|
export type { AskUserIO } from "./ask.ts";
|
|
11
11
|
/** pi itself, as turri is built against it: a host's own extensions and UI are made with this one, not another copy. */
|
|
12
12
|
export * as pi from "@earendil-works/pi-coding-agent";
|
|
13
|
-
export { configForSpec, debugMode, hasProjectConfig, modelSpec, projectModels, readProjectConfig, stacksOf, type ProjectConfig } from "./config.ts";
|
|
13
|
+
export { configForSpec, debugMode, DEFAULT_TEST_DIR, hasProjectConfig, modelSpec, projectModels, readProjectConfig, stacksOf, testDirOf, type ProjectConfig } from "./config.ts";
|
|
14
14
|
export { MODULES_DIR, projectDirOf, resolveTemplateDirs } from "./regenerate/paths.ts";
|
|
15
15
|
export { configSettings, currentValue, EFFECT_TEXT, overriddenBy, readConfigText, type Effect, type Setting, type SettingKind } from "./config-edit.ts";
|
|
16
|
+
export { bedrockRegionFor, type BedrockRegion, type BedrockRegionSource } from "./bedrock-region.ts";
|
|
16
17
|
export { BEDROCK_DEFAULT, BEDROCK_GEOGRAPHIES, BEDROCK_IN_REGION, BEDROCK_REGIONS, bedrockAwsRegion, bedrockDefaultModels, bedrockMakers, bedrockModels, bedrockModelsIn, bedrockNeedsAwsRegion, bedrockPlaceOf, initConfig, makerLabel, VENDORS, type BedrockChoice, type BedrockMaker, type BedrockOffer, type InitConfigOptions, type ModelChoice, type ModelSet, type Vendor, } from "./init-config.ts";
|
|
17
18
|
export { piModelCatalogue, type CatalogueModel, type ModelCatalogue } from "./model-check.ts";
|
|
18
19
|
export { doctor, type Check, type DoctorOptions, type Level } from "./setup.ts";
|
|
@@ -22,11 +23,13 @@ export { FUNCTIONAL_REQUIREMENTS, iterateFunctionalSpecs } from "./plain/spec.ts
|
|
|
22
23
|
export { highlightLines, roleOf, type PlainRole } from "./plain/highlight.ts";
|
|
23
24
|
export { conceptsOf, type ModuleConcept } from "./plain/module-concepts.ts";
|
|
24
25
|
export { conceptBeingTyped, findConcepts } from "./plain/concepts.ts";
|
|
25
|
-
export { plainGraph, type PlainConceptNode, type PlainGraph, type PlainItemNode, type PlainLink, type PlainModuleNode, type PlainSection } from "./plain/graph.ts";
|
|
26
|
+
export { plainGraph, type PlainConceptNode, type PlainGraph, type PlainItemNode, type PlainLink, type PlainModuleNode, type PlainScenario, type PlainSection, type PlainTestPlainFileNode } from "./plain/graph.ts";
|
|
26
27
|
export { isStack, STDLIB_KINDS, stdlibTemplates, type StdlibKind, type StdlibTemplate } from "./stdlib.ts";
|
|
27
28
|
export { createWorkLoop, describeModules, functionalityCompletion, promptOf, type DriftReport, type ModuleStatus, type WorkLoop } from "./regenerate/loop.ts";
|
|
28
29
|
export { createJobRegistry, defaultParallelJobs, type Job, type JobRegistry, type PulseCases, type PulseSpec } from "./regenerate/jobs.ts";
|
|
29
30
|
export { describeTurnIncident, onModelEvent, type TranscriptEntry } from "./regenerate/activity.ts";
|
|
30
31
|
export { sweepOrphanedGroups } from "./regenerate/shell.ts";
|
|
32
|
+
export { readAdvisor, textHash, type AdvisorEntry, type AdvisorFile, type AdvisorReport, type AdvisorState } from "./regenerate/advisor-records.ts";
|
|
33
|
+
export type { EvaluateOutcome } from "./advisor-chat.ts";
|
|
31
34
|
export { ledgerDir, onLedgerEvent, readLedger, type AgentRef, type LedgerEntry, type LedgerEvent, type LedgerKind, type LedgerQuery } from "./regenerate/ledger.ts";
|
|
32
35
|
export { asJob, describePulseView, describeRuns, earlierPulses, ledgerProjects, pulseView, runViews, type PulseView, type RunView } from "./regenerate/ledger-view.ts";
|
package/dist/host.js
CHANGED
|
@@ -12,11 +12,14 @@ export { SENTINEL, SENTINEL_START } from "./notice.js";
|
|
|
12
12
|
/** pi itself, as turri is built against it: a host's own extensions and UI are made with this one, not another copy. */
|
|
13
13
|
export * as pi from "@earendil-works/pi-coding-agent";
|
|
14
14
|
// The project and its settings.
|
|
15
|
-
export { configForSpec, debugMode, hasProjectConfig, modelSpec, projectModels, readProjectConfig, stacksOf } from "./config.js";
|
|
15
|
+
export { configForSpec, debugMode, DEFAULT_TEST_DIR, hasProjectConfig, modelSpec, projectModels, readProjectConfig, stacksOf, testDirOf } from "./config.js";
|
|
16
16
|
export { MODULES_DIR, projectDirOf, resolveTemplateDirs } from "./regenerate/paths.js";
|
|
17
17
|
// Every setting of config.turri.yaml as /turri-config knows it - what it takes, what it is unset, when a change takes
|
|
18
18
|
// effect - and what the file has now: for a host that shows them all, changing each through /turri-config.
|
|
19
19
|
export { configSettings, currentValue, EFFECT_TEXT, overriddenBy, readConfigText } from "./config-edit.js";
|
|
20
|
+
// The AWS region a project's Bedrock models are called in, and where it comes from - what turri sets itself, as a host's
|
|
21
|
+
// session starts, when the models need one and the person set none.
|
|
22
|
+
export { bedrockRegionFor } from "./bedrock-region.js";
|
|
20
23
|
// A project's first config.turri.yaml, as `turri init-config` writes it - the vendor, or the two models themselves, chosen by the host.
|
|
21
24
|
export { BEDROCK_DEFAULT, BEDROCK_GEOGRAPHIES, BEDROCK_IN_REGION, BEDROCK_REGIONS, bedrockAwsRegion, bedrockDefaultModels, bedrockMakers, bedrockModels, bedrockModelsIn, bedrockNeedsAwsRegion, bedrockPlaceOf, initConfig, makerLabel, VENDORS, } from "./init-config.js";
|
|
22
25
|
// pi's model catalogue, read without a request: what initConfig checks the models given against, and what a host offers.
|
|
@@ -41,6 +44,9 @@ export { createWorkLoop, describeModules, functionalityCompletion, promptOf } fr
|
|
|
41
44
|
export { createJobRegistry, defaultParallelJobs } from "./regenerate/jobs.js";
|
|
42
45
|
export { describeTurnIncident, onModelEvent } from "./regenerate/activity.js";
|
|
43
46
|
export { sweepOrphanedGroups } from "./regenerate/shell.js";
|
|
47
|
+
// The test advisor: what it made of each functional spec of a module - pending, yes, no or failed, with its report - by
|
|
48
|
+
// func-id, an entry current while its hash is textHash of the functional spec's text; and what an evaluation came to.
|
|
49
|
+
export { readAdvisor, textHash } from "./regenerate/advisor-records.js";
|
|
44
50
|
// What turri did, as facts: the ledger, heard live and read back - this session's pulses and every earlier one's.
|
|
45
51
|
export { ledgerDir, onLedgerEvent, readLedger } from "./regenerate/ledger.js";
|
|
46
52
|
export { asJob, describePulseView, describeRuns, earlierPulses, ledgerProjects, pulseView, runViews } from "./regenerate/ledger-view.js";
|
package/dist/init-config.d.ts
CHANGED
|
@@ -108,12 +108,12 @@ export declare function withModels(text: string, lines: [string, string]): strin
|
|
|
108
108
|
* must stay what the code falls back to - tests/init-config.test.ts holds them to the constants they mirror.
|
|
109
109
|
*/
|
|
110
110
|
export declare const DEFAULTS: {
|
|
111
|
-
readonly conformanceTests: false;
|
|
112
111
|
readonly review: false;
|
|
113
112
|
readonly mutationTesting: true;
|
|
114
113
|
readonly allowToStopJobs: true;
|
|
115
114
|
readonly releaseAfterPulse: true;
|
|
116
115
|
readonly sentinel: "ask";
|
|
116
|
+
readonly testAdvisor: true;
|
|
117
117
|
readonly testingScriptsRunOn: "in-place";
|
|
118
118
|
readonly turnLimit: 120;
|
|
119
119
|
readonly compactAt: 100000;
|
package/dist/init-config.js
CHANGED
|
@@ -215,12 +215,12 @@ export function withModels(text, lines) {
|
|
|
215
215
|
* must stay what the code falls back to - tests/init-config.test.ts holds them to the constants they mirror.
|
|
216
216
|
*/
|
|
217
217
|
export const DEFAULTS = {
|
|
218
|
-
conformanceTests: false,
|
|
219
218
|
review: false,
|
|
220
219
|
mutationTesting: true,
|
|
221
220
|
allowToStopJobs: true,
|
|
222
221
|
releaseAfterPulse: true,
|
|
223
222
|
sentinel: "ask",
|
|
223
|
+
testAdvisor: true,
|
|
224
224
|
testingScriptsRunOn: "in-place",
|
|
225
225
|
turnLimit: 120,
|
|
226
226
|
compactAt: 100000,
|
|
@@ -247,10 +247,10 @@ export function quickStartConfig(vendor = "other", bedrock, models) {
|
|
|
247
247
|
"# built: change one to change it. The optional ones, which have no value of their own, are commented out - uncomment",
|
|
248
248
|
"# one to use it. docs/config.md has them all.",
|
|
249
249
|
"",
|
|
250
|
-
"#
|
|
251
|
-
"#
|
|
252
|
-
"#
|
|
253
|
-
|
|
250
|
+
"# Whether functional specs are conformance tested: black-box tests of the built software against the scenarios of",
|
|
251
|
+
"# their test plain files, run with the whole suite as more lands. false: none - no scenarios written or tested, the",
|
|
252
|
+
"# test advisor off. Asking for them in the chat turns them on, or true here.",
|
|
253
|
+
"conformance-tests: false",
|
|
254
254
|
"",
|
|
255
255
|
"# Whether the code and its tests are reviewed once they pass - two reviews at most, the second weighed by the arbiter.",
|
|
256
256
|
`review: ${DEFAULTS.review}`,
|
|
@@ -270,6 +270,11 @@ export function quickStartConfig(vendor = "other", bedrock, models) {
|
|
|
270
270
|
"# before it first opens in a session; true: it opens without asking; false: none.",
|
|
271
271
|
`sentinel: ${DEFAULTS.sentinel}`,
|
|
272
272
|
"",
|
|
273
|
+
"# Whether turri checks, in the background, each new or changed functional spec with no scenarios - could it fail",
|
|
274
|
+
"# silently, be read two ways, cost a lot when wrong - and when it needs testing, writes its test reqs, conformance",
|
|
275
|
+
"# testing script and scenarios itself. false: only the scenarios you ask for are written.",
|
|
276
|
+
`test-advisor: ${DEFAULTS.testAdvisor}`,
|
|
277
|
+
"",
|
|
273
278
|
"# What the testing scripts run on: in-place - the code itself; copy - a fresh copy of it.",
|
|
274
279
|
`testing-scripts-run-on: ${DEFAULTS.testingScriptsRunOn}`,
|
|
275
280
|
"",
|
|
@@ -323,9 +328,13 @@ export function quickStartConfig(vendor = "other", bedrock, models) {
|
|
|
323
328
|
"# Optional: the .plain file turri regenerate builds when none is named.",
|
|
324
329
|
"# module: app.plain",
|
|
325
330
|
"",
|
|
326
|
-
"# Optional
|
|
327
|
-
"# Without it,
|
|
328
|
-
"#
|
|
331
|
+
"# Optional: the folder of the test plain files - a functional spec's conformance and acceptance scenarios - a folder",
|
|
332
|
+
"# per module in it: tests/<module>/<func-id>.plain. Without it, tests.",
|
|
333
|
+
"# test-dir: tests",
|
|
334
|
+
"",
|
|
335
|
+
"# Optional: a folder the code starts from - an existing codebase to build on, or files to use, such as images. It is",
|
|
336
|
+
"# copied in once, before the first pulse, and never written to; the ***plain can refer to it, and link into it.",
|
|
337
|
+
"# base-folder: existing-app",
|
|
329
338
|
"",
|
|
330
339
|
"# Optional: the judge and test review of a conformance run, when not on coding-model. A model is provider/id,",
|
|
331
340
|
"# provider/id:thinking, or { model, thinking } - thinking is off, minimal, low, medium, high, xhigh or max.",
|
|
@@ -337,7 +346,6 @@ export function quickStartConfig(vendor = "other", bedrock, models) {
|
|
|
337
346
|
`# default: ${coding}`,
|
|
338
347
|
`${column(`# chat: ${harness}`, 72)}# the conversation - as harness-model, which it wins over`,
|
|
339
348
|
`${column(`# sentinel: ${harness}`, 72)}# the sentinel: checks every finished pulse and tests the release`,
|
|
340
|
-
role("chooser", harness, "chooses what gets conformance tests under turri regenerate"),
|
|
341
349
|
role("planner", harness, "cuts the work into pulses"),
|
|
342
350
|
role("diagnosis", harness, "looks into a pulse that failed for good"),
|
|
343
351
|
role("release", coding, "turri release's agent, and release-after-pulse's"),
|
|
@@ -349,6 +357,7 @@ export function quickStartConfig(vendor = "other", bedrock, models) {
|
|
|
349
357
|
role("judge", strong, "judges a failing conformance run - as judge-model, which it wins over"),
|
|
350
358
|
role("arbiter", strong, "weighs a second review"),
|
|
351
359
|
role("debugger", strong, "a fresh look at unit tests that keep failing the same way"),
|
|
360
|
+
role("advisor", coding, "the test advisor: which functional specs need scenarios"),
|
|
352
361
|
"",
|
|
353
362
|
].join("\n");
|
|
354
363
|
}
|
|
@@ -411,12 +420,12 @@ function signInText(vendor, bedrock, models) {
|
|
|
411
420
|
return [
|
|
412
421
|
brand.bold("Sign in to AWS"),
|
|
413
422
|
` ${set("AWS_PROFILE")} ${brand.muted("your profile (aws configure, or aws sso login)")}`,
|
|
414
|
-
` ${set("AWS_REGION", region)}`,
|
|
415
423
|
` ${brand.muted("or, instead of a profile, a Bedrock API key:")} ${set("AWS_BEARER_TOKEN_BEDROCK")}`,
|
|
416
424
|
"",
|
|
417
425
|
brand.muted(keep),
|
|
426
|
+
// The region is turri's to set (bedrock-region.ts): said, not asked for.
|
|
418
427
|
...(bedrockNeedsAwsRegion(geography)
|
|
419
|
-
? [brand.muted(`
|
|
428
|
+
? [brand.muted(`turri calls ${geography}'s models in ${region}. AWS_REGION, set, overrides it - and so does your AWS profile's region, when it is in ${geography}.`)]
|
|
420
429
|
: []),
|
|
421
430
|
brand.muted("Your AWS account needs access to the models: Bedrock console, model access."),
|
|
422
431
|
];
|
package/dist/loop-cli.d.ts
CHANGED
|
@@ -25,10 +25,10 @@ export declare function runLoop(options: {
|
|
|
25
25
|
export declare function moduleStates(reports: DriftReport[]): ModuleState[];
|
|
26
26
|
/**
|
|
27
27
|
* The options every command that regenerates takes for a headless run: `--report` and `--build-dir`, and the config's
|
|
28
|
-
* own keys (configKeyOptions) - `--harness-model`, `--coding-model` (`--model`), `--judge-model`, `--review
|
|
29
|
-
*
|
|
28
|
+
* own keys (configKeyOptions) - `--harness-model`, `--coding-model` (`--model`), `--judge-model`, `--review` and
|
|
29
|
+
* `--mutation-testing` - read as if config.turri.yaml had them. Exits on a value it cannot read.
|
|
30
30
|
*/
|
|
31
|
-
export declare function headlessOptions(options: Record<string, string | undefined
|
|
31
|
+
export declare function headlessOptions(options: Record<string, string | undefined>): {
|
|
32
32
|
report?: string;
|
|
33
33
|
buildDir?: string;
|
|
34
34
|
};
|
package/dist/loop-cli.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { sweepOrphanedGroups } from "./regenerate/shell.js";
|
|
2
|
+
import { refuseTestPlainFile } from "./test-plain-files.js";
|
|
2
3
|
import { createInterface } from "node:readline/promises";
|
|
3
4
|
import { resolve, sep } from "node:path";
|
|
4
5
|
import { configForSpec, inheritModel, modelOnly, modelSpec, projectModels, readProjectConfig, roleModel, ROLE_THINKING, splitModelSpec, } from "./config.js";
|
|
@@ -9,7 +10,6 @@ import { ledgerWanted, startLedger } from "./regenerate/ledger.js";
|
|
|
9
10
|
import { tryItCommand } from "./regenerate/delivery.js";
|
|
10
11
|
import { describeDiagnosis, diagnoseFailure } from "./regenerate/diagnose.js";
|
|
11
12
|
import { createJobRegistry, pulseName } from "./regenerate/jobs.js";
|
|
12
|
-
import { conformanceChooser } from "./regenerate/choose-conformance.js";
|
|
13
13
|
import { createWorkLoop, describeModules, functionalityCompletion, promptOf } from "./regenerate/loop.js";
|
|
14
14
|
import { MODULES_DIR, projectDirOf } from "./regenerate/paths.js";
|
|
15
15
|
import { exportModule } from "./regenerate/release.js";
|
|
@@ -25,6 +25,7 @@ import { configKeyOptions, optionValue } from "./cli-options.js";
|
|
|
25
25
|
*/
|
|
26
26
|
export async function runLoop(options) {
|
|
27
27
|
const plainFile = resolve(options.plainFile);
|
|
28
|
+
refuseTestPlainFile(plainFile);
|
|
28
29
|
// What a turri that was killed left running - commands' process groups - stopped before anything starts.
|
|
29
30
|
const orphans = sweepOrphanedGroups();
|
|
30
31
|
if (orphans > 0)
|
|
@@ -54,7 +55,6 @@ export async function runLoop(options) {
|
|
|
54
55
|
specFile: plainFile,
|
|
55
56
|
projectDir,
|
|
56
57
|
...(buildDir !== undefined ? { buildDir } : {}),
|
|
57
|
-
conformanceTests: conformanceLabel(project.conformanceTests),
|
|
58
58
|
review: project.review === true,
|
|
59
59
|
mutationTesting: project.mutationTesting !== false,
|
|
60
60
|
models: reportModels(project, model),
|
|
@@ -111,9 +111,6 @@ async function runLoopReporting(options) {
|
|
|
111
111
|
...(model !== undefined ? { modelFor: () => model } : {}),
|
|
112
112
|
...(planner !== undefined ? { plannerModel: planner } : {}),
|
|
113
113
|
...(options.dryRun === true ? { dryRun: true } : {}),
|
|
114
|
-
// Under conformance-tests: chosen or module, the chooser decides as a pulse ends, as in the chat - on the harness
|
|
115
|
-
// model, else the coding model: never pi's own default, which may be one this account cannot reach.
|
|
116
|
-
onChoose: conformanceChooser({ model: () => planner ?? model, ...(options.dryRun === true ? { dryRun: true } : {}) }),
|
|
117
114
|
});
|
|
118
115
|
report?.attach({
|
|
119
116
|
jobs: () => registry.list(),
|
|
@@ -130,7 +127,9 @@ async function runLoopReporting(options) {
|
|
|
130
127
|
const toStartOver = planned.filter((status) => status.startOver !== undefined);
|
|
131
128
|
if (toStartOver.length > 0 && options.dryRun !== true) {
|
|
132
129
|
const why = toStartOver
|
|
133
|
-
.map(({ startOver }) =>
|
|
130
|
+
.map(({ startOver }) => startOver.old === true
|
|
131
|
+
? `${startOver.codebases.join(", ")} was built when functional specs were numbered, before they had func-ids: nothing more can be built on it.`
|
|
132
|
+
: `${startOver.codebases.join(", ")} was built without ${startOver.requires.join(", ")}, which it now requires: no change to its code can bring it in.`)
|
|
134
133
|
.join("\n");
|
|
135
134
|
// No terminal and no --start-over: no one to ask, so the run stops here rather than build nothing and say it is done.
|
|
136
135
|
if (options.startOver !== true && process.stdin.isTTY !== true) {
|
|
@@ -187,11 +186,13 @@ export function moduleStates(reports) {
|
|
|
187
186
|
? "start_over_needed"
|
|
188
187
|
: report.why !== undefined
|
|
189
188
|
? "halted"
|
|
190
|
-
: report.code === null && (report.conformance === null || report.conformance === undefined)
|
|
189
|
+
: report.code === null && (report.conformance === null || report.conformance === undefined)
|
|
191
190
|
? "complete"
|
|
192
191
|
: "incomplete";
|
|
193
192
|
const why = state === "start_over_needed"
|
|
194
|
-
?
|
|
193
|
+
? report.startOver.old === true
|
|
194
|
+
? "built when functional specs were numbered, before they had func-ids: run with --start-over to regenerate its chain from scratch"
|
|
195
|
+
: `built without ${report.startOver.requires.join(", ")}, which it now requires: run with --start-over`
|
|
195
196
|
: state === "incomplete"
|
|
196
197
|
? report.code !== null && report.code !== undefined
|
|
197
198
|
? "its code is not regenerated from the spec as it is"
|
|
@@ -230,10 +231,6 @@ function exportCode(plainFile, dir) {
|
|
|
230
231
|
return { exported: false, dir, why: error instanceof Error ? error.message : String(error) };
|
|
231
232
|
}
|
|
232
233
|
}
|
|
233
|
-
/** `conformance-tests:` as the report says it - not set is false. */
|
|
234
|
-
function conformanceLabel(setting) {
|
|
235
|
-
return setting === true ? "all" : setting === "chosen" || setting === "module" ? setting : "false";
|
|
236
|
-
}
|
|
237
234
|
/** The models of the three roles as this run uses them: the coding model given, the others as they fall back - each with the level it thinks at. */
|
|
238
235
|
function reportModels(project, model) {
|
|
239
236
|
const coding = splitModelSpec(model);
|
|
@@ -252,11 +249,11 @@ function reportModels(project, model) {
|
|
|
252
249
|
}
|
|
253
250
|
/**
|
|
254
251
|
* The options every command that regenerates takes for a headless run: `--report` and `--build-dir`, and the config's
|
|
255
|
-
* own keys (configKeyOptions) - `--harness-model`, `--coding-model` (`--model`), `--judge-model`, `--review
|
|
256
|
-
*
|
|
252
|
+
* own keys (configKeyOptions) - `--harness-model`, `--coding-model` (`--model`), `--judge-model`, `--review` and
|
|
253
|
+
* `--mutation-testing` - read as if config.turri.yaml had them. Exits on a value it cannot read.
|
|
257
254
|
*/
|
|
258
|
-
export function headlessOptions(options
|
|
259
|
-
configKeyOptions(options, {
|
|
255
|
+
export function headlessOptions(options) {
|
|
256
|
+
configKeyOptions(options, { review: true });
|
|
260
257
|
const report = optionValue(options, "report");
|
|
261
258
|
const buildDir = optionValue(options, "build-dir");
|
|
262
259
|
return { ...(report !== undefined ? { report } : {}), ...(buildDir !== undefined ? { buildDir } : {}) };
|
package/dist/loop-tools.js
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import { existsSync } from "node:fs";
|
|
2
|
+
import { refuseTestPlainFile } from "./test-plain-files.js";
|
|
2
3
|
import { basename, relative, resolve } from "node:path";
|
|
3
4
|
import { defineTool } from "@earendil-works/pi-coding-agent";
|
|
4
5
|
import { Type } from "typebox";
|
|
6
|
+
import { advisingNote } from "./advisor-chat.js";
|
|
5
7
|
import { CONFIG_FILE, readProjectConfig, stackConfigFile, stackForModule, stackNamed, stacksOf, withStack } from "./config.js";
|
|
6
|
-
import { checkPlainFile } from "./plain/check.js";
|
|
8
|
+
import { checkPlainFile, formatCheckResults } from "./plain/check.js";
|
|
7
9
|
import { describeDrift, describeModules } from "./regenerate/loop.js";
|
|
8
10
|
import { pulseName } from "./regenerate/jobs.js";
|
|
9
11
|
import { stopDeployed } from "./regenerate/release.js";
|
|
@@ -145,7 +147,9 @@ function plainFileOf(cwd, given, what) {
|
|
|
145
147
|
const named = located.plain_file ?? readProjectConfig(located.base).module;
|
|
146
148
|
if (named === undefined)
|
|
147
149
|
throw new Error(`Name the .plain file to ${what}, or set module: in ${CONFIG_FILE}.`);
|
|
148
|
-
|
|
150
|
+
const plainFile = resolve(located.base, named);
|
|
151
|
+
refuseTestPlainFile(plainFile);
|
|
152
|
+
return plainFile;
|
|
149
153
|
}
|
|
150
154
|
/** Whether a /regenerate's words ask for the module from scratch: its code deleted, and all of it regenerated again. */
|
|
151
155
|
export function asksFromScratch(words) {
|
|
@@ -165,14 +169,14 @@ export function regenerateTool(options) {
|
|
|
165
169
|
"requires chain first. Call it after any change to the spec, by any means: the file tools, a skill, the user in an " +
|
|
166
170
|
"editor. It takes no diff: what is left to regenerate - from what each module's code was regenerated from to its spec now - is " +
|
|
167
171
|
"worked out and planned into pulses, and a pulse running that regenerates something the spec no longer wants is stopped and " +
|
|
168
|
-
"rolled back. Nothing to do where the code is regenerated from the spec as it is. With
|
|
172
|
+
"rolled back. Nothing to do where the code is regenerated from the spec as it is. With funcIds named - each as module:func-id - those are " +
|
|
169
173
|
"regenerated though their spec did not change - their code taken out and built anew, better made, never left as it was - " +
|
|
170
174
|
"planned into pulses as any change is, the ones next to each other together; their conformance tests stay as they are.",
|
|
171
175
|
promptSnippet: "regenerate a module's code from its spec as it is now - after any change to the spec",
|
|
172
176
|
promptGuidelines: [
|
|
173
177
|
"Call regenerate after editing a .plain file with the file tools - or when the user says they changed one - instead of working out a diff: turri compares what is regenerated with the spec now.",
|
|
174
178
|
"regenerate returns at once with what runs and what is planned. Report it, keep talking, and use pulses when the user asks; the pulses report when they finish.",
|
|
175
|
-
"When the user wants a functionality to come out differently, change its spec - the spec is what persists - then regenerate. When they want ones already built regenerated as their spec stands - better made, on another model, after many patches - name them in
|
|
179
|
+
"When the user wants a functionality to come out differently, change its spec - the spec is what persists - then regenerate. When they want ones already built regenerated as their spec stands - better made, on another model, after many patches - name them in funcIds, each as module:func-id, all in one call.",
|
|
176
180
|
"A change to a file the spec links - an API surface, a mapping document - is a change to the spec: regenerate sees it by itself, and regenerates every functional spec that uses what links it.",
|
|
177
181
|
"Never stop pulses and start them again yourself to follow a spec change: regenerate does it.",
|
|
178
182
|
"Set from_scratch only when the user asks for the module to be regenerated from scratch - started over, its code deleted - in this conversation, or agrees to it when a module's status says it has to start over: never to fix a pulse that did not land.",
|
|
@@ -183,8 +187,8 @@ export function regenerateTool(options) {
|
|
|
183
187
|
plain_file: Type.Optional(Type.String({ description: "Path to the .plain file. Omitted: the module the project's config.turri.yaml names" })),
|
|
184
188
|
working_dir: WORKING_DIR_PARAM,
|
|
185
189
|
guidance: GUIDANCE_PARAM,
|
|
186
|
-
|
|
187
|
-
description: "Functional specs already built,
|
|
190
|
+
funcIds: Type.Optional(Type.Array(Type.String(), {
|
|
191
|
+
description: "Functional specs already built, each as module:func-id (todo:add-task), to regenerate though their spec did not change. Omitted: what the spec now differs from the code in",
|
|
188
192
|
})),
|
|
189
193
|
from_scratch: Type.Optional(Type.Union([Type.Literal("module"), Type.Literal("chain")], {
|
|
190
194
|
description: "Only when the user asks for it: the module's code and conformance tests deleted - committed first, so its lineage keeps them - and the whole module regenerated from its spec. " +
|
|
@@ -198,11 +202,12 @@ export function regenerateTool(options) {
|
|
|
198
202
|
const plainFile = plainFileOf(options.cwd, given, "regenerate");
|
|
199
203
|
return withCallStack(plainFile, given.stack, async () => {
|
|
200
204
|
const check = checkPlainFile(plainFile);
|
|
205
|
+
// The parser's message as it gives it, a test plain file out of place, and turri's next step for the old syntax.
|
|
201
206
|
if (!check.ok)
|
|
202
|
-
throw new Error(`${relative(options.cwd, plainFile) || plainFile} does not parse, so nothing can be regenerated from it yet
|
|
203
|
-
const again = given.
|
|
207
|
+
throw new Error(`${relative(options.cwd, plainFile) || plainFile} does not parse, so nothing can be regenerated from it yet:\n${formatCheckResults([check])}`);
|
|
208
|
+
const again = given.funcIds ?? [];
|
|
204
209
|
if (again.length > 0 && given.from_scratch !== undefined)
|
|
205
|
-
throw new Error("Name
|
|
210
|
+
throw new Error("Name funcIds or set from_scratch, not both: from scratch regenerates every one of them.");
|
|
206
211
|
// Named functionalities are work on functionalities, as engine chooses a model for it; the rest, spec changes.
|
|
207
212
|
const work = again.length > 0 ? "functionalities" : "spec_changes";
|
|
208
213
|
const model = options.model !== undefined ? options.model(ctx, plainFile, given.model, work) : given.model;
|
|
@@ -213,7 +218,10 @@ export function regenerateTool(options) {
|
|
|
213
218
|
: again.length > 0
|
|
214
219
|
? await loop.regenerateAgain(plainFile, again, request)
|
|
215
220
|
: await loop.bringUp(plainFile, request);
|
|
216
|
-
|
|
221
|
+
const reply = await loopReply(loop, statuses, options.wait !== undefined ? options.wait(ctx, given.wait) : given.wait === true);
|
|
222
|
+
// The functional specs the test advisor took up, for the agent to say so rather than offer their scenarios.
|
|
223
|
+
const advising = advisingNote(loop, plainFile);
|
|
224
|
+
return advising === "" ? reply : { ...reply, content: [...reply.content, { type: "text", text: advising }] };
|
|
217
225
|
});
|
|
218
226
|
},
|
|
219
227
|
});
|
package/dist/model-check.d.ts
CHANGED
|
@@ -59,7 +59,12 @@ export declare function piModelCatalogue(): Promise<ModelCatalogue>;
|
|
|
59
59
|
export declare function closestModels(id: string, known: string[]): string[];
|
|
60
60
|
/** pi's own model runtime, with pi's credentials - auth.json, models.json and the environment - as turri's agents have them. */
|
|
61
61
|
export declare function piModelAccess(): Promise<ModelAccess>;
|
|
62
|
-
/**
|
|
63
|
-
|
|
62
|
+
/**
|
|
63
|
+
* What to do about a provider's error, from what it says. `region`: for Bedrock, the region it is called in and where
|
|
64
|
+
* that comes from, as a line (bedrock-region.ts `describeBedrockRegion`) - turri sets it, so a person is not told to.
|
|
65
|
+
*/
|
|
66
|
+
export declare function fixFor(provider: string, problem: string, region?: string): string;
|
|
64
67
|
/** Each model the config uses, tried: answered, or what is wrong and what to do. One request a model. */
|
|
65
|
-
export declare function checkModels(models: UsedModel[], access: ModelAccess
|
|
68
|
+
export declare function checkModels(models: UsedModel[], access: ModelAccess, options?: {
|
|
69
|
+
bedrockRegion?: string;
|
|
70
|
+
}): Promise<ModelVerdict[]>;
|
package/dist/model-check.js
CHANGED
|
@@ -84,23 +84,28 @@ function signIn(provider) {
|
|
|
84
84
|
anthropic: "ANTHROPIC_API_KEY, or /login in turri",
|
|
85
85
|
openai: "OPENAI_API_KEY, or /login in turri",
|
|
86
86
|
google: "GEMINI_API_KEY",
|
|
87
|
-
"amazon-bedrock": "AWS_PROFILE (aws configure, or aws sso login) or AWS_BEARER_TOKEN_BEDROCK
|
|
87
|
+
"amazon-bedrock": "AWS_PROFILE (aws configure, or aws sso login) or AWS_BEARER_TOKEN_BEDROCK",
|
|
88
88
|
};
|
|
89
89
|
return keys[provider] ?? `the key pi reads for ${provider}, or /login in turri - https://pi.dev lists them`;
|
|
90
90
|
}
|
|
91
|
-
/**
|
|
92
|
-
|
|
91
|
+
/**
|
|
92
|
+
* What to do about a provider's error, from what it says. `region`: for Bedrock, the region it is called in and where
|
|
93
|
+
* that comes from, as a line (bedrock-region.ts `describeBedrockRegion`) - turri sets it, so a person is not told to.
|
|
94
|
+
*/
|
|
95
|
+
export function fixFor(provider, problem, region) {
|
|
93
96
|
const text = problem.toLowerCase();
|
|
97
|
+
const where = region !== undefined ? ` - ${region}` : " - the region pi calls Bedrock in, which AWS_REGION, set, chooses";
|
|
94
98
|
if (/access (to|denied).*model|don't have access|not authorized to (invoke|access)|model access|accessdenied/.test(text) && provider === "amazon-bedrock") {
|
|
95
|
-
return
|
|
99
|
+
return `ask for access to this model in the Bedrock console, under model access, for its region${where}`;
|
|
96
100
|
}
|
|
97
101
|
if (/provider is not configured|no credentials|not logged in/.test(text))
|
|
98
102
|
return `sign in to ${provider}: ${signIn(provider)}`;
|
|
99
103
|
if (/401|403|unauthori[sz]ed|forbidden|invalid.*(api key|x-api-key|token|credential)|credential|security token|could not load|unable to locate|expired|no api key|missing api key|authentication/.test(text)) {
|
|
100
104
|
return `check the credentials pi reads for ${provider}: ${signIn(provider)}`;
|
|
101
105
|
}
|
|
102
|
-
if (/region|endpoint|enotfound|getaddrinfo/.test(text))
|
|
103
|
-
return provider === "amazon-bedrock" ?
|
|
106
|
+
if (/region|endpoint|enotfound|getaddrinfo/.test(text)) {
|
|
107
|
+
return provider === "amazon-bedrock" ? `the model has to be served in the region it is called in${where}` : "check the network, and the provider's endpoint";
|
|
108
|
+
}
|
|
104
109
|
if (/not found|404|does not exist|unknown model|invalid model/.test(text))
|
|
105
110
|
return "the provider does not serve this model id: change it in config.turri.yaml";
|
|
106
111
|
if (/429|rate|quota|overloaded|capacity/.test(text))
|
|
@@ -117,7 +122,7 @@ function commonPrefix(a, b) {
|
|
|
117
122
|
return at;
|
|
118
123
|
}
|
|
119
124
|
/** Each model the config uses, tried: answered, or what is wrong and what to do. One request a model. */
|
|
120
|
-
export async function checkModels(models, access) {
|
|
125
|
+
export async function checkModels(models, access, options = {}) {
|
|
121
126
|
return Promise.all(models.map(async ({ spec, usedBy }) => {
|
|
122
127
|
const slash = spec.indexOf("/");
|
|
123
128
|
if (slash === -1)
|
|
@@ -136,6 +141,6 @@ export async function checkModels(models, access) {
|
|
|
136
141
|
if (problem === undefined)
|
|
137
142
|
return { ok: true, spec, usedBy, ms: Date.now() - started };
|
|
138
143
|
const said = problem.split("\n").find((line) => line.trim() !== "")?.trim().slice(0, 300) ?? problem;
|
|
139
|
-
return { ok: false, spec, usedBy, problem: said, fix: fixFor(provider, problem) };
|
|
144
|
+
return { ok: false, spec, usedBy, problem: said, fix: fixFor(provider, problem, provider === "amazon-bedrock" ? options.bedrockRegion : undefined) };
|
|
140
145
|
}));
|
|
141
146
|
}
|
package/dist/new-project.js
CHANGED
|
@@ -11,16 +11,20 @@ export const NEW_PROJECT = [
|
|
|
11
11
|
" install, and that turri doctor checks it. Read the stack's template, its language's and its kind's common first.",
|
|
12
12
|
"2. One module - a .plain file in the project's root, named after what it is (server.plain) - importing the stack and",
|
|
13
13
|
" writing only what the module needs beyond it. Two side by side, each on its stack, only when it needs two stacks.",
|
|
14
|
-
"3. config.turri.yaml: module: the new file
|
|
15
|
-
"
|
|
16
|
-
"4. The unit testing script: keep one turri already finds; otherwise
|
|
17
|
-
"
|
|
18
|
-
"
|
|
14
|
+
"3. config.turri.yaml: module: the new file. What a config there already settles - a stack, a script - is kept, not",
|
|
15
|
+
" chosen again.",
|
|
16
|
+
"4. The unit testing script: keep one turri already finds; otherwise start cultivate with implement-unit-testing-script,",
|
|
17
|
+
" plainFile the new module. It runs in the background: go straight on - the module's pulses wait for the script.",
|
|
18
|
+
" Tests only if the person asked for them: turn conformance tests on first (turn_on_conformance_tests), then in this",
|
|
19
|
+
" order: the ***test reqs*** - the stack's conformance template - then cultivate with",
|
|
20
|
+
" implement-conformance-testing-script, in the background too, then the scenarios.",
|
|
19
21
|
"5. The first functional spec: the smallest thing that runs and shows something - the server answers GET / with the",
|
|
20
|
-
" app's name, the CLI prints its usage
|
|
22
|
+
" app's name, the CLI prints its usage - with no test plain file, unless they asked for tests. parse, fix",
|
|
23
|
+
" what it finds, and regenerate at once.",
|
|
21
24
|
"6. While it regenerates: the main thing they described, on its happy path, and at most one more - each a functional",
|
|
22
|
-
" spec, with its concepts
|
|
23
|
-
" software, write none, and invite them to say what
|
|
25
|
+
" spec, with its concepts, and a test plain file only if they asked for tests - then parse and regenerate",
|
|
26
|
+
" again. Only what they described: they named only the kind of software, write none, and invite them to say what",
|
|
27
|
+
" it does. No validation or edge cases yet.",
|
|
24
28
|
"Then hand over in a few lines: what you chose, what is regenerating, and the next slices you would write - they say",
|
|
25
29
|
"go on, or what to change, and every change after is ***plain you write and regenerate.",
|
|
26
30
|
"</new-project>",
|
|
@@ -1,9 +1,13 @@
|
|
|
1
1
|
import { checkPlainTargets, formatCheckResults } from "./plain/check.js";
|
|
2
2
|
import { c } from "./module-report.js";
|
|
3
|
-
const USAGE = `usage: turri
|
|
3
|
+
const USAGE = `usage: turri parse <file.plain | directory> [options]
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
required modules,
|
|
5
|
+
Parses ***plain - its syntax and structure, never its code or tests: each module with its test plain files,
|
|
6
|
+
its imports and required modules, every error reported without regenerating anything - and every test plain file
|
|
7
|
+
outside its module's folder. A functional spec with no test plain file is not tested. A module whose
|
|
8
|
+
functional specs have scenarios but which has no test reqs, or no conformance testing script for its
|
|
9
|
+
stack, is a warning: its conformance tests are not written until it has them. A test plain file or
|
|
10
|
+
test folder is refused: name its module.
|
|
7
11
|
|
|
8
12
|
--template-dir <dir> extra template directory (repeatable)
|
|
9
13
|
--json machine-readable output
|
|
@@ -38,10 +42,12 @@ if (json) {
|
|
|
38
42
|
else {
|
|
39
43
|
const output = formatCheckResults(results)
|
|
40
44
|
.split("\n")
|
|
41
|
-
.map((line) => line.startsWith("PASS") ? c.success(line) : line.startsWith("FAIL") ? c.error(line) : c.dim(line))
|
|
45
|
+
.map((line) => line.startsWith("PASS") ? c.success(line) : line.startsWith("FAIL") ? c.error(line) : line.startsWith("WARN") ? c.warning(line) : c.dim(line))
|
|
42
46
|
.join("\n");
|
|
43
47
|
console.log(output);
|
|
44
48
|
const failed = results.filter((r) => !r.ok).length;
|
|
45
|
-
|
|
49
|
+
const warned = results.reduce((count, r) => count + (r.warnings?.length ?? 0), 0);
|
|
50
|
+
const warnings = warned > 0 ? c.warning(` - ${warned} warning${warned === 1 ? "" : "s"}`) : "";
|
|
51
|
+
console.log(`\n${failed === 0 ? c.success(c.bold("all specs valid")) + warnings : c.error(c.bold(`${failed} of ${results.length} failed`))}`);
|
|
46
52
|
}
|
|
47
53
|
process.exit(results.every((r) => r.ok) ? 0 : 1);
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { Type } from "typebox";
|
|
2
|
+
/** parse, for the conversation and for the skills that write specs alike: it checks the ***plain, never the code. */
|
|
3
|
+
export declare function checkPlainTool(cwd: string): import("@earendil-works/pi-coding-agent").ToolDefinition<Type.TObject<{
|
|
4
|
+
target: Type.TString;
|
|
5
|
+
template_dir: Type.TOptional<Type.TArray<Type.TString>>;
|
|
6
|
+
}>, {
|
|
7
|
+
failed: number;
|
|
8
|
+
checked: number;
|
|
9
|
+
}, any> & import("@earendil-works/pi-coding-agent").ToolDefinition<any, any, any>;
|