@shanepadgett/tau-agent 0.33.1 → 0.34.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/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 +79 -0
- package/extensions/checkpoint/checkpoint.ts +277 -0
- package/extensions/checkpoint/index.ts +102 -0
- package/extensions/checkpoint/messages.ts +169 -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/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/panel.ts +28 -16
- package/extensions/review/index.ts +63 -51
- package/extensions/review/panel.ts +5 -34
- 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/subagent/agents/context-sync.md +185 -33
- package/extensions/subagent/agents/scout.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 +304 -193
- package/extensions/subagent/runtime.ts +781 -343
- package/extensions/tau/index.ts +47 -38
- package/extensions/tau-help/help.md +14 -6
- 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 +20 -33
- 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 +71 -29
- package/shared/model-effort.ts +9 -19
- 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/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
|
@@ -2,19 +2,19 @@ import { StringEnum } from "@earendil-works/pi-ai";
|
|
|
2
2
|
import { defineTool } from "@earendil-works/pi-coding-agent";
|
|
3
3
|
import { basename } from "node:path";
|
|
4
4
|
import { Type, type Static } from "typebox";
|
|
5
|
-
import { truncateBoundedHead } from "
|
|
6
|
-
import type { ToolRowStateStore } from "
|
|
7
|
-
import type { ExploreEngine } from "
|
|
8
|
-
import { formatShowBatch } from "
|
|
9
|
-
import { showTargets, type ShowTargetInput } from "
|
|
10
|
-
import { stripLeadingAt } from "
|
|
5
|
+
import { truncateBoundedHead } from "../../../shared/bounded-text-result.ts";
|
|
6
|
+
import type { ToolRowStateStore } from "../../../shared/tool-row-state.ts";
|
|
7
|
+
import type { ExploreEngine } from "../../../src/ast/engine.ts";
|
|
8
|
+
import { formatShowBatch } from "../../../src/ast/format/show.ts";
|
|
9
|
+
import { showTargets, type ShowTargetInput } from "../../../src/ast/queries/show.ts";
|
|
10
|
+
import { stripLeadingAt } from "../../../src/ast/traverse.ts";
|
|
11
11
|
import { ExploreCallComponent, renderExploreResult, shrinkingListVariants, type ExploreToolDetails } from "./render.ts";
|
|
12
12
|
|
|
13
13
|
const showTargetSchema = Type.Object(
|
|
14
14
|
{
|
|
15
|
-
path: Type.String({ description: "
|
|
16
|
-
name: Type.String({ minLength: 1, description: "
|
|
17
|
-
line: Type.Optional(Type.Integer({ minimum: 1, description: "1-
|
|
15
|
+
path: Type.String({ description: "Defining file" }),
|
|
16
|
+
name: Type.String({ minLength: 1, description: "Decl name; dotted Type.method ok" }),
|
|
17
|
+
line: Type.Optional(Type.Integer({ minimum: 1, description: "1-based line inside decl range" })),
|
|
18
18
|
},
|
|
19
19
|
{ additionalProperties: false },
|
|
20
20
|
);
|
|
@@ -23,16 +23,15 @@ const showParams = Type.Object(
|
|
|
23
23
|
{
|
|
24
24
|
targets: Type.Array(showTargetSchema, {
|
|
25
25
|
minItems: 1,
|
|
26
|
-
description: "
|
|
26
|
+
description: "path+name targets (optional line pin)",
|
|
27
27
|
}),
|
|
28
28
|
view: StringEnum(["signature", "signatureWithDocs", "declaration", "declarationWithImports"] as const, {
|
|
29
|
-
description:
|
|
30
|
-
"signature omits docs and bodies; signatureWithDocs adds attached docs; declaration is exact source; declarationWithImports adds import statements that mention identifiers in the declaration",
|
|
29
|
+
description: "signature | signatureWithDocs | declaration | declarationWithImports",
|
|
31
30
|
}),
|
|
32
31
|
contextLines: Type.Optional(
|
|
33
32
|
Type.Integer({
|
|
34
33
|
minimum: 0,
|
|
35
|
-
description: "
|
|
34
|
+
description: "Extra lines around decl (declaration only)",
|
|
36
35
|
}),
|
|
37
36
|
),
|
|
38
37
|
},
|
|
@@ -69,13 +68,11 @@ export function createShowTool(rowState: ToolRowStateStore, engineFor: (cwd: str
|
|
|
69
68
|
name: "show",
|
|
70
69
|
label: "show",
|
|
71
70
|
description:
|
|
72
|
-
"
|
|
73
|
-
promptSnippet: "
|
|
71
|
+
"Exact signature or source for path+name targets. Whole batch fails on any missing/ambiguous target (candidate list, no partials). Views: signature → signatureWithDocs → declaration → declarationWithImports. Over budget throws — request fewer targets (bodies are not truncated).",
|
|
72
|
+
promptSnippet: "Signature or source for path+name targets",
|
|
74
73
|
promptGuidelines: [
|
|
75
|
-
"
|
|
76
|
-
"
|
|
77
|
-
"Disambiguate with path and optional line. Do not guess among candidates.",
|
|
78
|
-
"If the batch exceeds the model-output budget, request fewer targets — show never truncates bodies.",
|
|
74
|
+
"Cheapest view that answers; declarationWithImports only when edits need imports.",
|
|
75
|
+
"Pin with path and line when names collide — do not guess.",
|
|
79
76
|
],
|
|
80
77
|
parameters: showParams,
|
|
81
78
|
async execute(_toolCallId, params, signal, _onUpdate, ctx) {
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { Type } from "typebox";
|
|
2
|
+
|
|
3
|
+
/** Parameters every declaration-targeting Explore tool accepts. */
|
|
4
|
+
export const targetParams = {
|
|
5
|
+
path: Type.String({ description: "Directory scope" }),
|
|
6
|
+
targetPath: Type.Optional(Type.String({ description: "Defining file when known" })),
|
|
7
|
+
name: Type.String({ minLength: 1, description: "Decl name; dotted Type.method ok" }),
|
|
8
|
+
line: Type.Optional(Type.Integer({ minimum: 1, description: "1-based line pin" })),
|
|
9
|
+
};
|
|
@@ -260,12 +260,37 @@ async function saveEnabled(ctx: ExtensionContext, enabled: boolean): Promise<voi
|
|
|
260
260
|
await updateTauExtensionSettings("global", ctx, footerSettings, (current) => ({ ...current, enabled }));
|
|
261
261
|
}
|
|
262
262
|
|
|
263
|
+
function countGitLine(
|
|
264
|
+
line: string,
|
|
265
|
+
counts: { staged: number; modified: number; untracked: number; conflicts: number },
|
|
266
|
+
): void {
|
|
267
|
+
const x = line[0];
|
|
268
|
+
const y = line[1];
|
|
269
|
+
if (x === "?" && y === "?") {
|
|
270
|
+
counts.untracked += 1;
|
|
271
|
+
return;
|
|
272
|
+
}
|
|
273
|
+
if (isConflict(x, y)) {
|
|
274
|
+
counts.conflicts += 1;
|
|
275
|
+
return;
|
|
276
|
+
}
|
|
277
|
+
if (x && x !== " ") counts.staged += 1;
|
|
278
|
+
if (y && y !== " ") counts.modified += 1;
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
function formatGitCounts(counts: { staged: number; modified: number; untracked: number; conflicts: number }): string {
|
|
282
|
+
const parts = [
|
|
283
|
+
counts.staged ? `+${counts.staged}` : "",
|
|
284
|
+
counts.modified ? `~${counts.modified}` : "",
|
|
285
|
+
counts.untracked ? `?${counts.untracked}` : "",
|
|
286
|
+
counts.conflicts ? `!${counts.conflicts}` : "",
|
|
287
|
+
].filter(Boolean);
|
|
288
|
+
return parts.length ? parts.join(" ") : "clean";
|
|
289
|
+
}
|
|
290
|
+
|
|
263
291
|
function parseGitStatus(stdout: string): GitSummary | undefined {
|
|
264
292
|
let branch = "";
|
|
265
|
-
|
|
266
|
-
let modified = 0;
|
|
267
|
-
let untracked = 0;
|
|
268
|
-
let conflicts = 0;
|
|
293
|
+
const counts = { staged: 0, modified: 0, untracked: 0, conflicts: 0 };
|
|
269
294
|
|
|
270
295
|
for (const line of stdout.split("\n")) {
|
|
271
296
|
if (!line) continue;
|
|
@@ -273,29 +298,11 @@ function parseGitStatus(stdout: string): GitSummary | undefined {
|
|
|
273
298
|
branch = line.slice(3).split("...")[0]?.trim() ?? "";
|
|
274
299
|
continue;
|
|
275
300
|
}
|
|
276
|
-
|
|
277
|
-
const x = line[0];
|
|
278
|
-
const y = line[1];
|
|
279
|
-
if (x === "?" && y === "?") {
|
|
280
|
-
untracked += 1;
|
|
281
|
-
continue;
|
|
282
|
-
}
|
|
283
|
-
if (isConflict(x, y)) {
|
|
284
|
-
conflicts += 1;
|
|
285
|
-
continue;
|
|
286
|
-
}
|
|
287
|
-
if (x && x !== " ") staged += 1;
|
|
288
|
-
if (y && y !== " ") modified += 1;
|
|
301
|
+
countGitLine(line, counts);
|
|
289
302
|
}
|
|
290
303
|
|
|
291
304
|
if (!branch) return undefined;
|
|
292
|
-
|
|
293
|
-
staged ? `+${staged}` : "",
|
|
294
|
-
modified ? `~${modified}` : "",
|
|
295
|
-
untracked ? `?${untracked}` : "",
|
|
296
|
-
conflicts ? `!${conflicts}` : "",
|
|
297
|
-
].filter(Boolean);
|
|
298
|
-
return { branch, text: parts.length ? parts.join(" ") : "clean" };
|
|
305
|
+
return { branch, text: formatGitCounts(counts) };
|
|
299
306
|
}
|
|
300
307
|
|
|
301
308
|
function gitText(git: GitSummary | undefined): string {
|
|
@@ -307,7 +314,7 @@ function isConflict(x: string | undefined, y: string | undefined): boolean {
|
|
|
307
314
|
return x === "U" || y === "U" || (x === "A" && y === "A") || (x === "D" && y === "D");
|
|
308
315
|
}
|
|
309
316
|
|
|
310
|
-
|
|
317
|
+
function sessionCost(ctx: Pick<ExtensionContext, "sessionManager">): UsageSummary {
|
|
311
318
|
let usage = zeroUsage();
|
|
312
319
|
for (const entry of ctx.sessionManager.getEntries()) {
|
|
313
320
|
if (entry.type === "message" && entry.message.role === "assistant") {
|
|
@@ -380,7 +387,44 @@ async function scanDailyCost(): Promise<number> {
|
|
|
380
387
|
return total;
|
|
381
388
|
}
|
|
382
389
|
|
|
383
|
-
|
|
390
|
+
function usageIdentityFromEntry(
|
|
391
|
+
entry: Record<string, unknown>,
|
|
392
|
+
): { usageValue: unknown; timestamp: number; identity: unknown[] } | undefined {
|
|
393
|
+
if (entry.type === "message") {
|
|
394
|
+
const message = asRecord(entry.message);
|
|
395
|
+
if (!message) return undefined;
|
|
396
|
+
const timestamp = timestampMs(message.timestamp, entry.timestamp);
|
|
397
|
+
if (message.role === "assistant" && asRecord(message.usage)) {
|
|
398
|
+
return {
|
|
399
|
+
usageValue: message.usage,
|
|
400
|
+
timestamp,
|
|
401
|
+
identity: ["assistant", message.provider, message.model],
|
|
402
|
+
};
|
|
403
|
+
}
|
|
404
|
+
if (message.role === "toolResult" && asRecord(message.usage)) {
|
|
405
|
+
return {
|
|
406
|
+
usageValue: message.usage,
|
|
407
|
+
timestamp,
|
|
408
|
+
identity: ["toolResult", message.toolName, message.toolCallId],
|
|
409
|
+
};
|
|
410
|
+
}
|
|
411
|
+
return undefined;
|
|
412
|
+
}
|
|
413
|
+
if ((entry.type === "compaction" || entry.type === "branch_summary") && asRecord(entry.usage)) {
|
|
414
|
+
return {
|
|
415
|
+
usageValue: entry.usage,
|
|
416
|
+
timestamp: timestampMs(undefined, entry.timestamp),
|
|
417
|
+
identity: [entry.type, entry.id],
|
|
418
|
+
};
|
|
419
|
+
}
|
|
420
|
+
return undefined;
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
function usageDedupeKey(identity: readonly unknown[], timestamp: number, usage: UsageSummary): string {
|
|
424
|
+
return [...identity, timestamp, usage.input, usage.output, usage.cacheRead, usage.cacheWrite, usage.cost].join(":");
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
function dailyCostFromJsonl(
|
|
384
428
|
raw: string,
|
|
385
429
|
range: { startMs: number; endMs: number },
|
|
386
430
|
seen: Set<string> = new Set<string>(),
|
|
@@ -389,36 +433,11 @@ export function dailyCostFromJsonl(
|
|
|
389
433
|
for (const line of raw.split("\n")) {
|
|
390
434
|
const entry = parseRecord(line);
|
|
391
435
|
if (!entry) continue;
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
if (!message) continue;
|
|
398
|
-
timestamp = timestampMs(message.timestamp, entry.timestamp);
|
|
399
|
-
if (message.role === "assistant" && asRecord(message.usage)) {
|
|
400
|
-
usageValue = message.usage;
|
|
401
|
-
identity = ["assistant", message.provider, message.model];
|
|
402
|
-
} else if (message.role === "toolResult" && asRecord(message.usage)) {
|
|
403
|
-
usageValue = message.usage;
|
|
404
|
-
identity = ["toolResult", message.toolName, message.toolCallId];
|
|
405
|
-
} else continue;
|
|
406
|
-
} else if ((entry.type === "compaction" || entry.type === "branch_summary") && asRecord(entry.usage)) {
|
|
407
|
-
usageValue = entry.usage;
|
|
408
|
-
timestamp = timestampMs(undefined, entry.timestamp);
|
|
409
|
-
identity = [entry.type, entry.id];
|
|
410
|
-
} else continue;
|
|
411
|
-
if (timestamp < range.startMs || timestamp >= range.endMs) continue;
|
|
412
|
-
const usage = normalizeUsage(usageValue);
|
|
413
|
-
const key = [
|
|
414
|
-
...identity,
|
|
415
|
-
timestamp,
|
|
416
|
-
usage.input,
|
|
417
|
-
usage.output,
|
|
418
|
-
usage.cacheRead,
|
|
419
|
-
usage.cacheWrite,
|
|
420
|
-
usage.cost,
|
|
421
|
-
].join(":");
|
|
436
|
+
const parsed = usageIdentityFromEntry(entry);
|
|
437
|
+
if (!parsed) continue;
|
|
438
|
+
if (parsed.timestamp < range.startMs || parsed.timestamp >= range.endMs) continue;
|
|
439
|
+
const usage = normalizeUsage(parsed.usageValue);
|
|
440
|
+
const key = usageDedupeKey(parsed.identity, parsed.timestamp, usage);
|
|
422
441
|
if (seen.has(key)) continue;
|
|
423
442
|
seen.add(key);
|
|
424
443
|
total += usage.cost;
|
|
@@ -6,9 +6,9 @@ import {
|
|
|
6
6
|
type ExtensionAPI,
|
|
7
7
|
serializeConversation,
|
|
8
8
|
} from "@earendil-works/pi-coding-agent";
|
|
9
|
-
import { prepareAutoreadMessage, type AutoreadDetails } from "../../shared/autoread.ts";
|
|
10
9
|
import { generateToolValidated, resolveCandidates } from "../../shared/model-fallback/index.ts";
|
|
11
10
|
import { errorText } from "../../shared/text.ts";
|
|
11
|
+
import { prepareFileInjection } from "@shanepadgett/tau-agent";
|
|
12
12
|
import { buildHandoffRequest, type HandoffDraft, handoffDraftFromToolInput, HANDOFF_TOOL } from "./model.ts";
|
|
13
13
|
|
|
14
14
|
export default function handoffExtension(pi: ExtensionAPI): void {
|
|
@@ -92,38 +92,16 @@ export default function handoffExtension(pi: ExtensionAPI): void {
|
|
|
92
92
|
return;
|
|
93
93
|
}
|
|
94
94
|
|
|
95
|
-
const
|
|
96
|
-
|
|
95
|
+
const fileMessages = await prepareFileInjection(pi, {
|
|
96
|
+
cwd: ctx.cwd,
|
|
97
|
+
source: "handoff",
|
|
98
|
+
batchId: randomUUID(),
|
|
99
|
+
files: draft.files.map((path) => ({ path, mode: "full" as const })),
|
|
100
|
+
});
|
|
97
101
|
const result = await ctx.newSession({
|
|
98
102
|
parentSession: currentSessionFile,
|
|
99
103
|
setup: async (sessionManager) => {
|
|
100
|
-
const
|
|
101
|
-
draft.files.map(async (path, index) => {
|
|
102
|
-
const details = {
|
|
103
|
-
rowId: `${batchId}:${index}`,
|
|
104
|
-
path,
|
|
105
|
-
cwd,
|
|
106
|
-
source: "handoff",
|
|
107
|
-
batchId,
|
|
108
|
-
};
|
|
109
|
-
try {
|
|
110
|
-
return await prepareAutoreadMessage({
|
|
111
|
-
...details,
|
|
112
|
-
signal: undefined,
|
|
113
|
-
isLifecycleCurrent: () => true,
|
|
114
|
-
});
|
|
115
|
-
} catch (error) {
|
|
116
|
-
const message = errorText(error);
|
|
117
|
-
return {
|
|
118
|
-
customType: "tau.autoread" as const,
|
|
119
|
-
content: `${path}\nAutoread failed: ${message}`,
|
|
120
|
-
display: true as const,
|
|
121
|
-
details: { ...details, status: "failed", error: message } satisfies AutoreadDetails,
|
|
122
|
-
};
|
|
123
|
-
}
|
|
124
|
-
}),
|
|
125
|
-
);
|
|
126
|
-
for (const message of messages) {
|
|
104
|
+
for (const message of fileMessages) {
|
|
127
105
|
sessionManager.appendCustomMessageEntry(
|
|
128
106
|
message.customType,
|
|
129
107
|
message.content,
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { defineTool, type ExtensionAPI } from "@earendil-works/pi-coding-agent";
|
|
2
2
|
import {
|
|
3
3
|
generateImage,
|
|
4
|
+
registerDeferredToolGroup,
|
|
5
|
+
type DeferredToolGroup,
|
|
4
6
|
type GeneratedImageResult,
|
|
5
7
|
type GenerateImageRequest,
|
|
6
8
|
type ImageGenerationContext,
|
|
@@ -31,51 +33,55 @@ type ImageGenParams = Static<typeof imageGenSchema>;
|
|
|
31
33
|
type ImageGenDetails = Omit<GeneratedImageResult, "bytes">;
|
|
32
34
|
|
|
33
35
|
export default function imageGenExtension(pi: ExtensionAPI): void {
|
|
34
|
-
pi
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
text: "Processing image request...",
|
|
47
|
-
},
|
|
48
|
-
],
|
|
49
|
-
details: undefined,
|
|
50
|
-
});
|
|
51
|
-
const request = {
|
|
52
|
-
prompt: params.prompt,
|
|
53
|
-
provider: params.provider,
|
|
54
|
-
path: params.path,
|
|
55
|
-
referencedImagePaths: params.referenced_image_paths,
|
|
56
|
-
signal,
|
|
57
|
-
} satisfies GenerateImageRequest;
|
|
58
|
-
const { bytes, ...details } = await generateImage(ctx satisfies ImageGenerationContext, request);
|
|
59
|
-
const verb = details.operation === "generate" ? "Generated" : "Edited";
|
|
60
|
-
if (bytes.length > MAX_INLINE_BYTES) {
|
|
61
|
-
return {
|
|
36
|
+
registerDeferredToolGroup(pi, {
|
|
37
|
+
id: "image",
|
|
38
|
+
description: "Raster image generation and editing",
|
|
39
|
+
tools: [
|
|
40
|
+
defineTool<typeof imageGenSchema, ImageGenDetails | undefined>({
|
|
41
|
+
name: "image_gen",
|
|
42
|
+
label: "Image Generation",
|
|
43
|
+
description:
|
|
44
|
+
"Generate a requested raster image or AI-edit existing images with OpenAI GPT Image or xAI Grok Imagine. Omit provider to follow the parent model; set it to openai or xai to override. Omit referenced_image_paths to generate; pass one to three local paths to edit or compose. Omit path to use Tau's external image store; pass path only when the user explicitly requests a repository file or other destination. Returns the image for inspection.",
|
|
45
|
+
parameters: imageGenSchema,
|
|
46
|
+
async execute(_toolCallId, params: ImageGenParams, signal, onUpdate, ctx) {
|
|
47
|
+
await onUpdate?.({
|
|
62
48
|
content: [
|
|
63
49
|
{
|
|
64
50
|
type: "text",
|
|
65
|
-
text:
|
|
51
|
+
text: "Processing image request...",
|
|
66
52
|
},
|
|
67
53
|
],
|
|
54
|
+
details: undefined,
|
|
55
|
+
});
|
|
56
|
+
const request = {
|
|
57
|
+
prompt: params.prompt,
|
|
58
|
+
provider: params.provider,
|
|
59
|
+
path: params.path,
|
|
60
|
+
referencedImagePaths: params.referenced_image_paths,
|
|
61
|
+
signal,
|
|
62
|
+
} satisfies GenerateImageRequest;
|
|
63
|
+
const { bytes, ...details } = await generateImage(ctx satisfies ImageGenerationContext, request);
|
|
64
|
+
const verb = details.operation === "generate" ? "Generated" : "Edited";
|
|
65
|
+
if (bytes.length > MAX_INLINE_BYTES) {
|
|
66
|
+
return {
|
|
67
|
+
content: [
|
|
68
|
+
{
|
|
69
|
+
type: "text",
|
|
70
|
+
text: `${verb} image saved to ${details.path}. The image exceeds the 12 MiB attachment limit, so it was not added to model context.`,
|
|
71
|
+
},
|
|
72
|
+
],
|
|
73
|
+
details,
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
return {
|
|
77
|
+
content: [
|
|
78
|
+
{ type: "text", text: `${verb} image saved to ${details.path}` },
|
|
79
|
+
{ type: "image", data: bytes.toString("base64"), mimeType: details.mimeType },
|
|
80
|
+
],
|
|
68
81
|
details,
|
|
69
82
|
};
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
{ type: "image", data: bytes.toString("base64"), mimeType: details.mimeType },
|
|
75
|
-
],
|
|
76
|
-
details,
|
|
77
|
-
};
|
|
78
|
-
},
|
|
79
|
-
}),
|
|
80
|
-
);
|
|
83
|
+
},
|
|
84
|
+
}),
|
|
85
|
+
],
|
|
86
|
+
} satisfies DeferredToolGroup);
|
|
81
87
|
}
|