@oh-my-pi/pi-ai 16.1.23 → 16.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +35 -0
- package/dist/types/auth-broker/wire-schemas.d.ts +5 -0
- package/dist/types/index.d.ts +2 -0
- package/dist/types/providers/anthropic-messages-server-schema.d.ts +31 -0
- package/dist/types/providers/gitlab-duo-workflow.d.ts +254 -0
- package/dist/types/registry/gitlab-duo-workflow.d.ts +10 -0
- package/dist/types/registry/gitlab-duo.d.ts +1 -1
- package/dist/types/registry/oauth/gitlab-duo-workflow.d.ts +6 -0
- package/dist/types/registry/registry.d.ts +9 -1
- package/dist/types/stream.d.ts +8 -0
- package/dist/types/types.d.ts +12 -0
- package/dist/types/usage/ollama.d.ts +5 -0
- package/dist/types/usage/openai-codex-base-url.d.ts +1 -0
- package/dist/types/usage/openai-codex.d.ts +0 -1
- package/dist/types/usage.d.ts +33 -0
- package/dist/types/utils/thinking-loop.d.ts +46 -0
- package/package.json +4 -4
- package/src/api-registry.ts +1 -0
- package/src/auth-broker/wire-schemas.ts +7 -0
- package/src/auth-storage.ts +15 -2
- package/src/dialect/anthropic.md +2 -2
- package/src/dialect/anthropic.ts +1 -1
- package/src/dialect/deepseek.md +2 -1
- package/src/dialect/deepseek.ts +1 -1
- package/src/dialect/gemini.md +2 -1
- package/src/dialect/gemma.md +2 -1
- package/src/dialect/glm.md +2 -2
- package/src/dialect/harmony.md +2 -1
- package/src/dialect/harmony.ts +1 -1
- package/src/dialect/hermes.md +2 -1
- package/src/dialect/hermes.ts +1 -1
- package/src/dialect/kimi.md +2 -1
- package/src/dialect/kimi.ts +1 -1
- package/src/dialect/minimax.md +2 -2
- package/src/dialect/pi.md +1 -1
- package/src/dialect/qwen3.md +2 -1
- package/src/dialect/qwen3.ts +1 -1
- package/src/dialect/xml.md +2 -2
- package/src/index.ts +2 -0
- package/src/providers/amazon-bedrock.ts +8 -2
- package/src/providers/anthropic-messages-server-schema.ts +6 -1
- package/src/providers/anthropic.ts +2 -1
- package/src/providers/cursor.ts +7 -2
- package/src/providers/devin.ts +1 -2
- package/src/providers/gitlab-duo-workflow-chatml-note.md +1 -0
- package/src/providers/gitlab-duo-workflow.ts +3038 -0
- package/src/providers/ollama.ts +1 -2
- package/src/providers/openai-codex-responses.ts +1 -1
- package/src/providers/openai-completions.ts +8 -2
- package/src/providers/openai-shared.ts +8 -2
- package/src/registry/gitlab-duo-workflow.ts +20 -0
- package/src/registry/gitlab-duo.ts +1 -1
- package/src/registry/oauth/gitlab-duo-workflow.ts +134 -0
- package/src/registry/registry.ts +2 -0
- package/src/stream.ts +505 -16
- package/src/types.ts +13 -0
- package/src/usage/ollama.ts +41 -0
- package/src/usage/openai-codex-base-url.ts +15 -0
- package/src/usage/openai-codex-reset.ts +1 -1
- package/src/usage/openai-codex.ts +30 -15
- package/src/usage.ts +26 -0
- package/src/utils/thinking-loop.ts +89 -14
- package/dist/types/utils/json-parse.d.ts +0 -48
- package/src/utils/json-parse.ts +0 -558
|
@@ -183,8 +183,15 @@ const usageLimitSchema = type({
|
|
|
183
183
|
"notes?": "string[]",
|
|
184
184
|
});
|
|
185
185
|
|
|
186
|
+
const usageResetCreditDetailSchema = type({
|
|
187
|
+
"grantedAt?": "string",
|
|
188
|
+
"expiresAt?": "string",
|
|
189
|
+
"status?": "string",
|
|
190
|
+
});
|
|
191
|
+
|
|
186
192
|
const usageResetCreditsSchema = type({
|
|
187
193
|
availableCount: "number",
|
|
194
|
+
"credits?": usageResetCreditDetailSchema.array(),
|
|
188
195
|
});
|
|
189
196
|
|
|
190
197
|
const arkUsageReportSchema = type({
|
package/src/auth-storage.ts
CHANGED
|
@@ -13,7 +13,7 @@ import * as path from "node:path";
|
|
|
13
13
|
import { extractHttpStatusFromError, getAgentDbPath, logger } from "@oh-my-pi/pi-utils";
|
|
14
14
|
import type { ApiKeyResolver } from "./auth-retry";
|
|
15
15
|
import { isUsageLimitOutcome } from "./rate-limit-utils";
|
|
16
|
-
import { getProviderDefinition } from "./registry";
|
|
16
|
+
import { getProviderDefinition, PASTE_CODE_LOGIN_PROVIDERS } from "./registry";
|
|
17
17
|
import { getOAuthApiKey, getOAuthProvider, refreshOAuthToken } from "./registry/oauth";
|
|
18
18
|
import type { OAuthController, OAuthCredentials, OAuthProvider, OAuthProviderId } from "./registry/oauth/types";
|
|
19
19
|
import { getEnvApiKey, getEnvApiKeyName } from "./stream";
|
|
@@ -39,6 +39,7 @@ import { googleGeminiCliUsageProvider } from "./usage/gemini";
|
|
|
39
39
|
import { githubCopilotUsageProvider } from "./usage/github-copilot";
|
|
40
40
|
import { antigravityRankingStrategy, antigravityUsageProvider } from "./usage/google-antigravity";
|
|
41
41
|
import { kimiUsageProvider } from "./usage/kimi";
|
|
42
|
+
import { ollamaCloudUsageProvider, ollamaUsageProvider } from "./usage/ollama";
|
|
42
43
|
import { codexRankingStrategy, openaiCodexUsageProvider } from "./usage/openai-codex";
|
|
43
44
|
import {
|
|
44
45
|
type CodexResetConsumeCode,
|
|
@@ -496,6 +497,8 @@ const DEFAULT_USAGE_PROVIDERS: UsageProvider[] = [
|
|
|
496
497
|
kimiUsageProvider,
|
|
497
498
|
antigravityUsageProvider,
|
|
498
499
|
googleGeminiCliUsageProvider,
|
|
500
|
+
ollamaUsageProvider,
|
|
501
|
+
ollamaCloudUsageProvider,
|
|
499
502
|
claudeUsageProvider,
|
|
500
503
|
zaiUsageProvider,
|
|
501
504
|
opencodeGoUsageProvider,
|
|
@@ -1884,7 +1887,17 @@ export class AuthStorage {
|
|
|
1884
1887
|
onPrompt: (prompt: { message: string; placeholder?: string }) => Promise<string>;
|
|
1885
1888
|
},
|
|
1886
1889
|
): Promise<void> {
|
|
1887
|
-
|
|
1890
|
+
// Only paste-code providers (fixed non-loopback redirect, e.g. GitLab Duo
|
|
1891
|
+
// Agent's vscode:// URI) get a default manual-code prompt. For loopback OAuth
|
|
1892
|
+
// providers the `OAuthCallbackFlow` would otherwise race this readline prompt
|
|
1893
|
+
// against the HTTP callback and, when the callback wins, leave the prompt
|
|
1894
|
+
// outstanding — a dirty/blocked terminal. Synthesizing the default only for
|
|
1895
|
+
// paste-code providers is the authoritative gate (it covers every caller, not
|
|
1896
|
+
// just the CLI); an explicit caller-supplied `onManualCodeInput` is still
|
|
1897
|
+
// honored for any provider as an escape hatch.
|
|
1898
|
+
const manualCodeInput = PASTE_CODE_LOGIN_PROVIDERS.has(provider)
|
|
1899
|
+
? () => ctrl.onPrompt({ message: "Paste the authorization code (or full redirect URL):" })
|
|
1900
|
+
: undefined;
|
|
1888
1901
|
// Built-in registry first, then runtime-registered extension providers.
|
|
1889
1902
|
const def = getProviderDefinition(provider) ?? getOAuthProvider(provider);
|
|
1890
1903
|
if (!def?.login) {
|
package/src/dialect/anthropic.md
CHANGED
|
@@ -22,10 +22,10 @@ Results arrive later in a `<function_results>` block, one `<result>` per call (f
|
|
|
22
22
|
## Rules
|
|
23
23
|
|
|
24
24
|
- `name` MUST match a listed function.
|
|
25
|
-
- String/scalar parameters: exact text, spaces preserved. Lists/objects: JSON.
|
|
25
|
+
- String/scalar parameters: exact text, spaces preserved — bodies are read by regex (delimiter matching), NOT a real XML parser, so never HTML-escape them (emit `a & b`, not `a & b`; `<`/`>` stay literal); only the body's own `</parameter>` closing tag is reserved. Lists/objects: JSON.
|
|
26
26
|
- Multiple calls: multiple `<invoke>` blocks in one `<function_calls>`.
|
|
27
27
|
- You MAY write visible text before the calls.
|
|
28
28
|
- NEVER emit `tool_calls` JSON.
|
|
29
29
|
- NEVER use the legacy `<tool_name>`/`<parameters>` call syntax.
|
|
30
30
|
- Read each `<result>`/`<error>` in call order. NEVER emit `<function_results>` yourself.
|
|
31
|
-
-
|
|
31
|
+
- Emit the stop sequence ONLY after the call is fully written — NEVER announce a tool then stop (e.g. halting at "Let's run `cargo clippy`" with no `<invoke>` emitted). Write the complete call, THEN the stop sequence, THEN halt.
|
package/src/dialect/anthropic.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
+
import { parseJsonWithRepair } from "@oh-my-pi/pi-utils";
|
|
1
2
|
import type { Message, ToolCall } from "../types";
|
|
2
|
-
import { parseJsonWithRepair } from "../utils/json-parse";
|
|
3
3
|
import dialectPrompt from "./anthropic.md" with { type: "text" };
|
|
4
4
|
import { buildArgShapes, buildStringArgsResolver, mintToolCallId, type ToolArgShape } from "./coercion";
|
|
5
5
|
import {
|
package/src/dialect/deepseek.md
CHANGED
|
@@ -16,8 +16,9 @@ Results arrive as output tokens:
|
|
|
16
16
|
|
|
17
17
|
- Use `|` (U+FF5C) and `▁` (U+2581) exactly.
|
|
18
18
|
- Tool name MUST match an available function; arguments are one valid JSON object.
|
|
19
|
+
- Argument string values use only normal JSON string escaping (`\"`, `\\`, `\n`); never HTML-escape their contents — write `a & b`, not `a & b`.
|
|
19
20
|
- NEVER wrap arguments in Markdown fences; NEVER emit a `type` field or `function` prefix.
|
|
20
21
|
- Multiple calls chain `<|tool▁call▁begin|>...<|tool▁call▁end|>` directly — no separators, spaces, or newlines between them.
|
|
21
22
|
- Private reasoning, when needed, goes in `<think>...</think>` before the tokens.
|
|
22
23
|
- Read each output token in call order. NEVER emit output tokens yourself.
|
|
23
|
-
-
|
|
24
|
+
- Emit the stop sequence ONLY after the call is fully written — NEVER announce a tool then stop (e.g. halting at "Let's run `cargo clippy`" with no `<|tool▁call▁begin|>` emitted). Write the complete call, THEN the stop sequence, THEN halt.
|
package/src/dialect/deepseek.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
+
import { parseJsonWithRepair } from "@oh-my-pi/pi-utils";
|
|
1
2
|
import type { Message, ToolCall } from "../types";
|
|
2
|
-
import { parseJsonWithRepair } from "../utils/json-parse";
|
|
3
3
|
import { asRecord, mintToolCallId, partialSuffixOverlapAny } from "./coercion";
|
|
4
4
|
import dialectPrompt from "./deepseek.md" with { type: "text" };
|
|
5
5
|
import { assistantTranscriptParts, collectToolResultRun, messageContentText, stringifyJson } from "./rendering";
|
package/src/dialect/gemini.md
CHANGED
|
@@ -37,7 +37,8 @@ brief reasoning
|
|
|
37
37
|
## Rules
|
|
38
38
|
|
|
39
39
|
- The function name MUST match a listed function; arguments are keyword form (`name=value`).
|
|
40
|
+
- Argument string values use only normal Python string escaping; never HTML-escape their contents — write `"a & b"`, not `"a & b"`.
|
|
40
41
|
- Multiple calls = a single `[...]` list (or one `default_api...` call per line) inside one ` ```tool_code ` block.
|
|
41
42
|
- Put private reasoning in a ` ```thinking ` block before the ` ```tool_code ` block, never inside ` ```tool_code `.
|
|
42
43
|
- Read each ` ```tool_outputs ` block in call order. NEVER write a ` ```tool_outputs ` block yourself.
|
|
43
|
-
-
|
|
44
|
+
- Emit the ` ```tool_code ` block in full, THEN stop and halt — NEVER announce a tool then stop (e.g. halting at "Let's run `cargo clippy`" with no ` ```tool_code ` block emitted).
|
package/src/dialect/gemma.md
CHANGED
|
@@ -25,8 +25,9 @@ brief reasoning
|
|
|
25
25
|
## Rules
|
|
26
26
|
|
|
27
27
|
- `NAME` MUST match a listed function; arguments are `key:value` pairs separated by commas.
|
|
28
|
+
- String values between `<|"|>` tokens are raw literal text (no escaping); never HTML-escape them — write `a & b`, not `a & b`.
|
|
28
29
|
- Multiple calls = consecutive `<|tool_call>...<tool_call|>` blocks; keep prose outside them.
|
|
29
30
|
- The closer is `<tool_call|>` (pipe on the right), not `</tool_call>` or `<|tool_call>`.
|
|
30
31
|
- Private reasoning goes in a `<|channel>thought…<channel|>` block before any call; NEVER put tool calls inside it.
|
|
31
32
|
- Read each `<|tool_response>` block in call order. NEVER write a `<|tool_response>` block yourself.
|
|
32
|
-
-
|
|
33
|
+
- Write each call in full, THEN stop and halt — NEVER announce a tool then stop (e.g. halting at "Let's run `cargo clippy`" with no `<|tool_call>` block emitted).
|
package/src/dialect/glm.md
CHANGED
|
@@ -25,8 +25,8 @@ verbatim tool result
|
|
|
25
25
|
|
|
26
26
|
- The name after `<tool_call>` must match a listed function and sit on the same line.
|
|
27
27
|
- Emit one `<arg_key>name</arg_key>` + `<arg_value>value</arg_value>` pair per argument; omit unset optional args.
|
|
28
|
-
-
|
|
28
|
+
- `<arg_value>` bodies are read by regex (delimiter matching), NOT a real XML parser: write string values as raw literal text and never HTML-escape them (emit `a & b`, not `a & b`; `<`/`>` stay literal); only the body's own `</arg_value>` closing tag is reserved. Non-string values are valid JSON.
|
|
29
29
|
- Multiple calls are consecutive `<tool_call>…</tool_call>` blocks.
|
|
30
30
|
- Private reasoning goes in `<think>…</think>`; NEVER put tool calls inside `<think>`.
|
|
31
31
|
- Read each `<tool_response>` in call order. NEVER emit `<tool_response>` yourself.
|
|
32
|
-
-
|
|
32
|
+
- Emit the stop sequence ONLY after the call is fully written — NEVER announce a tool then stop (e.g. halting at "Let's run `cargo clippy`" with no `<tool_call>` emitted). Write the complete call, THEN the stop sequence, THEN halt.
|
package/src/dialect/harmony.md
CHANGED
|
@@ -22,9 +22,10 @@ Tool results arrive as messages authored by the function, addressed back to the
|
|
|
22
22
|
|
|
23
23
|
- Recipient is `functions.` + a listed function name.
|
|
24
24
|
- Body is one JSON object matching the schema; omit optional arguments you are not setting.
|
|
25
|
+
- Argument string values use only normal JSON string escaping (`\"`, `\\`, `\n`); never HTML-escape their contents — write `a & b`, not `a & b`.
|
|
25
26
|
- Multiple calls = consecutive call messages.
|
|
26
27
|
- An optional visible preamble is a `commentary` message ending `<|end|>`.
|
|
27
28
|
- NEVER put tool calls in `analysis`.
|
|
28
29
|
- NEVER wrap calls in Markdown/code fences.
|
|
29
30
|
- Read each tool-result message in call order. NEVER emit tool-result messages yourself.
|
|
30
|
-
-
|
|
31
|
+
- Emit the stop sequence ONLY after the call is fully written — NEVER announce a tool then stop (e.g. halting at "Let's run `cargo clippy`" with no `<|call|>` message emitted). Write the complete call, THEN the stop sequence, THEN halt.
|
package/src/dialect/harmony.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
+
import { parseJsonWithRepair } from "@oh-my-pi/pi-utils";
|
|
1
2
|
import type { Message, ToolCall } from "../types";
|
|
2
|
-
import { parseJsonWithRepair } from "../utils/json-parse";
|
|
3
3
|
import { asRecord, mintToolCallId, partialSuffixOverlapAny } from "./coercion";
|
|
4
4
|
import dialectPrompt from "./harmony.md" with { type: "text" };
|
|
5
5
|
import {
|
package/src/dialect/hermes.md
CHANGED
|
@@ -19,6 +19,7 @@ verbatim tool result
|
|
|
19
19
|
## Rules
|
|
20
20
|
|
|
21
21
|
- `name` MUST match a listed function; `arguments` is a JSON object, never a stringified JSON.
|
|
22
|
+
- Argument string values use only normal JSON string escaping (`\"`, `\\`, `\n`); never HTML-escape their contents — write `a & b`, not `a & b`.
|
|
22
23
|
- Emit multiple calls as consecutive `<tool_call>` blocks; keep any prose outside them.
|
|
23
24
|
- Read each `<tool_response>` in call order. NEVER emit `<tool_response>` yourself.
|
|
24
|
-
-
|
|
25
|
+
- Emit the stop sequence ONLY after the call is fully written — NEVER announce a tool then stop (e.g. halting at "Let's run `cargo clippy`" with no `<tool_call>` emitted). Write the complete call, THEN the stop sequence, THEN halt.
|
package/src/dialect/hermes.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
+
import { parseJsonWithRepair, parseStreamingJson } from "@oh-my-pi/pi-utils";
|
|
1
2
|
import type { Message, ToolCall } from "../types";
|
|
2
|
-
import { parseJsonWithRepair, parseStreamingJson } from "../utils/json-parse";
|
|
3
3
|
import { asRecord, mintToolCallId, partialSuffixOverlapAny } from "./coercion";
|
|
4
4
|
import dialectPrompt from "./hermes.md" with { type: "text" };
|
|
5
5
|
import { renderChatMlTranscript, renderDelimitedThinking, renderToolResponseResults, stringifyJson } from "./rendering";
|
package/src/dialect/kimi.md
CHANGED
|
@@ -17,7 +17,8 @@ verbatim tool result<|im_end|>
|
|
|
17
17
|
|
|
18
18
|
- `NAME` MUST match a listed function exactly.
|
|
19
19
|
- Arguments MUST be one JSON object with double-quoted keys.
|
|
20
|
+
- Argument string values use only normal JSON string escaping (`\"`, `\\`, `\n`); never HTML-escape their contents — write `a & b`, not `a & b`.
|
|
20
21
|
- Multiple calls = consecutive `<|tool_call_begin|>…<|tool_call_end|>` blocks in the same section; `INDEX` increments from `0`.
|
|
21
22
|
- Private reasoning, when supported, goes in `<think>…</think>` before the tool-call section; NEVER put tool calls inside `<think>`.
|
|
22
23
|
- Read each result turn in call order. NEVER emit result turns yourself.
|
|
23
|
-
-
|
|
24
|
+
- Emit the stop sequence ONLY after the call is fully written — NEVER announce a tool then stop (e.g. halting at "Let's run `cargo clippy`" with no `<|tool_call_begin|>` emitted). Write the complete call, THEN the stop sequence, THEN halt.
|
package/src/dialect/kimi.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
+
import { parseJsonWithRepair } from "@oh-my-pi/pi-utils";
|
|
1
2
|
import type { Message, ToolCall } from "../types";
|
|
2
|
-
import { parseJsonWithRepair } from "../utils/json-parse";
|
|
3
3
|
import { asRecord, normalizeKimiFunctionName, partialSuffixOverlapAny } from "./coercion";
|
|
4
4
|
import dialectPrompt from "./kimi.md" with { type: "text" };
|
|
5
5
|
import { assistantTranscriptParts, collectToolResultRun, messageContentText, stringifyJson } from "./rendering";
|
package/src/dialect/minimax.md
CHANGED
|
@@ -22,10 +22,10 @@ Results arrive later in a `<function_results>` block, one `<result>` per call (f
|
|
|
22
22
|
## Rules
|
|
23
23
|
|
|
24
24
|
- `name` MUST match a listed function.
|
|
25
|
-
- String/scalar parameters: exact text, spaces preserved. Lists/objects: JSON.
|
|
25
|
+
- String/scalar parameters: exact text, spaces preserved — bodies are read by regex (delimiter matching), NOT a real XML parser, so never HTML-escape them (emit `a & b`, not `a & b`; `<`/`>` stay literal); only the body's own `</parameter>` closing tag is reserved. Lists/objects: JSON.
|
|
26
26
|
- Multiple calls: multiple `<invoke>` blocks in one `<minimax:tool_call>`.
|
|
27
27
|
- You MAY write visible text before the calls.
|
|
28
28
|
- NEVER emit `tool_calls` JSON.
|
|
29
29
|
- NEVER use `<function_calls>` or the legacy `<tool_name>`/`<parameters>` call syntax.
|
|
30
30
|
- Read each `<result>`/`<error>` in call order. NEVER emit `<function_results>` yourself.
|
|
31
|
-
-
|
|
31
|
+
- Emit the stop sequence ONLY after the call is fully written — NEVER announce a tool then stop (e.g. halting at "Let's run `cargo clippy`" with no `<invoke>` emitted). Write the complete call, THEN the stop sequence, THEN halt.
|
package/src/dialect/pi.md
CHANGED
|
@@ -52,4 +52,4 @@ verbatim tool result
|
|
|
52
52
|
- Emit parallel calls as consecutive `§…` blocks. NEVER invent call ids; results are positional.
|
|
53
53
|
- Private reasoning goes in a `¤…¤` block before your calls; NEVER put calls inside it, and keep a literal `¤` out of the reasoning text.
|
|
54
54
|
- Read each `‡‡…‡‡` result in call order. NEVER emit a `‡‡` block yourself.
|
|
55
|
-
-
|
|
55
|
+
- Emit the stop sequence ONLY after the call is fully written — NEVER announce a tool then stop (e.g. halting at "Let's run `cargo clippy`" with no `§` call emitted). Write the complete call, THEN the stop sequence, THEN halt.
|
package/src/dialect/qwen3.md
CHANGED
|
@@ -21,7 +21,8 @@ verbatim tool result
|
|
|
21
21
|
## Rules
|
|
22
22
|
|
|
23
23
|
- `name` MUST match a listed function; `arguments` is a JSON object, never a JSON string.
|
|
24
|
+
- Argument string values use only normal JSON string escaping (`\"`, `\\`, `\n`); never HTML-escape their contents — write `a & b`, not `a & b`.
|
|
24
25
|
- Multiple calls = consecutive `<tool_call>...</tool_call>` blocks; keep prose outside them.
|
|
25
26
|
- NEVER put tool calls inside `<think>`.
|
|
26
27
|
- Read each `<tool_response>` in call order. NEVER emit `<tool_response>` yourself.
|
|
27
|
-
-
|
|
28
|
+
- Emit the stop sequence ONLY after the call is fully written — NEVER announce a tool then stop (e.g. halting at "Let's run `cargo clippy`" with no `<tool_call>` emitted). Write the complete call, THEN the stop sequence, THEN halt.
|
package/src/dialect/qwen3.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
+
import { parseJsonWithRepair } from "@oh-my-pi/pi-utils";
|
|
1
2
|
import type { Message, ToolCall } from "../types";
|
|
2
|
-
import { parseJsonWithRepair } from "../utils/json-parse";
|
|
3
3
|
import { asRecord, mintToolCallId, partialSuffixOverlapAny } from "./coercion";
|
|
4
4
|
import dialectPrompt from "./qwen3.md" with { type: "text" };
|
|
5
5
|
import { renderChatMlTranscript, renderToolResponseResults, stringifyJson } from "./rendering";
|
package/src/dialect/xml.md
CHANGED
|
@@ -17,6 +17,6 @@ verbatim tool result
|
|
|
17
17
|
## Rules
|
|
18
18
|
|
|
19
19
|
- `name` MUST match a listed function.
|
|
20
|
-
-
|
|
20
|
+
- Parameter values are read literally by regex (delimiter matching), NOT a real XML parser: write them verbatim and never HTML-escape (emit `a & b`, never `a & b`; `<`/`>` stay literal too). Only the body's own `</parameter>` closing tag is reserved. Non-string values are JSON; add `string="false"` to a parameter only to force JSON parsing of a value the schema treats as a string.
|
|
21
21
|
- Read each `<tool_response>` in call order. NEVER emit `<tool_response>` yourself.
|
|
22
|
-
-
|
|
22
|
+
- Emit the stop sequence ONLY after the call is fully written — NEVER announce a tool then stop (e.g. halting at "Let's run `cargo clippy`" with no `<invoke>` emitted). Write the complete call, THEN the stop sequence, THEN halt.
|
package/src/index.ts
CHANGED
|
@@ -13,6 +13,7 @@ export * from "./providers/anthropic-client";
|
|
|
13
13
|
export * from "./providers/azure-openai-responses";
|
|
14
14
|
export type * from "./providers/cursor";
|
|
15
15
|
export * from "./providers/gitlab-duo";
|
|
16
|
+
export * from "./providers/gitlab-duo-workflow";
|
|
16
17
|
export type * from "./providers/google";
|
|
17
18
|
export type * from "./providers/google-gemini-cli";
|
|
18
19
|
export type * from "./providers/google-vertex";
|
|
@@ -34,6 +35,7 @@ export * from "./usage/github-copilot";
|
|
|
34
35
|
export * from "./usage/google-antigravity";
|
|
35
36
|
export * from "./usage/kimi";
|
|
36
37
|
export * from "./usage/minimax-code";
|
|
38
|
+
export * from "./usage/ollama";
|
|
37
39
|
export * from "./usage/openai-codex";
|
|
38
40
|
export * from "./usage/openai-codex-reset";
|
|
39
41
|
export * from "./usage/opencode-go";
|
|
@@ -10,7 +10,14 @@
|
|
|
10
10
|
import type { Effort } from "@oh-my-pi/pi-catalog/effort";
|
|
11
11
|
import { mapEffortToAnthropicAdaptiveEffort, requireSupportedEffort } from "@oh-my-pi/pi-catalog/model-thinking";
|
|
12
12
|
import { calculateCost } from "@oh-my-pi/pi-catalog/models";
|
|
13
|
-
import {
|
|
13
|
+
import {
|
|
14
|
+
$env,
|
|
15
|
+
$flag,
|
|
16
|
+
extractHttpStatusFromError,
|
|
17
|
+
fetchWithRetry,
|
|
18
|
+
parseStreamingJson,
|
|
19
|
+
parseStreamingJsonThrottled,
|
|
20
|
+
} from "@oh-my-pi/pi-utils";
|
|
14
21
|
import { ProviderHttpError } from "../errors";
|
|
15
22
|
import type {
|
|
16
23
|
Api,
|
|
@@ -32,7 +39,6 @@ import { normalizeToolCallId, resolveCacheRetention } from "../utils";
|
|
|
32
39
|
import { AssistantMessageEventStream } from "../utils/event-stream";
|
|
33
40
|
import { appendRawHttpRequestDumpFor400, type RawHttpRequestDump } from "../utils/http-inspector";
|
|
34
41
|
import { armPreResponseTimeout, getStreamFirstEventTimeoutMs } from "../utils/idle-iterator";
|
|
35
|
-
import { parseStreamingJson, parseStreamingJsonThrottled } from "../utils/json-parse";
|
|
36
42
|
import { toolWireSchema } from "../utils/schema/wire";
|
|
37
43
|
import { invalidateAwsCredentialCache, resolveAwsCredentials } from "./aws-credentials";
|
|
38
44
|
import { decodeEventStream } from "./aws-eventstream";
|
|
@@ -135,12 +135,17 @@ export const userMessageSchema = type({
|
|
|
135
135
|
content: type("string").or(userContentBlockSchema.array()),
|
|
136
136
|
});
|
|
137
137
|
|
|
138
|
+
export const systemMessageSchema = type({
|
|
139
|
+
role: "'system'",
|
|
140
|
+
content: type("string").or(systemBlockSchema.array()),
|
|
141
|
+
});
|
|
142
|
+
|
|
138
143
|
export const assistantMessageSchema = type({
|
|
139
144
|
role: "'assistant'",
|
|
140
145
|
content: type("string").or(assistantContentBlockSchema.array()),
|
|
141
146
|
});
|
|
142
147
|
|
|
143
|
-
export const messageSchema = userMessageSchema.or(assistantMessageSchema);
|
|
148
|
+
export const messageSchema = userMessageSchema.or(assistantMessageSchema).or(systemMessageSchema);
|
|
144
149
|
|
|
145
150
|
// ─── Tools ─────────────────────────────────────────────────────────────────
|
|
146
151
|
|
|
@@ -15,6 +15,8 @@ import {
|
|
|
15
15
|
isRetryableError,
|
|
16
16
|
isUnexpectedSocketCloseMessage,
|
|
17
17
|
logger,
|
|
18
|
+
parseJsonWithRepair,
|
|
19
|
+
parseStreamingJsonThrottled,
|
|
18
20
|
readSseEvents,
|
|
19
21
|
} from "@oh-my-pi/pi-utils";
|
|
20
22
|
import { isUsageLimitError } from "../rate-limit-utils";
|
|
@@ -51,7 +53,6 @@ import { AssistantMessageEventStream } from "../utils/event-stream";
|
|
|
51
53
|
import { isFoundryEnabled } from "../utils/foundry";
|
|
52
54
|
import { finalizeErrorMessage, type RawHttpRequestDump, rewriteCopilotError } from "../utils/http-inspector";
|
|
53
55
|
import { getStreamFirstEventTimeoutMs, getStreamIdleTimeoutMs, iterateWithIdleTimeout } from "../utils/idle-iterator";
|
|
54
|
-
import { parseJsonWithRepair, parseStreamingJsonThrottled } from "../utils/json-parse";
|
|
55
56
|
import { notifyProviderResponse } from "../utils/provider-response";
|
|
56
57
|
import { isCopilotTransientModelError } from "../utils/retry";
|
|
57
58
|
import { COMBINATOR_KEYS, NO_STRICT, toolWireSchema } from "../utils/schema";
|
package/src/providers/cursor.ts
CHANGED
|
@@ -102,7 +102,13 @@ import {
|
|
|
102
102
|
WriteSuccessSchema,
|
|
103
103
|
} from "@oh-my-pi/pi-catalog/discovery/cursor-gen/agent_pb";
|
|
104
104
|
import { calculateCost } from "@oh-my-pi/pi-catalog/models";
|
|
105
|
-
import {
|
|
105
|
+
import {
|
|
106
|
+
$env,
|
|
107
|
+
extractHttpStatusFromError,
|
|
108
|
+
parseJsonWithRepair,
|
|
109
|
+
parseStreamingJson,
|
|
110
|
+
sanitizeText,
|
|
111
|
+
} from "@oh-my-pi/pi-utils";
|
|
106
112
|
import type {
|
|
107
113
|
Api,
|
|
108
114
|
AssistantMessage,
|
|
@@ -126,7 +132,6 @@ import type {
|
|
|
126
132
|
import { normalizeSystemPrompts } from "../utils";
|
|
127
133
|
import { deterministicUuid } from "../utils/deterministic-id";
|
|
128
134
|
import { AssistantMessageEventStream } from "../utils/event-stream";
|
|
129
|
-
import { parseJsonWithRepair, parseStreamingJson } from "../utils/json-parse";
|
|
130
135
|
import { connectProxiedSocket, getProxyForProvider, shouldBypassProxy } from "../utils/proxy";
|
|
131
136
|
import { createRequestDebugSession, isRequestDebugEnabled, type RequestDebugResponseLog } from "../utils/request-debug";
|
|
132
137
|
import { formatErrorMessageWithRetryAfter } from "../utils/retry-after";
|
package/src/providers/devin.ts
CHANGED
|
@@ -28,7 +28,7 @@ import {
|
|
|
28
28
|
StopReason,
|
|
29
29
|
} from "@oh-my-pi/pi-catalog/discovery/devin-gen/exa/codeium_common_pb/codeium_common_pb";
|
|
30
30
|
import { calculateCost } from "@oh-my-pi/pi-catalog/models";
|
|
31
|
-
import { extractHttpStatusFromError, logger } from "@oh-my-pi/pi-utils";
|
|
31
|
+
import { extractHttpStatusFromError, logger, parseStreamingJson } from "@oh-my-pi/pi-utils";
|
|
32
32
|
import type {
|
|
33
33
|
Api,
|
|
34
34
|
AssistantMessage,
|
|
@@ -44,7 +44,6 @@ import type {
|
|
|
44
44
|
} from "../types";
|
|
45
45
|
import { deterministicUuid } from "../utils/deterministic-id";
|
|
46
46
|
import { AssistantMessageEventStream } from "../utils/event-stream";
|
|
47
|
-
import { parseStreamingJson } from "../utils/json-parse";
|
|
48
47
|
import { formatErrorMessageWithRetryAfter } from "../utils/retry-after";
|
|
49
48
|
import { toolWireSchema } from "../utils/schema/wire";
|
|
50
49
|
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
The task below is a transcript of the conversation so far, written as a plain-text log. Turn boundaries (`<|im_start|>role` … `<|im_end|>`) and any `<ran NAME>{…}</ran>` / `<ran:result>` entries inside it are a RECORD of what already happened — past tool calls and their results. They are not a syntax for you to emit. To call a tool, use your normal structured tool-calling channel; never write `<ran …>`, `<tool_call>`, `<|im_start|>`, or similar markers as your own output.
|