@shanepadgett/tau-agent 0.28.1 → 0.30.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.
Files changed (66) hide show
  1. package/docs/context.md +14 -9
  2. package/docs/subagents.md +7 -5
  3. package/extensions/cache-diagnostics/index.ts +4 -5
  4. package/extensions/context/README.md +8 -5
  5. package/extensions/context/definitions.ts +28 -17
  6. package/extensions/context/evidence.ts +4 -3
  7. package/extensions/context/index.ts +57 -35
  8. package/extensions/context/panel.ts +10 -9
  9. package/extensions/context/projection.ts +141 -0
  10. package/extensions/context/state.ts +30 -0
  11. package/extensions/explore/README.md +1 -1
  12. package/extensions/explore/ast/read/hook.ts +5 -35
  13. package/extensions/explore/ast/read/policy.ts +0 -32
  14. package/extensions/explore/index.ts +2 -0
  15. package/extensions/explore/outline-injection.ts +151 -0
  16. package/extensions/explore/settings.ts +0 -8
  17. package/extensions/ideas/browser.ts +27 -16
  18. package/extensions/review/README.md +11 -0
  19. package/extensions/review/index.ts +135 -0
  20. package/extensions/review/model.ts +144 -0
  21. package/extensions/review/panel.ts +128 -0
  22. package/extensions/review/session.ts +106 -0
  23. package/extensions/runtime-context/README.md +1 -1
  24. package/extensions/runtime-context/index.ts +3 -66
  25. package/extensions/script-runner/README.md +7 -0
  26. package/extensions/script-runner/index.ts +275 -0
  27. package/extensions/stash/browser.ts +30 -18
  28. package/extensions/subagent/README.md +17 -4
  29. package/extensions/subagent/agents/context-sync.md +2 -2
  30. package/extensions/subagent/agents/scout.md +49 -52
  31. package/extensions/subagent/agents.ts +0 -1
  32. package/extensions/subagent/cmux-dashboard.ts +7 -3
  33. package/extensions/subagent/index.ts +105 -4
  34. package/extensions/subagent/panel.ts +124 -0
  35. package/extensions/subagent/render.ts +2 -1
  36. package/extensions/subagent/run.ts +9 -9
  37. package/extensions/subagent/runtime.ts +5 -5
  38. package/extensions/subagent/session-resource.ts +19 -127
  39. package/extensions/subagent/settings.ts +18 -0
  40. package/extensions/tau-help/help.md +12 -8
  41. package/extensions/working-memory/README.md +9 -0
  42. package/extensions/working-memory/checkpoint.ts +175 -0
  43. package/extensions/working-memory/index.ts +338 -0
  44. package/extensions/working-memory/memory.ts +266 -0
  45. package/extensions/working-memory/render.ts +178 -0
  46. package/extensions/working-memory/settings.ts +38 -0
  47. package/extensions/working-memory/state.ts +152 -0
  48. package/package.json +2 -2
  49. package/schemas/tau.schema.json +35 -55
  50. package/shared/context-messages.ts +19 -0
  51. package/shared/events.ts +5 -0
  52. package/shared/full-file-knowledge.ts +0 -1
  53. package/shared/injected-context.ts +2 -2
  54. package/shared/isolated-session.ts +151 -0
  55. package/shared/outline-injection.ts +56 -0
  56. package/extensions/context-pruning/README.md +0 -39
  57. package/extensions/context-pruning/index.ts +0 -382
  58. package/extensions/context-pruning/projection.ts +0 -60
  59. package/extensions/context-pruning/prune.ts +0 -199
  60. package/extensions/context-pruning/render.ts +0 -251
  61. package/extensions/context-pruning/settings.ts +0 -39
  62. package/extensions/subagent/agents/review.md +0 -68
  63. package/extensions/turn-budget/README.md +0 -14
  64. package/extensions/turn-budget/index.ts +0 -116
  65. package/extensions/turn-budget/settings.ts +0 -35
  66. package/shared/context-pruning-state.ts +0 -152
