@shanepadgett/tau-agent 0.33.1 → 0.35.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/docs/context.md +29 -20
- package/docs/extending-tau-agent.md +63 -24
- package/extensions/appshot/index.ts +112 -111
- package/extensions/aside/README.md +7 -0
- package/extensions/aside/index.ts +168 -0
- package/extensions/aside/panel.ts +83 -0
- package/extensions/bash-approval/README.md +20 -0
- package/extensions/bash-approval/index.ts +235 -0
- package/extensions/bash-approval/settings.ts +24 -0
- package/extensions/branch/index.ts +38 -21
- package/extensions/cache-diagnostics/index.ts +70 -58
- package/extensions/checkpoint/README.md +9 -0
- package/extensions/checkpoint/checkpoint-budget.ts +66 -0
- package/extensions/checkpoint/checkpoint.ts +279 -0
- package/extensions/checkpoint/index.ts +102 -0
- package/extensions/checkpoint/messages.ts +170 -0
- package/extensions/checkpoint/prompt.ts +24 -0
- package/extensions/checkpoint/settings.ts +27 -0
- package/extensions/commit/commit-effort.ts +3 -3
- package/extensions/commit/commit-plan.ts +2 -2
- package/extensions/context/README.md +12 -8
- package/extensions/context/definitions.ts +178 -55
- package/extensions/context/index.ts +192 -160
- package/extensions/context/panel.ts +57 -37
- package/extensions/context/sync.ts +139 -89
- package/extensions/context/validation.ts +37 -25
- package/extensions/effort/README.md +1 -1
- package/extensions/effort/index.ts +3 -3
- package/extensions/effort/state.ts +3 -18
- package/extensions/explore/guidance.ts +6 -47
- package/extensions/explore/index.ts +38 -53
- package/extensions/explore/{ast/read → read}/hook.ts +12 -7
- package/extensions/explore/{ast/tools → tools}/ast-search.ts +15 -19
- package/extensions/explore/{ast/tools → tools}/context.ts +16 -23
- package/extensions/explore/{ast/tools → tools}/deps.ts +11 -15
- package/extensions/explore/{ast/tools → tools}/discover.ts +15 -17
- package/extensions/explore/{ast/tools → tools}/impact.ts +20 -23
- package/extensions/explore/{ast/tools → tools}/outline.ts +21 -24
- package/extensions/explore/{ast/tools → tools}/relationships.ts +23 -32
- package/extensions/explore/{ast/tools → tools}/render.ts +1 -1
- package/extensions/explore/{ast/tools → tools}/reverse-deps.ts +11 -15
- package/extensions/explore/{ast/tools → tools}/show.ts +16 -19
- package/extensions/explore/tools/target-params.ts +9 -0
- package/extensions/footer/index.ts +75 -56
- package/extensions/handoff/index.ts +8 -30
- package/extensions/image-gen/index.ts +46 -40
- package/extensions/patch/executor.ts +190 -135
- package/extensions/patch/matcher.ts +82 -48
- package/extensions/patch/parser.ts +149 -105
- package/extensions/patch/render.ts +32 -39
- package/extensions/patch/summary.ts +30 -26
- package/extensions/ready/README.md +7 -0
- package/extensions/ready/index.ts +58 -0
- package/extensions/ready/model.ts +128 -0
- package/extensions/ready/packs.ts +272 -0
- package/extensions/ready/render.ts +445 -0
- package/extensions/ready/scan.ts +760 -0
- package/extensions/reference/index.ts +2 -0
- package/extensions/reference/panel.ts +94 -31
- package/extensions/review/README.md +14 -6
- package/extensions/review/index.ts +58 -99
- package/extensions/review/model.ts +13 -33
- package/extensions/review/session.ts +9 -23
- package/extensions/runtime-context/context.ts +30 -26
- package/extensions/script-runner/README.md +2 -2
- package/extensions/script-runner/index.ts +122 -82
- package/extensions/silent-command-runner/index.ts +38 -23
- package/extensions/soul/README.md +2 -2
- package/extensions/soul/index.ts +4 -4
- package/extensions/soul/prompt.ts +6 -10
- package/extensions/soul/settings.ts +6 -3
- package/extensions/subagent/agents/context-sync.md +185 -33
- package/extensions/subagent/agents/scout.md +2 -2
- package/extensions/subagent/agents/web-research.md +2 -2
- package/extensions/subagent/agents.ts +137 -84
- package/extensions/subagent/cmux-dashboard.ts +39 -30
- package/extensions/subagent/index.ts +79 -59
- package/extensions/subagent/resume.ts +1 -1
- package/extensions/subagent/run.ts +308 -193
- package/extensions/subagent/runtime.ts +781 -343
- package/extensions/tau/index.ts +47 -38
- package/extensions/tau-help/help.md +20 -8
- package/extensions/tool-loader/README.md +4 -2
- package/extensions/tool-loader/index.ts +77 -52
- package/extensions/web/index.ts +6 -3
- package/extensions/web/webfetch.ts +114 -86
- package/package.json +3 -3
- package/schemas/tau.schema.json +38 -35
- package/shared/bounded-text-result.ts +1 -0
- package/shared/checkpoint-visibility.ts +9 -0
- package/shared/events.ts +28 -10
- package/shared/isolated-session.ts +72 -30
- package/shared/model-effort.ts +23 -22
- package/shared/model-fallback/index.ts +66 -41
- package/shared/settings/load.ts +45 -38
- package/shared/temporary-output-store.ts +16 -10
- package/{extensions/explore → src}/ast/adapter.ts +11 -2
- package/{extensions/explore → src}/ast/engine.ts +54 -38
- package/{extensions/explore → src}/ast/format/ast-search.ts +15 -6
- package/{extensions/explore → src}/ast/format/context.ts +3 -6
- package/src/ast/format/deps.ts +94 -0
- package/{extensions/explore → src}/ast/format/discover.ts +2 -2
- package/{extensions/explore → src}/ast/format/impact.ts +9 -11
- package/{extensions/explore → src}/ast/format/outline.ts +2 -2
- package/{extensions/explore → src}/ast/format/relationships.ts +11 -7
- package/{extensions/explore → src}/ast/format/show.ts +1 -1
- package/src/ast/format/targeted-result.ts +20 -0
- package/src/ast/grammars/c_sharp.wasm +0 -0
- package/{extensions/explore → src}/ast/grammars/manifest.json +9 -12
- package/{extensions/explore → src}/ast/grammars/manifest.ts +0 -4
- package/{extensions/explore → src}/ast/graph/file-graph.ts +210 -98
- package/{extensions/explore → src}/ast/graph/relationships.ts +285 -72
- package/{extensions/explore → src}/ast/ir.ts +6 -0
- package/src/ast/languages/csharp-file-deps.ts +90 -0
- package/{extensions/explore → src}/ast/languages/csharp.ts +9 -40
- package/src/ast/languages/dotted-index.ts +131 -0
- package/{extensions/explore → src}/ast/languages/file-dep-util.ts +22 -13
- package/src/ast/languages/fixtures/sample.cs +53 -0
- package/src/ast/languages/fixtures/sample.cs.expected.json +156 -0
- package/src/ast/languages/fixtures/sample.go +37 -0
- package/src/ast/languages/fixtures/sample.go.expected.json +96 -0
- package/src/ast/languages/fixtures/sample.java +40 -0
- package/src/ast/languages/fixtures/sample.java.expected.json +126 -0
- package/src/ast/languages/fixtures/sample.kt +31 -0
- package/src/ast/languages/fixtures/sample.kt.expected.json +134 -0
- package/src/ast/languages/fixtures/sample.md +23 -0
- package/src/ast/languages/fixtures/sample.md.expected.json +44 -0
- package/src/ast/languages/fixtures/sample.rs +54 -0
- package/src/ast/languages/fixtures/sample.rs.expected.json +178 -0
- package/src/ast/languages/fixtures/sample.swift +45 -0
- package/src/ast/languages/fixtures/sample.swift.expected.json +147 -0
- package/src/ast/languages/fixtures/sample.ts +45 -0
- package/src/ast/languages/fixtures/sample.ts.expected.json +141 -0
- package/src/ast/languages/fixtures/sample.tsx +36 -0
- package/src/ast/languages/fixtures/sample.tsx.expected.json +59 -0
- package/{extensions/explore → src}/ast/languages/go-file-deps.ts +6 -0
- package/{extensions/explore → src}/ast/languages/go.ts +21 -3
- package/{extensions/explore → src}/ast/languages/java.ts +5 -38
- package/src/ast/languages/jvm-file-deps.ts +135 -0
- package/{extensions/explore → src}/ast/languages/kotlin.ts +5 -39
- package/{extensions/explore → src}/ast/languages/rust-file-deps.ts +3 -3
- package/{extensions/explore → src}/ast/languages/rust.ts +21 -13
- package/{extensions/explore → src}/ast/languages/swift-file-deps.ts +22 -15
- package/{extensions/explore → src}/ast/languages/swift.ts +9 -39
- package/{extensions/explore → src}/ast/languages/tree.ts +47 -0
- package/{extensions/explore → src}/ast/languages/typescript-file-deps.ts +108 -0
- package/{extensions/explore → src}/ast/languages/typescript-package-surface.ts +4 -3
- package/{extensions/explore → src}/ast/languages/typescript.ts +3 -5
- package/{extensions/explore → src}/ast/markdown.ts +72 -47
- package/{extensions/explore → src}/ast/queries/ast-search.ts +164 -146
- package/{extensions/explore → src}/ast/queries/composite-target.ts +1 -1
- package/{extensions/explore → src}/ast/queries/context.ts +116 -80
- package/{extensions/explore → src}/ast/queries/discover.ts +154 -105
- package/src/ast/queries/impact.ts +291 -0
- package/{extensions/explore → src}/ast/queries/outline.ts +4 -2
- package/{extensions/explore → src}/ast/queries/show.ts +46 -42
- package/{extensions/explore → src}/ast/query.ts +1 -1
- package/{extensions/explore → src}/ast/registry.ts +1 -2
- package/{extensions/explore → src}/ast/scan.ts +1 -1
- package/src/ast/session.ts +50 -0
- package/{extensions/explore → src}/ast/slice.ts +8 -0
- package/{extensions/explore → src/ast}/traverse.ts +32 -20
- package/src/file-injection/index.ts +547 -0
- package/src/image-generation/client.ts +50 -31
- package/src/image-generation/index.ts +177 -134
- package/src/index.ts +2 -0
- package/src/tool-loading/index.ts +58 -0
- package/extensions/context/evidence.ts +0 -517
- package/extensions/context/projection.ts +0 -141
- package/extensions/context/state.ts +0 -30
- package/extensions/context/write-scope.ts +0 -109
- package/extensions/explore/ast/format/deps.ts +0 -86
- package/extensions/explore/ast/grammars/odin.wasm +0 -0
- package/extensions/explore/ast/languages/csharp-file-deps.ts +0 -189
- package/extensions/explore/ast/languages/fixtures/sample.cs +0 -17
- package/extensions/explore/ast/languages/fixtures/sample.java +0 -21
- package/extensions/explore/ast/languages/fixtures/sample.kt +0 -15
- package/extensions/explore/ast/languages/fixtures/sample.odin +0 -28
- package/extensions/explore/ast/languages/fixtures/sample.rs +0 -31
- package/extensions/explore/ast/languages/fixtures/sample.swift +0 -25
- package/extensions/explore/ast/languages/jvm-file-deps.ts +0 -217
- package/extensions/explore/ast/languages/odin-file-deps.ts +0 -175
- package/extensions/explore/ast/languages/odin.ts +0 -407
- package/extensions/explore/ast/queries/impact.ts +0 -250
- package/extensions/explore/outline-injection.ts +0 -151
- package/extensions/explore/read/autoread.ts +0 -118
- package/extensions/review/panel.ts +0 -128
- package/extensions/working-memory/README.md +0 -17
- package/extensions/working-memory/checkpoint.ts +0 -242
- package/extensions/working-memory/index.ts +0 -341
- package/extensions/working-memory/memory.ts +0 -235
- package/extensions/working-memory/render.ts +0 -185
- package/extensions/working-memory/settings.ts +0 -38
- package/extensions/working-memory/state.ts +0 -158
- package/shared/autoread.ts +0 -234
- package/shared/context-messages.ts +0 -19
- package/shared/outline-injection.ts +0 -56
- /package/{extensions/explore → src}/ast/format/composite.ts +0 -0
- /package/{extensions/explore → src}/ast/grammars/kotlin.wasm +0 -0
- /package/{extensions/explore → src}/ast/grammars/swift.wasm +0 -0
- /package/{extensions/explore → src}/ast/identity.ts +0 -0
- /package/{extensions/explore → src}/ast/package-surface.ts +0 -0
- /package/{extensions/explore/ast/read/policy.ts → src/ast/read-policy.ts} +0 -0
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { spawnSync } from "node:child_process";
|
|
2
|
-
import { createHash } from "node:crypto";
|
|
3
2
|
import { type Dirent, readdirSync } from "node:fs";
|
|
4
3
|
import { join, resolve } from "node:path";
|
|
5
4
|
|
|
@@ -19,13 +18,6 @@ export function freezeRuntimeContext(cwd: string): RuntimeContext {
|
|
|
19
18
|
return { cwd: cwd.replace(/\\/g, "/"), rootSnapshot: listRootSnapshot(cwd) };
|
|
20
19
|
}
|
|
21
20
|
|
|
22
|
-
export function formatLocalDateKey(date: Date): string {
|
|
23
|
-
const year = date.getFullYear();
|
|
24
|
-
const month = String(date.getMonth() + 1).padStart(2, "0");
|
|
25
|
-
const day = String(date.getDate()).padStart(2, "0");
|
|
26
|
-
return `${year}-${month}-${day}`;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
21
|
export function formatLocalDisplayDate(date: Date): string {
|
|
30
22
|
const months = [
|
|
31
23
|
"January",
|
|
@@ -44,12 +36,6 @@ export function formatLocalDisplayDate(date: Date): string {
|
|
|
44
36
|
return `${date.getDate()} ${months[date.getMonth()]} ${date.getFullYear()}`;
|
|
45
37
|
}
|
|
46
38
|
|
|
47
|
-
export function fingerprintRuntimeSnapshot(context: RuntimeContext): string {
|
|
48
|
-
return createHash("sha256")
|
|
49
|
-
.update(JSON.stringify({ version: 1, cwd: context.cwd, paths: context.rootSnapshot }))
|
|
50
|
-
.digest("hex");
|
|
51
|
-
}
|
|
52
|
-
|
|
53
39
|
export function formatRuntimeContextMessage(displayDate: string, rootSnapshot: readonly string[] | undefined): string {
|
|
54
40
|
const blocks = [`Current local date: ${displayDate}`];
|
|
55
41
|
if (rootSnapshot?.length) {
|
|
@@ -58,42 +44,60 @@ export function formatRuntimeContextMessage(displayDate: string, rootSnapshot: r
|
|
|
58
44
|
return blocks.join("\n");
|
|
59
45
|
}
|
|
60
46
|
|
|
61
|
-
function
|
|
62
|
-
const root = resolve(cwd);
|
|
47
|
+
function visibleRootEntries(root: string): SnapshotEntry[] {
|
|
63
48
|
const rootEntries = listSnapshotEntries(root, ".");
|
|
64
49
|
const ignoredRootPaths = gitIgnoredPaths(
|
|
65
50
|
root,
|
|
66
51
|
rootEntries.map((entry) => entry.path),
|
|
67
52
|
);
|
|
68
|
-
|
|
53
|
+
return rootEntries.filter(
|
|
69
54
|
(entry) => !isAlwaysHiddenFromSnapshot(entry.dirent.name) && !ignoredRootPaths.has(entry.path),
|
|
70
55
|
);
|
|
71
|
-
|
|
72
|
-
const childPaths: string[] = [];
|
|
56
|
+
}
|
|
73
57
|
|
|
74
|
-
|
|
58
|
+
function childEntriesByParent(
|
|
59
|
+
root: string,
|
|
60
|
+
roots: readonly SnapshotEntry[],
|
|
61
|
+
): {
|
|
62
|
+
byParent: Map<string, SnapshotEntry[]>;
|
|
63
|
+
ignoredChildPaths: Set<string>;
|
|
64
|
+
} {
|
|
65
|
+
const byParent = new Map<string, SnapshotEntry[]>();
|
|
66
|
+
const childPaths: string[] = [];
|
|
67
|
+
for (const entry of roots) {
|
|
75
68
|
if (!entry.dirent.isDirectory()) continue;
|
|
76
69
|
const childEntries = listSnapshotEntries(root, entry.path).filter(
|
|
77
70
|
(childEntry) => !isAlwaysHiddenFromSnapshot(childEntry.dirent.name),
|
|
78
71
|
);
|
|
79
|
-
|
|
72
|
+
byParent.set(entry.path, childEntries);
|
|
80
73
|
childPaths.push(...childEntries.map((childEntry) => childEntry.path));
|
|
81
74
|
}
|
|
75
|
+
return { byParent, ignoredChildPaths: gitIgnoredPaths(root, childPaths) };
|
|
76
|
+
}
|
|
82
77
|
|
|
83
|
-
|
|
78
|
+
function collectSnapshotPaths(
|
|
79
|
+
roots: readonly SnapshotEntry[],
|
|
80
|
+
byParent: Map<string, SnapshotEntry[]>,
|
|
81
|
+
ignoredChildPaths: ReadonlySet<string>,
|
|
82
|
+
): string[] {
|
|
84
83
|
const paths: string[] = [];
|
|
85
|
-
|
|
86
|
-
for (const entry of visibleRootEntries) {
|
|
84
|
+
for (const entry of roots) {
|
|
87
85
|
pushSnapshotPath(paths, entry);
|
|
88
86
|
if (paths.length >= ROOT_SNAPSHOT_MAX_PATHS) break;
|
|
89
|
-
|
|
90
|
-
for (const childEntry of childEntriesByParent.get(entry.path) ?? []) {
|
|
87
|
+
for (const childEntry of byParent.get(entry.path) ?? []) {
|
|
91
88
|
if (ignoredChildPaths.has(childEntry.path)) continue;
|
|
92
89
|
pushSnapshotPath(paths, childEntry);
|
|
93
90
|
if (paths.length >= ROOT_SNAPSHOT_MAX_PATHS) break;
|
|
94
91
|
}
|
|
95
92
|
}
|
|
93
|
+
return paths;
|
|
94
|
+
}
|
|
96
95
|
|
|
96
|
+
function listRootSnapshot(cwd: string): string[] {
|
|
97
|
+
const root = resolve(cwd);
|
|
98
|
+
const roots = visibleRootEntries(root);
|
|
99
|
+
const children = childEntriesByParent(root, roots);
|
|
100
|
+
const paths = collectSnapshotPaths(roots, children.byParent, children.ignoredChildPaths);
|
|
97
101
|
return paths.length === ROOT_SNAPSHOT_MAX_PATHS ? [...paths, "..."] : paths;
|
|
98
102
|
}
|
|
99
103
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# Script Runner
|
|
2
2
|
|
|
3
|
-
Gives the agent a first-class `script_runner` tool for running Python 3 and
|
|
3
|
+
Gives the agent a first-class `script_runner` tool for running Python 3, Node.js, and Deno scripts instead of falling back to bash. The agent picks whichever runtime is more efficient for the task.
|
|
4
4
|
|
|
5
5
|
When a run fails, the tool keeps the script and returns a `scriptId`. The agent retries with targeted `{oldText, newText}` edits against what it just wrote instead of resending the whole script, saving output tokens and keeping duplicate scripts out of context. Only the source the agent already sent is referenced; no file path is exposed.
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
Runtimes are detected from the environment: Python 3 via `python3`, Node via the current process when Node is 22.6 or newer (`node --experimental-strip-types`), Deno via `deno` (`deno run -A`). The `node` language is the local Node.js runtime with full Node APIs; scripts may be TypeScript with erasable syntax or plain JavaScript. The `deno` language is the local Deno runtime with full permissions and native TypeScript/JavaScript. The tool registers only the runtimes actually available and is hidden from the prompt entirely when none are present.
|
|
@@ -16,11 +16,12 @@ import {
|
|
|
16
16
|
import { Text } from "@earendil-works/pi-tui";
|
|
17
17
|
import { Type } from "typebox";
|
|
18
18
|
|
|
19
|
-
type Language = "python3" | "
|
|
19
|
+
type Language = "python3" | "node" | "deno";
|
|
20
20
|
|
|
21
21
|
interface Runtimes {
|
|
22
22
|
python3: string | undefined;
|
|
23
|
-
|
|
23
|
+
node: string | undefined;
|
|
24
|
+
deno: string | undefined;
|
|
24
25
|
}
|
|
25
26
|
|
|
26
27
|
interface StoredScript {
|
|
@@ -40,15 +41,34 @@ function detectRuntimes(): Runtimes {
|
|
|
40
41
|
// runtime not installed
|
|
41
42
|
}
|
|
42
43
|
const [major, minor] = process.versions.node.split(".").map(Number);
|
|
43
|
-
let
|
|
44
|
+
let node: string | undefined;
|
|
44
45
|
if (major > 22 || (major === 22 && minor >= 6)) {
|
|
45
|
-
|
|
46
|
+
node = process.execPath;
|
|
46
47
|
}
|
|
47
|
-
|
|
48
|
+
let deno: string | undefined;
|
|
49
|
+
try {
|
|
50
|
+
execFileSync("deno", ["--version"], { stdio: ["ignore", "pipe", "ignore"] });
|
|
51
|
+
deno = "deno";
|
|
52
|
+
} catch {
|
|
53
|
+
// runtime not installed
|
|
54
|
+
}
|
|
55
|
+
return { python3, node, deno };
|
|
48
56
|
}
|
|
49
57
|
|
|
50
58
|
function capitalize(lang: Language): string {
|
|
51
|
-
|
|
59
|
+
if (lang === "python3") return "Python 3";
|
|
60
|
+
if (lang === "node") return "Node";
|
|
61
|
+
return "Deno";
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function formatLangList(langs: readonly Language[]): string {
|
|
65
|
+
const names = langs.map(capitalize);
|
|
66
|
+
if (names.length <= 2) return names.join(" or ");
|
|
67
|
+
return `${names.slice(0, -1).join(", ")}, or ${names[names.length - 1]}`;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
function languageLabel(lang: string): string {
|
|
71
|
+
return lang === "node" ? "node (Node.js)" : lang;
|
|
52
72
|
}
|
|
53
73
|
|
|
54
74
|
function newScriptId(): string {
|
|
@@ -65,9 +85,7 @@ function applyEdits(source: string, edits: ReadonlyArray<{ oldText: string; newT
|
|
|
65
85
|
for (const edit of edits) {
|
|
66
86
|
const idx = next.indexOf(edit.oldText);
|
|
67
87
|
if (idx === -1) {
|
|
68
|
-
throw new Error(
|
|
69
|
-
"An edits oldText was not found in the script. Copy the exact text from the script you wrote.",
|
|
70
|
-
);
|
|
88
|
+
throw new Error("edits oldText not found. Copy exact text from the script you wrote.");
|
|
71
89
|
}
|
|
72
90
|
next = next.slice(0, idx) + edit.newText + next.slice(idx + edit.oldText.length);
|
|
73
91
|
}
|
|
@@ -90,14 +108,64 @@ function renderEditsPreview(edits: ReadonlyArray<{ oldText: string; newText: str
|
|
|
90
108
|
.join("\n");
|
|
91
109
|
}
|
|
92
110
|
|
|
111
|
+
function resolveScriptSource(
|
|
112
|
+
scripts: Map<string, StoredScript>,
|
|
113
|
+
language: Language,
|
|
114
|
+
params: {
|
|
115
|
+
script?: string;
|
|
116
|
+
scriptId?: string;
|
|
117
|
+
edits?: ReadonlyArray<{ oldText: string; newText: string }>;
|
|
118
|
+
},
|
|
119
|
+
): { scriptId: string; source: string } {
|
|
120
|
+
const edits = params.edits;
|
|
121
|
+
if (edits && edits.length > 0) {
|
|
122
|
+
const scriptId = params.scriptId;
|
|
123
|
+
if (!scriptId) throw new Error("edits require scriptId from the failed run.");
|
|
124
|
+
const stored = scripts.get(scriptId);
|
|
125
|
+
if (!stored) throw new Error(`No stored script for scriptId ${scriptId}. Evicted; resend full script.`);
|
|
126
|
+
if (stored.language !== language) {
|
|
127
|
+
throw new Error(`Language mismatch: scriptId ${scriptId} is ${stored.language}, not ${language}.`);
|
|
128
|
+
}
|
|
129
|
+
return { scriptId, source: applyEdits(stored.source, edits) };
|
|
130
|
+
}
|
|
131
|
+
if (typeof params.script !== "string" || params.script.length === 0) {
|
|
132
|
+
throw new Error("Provide script, or edits + scriptId.");
|
|
133
|
+
}
|
|
134
|
+
return { scriptId: params.scriptId ?? newScriptId(), source: params.script };
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
function formatTruncatedTail(text: string): { body: string; note: string } {
|
|
138
|
+
const trunc = truncateTail(text, { maxLines: DEFAULT_MAX_LINES, maxBytes: DEFAULT_MAX_BYTES });
|
|
139
|
+
const note = trunc.truncated
|
|
140
|
+
? `\n\n[output truncated: kept tail ${trunc.outputLines} / ${trunc.totalLines} lines]`
|
|
141
|
+
: "";
|
|
142
|
+
return { body: trunc.content, note };
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
function successScriptResult(stdout: string): { content: [{ type: "text"; text: string }]; details: undefined } {
|
|
146
|
+
const { body, note } = formatTruncatedTail(stdout.trim());
|
|
147
|
+
const out = body.trim();
|
|
148
|
+
return {
|
|
149
|
+
content: [{ type: "text", text: out ? `${out}${note}` : `(no output)${note}` }],
|
|
150
|
+
details: undefined,
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
function throwScriptFailure(scriptId: string, result: { stdout: string; stderr: string }): never {
|
|
155
|
+
const diag = result.stderr.trim() || result.stdout.trim();
|
|
156
|
+
const { body, note } = formatTruncatedTail(diag);
|
|
157
|
+
const detail = body ? `${body}${note}\n\n` : "";
|
|
158
|
+
throw new Error(`${detail}scriptId: ${scriptId}`);
|
|
159
|
+
}
|
|
160
|
+
|
|
93
161
|
export default function scriptRunnerExtension(pi: ExtensionAPI): void {
|
|
94
162
|
const runtimes = detectRuntimes();
|
|
95
|
-
const detected = (["python3", "
|
|
96
|
-
(lang): lang is Language =>
|
|
163
|
+
const detected = (["python3", "node", "deno"] as const).filter(
|
|
164
|
+
(lang): lang is Language => runtimes[lang] !== undefined,
|
|
97
165
|
);
|
|
98
166
|
if (detected.length === 0) return;
|
|
99
167
|
|
|
100
|
-
const langPhrase = detected
|
|
168
|
+
const langPhrase = formatLangList(detected);
|
|
101
169
|
|
|
102
170
|
const scripts = new Map<string, StoredScript>();
|
|
103
171
|
let tempDir: string | undefined;
|
|
@@ -112,14 +180,13 @@ export default function scriptRunnerExtension(pi: ExtensionAPI): void {
|
|
|
112
180
|
}
|
|
113
181
|
|
|
114
182
|
function resolveCommand(language: Language): string {
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
183
|
+
const cmd = runtimes[language];
|
|
184
|
+
if (cmd) return cmd;
|
|
185
|
+
if (language === "python3") throw new Error("Python 3 is not available on this machine.");
|
|
186
|
+
if (language === "node") {
|
|
187
|
+
throw new Error("Node unavailable (needs Node >= 22.6 with --experimental-strip-types).");
|
|
119
188
|
}
|
|
120
|
-
|
|
121
|
-
if (!cmd) throw new Error("TypeScript is not available (requires Node >= 22.6).");
|
|
122
|
-
return cmd;
|
|
189
|
+
throw new Error("Deno is not available on this machine.");
|
|
123
190
|
}
|
|
124
191
|
|
|
125
192
|
async function ensureTempDir(): Promise<string> {
|
|
@@ -138,7 +205,12 @@ export default function scriptRunnerExtension(pi: ExtensionAPI): void {
|
|
|
138
205
|
const dir = await ensureTempDir();
|
|
139
206
|
const file = join(dir, language === "python3" ? "_run.py" : "_run.ts");
|
|
140
207
|
await writeFile(file, source, "utf8");
|
|
141
|
-
const args =
|
|
208
|
+
const args =
|
|
209
|
+
language === "python3"
|
|
210
|
+
? [file]
|
|
211
|
+
: language === "node"
|
|
212
|
+
? ["--experimental-strip-types", file]
|
|
213
|
+
: ["run", "-A", file];
|
|
142
214
|
const result = await pi.exec(command, args, { cwd, signal, timeout: TIMEOUT_MS });
|
|
143
215
|
return {
|
|
144
216
|
...result,
|
|
@@ -149,13 +221,13 @@ export default function scriptRunnerExtension(pi: ExtensionAPI): void {
|
|
|
149
221
|
|
|
150
222
|
const paramsSchema = Type.Object(
|
|
151
223
|
{
|
|
152
|
-
language: StringEnum(detected, {
|
|
224
|
+
language: StringEnum(detected, {
|
|
225
|
+
description: "Execution runtime.",
|
|
226
|
+
}),
|
|
153
227
|
script: Type.Optional(
|
|
154
|
-
Type.String({ description: "Full
|
|
155
|
-
),
|
|
156
|
-
scriptId: Type.Optional(
|
|
157
|
-
Type.String({ description: "scriptId returned by a failed run. Required when retrying with edits." }),
|
|
228
|
+
Type.String({ description: "Full source for a new run. Omit when retrying with edits." }),
|
|
158
229
|
),
|
|
230
|
+
scriptId: Type.Optional(Type.String({ description: "From a failed run. Required with edits." })),
|
|
159
231
|
edits: Type.Optional(
|
|
160
232
|
Type.Array(
|
|
161
233
|
Type.Object({
|
|
@@ -163,8 +235,7 @@ export default function scriptRunnerExtension(pi: ExtensionAPI): void {
|
|
|
163
235
|
newText: Type.String({ description: "Replacement text." }),
|
|
164
236
|
}),
|
|
165
237
|
{
|
|
166
|
-
description:
|
|
167
|
-
"Targeted oldText/newText patches applied to the stored script before rerun. Prefer this over resending the whole script.",
|
|
238
|
+
description: "Patches applied to the stored script before rerun.",
|
|
168
239
|
},
|
|
169
240
|
),
|
|
170
241
|
),
|
|
@@ -172,15 +243,26 @@ export default function scriptRunnerExtension(pi: ExtensionAPI): void {
|
|
|
172
243
|
{ additionalProperties: false },
|
|
173
244
|
);
|
|
174
245
|
|
|
246
|
+
const runtimeNotes = [
|
|
247
|
+
detected.includes("node")
|
|
248
|
+
? "language=node: local Node.js via node --experimental-strip-types (not tsc/ts-node)."
|
|
249
|
+
: undefined,
|
|
250
|
+
detected.includes("deno") ? "language=deno: local Deno via deno run -A." : undefined,
|
|
251
|
+
].filter((note): note is string => note !== undefined);
|
|
252
|
+
|
|
175
253
|
const tool = defineTool<typeof paramsSchema, undefined>({
|
|
176
254
|
name: "script_runner",
|
|
177
255
|
label: "Script Runner",
|
|
178
|
-
description:
|
|
179
|
-
|
|
256
|
+
description: [
|
|
257
|
+
`Run a ${langPhrase} script in the project cwd and return stdout.`,
|
|
258
|
+
...runtimeNotes,
|
|
259
|
+
"On non-zero exit: result includes scriptId. Retry with same language + scriptId + edits [{oldText,newText}]; do not resend the full script unless the approach is wrong.",
|
|
260
|
+
`Available: ${langPhrase}.`,
|
|
261
|
+
].join("\n"),
|
|
262
|
+
promptSnippet: `Run ${langPhrase} scripts; on failure retry with edits + scriptId.`,
|
|
180
263
|
promptGuidelines: [
|
|
181
|
-
`Prefer script_runner over bash for ${langPhrase} when computation, data handling, or bulk file work is cleaner than chaining
|
|
182
|
-
|
|
183
|
-
`script_runner never exposes the script file path, and you already know the script you sent. Never try to read it back.`,
|
|
264
|
+
`Prefer script_runner over bash for ${langPhrase} when computation, data handling, or bulk file work is cleaner than chaining tools.`,
|
|
265
|
+
"script_runner never exposes the script path; you already have the source. Never try to read it back.",
|
|
184
266
|
],
|
|
185
267
|
parameters: paramsSchema,
|
|
186
268
|
async execute(_toolCallId, params, signal, onUpdate, ctx) {
|
|
@@ -188,65 +270,23 @@ export default function scriptRunnerExtension(pi: ExtensionAPI): void {
|
|
|
188
270
|
if (signal?.aborted) {
|
|
189
271
|
return { content: [{ type: "text", text: "Cancelled." }], details: undefined };
|
|
190
272
|
}
|
|
191
|
-
|
|
192
273
|
const command = resolveCommand(language);
|
|
193
|
-
const
|
|
194
|
-
let scriptId: string | undefined = params.scriptId;
|
|
195
|
-
let source: string;
|
|
196
|
-
|
|
197
|
-
if (edits && edits.length > 0) {
|
|
198
|
-
if (!scriptId) throw new Error("edits require the scriptId returned by the failed run.");
|
|
199
|
-
const stored = scripts.get(scriptId);
|
|
200
|
-
if (!stored) {
|
|
201
|
-
throw new Error(
|
|
202
|
-
`No stored script for scriptId ${scriptId}. It may have been evicted; resend the full script.`,
|
|
203
|
-
);
|
|
204
|
-
}
|
|
205
|
-
if (stored.language !== language) {
|
|
206
|
-
throw new Error(`Language mismatch: scriptId ${scriptId} is ${stored.language}, not ${language}.`);
|
|
207
|
-
}
|
|
208
|
-
source = applyEdits(stored.source, edits);
|
|
209
|
-
} else {
|
|
210
|
-
if (typeof params.script !== "string" || params.script.length === 0) {
|
|
211
|
-
throw new Error("Provide a script for a new run, or edits + scriptId to retry.");
|
|
212
|
-
}
|
|
213
|
-
source = params.script;
|
|
214
|
-
if (!scriptId) scriptId = newScriptId();
|
|
215
|
-
}
|
|
216
|
-
|
|
274
|
+
const { scriptId, source } = resolveScriptSource(scripts, language, params);
|
|
217
275
|
remember(scriptId, { language, source });
|
|
218
|
-
await onUpdate?.({
|
|
219
|
-
|
|
276
|
+
await onUpdate?.({
|
|
277
|
+
content: [{ type: "text", text: `Running ${languageLabel(language)}...` }],
|
|
278
|
+
details: undefined,
|
|
279
|
+
});
|
|
220
280
|
const result = await runScript(language, command, source, ctx.cwd, signal);
|
|
221
281
|
if (result.code === 0 && !result.killed) {
|
|
222
282
|
scripts.delete(scriptId);
|
|
223
|
-
|
|
224
|
-
maxLines: DEFAULT_MAX_LINES,
|
|
225
|
-
maxBytes: DEFAULT_MAX_BYTES,
|
|
226
|
-
});
|
|
227
|
-
const out = trunc.content.trim();
|
|
228
|
-
const note = trunc.truncated
|
|
229
|
-
? `\n\n[output truncated: kept tail ${trunc.outputLines} / ${trunc.totalLines} lines]`
|
|
230
|
-
: "";
|
|
231
|
-
return {
|
|
232
|
-
content: [{ type: "text", text: out ? `${out}${note}` : `(no output)${note}` }],
|
|
233
|
-
details: undefined,
|
|
234
|
-
};
|
|
283
|
+
return successScriptResult(result.stdout);
|
|
235
284
|
}
|
|
236
|
-
|
|
237
|
-
const diag = result.stderr.trim() || result.stdout.trim();
|
|
238
|
-
const trunc = truncateTail(diag, { maxLines: DEFAULT_MAX_LINES, maxBytes: DEFAULT_MAX_BYTES });
|
|
239
|
-
const note = trunc.truncated
|
|
240
|
-
? `\n\n[output truncated: kept tail ${trunc.outputLines} / ${trunc.totalLines} lines]`
|
|
241
|
-
: "";
|
|
242
|
-
const detail = trunc.content ? `${trunc.content}${note}\n\n` : "";
|
|
243
|
-
throw new Error(
|
|
244
|
-
`${detail}scriptId: ${scriptId}\nRetry with edits: [{oldText,newText}] using the same language and scriptId; do not resend the full script.`,
|
|
245
|
-
);
|
|
285
|
+
throwScriptFailure(scriptId, result);
|
|
246
286
|
},
|
|
247
287
|
renderCall(args, theme, context) {
|
|
248
288
|
const text = (context.lastComponent as Text | undefined) ?? new Text("", 0, 0);
|
|
249
|
-
const header = `${theme.fg("toolTitle", theme.bold("script_runner"))} ${theme.fg("muted", args.language)}`;
|
|
289
|
+
const header = `${theme.fg("toolTitle", theme.bold("script_runner"))} ${theme.fg("muted", languageLabel(args.language))}`;
|
|
250
290
|
const edits = args.edits;
|
|
251
291
|
const body =
|
|
252
292
|
edits && edits.length > 0
|
|
@@ -146,25 +146,11 @@ export default function silentCommandRunnerExtension(pi: ExtensionAPI): void {
|
|
|
146
146
|
attentionHoldId = undefined;
|
|
147
147
|
});
|
|
148
148
|
|
|
149
|
-
async function
|
|
150
|
-
|
|
151
|
-
|
|
149
|
+
async function collectCommandFailures(
|
|
150
|
+
projectRoot: string,
|
|
151
|
+
changed: readonly CommandConfig[],
|
|
152
152
|
notify: (message: string, type?: "info" | "warning" | "error") => void,
|
|
153
|
-
): Promise<
|
|
154
|
-
if (!settings.enabled || settings.commands.length === 0) return;
|
|
155
|
-
|
|
156
|
-
const projectRoot = await resolveProjectRoot(cwd);
|
|
157
|
-
const paths = await walkFiles(projectRoot);
|
|
158
|
-
const changed = await scanChangedCommands(projectRoot, settings.commands, paths, turnPaths, turnStart);
|
|
159
|
-
if (!sessionActive || changed.length === 0) return;
|
|
160
|
-
|
|
161
|
-
notify(
|
|
162
|
-
changed.length === 1
|
|
163
|
-
? `silent-command-runner: running ${changed[0]?.name ?? "command"}`
|
|
164
|
-
: `silent-command-runner: running ${changed.length} commands`,
|
|
165
|
-
"info",
|
|
166
|
-
);
|
|
167
|
-
|
|
153
|
+
): Promise<FailedCommandDetails[] | undefined> {
|
|
168
154
|
const failures: FailedCommandDetails[] = [];
|
|
169
155
|
const controller = new AbortController();
|
|
170
156
|
abortController = controller;
|
|
@@ -175,32 +161,61 @@ export default function silentCommandRunnerExtension(pi: ExtensionAPI): void {
|
|
|
175
161
|
try {
|
|
176
162
|
result = await runCommand(pi, projectRoot, command, controller.signal, settings.maxOutputBytes);
|
|
177
163
|
} catch (error: unknown) {
|
|
178
|
-
if (controller.signal.aborted) return;
|
|
164
|
+
if (controller.signal.aborted) return undefined;
|
|
179
165
|
throw error;
|
|
180
166
|
}
|
|
181
|
-
if (controller.signal.aborted) return;
|
|
167
|
+
if (controller.signal.aborted) return undefined;
|
|
182
168
|
if (result.code !== 0 || result.killed) failures.push(result);
|
|
183
169
|
}
|
|
184
170
|
} finally {
|
|
185
171
|
if (abortController === controller) abortController = undefined;
|
|
186
172
|
}
|
|
187
|
-
|
|
173
|
+
return failures;
|
|
174
|
+
}
|
|
188
175
|
|
|
176
|
+
function reportCommandResults(
|
|
177
|
+
changed: readonly CommandConfig[],
|
|
178
|
+
failures: readonly FailedCommandDetails[],
|
|
179
|
+
notify: (message: string, type?: "info" | "warning" | "error") => void,
|
|
180
|
+
): void {
|
|
189
181
|
const failedNames = new Set(failures.map((failure) => failure.name));
|
|
190
182
|
const passed = changed.filter((command) => !failedNames.has(command.name));
|
|
191
183
|
if (passed.length > 0) notify(`silent-command-runner: passed ${formatCommandNames(passed)}`, "info");
|
|
192
184
|
if (failures.length === 0) return;
|
|
193
|
-
|
|
194
185
|
pi.sendMessage<FailureDetails>(
|
|
195
186
|
{
|
|
196
187
|
customType: MESSAGE_TYPE,
|
|
197
188
|
content: formatAgentMessage(failures),
|
|
198
189
|
display: true,
|
|
199
|
-
details: { failed: failures },
|
|
190
|
+
details: { failed: [...failures] },
|
|
200
191
|
},
|
|
201
192
|
{ deliverAs: "followUp" },
|
|
202
193
|
);
|
|
203
194
|
}
|
|
195
|
+
|
|
196
|
+
async function runChangedCommands(
|
|
197
|
+
cwd: string,
|
|
198
|
+
turnStart: number,
|
|
199
|
+
notify: (message: string, type?: "info" | "warning" | "error") => void,
|
|
200
|
+
): Promise<void> {
|
|
201
|
+
if (!settings.enabled || settings.commands.length === 0) return;
|
|
202
|
+
|
|
203
|
+
const projectRoot = await resolveProjectRoot(cwd);
|
|
204
|
+
const paths = await walkFiles(projectRoot);
|
|
205
|
+
const changed = await scanChangedCommands(projectRoot, settings.commands, paths, turnPaths, turnStart);
|
|
206
|
+
if (!sessionActive || changed.length === 0) return;
|
|
207
|
+
|
|
208
|
+
notify(
|
|
209
|
+
changed.length === 1
|
|
210
|
+
? `silent-command-runner: running ${changed[0]?.name ?? "command"}`
|
|
211
|
+
: `silent-command-runner: running ${changed.length} commands`,
|
|
212
|
+
"info",
|
|
213
|
+
);
|
|
214
|
+
|
|
215
|
+
const failures = await collectCommandFailures(projectRoot, changed, notify);
|
|
216
|
+
if (failures === undefined || !sessionActive) return;
|
|
217
|
+
reportCommandResults(changed, failures, notify);
|
|
218
|
+
}
|
|
204
219
|
}
|
|
205
220
|
|
|
206
221
|
function normalizeSettings(value: typeof silentCommandRunnerSettings.defaults): Settings {
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
Soul shapes how Tau works and talks by adding two independent sections to Pi's native assistant prompt:
|
|
4
4
|
|
|
5
5
|
- **ponytail** — a lazy-senior-dev build ethos: do the smallest correct thing, reuse before writing, YAGNI, fix bugs at the root, never cut validation, security, or accessibility.
|
|
6
|
-
- **
|
|
6
|
+
- **simplified** — Simplified Technical English (ASD-STE100): use short sentences and paragraphs, explain jargon, and shape plans and conversations in small chunks.
|
|
7
7
|
|
|
8
8
|
Pi continues to own tool guidance, project instructions, skills, documentation paths, custom prompts, and working-directory context.
|
|
9
9
|
|
|
@@ -12,7 +12,7 @@ Toggle each section in Tau settings (both on by default):
|
|
|
12
12
|
```json
|
|
13
13
|
{
|
|
14
14
|
"extensions": {
|
|
15
|
-
"soul": { "ponytail": true, "
|
|
15
|
+
"soul": { "ponytail": true, "simplified": false }
|
|
16
16
|
}
|
|
17
17
|
}
|
|
18
18
|
```
|
package/extensions/soul/index.ts
CHANGED
|
@@ -1,22 +1,22 @@
|
|
|
1
1
|
import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
|
|
2
2
|
import { loadTauExtensionSettings } from "../../shared/settings/load.ts";
|
|
3
|
-
import {
|
|
3
|
+
import { PONYTAIL_ETHOS, SIMPLIFIED_TECHNICAL_ENGLISH } from "./prompt.ts";
|
|
4
4
|
import soulSettings from "./settings.ts";
|
|
5
5
|
|
|
6
6
|
export default function soulExtension(pi: ExtensionAPI): void {
|
|
7
7
|
let ponytail = true;
|
|
8
|
-
let
|
|
8
|
+
let simplified = true;
|
|
9
9
|
|
|
10
10
|
pi.on("session_start", async (_event, ctx) => {
|
|
11
11
|
const settings = await loadTauExtensionSettings(ctx, soulSettings);
|
|
12
12
|
ponytail = settings.ponytail;
|
|
13
|
-
|
|
13
|
+
simplified = settings.simplified;
|
|
14
14
|
});
|
|
15
15
|
|
|
16
16
|
pi.on("before_agent_start", (event) => {
|
|
17
17
|
const sections: string[] = [];
|
|
18
18
|
if (ponytail) sections.push(PONYTAIL_ETHOS);
|
|
19
|
-
if (
|
|
19
|
+
if (simplified) sections.push(SIMPLIFIED_TECHNICAL_ENGLISH);
|
|
20
20
|
if (sections.length === 0) return undefined;
|
|
21
21
|
return { systemPrompt: [event.systemPrompt, ...sections].join("\n\n") };
|
|
22
22
|
});
|
|
@@ -26,18 +26,14 @@ Non-trivial logic leaves one runnable check behind: the smallest thing that fail
|
|
|
26
26
|
|
|
27
27
|
Mark a deliberate simplification that cuts a real corner with a named ceiling and its upgrade path.`;
|
|
28
28
|
|
|
29
|
-
export const
|
|
29
|
+
export const SIMPLIFIED_TECHNICAL_ENGLISH = `## Communication style
|
|
30
30
|
|
|
31
|
-
|
|
31
|
+
Use Simplified Technical English (ASD-STE100) when you communicate with the user. Assume the user is tired and has limited capacity for jargon.
|
|
32
32
|
|
|
33
|
-
|
|
33
|
+
Use short sentences and short paragraphs. Explain one idea at a time. Prefer common words, active voice, and concrete explanations. Avoid idioms, vague language, filler, and unexplained abbreviations. Explain unavoidable jargon in plain words when you first use it.
|
|
34
34
|
|
|
35
|
-
|
|
35
|
+
Keep technical content exact. Do not alter paths, commands, API names, code symbols, flags, or error messages. Explain what they mean around the exact text.
|
|
36
36
|
|
|
37
|
-
|
|
37
|
+
Work in small chunks. Answer the immediate question first. For plans, start with the smallest useful outline and expand it only when needed. Expect plans to change after each decision. Do not write a novel before the plan has been checked.
|
|
38
38
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
No filler emphasis or manufactured insight. Skip "here's the thing", "that's the part that really matters", "and that's the key". Skip "not just X, it's Y" and "it's not X, it's Y" framing. Skip grand closers that restate the point as a lesson. State the fact, the mechanism, or the next step, then stop.
|
|
42
|
-
|
|
43
|
-
Full clear sentences, terse style dropped, for security warnings, irreversible-action confirmations, multi-step sequences where order matters, and anywhere compression would create ambiguity. Resume terse after.`;
|
|
39
|
+
Keep responses short enough to scan, while giving enough explanation for the user to understand the reason and next step. Do not replace explanations with fragments just to be brief. Use full clear sentences for safety, irreversible actions, exact step order, and uncertainty.`;
|
|
@@ -3,14 +3,17 @@ import { defineTauExtensionSettings } from "../../shared/settings/define.ts";
|
|
|
3
3
|
|
|
4
4
|
export default defineTauExtensionSettings({
|
|
5
5
|
key: "soul",
|
|
6
|
-
defaults: { ponytail: true as boolean,
|
|
6
|
+
defaults: { ponytail: true as boolean, simplified: true as boolean },
|
|
7
7
|
schema: Type.Object(
|
|
8
8
|
{
|
|
9
9
|
ponytail: Type.Optional(
|
|
10
10
|
Type.Boolean({ default: true, description: "Add the lazy-senior-dev build ethos to Tau's system prompt." }),
|
|
11
11
|
),
|
|
12
|
-
|
|
13
|
-
Type.Boolean({
|
|
12
|
+
simplified: Type.Optional(
|
|
13
|
+
Type.Boolean({
|
|
14
|
+
default: true,
|
|
15
|
+
description: "Add Simplified Technical English and small-chunk explanations to Tau's system prompt.",
|
|
16
|
+
}),
|
|
14
17
|
),
|
|
15
18
|
},
|
|
16
19
|
{ additionalProperties: false },
|