@pencil-agent/nano-pencil 2.0.0-beta.2 → 2.0.0-beta.3
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/dist/build-meta.json +3 -3
- package/dist/node_modules/@pencil-agent/agent-core/dist/agent-loop-continuations.d.ts +17 -0
- package/dist/node_modules/@pencil-agent/agent-core/dist/agent-loop-continuations.js +60 -0
- package/dist/node_modules/@pencil-agent/agent-core/dist/agent-loop-stream-events.d.ts +19 -0
- package/dist/node_modules/@pencil-agent/agent-core/dist/agent-loop-stream-events.js +55 -0
- package/dist/node_modules/@pencil-agent/agent-core/dist/agent-loop-tool-results.d.ts +10 -0
- package/dist/node_modules/@pencil-agent/agent-core/dist/agent-loop-tool-results.js +137 -0
- package/dist/node_modules/@pencil-agent/agent-core/dist/agent-loop-tool-summaries.d.ts +22 -0
- package/dist/node_modules/@pencil-agent/agent-core/dist/agent-loop-tool-summaries.js +64 -0
- package/dist/node_modules/@pencil-agent/agent-core/dist/agent-loop.d.ts +26 -0
- package/dist/node_modules/@pencil-agent/agent-core/dist/agent-loop.js +913 -0
- package/dist/node_modules/@pencil-agent/agent-core/dist/agent-run-result.d.ts +9 -0
- package/dist/node_modules/@pencil-agent/agent-core/dist/agent-run-result.js +32 -0
- package/dist/node_modules/@pencil-agent/agent-core/dist/agent.d.ts +215 -0
- package/dist/node_modules/@pencil-agent/agent-core/dist/agent.js +522 -0
- package/dist/node_modules/@pencil-agent/agent-core/dist/errors.d.ts +62 -0
- package/dist/node_modules/@pencil-agent/agent-core/dist/errors.js +146 -0
- package/dist/node_modules/@pencil-agent/agent-core/dist/index.d.ts +14 -0
- package/dist/node_modules/@pencil-agent/agent-core/dist/index.js +19 -0
- package/dist/node_modules/@pencil-agent/agent-core/dist/proxy.d.ts +91 -0
- package/dist/node_modules/@pencil-agent/agent-core/dist/proxy.js +279 -0
- package/dist/node_modules/@pencil-agent/agent-core/dist/structured-adaptive-agent-loop.d.ts +15 -0
- package/dist/node_modules/@pencil-agent/agent-core/dist/structured-adaptive-agent-loop.js +625 -0
- package/dist/node_modules/@pencil-agent/agent-core/dist/structured-adaptive-streaming-tool-executor.d.ts +33 -0
- package/dist/node_modules/@pencil-agent/agent-core/dist/structured-adaptive-streaming-tool-executor.js +189 -0
- package/dist/node_modules/@pencil-agent/agent-core/dist/structured-adaptive-tool-orchestration.d.ts +35 -0
- package/dist/node_modules/@pencil-agent/agent-core/dist/structured-adaptive-tool-orchestration.js +319 -0
- package/dist/node_modules/@pencil-agent/agent-core/dist/types.d.ts +417 -0
- package/dist/node_modules/@pencil-agent/agent-core/dist/types.js +13 -0
- package/dist/node_modules/@pencil-agent/agent-core/package.json +28 -0
- package/dist/node_modules/@pencil-agent/ai/dist/api-registry.d.ts +27 -0
- package/dist/node_modules/@pencil-agent/ai/dist/api-registry.js +152 -0
- package/dist/node_modules/@pencil-agent/ai/dist/cli.d.ts +2 -0
- package/dist/node_modules/@pencil-agent/ai/dist/cli.js +121 -0
- package/dist/node_modules/@pencil-agent/ai/dist/config-path.d.ts +1 -0
- package/dist/node_modules/@pencil-agent/ai/dist/config-path.js +17 -0
- package/dist/node_modules/@pencil-agent/ai/dist/debug-logger.d.ts +94 -0
- package/dist/node_modules/@pencil-agent/ai/dist/debug-logger.js +218 -0
- package/dist/node_modules/@pencil-agent/ai/dist/env-api-keys.d.ts +8 -0
- package/dist/node_modules/@pencil-agent/ai/dist/env-api-keys.js +107 -0
- package/dist/node_modules/@pencil-agent/ai/dist/env.d.ts +7 -0
- package/dist/node_modules/@pencil-agent/ai/dist/env.js +7 -0
- package/dist/node_modules/@pencil-agent/ai/dist/events.d.ts +8 -0
- package/dist/node_modules/@pencil-agent/ai/dist/events.js +7 -0
- package/dist/node_modules/@pencil-agent/ai/dist/index.d.ts +27 -0
- package/dist/node_modules/@pencil-agent/ai/dist/index.js +20 -0
- package/dist/node_modules/@pencil-agent/ai/dist/json.d.ts +7 -0
- package/dist/node_modules/@pencil-agent/ai/dist/json.js +7 -0
- package/dist/node_modules/@pencil-agent/ai/dist/models.d.ts +31 -0
- package/dist/node_modules/@pencil-agent/ai/dist/models.generated.d.ts +15159 -0
- package/dist/node_modules/@pencil-agent/ai/dist/models.generated.js +14928 -0
- package/dist/node_modules/@pencil-agent/ai/dist/models.js +60 -0
- package/dist/node_modules/@pencil-agent/ai/dist/overflow.d.ts +7 -0
- package/dist/node_modules/@pencil-agent/ai/dist/overflow.js +7 -0
- package/dist/node_modules/@pencil-agent/ai/dist/providers/amazon-bedrock.d.ts +20 -0
- package/dist/node_modules/@pencil-agent/ai/dist/providers/amazon-bedrock.js +606 -0
- package/dist/node_modules/@pencil-agent/ai/dist/providers/anthropic.d.ts +38 -0
- package/dist/node_modules/@pencil-agent/ai/dist/providers/anthropic.js +737 -0
- package/dist/node_modules/@pencil-agent/ai/dist/providers/azure-openai-responses.d.ts +21 -0
- package/dist/node_modules/@pencil-agent/ai/dist/providers/azure-openai-responses.js +193 -0
- package/dist/node_modules/@pencil-agent/ai/dist/providers/github-copilot-headers.d.ts +13 -0
- package/dist/node_modules/@pencil-agent/ai/dist/providers/github-copilot-headers.js +34 -0
- package/dist/node_modules/@pencil-agent/ai/dist/providers/google-gemini-cli.d.ts +79 -0
- package/dist/node_modules/@pencil-agent/ai/dist/providers/google-gemini-cli.js +753 -0
- package/dist/node_modules/@pencil-agent/ai/dist/providers/google-shared.d.ts +70 -0
- package/dist/node_modules/@pencil-agent/ai/dist/providers/google-shared.js +311 -0
- package/dist/node_modules/@pencil-agent/ai/dist/providers/google-vertex.d.ts +20 -0
- package/dist/node_modules/@pencil-agent/ai/dist/providers/google-vertex.js +380 -0
- package/dist/node_modules/@pencil-agent/ai/dist/providers/google.d.ts +18 -0
- package/dist/node_modules/@pencil-agent/ai/dist/providers/google.js +360 -0
- package/dist/node_modules/@pencil-agent/ai/dist/providers/openai-codex-responses.d.ts +8 -0
- package/dist/node_modules/@pencil-agent/ai/dist/providers/openai-codex-responses.js +704 -0
- package/dist/node_modules/@pencil-agent/ai/dist/providers/openai-completions.d.ts +20 -0
- package/dist/node_modules/@pencil-agent/ai/dist/providers/openai-completions.js +870 -0
- package/dist/node_modules/@pencil-agent/ai/dist/providers/openai-responses-shared.d.ts +22 -0
- package/dist/node_modules/@pencil-agent/ai/dist/providers/openai-responses-shared.js +432 -0
- package/dist/node_modules/@pencil-agent/ai/dist/providers/openai-responses.d.ts +19 -0
- package/dist/node_modules/@pencil-agent/ai/dist/providers/openai-responses.js +207 -0
- package/dist/node_modules/@pencil-agent/ai/dist/providers/register-builtins.d.ts +8 -0
- package/dist/node_modules/@pencil-agent/ai/dist/providers/register-builtins.js +86 -0
- package/dist/node_modules/@pencil-agent/ai/dist/providers/simple-options.d.ts +13 -0
- package/dist/node_modules/@pencil-agent/ai/dist/providers/simple-options.js +40 -0
- package/dist/node_modules/@pencil-agent/ai/dist/providers/transform-messages.d.ts +13 -0
- package/dist/node_modules/@pencil-agent/ai/dist/providers/transform-messages.js +175 -0
- package/dist/node_modules/@pencil-agent/ai/dist/registry.d.ts +8 -0
- package/dist/node_modules/@pencil-agent/ai/dist/registry.js +8 -0
- package/dist/node_modules/@pencil-agent/ai/dist/schema.d.ts +10 -0
- package/dist/node_modules/@pencil-agent/ai/dist/schema.js +9 -0
- package/dist/node_modules/@pencil-agent/ai/dist/stream.d.ts +25 -0
- package/dist/node_modules/@pencil-agent/ai/dist/stream.js +324 -0
- package/dist/node_modules/@pencil-agent/ai/dist/types.d.ts +306 -0
- package/dist/node_modules/@pencil-agent/ai/dist/types.js +7 -0
- package/dist/node_modules/@pencil-agent/ai/dist/utils/event-stream-types.d.ts +12 -0
- package/dist/node_modules/@pencil-agent/ai/dist/utils/event-stream-types.js +7 -0
- package/dist/node_modules/@pencil-agent/ai/dist/utils/event-stream.d.ts +31 -0
- package/dist/node_modules/@pencil-agent/ai/dist/utils/event-stream.js +98 -0
- package/dist/node_modules/@pencil-agent/ai/dist/utils/http-proxy.d.ts +13 -0
- package/dist/node_modules/@pencil-agent/ai/dist/utils/http-proxy.js +20 -0
- package/dist/node_modules/@pencil-agent/ai/dist/utils/json-parse.d.ts +14 -0
- package/dist/node_modules/@pencil-agent/ai/dist/utils/json-parse.js +34 -0
- package/dist/node_modules/@pencil-agent/ai/dist/utils/oauth/anthropic.d.ts +22 -0
- package/dist/node_modules/@pencil-agent/ai/dist/utils/oauth/anthropic.js +109 -0
- package/dist/node_modules/@pencil-agent/ai/dist/utils/oauth/decode-credential.d.ts +12 -0
- package/dist/node_modules/@pencil-agent/ai/dist/utils/oauth/decode-credential.js +25 -0
- package/dist/node_modules/@pencil-agent/ai/dist/utils/oauth/github-copilot.d.ts +35 -0
- package/dist/node_modules/@pencil-agent/ai/dist/utils/oauth/github-copilot.js +286 -0
- package/dist/node_modules/@pencil-agent/ai/dist/utils/oauth/google-antigravity.d.ts +31 -0
- package/dist/node_modules/@pencil-agent/ai/dist/utils/oauth/google-antigravity.js +378 -0
- package/dist/node_modules/@pencil-agent/ai/dist/utils/oauth/google-gemini-cli.d.ts +31 -0
- package/dist/node_modules/@pencil-agent/ai/dist/utils/oauth/google-gemini-cli.js +483 -0
- package/dist/node_modules/@pencil-agent/ai/dist/utils/oauth/index.d.ts +60 -0
- package/dist/node_modules/@pencil-agent/ai/dist/utils/oauth/index.js +131 -0
- package/dist/node_modules/@pencil-agent/ai/dist/utils/oauth/openai-codex.d.ts +39 -0
- package/dist/node_modules/@pencil-agent/ai/dist/utils/oauth/openai-codex.js +385 -0
- package/dist/node_modules/@pencil-agent/ai/dist/utils/oauth/pkce.d.ts +18 -0
- package/dist/node_modules/@pencil-agent/ai/dist/utils/oauth/pkce.js +36 -0
- package/dist/node_modules/@pencil-agent/ai/dist/utils/oauth/types.d.ts +52 -0
- package/dist/node_modules/@pencil-agent/ai/dist/utils/oauth/types.js +7 -0
- package/dist/node_modules/@pencil-agent/ai/dist/utils/overflow.d.ts +57 -0
- package/dist/node_modules/@pencil-agent/ai/dist/utils/overflow.js +120 -0
- package/dist/node_modules/@pencil-agent/ai/dist/utils/sanitize-unicode.d.ts +16 -0
- package/dist/node_modules/@pencil-agent/ai/dist/utils/sanitize-unicode.js +20 -0
- package/dist/node_modules/@pencil-agent/ai/dist/utils/typebox-helpers.d.ts +22 -0
- package/dist/node_modules/@pencil-agent/ai/dist/utils/typebox-helpers.js +26 -0
- package/dist/node_modules/@pencil-agent/ai/dist/utils/validation.d.ts +23 -0
- package/dist/node_modules/@pencil-agent/ai/dist/utils/validation.js +78 -0
- package/dist/node_modules/@pencil-agent/ai/package.json +94 -0
- package/dist/node_modules/@pencil-agent/tui/dist/autocomplete.d.ts +62 -0
- package/dist/node_modules/@pencil-agent/tui/dist/autocomplete.js +624 -0
- package/dist/node_modules/@pencil-agent/tui/dist/components/box.d.ts +27 -0
- package/dist/node_modules/@pencil-agent/tui/dist/components/box.js +109 -0
- package/dist/node_modules/@pencil-agent/tui/dist/components/cancellable-loader.d.ts +27 -0
- package/dist/node_modules/@pencil-agent/tui/dist/components/cancellable-loader.js +40 -0
- package/dist/node_modules/@pencil-agent/tui/dist/components/editor.d.ts +218 -0
- package/dist/node_modules/@pencil-agent/tui/dist/components/editor.js +1697 -0
- package/dist/node_modules/@pencil-agent/tui/dist/components/image.d.ts +33 -0
- package/dist/node_modules/@pencil-agent/tui/dist/components/image.js +74 -0
- package/dist/node_modules/@pencil-agent/tui/dist/components/input.d.ts +42 -0
- package/dist/node_modules/@pencil-agent/tui/dist/components/input.js +438 -0
- package/dist/node_modules/@pencil-agent/tui/dist/components/loader.d.ts +26 -0
- package/dist/node_modules/@pencil-agent/tui/dist/components/loader.js +54 -0
- package/dist/node_modules/@pencil-agent/tui/dist/components/markdown.d.ts +100 -0
- package/dist/node_modules/@pencil-agent/tui/dist/components/markdown.js +634 -0
- package/dist/node_modules/@pencil-agent/tui/dist/components/select-list.d.ts +37 -0
- package/dist/node_modules/@pencil-agent/tui/dist/components/select-list.js +157 -0
- package/dist/node_modules/@pencil-agent/tui/dist/components/settings-list.d.ts +55 -0
- package/dist/node_modules/@pencil-agent/tui/dist/components/settings-list.js +190 -0
- package/dist/node_modules/@pencil-agent/tui/dist/components/spacer.d.ts +17 -0
- package/dist/node_modules/@pencil-agent/tui/dist/components/spacer.js +28 -0
- package/dist/node_modules/@pencil-agent/tui/dist/components/text.d.ts +24 -0
- package/dist/node_modules/@pencil-agent/tui/dist/components/text.js +94 -0
- package/dist/node_modules/@pencil-agent/tui/dist/components/truncated-text.d.ts +18 -0
- package/dist/node_modules/@pencil-agent/tui/dist/components/truncated-text.js +56 -0
- package/dist/node_modules/@pencil-agent/tui/dist/editor-component.d.ts +51 -0
- package/dist/node_modules/@pencil-agent/tui/dist/editor-component.js +7 -0
- package/dist/node_modules/@pencil-agent/tui/dist/fuzzy.d.ts +32 -0
- package/dist/node_modules/@pencil-agent/tui/dist/fuzzy.js +152 -0
- package/dist/node_modules/@pencil-agent/tui/dist/index.d.ts +28 -0
- package/dist/node_modules/@pencil-agent/tui/dist/index.js +37 -0
- package/dist/node_modules/@pencil-agent/tui/dist/keybindings.d.ts +44 -0
- package/dist/node_modules/@pencil-agent/tui/dist/keybindings.js +119 -0
- package/dist/node_modules/@pencil-agent/tui/dist/keys.d.ts +149 -0
- package/dist/node_modules/@pencil-agent/tui/dist/keys.js +948 -0
- package/dist/node_modules/@pencil-agent/tui/dist/kill-ring.d.ts +33 -0
- package/dist/node_modules/@pencil-agent/tui/dist/kill-ring.js +49 -0
- package/dist/node_modules/@pencil-agent/tui/dist/stdin-buffer.d.ts +38 -0
- package/dist/node_modules/@pencil-agent/tui/dist/stdin-buffer.js +307 -0
- package/dist/node_modules/@pencil-agent/tui/dist/terminal-image.d.ts +73 -0
- package/dist/node_modules/@pencil-agent/tui/dist/terminal-image.js +287 -0
- package/dist/node_modules/@pencil-agent/tui/dist/terminal.d.ts +86 -0
- package/dist/node_modules/@pencil-agent/tui/dist/terminal.js +266 -0
- package/dist/node_modules/@pencil-agent/tui/dist/tui.d.ts +219 -0
- package/dist/node_modules/@pencil-agent/tui/dist/tui.js +1001 -0
- package/dist/node_modules/@pencil-agent/tui/dist/undo-stack.d.ts +22 -0
- package/dist/node_modules/@pencil-agent/tui/dist/undo-stack.js +30 -0
- package/dist/node_modules/@pencil-agent/tui/dist/utils.d.ts +83 -0
- package/dist/node_modules/@pencil-agent/tui/dist/utils.js +811 -0
- package/dist/node_modules/@pencil-agent/tui/package.json +37 -0
- package/package.json +3 -2
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared utilities for Google Generative AI and Google Cloud Code Assist providers.
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* [WHO]: isThinkingPart, retainThoughtSignature, requiresToolCallId, convertMessages, convertTools
|
|
6
|
+
* [FROM]: Depends on @google/genai, ../utils/sanitize-unicode.js, ./transform-messages.js
|
|
7
|
+
* [TO]: Consumed by core/lib/ai/src/index.ts
|
|
8
|
+
* [HERE]: core/lib/ai/src/providers/google-shared.ts -
|
|
9
|
+
*/
|
|
10
|
+
import { type Content, FinishReason, FunctionCallingConfigMode, type Part } from "@google/genai";
|
|
11
|
+
import type { Context, Model, StopReason, Tool } from "../types.js";
|
|
12
|
+
type GoogleApiType = "google-generative-ai" | "google-gemini-cli" | "google-vertex";
|
|
13
|
+
/**
|
|
14
|
+
* Determines whether a streamed Gemini `Part` should be treated as "thinking".
|
|
15
|
+
*
|
|
16
|
+
* Protocol note (Gemini / Vertex AI thought signatures):
|
|
17
|
+
* - `thought: true` is the definitive marker for thinking content (thought summaries).
|
|
18
|
+
* - `thoughtSignature` is an encrypted representation of the model's internal thought process
|
|
19
|
+
* used to preserve reasoning context across multi-turn interactions.
|
|
20
|
+
* - `thoughtSignature` can appear on ANY part type (text, functionCall, etc.) - it does NOT
|
|
21
|
+
* indicate the part itself is thinking content.
|
|
22
|
+
* - For non-functionCall responses, the signature appears on the last part for context replay.
|
|
23
|
+
* - When persisting/replaying model outputs, signature-bearing parts must be preserved as-is;
|
|
24
|
+
* do not merge/move signatures across parts.
|
|
25
|
+
*
|
|
26
|
+
* See: https://ai.google.dev/gemini-api/docs/thought-signatures
|
|
27
|
+
*/
|
|
28
|
+
export declare function isThinkingPart(part: Pick<Part, "thought" | "thoughtSignature">): boolean;
|
|
29
|
+
/**
|
|
30
|
+
* Retain thought signatures during streaming.
|
|
31
|
+
*
|
|
32
|
+
* Some backends only send `thoughtSignature` on the first delta for a given part/block; later deltas may omit it.
|
|
33
|
+
* This helper preserves the last non-empty signature for the current block.
|
|
34
|
+
*
|
|
35
|
+
* Note: this does NOT merge or move signatures across distinct response parts. It only prevents
|
|
36
|
+
* a signature from being overwritten with `undefined` within the same streamed block.
|
|
37
|
+
*/
|
|
38
|
+
export declare function retainThoughtSignature(existing: string | undefined, incoming: string | undefined): string | undefined;
|
|
39
|
+
/**
|
|
40
|
+
* Models via Google APIs that require explicit tool call IDs in function calls/responses.
|
|
41
|
+
*/
|
|
42
|
+
export declare function requiresToolCallId(modelId: string): boolean;
|
|
43
|
+
/**
|
|
44
|
+
* Convert internal messages to Gemini Content[] format.
|
|
45
|
+
*/
|
|
46
|
+
export declare function convertMessages<T extends GoogleApiType>(model: Model<T>, context: Context): Content[];
|
|
47
|
+
/**
|
|
48
|
+
* Convert tools to Gemini function declarations format.
|
|
49
|
+
*
|
|
50
|
+
* By default uses `parametersJsonSchema` which supports full JSON Schema (including
|
|
51
|
+
* anyOf, oneOf, const, etc.). Set `useParameters` to true to use the legacy `parameters`
|
|
52
|
+
* field instead (OpenAPI 3.03 Schema). This is needed for Cloud Code Assist with Claude
|
|
53
|
+
* models, where the API translates `parameters` into Anthropic's `input_schema`.
|
|
54
|
+
*/
|
|
55
|
+
export declare function convertTools(tools: Tool[], useParameters?: boolean): {
|
|
56
|
+
functionDeclarations: Record<string, unknown>[];
|
|
57
|
+
}[] | undefined;
|
|
58
|
+
/**
|
|
59
|
+
* Map tool choice string to Gemini FunctionCallingConfigMode.
|
|
60
|
+
*/
|
|
61
|
+
export declare function mapToolChoice(choice: string): FunctionCallingConfigMode;
|
|
62
|
+
/**
|
|
63
|
+
* Map Gemini FinishReason to our StopReason.
|
|
64
|
+
*/
|
|
65
|
+
export declare function mapStopReason(reason: FinishReason): StopReason;
|
|
66
|
+
/**
|
|
67
|
+
* Map string finish reason to our StopReason (for raw API responses).
|
|
68
|
+
*/
|
|
69
|
+
export declare function mapStopReasonString(reason: string): StopReason;
|
|
70
|
+
export {};
|
|
@@ -0,0 +1,311 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared utilities for Google Generative AI and Google Cloud Code Assist providers.
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* [WHO]: isThinkingPart, retainThoughtSignature, requiresToolCallId, convertMessages, convertTools
|
|
6
|
+
* [FROM]: Depends on @google/genai, ../utils/sanitize-unicode.js, ./transform-messages.js
|
|
7
|
+
* [TO]: Consumed by core/lib/ai/src/index.ts
|
|
8
|
+
* [HERE]: core/lib/ai/src/providers/google-shared.ts -
|
|
9
|
+
*/
|
|
10
|
+
import { FinishReason, FunctionCallingConfigMode } from "@google/genai";
|
|
11
|
+
import { sanitizeSurrogates } from "../utils/sanitize-unicode.js";
|
|
12
|
+
import { transformMessages } from "./transform-messages.js";
|
|
13
|
+
/**
|
|
14
|
+
* Determines whether a streamed Gemini `Part` should be treated as "thinking".
|
|
15
|
+
*
|
|
16
|
+
* Protocol note (Gemini / Vertex AI thought signatures):
|
|
17
|
+
* - `thought: true` is the definitive marker for thinking content (thought summaries).
|
|
18
|
+
* - `thoughtSignature` is an encrypted representation of the model's internal thought process
|
|
19
|
+
* used to preserve reasoning context across multi-turn interactions.
|
|
20
|
+
* - `thoughtSignature` can appear on ANY part type (text, functionCall, etc.) - it does NOT
|
|
21
|
+
* indicate the part itself is thinking content.
|
|
22
|
+
* - For non-functionCall responses, the signature appears on the last part for context replay.
|
|
23
|
+
* - When persisting/replaying model outputs, signature-bearing parts must be preserved as-is;
|
|
24
|
+
* do not merge/move signatures across parts.
|
|
25
|
+
*
|
|
26
|
+
* See: https://ai.google.dev/gemini-api/docs/thought-signatures
|
|
27
|
+
*/
|
|
28
|
+
export function isThinkingPart(part) {
|
|
29
|
+
return part.thought === true;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Retain thought signatures during streaming.
|
|
33
|
+
*
|
|
34
|
+
* Some backends only send `thoughtSignature` on the first delta for a given part/block; later deltas may omit it.
|
|
35
|
+
* This helper preserves the last non-empty signature for the current block.
|
|
36
|
+
*
|
|
37
|
+
* Note: this does NOT merge or move signatures across distinct response parts. It only prevents
|
|
38
|
+
* a signature from being overwritten with `undefined` within the same streamed block.
|
|
39
|
+
*/
|
|
40
|
+
export function retainThoughtSignature(existing, incoming) {
|
|
41
|
+
if (typeof incoming === "string" && incoming.length > 0)
|
|
42
|
+
return incoming;
|
|
43
|
+
return existing;
|
|
44
|
+
}
|
|
45
|
+
// Thought signatures must be base64 for Google APIs (TYPE_BYTES).
|
|
46
|
+
const base64SignaturePattern = /^[A-Za-z0-9+/]+={0,2}$/;
|
|
47
|
+
function isValidThoughtSignature(signature) {
|
|
48
|
+
if (!signature)
|
|
49
|
+
return false;
|
|
50
|
+
if (signature.length % 4 !== 0)
|
|
51
|
+
return false;
|
|
52
|
+
return base64SignaturePattern.test(signature);
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Only keep signatures from the same provider/model and with valid base64.
|
|
56
|
+
*/
|
|
57
|
+
function resolveThoughtSignature(isSameProviderAndModel, signature) {
|
|
58
|
+
return isSameProviderAndModel && isValidThoughtSignature(signature) ? signature : undefined;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Models via Google APIs that require explicit tool call IDs in function calls/responses.
|
|
62
|
+
*/
|
|
63
|
+
export function requiresToolCallId(modelId) {
|
|
64
|
+
return modelId.startsWith("claude-") || modelId.startsWith("gpt-oss-");
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Convert internal messages to Gemini Content[] format.
|
|
68
|
+
*/
|
|
69
|
+
export function convertMessages(model, context) {
|
|
70
|
+
const contents = [];
|
|
71
|
+
const normalizeToolCallId = (id) => {
|
|
72
|
+
if (!requiresToolCallId(model.id))
|
|
73
|
+
return id;
|
|
74
|
+
return id.replace(/[^a-zA-Z0-9_-]/g, "_").slice(0, 64);
|
|
75
|
+
};
|
|
76
|
+
const transformedMessages = transformMessages(context.messages, model, normalizeToolCallId);
|
|
77
|
+
for (const msg of transformedMessages) {
|
|
78
|
+
if (msg.role === "user") {
|
|
79
|
+
if (typeof msg.content === "string") {
|
|
80
|
+
contents.push({
|
|
81
|
+
role: "user",
|
|
82
|
+
parts: [{ text: sanitizeSurrogates(msg.content) }],
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
else {
|
|
86
|
+
const parts = msg.content.map((item) => {
|
|
87
|
+
if (item.type === "text") {
|
|
88
|
+
return { text: sanitizeSurrogates(item.text) };
|
|
89
|
+
}
|
|
90
|
+
else {
|
|
91
|
+
return {
|
|
92
|
+
inlineData: {
|
|
93
|
+
mimeType: item.mimeType,
|
|
94
|
+
data: item.data,
|
|
95
|
+
},
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
});
|
|
99
|
+
const filteredParts = !model.input.includes("image") ? parts.filter((p) => p.text !== undefined) : parts;
|
|
100
|
+
if (filteredParts.length === 0)
|
|
101
|
+
continue;
|
|
102
|
+
contents.push({
|
|
103
|
+
role: "user",
|
|
104
|
+
parts: filteredParts,
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
else if (msg.role === "assistant") {
|
|
109
|
+
const parts = [];
|
|
110
|
+
// Check if message is from same provider and model - only then keep thinking blocks
|
|
111
|
+
const isSameProviderAndModel = msg.provider === model.provider && msg.model === model.id;
|
|
112
|
+
for (const block of msg.content) {
|
|
113
|
+
if (block.type === "text") {
|
|
114
|
+
// Skip empty text blocks - they can cause issues with some models (e.g. Claude via Antigravity)
|
|
115
|
+
if (!block.text || block.text.trim() === "")
|
|
116
|
+
continue;
|
|
117
|
+
const thoughtSignature = resolveThoughtSignature(isSameProviderAndModel, block.textSignature);
|
|
118
|
+
parts.push({
|
|
119
|
+
text: sanitizeSurrogates(block.text),
|
|
120
|
+
...(thoughtSignature && { thoughtSignature }),
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
else if (block.type === "thinking") {
|
|
124
|
+
// Skip empty thinking blocks
|
|
125
|
+
if (!block.thinking || block.thinking.trim() === "")
|
|
126
|
+
continue;
|
|
127
|
+
// Only keep as thinking block if same provider AND same model
|
|
128
|
+
// Otherwise convert to plain text (no tags to avoid model mimicking them)
|
|
129
|
+
if (isSameProviderAndModel) {
|
|
130
|
+
const thoughtSignature = resolveThoughtSignature(isSameProviderAndModel, block.thinkingSignature);
|
|
131
|
+
parts.push({
|
|
132
|
+
thought: true,
|
|
133
|
+
text: sanitizeSurrogates(block.thinking),
|
|
134
|
+
...(thoughtSignature && { thoughtSignature }),
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
else {
|
|
138
|
+
parts.push({
|
|
139
|
+
text: sanitizeSurrogates(block.thinking),
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
else if (block.type === "toolCall") {
|
|
144
|
+
const thoughtSignature = resolveThoughtSignature(isSameProviderAndModel, block.thoughtSignature);
|
|
145
|
+
// Gemini 3 requires thoughtSignature on all function calls when thinking mode is enabled.
|
|
146
|
+
// When replaying history from providers without thought signatures (e.g. Claude via Antigravity),
|
|
147
|
+
// convert unsigned function calls to text to avoid API validation errors.
|
|
148
|
+
// We include a note telling the model this is historical context to prevent mimicry.
|
|
149
|
+
const isGemini3 = model.id.toLowerCase().includes("gemini-3");
|
|
150
|
+
if (isGemini3 && !thoughtSignature) {
|
|
151
|
+
const argsStr = JSON.stringify(block.arguments ?? {}, null, 2);
|
|
152
|
+
parts.push({
|
|
153
|
+
text: `[Historical context: a different model called tool "${block.name}" with arguments: ${argsStr}. Do not mimic this format - use proper function calling.]`,
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
else {
|
|
157
|
+
const part = {
|
|
158
|
+
functionCall: {
|
|
159
|
+
name: block.name,
|
|
160
|
+
args: block.arguments ?? {},
|
|
161
|
+
...(requiresToolCallId(model.id) ? { id: block.id } : {}),
|
|
162
|
+
},
|
|
163
|
+
};
|
|
164
|
+
if (thoughtSignature) {
|
|
165
|
+
part.thoughtSignature = thoughtSignature;
|
|
166
|
+
}
|
|
167
|
+
parts.push(part);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
if (parts.length === 0)
|
|
172
|
+
continue;
|
|
173
|
+
contents.push({
|
|
174
|
+
role: "model",
|
|
175
|
+
parts,
|
|
176
|
+
});
|
|
177
|
+
}
|
|
178
|
+
else if (msg.role === "toolResult") {
|
|
179
|
+
// Extract text and image content
|
|
180
|
+
const textContent = msg.content.filter((c) => c.type === "text");
|
|
181
|
+
const textResult = textContent.map((c) => c.text).join("\n");
|
|
182
|
+
const imageContent = model.input.includes("image")
|
|
183
|
+
? msg.content.filter((c) => c.type === "image")
|
|
184
|
+
: [];
|
|
185
|
+
const hasText = textResult.length > 0;
|
|
186
|
+
const hasImages = imageContent.length > 0;
|
|
187
|
+
// Gemini 3 supports multimodal function responses with images nested inside functionResponse.parts
|
|
188
|
+
// See: https://ai.google.dev/gemini-api/docs/function-calling#multimodal
|
|
189
|
+
// Older models don't support this, so we put images in a separate user message.
|
|
190
|
+
const supportsMultimodalFunctionResponse = model.id.includes("gemini-3");
|
|
191
|
+
// Use "output" key for success, "error" key for errors as per SDK documentation
|
|
192
|
+
const responseValue = hasText ? sanitizeSurrogates(textResult) : hasImages ? "(see attached image)" : "";
|
|
193
|
+
const imageParts = imageContent.map((imageBlock) => ({
|
|
194
|
+
inlineData: {
|
|
195
|
+
mimeType: imageBlock.mimeType,
|
|
196
|
+
data: imageBlock.data,
|
|
197
|
+
},
|
|
198
|
+
}));
|
|
199
|
+
const includeId = requiresToolCallId(model.id);
|
|
200
|
+
const functionResponsePart = {
|
|
201
|
+
functionResponse: {
|
|
202
|
+
name: msg.toolName,
|
|
203
|
+
response: msg.isError ? { error: responseValue } : { output: responseValue },
|
|
204
|
+
// Nest images inside functionResponse.parts for Gemini 3
|
|
205
|
+
...(hasImages && supportsMultimodalFunctionResponse && { parts: imageParts }),
|
|
206
|
+
...(includeId ? { id: msg.toolCallId } : {}),
|
|
207
|
+
},
|
|
208
|
+
};
|
|
209
|
+
// Cloud Code Assist API requires all function responses to be in a single user turn.
|
|
210
|
+
// Check if the last content is already a user turn with function responses and merge.
|
|
211
|
+
const lastContent = contents[contents.length - 1];
|
|
212
|
+
if (lastContent?.role === "user" && lastContent.parts?.some((p) => p.functionResponse)) {
|
|
213
|
+
lastContent.parts.push(functionResponsePart);
|
|
214
|
+
}
|
|
215
|
+
else {
|
|
216
|
+
contents.push({
|
|
217
|
+
role: "user",
|
|
218
|
+
parts: [functionResponsePart],
|
|
219
|
+
});
|
|
220
|
+
}
|
|
221
|
+
// For older models, add images in a separate user message
|
|
222
|
+
if (hasImages && !supportsMultimodalFunctionResponse) {
|
|
223
|
+
contents.push({
|
|
224
|
+
role: "user",
|
|
225
|
+
parts: [{ text: "Tool result image:" }, ...imageParts],
|
|
226
|
+
});
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
return contents;
|
|
231
|
+
}
|
|
232
|
+
/**
|
|
233
|
+
* Convert tools to Gemini function declarations format.
|
|
234
|
+
*
|
|
235
|
+
* By default uses `parametersJsonSchema` which supports full JSON Schema (including
|
|
236
|
+
* anyOf, oneOf, const, etc.). Set `useParameters` to true to use the legacy `parameters`
|
|
237
|
+
* field instead (OpenAPI 3.03 Schema). This is needed for Cloud Code Assist with Claude
|
|
238
|
+
* models, where the API translates `parameters` into Anthropic's `input_schema`.
|
|
239
|
+
*/
|
|
240
|
+
export function convertTools(tools, useParameters = false) {
|
|
241
|
+
if (tools.length === 0)
|
|
242
|
+
return undefined;
|
|
243
|
+
return [
|
|
244
|
+
{
|
|
245
|
+
functionDeclarations: tools.map((tool) => ({
|
|
246
|
+
name: tool.name,
|
|
247
|
+
description: tool.description,
|
|
248
|
+
...(useParameters ? { parameters: tool.parameters } : { parametersJsonSchema: tool.parameters }),
|
|
249
|
+
})),
|
|
250
|
+
},
|
|
251
|
+
];
|
|
252
|
+
}
|
|
253
|
+
/**
|
|
254
|
+
* Map tool choice string to Gemini FunctionCallingConfigMode.
|
|
255
|
+
*/
|
|
256
|
+
export function mapToolChoice(choice) {
|
|
257
|
+
switch (choice) {
|
|
258
|
+
case "auto":
|
|
259
|
+
return FunctionCallingConfigMode.AUTO;
|
|
260
|
+
case "none":
|
|
261
|
+
return FunctionCallingConfigMode.NONE;
|
|
262
|
+
case "any":
|
|
263
|
+
return FunctionCallingConfigMode.ANY;
|
|
264
|
+
default:
|
|
265
|
+
return FunctionCallingConfigMode.AUTO;
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
/**
|
|
269
|
+
* Map Gemini FinishReason to our StopReason.
|
|
270
|
+
*/
|
|
271
|
+
export function mapStopReason(reason) {
|
|
272
|
+
switch (reason) {
|
|
273
|
+
case FinishReason.STOP:
|
|
274
|
+
return "stop";
|
|
275
|
+
case FinishReason.MAX_TOKENS:
|
|
276
|
+
return "length";
|
|
277
|
+
case FinishReason.BLOCKLIST:
|
|
278
|
+
case FinishReason.PROHIBITED_CONTENT:
|
|
279
|
+
case FinishReason.SPII:
|
|
280
|
+
case FinishReason.SAFETY:
|
|
281
|
+
case FinishReason.IMAGE_SAFETY:
|
|
282
|
+
case FinishReason.IMAGE_PROHIBITED_CONTENT:
|
|
283
|
+
case FinishReason.IMAGE_RECITATION:
|
|
284
|
+
case FinishReason.IMAGE_OTHER:
|
|
285
|
+
case FinishReason.RECITATION:
|
|
286
|
+
case FinishReason.FINISH_REASON_UNSPECIFIED:
|
|
287
|
+
case FinishReason.OTHER:
|
|
288
|
+
case FinishReason.LANGUAGE:
|
|
289
|
+
case FinishReason.MALFORMED_FUNCTION_CALL:
|
|
290
|
+
case FinishReason.UNEXPECTED_TOOL_CALL:
|
|
291
|
+
case FinishReason.NO_IMAGE:
|
|
292
|
+
return "error";
|
|
293
|
+
default: {
|
|
294
|
+
const _exhaustive = reason;
|
|
295
|
+
throw new Error(`Unhandled stop reason: ${_exhaustive}`);
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
/**
|
|
300
|
+
* Map string finish reason to our StopReason (for raw API responses).
|
|
301
|
+
*/
|
|
302
|
+
export function mapStopReasonString(reason) {
|
|
303
|
+
switch (reason) {
|
|
304
|
+
case "STOP":
|
|
305
|
+
return "stop";
|
|
306
|
+
case "MAX_TOKENS":
|
|
307
|
+
return "length";
|
|
308
|
+
default:
|
|
309
|
+
return "error";
|
|
310
|
+
}
|
|
311
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* [WHO]: GoogleVertexOptions, streamGoogleVertex, streamSimpleGoogleVertex
|
|
3
|
+
* [FROM]: Depends on ../models.js, ../utils/event-stream.js, ../utils/sanitize-unicode.js, ./simple-options.js
|
|
4
|
+
* [TO]: Consumed by core/lib/ai/src/index.ts
|
|
5
|
+
* [HERE]: core/lib/ai/src/providers/google-vertex.ts -
|
|
6
|
+
*/
|
|
7
|
+
import type { SimpleStreamOptions, StreamFunction, StreamOptions } from "../types.js";
|
|
8
|
+
import type { GoogleThinkingLevel } from "./google-gemini-cli.js";
|
|
9
|
+
export interface GoogleVertexOptions extends StreamOptions {
|
|
10
|
+
toolChoice?: "auto" | "none" | "any";
|
|
11
|
+
thinking?: {
|
|
12
|
+
enabled: boolean;
|
|
13
|
+
budgetTokens?: number;
|
|
14
|
+
level?: GoogleThinkingLevel;
|
|
15
|
+
};
|
|
16
|
+
project?: string;
|
|
17
|
+
location?: string;
|
|
18
|
+
}
|
|
19
|
+
export declare const streamGoogleVertex: StreamFunction<"google-vertex", GoogleVertexOptions>;
|
|
20
|
+
export declare const streamSimpleGoogleVertex: StreamFunction<"google-vertex", SimpleStreamOptions>;
|