@oh-my-pi/pi-coding-agent 15.1.2 → 15.1.4
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 +60 -0
- package/dist/types/async/job-manager.d.ts +3 -2
- package/dist/types/cli/auth-broker-cli.d.ts +25 -0
- package/dist/types/cli/auth-gateway-cli.d.ts +18 -0
- package/dist/types/cli/grievances-cli.d.ts +12 -0
- package/dist/types/commands/auth-broker.d.ts +54 -0
- package/dist/types/commands/auth-gateway.d.ts +32 -0
- package/dist/types/commands/grievances.d.ts +1 -1
- package/dist/types/commit/agentic/tools/propose-commit.d.ts +9 -1
- package/dist/types/commit/agentic/tools/schemas.d.ts +9 -1
- package/dist/types/commit/agentic/tools/split-commit.d.ts +9 -1
- package/dist/types/config/model-registry.d.ts +3 -0
- package/dist/types/config/models-config-schema.d.ts +1 -0
- package/dist/types/config/settings-schema.d.ts +46 -0
- package/dist/types/discovery/agents.d.ts +12 -1
- package/dist/types/edit/renderer.d.ts +3 -0
- package/dist/types/eval/index.d.ts +0 -2
- package/dist/types/goals/tools/goal-tool.d.ts +10 -2
- package/dist/types/index.d.ts +0 -1
- package/dist/types/internal-urls/index.d.ts +1 -1
- package/dist/types/internal-urls/{pi-protocol.d.ts → omp-protocol.d.ts} +3 -3
- package/dist/types/internal-urls/types.d.ts +1 -1
- package/dist/types/main.d.ts +11 -2
- package/dist/types/modes/acp/acp-agent.d.ts +2 -1
- package/dist/types/modes/acp/acp-event-mapper.d.ts +13 -1
- package/dist/types/modes/acp/acp-mode.d.ts +3 -1
- package/dist/types/modes/emoji-autocomplete.d.ts +16 -0
- package/dist/types/modes/interactive-mode.d.ts +1 -1
- package/dist/types/modes/prompt-action-autocomplete.d.ts +4 -0
- package/dist/types/plan-mode/approved-plan.d.ts +10 -4
- package/dist/types/sdk.d.ts +10 -3
- package/dist/types/session/agent-session.d.ts +7 -3
- package/dist/types/session/auth-broker-config.d.ts +13 -0
- package/dist/types/session/auth-storage.d.ts +1 -1
- package/dist/types/session/client-bridge.d.ts +3 -0
- package/dist/types/tools/eval.d.ts +41 -7
- package/dist/types/tools/irc.d.ts +8 -2
- package/dist/types/tools/report-tool-issue.d.ts +118 -1
- package/dist/types/tools/resolve.d.ts +8 -2
- package/examples/custom-tools/README.md +3 -12
- package/examples/extensions/README.md +2 -15
- package/examples/extensions/api-demo.ts +1 -7
- package/package.json +7 -7
- package/src/async/job-manager.ts +111 -13
- package/src/autoresearch/tools/init-experiment.ts +11 -33
- package/src/autoresearch/tools/log-experiment.ts +10 -24
- package/src/autoresearch/tools/run-experiment.ts +1 -1
- package/src/autoresearch/tools/update-notes.ts +2 -9
- package/src/cli/auth-broker-cli.ts +746 -0
- package/src/cli/auth-gateway-cli.ts +342 -0
- package/src/cli/grievances-cli.ts +109 -16
- package/src/cli/update-cli.ts +1 -5
- package/src/cli.ts +4 -2
- package/src/commands/auth-broker.ts +96 -0
- package/src/commands/auth-gateway.ts +61 -0
- package/src/commands/grievances.ts +13 -8
- package/src/commands/launch.ts +1 -1
- package/src/commit/agentic/agent.ts +2 -0
- package/src/commit/agentic/tools/analyze-file.ts +2 -2
- package/src/commit/agentic/tools/git-file-diff.ts +2 -2
- package/src/commit/agentic/tools/git-hunk.ts +3 -3
- package/src/commit/agentic/tools/git-overview.ts +2 -2
- package/src/commit/agentic/tools/propose-changelog.ts +1 -3
- package/src/commit/agentic/tools/recent-commits.ts +1 -1
- package/src/commit/agentic/tools/schemas.ts +1 -9
- package/src/config/model-equivalence.ts +279 -174
- package/src/config/model-registry.ts +37 -6
- package/src/config/model-resolver.ts +13 -8
- package/src/config/models-config-schema.ts +8 -0
- package/src/config/settings-schema.ts +52 -0
- package/src/cursor.ts +1 -1
- package/src/debug/log-formatting.ts +1 -1
- package/src/debug/log-viewer.ts +1 -1
- package/src/debug/profiler.ts +4 -0
- package/src/debug/raw-sse-buffer.ts +100 -59
- package/src/debug/raw-sse.ts +1 -1
- package/src/discovery/agents.ts +15 -4
- package/src/edit/modes/apply-patch.ts +1 -5
- package/src/edit/modes/patch.ts +5 -5
- package/src/edit/modes/replace.ts +5 -5
- package/src/edit/renderer.ts +2 -1
- package/src/edit/streaming.ts +1 -1
- package/src/eval/index.ts +0 -2
- package/src/eval/js/shared/runtime.ts +107 -2
- package/src/eval/py/kernel.ts +1 -1
- package/src/exa/researcher.ts +4 -4
- package/src/exa/search.ts +10 -22
- package/src/exa/websets.ts +33 -33
- package/src/extensibility/typebox.ts +44 -17
- package/src/goals/tools/goal-tool.ts +3 -3
- package/src/index.ts +0 -3
- package/src/internal-urls/docs-index.generated.ts +21 -18
- package/src/internal-urls/index.ts +1 -1
- package/src/internal-urls/{pi-protocol.ts → omp-protocol.ts} +10 -10
- package/src/internal-urls/router.ts +3 -3
- package/src/internal-urls/types.ts +1 -1
- package/src/lsp/types.ts +8 -11
- package/src/main.ts +216 -146
- package/src/mcp/tool-bridge.ts +3 -3
- package/src/modes/acp/acp-agent.ts +203 -57
- package/src/modes/acp/acp-client-bridge.ts +2 -1
- package/src/modes/acp/acp-event-mapper.ts +208 -32
- package/src/modes/acp/acp-mode.ts +11 -3
- package/src/modes/components/bash-execution.ts +1 -1
- package/src/modes/components/diff.ts +1 -2
- package/src/modes/components/eval-execution.ts +1 -1
- package/src/modes/components/oauth-selector.ts +38 -2
- package/src/modes/components/tool-execution.ts +1 -2
- package/src/modes/components/tree-selector.ts +26 -7
- package/src/modes/controllers/command-controller.ts +95 -34
- package/src/modes/controllers/input-controller.ts +4 -3
- package/src/modes/data/emojis.json +1 -0
- package/src/modes/emoji-autocomplete.ts +285 -0
- package/src/modes/interactive-mode.ts +92 -19
- package/src/modes/print-mode.ts +3 -3
- package/src/modes/prompt-action-autocomplete.ts +14 -0
- package/src/plan-mode/approved-plan.ts +30 -9
- package/src/prompts/system/system-prompt.md +1 -1
- package/src/prompts/system/ttsr-tool-reminder.md +5 -0
- package/src/prompts/tools/ask.md +4 -3
- package/src/prompts/tools/eval.md +25 -26
- package/src/prompts/tools/read.md +1 -1
- package/src/prompts/tools/resolve.md +1 -1
- package/src/prompts/tools/search.md +1 -1
- package/src/prompts/tools/web-search.md +1 -1
- package/src/sdk.ts +81 -8
- package/src/session/agent-session.ts +362 -131
- package/src/session/agent-storage.ts +7 -2
- package/src/session/auth-broker-config.ts +102 -0
- package/src/session/auth-storage.ts +7 -1
- package/src/session/client-bridge.ts +3 -0
- package/src/session/streaming-output.ts +1 -1
- package/src/task/types.ts +10 -35
- package/src/tools/bash-interactive.ts +4 -1
- package/src/tools/bash-pty-selection.ts +2 -2
- package/src/tools/browser.ts +12 -20
- package/src/tools/eval.ts +77 -100
- package/src/tools/gh.ts +21 -45
- package/src/tools/hindsight-recall.ts +1 -1
- package/src/tools/hindsight-reflect.ts +2 -2
- package/src/tools/hindsight-retain.ts +3 -7
- package/src/tools/index.ts +8 -1
- package/src/tools/inspect-image.ts +4 -1
- package/src/tools/irc.ts +4 -12
- package/src/tools/job.ts +3 -11
- package/src/tools/report-tool-issue.ts +462 -17
- package/src/tools/resolve.ts +2 -7
- package/src/tools/todo-write.ts +8 -15
- package/src/utils/title-generator.ts +3 -0
- package/src/web/search/index.ts +6 -6
- package/dist/types/eval/parse.d.ts +0 -28
- package/dist/types/eval/sniff.d.ts +0 -11
- package/src/eval/eval.lark +0 -36
- package/src/eval/parse.ts +0 -407
- package/src/eval/sniff.ts +0 -28
|
@@ -1,25 +1,22 @@
|
|
|
1
|
-
Run code in a persistent kernel using
|
|
1
|
+
Run code in a persistent kernel using a list of cells.
|
|
2
2
|
|
|
3
3
|
<instruction>
|
|
4
|
-
Each
|
|
4
|
+
Each call submits one or more cells. Cells run in array order. State persists within each language across cells **and across tool calls**.
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
*** Cell py:"optional title" t:10s rst
|
|
8
|
-
print("hi")
|
|
9
|
-
```
|
|
6
|
+
Cell fields:
|
|
10
7
|
|
|
11
|
-
-
|
|
12
|
-
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
-
|
|
16
|
-
- Stack multiple cells back-to-back; blank lines between cells are ignored.
|
|
8
|
+
- `language` — {{#if py}}`"py"` for the IPython kernel{{/if}}{{#ifAll py js}}, {{/ifAll}}{{#if js}}`"js"` for the persistent JavaScript VM{{/if}}.
|
|
9
|
+
- `code` — cell body, verbatim. Newlines, quotes, and indentation are JSON-encoded; no fences, no headers.
|
|
10
|
+
- `title` (optional) — short label shown in the transcript (e.g. `"imports"`, `"load config"`).
|
|
11
|
+
- `timeout` (optional) — per-cell timeout in seconds (1-600). Default 30.
|
|
12
|
+
- `reset` (optional) — wipe this cell's language kernel before running.{{#ifAll py js}} Reset is per-language: a `py` cell's reset does not touch the JavaScript VM and vice versa.{{/ifAll}}
|
|
17
13
|
|
|
18
14
|
**Work incrementally:**
|
|
15
|
+
|
|
19
16
|
- One logical step per cell (imports, define, test, use).
|
|
20
17
|
- Pass multiple small cells in one call.
|
|
21
18
|
- Define small reusable functions for individual debugging.
|
|
22
|
-
- Put workflow explanations in the assistant message or
|
|
19
|
+
- Put workflow explanations in the assistant message or `title` — never inside cell code.
|
|
23
20
|
{{#if py}}- Python cells run inside an IPython kernel with a live event loop. Use top-level `await` directly (e.g. `await main()`); `asyncio.run(…)` raises "cannot be called from a running event loop".{{/if}}
|
|
24
21
|
**On failure:** errors identify the failing cell (e.g., "Cell 3 failed"). Resubmit only the fixed cell (or fixed cell + remaining cells).
|
|
25
22
|
</instruction>
|
|
@@ -55,22 +52,24 @@ Cells render like a Jupyter notebook. `display(value)` renders non-presentable d
|
|
|
55
52
|
</output>
|
|
56
53
|
|
|
57
54
|
<caution>
|
|
58
|
-
- In session mode, use `rst` on a cell to wipe its language's kernel before running.{{#ifAll py js}} Reset is per-language: a python cell's `rst` does not touch the JavaScript kernel and vice versa.{{/ifAll}}
|
|
59
55
|
{{#if js}}- **js**: the VM exposes a selective `process` subset, Web APIs, `Buffer`, `fs/promises`, and the `Bun` global.
|
|
60
56
|
{{/if}}</caution>
|
|
61
57
|
|
|
62
58
|
<example>
|
|
63
|
-
{{#if py}}
|
|
64
|
-
|
|
65
|
-
|
|
59
|
+
{{#if py}}```json
|
|
60
|
+
{
|
|
61
|
+
"cells": [
|
|
62
|
+
{ "language": "py", "title": "imports", "timeout": 10, "code": "import json\nfrom pathlib import Path" },
|
|
63
|
+
{ "language": "py", "title": "load config", "code": "data = json.loads(read('package.json'))\ndisplay(data)" }
|
|
64
|
+
]
|
|
65
|
+
}
|
|
66
|
+
```{{/if}}{{#ifAll py js}}
|
|
66
67
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
{
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
return data.name;
|
|
75
|
-
{{/if}}
|
|
68
|
+
{{/ifAll}}{{#if js}}```json
|
|
69
|
+
{
|
|
70
|
+
"cells": [
|
|
71
|
+
{ "language": "js", "title": "summary", "reset": true, "code": "const data = JSON.parse(await read('package.json'));\ndisplay(data);\nreturn data.name;" }
|
|
72
|
+
]
|
|
73
|
+
}
|
|
74
|
+
```{{/if}}
|
|
76
75
|
</example>
|
|
@@ -28,7 +28,7 @@ Append `:<sel>` to `path`. The bare path falls back to the default mode.
|
|
|
28
28
|
|
|
29
29
|
- Reading a directory path returns a depth-limited dirent listing.
|
|
30
30
|
{{#if IS_HL_MODE}}
|
|
31
|
-
- Reading a file with an explicit selector returns lines prefixed with `line+hash` anchors: `41th|def alpha():`. The 2-char hash is a content fingerprint that `edit` / `apply_patch` consume — copy it verbatim, NEVER fabricate.
|
|
31
|
+
- Reading a file with an explicit selector returns lines prefixed with `line+hash` anchors: `41th|def alpha():`. The 2-char hash is a content fingerprint that `edit` / `apply_patch` consume — copy it verbatim, NEVER fabricate. The pipe character after the hash is a separator, not part of the file content.
|
|
32
32
|
{{else}}
|
|
33
33
|
{{#if IS_LINE_NUMBER_MODE}}
|
|
34
34
|
- Reading a file with an explicit selector returns lines prefixed with line numbers: `41|def alpha():`.
|
|
@@ -2,7 +2,7 @@ Resolves a pending action by either applying or discarding it.
|
|
|
2
2
|
- `action` is required:
|
|
3
3
|
- `"apply"` persists / submits the pending action.
|
|
4
4
|
- `"discard"` rejects the pending action.
|
|
5
|
-
- `reason` is required
|
|
5
|
+
- `reason` is required: one short complete sentence explaining why, starting with a capital letter and ending with a period.
|
|
6
6
|
- `extra` (optional) is free-form metadata passed to the resolving tool. Schema depends on context:
|
|
7
7
|
|
|
8
8
|
Valid whenever a pending action exists — either a preview-style staging (e.g. `ast_edit`) or a long-lived approval gate.
|
|
@@ -8,7 +8,7 @@ Searches files using powerful regex matching.
|
|
|
8
8
|
|
|
9
9
|
<output>
|
|
10
10
|
{{#if IS_HL_MODE}}
|
|
11
|
-
- Text output is anchor-prefixed: `*5th|content` (match) or ` 9x}|content` (context, leading space). The 2-char suffix is a content fingerprint.
|
|
11
|
+
- Text output is anchor-prefixed: `*5th|content` (match) or ` 9x}|content` (context, leading space). The 2-char suffix is a content fingerprint. The `|` before content is a separator, not part of the file content.
|
|
12
12
|
{{else}}
|
|
13
13
|
{{#if IS_LINE_NUMBER_MODE}}
|
|
14
14
|
- Text output is line-number-prefixed
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
Searches the web for up-to-date information beyond
|
|
1
|
+
Searches the web for up-to-date information beyond knowledge cutoff.
|
|
2
2
|
|
|
3
3
|
<instruction>
|
|
4
4
|
- You SHOULD prefer primary sources (papers, official docs) and corroborate key claims with multiple sources
|
package/src/sdk.ts
CHANGED
|
@@ -7,7 +7,13 @@ import {
|
|
|
7
7
|
INTENT_FIELD,
|
|
8
8
|
type ThinkingLevel,
|
|
9
9
|
} from "@oh-my-pi/pi-agent-core";
|
|
10
|
-
import
|
|
10
|
+
import {
|
|
11
|
+
type CredentialDisabledEvent,
|
|
12
|
+
type Message,
|
|
13
|
+
type Model,
|
|
14
|
+
type SimpleStreamOptions,
|
|
15
|
+
streamSimple,
|
|
16
|
+
} from "@oh-my-pi/pi-ai";
|
|
11
17
|
import {
|
|
12
18
|
getOpenAICodexTransportDetails,
|
|
13
19
|
prewarmOpenAICodexResponses,
|
|
@@ -93,7 +99,8 @@ import {
|
|
|
93
99
|
SecretObfuscator,
|
|
94
100
|
} from "./secrets";
|
|
95
101
|
import { AgentSession } from "./session/agent-session";
|
|
96
|
-
import {
|
|
102
|
+
import { resolveAuthBrokerConfig } from "./session/auth-broker-config";
|
|
103
|
+
import { AuthBrokerClient, AuthStorage, RemoteAuthCredentialStore } from "./session/auth-storage";
|
|
97
104
|
import { convertToLlm } from "./session/messages";
|
|
98
105
|
import { SessionManager } from "./session/session-manager";
|
|
99
106
|
import { closeAllConnections } from "./ssh/connection-manager";
|
|
@@ -317,13 +324,37 @@ function getDefaultAgentDir(): string {
|
|
|
317
324
|
// Discovery Functions
|
|
318
325
|
|
|
319
326
|
/**
|
|
320
|
-
* Create an AuthStorage instance
|
|
321
|
-
*
|
|
327
|
+
* Create an AuthStorage instance.
|
|
328
|
+
*
|
|
329
|
+
* Default: local SQLite store at `<agentDir>/agent.db`.
|
|
330
|
+
*
|
|
331
|
+
* Broker mode: when `OMP_AUTH_BROKER_URL` is set, credentials are pulled from
|
|
332
|
+
* a remote auth-broker over the wire. Refresh tokens never leave the broker;
|
|
333
|
+
* the client receives access tokens with `refresh = "__remote__"` and calls
|
|
334
|
+
* back into the broker through the {@link AuthStorageOptions.refreshOAuthCredential}
|
|
335
|
+
* override to re-mint access tokens when needed.
|
|
322
336
|
*/
|
|
323
337
|
export async function discoverAuthStorage(agentDir: string = getDefaultAgentDir()): Promise<AuthStorage> {
|
|
338
|
+
const brokerConfig = await resolveAuthBrokerConfig();
|
|
339
|
+
if (brokerConfig) {
|
|
340
|
+
const client = new AuthBrokerClient({ url: brokerConfig.url, token: brokerConfig.token });
|
|
341
|
+
const initialResult = await client.fetchSnapshot();
|
|
342
|
+
if (initialResult.status !== 200) throw new Error("Auth broker returned no initial snapshot");
|
|
343
|
+
const store = new RemoteAuthCredentialStore({ client, initialSnapshot: initialResult.snapshot });
|
|
344
|
+
// Refresh + usage hooks live on RemoteAuthCredentialStore; AuthStorage
|
|
345
|
+
// discovers them automatically when no explicit option overrides them.
|
|
346
|
+
const storage = new AuthStorage(store, {
|
|
347
|
+
configValueResolver: resolveConfigValue,
|
|
348
|
+
sourceLabel: `broker ${brokerConfig.url}`,
|
|
349
|
+
});
|
|
350
|
+
await storage.reload();
|
|
351
|
+
return storage;
|
|
352
|
+
}
|
|
324
353
|
const dbPath = getAgentDbPath(agentDir);
|
|
325
|
-
|
|
326
|
-
|
|
354
|
+
const storage = await AuthStorage.create(dbPath, {
|
|
355
|
+
configValueResolver: resolveConfigValue,
|
|
356
|
+
sourceLabel: `local ${dbPath}`,
|
|
357
|
+
});
|
|
327
358
|
await storage.reload();
|
|
328
359
|
return storage;
|
|
329
360
|
}
|
|
@@ -885,6 +916,13 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {}
|
|
|
885
916
|
thinkingLevel = logger.time("resolveThinkingLevelForModel", () =>
|
|
886
917
|
resolveThinkingLevelForModel(resolvedModel, thinkingLevel),
|
|
887
918
|
);
|
|
919
|
+
// Fire-and-forget TLS+H2 handshake to the model's host so it overlaps
|
|
920
|
+
// with the rest of session setup (extension/skill load, tool registry,
|
|
921
|
+
// system prompt build). Without this, the first `fetch(...)` pays the
|
|
922
|
+
// full handshake serially — 100–300 ms transcontinental for
|
|
923
|
+
// api.anthropic.com from a residential IP. Every mode benefits
|
|
924
|
+
// (interactive, print, rpc, acp).
|
|
925
|
+
preconnectModelHost(model.baseUrl);
|
|
888
926
|
}
|
|
889
927
|
|
|
890
928
|
let skills: Skill[];
|
|
@@ -1032,7 +1070,9 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {}
|
|
|
1032
1070
|
return undefined;
|
|
1033
1071
|
};
|
|
1034
1072
|
const toolSession: ToolSession = {
|
|
1035
|
-
cwd
|
|
1073
|
+
get cwd() {
|
|
1074
|
+
return sessionManager.getCwd();
|
|
1075
|
+
},
|
|
1036
1076
|
hasUI: options.hasUI ?? false,
|
|
1037
1077
|
enableLsp,
|
|
1038
1078
|
get hasEditTool() {
|
|
@@ -1763,6 +1803,18 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {}
|
|
|
1763
1803
|
}
|
|
1764
1804
|
return key;
|
|
1765
1805
|
},
|
|
1806
|
+
streamFn: (streamModel, context, streamOptions) =>
|
|
1807
|
+
streamSimple(streamModel, context, {
|
|
1808
|
+
...streamOptions,
|
|
1809
|
+
onAuthError: async (provider, oldKey, error) => {
|
|
1810
|
+
await modelRegistry.authStorage.invalidateCredentialMatching(provider, oldKey, streamOptions?.signal);
|
|
1811
|
+
logger.debug("Retrying provider request after credential invalidation", {
|
|
1812
|
+
provider,
|
|
1813
|
+
error: error instanceof Error ? error.message : String(error),
|
|
1814
|
+
});
|
|
1815
|
+
return modelRegistry.getApiKeyForProvider(provider, agent.sessionId);
|
|
1816
|
+
},
|
|
1817
|
+
}),
|
|
1766
1818
|
cursorExecHandlers,
|
|
1767
1819
|
transformToolCallArguments: (args, _toolName) => {
|
|
1768
1820
|
let result = args;
|
|
@@ -1899,8 +1951,12 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {}
|
|
|
1899
1951
|
}
|
|
1900
1952
|
|
|
1901
1953
|
// Start LSP warmup in the background so startup does not block on language server initialization.
|
|
1954
|
+
// Print/script invocations (`hasUI=false`) don't render the warmup status indicator AND typically
|
|
1955
|
+
// finish before LSP servers would have stabilized — warming them just spends CPU parsing big
|
|
1956
|
+
// `initialize` responses concurrently with the LLM stream consumer, jittering perceived latency.
|
|
1957
|
+
// Tools that need an LSP server still spin one up on demand through `getOrCreateClient`.
|
|
1902
1958
|
let lspServers: CreateAgentSessionResult["lspServers"];
|
|
1903
|
-
if (enableLsp && settings.get("lsp.diagnosticsOnWrite")) {
|
|
1959
|
+
if (enableLsp && options.hasUI && settings.get("lsp.diagnosticsOnWrite")) {
|
|
1904
1960
|
lspServers = discoverStartupLspServers(cwd);
|
|
1905
1961
|
if (lspServers.length > 0) {
|
|
1906
1962
|
void (async () => {
|
|
@@ -2017,3 +2073,20 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {}
|
|
|
2017
2073
|
throw error;
|
|
2018
2074
|
}
|
|
2019
2075
|
}
|
|
2076
|
+
|
|
2077
|
+
/**
|
|
2078
|
+
* Best-effort preconnect to the model's API host. Bun's `fetch.preconnect`
|
|
2079
|
+
* primes DNS + TCP + TLS + H2 so the first real request reuses the warm
|
|
2080
|
+
* connection. Errors are swallowed: preconnect is an optimization, never a
|
|
2081
|
+
* hard dependency.
|
|
2082
|
+
*/
|
|
2083
|
+
function preconnectModelHost(baseUrl: string | undefined): void {
|
|
2084
|
+
if (!baseUrl) return;
|
|
2085
|
+
const preconnect = (globalThis.fetch as typeof fetch & { preconnect?: (url: string) => void }).preconnect;
|
|
2086
|
+
if (typeof preconnect !== "function") return;
|
|
2087
|
+
try {
|
|
2088
|
+
preconnect(baseUrl);
|
|
2089
|
+
} catch {
|
|
2090
|
+
// Best effort.
|
|
2091
|
+
}
|
|
2092
|
+
}
|