@turri-dev/cli 0.1.9 → 0.1.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,11 @@
1
+ import { type ToolDefinition } from "@earendil-works/pi-coding-agent";
2
+ type AnyTool = ToolDefinition<any, any, any>;
3
+ /**
4
+ * doctor: `turri doctor`'s checks from inside the conversation - this machine, and the project the conversation is in -
5
+ * against turri's own environment, the one its pulses run with, not the agent's shell's. Changes nothing; asks the
6
+ * project's models only when told to, a request a model.
7
+ */
8
+ export declare function doctorTool(options: {
9
+ cwd: string;
10
+ }): AnyTool;
11
+ export {};
@@ -0,0 +1,33 @@
1
+ import { join } from "node:path";
2
+ import { defineTool } from "@earendil-works/pi-coding-agent";
3
+ import { Type } from "typebox";
4
+ import { projectDirOf } from "./regenerate/paths.js";
5
+ import { describeChecks, doctor, verdictOf } from "./setup.js";
6
+ /**
7
+ * doctor: `turri doctor`'s checks from inside the conversation - this machine, and the project the conversation is in -
8
+ * against turri's own environment, the one its pulses run with, not the agent's shell's. Changes nothing; asks the
9
+ * project's models only when told to, a request a model.
10
+ */
11
+ export function doctorTool(options) {
12
+ return defineTool({
13
+ name: "doctor",
14
+ label: "Doctor",
15
+ description: "Whether this machine and this project are ready for turri, as turri doctor checks it: Node, bash, git, which OS " +
16
+ "sandbox is up under the agents' commands, whether a model provider has credentials, the toolchains the modules' " +
17
+ "implementation reqs name and what the testing scripts run that this machine lacks - against the PATH turri's pulses " +
18
+ "run with. With models: true, each model config.turri.yaml names is asked for a word with this machine's credentials - " +
19
+ "a request a model, which costs money. Changes nothing.",
20
+ promptSnippet: "doctor: turri's self check - this machine and project, ready or what to fix",
21
+ promptGuidelines: [
22
+ "Use doctor, not `turri doctor` in the shell, to check whether this machine and project are ready - when the person asks, when a pulse fails for a missing toolchain or command, or before the first build on a machine. Ask the models (models: true) only when the person asks, or a model fails to answer: it costs a request a model.",
23
+ ],
24
+ parameters: Type.Object({
25
+ models: Type.Optional(Type.Boolean({ description: "Ask each model the project's config names for a word - one paid request a model. Default false" })),
26
+ }),
27
+ async execute(_id, params) {
28
+ const checks = await doctor({ dir: projectDirOf(join(options.cwd, "session.plain")), models: params.models === true });
29
+ const verdict = verdictOf(checks);
30
+ return { content: [{ type: "text", text: describeChecks(checks) }], details: { ready: verdict.ready, limited: verdict.limited } };
31
+ },
32
+ });
33
+ }
package/dist/extension.js CHANGED
@@ -46,6 +46,7 @@ import { defaultBuildDir } from "./regenerate/paths.js";
46
46
  import { describeTurnIncident, describeUsage, onModelEvent } from "./regenerate/activity.js";
47
47
  import { ledgerWanted, startLedger } from "./regenerate/ledger.js";
48
48
  import { describePastPulse, describeRuns, earlierPulses, ledgerProjects } from "./regenerate/ledger-view.js";
49
+ import { doctorTool } from "./doctor-tool.js";
49
50
  import { ledgerTool } from "./ledger-tools.js";
50
51
  import { describeSpecConflict } from "./regenerate/stop-report.js";
51
52
  import { inheritProviders, inheritThinkingLevel } from "./pi.js";
@@ -1497,6 +1498,7 @@ function registerJobTools(pi, jobs, cwd) {
1497
1498
  },
1498
1499
  });
1499
1500
  pi.registerTool(ledgerTool({ cwd }));
