@code-yeongyu/senpi 2026.5.13-4 → 2026.5.14
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/CHANGELOG.md +10 -0
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +12 -5
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/bash-executor.d.ts.map +1 -1
- package/dist/core/bash-executor.js +1 -1
- package/dist/core/bash-executor.js.map +1 -1
- package/dist/core/compaction/compaction.d.ts.map +1 -1
- package/dist/core/compaction/compaction.js +2 -2
- package/dist/core/compaction/compaction.js.map +1 -1
- package/dist/core/export-html/index.d.ts.map +1 -1
- package/dist/core/export-html/index.js +8 -1
- package/dist/core/export-html/index.js.map +1 -1
- package/dist/core/extensions/builtin/anthropic-web-search/index.d.ts.map +1 -1
- package/dist/core/extensions/builtin/anthropic-web-search/index.js +20 -0
- package/dist/core/extensions/builtin/anthropic-web-search/index.js.map +1 -1
- package/dist/core/extensions/builtin/index.d.ts.map +1 -1
- package/dist/core/extensions/builtin/index.js +0 -18
- package/dist/core/extensions/builtin/index.js.map +1 -1
- package/dist/core/extensions/builtin/openai-web-search/index.d.ts.map +1 -1
- package/dist/core/extensions/builtin/openai-web-search/index.js +28 -0
- package/dist/core/extensions/builtin/openai-web-search/index.js.map +1 -1
- package/dist/core/extensions/builtin/todotools/state.d.ts.map +1 -1
- package/dist/core/extensions/builtin/todotools/state.js +1 -1
- package/dist/core/extensions/builtin/todotools/state.js.map +1 -1
- package/dist/core/resource-loader.d.ts.map +1 -1
- package/dist/core/resource-loader.js +0 -9
- package/dist/core/resource-loader.js.map +1 -1
- package/dist/core/sdk.d.ts +1 -1
- package/dist/core/sdk.d.ts.map +1 -1
- package/dist/core/sdk.js +1 -1
- package/dist/core/sdk.js.map +1 -1
- package/dist/core/session-manager.d.ts.map +1 -1
- package/dist/core/session-manager.js.map +1 -1
- package/dist/core/tools/render-utils.d.ts.map +1 -1
- package/dist/core/tools/render-utils.js +1 -1
- package/dist/core/tools/render-utils.js.map +1 -1
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +3 -2
- package/dist/main.js.map +1 -1
- package/dist/modes/interactive/components/assistant-message.d.ts +0 -3
- package/dist/modes/interactive/components/assistant-message.d.ts.map +1 -1
- package/dist/modes/interactive/components/assistant-message.js +3 -22
- package/dist/modes/interactive/components/assistant-message.js.map +1 -1
- package/dist/modes/interactive/components/bash-execution.d.ts.map +1 -1
- package/dist/modes/interactive/components/bash-execution.js +1 -1
- package/dist/modes/interactive/components/bash-execution.js.map +1 -1
- package/dist/modes/interactive/components/extension-selector.d.ts +2 -0
- package/dist/modes/interactive/components/extension-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/extension-selector.js +6 -1
- package/dist/modes/interactive/components/extension-selector.js.map +1 -1
- package/dist/modes/interactive/interactive-mode.d.ts +12 -0
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +43 -5
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/dist/modes/interactive/theme/theme.d.ts.map +1 -1
- package/dist/modes/interactive/theme/theme.js +2 -2
- package/dist/modes/interactive/theme/theme.js.map +1 -1
- package/dist/modes/print-mode.d.ts.map +1 -1
- package/dist/modes/print-mode.js +3 -11
- package/dist/modes/print-mode.js.map +1 -1
- package/dist/modes/provider-native-rendering.d.ts +5 -0
- package/dist/modes/provider-native-rendering.d.ts.map +1 -0
- package/dist/modes/provider-native-rendering.js +247 -0
- package/dist/modes/provider-native-rendering.js.map +1 -0
- package/dist/utils/ansi.d.ts +2 -0
- package/dist/utils/ansi.d.ts.map +1 -0
- package/dist/utils/ansi.js +52 -0
- package/dist/utils/ansi.js.map +1 -0
- package/dist/utils/html.d.ts +7 -0
- package/dist/utils/html.d.ts.map +1 -0
- package/dist/utils/html.js +40 -0
- package/dist/utils/html.js.map +1 -0
- package/dist/utils/mime.d.ts +1 -0
- package/dist/utils/mime.d.ts.map +1 -1
- package/dist/utils/mime.js +59 -16
- package/dist/utils/mime.js.map +1 -1
- package/dist/utils/syntax-highlight.d.ts +12 -0
- package/dist/utils/syntax-highlight.d.ts.map +1 -0
- package/dist/utils/syntax-highlight.js +118 -0
- package/dist/utils/syntax-highlight.js.map +1 -0
- package/dist/utils/tools-manager.d.ts.map +1 -1
- package/dist/utils/tools-manager.js +76 -7
- package/dist/utils/tools-manager.js.map +1 -1
- package/docs/sdk.md +25 -43
- package/examples/sdk/01-minimal.ts +14 -10
- package/examples/sdk/02-custom-model.ts +12 -8
- package/examples/sdk/03-custom-prompt.ts +24 -16
- package/examples/sdk/04-skills.ts +2 -2
- package/examples/sdk/05-tools.ts +8 -4
- package/examples/sdk/06-extensions.ts +11 -7
- package/examples/sdk/07-context-files.ts +2 -2
- package/examples/sdk/08-prompt-templates.ts +2 -2
- package/examples/sdk/09-api-keys-and-oauth.ts +8 -4
- package/examples/sdk/10-settings.ts +4 -4
- package/examples/sdk/11-sessions.ts +4 -0
- package/examples/sdk/12-full-control.ts +11 -7
- package/examples/sdk/README.md +6 -9
- package/package.json +5 -10
- package/dist/core/extensions/builtin/anthropic-code-execution/index.d.ts +0 -7
- package/dist/core/extensions/builtin/anthropic-code-execution/index.d.ts.map +0 -1
- package/dist/core/extensions/builtin/anthropic-code-execution/index.js +0 -79
- package/dist/core/extensions/builtin/anthropic-code-execution/index.js.map +0 -1
- package/dist/core/extensions/builtin/anthropic-computer-use/index.d.ts +0 -53
- package/dist/core/extensions/builtin/anthropic-computer-use/index.d.ts.map +0 -1
- package/dist/core/extensions/builtin/anthropic-computer-use/index.js +0 -676
- package/dist/core/extensions/builtin/anthropic-computer-use/index.js.map +0 -1
- package/dist/core/extensions/builtin/anthropic-text-editor/index.d.ts +0 -25
- package/dist/core/extensions/builtin/anthropic-text-editor/index.d.ts.map +0 -1
- package/dist/core/extensions/builtin/anthropic-text-editor/index.js +0 -244
- package/dist/core/extensions/builtin/anthropic-text-editor/index.js.map +0 -1
- package/dist/core/extensions/builtin/anthropic-tool-search/index.d.ts +0 -6
- package/dist/core/extensions/builtin/anthropic-tool-search/index.d.ts.map +0 -1
- package/dist/core/extensions/builtin/anthropic-tool-search/index.js +0 -112
- package/dist/core/extensions/builtin/anthropic-tool-search/index.js.map +0 -1
- package/dist/core/extensions/builtin/google-code-execution/index.d.ts +0 -7
- package/dist/core/extensions/builtin/google-code-execution/index.d.ts.map +0 -1
- package/dist/core/extensions/builtin/google-code-execution/index.js +0 -73
- package/dist/core/extensions/builtin/google-code-execution/index.js.map +0 -1
- package/dist/core/extensions/builtin/google-google-search/index.d.ts +0 -7
- package/dist/core/extensions/builtin/google-google-search/index.d.ts.map +0 -1
- package/dist/core/extensions/builtin/google-google-search/index.js +0 -83
- package/dist/core/extensions/builtin/google-google-search/index.js.map +0 -1
- package/dist/core/extensions/builtin/google-url-context/index.d.ts +0 -7
- package/dist/core/extensions/builtin/google-url-context/index.d.ts.map +0 -1
- package/dist/core/extensions/builtin/google-url-context/index.js +0 -82
- package/dist/core/extensions/builtin/google-url-context/index.js.map +0 -1
- package/dist/core/extensions/builtin/openai-api-parallel-tool-calls/index.d.ts +0 -6
- package/dist/core/extensions/builtin/openai-api-parallel-tool-calls/index.d.ts.map +0 -1
- package/dist/core/extensions/builtin/openai-api-parallel-tool-calls/index.js +0 -57
- package/dist/core/extensions/builtin/openai-api-parallel-tool-calls/index.js.map +0 -1
- package/dist/core/extensions/builtin/openai-code-interpreter/index.d.ts +0 -10
- package/dist/core/extensions/builtin/openai-code-interpreter/index.d.ts.map +0 -1
- package/dist/core/extensions/builtin/openai-code-interpreter/index.js +0 -95
- package/dist/core/extensions/builtin/openai-code-interpreter/index.js.map +0 -1
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
import type { Api } from "@earendil-works/pi-ai";
|
|
2
|
-
import type { ExtensionAPI } from "../../types.js";
|
|
3
|
-
export declare function isGoogleCodeExecutionEnabled(): boolean;
|
|
4
|
-
export declare function addGoogleCodeExecutionToPayload(api: Api | undefined, payload: unknown): unknown;
|
|
5
|
-
export declare const GOOGLE_CODE_EXECUTION_SECTION = "\n## Code Execution\n\nThe native code_execution tool is available in this session. The model\nruns Python in a Google-managed sandbox. Prefer code_execution for\nnumerical work, file analysis, and one-off computations when explicit\nresults are needed.\n";
|
|
6
|
-
export default function googleCodeExecutionExtension(pi: ExtensionAPI): void;
|
|
7
|
-
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/google-code-execution/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,uBAAuB,CAAC;AACjD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AA0BnD,wBAAgB,4BAA4B,IAAI,OAAO,CAQtD;AAED,wBAAgB,+BAA+B,CAAC,GAAG,EAAE,GAAG,GAAG,SAAS,EAAE,OAAO,EAAE,OAAO,GAAG,OAAO,CA2B/F;AAED,eAAO,MAAM,6BAA6B,oQAOzC,CAAC;AAEF,MAAM,CAAC,OAAO,UAAU,4BAA4B,CAAC,EAAE,EAAE,YAAY,GAAG,IAAI,CAkB3E","sourcesContent":["import type { Api } from \"@earendil-works/pi-ai\";\nimport type { ExtensionAPI } from \"../../types.js\";\n\ntype ToolDefinition = Record<string, unknown>;\n\nconst ENABLE_ENV = \"PI_GOOGLE_CODE_EXECUTION\";\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n\treturn typeof value === \"object\" && value !== null;\n}\n\nfunction isGoogleApi(api: Api | undefined): api is \"google-generative-ai\" | \"google-vertex\" {\n\treturn api === \"google-generative-ai\" || api === \"google-vertex\";\n}\n\nfunction sanitizeTools(tools: unknown[]): ToolDefinition[] {\n\tconst sanitizedTools: ToolDefinition[] = [];\n\tfor (const tool of tools) {\n\t\tif (!isRecord(tool)) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tsanitizedTools.push(tool);\n\t}\n\treturn sanitizedTools;\n}\n\nexport function isGoogleCodeExecutionEnabled(): boolean {\n\tconst value = process.env[ENABLE_ENV];\n\tif (!value) {\n\t\treturn false;\n\t}\n\n\tconst normalized = value.trim().toLowerCase();\n\treturn normalized === \"1\" || normalized === \"true\" || normalized === \"yes\" || normalized === \"on\";\n}\n\nexport function addGoogleCodeExecutionToPayload(api: Api | undefined, payload: unknown): unknown {\n\tif (!isGoogleApi(api)) {\n\t\treturn payload;\n\t}\n\n\tif (!isGoogleCodeExecutionEnabled()) {\n\t\treturn payload;\n\t}\n\n\tif (!isRecord(payload)) {\n\t\treturn payload;\n\t}\n\n\tconst tools = Array.isArray(payload.tools) ? payload.tools : [];\n\tconst sanitizedTools = sanitizeTools(tools);\n\n\t// Google function tools use `functionDeclarations`, not a `codeExecution` key,\n\t// so there is no function-tool name conflict to deduplicate here.\n\tconst hasCodeExecution = sanitizedTools.some((tool) => \"codeExecution\" in tool);\n\tif (!hasCodeExecution) {\n\t\tsanitizedTools.push({ codeExecution: {} });\n\t}\n\n\treturn {\n\t\t...payload,\n\t\ttools: sanitizedTools,\n\t};\n}\n\nexport const GOOGLE_CODE_EXECUTION_SECTION = `\n## Code Execution\n\nThe native code_execution tool is available in this session. The model\nruns Python in a Google-managed sandbox. Prefer code_execution for\nnumerical work, file analysis, and one-off computations when explicit\nresults are needed.\n`;\n\nexport default function googleCodeExecutionExtension(pi: ExtensionAPI): void {\n\tpi.on(\"before_provider_request\", (event, ctx) => {\n\t\treturn addGoogleCodeExecutionToPayload(ctx.model?.api, event.payload);\n\t});\n\n\tpi.on(\"before_agent_start\", async (event, ctx) => {\n\t\tif (!isGoogleApi(ctx.model?.api)) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\tif (!isGoogleCodeExecutionEnabled()) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\treturn {\n\t\t\tsystemPrompt: `${event.systemPrompt}\\n${GOOGLE_CODE_EXECUTION_SECTION}`,\n\t\t};\n\t});\n}\n"]}
|
|
@@ -1,73 +0,0 @@
|
|
|
1
|
-
const ENABLE_ENV = "PI_GOOGLE_CODE_EXECUTION";
|
|
2
|
-
function isRecord(value) {
|
|
3
|
-
return typeof value === "object" && value !== null;
|
|
4
|
-
}
|
|
5
|
-
function isGoogleApi(api) {
|
|
6
|
-
return api === "google-generative-ai" || api === "google-vertex";
|
|
7
|
-
}
|
|
8
|
-
function sanitizeTools(tools) {
|
|
9
|
-
const sanitizedTools = [];
|
|
10
|
-
for (const tool of tools) {
|
|
11
|
-
if (!isRecord(tool)) {
|
|
12
|
-
continue;
|
|
13
|
-
}
|
|
14
|
-
sanitizedTools.push(tool);
|
|
15
|
-
}
|
|
16
|
-
return sanitizedTools;
|
|
17
|
-
}
|
|
18
|
-
export function isGoogleCodeExecutionEnabled() {
|
|
19
|
-
const value = process.env[ENABLE_ENV];
|
|
20
|
-
if (!value) {
|
|
21
|
-
return false;
|
|
22
|
-
}
|
|
23
|
-
const normalized = value.trim().toLowerCase();
|
|
24
|
-
return normalized === "1" || normalized === "true" || normalized === "yes" || normalized === "on";
|
|
25
|
-
}
|
|
26
|
-
export function addGoogleCodeExecutionToPayload(api, payload) {
|
|
27
|
-
if (!isGoogleApi(api)) {
|
|
28
|
-
return payload;
|
|
29
|
-
}
|
|
30
|
-
if (!isGoogleCodeExecutionEnabled()) {
|
|
31
|
-
return payload;
|
|
32
|
-
}
|
|
33
|
-
if (!isRecord(payload)) {
|
|
34
|
-
return payload;
|
|
35
|
-
}
|
|
36
|
-
const tools = Array.isArray(payload.tools) ? payload.tools : [];
|
|
37
|
-
const sanitizedTools = sanitizeTools(tools);
|
|
38
|
-
// Google function tools use `functionDeclarations`, not a `codeExecution` key,
|
|
39
|
-
// so there is no function-tool name conflict to deduplicate here.
|
|
40
|
-
const hasCodeExecution = sanitizedTools.some((tool) => "codeExecution" in tool);
|
|
41
|
-
if (!hasCodeExecution) {
|
|
42
|
-
sanitizedTools.push({ codeExecution: {} });
|
|
43
|
-
}
|
|
44
|
-
return {
|
|
45
|
-
...payload,
|
|
46
|
-
tools: sanitizedTools,
|
|
47
|
-
};
|
|
48
|
-
}
|
|
49
|
-
export const GOOGLE_CODE_EXECUTION_SECTION = `
|
|
50
|
-
## Code Execution
|
|
51
|
-
|
|
52
|
-
The native code_execution tool is available in this session. The model
|
|
53
|
-
runs Python in a Google-managed sandbox. Prefer code_execution for
|
|
54
|
-
numerical work, file analysis, and one-off computations when explicit
|
|
55
|
-
results are needed.
|
|
56
|
-
`;
|
|
57
|
-
export default function googleCodeExecutionExtension(pi) {
|
|
58
|
-
pi.on("before_provider_request", (event, ctx) => {
|
|
59
|
-
return addGoogleCodeExecutionToPayload(ctx.model?.api, event.payload);
|
|
60
|
-
});
|
|
61
|
-
pi.on("before_agent_start", async (event, ctx) => {
|
|
62
|
-
if (!isGoogleApi(ctx.model?.api)) {
|
|
63
|
-
return undefined;
|
|
64
|
-
}
|
|
65
|
-
if (!isGoogleCodeExecutionEnabled()) {
|
|
66
|
-
return undefined;
|
|
67
|
-
}
|
|
68
|
-
return {
|
|
69
|
-
systemPrompt: `${event.systemPrompt}\n${GOOGLE_CODE_EXECUTION_SECTION}`,
|
|
70
|
-
};
|
|
71
|
-
});
|
|
72
|
-
}
|
|
73
|
-
//# sourceMappingURL=index.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/google-code-execution/index.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Api } from \"@earendil-works/pi-ai\";\nimport type { ExtensionAPI } from \"../../types.js\";\n\ntype ToolDefinition = Record<string, unknown>;\n\nconst ENABLE_ENV = \"PI_GOOGLE_CODE_EXECUTION\";\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n\treturn typeof value === \"object\" && value !== null;\n}\n\nfunction isGoogleApi(api: Api | undefined): api is \"google-generative-ai\" | \"google-vertex\" {\n\treturn api === \"google-generative-ai\" || api === \"google-vertex\";\n}\n\nfunction sanitizeTools(tools: unknown[]): ToolDefinition[] {\n\tconst sanitizedTools: ToolDefinition[] = [];\n\tfor (const tool of tools) {\n\t\tif (!isRecord(tool)) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tsanitizedTools.push(tool);\n\t}\n\treturn sanitizedTools;\n}\n\nexport function isGoogleCodeExecutionEnabled(): boolean {\n\tconst value = process.env[ENABLE_ENV];\n\tif (!value) {\n\t\treturn false;\n\t}\n\n\tconst normalized = value.trim().toLowerCase();\n\treturn normalized === \"1\" || normalized === \"true\" || normalized === \"yes\" || normalized === \"on\";\n}\n\nexport function addGoogleCodeExecutionToPayload(api: Api | undefined, payload: unknown): unknown {\n\tif (!isGoogleApi(api)) {\n\t\treturn payload;\n\t}\n\n\tif (!isGoogleCodeExecutionEnabled()) {\n\t\treturn payload;\n\t}\n\n\tif (!isRecord(payload)) {\n\t\treturn payload;\n\t}\n\n\tconst tools = Array.isArray(payload.tools) ? payload.tools : [];\n\tconst sanitizedTools = sanitizeTools(tools);\n\n\t// Google function tools use `functionDeclarations`, not a `codeExecution` key,\n\t// so there is no function-tool name conflict to deduplicate here.\n\tconst hasCodeExecution = sanitizedTools.some((tool) => \"codeExecution\" in tool);\n\tif (!hasCodeExecution) {\n\t\tsanitizedTools.push({ codeExecution: {} });\n\t}\n\n\treturn {\n\t\t...payload,\n\t\ttools: sanitizedTools,\n\t};\n}\n\nexport const GOOGLE_CODE_EXECUTION_SECTION = `\n## Code Execution\n\nThe native code_execution tool is available in this session. The model\nruns Python in a Google-managed sandbox. Prefer code_execution for\nnumerical work, file analysis, and one-off computations when explicit\nresults are needed.\n`;\n\nexport default function googleCodeExecutionExtension(pi: ExtensionAPI): void {\n\tpi.on(\"before_provider_request\", (event, ctx) => {\n\t\treturn addGoogleCodeExecutionToPayload(ctx.model?.api, event.payload);\n\t});\n\n\tpi.on(\"before_agent_start\", async (event, ctx) => {\n\t\tif (!isGoogleApi(ctx.model?.api)) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\tif (!isGoogleCodeExecutionEnabled()) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\treturn {\n\t\t\tsystemPrompt: `${event.systemPrompt}\\n${GOOGLE_CODE_EXECUTION_SECTION}`,\n\t\t};\n\t});\n}\n"]}
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
import type { Api } from "@earendil-works/pi-ai";
|
|
2
|
-
import type { ExtensionAPI } from "../../types.js";
|
|
3
|
-
export declare function addGoogleGoogleSearchToPayload(api: Api | undefined, payload: unknown): unknown;
|
|
4
|
-
export declare function isGoogleGoogleSearchEnabled(): boolean;
|
|
5
|
-
export declare const GOOGLE_GOOGLE_SEARCH_SECTION = "\n## Google Search\n\nThe native google_search tool is available in this session. The model\nqueries Google for current information and grounds responses in real\nsearch results. Prefer google_search when the user asks for current\nor online information.\n";
|
|
6
|
-
export default function googleGoogleSearchExtension(pi: ExtensionAPI): void;
|
|
7
|
-
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/google-google-search/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,uBAAuB,CAAC;AACjD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AA6CnD,wBAAgB,8BAA8B,CAAC,GAAG,EAAE,GAAG,GAAG,SAAS,EAAE,OAAO,EAAE,OAAO,GAAG,OAAO,CA2B9F;AAED,wBAAgB,2BAA2B,IAAI,OAAO,CAErD;AAED,eAAO,MAAM,4BAA4B,qQAOxC,CAAC;AAEF,MAAM,CAAC,OAAO,UAAU,2BAA2B,CAAC,EAAE,EAAE,YAAY,GAAG,IAAI,CAkB1E","sourcesContent":["import type { Api } from \"@earendil-works/pi-ai\";\nimport type { ExtensionAPI } from \"../../types.js\";\n\ntype ToolDefinition = Record<string, unknown>;\n\nconst ENABLE_ENV = \"PI_GOOGLE_GOOGLE_SEARCH\";\n\nfunction parseEnableEnv(envVar: string): boolean {\n\tconst envValue = process.env[envVar];\n\tif (!envValue) {\n\t\treturn true;\n\t}\n\n\tconst normalized = envValue.trim().toLowerCase();\n\tif (normalized === \"0\" || normalized === \"false\" || normalized === \"no\" || normalized === \"off\") {\n\t\treturn false;\n\t}\n\n\tif (normalized === \"1\" || normalized === \"true\" || normalized === \"yes\" || normalized === \"on\") {\n\t\treturn true;\n\t}\n\n\t// Unknown values fall back to default-on behavior.\n\treturn true;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n\treturn typeof value === \"object\" && value !== null;\n}\n\nfunction isGoogleApi(api: Api | undefined): api is \"google-generative-ai\" | \"google-vertex\" {\n\treturn api === \"google-generative-ai\" || api === \"google-vertex\";\n}\n\nfunction sanitizeTools(tools: unknown[]): ToolDefinition[] {\n\tconst sanitizedTools: ToolDefinition[] = [];\n\tfor (const tool of tools) {\n\t\tif (!isRecord(tool)) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tsanitizedTools.push(tool);\n\t}\n\treturn sanitizedTools;\n}\n\nexport function addGoogleGoogleSearchToPayload(api: Api | undefined, payload: unknown): unknown {\n\tif (!isGoogleApi(api)) {\n\t\treturn payload;\n\t}\n\n\tif (!isGoogleGoogleSearchEnabled()) {\n\t\treturn payload;\n\t}\n\n\tif (!isRecord(payload)) {\n\t\treturn payload;\n\t}\n\n\tconst tools = Array.isArray(payload.tools) ? payload.tools : [];\n\tconst sanitizedTools = sanitizeTools(tools);\n\n\t// Google function tools use `functionDeclarations`, not a `googleSearch` key,\n\t// so there is no function-tool name conflict to deduplicate here.\n\tconst hasGoogleSearch = sanitizedTools.some((tool) => \"googleSearch\" in tool);\n\tif (!hasGoogleSearch) {\n\t\tsanitizedTools.push({ googleSearch: {} });\n\t}\n\n\treturn {\n\t\t...payload,\n\t\ttools: sanitizedTools,\n\t};\n}\n\nexport function isGoogleGoogleSearchEnabled(): boolean {\n\treturn parseEnableEnv(ENABLE_ENV);\n}\n\nexport const GOOGLE_GOOGLE_SEARCH_SECTION = `\n## Google Search\n\nThe native google_search tool is available in this session. The model\nqueries Google for current information and grounds responses in real\nsearch results. Prefer google_search when the user asks for current\nor online information.\n`;\n\nexport default function googleGoogleSearchExtension(pi: ExtensionAPI): void {\n\tpi.on(\"before_provider_request\", (event, ctx) => {\n\t\treturn addGoogleGoogleSearchToPayload(ctx.model?.api, event.payload);\n\t});\n\n\tpi.on(\"before_agent_start\", async (event, ctx) => {\n\t\tif (!isGoogleApi(ctx.model?.api)) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\tif (!isGoogleGoogleSearchEnabled()) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\treturn {\n\t\t\tsystemPrompt: `${event.systemPrompt}\\n${GOOGLE_GOOGLE_SEARCH_SECTION}`,\n\t\t};\n\t});\n}\n"]}
|
|
@@ -1,83 +0,0 @@
|
|
|
1
|
-
const ENABLE_ENV = "PI_GOOGLE_GOOGLE_SEARCH";
|
|
2
|
-
function parseEnableEnv(envVar) {
|
|
3
|
-
const envValue = process.env[envVar];
|
|
4
|
-
if (!envValue) {
|
|
5
|
-
return true;
|
|
6
|
-
}
|
|
7
|
-
const normalized = envValue.trim().toLowerCase();
|
|
8
|
-
if (normalized === "0" || normalized === "false" || normalized === "no" || normalized === "off") {
|
|
9
|
-
return false;
|
|
10
|
-
}
|
|
11
|
-
if (normalized === "1" || normalized === "true" || normalized === "yes" || normalized === "on") {
|
|
12
|
-
return true;
|
|
13
|
-
}
|
|
14
|
-
// Unknown values fall back to default-on behavior.
|
|
15
|
-
return true;
|
|
16
|
-
}
|
|
17
|
-
function isRecord(value) {
|
|
18
|
-
return typeof value === "object" && value !== null;
|
|
19
|
-
}
|
|
20
|
-
function isGoogleApi(api) {
|
|
21
|
-
return api === "google-generative-ai" || api === "google-vertex";
|
|
22
|
-
}
|
|
23
|
-
function sanitizeTools(tools) {
|
|
24
|
-
const sanitizedTools = [];
|
|
25
|
-
for (const tool of tools) {
|
|
26
|
-
if (!isRecord(tool)) {
|
|
27
|
-
continue;
|
|
28
|
-
}
|
|
29
|
-
sanitizedTools.push(tool);
|
|
30
|
-
}
|
|
31
|
-
return sanitizedTools;
|
|
32
|
-
}
|
|
33
|
-
export function addGoogleGoogleSearchToPayload(api, payload) {
|
|
34
|
-
if (!isGoogleApi(api)) {
|
|
35
|
-
return payload;
|
|
36
|
-
}
|
|
37
|
-
if (!isGoogleGoogleSearchEnabled()) {
|
|
38
|
-
return payload;
|
|
39
|
-
}
|
|
40
|
-
if (!isRecord(payload)) {
|
|
41
|
-
return payload;
|
|
42
|
-
}
|
|
43
|
-
const tools = Array.isArray(payload.tools) ? payload.tools : [];
|
|
44
|
-
const sanitizedTools = sanitizeTools(tools);
|
|
45
|
-
// Google function tools use `functionDeclarations`, not a `googleSearch` key,
|
|
46
|
-
// so there is no function-tool name conflict to deduplicate here.
|
|
47
|
-
const hasGoogleSearch = sanitizedTools.some((tool) => "googleSearch" in tool);
|
|
48
|
-
if (!hasGoogleSearch) {
|
|
49
|
-
sanitizedTools.push({ googleSearch: {} });
|
|
50
|
-
}
|
|
51
|
-
return {
|
|
52
|
-
...payload,
|
|
53
|
-
tools: sanitizedTools,
|
|
54
|
-
};
|
|
55
|
-
}
|
|
56
|
-
export function isGoogleGoogleSearchEnabled() {
|
|
57
|
-
return parseEnableEnv(ENABLE_ENV);
|
|
58
|
-
}
|
|
59
|
-
export const GOOGLE_GOOGLE_SEARCH_SECTION = `
|
|
60
|
-
## Google Search
|
|
61
|
-
|
|
62
|
-
The native google_search tool is available in this session. The model
|
|
63
|
-
queries Google for current information and grounds responses in real
|
|
64
|
-
search results. Prefer google_search when the user asks for current
|
|
65
|
-
or online information.
|
|
66
|
-
`;
|
|
67
|
-
export default function googleGoogleSearchExtension(pi) {
|
|
68
|
-
pi.on("before_provider_request", (event, ctx) => {
|
|
69
|
-
return addGoogleGoogleSearchToPayload(ctx.model?.api, event.payload);
|
|
70
|
-
});
|
|
71
|
-
pi.on("before_agent_start", async (event, ctx) => {
|
|
72
|
-
if (!isGoogleApi(ctx.model?.api)) {
|
|
73
|
-
return undefined;
|
|
74
|
-
}
|
|
75
|
-
if (!isGoogleGoogleSearchEnabled()) {
|
|
76
|
-
return undefined;
|
|
77
|
-
}
|
|
78
|
-
return {
|
|
79
|
-
systemPrompt: `${event.systemPrompt}\n${GOOGLE_GOOGLE_SEARCH_SECTION}`,
|
|
80
|
-
};
|
|
81
|
-
});
|
|
82
|
-
}
|
|
83
|
-
//# sourceMappingURL=index.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/google-google-search/index.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Api } from \"@earendil-works/pi-ai\";\nimport type { ExtensionAPI } from \"../../types.js\";\n\ntype ToolDefinition = Record<string, unknown>;\n\nconst ENABLE_ENV = \"PI_GOOGLE_GOOGLE_SEARCH\";\n\nfunction parseEnableEnv(envVar: string): boolean {\n\tconst envValue = process.env[envVar];\n\tif (!envValue) {\n\t\treturn true;\n\t}\n\n\tconst normalized = envValue.trim().toLowerCase();\n\tif (normalized === \"0\" || normalized === \"false\" || normalized === \"no\" || normalized === \"off\") {\n\t\treturn false;\n\t}\n\n\tif (normalized === \"1\" || normalized === \"true\" || normalized === \"yes\" || normalized === \"on\") {\n\t\treturn true;\n\t}\n\n\t// Unknown values fall back to default-on behavior.\n\treturn true;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n\treturn typeof value === \"object\" && value !== null;\n}\n\nfunction isGoogleApi(api: Api | undefined): api is \"google-generative-ai\" | \"google-vertex\" {\n\treturn api === \"google-generative-ai\" || api === \"google-vertex\";\n}\n\nfunction sanitizeTools(tools: unknown[]): ToolDefinition[] {\n\tconst sanitizedTools: ToolDefinition[] = [];\n\tfor (const tool of tools) {\n\t\tif (!isRecord(tool)) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tsanitizedTools.push(tool);\n\t}\n\treturn sanitizedTools;\n}\n\nexport function addGoogleGoogleSearchToPayload(api: Api | undefined, payload: unknown): unknown {\n\tif (!isGoogleApi(api)) {\n\t\treturn payload;\n\t}\n\n\tif (!isGoogleGoogleSearchEnabled()) {\n\t\treturn payload;\n\t}\n\n\tif (!isRecord(payload)) {\n\t\treturn payload;\n\t}\n\n\tconst tools = Array.isArray(payload.tools) ? payload.tools : [];\n\tconst sanitizedTools = sanitizeTools(tools);\n\n\t// Google function tools use `functionDeclarations`, not a `googleSearch` key,\n\t// so there is no function-tool name conflict to deduplicate here.\n\tconst hasGoogleSearch = sanitizedTools.some((tool) => \"googleSearch\" in tool);\n\tif (!hasGoogleSearch) {\n\t\tsanitizedTools.push({ googleSearch: {} });\n\t}\n\n\treturn {\n\t\t...payload,\n\t\ttools: sanitizedTools,\n\t};\n}\n\nexport function isGoogleGoogleSearchEnabled(): boolean {\n\treturn parseEnableEnv(ENABLE_ENV);\n}\n\nexport const GOOGLE_GOOGLE_SEARCH_SECTION = `\n## Google Search\n\nThe native google_search tool is available in this session. The model\nqueries Google for current information and grounds responses in real\nsearch results. Prefer google_search when the user asks for current\nor online information.\n`;\n\nexport default function googleGoogleSearchExtension(pi: ExtensionAPI): void {\n\tpi.on(\"before_provider_request\", (event, ctx) => {\n\t\treturn addGoogleGoogleSearchToPayload(ctx.model?.api, event.payload);\n\t});\n\n\tpi.on(\"before_agent_start\", async (event, ctx) => {\n\t\tif (!isGoogleApi(ctx.model?.api)) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\tif (!isGoogleGoogleSearchEnabled()) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\treturn {\n\t\t\tsystemPrompt: `${event.systemPrompt}\\n${GOOGLE_GOOGLE_SEARCH_SECTION}`,\n\t\t};\n\t});\n}\n"]}
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
import type { Api } from "@earendil-works/pi-ai";
|
|
2
|
-
import type { ExtensionAPI } from "../../types.js";
|
|
3
|
-
export declare function addGoogleUrlContextToPayload(api: Api | undefined, payload: unknown): unknown;
|
|
4
|
-
export declare function isGoogleUrlContextEnabled(): boolean;
|
|
5
|
-
export declare const GOOGLE_URL_CONTEXT_SECTION = "\n## URL Context\n\nThe native url_context tool is available in this session. The model\nfetches and grounds responses in URL contents. Prefer url_context\nwhen the user references specific URLs they want analyzed.\n";
|
|
6
|
-
export default function googleUrlContextExtension(pi: ExtensionAPI): void;
|
|
7
|
-
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/google-url-context/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,uBAAuB,CAAC;AACjD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AA6CnD,wBAAgB,4BAA4B,CAAC,GAAG,EAAE,GAAG,GAAG,SAAS,EAAE,OAAO,EAAE,OAAO,GAAG,OAAO,CA2B5F;AAED,wBAAgB,yBAAyB,IAAI,OAAO,CAEnD;AAED,eAAO,MAAM,0BAA0B,6NAMtC,CAAC;AAEF,MAAM,CAAC,OAAO,UAAU,yBAAyB,CAAC,EAAE,EAAE,YAAY,GAAG,IAAI,CAkBxE","sourcesContent":["import type { Api } from \"@earendil-works/pi-ai\";\nimport type { ExtensionAPI } from \"../../types.js\";\n\ntype ToolDefinition = Record<string, unknown>;\n\nconst ENABLE_ENV = \"PI_GOOGLE_URL_CONTEXT\";\n\nfunction parseEnableEnv(envVar: string): boolean {\n\tconst envValue = process.env[envVar];\n\tif (!envValue) {\n\t\treturn true;\n\t}\n\n\tconst normalized = envValue.trim().toLowerCase();\n\tif (normalized === \"0\" || normalized === \"false\" || normalized === \"no\" || normalized === \"off\") {\n\t\treturn false;\n\t}\n\n\tif (normalized === \"1\" || normalized === \"true\" || normalized === \"yes\" || normalized === \"on\") {\n\t\treturn true;\n\t}\n\n\t// Unknown values fall back to default-on behavior.\n\treturn true;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n\treturn typeof value === \"object\" && value !== null;\n}\n\nfunction isGoogleApi(api: Api | undefined): api is \"google-generative-ai\" | \"google-vertex\" {\n\treturn api === \"google-generative-ai\" || api === \"google-vertex\";\n}\n\nfunction sanitizeTools(tools: unknown[]): ToolDefinition[] {\n\tconst sanitizedTools: ToolDefinition[] = [];\n\tfor (const tool of tools) {\n\t\tif (!isRecord(tool)) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tsanitizedTools.push(tool);\n\t}\n\treturn sanitizedTools;\n}\n\nexport function addGoogleUrlContextToPayload(api: Api | undefined, payload: unknown): unknown {\n\tif (!isGoogleApi(api)) {\n\t\treturn payload;\n\t}\n\n\tif (!isGoogleUrlContextEnabled()) {\n\t\treturn payload;\n\t}\n\n\tif (!isRecord(payload)) {\n\t\treturn payload;\n\t}\n\n\tconst tools = Array.isArray(payload.tools) ? payload.tools : [];\n\tconst sanitizedTools = sanitizeTools(tools);\n\n\t// Google function tools use `functionDeclarations`, not a `urlContext` key,\n\t// so there is no function-tool name conflict to deduplicate here.\n\tconst hasUrlContext = sanitizedTools.some((tool) => \"urlContext\" in tool);\n\tif (!hasUrlContext) {\n\t\tsanitizedTools.push({ urlContext: {} });\n\t}\n\n\treturn {\n\t\t...payload,\n\t\ttools: sanitizedTools,\n\t};\n}\n\nexport function isGoogleUrlContextEnabled(): boolean {\n\treturn parseEnableEnv(ENABLE_ENV);\n}\n\nexport const GOOGLE_URL_CONTEXT_SECTION = `\n## URL Context\n\nThe native url_context tool is available in this session. The model\nfetches and grounds responses in URL contents. Prefer url_context\nwhen the user references specific URLs they want analyzed.\n`;\n\nexport default function googleUrlContextExtension(pi: ExtensionAPI): void {\n\tpi.on(\"before_provider_request\", (event, ctx) => {\n\t\treturn addGoogleUrlContextToPayload(ctx.model?.api, event.payload);\n\t});\n\n\tpi.on(\"before_agent_start\", async (event, ctx) => {\n\t\tif (!isGoogleApi(ctx.model?.api)) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\tif (!isGoogleUrlContextEnabled()) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\treturn {\n\t\t\tsystemPrompt: `${event.systemPrompt}\\n${GOOGLE_URL_CONTEXT_SECTION}`,\n\t\t};\n\t});\n}\n"]}
|
|
@@ -1,82 +0,0 @@
|
|
|
1
|
-
const ENABLE_ENV = "PI_GOOGLE_URL_CONTEXT";
|
|
2
|
-
function parseEnableEnv(envVar) {
|
|
3
|
-
const envValue = process.env[envVar];
|
|
4
|
-
if (!envValue) {
|
|
5
|
-
return true;
|
|
6
|
-
}
|
|
7
|
-
const normalized = envValue.trim().toLowerCase();
|
|
8
|
-
if (normalized === "0" || normalized === "false" || normalized === "no" || normalized === "off") {
|
|
9
|
-
return false;
|
|
10
|
-
}
|
|
11
|
-
if (normalized === "1" || normalized === "true" || normalized === "yes" || normalized === "on") {
|
|
12
|
-
return true;
|
|
13
|
-
}
|
|
14
|
-
// Unknown values fall back to default-on behavior.
|
|
15
|
-
return true;
|
|
16
|
-
}
|
|
17
|
-
function isRecord(value) {
|
|
18
|
-
return typeof value === "object" && value !== null;
|
|
19
|
-
}
|
|
20
|
-
function isGoogleApi(api) {
|
|
21
|
-
return api === "google-generative-ai" || api === "google-vertex";
|
|
22
|
-
}
|
|
23
|
-
function sanitizeTools(tools) {
|
|
24
|
-
const sanitizedTools = [];
|
|
25
|
-
for (const tool of tools) {
|
|
26
|
-
if (!isRecord(tool)) {
|
|
27
|
-
continue;
|
|
28
|
-
}
|
|
29
|
-
sanitizedTools.push(tool);
|
|
30
|
-
}
|
|
31
|
-
return sanitizedTools;
|
|
32
|
-
}
|
|
33
|
-
export function addGoogleUrlContextToPayload(api, payload) {
|
|
34
|
-
if (!isGoogleApi(api)) {
|
|
35
|
-
return payload;
|
|
36
|
-
}
|
|
37
|
-
if (!isGoogleUrlContextEnabled()) {
|
|
38
|
-
return payload;
|
|
39
|
-
}
|
|
40
|
-
if (!isRecord(payload)) {
|
|
41
|
-
return payload;
|
|
42
|
-
}
|
|
43
|
-
const tools = Array.isArray(payload.tools) ? payload.tools : [];
|
|
44
|
-
const sanitizedTools = sanitizeTools(tools);
|
|
45
|
-
// Google function tools use `functionDeclarations`, not a `urlContext` key,
|
|
46
|
-
// so there is no function-tool name conflict to deduplicate here.
|
|
47
|
-
const hasUrlContext = sanitizedTools.some((tool) => "urlContext" in tool);
|
|
48
|
-
if (!hasUrlContext) {
|
|
49
|
-
sanitizedTools.push({ urlContext: {} });
|
|
50
|
-
}
|
|
51
|
-
return {
|
|
52
|
-
...payload,
|
|
53
|
-
tools: sanitizedTools,
|
|
54
|
-
};
|
|
55
|
-
}
|
|
56
|
-
export function isGoogleUrlContextEnabled() {
|
|
57
|
-
return parseEnableEnv(ENABLE_ENV);
|
|
58
|
-
}
|
|
59
|
-
export const GOOGLE_URL_CONTEXT_SECTION = `
|
|
60
|
-
## URL Context
|
|
61
|
-
|
|
62
|
-
The native url_context tool is available in this session. The model
|
|
63
|
-
fetches and grounds responses in URL contents. Prefer url_context
|
|
64
|
-
when the user references specific URLs they want analyzed.
|
|
65
|
-
`;
|
|
66
|
-
export default function googleUrlContextExtension(pi) {
|
|
67
|
-
pi.on("before_provider_request", (event, ctx) => {
|
|
68
|
-
return addGoogleUrlContextToPayload(ctx.model?.api, event.payload);
|
|
69
|
-
});
|
|
70
|
-
pi.on("before_agent_start", async (event, ctx) => {
|
|
71
|
-
if (!isGoogleApi(ctx.model?.api)) {
|
|
72
|
-
return undefined;
|
|
73
|
-
}
|
|
74
|
-
if (!isGoogleUrlContextEnabled()) {
|
|
75
|
-
return undefined;
|
|
76
|
-
}
|
|
77
|
-
return {
|
|
78
|
-
systemPrompt: `${event.systemPrompt}\n${GOOGLE_URL_CONTEXT_SECTION}`,
|
|
79
|
-
};
|
|
80
|
-
});
|
|
81
|
-
}
|
|
82
|
-
//# sourceMappingURL=index.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/google-url-context/index.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Api } from \"@earendil-works/pi-ai\";\nimport type { ExtensionAPI } from \"../../types.js\";\n\ntype ToolDefinition = Record<string, unknown>;\n\nconst ENABLE_ENV = \"PI_GOOGLE_URL_CONTEXT\";\n\nfunction parseEnableEnv(envVar: string): boolean {\n\tconst envValue = process.env[envVar];\n\tif (!envValue) {\n\t\treturn true;\n\t}\n\n\tconst normalized = envValue.trim().toLowerCase();\n\tif (normalized === \"0\" || normalized === \"false\" || normalized === \"no\" || normalized === \"off\") {\n\t\treturn false;\n\t}\n\n\tif (normalized === \"1\" || normalized === \"true\" || normalized === \"yes\" || normalized === \"on\") {\n\t\treturn true;\n\t}\n\n\t// Unknown values fall back to default-on behavior.\n\treturn true;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n\treturn typeof value === \"object\" && value !== null;\n}\n\nfunction isGoogleApi(api: Api | undefined): api is \"google-generative-ai\" | \"google-vertex\" {\n\treturn api === \"google-generative-ai\" || api === \"google-vertex\";\n}\n\nfunction sanitizeTools(tools: unknown[]): ToolDefinition[] {\n\tconst sanitizedTools: ToolDefinition[] = [];\n\tfor (const tool of tools) {\n\t\tif (!isRecord(tool)) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tsanitizedTools.push(tool);\n\t}\n\treturn sanitizedTools;\n}\n\nexport function addGoogleUrlContextToPayload(api: Api | undefined, payload: unknown): unknown {\n\tif (!isGoogleApi(api)) {\n\t\treturn payload;\n\t}\n\n\tif (!isGoogleUrlContextEnabled()) {\n\t\treturn payload;\n\t}\n\n\tif (!isRecord(payload)) {\n\t\treturn payload;\n\t}\n\n\tconst tools = Array.isArray(payload.tools) ? payload.tools : [];\n\tconst sanitizedTools = sanitizeTools(tools);\n\n\t// Google function tools use `functionDeclarations`, not a `urlContext` key,\n\t// so there is no function-tool name conflict to deduplicate here.\n\tconst hasUrlContext = sanitizedTools.some((tool) => \"urlContext\" in tool);\n\tif (!hasUrlContext) {\n\t\tsanitizedTools.push({ urlContext: {} });\n\t}\n\n\treturn {\n\t\t...payload,\n\t\ttools: sanitizedTools,\n\t};\n}\n\nexport function isGoogleUrlContextEnabled(): boolean {\n\treturn parseEnableEnv(ENABLE_ENV);\n}\n\nexport const GOOGLE_URL_CONTEXT_SECTION = `\n## URL Context\n\nThe native url_context tool is available in this session. The model\nfetches and grounds responses in URL contents. Prefer url_context\nwhen the user references specific URLs they want analyzed.\n`;\n\nexport default function googleUrlContextExtension(pi: ExtensionAPI): void {\n\tpi.on(\"before_provider_request\", (event, ctx) => {\n\t\treturn addGoogleUrlContextToPayload(ctx.model?.api, event.payload);\n\t});\n\n\tpi.on(\"before_agent_start\", async (event, ctx) => {\n\t\tif (!isGoogleApi(ctx.model?.api)) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\tif (!isGoogleUrlContextEnabled()) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\treturn {\n\t\t\tsystemPrompt: `${event.systemPrompt}\\n${GOOGLE_URL_CONTEXT_SECTION}`,\n\t\t};\n\t});\n}\n"]}
|
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
import type { Api } from "@earendil-works/pi-ai";
|
|
2
|
-
import type { ExtensionAPI } from "../../types.js";
|
|
3
|
-
export declare function addOpenAIApiParallelToolCallsToPayload(api: Api | undefined, payload: unknown): unknown;
|
|
4
|
-
export declare const PARALLEL_TOOL_CALLS_SECTION = "\n## Execution Strategy\n\n### Parallel Tool Calls\n\nWhen multiple tool calls are independent, fire them ALL in the same turn. Sequential tool calls waste round-trips and slow down every task.\n\n- Multiple file reads in the same turn when you already know the paths\n- Multiple searches with different patterns fired simultaneously\n- Combining read operations with search operations when they gather independent context\n\nBefore calling any tool, ask: \"What other context will I need alongside this?\" Then gather it all in one turn.\n\n### Context Breadth Before Changes\n\nBefore modifying any file, gather enough context to get the change right on the first try:\n\n1. Read the target file and any files it directly depends on - understand the dependency chain\n2. Find every reference to symbols you will change - know the blast radius\n3. Check for related tests - know what might break\n4. Read inline comments or docs explaining design choices - understand the why\n\nMultiple well-informed edits in one pass beats a cycle of edit-then-fix-then-fix-again.\n";
|
|
5
|
-
export default function openaiApiParallelToolCallsExtension(pi: ExtensionAPI): void;
|
|
6
|
-
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/openai-api-parallel-tool-calls/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,uBAAuB,CAAC;AACjD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAmBnD,wBAAgB,sCAAsC,CAAC,GAAG,EAAE,GAAG,GAAG,SAAS,EAAE,OAAO,EAAE,OAAO,GAAG,OAAO,CAatG;AAED,eAAO,MAAM,2BAA2B,kjCAuBvC,CAAC;AAEF,MAAM,CAAC,OAAO,UAAU,mCAAmC,CAAC,EAAE,EAAE,YAAY,GAAG,IAAI,CAQlF","sourcesContent":["import type { Api } from \"@earendil-works/pi-ai\";\nimport type { ExtensionAPI } from \"../../types.js\";\n\ntype ProviderPayload = Record<string, unknown>;\n\nconst OPENAI_PARALLEL_TOOL_CALL_APIS: ReadonlySet<Api> = new Set([\n\t\"openai-completions\",\n\t\"openai-responses\",\n\t\"openai-codex-responses\",\n\t\"azure-openai-responses\",\n]);\n\nfunction isRecord(value: unknown): value is ProviderPayload {\n\treturn typeof value === \"object\" && value !== null;\n}\n\nfunction hasTools(payload: ProviderPayload): boolean {\n\treturn Array.isArray(payload.tools) && payload.tools.length > 0;\n}\n\nexport function addOpenAIApiParallelToolCallsToPayload(api: Api | undefined, payload: unknown): unknown {\n\tif (!api || !OPENAI_PARALLEL_TOOL_CALL_APIS.has(api)) {\n\t\treturn payload;\n\t}\n\n\tif (!isRecord(payload) || !hasTools(payload) || payload.parallel_tool_calls !== undefined) {\n\t\treturn payload;\n\t}\n\n\treturn {\n\t\t...payload,\n\t\tparallel_tool_calls: true,\n\t};\n}\n\nexport const PARALLEL_TOOL_CALLS_SECTION = `\n## Execution Strategy\n\n### Parallel Tool Calls\n\nWhen multiple tool calls are independent, fire them ALL in the same turn. Sequential tool calls waste round-trips and slow down every task.\n\n- Multiple file reads in the same turn when you already know the paths\n- Multiple searches with different patterns fired simultaneously\n- Combining read operations with search operations when they gather independent context\n\nBefore calling any tool, ask: \"What other context will I need alongside this?\" Then gather it all in one turn.\n\n### Context Breadth Before Changes\n\nBefore modifying any file, gather enough context to get the change right on the first try:\n\n1. Read the target file and any files it directly depends on - understand the dependency chain\n2. Find every reference to symbols you will change - know the blast radius\n3. Check for related tests - know what might break\n4. Read inline comments or docs explaining design choices - understand the why\n\nMultiple well-informed edits in one pass beats a cycle of edit-then-fix-then-fix-again.\n`;\n\nexport default function openaiApiParallelToolCallsExtension(pi: ExtensionAPI): void {\n\tpi.on(\"before_provider_request\", (event, ctx) => {\n\t\treturn addOpenAIApiParallelToolCallsToPayload(ctx.model?.api, event.payload);\n\t});\n\n\tpi.on(\"before_agent_start\", async (event) => ({\n\t\tsystemPrompt: `${event.systemPrompt}\\n${PARALLEL_TOOL_CALLS_SECTION}`,\n\t}));\n}\n"]}
|
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
const OPENAI_PARALLEL_TOOL_CALL_APIS = new Set([
|
|
2
|
-
"openai-completions",
|
|
3
|
-
"openai-responses",
|
|
4
|
-
"openai-codex-responses",
|
|
5
|
-
"azure-openai-responses",
|
|
6
|
-
]);
|
|
7
|
-
function isRecord(value) {
|
|
8
|
-
return typeof value === "object" && value !== null;
|
|
9
|
-
}
|
|
10
|
-
function hasTools(payload) {
|
|
11
|
-
return Array.isArray(payload.tools) && payload.tools.length > 0;
|
|
12
|
-
}
|
|
13
|
-
export function addOpenAIApiParallelToolCallsToPayload(api, payload) {
|
|
14
|
-
if (!api || !OPENAI_PARALLEL_TOOL_CALL_APIS.has(api)) {
|
|
15
|
-
return payload;
|
|
16
|
-
}
|
|
17
|
-
if (!isRecord(payload) || !hasTools(payload) || payload.parallel_tool_calls !== undefined) {
|
|
18
|
-
return payload;
|
|
19
|
-
}
|
|
20
|
-
return {
|
|
21
|
-
...payload,
|
|
22
|
-
parallel_tool_calls: true,
|
|
23
|
-
};
|
|
24
|
-
}
|
|
25
|
-
export const PARALLEL_TOOL_CALLS_SECTION = `
|
|
26
|
-
## Execution Strategy
|
|
27
|
-
|
|
28
|
-
### Parallel Tool Calls
|
|
29
|
-
|
|
30
|
-
When multiple tool calls are independent, fire them ALL in the same turn. Sequential tool calls waste round-trips and slow down every task.
|
|
31
|
-
|
|
32
|
-
- Multiple file reads in the same turn when you already know the paths
|
|
33
|
-
- Multiple searches with different patterns fired simultaneously
|
|
34
|
-
- Combining read operations with search operations when they gather independent context
|
|
35
|
-
|
|
36
|
-
Before calling any tool, ask: "What other context will I need alongside this?" Then gather it all in one turn.
|
|
37
|
-
|
|
38
|
-
### Context Breadth Before Changes
|
|
39
|
-
|
|
40
|
-
Before modifying any file, gather enough context to get the change right on the first try:
|
|
41
|
-
|
|
42
|
-
1. Read the target file and any files it directly depends on - understand the dependency chain
|
|
43
|
-
2. Find every reference to symbols you will change - know the blast radius
|
|
44
|
-
3. Check for related tests - know what might break
|
|
45
|
-
4. Read inline comments or docs explaining design choices - understand the why
|
|
46
|
-
|
|
47
|
-
Multiple well-informed edits in one pass beats a cycle of edit-then-fix-then-fix-again.
|
|
48
|
-
`;
|
|
49
|
-
export default function openaiApiParallelToolCallsExtension(pi) {
|
|
50
|
-
pi.on("before_provider_request", (event, ctx) => {
|
|
51
|
-
return addOpenAIApiParallelToolCallsToPayload(ctx.model?.api, event.payload);
|
|
52
|
-
});
|
|
53
|
-
pi.on("before_agent_start", async (event) => ({
|
|
54
|
-
systemPrompt: `${event.systemPrompt}\n${PARALLEL_TOOL_CALLS_SECTION}`,
|
|
55
|
-
}));
|
|
56
|
-
}
|
|
57
|
-
//# sourceMappingURL=index.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/openai-api-parallel-tool-calls/index.ts"],"names":[],"mappings":"AAKA,MAAM,8BAA8B,GAAqB,IAAI,GAAG,CAAC;IAChE,oBAAoB;IACpB,kBAAkB;IAClB,wBAAwB;IACxB,wBAAwB;CACxB,CAAC,CAAC;AAEH,SAAS,QAAQ,CAAC,KAAc,EAA4B;IAC3D,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,CAAC;AAAA,CACnD;AAED,SAAS,QAAQ,CAAC,OAAwB,EAAW;IACpD,OAAO,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,OAAO,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC;AAAA,CAChE;AAED,MAAM,UAAU,sCAAsC,CAAC,GAAoB,EAAE,OAAgB,EAAW;IACvG,IAAI,CAAC,GAAG,IAAI,CAAC,8BAA8B,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;QACtD,OAAO,OAAO,CAAC;IAChB,CAAC;IAED,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,OAAO,CAAC,mBAAmB,KAAK,SAAS,EAAE,CAAC;QAC3F,OAAO,OAAO,CAAC;IAChB,CAAC;IAED,OAAO;QACN,GAAG,OAAO;QACV,mBAAmB,EAAE,IAAI;KACzB,CAAC;AAAA,CACF;AAED,MAAM,CAAC,MAAM,2BAA2B,GAAG;;;;;;;;;;;;;;;;;;;;;;;CAuB1C,CAAC;AAEF,MAAM,CAAC,OAAO,UAAU,mCAAmC,CAAC,EAAgB,EAAQ;IACnF,EAAE,CAAC,EAAE,CAAC,yBAAyB,EAAE,CAAC,KAAK,EAAE,GAAG,EAAE,EAAE,CAAC;QAChD,OAAO,sCAAsC,CAAC,GAAG,CAAC,KAAK,EAAE,GAAG,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC;IAAA,CAC7E,CAAC,CAAC;IAEH,EAAE,CAAC,EAAE,CAAC,oBAAoB,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE,CAAC,CAAC;QAC7C,YAAY,EAAE,GAAG,KAAK,CAAC,YAAY,KAAK,2BAA2B,EAAE;KACrE,CAAC,CAAC,CAAC;AAAA,CACJ","sourcesContent":["import type { Api } from \"@earendil-works/pi-ai\";\nimport type { ExtensionAPI } from \"../../types.js\";\n\ntype ProviderPayload = Record<string, unknown>;\n\nconst OPENAI_PARALLEL_TOOL_CALL_APIS: ReadonlySet<Api> = new Set([\n\t\"openai-completions\",\n\t\"openai-responses\",\n\t\"openai-codex-responses\",\n\t\"azure-openai-responses\",\n]);\n\nfunction isRecord(value: unknown): value is ProviderPayload {\n\treturn typeof value === \"object\" && value !== null;\n}\n\nfunction hasTools(payload: ProviderPayload): boolean {\n\treturn Array.isArray(payload.tools) && payload.tools.length > 0;\n}\n\nexport function addOpenAIApiParallelToolCallsToPayload(api: Api | undefined, payload: unknown): unknown {\n\tif (!api || !OPENAI_PARALLEL_TOOL_CALL_APIS.has(api)) {\n\t\treturn payload;\n\t}\n\n\tif (!isRecord(payload) || !hasTools(payload) || payload.parallel_tool_calls !== undefined) {\n\t\treturn payload;\n\t}\n\n\treturn {\n\t\t...payload,\n\t\tparallel_tool_calls: true,\n\t};\n}\n\nexport const PARALLEL_TOOL_CALLS_SECTION = `\n## Execution Strategy\n\n### Parallel Tool Calls\n\nWhen multiple tool calls are independent, fire them ALL in the same turn. Sequential tool calls waste round-trips and slow down every task.\n\n- Multiple file reads in the same turn when you already know the paths\n- Multiple searches with different patterns fired simultaneously\n- Combining read operations with search operations when they gather independent context\n\nBefore calling any tool, ask: \"What other context will I need alongside this?\" Then gather it all in one turn.\n\n### Context Breadth Before Changes\n\nBefore modifying any file, gather enough context to get the change right on the first try:\n\n1. Read the target file and any files it directly depends on - understand the dependency chain\n2. Find every reference to symbols you will change - know the blast radius\n3. Check for related tests - know what might break\n4. Read inline comments or docs explaining design choices - understand the why\n\nMultiple well-informed edits in one pass beats a cycle of edit-then-fix-then-fix-again.\n`;\n\nexport default function openaiApiParallelToolCallsExtension(pi: ExtensionAPI): void {\n\tpi.on(\"before_provider_request\", (event, ctx) => {\n\t\treturn addOpenAIApiParallelToolCallsToPayload(ctx.model?.api, event.payload);\n\t});\n\n\tpi.on(\"before_agent_start\", async (event) => ({\n\t\tsystemPrompt: `${event.systemPrompt}\\n${PARALLEL_TOOL_CALLS_SECTION}`,\n\t}));\n}\n"]}
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import type { Api } from "@earendil-works/pi-ai";
|
|
2
|
-
import type { ExtensionAPI } from "../../types.js";
|
|
3
|
-
export declare function isCodeInterpreterEnabled(): boolean;
|
|
4
|
-
export declare function getCodeInterpreterContainer(): string | {
|
|
5
|
-
type: "auto";
|
|
6
|
-
};
|
|
7
|
-
export declare function addOpenaiCodeInterpreterToPayload(api: Api | undefined, payload: unknown): unknown;
|
|
8
|
-
export declare const OPENAI_CODE_INTERPRETER_SECTION = "\n## Code Interpreter\n\nThe native code_interpreter tool is available in this session. The model\nruns Python in an OpenAI-managed sandbox container. Use code_interpreter\nfor numerical work, file analysis, and one-off computations when explicit\nresults are needed.\n";
|
|
9
|
-
export default function openaiCodeInterpreterExtension(pi: ExtensionAPI): void;
|
|
10
|
-
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/openai-code-interpreter/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,uBAAuB,CAAC;AACjD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAsCnD,wBAAgB,wBAAwB,IAAI,OAAO,CAQlD;AAED,wBAAgB,2BAA2B,IAAI,MAAM,GAAG;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,CAYvE;AAED,wBAAgB,iCAAiC,CAAC,GAAG,EAAE,GAAG,GAAG,SAAS,EAAE,OAAO,EAAE,OAAO,GAAG,OAAO,CA2BjG;AAED,eAAO,MAAM,+BAA+B,kRAO3C,CAAC;AAEF,MAAM,CAAC,OAAO,UAAU,8BAA8B,CAAC,EAAE,EAAE,YAAY,GAAG,IAAI,CAkB7E","sourcesContent":["import type { Api } from \"@earendil-works/pi-ai\";\nimport type { ExtensionAPI } from \"../../types.js\";\n\ntype ToolDefinition = Record<string, unknown>;\n\nconst OPENAI_RESPONSES_APIS: ReadonlySet<Api> = new Set([\"openai-responses\", \"azure-openai-responses\"]);\nconst CODE_INTERPRETER_ENV = \"PI_OPENAI_CODE_INTERPRETER\";\nconst CODE_INTERPRETER_CONTAINER_ENV = \"PI_OPENAI_CODE_INTERPRETER_CONTAINER\";\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n\treturn typeof value === \"object\" && value !== null;\n}\n\nfunction isOpenAiResponsesApi(api: Api | undefined): api is \"openai-responses\" | \"azure-openai-responses\" {\n\treturn api !== undefined && OPENAI_RESPONSES_APIS.has(api);\n}\n\nfunction isCodeInterpreterTool(tool: ToolDefinition): boolean {\n\treturn tool.type === \"code_interpreter\";\n}\n\nfunction isCodeInterpreterFunctionVariant(tool: ToolDefinition): boolean {\n\treturn tool.type === \"function\" && tool.name === \"code_interpreter\";\n}\n\nfunction sanitizeTools(tools: unknown[]): ToolDefinition[] {\n\tconst sanitizedTools: ToolDefinition[] = [];\n\tfor (const tool of tools) {\n\t\tif (!isRecord(tool)) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (!isCodeInterpreterFunctionVariant(tool)) {\n\t\t\tsanitizedTools.push(tool);\n\t\t}\n\t}\n\treturn sanitizedTools;\n}\n\nexport function isCodeInterpreterEnabled(): boolean {\n\tconst value = process.env[CODE_INTERPRETER_ENV];\n\tif (!value) {\n\t\treturn false;\n\t}\n\n\tconst normalized = value.trim().toLowerCase();\n\treturn normalized === \"1\" || normalized === \"true\" || normalized === \"yes\" || normalized === \"on\";\n}\n\nexport function getCodeInterpreterContainer(): string | { type: \"auto\" } {\n\tconst value = process.env[CODE_INTERPRETER_CONTAINER_ENV];\n\tif (!value) {\n\t\treturn { type: \"auto\" };\n\t}\n\n\tconst trimmed = value.trim();\n\tif (trimmed.length === 0) {\n\t\treturn { type: \"auto\" };\n\t}\n\n\treturn trimmed;\n}\n\nexport function addOpenaiCodeInterpreterToPayload(api: Api | undefined, payload: unknown): unknown {\n\tif (!isOpenAiResponsesApi(api)) {\n\t\treturn payload;\n\t}\n\n\tif (!isCodeInterpreterEnabled()) {\n\t\treturn payload;\n\t}\n\n\tif (!isRecord(payload)) {\n\t\treturn payload;\n\t}\n\n\tconst tools = Array.isArray(payload.tools) ? payload.tools : [];\n\tconst sanitizedTools = sanitizeTools(tools);\n\tconst hasNativeCodeInterpreter = sanitizedTools.some((tool) => isCodeInterpreterTool(tool));\n\tif (!hasNativeCodeInterpreter) {\n\t\tsanitizedTools.push({\n\t\t\ttype: \"code_interpreter\",\n\t\t\tcontainer: getCodeInterpreterContainer(),\n\t\t});\n\t}\n\n\treturn {\n\t\t...payload,\n\t\ttools: sanitizedTools,\n\t};\n}\n\nexport const OPENAI_CODE_INTERPRETER_SECTION = `\n## Code Interpreter\n\nThe native code_interpreter tool is available in this session. The model\nruns Python in an OpenAI-managed sandbox container. Use code_interpreter\nfor numerical work, file analysis, and one-off computations when explicit\nresults are needed.\n`;\n\nexport default function openaiCodeInterpreterExtension(pi: ExtensionAPI): void {\n\tpi.on(\"before_provider_request\", (event, ctx) => {\n\t\treturn addOpenaiCodeInterpreterToPayload(ctx.model?.api, event.payload);\n\t});\n\n\tpi.on(\"before_agent_start\", async (event, ctx) => {\n\t\tif (!isOpenAiResponsesApi(ctx.model?.api)) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\tif (!isCodeInterpreterEnabled()) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\treturn {\n\t\t\tsystemPrompt: `${event.systemPrompt}\\n${OPENAI_CODE_INTERPRETER_SECTION}`,\n\t\t};\n\t});\n}\n"]}
|
|
@@ -1,95 +0,0 @@
|
|
|
1
|
-
const OPENAI_RESPONSES_APIS = new Set(["openai-responses", "azure-openai-responses"]);
|
|
2
|
-
const CODE_INTERPRETER_ENV = "PI_OPENAI_CODE_INTERPRETER";
|
|
3
|
-
const CODE_INTERPRETER_CONTAINER_ENV = "PI_OPENAI_CODE_INTERPRETER_CONTAINER";
|
|
4
|
-
function isRecord(value) {
|
|
5
|
-
return typeof value === "object" && value !== null;
|
|
6
|
-
}
|
|
7
|
-
function isOpenAiResponsesApi(api) {
|
|
8
|
-
return api !== undefined && OPENAI_RESPONSES_APIS.has(api);
|
|
9
|
-
}
|
|
10
|
-
function isCodeInterpreterTool(tool) {
|
|
11
|
-
return tool.type === "code_interpreter";
|
|
12
|
-
}
|
|
13
|
-
function isCodeInterpreterFunctionVariant(tool) {
|
|
14
|
-
return tool.type === "function" && tool.name === "code_interpreter";
|
|
15
|
-
}
|
|
16
|
-
function sanitizeTools(tools) {
|
|
17
|
-
const sanitizedTools = [];
|
|
18
|
-
for (const tool of tools) {
|
|
19
|
-
if (!isRecord(tool)) {
|
|
20
|
-
continue;
|
|
21
|
-
}
|
|
22
|
-
if (!isCodeInterpreterFunctionVariant(tool)) {
|
|
23
|
-
sanitizedTools.push(tool);
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
return sanitizedTools;
|
|
27
|
-
}
|
|
28
|
-
export function isCodeInterpreterEnabled() {
|
|
29
|
-
const value = process.env[CODE_INTERPRETER_ENV];
|
|
30
|
-
if (!value) {
|
|
31
|
-
return false;
|
|
32
|
-
}
|
|
33
|
-
const normalized = value.trim().toLowerCase();
|
|
34
|
-
return normalized === "1" || normalized === "true" || normalized === "yes" || normalized === "on";
|
|
35
|
-
}
|
|
36
|
-
export function getCodeInterpreterContainer() {
|
|
37
|
-
const value = process.env[CODE_INTERPRETER_CONTAINER_ENV];
|
|
38
|
-
if (!value) {
|
|
39
|
-
return { type: "auto" };
|
|
40
|
-
}
|
|
41
|
-
const trimmed = value.trim();
|
|
42
|
-
if (trimmed.length === 0) {
|
|
43
|
-
return { type: "auto" };
|
|
44
|
-
}
|
|
45
|
-
return trimmed;
|
|
46
|
-
}
|
|
47
|
-
export function addOpenaiCodeInterpreterToPayload(api, payload) {
|
|
48
|
-
if (!isOpenAiResponsesApi(api)) {
|
|
49
|
-
return payload;
|
|
50
|
-
}
|
|
51
|
-
if (!isCodeInterpreterEnabled()) {
|
|
52
|
-
return payload;
|
|
53
|
-
}
|
|
54
|
-
if (!isRecord(payload)) {
|
|
55
|
-
return payload;
|
|
56
|
-
}
|
|
57
|
-
const tools = Array.isArray(payload.tools) ? payload.tools : [];
|
|
58
|
-
const sanitizedTools = sanitizeTools(tools);
|
|
59
|
-
const hasNativeCodeInterpreter = sanitizedTools.some((tool) => isCodeInterpreterTool(tool));
|
|
60
|
-
if (!hasNativeCodeInterpreter) {
|
|
61
|
-
sanitizedTools.push({
|
|
62
|
-
type: "code_interpreter",
|
|
63
|
-
container: getCodeInterpreterContainer(),
|
|
64
|
-
});
|
|
65
|
-
}
|
|
66
|
-
return {
|
|
67
|
-
...payload,
|
|
68
|
-
tools: sanitizedTools,
|
|
69
|
-
};
|
|
70
|
-
}
|
|
71
|
-
export const OPENAI_CODE_INTERPRETER_SECTION = `
|
|
72
|
-
## Code Interpreter
|
|
73
|
-
|
|
74
|
-
The native code_interpreter tool is available in this session. The model
|
|
75
|
-
runs Python in an OpenAI-managed sandbox container. Use code_interpreter
|
|
76
|
-
for numerical work, file analysis, and one-off computations when explicit
|
|
77
|
-
results are needed.
|
|
78
|
-
`;
|
|
79
|
-
export default function openaiCodeInterpreterExtension(pi) {
|
|
80
|
-
pi.on("before_provider_request", (event, ctx) => {
|
|
81
|
-
return addOpenaiCodeInterpreterToPayload(ctx.model?.api, event.payload);
|
|
82
|
-
});
|
|
83
|
-
pi.on("before_agent_start", async (event, ctx) => {
|
|
84
|
-
if (!isOpenAiResponsesApi(ctx.model?.api)) {
|
|
85
|
-
return undefined;
|
|
86
|
-
}
|
|
87
|
-
if (!isCodeInterpreterEnabled()) {
|
|
88
|
-
return undefined;
|
|
89
|
-
}
|
|
90
|
-
return {
|
|
91
|
-
systemPrompt: `${event.systemPrompt}\n${OPENAI_CODE_INTERPRETER_SECTION}`,
|
|
92
|
-
};
|
|
93
|
-
});
|
|
94
|
-
}
|
|
95
|
-
//# sourceMappingURL=index.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/openai-code-interpreter/index.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Api } from \"@earendil-works/pi-ai\";\nimport type { ExtensionAPI } from \"../../types.js\";\n\ntype ToolDefinition = Record<string, unknown>;\n\nconst OPENAI_RESPONSES_APIS: ReadonlySet<Api> = new Set([\"openai-responses\", \"azure-openai-responses\"]);\nconst CODE_INTERPRETER_ENV = \"PI_OPENAI_CODE_INTERPRETER\";\nconst CODE_INTERPRETER_CONTAINER_ENV = \"PI_OPENAI_CODE_INTERPRETER_CONTAINER\";\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n\treturn typeof value === \"object\" && value !== null;\n}\n\nfunction isOpenAiResponsesApi(api: Api | undefined): api is \"openai-responses\" | \"azure-openai-responses\" {\n\treturn api !== undefined && OPENAI_RESPONSES_APIS.has(api);\n}\n\nfunction isCodeInterpreterTool(tool: ToolDefinition): boolean {\n\treturn tool.type === \"code_interpreter\";\n}\n\nfunction isCodeInterpreterFunctionVariant(tool: ToolDefinition): boolean {\n\treturn tool.type === \"function\" && tool.name === \"code_interpreter\";\n}\n\nfunction sanitizeTools(tools: unknown[]): ToolDefinition[] {\n\tconst sanitizedTools: ToolDefinition[] = [];\n\tfor (const tool of tools) {\n\t\tif (!isRecord(tool)) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (!isCodeInterpreterFunctionVariant(tool)) {\n\t\t\tsanitizedTools.push(tool);\n\t\t}\n\t}\n\treturn sanitizedTools;\n}\n\nexport function isCodeInterpreterEnabled(): boolean {\n\tconst value = process.env[CODE_INTERPRETER_ENV];\n\tif (!value) {\n\t\treturn false;\n\t}\n\n\tconst normalized = value.trim().toLowerCase();\n\treturn normalized === \"1\" || normalized === \"true\" || normalized === \"yes\" || normalized === \"on\";\n}\n\nexport function getCodeInterpreterContainer(): string | { type: \"auto\" } {\n\tconst value = process.env[CODE_INTERPRETER_CONTAINER_ENV];\n\tif (!value) {\n\t\treturn { type: \"auto\" };\n\t}\n\n\tconst trimmed = value.trim();\n\tif (trimmed.length === 0) {\n\t\treturn { type: \"auto\" };\n\t}\n\n\treturn trimmed;\n}\n\nexport function addOpenaiCodeInterpreterToPayload(api: Api | undefined, payload: unknown): unknown {\n\tif (!isOpenAiResponsesApi(api)) {\n\t\treturn payload;\n\t}\n\n\tif (!isCodeInterpreterEnabled()) {\n\t\treturn payload;\n\t}\n\n\tif (!isRecord(payload)) {\n\t\treturn payload;\n\t}\n\n\tconst tools = Array.isArray(payload.tools) ? payload.tools : [];\n\tconst sanitizedTools = sanitizeTools(tools);\n\tconst hasNativeCodeInterpreter = sanitizedTools.some((tool) => isCodeInterpreterTool(tool));\n\tif (!hasNativeCodeInterpreter) {\n\t\tsanitizedTools.push({\n\t\t\ttype: \"code_interpreter\",\n\t\t\tcontainer: getCodeInterpreterContainer(),\n\t\t});\n\t}\n\n\treturn {\n\t\t...payload,\n\t\ttools: sanitizedTools,\n\t};\n}\n\nexport const OPENAI_CODE_INTERPRETER_SECTION = `\n## Code Interpreter\n\nThe native code_interpreter tool is available in this session. The model\nruns Python in an OpenAI-managed sandbox container. Use code_interpreter\nfor numerical work, file analysis, and one-off computations when explicit\nresults are needed.\n`;\n\nexport default function openaiCodeInterpreterExtension(pi: ExtensionAPI): void {\n\tpi.on(\"before_provider_request\", (event, ctx) => {\n\t\treturn addOpenaiCodeInterpreterToPayload(ctx.model?.api, event.payload);\n\t});\n\n\tpi.on(\"before_agent_start\", async (event, ctx) => {\n\t\tif (!isOpenAiResponsesApi(ctx.model?.api)) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\tif (!isCodeInterpreterEnabled()) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\treturn {\n\t\t\tsystemPrompt: `${event.systemPrompt}\\n${OPENAI_CODE_INTERPRETER_SECTION}`,\n\t\t};\n\t});\n}\n"]}
|