@@ -1,35 +0,0 @@
1
- import { Type } from "typebox";
2
- import { defineTauExtensionSettings } from "../../shared/settings/define.ts";
3
-
4
- export default defineTauExtensionSettings({
5
- key: "turnBudget",
6
- defaults: {
7
- enabled: true as boolean,
8
- turnLimit: 30 as number,
9
- nudgeEveryTurns: 5 as number,
10
- softCapIncrement: 10 as number,
11
- },
12
- schema: Type.Object(
13
- {
14
- enabled: Type.Optional(Type.Boolean({ default: true, description: "Enable turn-budget hints." })),
15
- turnLimit: Type.Optional(
16
- Type.Integer({
17
- default: 30,
18
- minimum: 1,
19
- description: "Initial soft cap for tool-using turns per user prompt.",
20
- }),
21
- ),
22
- nudgeEveryTurns: Type.Optional(
23
- Type.Integer({
24
- default: 5,
25
- minimum: 1,
26
- description: "Tool-using turn interval between turn-budget hints.",
27
- }),
28
- ),
29
- softCapIncrement: Type.Optional(
30
- Type.Integer({ default: 10, minimum: 1, description: "Turns added when the soft cap is reached." }),
31
- ),
32
- },
33
- { additionalProperties: false },
34
- ),
35
- });
@@ -1,152 +0,0 @@
1
- import type { SessionEntry } from "@earendil-works/pi-coding-agent";
2
-
3
- const CONTEXT_PRUNE_TOOL = "context_prune";
4
-
5
- export interface ContextPruneRefreshedFileV2 {
6
- path: string;
7
- rowId: string;
8
- }
9
-
10
- export interface ContextPruneDeferredFileV2 {
11
- path: string;
12
- reason: string;
13
- relevantWhen: string;
14
- }
15
-
16
- export interface ContextPruneDetailsV2 {
17
- v: 2;
18
- anchorToolCallId: string;
19
- prunedToolCallIds: string[];
20
- prunedAutoreadRowIds: string[];
21
- retainedToolCallIds: string[];
22
- retainedAutoreadRowIds: string[];
23
- refreshedFiles: ContextPruneRefreshedFileV2[];
24
- deferredFiles: ContextPruneDeferredFileV2[];
25
- warnings: string[];
26
- }
27
-
28
- export interface ActiveContextPruningState {
29
- latestAnchorToolCallId: string | undefined;
30
- retainedToolCallIds: ReadonlySet<string>;
31
- prunedToolCallIds: ReadonlySet<string>;
32
- prunedAutoreadRowIds: ReadonlySet<string>;
33
- deferredFiles: readonly ContextPruneDeferredFileV2[];
34
- }
35
-
36
- const RUNTIME_ENABLED_KEY = Symbol.for("@earendil-works/tau-agent/context-pruning-enabled");
37
- const runtimeState = globalThis as typeof globalThis & { [key: symbol]: unknown };
38
-
39
- export function setContextPruningEnabled(enabled: boolean): void {
40
- runtimeState[RUNTIME_ENABLED_KEY] = enabled;
41
- }
42
-
43
- function isContextPruningEnabled(): boolean {
44
- return runtimeState[RUNTIME_ENABLED_KEY] === true;
45
- }
46
-
47
- export function parseContextPruneDetailsV2(value: unknown): ContextPruneDetailsV2 | undefined {
48
- if (!isRecord(value) || value.v !== 2 || !isNonEmptyString(value.anchorToolCallId)) return undefined;
49
- const prunedToolCallIds = parseUniqueStrings(value.prunedToolCallIds);
50
- const prunedAutoreadRowIds = parseUniqueStrings(value.prunedAutoreadRowIds);
51
- const retainedToolCallIds = parseUniqueStrings(value.retainedToolCallIds, true);
52
- const retainedAutoreadRowIds = parseUniqueStrings(value.retainedAutoreadRowIds);
53
- const refreshedFiles = parseRefreshedFiles(value.refreshedFiles);
54
- const deferredFiles = parseDeferredFiles(value.deferredFiles);
55
- const warnings = parseStrings(value.warnings, true);
56
- if (
57
- !prunedToolCallIds ||
58
- !prunedAutoreadRowIds ||
59
- !retainedToolCallIds ||
60
- !retainedAutoreadRowIds ||
61
- !refreshedFiles ||
62
- !deferredFiles ||
63
- !warnings
64
- )
65
- return undefined;
66
- return {
67
- v: 2,
68
- anchorToolCallId: value.anchorToolCallId,
69
- prunedToolCallIds,
70
- prunedAutoreadRowIds,
71
- retainedToolCallIds,
72
- retainedAutoreadRowIds,
73
- refreshedFiles,
74
- deferredFiles,
75
- warnings,
76
- };
77
- }
78
-
79
- export function replayContextPruningState(
80
- branch: readonly SessionEntry[],
81
- enabled = isContextPruningEnabled(),
82
- ): ActiveContextPruningState {
83
- const prunedToolCallIds = new Set<string>();
84
- const prunedAutoreadRowIds = new Set<string>();
85
- let latestAnchorToolCallId: string | undefined;
86
- let retainedToolCallIds = new Set<string>();
87
- let deferredFiles: readonly ContextPruneDeferredFileV2[] = [];
88
- if (enabled) {
89
- for (const entry of branch) {
90
- if (entry.type !== "message" || entry.message.role !== "toolResult") continue;
91
- const result = entry.message;
92
- if (result.toolName !== CONTEXT_PRUNE_TOOL) continue;
93
- const details = parseContextPruneDetailsV2(result.details);
94
- if (!details || details.anchorToolCallId !== result.toolCallId) continue;
95
- for (const id of details.prunedToolCallIds) prunedToolCallIds.add(id);
96
- for (const id of details.prunedAutoreadRowIds) prunedAutoreadRowIds.add(id);
97
- latestAnchorToolCallId = details.anchorToolCallId;
98
- retainedToolCallIds = new Set(details.retainedToolCallIds);
99
- deferredFiles = details.deferredFiles;
100
- }
101
- for (const id of retainedToolCallIds) prunedToolCallIds.delete(id);
102
- }
103
- return {
104
- latestAnchorToolCallId,
105
- retainedToolCallIds,
106
- prunedToolCallIds,
107
- prunedAutoreadRowIds,
108
- deferredFiles,
109
- };
110
- }
111
-
112
- function parseRefreshedFiles(value: unknown): ContextPruneRefreshedFileV2[] | undefined {
113
- if (!Array.isArray(value)) return undefined;
114
- const files: ContextPruneRefreshedFileV2[] = [];
115
- for (const item of value) {
116
- if (!isRecord(item) || !isNonEmptyString(item.path) || !isNonEmptyString(item.rowId)) return undefined;
117
- files.push({ path: item.path, rowId: item.rowId });
118
- }
119
- return files;
120
- }
121
-
122
- function parseDeferredFiles(value: unknown): ContextPruneDeferredFileV2[] | undefined {
123
- if (!Array.isArray(value)) return undefined;
124
- const files: ContextPruneDeferredFileV2[] = [];
125
- for (const item of value) {
126
- if (!isRecord(item) || typeof item.path !== "string" || typeof item.reason !== "string") return undefined;
127
- if (typeof item.relevantWhen !== "string") return undefined;
128
- files.push({ path: item.path, reason: item.reason, relevantWhen: item.relevantWhen });
129
- }
130
- return files;
131
- }
132
-
133
- function parseUniqueStrings(value: unknown, allowEmpty = false): string[] | undefined {
134
- const strings = parseStrings(value, allowEmpty);
135
- if (!strings || new Set(strings).size !== strings.length) return undefined;
136
- return strings;
137
- }
138
-
139
- function parseStrings(value: unknown, allowEmpty = false): string[] | undefined {
140
- if (!Array.isArray(value) || !value.every((item) => typeof item === "string" && (allowEmpty || item.length > 0))) {
141
- return undefined;
142
- }
143
- return [...value];
144
- }
145
-
146
- function isRecord(value: unknown): value is Record<string, unknown> {
147
- return typeof value === "object" && value !== null && !Array.isArray(value);
148
- }
149
-
150
- function isNonEmptyString(value: unknown): value is string {
151
- return typeof value === "string" && value.length > 0;
152
- }