@ian-pascoe/pi-codemode 0.4.0 → 0.5.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/README.md +45 -7
- package/package.json +13 -3
- package/src/codemode-cell-transform.ts +1 -1
- package/src/codemode-known-output-schemas.ts +222 -0
- package/src/codemode-session-coordinator.ts +31 -6
- package/src/codemode-tool-catalog.ts +369 -51
- package/src/codemode-tool-contract.ts +77 -3
- package/src/codemode-tool-rendering.ts +171 -5
- package/src/pi-codemode-extension.ts +114 -19
|
@@ -29,6 +29,8 @@ import {
|
|
|
29
29
|
CodeModeResultParametersSchema,
|
|
30
30
|
CodeModeSessionsParametersSchema,
|
|
31
31
|
CodeModeSessionsResultSchema,
|
|
32
|
+
CodeModeToolSearchPageSchema,
|
|
33
|
+
CodeModeToolSearchParametersSchema,
|
|
32
34
|
createCodeModeToolDefinitions,
|
|
33
35
|
type CodeModeCancelParameters,
|
|
34
36
|
type CodeModeErrorCode,
|
|
@@ -41,6 +43,8 @@ import {
|
|
|
41
43
|
type CodeModeSessionsParameters,
|
|
42
44
|
type CodeModeSessionsResult,
|
|
43
45
|
type CodeModeToolOperations,
|
|
46
|
+
type CodeModeToolSearchPage,
|
|
47
|
+
type CodeModeToolSearchParameters,
|
|
44
48
|
} from "./codemode-tool-contract.js";
|
|
45
49
|
|
|
46
50
|
/** Names of the four CodeMode tools with semantic Transcript rendering. */
|
|
@@ -75,6 +79,7 @@ const CODEMODE_STATUS_PRESENTATION = {
|
|
|
75
79
|
} satisfies Record<CodeModeCellState, CodeModeStatusPresentation>;
|
|
76
80
|
const CODEMODE_COLLAPSED_SCRIPT_LINES = 8;
|
|
77
81
|
const CODEMODE_PRESENTATION_MAX_BYTES = 50 * 1024;
|
|
82
|
+
const CODEMODE_SEARCH_DECLARATION_MAX_LINES = 2_000;
|
|
78
83
|
const CodeModeJsonStringSchema = Type.String();
|
|
79
84
|
|
|
80
85
|
function sanitizeCodeModeText(text: string): string {
|
|
@@ -434,6 +439,162 @@ function renderCodeModeSessionsResult(
|
|
|
434
439
|
return container;
|
|
435
440
|
}
|
|
436
441
|
|
|
442
|
+
function parseCodeModeToolSearchParameters(
|
|
443
|
+
parameters: CodeModeJsonValue,
|
|
444
|
+
): CodeModeToolSearchParameters | undefined {
|
|
445
|
+
return Value.Check(CodeModeToolSearchParametersSchema, parameters) ? parameters : undefined;
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
/** Render a direct CodeMode tool search call with its query and explicit page controls. */
|
|
449
|
+
export function renderCodeModeToolSearchCall(
|
|
450
|
+
parameters: CodeModeJsonValue,
|
|
451
|
+
theme: CodeModeRenderTheme,
|
|
452
|
+
expanded: boolean,
|
|
453
|
+
): Component {
|
|
454
|
+
const parsed = parseCodeModeToolSearchParameters(parameters);
|
|
455
|
+
const query = parsed?.query?.trim();
|
|
456
|
+
const container = new Container();
|
|
457
|
+
container.addChild(
|
|
458
|
+
new Text(
|
|
459
|
+
[
|
|
460
|
+
theme.fg("toolTitle", theme.bold("CodeMode")),
|
|
461
|
+
theme.fg("accent", "Search Tools"),
|
|
462
|
+
theme.fg(
|
|
463
|
+
"muted",
|
|
464
|
+
query ? boundedCodeModePreview(JSON.stringify(query), 72) : "all exposed",
|
|
465
|
+
),
|
|
466
|
+
].join(" "),
|
|
467
|
+
0,
|
|
468
|
+
0,
|
|
469
|
+
),
|
|
470
|
+
);
|
|
471
|
+
if (!expanded || parsed === undefined) return container;
|
|
472
|
+
if (parsed.group === undefined && parsed.limit === undefined && parsed.offset === undefined) {
|
|
473
|
+
return container;
|
|
474
|
+
}
|
|
475
|
+
container.addChild(new Spacer(1));
|
|
476
|
+
if (parsed.group !== undefined) appendCodeModeField(container, theme, "Group", parsed.group);
|
|
477
|
+
if (parsed.limit !== undefined) appendCodeModeField(container, theme, "Limit", parsed.limit);
|
|
478
|
+
if (parsed.offset !== undefined) appendCodeModeField(container, theme, "Offset", parsed.offset);
|
|
479
|
+
return container;
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
function codeModeToolSearchOffset(
|
|
483
|
+
page: CodeModeToolSearchPage,
|
|
484
|
+
parameters: CodeModeJsonValue,
|
|
485
|
+
): number {
|
|
486
|
+
const explicitOffset = parseCodeModeToolSearchParameters(parameters)?.offset;
|
|
487
|
+
if (explicitOffset !== undefined) return explicitOffset;
|
|
488
|
+
if (page.nextOffset !== null) return Math.max(0, page.nextOffset - page.items.length);
|
|
489
|
+
return Math.max(0, page.total - page.items.length);
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
function renderCodeModeToolSearchSummary(
|
|
493
|
+
page: CodeModeToolSearchPage,
|
|
494
|
+
parameters: CodeModeJsonValue,
|
|
495
|
+
theme: CodeModeRenderTheme,
|
|
496
|
+
): string {
|
|
497
|
+
const offset = codeModeToolSearchOffset(page, parameters);
|
|
498
|
+
if (page.items.length === 0) {
|
|
499
|
+
return page.total === 0
|
|
500
|
+
? theme.fg("dim", "No matching tools")
|
|
501
|
+
: `${theme.fg("warning", "! No tools on this page")} ${theme.fg("muted", `${pluralizedCodeModeCount(page.total, "match")} · offset ${offset}`)}`;
|
|
502
|
+
}
|
|
503
|
+
const unavailableCount = page.items.filter((item) => "declarationError" in item).length;
|
|
504
|
+
const status = unavailableCount === 0 ? theme.fg("success", "✓") : theme.fg("warning", "!");
|
|
505
|
+
const range =
|
|
506
|
+
page.items.length === page.total
|
|
507
|
+
? pluralizedCodeModeCount(page.total, "tool")
|
|
508
|
+
: `${offset + 1}–${offset + page.items.length} of ${page.total} tools`;
|
|
509
|
+
return [
|
|
510
|
+
`${status} ${range}`,
|
|
511
|
+
unavailableCount === 0
|
|
512
|
+
? undefined
|
|
513
|
+
: theme.fg(
|
|
514
|
+
"warning",
|
|
515
|
+
`${unavailableCount} declaration${unavailableCount === 1 ? "" : "s"} unavailable`,
|
|
516
|
+
),
|
|
517
|
+
page.nextOffset === null ? undefined : theme.fg("muted", `next offset ${page.nextOffset}`),
|
|
518
|
+
]
|
|
519
|
+
.filter((part): part is string => part !== undefined)
|
|
520
|
+
.join(theme.fg("dim", " · "));
|
|
521
|
+
}
|
|
522
|
+
|
|
523
|
+
function boundedCodeModeToolSearchDeclaration(
|
|
524
|
+
declaration: string,
|
|
525
|
+
declarationCount: number,
|
|
526
|
+
): string {
|
|
527
|
+
const safe = sanitizeCodeModeText(declaration);
|
|
528
|
+
const truncated = truncateHead(safe, {
|
|
529
|
+
maxBytes: Math.max(1, Math.floor(CODEMODE_PRESENTATION_MAX_BYTES / declarationCount)),
|
|
530
|
+
maxLines: Math.max(1, Math.floor(CODEMODE_SEARCH_DECLARATION_MAX_LINES / declarationCount)),
|
|
531
|
+
});
|
|
532
|
+
return truncated.truncated
|
|
533
|
+
? `${truncated.content}\n… declaration truncated in Transcript`
|
|
534
|
+
: truncated.content;
|
|
535
|
+
}
|
|
536
|
+
|
|
537
|
+
/** Render direct CodeMode tool search results as a compact page or expanded declaration list. */
|
|
538
|
+
export function renderCodeModeToolSearchResult(
|
|
539
|
+
result: AgentToolResult<unknown>,
|
|
540
|
+
options: ToolRenderResultOptions,
|
|
541
|
+
theme: CodeModeRenderTheme,
|
|
542
|
+
isError: boolean,
|
|
543
|
+
parameters: CodeModeJsonValue,
|
|
544
|
+
): Component {
|
|
545
|
+
if (options.isPartial) return new Text(theme.fg("accent", "Searching…"), 0, 0);
|
|
546
|
+
if (isError || !Value.Check(CodeModeToolSearchPageSchema, result.details)) {
|
|
547
|
+
return renderCodeModeFallback(result, options, theme, isError);
|
|
548
|
+
}
|
|
549
|
+
const page = result.details;
|
|
550
|
+
const summary = renderCodeModeToolSearchSummary(page, parameters, theme);
|
|
551
|
+
if (!options.expanded || page.items.length === 0) {
|
|
552
|
+
const hint =
|
|
553
|
+
options.expanded || page.items.length === 0
|
|
554
|
+
? ""
|
|
555
|
+
: ` · ${keyText("app.tools.expand")} to expand`;
|
|
556
|
+
return new Text(`${summary}${theme.fg("dim", hint)}`, 0, 0);
|
|
557
|
+
}
|
|
558
|
+
|
|
559
|
+
const container = new Container();
|
|
560
|
+
container.addChild(new Text(summary, 0, 0));
|
|
561
|
+
const declarationCount = Math.max(1, page.items.filter((item) => "declaration" in item).length);
|
|
562
|
+
for (const item of page.items) {
|
|
563
|
+
container.addChild(new Spacer(1));
|
|
564
|
+
container.addChild(
|
|
565
|
+
new Text(
|
|
566
|
+
`${theme.fg("toolOutput", theme.bold(boundedCodeModePreview(item.name, 256)))} ${theme.fg("muted", boundedCodeModePreview(item.group, 128))}`,
|
|
567
|
+
0,
|
|
568
|
+
0,
|
|
569
|
+
),
|
|
570
|
+
);
|
|
571
|
+
if ("declaration" in item) {
|
|
572
|
+
appendHighlightedCodeModeSource(
|
|
573
|
+
container,
|
|
574
|
+
boundedCodeModeToolSearchDeclaration(item.declaration, declarationCount),
|
|
575
|
+
);
|
|
576
|
+
} else {
|
|
577
|
+
if (item.description !== undefined) {
|
|
578
|
+
container.addChild(
|
|
579
|
+
new Text(theme.fg("muted", boundedCodeModePreview(item.description, 240)), 0, 0),
|
|
580
|
+
);
|
|
581
|
+
}
|
|
582
|
+
container.addChild(
|
|
583
|
+
new Text(
|
|
584
|
+
theme.fg("warning", `! ${boundedCodeModePreview(item.declarationError, 240)}`),
|
|
585
|
+
0,
|
|
586
|
+
0,
|
|
587
|
+
),
|
|
588
|
+
);
|
|
589
|
+
}
|
|
590
|
+
}
|
|
591
|
+
if (page.nextOffset !== null) {
|
|
592
|
+
container.addChild(new Spacer(1));
|
|
593
|
+
appendCodeModeField(container, theme, "Next offset", page.nextOffset);
|
|
594
|
+
}
|
|
595
|
+
return container;
|
|
596
|
+
}
|
|
597
|
+
|
|
437
598
|
/** Render one CodeMode result in collapsed, expanded, partial, or historical form. */
|
|
438
599
|
export function renderCodeModeToolResult(
|
|
439
600
|
toolName: CodeModeRenderedToolName,
|
|
@@ -529,16 +690,14 @@ export function renderCodeModeToolResult(
|
|
|
529
690
|
return container;
|
|
530
691
|
}
|
|
531
692
|
|
|
532
|
-
/** Create
|
|
693
|
+
/** Create five CodeMode tools with semantic call and result Transcript rendering. */
|
|
533
694
|
export function createRenderedCodeModeToolDefinitions(
|
|
534
695
|
operations: CodeModeToolOperations,
|
|
535
696
|
executeDescription?: string,
|
|
536
697
|
formatSessionPrefix: CodeModeSessionPrefixFormatter = shortCodeModeSessionId,
|
|
537
698
|
): ReturnType<typeof createCodeModeToolDefinitions> {
|
|
538
|
-
const [executeTool, resultTool, cancelTool, sessionsTool] =
|
|
539
|
-
operations,
|
|
540
|
-
executeDescription,
|
|
541
|
-
);
|
|
699
|
+
const [executeTool, resultTool, cancelTool, sessionsTool, searchTool] =
|
|
700
|
+
createCodeModeToolDefinitions(operations, executeDescription);
|
|
542
701
|
return [
|
|
543
702
|
{
|
|
544
703
|
...executeTool,
|
|
@@ -620,5 +779,12 @@ export function createRenderedCodeModeToolDefinitions(
|
|
|
620
779
|
formatSessionPrefix,
|
|
621
780
|
),
|
|
622
781
|
},
|
|
782
|
+
{
|
|
783
|
+
...searchTool,
|
|
784
|
+
renderCall: (args, theme, context) =>
|
|
785
|
+
renderCodeModeToolSearchCall(args, theme, context.expanded),
|
|
786
|
+
renderResult: (result, options, theme, context) =>
|
|
787
|
+
renderCodeModeToolSearchResult(result, options, theme, context.isError, context.args),
|
|
788
|
+
},
|
|
623
789
|
];
|
|
624
790
|
}
|
|
@@ -5,7 +5,15 @@ import type {
|
|
|
5
5
|
ExtensionContext,
|
|
6
6
|
ExtensionFactory,
|
|
7
7
|
} from "@earendil-works/pi-coding-agent";
|
|
8
|
-
import {
|
|
8
|
+
import { Type } from "typebox";
|
|
9
|
+
import { Value } from "typebox/value";
|
|
10
|
+
import { resolveKnownToolOutputSchema } from "./codemode-known-output-schemas.js";
|
|
11
|
+
import {
|
|
12
|
+
renderCodeModeToolCatalogue,
|
|
13
|
+
searchCodeModeToolCatalogue,
|
|
14
|
+
type CodeModeToolCatalogue,
|
|
15
|
+
type CodeModeToolSchema,
|
|
16
|
+
} from "./codemode-tool-catalog.js";
|
|
9
17
|
import { CodeModeObserverUiController } from "./codemode-observer-ui.js";
|
|
10
18
|
import {
|
|
11
19
|
CodeModeSessionCoordinator,
|
|
@@ -16,6 +24,7 @@ import {
|
|
|
16
24
|
import { CODEMODE_SYSTEM_RUNTIME } from "./codemode-runtime.js";
|
|
17
25
|
import { createCodeModeSessionFiles, type CodeModeSessionFiles } from "./codemode-session-files.js";
|
|
18
26
|
import {
|
|
27
|
+
CODEMODE_SEARCH_TOOL_NAME,
|
|
19
28
|
createCodeModeFailure,
|
|
20
29
|
createCodeModePending,
|
|
21
30
|
isCodeModeJsonObject,
|
|
@@ -40,6 +49,11 @@ import {
|
|
|
40
49
|
|
|
41
50
|
const CODEMODE_EXECUTE_DESCRIPTION =
|
|
42
51
|
"Execute a TypeScript Cell in a persistent isolated Deno CodeMode Session. Reuse a Session ID to retain Notebook Bindings; a new Session reclaims the least-recently-used idle Session at capacity. Use the read-only tools object for registered Pi tools. Return final result data with a top-level return statement. Reserve console.log, console.info, console.warn, console.error, and console.debug for diagnostics; captured output arrives only with terminal results.";
|
|
52
|
+
const CODEMODE_SEARCH_BATCH_LIMIT = 20;
|
|
53
|
+
const CodeModeToolSchemaMetadataSchema = Type.Union([
|
|
54
|
+
Type.Boolean(),
|
|
55
|
+
Type.Object({}, { additionalProperties: true }),
|
|
56
|
+
]);
|
|
43
57
|
|
|
44
58
|
type PiCodeModeGeneration = {
|
|
45
59
|
readonly captured: CapturedPiAgentSession;
|
|
@@ -50,6 +64,7 @@ type PiCodeModeGeneration = {
|
|
|
50
64
|
readonly operations: CodeModeToolOperations;
|
|
51
65
|
exposure?: InstalledCodeModeToolExposure;
|
|
52
66
|
decision: CodeModeToolExposureDecision;
|
|
67
|
+
catalogue: CodeModeToolCatalogue;
|
|
53
68
|
executeDescription: string;
|
|
54
69
|
active: boolean;
|
|
55
70
|
toolsRegistered: boolean;
|
|
@@ -58,8 +73,33 @@ type PiCodeModeGeneration = {
|
|
|
58
73
|
catalogueWarningShown: boolean;
|
|
59
74
|
};
|
|
60
75
|
|
|
61
|
-
function catalogueDescription(catalogue:
|
|
62
|
-
|
|
76
|
+
function catalogueDescription(catalogue: CodeModeToolCatalogue): string {
|
|
77
|
+
const coverage = catalogue.complete
|
|
78
|
+
? `COMPLETE: all ${catalogue.totalCount} declarations are shown.`
|
|
79
|
+
: `PARTIAL: ${catalogue.shownCount} of ${catalogue.totalCount} declarations are shown. Use \`tools.${CODEMODE_SEARCH_TOOL_NAME}({ query: "<intent or exact name>" })\` to find the rest; each result contains the exact flat name and its complete declaration when within the search response bound.`;
|
|
80
|
+
return `${CODEMODE_EXECUTE_DESCRIPTION}\n\nCurrent CodeMode tool declarations:\n\n${coverage}\n\n\`\`\`ts\n${catalogue.text}\`\`\``;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
type RegisteredToolDefinition = ReturnType<CapturedPiAgentSession["session"]["getToolDefinition"]>;
|
|
84
|
+
|
|
85
|
+
function codeModeToolCatalogueGroup(name: string, source: string | undefined): string {
|
|
86
|
+
const mcpPrefix = "mcp__";
|
|
87
|
+
if (name.startsWith(mcpPrefix)) {
|
|
88
|
+
const serverEnd = name.indexOf("__", mcpPrefix.length);
|
|
89
|
+
if (serverEnd > mcpPrefix.length) return `mcp:${name.slice(mcpPrefix.length, serverEnd)}`;
|
|
90
|
+
}
|
|
91
|
+
return source === undefined || source.length === 0 ? "registered" : source;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
function registeredOutputSchema(
|
|
95
|
+
definition: RegisteredToolDefinition,
|
|
96
|
+
): CodeModeToolSchema | undefined {
|
|
97
|
+
if (definition === undefined) return undefined;
|
|
98
|
+
const descriptor = Object.getOwnPropertyDescriptor(definition, "outputSchema");
|
|
99
|
+
if (descriptor === undefined || !("value" in descriptor)) return undefined;
|
|
100
|
+
return Value.Check(CodeModeToolSchemaMetadataSchema, descriptor.value)
|
|
101
|
+
? descriptor.value
|
|
102
|
+
: undefined;
|
|
63
103
|
}
|
|
64
104
|
|
|
65
105
|
function renderGenerationCatalogue(
|
|
@@ -67,12 +107,27 @@ function renderGenerationCatalogue(
|
|
|
67
107
|
decision: CodeModeToolExposureDecision,
|
|
68
108
|
) {
|
|
69
109
|
const registry = captured.getToolRegistry();
|
|
110
|
+
const toolInfoByName = new Map(
|
|
111
|
+
captured.session.getAllTools().map((toolInfo) => [toolInfo.name, toolInfo]),
|
|
112
|
+
);
|
|
70
113
|
return renderCodeModeToolCatalogue(
|
|
71
114
|
decision.codeModeNames.flatMap((name) => {
|
|
72
115
|
const tool = registry.get(name);
|
|
116
|
+
const toolInfo = toolInfoByName.get(name);
|
|
117
|
+
const outputSchema =
|
|
118
|
+
registeredOutputSchema(captured.session.getToolDefinition(name)) ??
|
|
119
|
+
(toolInfo === undefined ? undefined : resolveKnownToolOutputSchema(toolInfo));
|
|
73
120
|
return tool === undefined
|
|
74
121
|
? []
|
|
75
|
-
: [
|
|
122
|
+
: [
|
|
123
|
+
{
|
|
124
|
+
name,
|
|
125
|
+
group: codeModeToolCatalogueGroup(name, toolInfo?.sourceInfo.source),
|
|
126
|
+
description: tool.description,
|
|
127
|
+
inputSchema: tool.parameters,
|
|
128
|
+
...(outputSchema !== undefined && { outputSchema }),
|
|
129
|
+
},
|
|
130
|
+
];
|
|
76
131
|
}),
|
|
77
132
|
);
|
|
78
133
|
}
|
|
@@ -153,7 +208,7 @@ class PiCodeModeLifecycleController {
|
|
|
153
208
|
if (!initialCatalogue.ok) {
|
|
154
209
|
this.notifyWarning(
|
|
155
210
|
context,
|
|
156
|
-
"Pi CodeMode disabled:
|
|
211
|
+
"Pi CodeMode disabled: generated tool catalogue exceeds the 1 MiB outer limit",
|
|
157
212
|
);
|
|
158
213
|
return;
|
|
159
214
|
}
|
|
@@ -177,10 +232,13 @@ class PiCodeModeLifecycleController {
|
|
|
177
232
|
resultSpillWriter: sessionFiles,
|
|
178
233
|
onSnapshotChange: (snapshot) => observer.onSnapshotChange(snapshot),
|
|
179
234
|
onUnexpectedFailure: (failure) => observer.onUnexpectedFailure(failure),
|
|
180
|
-
|
|
235
|
+
getToolSnapshot: () =>
|
|
181
236
|
generation.active && this.generation === generation
|
|
182
|
-
?
|
|
183
|
-
|
|
237
|
+
? {
|
|
238
|
+
names: [CODEMODE_SEARCH_TOOL_NAME, ...generation.decision.codeModeNames],
|
|
239
|
+
searchEntries: generation.catalogue.searchEntries,
|
|
240
|
+
}
|
|
241
|
+
: { names: [], searchEntries: [] },
|
|
184
242
|
executeToolBatch: (batch) => this.executeNestedToolBatch(generation, batch),
|
|
185
243
|
});
|
|
186
244
|
const operations: CodeModeToolOperations = {
|
|
@@ -211,6 +269,14 @@ class PiCodeModeLifecycleController {
|
|
|
211
269
|
result: "success",
|
|
212
270
|
sessions: [...coordinator.listSessions()],
|
|
213
271
|
}),
|
|
272
|
+
search: async (input) => {
|
|
273
|
+
if (!generation.active || this.generation !== generation) {
|
|
274
|
+
throw new Error("Pi CodeMode session generation is inactive");
|
|
275
|
+
}
|
|
276
|
+
const searched = searchCodeModeToolCatalogue(generation.catalogue.searchEntries, input);
|
|
277
|
+
if (!searched.ok) throw new Error(searched.message);
|
|
278
|
+
return searched.page;
|
|
279
|
+
},
|
|
214
280
|
};
|
|
215
281
|
generation = {
|
|
216
282
|
captured,
|
|
@@ -220,7 +286,8 @@ class PiCodeModeLifecycleController {
|
|
|
220
286
|
sessionFiles,
|
|
221
287
|
operations,
|
|
222
288
|
decision: initialDecision,
|
|
223
|
-
|
|
289
|
+
catalogue: initialCatalogue,
|
|
290
|
+
executeDescription: catalogueDescription(initialCatalogue),
|
|
224
291
|
active: true,
|
|
225
292
|
toolsRegistered: false,
|
|
226
293
|
synchronizing: false,
|
|
@@ -257,7 +324,7 @@ class PiCodeModeLifecycleController {
|
|
|
257
324
|
return;
|
|
258
325
|
}
|
|
259
326
|
|
|
260
|
-
const [executeTool, resultTool, cancelTool, sessionsTool] =
|
|
327
|
+
const [executeTool, resultTool, cancelTool, sessionsTool, searchTool] =
|
|
261
328
|
createRenderedCodeModeToolDefinitions(
|
|
262
329
|
operations,
|
|
263
330
|
generation.executeDescription,
|
|
@@ -267,6 +334,7 @@ class PiCodeModeLifecycleController {
|
|
|
267
334
|
this.pi.registerTool(resultTool);
|
|
268
335
|
this.pi.registerTool(cancelTool);
|
|
269
336
|
this.pi.registerTool(sessionsTool);
|
|
337
|
+
this.pi.registerTool(searchTool);
|
|
270
338
|
generation.toolsRegistered = true;
|
|
271
339
|
this.synchronizeGeneration(generation);
|
|
272
340
|
}
|
|
@@ -282,7 +350,7 @@ class PiCodeModeLifecycleController {
|
|
|
282
350
|
generation.catalogueWarningShown = true;
|
|
283
351
|
this.notifyWarning(
|
|
284
352
|
generation.context,
|
|
285
|
-
"Pi CodeMode retained its previous exposure because
|
|
353
|
+
"Pi CodeMode retained its previous exposure because the generated tool catalogue exceeds the 1 MiB outer limit",
|
|
286
354
|
);
|
|
287
355
|
}
|
|
288
356
|
return false;
|
|
@@ -307,7 +375,8 @@ class PiCodeModeLifecycleController {
|
|
|
307
375
|
const catalogue = renderGenerationCatalogue(generation.captured, decision);
|
|
308
376
|
if (!catalogue.ok) continue;
|
|
309
377
|
generation.decision = decision;
|
|
310
|
-
|
|
378
|
+
generation.catalogue = catalogue;
|
|
379
|
+
const description = catalogueDescription(catalogue);
|
|
311
380
|
if (description === generation.executeDescription) continue;
|
|
312
381
|
generation.executeDescription = description;
|
|
313
382
|
if (!generation.toolsRegistered) continue;
|
|
@@ -343,8 +412,29 @@ class PiCodeModeLifecycleController {
|
|
|
343
412
|
const registry = generation.captured.getToolRegistry();
|
|
344
413
|
const earlyResults = new Map<string, CodeModeNestedToolResult>();
|
|
345
414
|
const bridgeCalls: PiToolBridgeCall[] = [];
|
|
415
|
+
let searchCallCount = 0;
|
|
346
416
|
for (const call of batch.calls) {
|
|
347
|
-
if (
|
|
417
|
+
if (call.toolName === CODEMODE_SEARCH_TOOL_NAME) {
|
|
418
|
+
searchCallCount += 1;
|
|
419
|
+
if (searchCallCount > CODEMODE_SEARCH_BATCH_LIMIT) {
|
|
420
|
+
earlyResults.set(
|
|
421
|
+
call.callId,
|
|
422
|
+
unavailableNestedResult(
|
|
423
|
+
call.callId,
|
|
424
|
+
"validation",
|
|
425
|
+
`Pi CodeMode accepts at most ${CODEMODE_SEARCH_BATCH_LIMIT} searches in one batch`,
|
|
426
|
+
),
|
|
427
|
+
);
|
|
428
|
+
} else {
|
|
429
|
+
const searched = searchCodeModeToolCatalogue(batch.searchEntries, call.input);
|
|
430
|
+
earlyResults.set(
|
|
431
|
+
call.callId,
|
|
432
|
+
searched.ok
|
|
433
|
+
? { callId: call.callId, outcome: "success", result: searched.page }
|
|
434
|
+
: unavailableNestedResult(call.callId, searched.code, searched.message),
|
|
435
|
+
);
|
|
436
|
+
}
|
|
437
|
+
} else if (!exposedNames.has(call.toolName) || !registry.has(call.toolName)) {
|
|
348
438
|
earlyResults.set(
|
|
349
439
|
call.callId,
|
|
350
440
|
unavailableNestedResult(
|
|
@@ -400,9 +490,12 @@ class PiCodeModeLifecycleController {
|
|
|
400
490
|
},
|
|
401
491
|
}),
|
|
402
492
|
};
|
|
403
|
-
const bridged =
|
|
493
|
+
const bridged =
|
|
494
|
+
bridgeCalls.length === 0
|
|
495
|
+
? undefined
|
|
496
|
+
: await executePiToolBridgeBatch(bridgeCaptured, bridgeOptions);
|
|
404
497
|
const bridgedResults = new Map<string, CodeModeNestedToolResult>(
|
|
405
|
-
bridged
|
|
498
|
+
(bridged?.calls ?? []).map((outcome) => [
|
|
406
499
|
outcome.callId,
|
|
407
500
|
outcome.ok
|
|
408
501
|
? {
|
|
@@ -429,10 +522,12 @@ class PiCodeModeLifecycleController {
|
|
|
429
522
|
);
|
|
430
523
|
return {
|
|
431
524
|
results,
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
...(bridged
|
|
435
|
-
...(bridged
|
|
525
|
+
...(bridged !== undefined &&
|
|
526
|
+
bridged.presentation.length > 0 && { presentation: bridged.presentation }),
|
|
527
|
+
...(bridged?.usage !== undefined && { usage: bridged.usage }),
|
|
528
|
+
...(bridged !== undefined &&
|
|
529
|
+
bridged.addedToolNames.length > 0 && { addedToolNames: bridged.addedToolNames }),
|
|
530
|
+
...(bridged?.terminate === true && { terminate: true }),
|
|
436
531
|
};
|
|
437
532
|
}
|
|
438
533
|
|