1501
+ pi.registerTool(doctorTool({ cwd }));
1500
1502
  pi.registerTool({
1501
1503
  name: "pulses",
1502
1504
  label: "Pulses",
@@ -1992,7 +1994,7 @@ export const JOB_FINISHED_REACTION = [
1992
1994
  " JavaVirtualMachines, a version manager the person uses - mise, asdf, sdkman, nvm). Then ask the person with ask_user",
1993
1995
  " to let you put it in place the way this machine installs things - the exact command, `brew install openjdk@21`,",
1994
1996
  " `mise use -g java@21`, `sdk install maven` - and on yes run it in your shell, check that the command is found now as",
1995
- " the testing script would find it (`command -v`, `turri doctor`), and resume. A tool installed where the PATH turri",
1997
+ " the testing script would find it (`command -v`, then the doctor tool, which looks on turri's own PATH), and resume. A tool installed where the PATH turri",
1996
1998
  " was started with does not reach needs turri restarted: say so, with the line for the shell profile. On no, or when it",
1997
1999
  " needs what you cannot do - sudo with a password, a licence, a download behind a login - tell the person exactly what",
1998
2000
  " to do, and that \"resume\" picks it up once it is in.",
package/dist/host.d.ts CHANGED
@@ -10,7 +10,9 @@ export type { AskUserIO } from "./ask.ts";
10
10
  export * as pi from "@earendil-works/pi-coding-agent";
11
11
  export { configForSpec, debugMode, hasProjectConfig, modelSpec, projectModels, readProjectConfig, stacksOf, type ProjectConfig } from "./config.ts";
12
12
  export { MODULES_DIR, projectDirOf, resolveTemplateDirs } from "./regenerate/paths.ts";
13
- export { BEDROCK_DEFAULT, BEDROCK_REGIONS, bedrockModels, initConfig, VENDORS, type BedrockChoice, type Vendor } from "./init-config.ts";
13
+ 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";
14
+ export { piModelCatalogue, type CatalogueModel, type ModelCatalogue } from "./model-check.ts";
15
+ export { doctor, type Check, type DoctorOptions, type Level } from "./setup.ts";
14
16
  export { checkPlainFile, type CheckResult } from "./plain/check.ts";
15
17
  export { plainFileParser } from "./plain/parser.ts";
16
18
  export { FUNCTIONAL_REQUIREMENTS, iterateFunctionalSpecs } from "./plain/spec.ts";
package/dist/host.js CHANGED
@@ -11,8 +11,12 @@ export * as pi from "@earendil-works/pi-coding-agent";
11
11
  // The project and its settings.
12
12
  export { configForSpec, debugMode, hasProjectConfig, modelSpec, projectModels, readProjectConfig, stacksOf } from "./config.js";
13
13
  export { MODULES_DIR, projectDirOf, resolveTemplateDirs } from "./regenerate/paths.js";
14
- // A project's first config.turri.yaml, as `turri init-config` writes it - the vendor whose models it takes chosen by the host.
15
- export { BEDROCK_DEFAULT, BEDROCK_REGIONS, bedrockModels, initConfig, VENDORS } from "./init-config.js";
14
+ // A project's first config.turri.yaml, as `turri init-config` writes it - the vendor, or the two models themselves, chosen by the host.
15
+ export { BEDROCK_DEFAULT, BEDROCK_GEOGRAPHIES, BEDROCK_IN_REGION, BEDROCK_REGIONS, bedrockAwsRegion, bedrockDefaultModels, bedrockMakers, bedrockModels, bedrockModelsIn, bedrockNeedsAwsRegion, bedrockPlaceOf, initConfig, makerLabel, VENDORS, } from "./init-config.js";
16
+ // pi's model catalogue, read without a request: what initConfig checks the models given against, and what a host offers.
17
+ export { piModelCatalogue } from "./model-check.js";
18
+ // Whether this machine, and a project on it, is ready for turri - as `turri doctor` checks it, printing nothing.
19
+ export { doctor } from "./setup.js";
16
20
  // A spec: parsed, checked, coloured.
17
21
  export { checkPlainFile } from "./plain/check.js";
18
22
  export { plainFileParser } from "./plain/parser.js";
@@ -1,3 +1,4 @@
1
+ import { type CatalogueModel, type ModelCatalogue } from "./model-check.ts";
1
2
  /**
2
3
  * `turri init-config`: a project's first config.turri.yaml - the two models, a strong one to talk to and a smaller one to
3
4
  * write the code - so a new project starts with a choice that works rather than an empty file. It asks which vendor's
@@ -8,29 +9,80 @@
8
9
  * Then it says what to do next: where the file is - turri reads it from that folder and the folders below it, nowhere
9
10
  * else - and how to sign in to the vendor so pi, which turri runs on, can reach the models.
10
11
  *
11
- * Amazon Bedrock serves Anthropic's and OpenAI's models in a geography each - an inference profile, `eu.`, `us.`,
12
- * `global.` - so it asks which of the two, and where. A config.turri.yaml already there keeps everything but the two models; a new one takes
13
- * from a config.yaml beside it the keys turri reads too.
12
+ * Amazon Bedrock serves many makers' models - Anthropic's, OpenAI's, xAI's, Meta's... - each in a geography, an inference
13
+ * profile its id starts with (`global.`, `us.`, `eu.`, ...), or in the AWS region it is called in: it asks whose, where, and
14
+ * which two, from pi's catalogue - turri's own pair offered where it has one. The two models can be given instead, any pair
15
+ * pi's catalogue has, and are checked against it. A config.turri.yaml already there keeps everything but the two models; a
16
+ * new one takes from a config.yaml beside it the keys turri reads too.
14
17
  */
15
18
  /** A vendor whose models the quick start config is filled in with. */
16
19
  export type Vendor = "anthropic" | "openai" | "google" | "amazon-bedrock" | "other";
17
- /** Whose models Amazon Bedrock serves here. */
18
- export type BedrockMaker = "anthropic" | "openai";
19
- /** Amazon Bedrock's choice: whose models, and the geography of the inference profile they run in. */
20
+ /** Whose models Amazon Bedrock serves: the maker a model's id names after its geography - anthropic, openai, xai, meta... */
21
+ export type BedrockMaker = string;
22
+ /**
23
+ * Amazon Bedrock's choice: the geography of the inference profile the models run in, and whose they are - read from the
24
+ * models when they are given, Anthropic's when nothing says.
25
+ */
20
26
  export interface BedrockChoice {
21
- maker: BedrockMaker;
27
+ maker?: BedrockMaker;
22
28
  region: string;
23
29
  }
24
- /** The geographies Bedrock serves each maker's two models in, as pi knows them - the first the default. */
25
- export declare const BEDROCK_REGIONS: Record<BedrockMaker, string[]>;
26
- /** Bedrock's models for a maker in a geography: Opus 5.5 and Haiku 5.5, or GPT-6 Astra and Luna. */
27
- export declare function bedrockModels(choice: BedrockChoice): {
30
+ /** The three models a config names: the one you talk to, the one that codes, and a strong one for the judging examples. */
31
+ export interface ModelSet {
28
32
  harness: string;
29
33
  coding: string;
30
34
  strong: string;
35
+ }
36
+ /** The two models given, full specs without a thinking level - `amazon-bedrock/global.xai.grok-4.7`; strong is harness unless named. */
37
+ export type ModelChoice = Omit<ModelSet, "strong"> & {
38
+ strong?: string;
31
39
  };
40
+ /** The makers turri has a pair of its own for on Bedrock. */
41
+ type PresetMaker = "anthropic" | "openai";
42
+ /** The geographies turri's own pair for each maker is served in - the first the default. Every other: bedrockMakers. */
43
+ export declare const BEDROCK_REGIONS: Record<PresetMaker, string[]>;
44
+ /** The geographies an inference profile's id starts with, in the order they are offered. */
45
+ export declare const BEDROCK_GEOGRAPHIES: string[];
46
+ /** A Bedrock model whose id names no geography: served in the AWS region it is called in. */
47
+ export declare const BEDROCK_IN_REGION = "in-region";
48
+ /** The AWS region to call a geography's models in - AWS_REGION's value. */
49
+ export declare function bedrockAwsRegion(geography: string): string;
50
+ /**
51
+ * Whether a geography's models need AWS_REGION set: every one but global, us and in-region, which pi's us-east-1 serves.
52
+ * pi calls Bedrock in AWS_REGION, else - with an AWS_PROFILE - the profile's region, else us-east-1. It pins eu's
53
+ * endpoint itself only with neither AWS_REGION nor AWS_PROFILE set, so eu needs it too.
54
+ */
55
+ export declare function bedrockNeedsAwsRegion(geography: string): boolean;
56
+ /** Where a Bedrock model is served and whose it is, from its id or spec: `global.xai.grok-4.7` - global, xai; `meta.llama4` - in-region, meta. */
57
+ export declare function bedrockPlaceOf(model: string): {
58
+ geography: string;
59
+ maker: BedrockMaker;
60
+ };
61
+ /** A maker's - or a provider's - name, as the messages say it: xAI for xai; its id when turri has no name for it. */
62
+ export declare function makerLabel(maker: string): string;
63
+ /** A maker pi's catalogue serves on Bedrock, and the geographies it serves its chat models in - in the order they are offered. */
64
+ export interface BedrockOffer {
65
+ maker: BedrockMaker;
66
+ label: string;
67
+ regions: string[];
68
+ }
69
+ /** Every maker pi's catalogue serves on Bedrock - Anthropic and OpenAI first, the rest by name - with their geographies. */
70
+ export declare function bedrockMakers(catalogue: ModelCatalogue): BedrockOffer[];
71
+ /** A maker's chat models in a geography, as pi's catalogue has them on Bedrock. */
72
+ export declare function bedrockModelsIn(catalogue: ModelCatalogue, choice: Required<BedrockChoice>): CatalogueModel[];
73
+ /** turri's own pair on Bedrock for a maker in a geography: Opus 5.5 and Haiku 5.5, or GPT-6 Astra and Luna. */
74
+ export declare function bedrockModels(choice: {
75
+ maker?: PresetMaker;
76
+ region: string;
77
+ }): ModelSet;
78
+ /**
79
+ * The pair to offer for a maker in a geography: turri's own where it has one; else, from pi's catalogue, the strongest
80
+ * that reasons to talk to - price standing in for strength - and the cheapest costing at least a fifth of it to code,
81
+ * ties to the newest. Undefined when the catalogue has none of the maker's models there.
82
+ */
83
+ export declare function bedrockDefaultModels(catalogue: ModelCatalogue, choice: BedrockChoice): ModelSet | undefined;
32
84
  /** Bedrock's default: Anthropic's models, anywhere. */
33
- export declare const BEDROCK_DEFAULT: BedrockChoice;
85
+ export declare const BEDROCK_DEFAULT: Required<BedrockChoice>;
34
86
  interface VendorPreset {
35
87
  label: string;
36
88
  /** The model you talk to: it writes the specs and plans the work. */
@@ -72,16 +124,16 @@ export declare const DEFAULTS: {
72
124
  };
73
125
  /** How many pulses run at once without a setting: half this machine's cores, one to four - as regenerate/jobs.ts has it. */
74
126
  export declare function defaultParallel(cores?: number): number;
75
- /** The quick start config.turri.yaml for a vendor's models - for Bedrock, the maker and geography chosen. */
76
- export declare function quickStartConfig(vendor?: Vendor, bedrock?: BedrockChoice): string;
127
+ /** The quick start config.turri.yaml for a vendor's models - for Bedrock, the maker and geography chosen - or the models given. */
128
+ export declare function quickStartConfig(vendor?: Vendor, bedrock?: BedrockChoice, models?: ModelSet): string;
77
129
  /** The quick start config for the mix of vendors: what turri wrote before it asked. */
78
130
  export declare const QUICK_START_CONFIG: string;
79
131
  /** A vendor from what was typed: its number in the list, or its name. */
80
132
  export declare function vendorOf(answer: string): Vendor | undefined;
81
- /** Bedrock's maker from what was typed: its number - 1 Anthropic, 2 OpenAI - or its name. */
82
- export declare function bedrockMakerOf(answer: string): BedrockMaker | undefined;
83
- /** A geography the maker's models are served in, from what was typed: its number in the list, or its name. */
84
- export declare function bedrockRegionOf(maker: BedrockMaker, answer: string): string | undefined;
133
+ /** Bedrock's maker from what was typed: its number in the list - with no catalogue, 1 Anthropic, 2 OpenAI - or its name. */
134
+ export declare function bedrockMakerOf(answer: string, catalogue?: ModelCatalogue): BedrockMaker | undefined;
135
+ /** A geography the maker's models are served in, from what was typed: its number in the list, or its name - pi's catalogue's, or without it turri's pair's. */
136
+ export declare function bedrockRegionOf(maker: BedrockMaker, answer: string, catalogue?: ModelCatalogue): string | undefined;
85
137
  /**
86
138
  * What a config.yaml in `folder` says that turri reads too - another tool's testing scripts, say - by turri's names
87
139
  * (`template_dir` read as `template-dir`), in the file's order; and the keys it leaves, turri reading none of them. The
@@ -91,19 +143,27 @@ export declare function sharedWithLegacy(folder: string): {
91
143
  carried: Array<[string, unknown]>;
92
144
  left: string[];
93
145
  };
94
- /**
95
- * Write the quick start config.turri.yaml in `dir`, with what a config.yaml beside it says that turri reads too. One already
96
- * there keeps everything but its two models, which are set to the vendor's - `force` writes the whole of it again. Says
97
- * what it did.
98
- */
99
- export declare function initConfig(dir: string, options?: {
146
+ export interface InitConfigOptions {
147
+ /** Write the whole file again, not only the two models of one already there. */
100
148
  force?: boolean;
149
+ /** Whose models: read from the models when they are given, other when nothing says. */
101
150
  vendor?: Vendor;
151
+ /** On Amazon Bedrock: the geography, and whose models - read from the models when they are given. */
102
152
  bedrock?: BedrockChoice;
103
- }): {
153
+ /** The two models - any pair pi's catalogue has as chat models - in place of the vendor's own. */
154
+ models?: ModelChoice;
155
+ /** pi's catalogue, to check the models against - read from pi when it is needed and not given. */
156
+ catalogue?: ModelCatalogue;
157
+ }
158
+ /**
159
+ * Write the quick start config.turri.yaml in `dir`, with what a config.yaml beside it says that turri reads too. One already
160
+ * there keeps everything but its two models, which are set to the vendor's - or the ones given - and `force` writes the
161
+ * whole of it again. Says what it did; a model pi's catalogue does not have writes nothing and says so.
162
+ */
163
+ export declare function initConfig(dir: string, options?: InitConfigOptions): Promise<{
104
164
  written: boolean;
105
165
  message: string;
106
- };
107
- /** `turri init-config [--vendor <vendor>] [--maker <maker>] [--region <geography>] [--force] [folder]`. */
166
+ }>;
167
+ /** `turri init-config [--vendor <vendor>] [--maker <maker>] [--region <geography>] [--harness-model <spec> --coding-model <spec>] [--force] [folder]`. */
108
168
  export declare function main(args: string[]): Promise<number>;
109
169
  export {};