@gajae-code/coding-agent 0.16.7 → 0.17.1
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 +180 -1
- package/dist/types/capability/fs.d.ts +37 -4
- package/dist/types/capability/index.d.ts +19 -0
- package/dist/types/capability/types.d.ts +9 -0
- package/dist/types/cli/doctor/args.d.ts +36 -0
- package/dist/types/cli/doctor/checks.d.ts +18 -0
- package/dist/types/cli/doctor/config-repairs.d.ts +38 -0
- package/dist/types/cli/doctor/context.d.ts +89 -0
- package/dist/types/cli/doctor/files.d.ts +27 -0
- package/dist/types/cli/doctor/ids.d.ts +20 -0
- package/dist/types/cli/doctor/install-repairs.d.ts +94 -0
- package/dist/types/cli/doctor/journal.d.ts +43 -0
- package/dist/types/cli/doctor/managed-link.d.ts +39 -0
- package/dist/types/cli/doctor/native-probe.d.ts +2 -0
- package/dist/types/cli/doctor/permission-repairs.d.ts +25 -0
- package/dist/types/cli/doctor/plugin-quarantine.d.ts +77 -0
- package/dist/types/cli/doctor/plugin-restore.d.ts +40 -0
- package/dist/types/cli/doctor/plugin-targets.d.ts +11 -0
- package/dist/types/cli/doctor/probe-client.d.ts +9 -0
- package/dist/types/cli/doctor/probe-types.d.ts +18 -0
- package/dist/types/cli/doctor/probe.d.ts +3 -0
- package/dist/types/cli/doctor/projection-probe.d.ts +2 -0
- package/dist/types/cli/doctor/repairs.d.ts +28 -0
- package/dist/types/cli/doctor/report.d.ts +27 -0
- package/dist/types/cli/doctor/runner.d.ts +4 -0
- package/dist/types/cli/doctor/safety.d.ts +10 -0
- package/dist/types/cli/doctor/service-repairs.d.ts +8 -0
- package/dist/types/cli/doctor/service-targets.d.ts +41 -0
- package/dist/types/cli/doctor/types.d.ts +145 -0
- package/dist/types/cli/doctor-cli.d.ts +7 -0
- package/dist/types/cli/doctor-supervisor.d.ts +121 -0
- package/dist/types/cli/doctor-worker.d.ts +29 -0
- package/dist/types/cli/install-activation.d.ts +158 -0
- package/dist/types/cli/macos-community-app.d.ts +41 -0
- package/dist/types/cli/mcp-cli.d.ts +0 -11
- package/dist/types/cli/update-cli.d.ts +41 -4
- package/dist/types/cli-main.d.ts +174 -0
- package/dist/types/cli.d.ts +1 -171
- package/dist/types/commands/doctor.d.ts +7 -0
- package/dist/types/commands/sdk.d.ts +17 -8
- package/dist/types/config/autorouting-tier-map.d.ts +19 -0
- package/dist/types/config/file-lock.d.ts +27 -3
- package/dist/types/config/model-preset-registry.d.ts +1 -0
- package/dist/types/config/model-registry.d.ts +12 -5
- package/dist/types/config/model-resolver.d.ts +16 -3
- package/dist/types/config/models-config-schema.d.ts +2 -0
- package/dist/types/config/settings-schema.d.ts +1 -1
- package/dist/types/coordinator-mcp/question-gate-codec.d.ts +1 -1
- package/dist/types/coordinator-mcp/session-reaper.d.ts +15 -5
- package/dist/types/cursor.d.ts +9 -9
- package/dist/types/discovery/agents-md.d.ts +6 -1
- package/dist/types/discovery/helpers.d.ts +36 -7
- package/dist/types/discovery/index.d.ts +1 -1
- package/dist/types/discovery/mcp-json.d.ts +2 -0
- package/dist/types/extensibility/extensions/loader.d.ts +22 -1
- package/dist/types/extensibility/gjc-plugins/lifecycle.d.ts +14 -1
- package/dist/types/extensibility/gjc-plugins/paths.d.ts +2 -1
- package/dist/types/extensibility/gjc-plugins/types.d.ts +25 -0
- package/dist/types/extensibility/plugins/manager.d.ts +33 -4
- package/dist/types/extensibility/plugins/marketplace/cache.d.ts +6 -0
- package/dist/types/extensibility/plugins/marketplace/manager.d.ts +186 -0
- package/dist/types/extensibility/plugins/marketplace/registry.d.ts +27 -0
- package/dist/types/extensibility/plugins/marketplace/source-resolver.d.ts +16 -1
- package/dist/types/extensibility/runtime-skill-discovery.d.ts +16 -3
- package/dist/types/gjc-runtime/autoresearch-runtime.d.ts +6 -0
- package/dist/types/gjc-runtime/launch-worktree.d.ts +53 -0
- package/dist/types/gjc-runtime/session-layout.d.ts +8 -0
- package/dist/types/gjc-runtime/session-state-lock.d.ts +15 -0
- package/dist/types/gjc-runtime/session-state-sidecar.d.ts +13 -0
- package/dist/types/gjc-runtime/ultragoal-runtime.d.ts +6 -0
- package/dist/types/main.d.ts +19 -1
- package/dist/types/modes/acp/acp-agent.d.ts +40 -0
- package/dist/types/modes/components/agent-dashboard.d.ts +1 -0
- package/dist/types/modes/components/model-selector.d.ts +2 -0
- package/dist/types/modes/interactive-mode.d.ts +1 -1
- package/dist/types/runtime-mcp/config-writer.d.ts +47 -0
- package/dist/types/runtime-mcp/policy-json-edit.d.ts +60 -0
- package/dist/types/runtime-mcp/startup-policy.d.ts +4 -0
- package/dist/types/runtime-mcp/types.d.ts +2 -2
- package/dist/types/sdk/acp/adapter.d.ts +5 -1
- package/dist/types/sdk/broker/broker.d.ts +51 -0
- package/dist/types/sdk/broker/daemon-entry.d.ts +39 -0
- package/dist/types/sdk/broker/discovery.d.ts +38 -0
- package/dist/types/sdk/broker/doctor-restart.d.ts +79 -0
- package/dist/types/sdk/broker/endpoint-authority.d.ts +7 -0
- package/dist/types/sdk/broker/ensure.d.ts +14 -0
- package/dist/types/sdk/broker/lifecycle.d.ts +2 -0
- package/dist/types/sdk/broker/process-incarnation.d.ts +50 -0
- package/dist/types/sdk/broker/runtime.d.ts +26 -0
- package/dist/types/sdk/broker/session-index.d.ts +13 -4
- package/dist/types/sdk/broker/worktree-occupancy.d.ts +14 -0
- package/dist/types/sdk/bus/chat-daemon-cli.d.ts +16 -0
- package/dist/types/sdk/bus/chat-daemon-control.d.ts +101 -6
- package/dist/types/sdk/bus/chat-daemon-runtime.d.ts +16 -0
- package/dist/types/sdk/bus/daemon-startup-exclusion.d.ts +43 -0
- package/dist/types/sdk/bus/doctor-daemon-restart-client.d.ts +51 -0
- package/dist/types/sdk/bus/doctor-daemon-restart.d.ts +39 -0
- package/dist/types/sdk/bus/index.d.ts +2 -0
- package/dist/types/sdk/bus/notification-service.d.ts +3 -0
- package/dist/types/sdk/bus/telegram-daemon-cli.d.ts +11 -0
- package/dist/types/sdk/bus/telegram-daemon-contract.d.ts +1 -1
- package/dist/types/sdk/bus/telegram-daemon-control.d.ts +5 -0
- package/dist/types/sdk/bus/telegram-daemon-owner-registry.d.ts +1 -0
- package/dist/types/sdk/bus/telegram-daemon.d.ts +36 -5
- package/dist/types/sdk/cli/session-cli.d.ts +1 -0
- package/dist/types/sdk/host/session-runtime.d.ts +4 -0
- package/dist/types/sdk/host/surface-policy.d.ts +3 -1
- package/dist/types/sdk/lifecycle/service.d.ts +44 -10
- package/dist/types/sdk/prompt-deadline-lease.d.ts +6 -3
- package/dist/types/sdk/prompt-deadline-manager.d.ts +2 -2
- package/dist/types/sdk/prompt-failure.d.ts +47 -0
- package/dist/types/sdk/prompt-status.d.ts +19 -0
- package/dist/types/sdk/router/session-router.d.ts +3 -4
- package/dist/types/sdk/service-artifact-paths.d.ts +16 -0
- package/dist/types/sdk/session-authority.d.ts +9 -0
- package/dist/types/sdk/session.d.ts +3 -1
- package/dist/types/session/agent-session.d.ts +1 -1
- package/dist/types/session/blob-store.d.ts +1 -1
- package/dist/types/session/fallback-chain-controller.d.ts +3 -6
- package/dist/types/session/internal/managed-session-scope.d.ts +44 -0
- package/dist/types/session/primary-control-surface.d.ts +4 -0
- package/dist/types/session/session-manager.d.ts +6 -0
- package/dist/types/system-prompt.d.ts +6 -0
- package/dist/types/tools/ask.d.ts +25 -0
- package/dist/types/tools/image-gen.d.ts +0 -4
- package/dist/types/tools/skill-discovery.d.ts +7 -5
- package/dist/types/tools/ultragoal-ask-guard.d.ts +7 -4
- package/dist/types/utils/changelog.d.ts +0 -9
- package/dist/types/utils/mupdf-wasm.d.ts +1 -0
- package/package.json +9 -8
- package/scripts/compile-args.ts +8 -4
- package/src/capability/fs.ts +395 -17
- package/src/capability/index.ts +273 -10
- package/src/capability/types.ts +9 -0
- package/src/cli/customize-doctor.ts +18 -12
- package/src/cli/doctor/args.ts +236 -0
- package/src/cli/doctor/checks.ts +431 -0
- package/src/cli/doctor/config-repairs.ts +517 -0
- package/src/cli/doctor/context.ts +149 -0
- package/src/cli/doctor/files.ts +149 -0
- package/src/cli/doctor/ids.ts +115 -0
- package/src/cli/doctor/install-repairs.ts +335 -0
- package/src/cli/doctor/journal.ts +423 -0
- package/src/cli/doctor/managed-link.ts +514 -0
- package/src/cli/doctor/native-probe.ts +13 -0
- package/src/cli/doctor/permission-repairs.ts +242 -0
- package/src/cli/doctor/plugin-quarantine.ts +377 -0
- package/src/cli/doctor/plugin-restore.ts +59 -0
- package/src/cli/doctor/plugin-targets.ts +373 -0
- package/src/cli/doctor/probe-client.ts +195 -0
- package/src/cli/doctor/probe-types.ts +21 -0
- package/src/cli/doctor/probe.ts +42 -0
- package/src/cli/doctor/projection-probe.ts +249 -0
- package/src/cli/doctor/repairs.ts +1157 -0
- package/src/cli/doctor/report.ts +176 -0
- package/src/cli/doctor/runner.ts +342 -0
- package/src/cli/doctor/safety.ts +40 -0
- package/src/cli/doctor/service-repairs.ts +452 -0
- package/src/cli/doctor/service-targets.ts +274 -0
- package/src/cli/doctor/types.ts +164 -0
- package/src/cli/doctor-cli.ts +62 -0
- package/src/cli/doctor-supervisor.ts +571 -0
- package/src/cli/doctor-worker.ts +181 -0
- package/src/cli/install-activation.ts +666 -0
- package/src/cli/macos-community-app.ts +1449 -0
- package/src/cli/mcp-cli.ts +11 -21
- package/src/cli/nofile-limit.ts +5 -1
- package/src/cli/plugin-cli.ts +6 -1
- package/src/cli/update-cli.ts +362 -264
- package/src/cli-main.ts +517 -0
- package/src/cli.ts +64 -433
- package/src/commands/autoresearch.ts +11 -5
- package/src/commands/completion.ts +1 -1
- package/src/commands/doctor.ts +13 -0
- package/src/commands/sdk.ts +58 -10
- package/src/commands/ultragoal.ts +11 -5
- package/src/config/autorouting-tier-map.ts +7 -0
- package/src/config/file-lock.ts +736 -71
- package/src/config/mcp-schema.json +3 -3
- package/src/config/model-preset-registry.ts +1 -0
- package/src/config/model-registry.ts +80 -27
- package/src/config/model-resolver.ts +33 -4
- package/src/config/models-config-schema.ts +2 -0
- package/src/config/settings-schema.ts +6 -2
- package/src/coordinator-mcp/question-gate-codec.ts +1 -0
- package/src/coordinator-mcp/server.ts +534 -51
- package/src/coordinator-mcp/session-reaper.ts +64 -8
- package/src/cursor.ts +223 -53
- package/src/discovery/agents-md.ts +74 -8
- package/src/discovery/agents.ts +32 -7
- package/src/discovery/builtin.ts +184 -75
- package/src/discovery/claude-plugins.ts +85 -17
- package/src/discovery/cline.ts +38 -10
- package/src/discovery/cursor.ts +19 -6
- package/src/discovery/gemini.ts +62 -22
- package/src/discovery/github.ts +13 -3
- package/src/discovery/helpers.ts +483 -89
- package/src/discovery/index.ts +1 -0
- package/src/discovery/mcp-json.ts +36 -10
- package/src/discovery/opencode.ts +36 -19
- package/src/discovery/ssh.ts +11 -8
- package/src/discovery/windsurf.ts +12 -3
- package/src/exec/bash-executor.ts +10 -3
- package/src/exec/isolated-shell.ts +15 -2
- package/src/extensibility/extensions/loader.ts +88 -26
- package/src/extensibility/gjc-plugins/lifecycle.ts +189 -0
- package/src/extensibility/gjc-plugins/paths.ts +4 -1
- package/src/extensibility/gjc-plugins/types.ts +27 -0
- package/src/extensibility/plugins/manager.ts +200 -22
- package/src/extensibility/plugins/marketplace/cache.ts +55 -2
- package/src/extensibility/plugins/marketplace/manager.ts +1262 -162
- package/src/extensibility/plugins/marketplace/registry.ts +153 -0
- package/src/extensibility/plugins/marketplace/source-resolver.ts +116 -10
- package/src/extensibility/runtime-skill-discovery.ts +61 -9
- package/src/extensibility/skill-management.ts +7 -1
- package/src/gjc-runtime/autoresearch-runtime.ts +10 -1
- package/src/gjc-runtime/launch-worktree.test.ts +248 -0
- package/src/gjc-runtime/launch-worktree.ts +275 -38
- package/src/gjc-runtime/repository-binding.ts +26 -1
- package/src/gjc-runtime/session-layout.ts +10 -0
- package/src/gjc-runtime/session-state-lock.ts +330 -23
- package/src/gjc-runtime/session-state-sidecar.ts +328 -80
- package/src/gjc-runtime/ultragoal-runtime.ts +10 -1
- package/src/harness-control-plane/session-lease.ts +2 -2
- package/src/internal-urls/docs-index.generated.ts +28 -26
- package/src/main.ts +150 -29
- package/src/memories/index.ts +24 -2
- package/src/modes/acp/acp-agent.ts +522 -68
- package/src/modes/components/agent-dashboard.ts +3 -1
- package/src/modes/components/model-selector.ts +28 -19
- package/src/modes/components/plugin-settings.ts +2 -1
- package/src/modes/controllers/selector-controller.ts +15 -9
- package/src/modes/interactive-mode.ts +21 -3
- package/src/prompts/system/system-prompt.md +5 -1
- package/src/prompts/tools/browser.md +1 -1
- package/src/prompts/tools/move-session.md +4 -0
- package/src/prompts/tools/read.md +2 -1
- package/src/prompts/tools/skill-discovery.md +6 -5
- package/src/prompts/tools/task.md +1 -0
- package/src/runtime-mcp/config-writer.ts +228 -0
- package/src/runtime-mcp/oauth-discovery.ts +114 -14
- package/src/runtime-mcp/policy-json-edit.ts +129 -0
- package/src/runtime-mcp/startup-policy.ts +14 -0
- package/src/runtime-mcp/types.ts +2 -2
- package/src/sdk/acp/adapter.ts +27 -12
- package/src/sdk/broker/broker.ts +273 -44
- package/src/sdk/broker/daemon-entry.ts +119 -0
- package/src/sdk/broker/discovery.ts +173 -20
- package/src/sdk/broker/doctor-restart.ts +206 -0
- package/src/sdk/broker/endpoint-authority.ts +36 -0
- package/src/sdk/broker/ensure.ts +49 -14
- package/src/sdk/broker/lifecycle.ts +174 -42
- package/src/sdk/broker/process-incarnation.ts +86 -2
- package/src/sdk/broker/runtime.ts +145 -21
- package/src/sdk/broker/session-index.ts +136 -22
- package/src/sdk/broker/spawn-substrate.ts +4 -1
- package/src/sdk/broker/transport.ts +5 -0
- package/src/sdk/broker/worktree-occupancy.ts +21 -1
- package/src/sdk/bus/chat-daemon-cli.ts +63 -0
- package/src/sdk/bus/chat-daemon-control.ts +260 -64
- package/src/sdk/bus/chat-daemon-runtime.ts +141 -25
- package/src/sdk/bus/daemon-startup-exclusion.ts +119 -0
- package/src/sdk/bus/doctor-daemon-restart-client.ts +291 -0
- package/src/sdk/bus/doctor-daemon-restart.ts +92 -0
- package/src/sdk/bus/index.ts +252 -51
- package/src/sdk/bus/kind-aware-reconciliation.ts +76 -41
- package/src/sdk/bus/notification-service.ts +21 -3
- package/src/sdk/bus/reconciliation-store.ts +17 -11
- package/src/sdk/bus/telegram-daemon-cli.ts +91 -5
- package/src/sdk/bus/telegram-daemon-contract.ts +1 -1
- package/src/sdk/bus/telegram-daemon-control.ts +47 -0
- package/src/sdk/bus/telegram-daemon-owner-registry.ts +1 -1
- package/src/sdk/bus/telegram-daemon.ts +178 -13
- package/src/sdk/cli/session-cli.ts +100 -12
- package/src/sdk/host/host.ts +2 -7
- package/src/sdk/host/session-runtime.test.ts +329 -8
- package/src/sdk/host/session-runtime.ts +202 -50
- package/src/sdk/host/surface-policy.ts +8 -1
- package/src/sdk/lifecycle/service.ts +199 -22
- package/src/sdk/mcp/server.ts +1 -1
- package/src/sdk/prompt-deadline-lease.ts +12 -4
- package/src/sdk/prompt-deadline-manager.ts +5 -7
- package/src/sdk/prompt-failure.ts +148 -0
- package/src/sdk/prompt-status.ts +30 -1
- package/src/sdk/prompt-watchdog.ts +11 -3
- package/src/sdk/protocol/operation-inventory.generated.json +18 -0
- package/src/sdk/protocol/operation-registry.ts +20 -8
- package/src/sdk/router/session-router.ts +8 -3
- package/src/sdk/service-artifact-paths.ts +26 -0
- package/src/sdk/session-authority.ts +10 -0
- package/src/sdk/session.ts +361 -194
- package/src/session/agent-session.ts +398 -93
- package/src/session/blob-store.ts +9 -9
- package/src/session/fallback-chain-controller.ts +3 -7
- package/src/session/internal/managed-session-scope.ts +445 -29
- package/src/session/internal/managed-session-storage.ts +38 -6
- package/src/session/primary-control-surface.ts +12 -0
- package/src/session/session-manager.ts +11 -3
- package/src/session/session-storage.ts +1 -1
- package/src/session-import/codex.ts +6 -1
- package/src/session-import/redact.ts +7 -0
- package/src/skill-state/workflow-mutation-guard.ts +645 -39
- package/src/slash-commands/builtin-registry.ts +7 -3
- package/src/system-prompt.ts +8 -0
- package/src/task/executor.ts +36 -3
- package/src/task/types.ts +27 -5
- package/src/tools/ask.ts +114 -34
- package/src/tools/browser/actions.ts +2 -2
- package/src/tools/browser/tab-worker.ts +11 -8
- package/src/tools/descriptors.ts +6 -1
- package/src/tools/fetch.ts +7 -2
- package/src/tools/image-gen.ts +33 -34
- package/src/tools/read.ts +78 -32
- package/src/tools/skill-discovery.ts +17 -7
- package/src/tools/tool-catalog.generated.ts +8 -8
- package/src/tools/ultragoal-ask-guard.ts +16 -26
- package/src/utils/changelog.ts +7 -1
- package/src/utils/git.ts +3 -1
- package/src/utils/markit.ts +24 -2
- package/src/utils/mupdf-wasm.ts +26 -0
- package/src/web/search/providers/openai-compatible.ts +191 -14
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { readSseEvents } from "@gajae-code/utils";
|
|
1
2
|
import type { ActiveSearchModelCredentials, SearchCitation, SearchResponse, SearchSource } from "../types";
|
|
2
3
|
import { SearchProviderError } from "../types";
|
|
3
4
|
import type { SearchParams } from "./base";
|
|
@@ -50,14 +51,173 @@ function normalizeResponseBody(value: unknown): JsonObject {
|
|
|
50
51
|
return { ...value, output, choices };
|
|
51
52
|
}
|
|
52
53
|
|
|
53
|
-
function
|
|
54
|
+
function parseJsonObject(text: string): JsonObject {
|
|
54
55
|
let value: unknown;
|
|
55
56
|
try {
|
|
56
57
|
value = text ? JSON.parse(text) : {};
|
|
57
58
|
} catch {
|
|
58
59
|
throw new SearchProviderError("openai-compatible", "OpenAI-compatible web search returned invalid JSON", 502);
|
|
59
60
|
}
|
|
60
|
-
|
|
61
|
+
if (!isJsonObject(value)) malformedResponse("expected a JSON object");
|
|
62
|
+
return value;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
function validateJsonSuccess(value: JsonObject, chat: boolean): JsonObject {
|
|
66
|
+
const json = normalizeResponseBody(value);
|
|
67
|
+
if (json.error != null) malformedResponse("unsuccessful response");
|
|
68
|
+
if (chat) {
|
|
69
|
+
const firstChoice = optionalArray(json.choices, "choices must be an array").find(
|
|
70
|
+
(choice, index) => isJsonObject(choice) && (choice.index === 0 || (choice.index === undefined && index === 0)),
|
|
71
|
+
);
|
|
72
|
+
if (
|
|
73
|
+
isJsonObject(firstChoice) &&
|
|
74
|
+
firstChoice.finish_reason !== undefined &&
|
|
75
|
+
firstChoice.finish_reason !== "stop"
|
|
76
|
+
) {
|
|
77
|
+
malformedResponse("unsuccessful choice completion");
|
|
78
|
+
}
|
|
79
|
+
return json;
|
|
80
|
+
}
|
|
81
|
+
if ((json.status !== undefined && json.status !== "completed") || json.incomplete_details != null) {
|
|
82
|
+
malformedResponse("unsuccessful response");
|
|
83
|
+
}
|
|
84
|
+
for (const item of optionalArray(json.output, "output must be an array")) {
|
|
85
|
+
if (isJsonObject(item) && item.status !== undefined && item.status !== "completed") {
|
|
86
|
+
malformedResponse("unsuccessful output item");
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
return json;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
function failedStreamEvent(type: unknown): boolean {
|
|
93
|
+
return type === "error" || type === "response.failed" || type === "response.incomplete";
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
async function readStreamBody(response: Response, chat: boolean, signal: AbortSignal): Promise<JsonObject> {
|
|
97
|
+
if (!response.body) malformedResponse("missing event stream");
|
|
98
|
+
const outputItems = new Map<number, JsonObject>();
|
|
99
|
+
const chunks: string[] = [];
|
|
100
|
+
const annotations: unknown[] = [];
|
|
101
|
+
let id: string | undefined;
|
|
102
|
+
let toolUsage: unknown;
|
|
103
|
+
let completed = false;
|
|
104
|
+
try {
|
|
105
|
+
for await (const event of readSseEvents(response.body, signal)) {
|
|
106
|
+
signal.throwIfAborted();
|
|
107
|
+
if (failedStreamEvent(event.event)) malformedResponse("unsuccessful stream event");
|
|
108
|
+
if (event.data === "[DONE]") break;
|
|
109
|
+
if (!event.data) continue;
|
|
110
|
+
const json = parseJsonObject(event.data);
|
|
111
|
+
if (failedStreamEvent(json.type) || json.error != null) malformedResponse("unsuccessful stream event");
|
|
112
|
+
if (!chat) {
|
|
113
|
+
const type = json.type ?? event.event;
|
|
114
|
+
if (type === "response.output_item.done") {
|
|
115
|
+
const index = json.output_index;
|
|
116
|
+
const item = json.item;
|
|
117
|
+
if (
|
|
118
|
+
typeof index !== "number" ||
|
|
119
|
+
!Number.isInteger(index) ||
|
|
120
|
+
index < 0 ||
|
|
121
|
+
!isJsonObject(item) ||
|
|
122
|
+
typeof item.type !== "string"
|
|
123
|
+
) {
|
|
124
|
+
malformedResponse("invalid completed output item");
|
|
125
|
+
}
|
|
126
|
+
if (
|
|
127
|
+
(item.status !== undefined && item.status !== "completed") ||
|
|
128
|
+
((item.type === "message" || item.type === "web_search_call") && item.status !== "completed")
|
|
129
|
+
) {
|
|
130
|
+
malformedResponse("unsuccessful output item");
|
|
131
|
+
}
|
|
132
|
+
normalizeResponseBody({ output: [item] });
|
|
133
|
+
outputItems.set(index, item);
|
|
134
|
+
continue;
|
|
135
|
+
}
|
|
136
|
+
if (type !== "response.completed" && type !== "response.done") continue;
|
|
137
|
+
const snapshot = json.response;
|
|
138
|
+
if (
|
|
139
|
+
!isJsonObject(snapshot) ||
|
|
140
|
+
snapshot.status !== "completed" ||
|
|
141
|
+
snapshot.error != null ||
|
|
142
|
+
snapshot.incomplete_details != null
|
|
143
|
+
) {
|
|
144
|
+
malformedResponse("missing successful response snapshot");
|
|
145
|
+
}
|
|
146
|
+
// Nonempty terminal output is canonical. Streaming gateways can omit
|
|
147
|
+
// it after sending completed items; reconstruct only that sparse case,
|
|
148
|
+
// never from token deltas or before a successful response terminal.
|
|
149
|
+
const output = optionalArray(snapshot.output, "output must be an array");
|
|
150
|
+
for (const item of output) {
|
|
151
|
+
if (isJsonObject(item) && item.status !== undefined && item.status !== "completed") {
|
|
152
|
+
malformedResponse("unsuccessful output item");
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
return normalizeResponseBody({
|
|
156
|
+
...snapshot,
|
|
157
|
+
output: output.length > 0 ? output : [...outputItems].sort(([a], [b]) => a - b).map(([, item]) => item),
|
|
158
|
+
});
|
|
159
|
+
}
|
|
160
|
+
if (typeof json.id === "string") id = json.id;
|
|
161
|
+
if (webSearchPerformed({ tool_usage: json.tool_usage })) toolUsage = json.tool_usage;
|
|
162
|
+
const choice = optionalArray(json.choices, "choices must be an array").find(
|
|
163
|
+
(value, index) => isJsonObject(value) && (value.index === 0 || (value.index === undefined && index === 0)),
|
|
164
|
+
);
|
|
165
|
+
if (!isJsonObject(choice)) continue;
|
|
166
|
+
if (choice.delta !== undefined && !isJsonObject(choice.delta)) malformedResponse("invalid choice delta");
|
|
167
|
+
const delta = isJsonObject(choice.delta) ? choice.delta : undefined;
|
|
168
|
+
if (delta?.content != null) {
|
|
169
|
+
if (typeof delta.content !== "string") malformedResponse("invalid choice content");
|
|
170
|
+
if (completed && delta.content) malformedResponse("content after completion");
|
|
171
|
+
chunks.push(delta.content);
|
|
172
|
+
}
|
|
173
|
+
for (const annotation of optionalArray(delta?.annotations, "choice annotations must be an array")) {
|
|
174
|
+
annotations.push(annotation);
|
|
175
|
+
}
|
|
176
|
+
if (choice.finish_reason != null) {
|
|
177
|
+
if (choice.finish_reason !== "stop") malformedResponse("unsuccessful choice completion");
|
|
178
|
+
completed = true;
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
// readSseEvents intentionally swallows aborts. Never turn one into an
|
|
182
|
+
// EOF error, or return a partial answer after a successful choice chunk.
|
|
183
|
+
signal.throwIfAborted();
|
|
184
|
+
if (!chat || !completed) malformedResponse("stream ended before successful completion");
|
|
185
|
+
// Usage-only chunks may follow finish_reason, so consume through DONE/EOF.
|
|
186
|
+
return { id, tool_usage: toolUsage, choices: [{ message: { content: chunks.join(""), annotations } }] };
|
|
187
|
+
} catch (error) {
|
|
188
|
+
signal.throwIfAborted();
|
|
189
|
+
if (
|
|
190
|
+
error instanceof SearchProviderError ||
|
|
191
|
+
(error instanceof Error && (error.name === "AbortError" || error.name === "TimeoutError"))
|
|
192
|
+
) {
|
|
193
|
+
throw error;
|
|
194
|
+
}
|
|
195
|
+
malformedResponse("invalid event stream");
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
async function cancelResponseBody(response: Response): Promise<void> {
|
|
200
|
+
// readSseEvents cancels its iterator on early return/error, propagating
|
|
201
|
+
// cancellation through its abortable pipe. Cancel bodies not owned by it too.
|
|
202
|
+
if (!response.body || response.body.locked) return;
|
|
203
|
+
try {
|
|
204
|
+
await response.body.cancel();
|
|
205
|
+
} catch {
|
|
206
|
+
// Cleanup must not replace the provider error or caller's abort reason.
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
async function readResponseText(response: Response, signal: AbortSignal): Promise<string> {
|
|
211
|
+
try {
|
|
212
|
+
signal.throwIfAborted();
|
|
213
|
+
const body = response.body?.pipeThrough(new TransformStream<Uint8Array, Uint8Array>(), { signal });
|
|
214
|
+
const text = await (body ? new Response(body).text() : response.text());
|
|
215
|
+
signal.throwIfAborted();
|
|
216
|
+
return text;
|
|
217
|
+
} catch (error) {
|
|
218
|
+
signal.throwIfAborted();
|
|
219
|
+
throw error;
|
|
220
|
+
}
|
|
61
221
|
}
|
|
62
222
|
|
|
63
223
|
/**
|
|
@@ -184,6 +344,7 @@ export class OpenAICompatibleSearchProvider extends SearchProvider {
|
|
|
184
344
|
];
|
|
185
345
|
const responsesBody = {
|
|
186
346
|
model,
|
|
347
|
+
stream: true,
|
|
187
348
|
input: messages,
|
|
188
349
|
tools: [{ type: "web_search" }],
|
|
189
350
|
temperature: params.temperature,
|
|
@@ -191,18 +352,20 @@ export class OpenAICompatibleSearchProvider extends SearchProvider {
|
|
|
191
352
|
};
|
|
192
353
|
const chatBody = {
|
|
193
354
|
model,
|
|
355
|
+
stream: true,
|
|
194
356
|
messages,
|
|
195
357
|
web_search_options: {},
|
|
196
358
|
temperature: params.temperature,
|
|
197
359
|
max_tokens: params.maxOutputTokens,
|
|
198
360
|
};
|
|
199
361
|
|
|
362
|
+
const signal = withHardTimeout(params.signal, "llm");
|
|
200
363
|
const post = (api: "openai-responses" | "openai-completions", payload: unknown) =>
|
|
201
364
|
fetch(endpoint(baseUrl, api), {
|
|
202
365
|
method: "POST",
|
|
203
366
|
headers,
|
|
204
367
|
body: JSON.stringify(payload),
|
|
205
|
-
signal
|
|
368
|
+
signal,
|
|
206
369
|
});
|
|
207
370
|
|
|
208
371
|
// Web search is a Responses-API capability: many OpenAI-compatible
|
|
@@ -211,20 +374,34 @@ export class OpenAICompatibleSearchProvider extends SearchProvider {
|
|
|
211
374
|
// stale knowledge. Prefer `/responses` regardless of the model's chat wire,
|
|
212
375
|
// and fall back to `/chat/completions` only when `/responses` is absent.
|
|
213
376
|
let response = await post("openai-responses", responsesBody);
|
|
214
|
-
|
|
377
|
+
const chat = response.status === 404 || response.status === 405;
|
|
378
|
+
if (chat) {
|
|
379
|
+
await cancelResponseBody(response);
|
|
380
|
+
signal.throwIfAborted();
|
|
215
381
|
response = await post("openai-completions", chatBody);
|
|
216
382
|
}
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
if (
|
|
221
|
-
|
|
222
|
-
this.id,
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
383
|
+
let json: JsonObject;
|
|
384
|
+
try {
|
|
385
|
+
signal.throwIfAborted();
|
|
386
|
+
if (!response.ok) {
|
|
387
|
+
const text = await readResponseText(response, signal);
|
|
388
|
+
const classified = classifyProviderHttpError(this.id, response.status, text);
|
|
389
|
+
if (classified) throw classified;
|
|
390
|
+
throw new SearchProviderError(
|
|
391
|
+
this.id,
|
|
392
|
+
`OpenAI-compatible web search error (${response.status}): ${text}`,
|
|
393
|
+
response.status,
|
|
394
|
+
);
|
|
395
|
+
}
|
|
396
|
+
const streaming =
|
|
397
|
+
response.headers.get("content-type")?.split(";", 1)[0]?.trim().toLowerCase() === "text/event-stream";
|
|
398
|
+
json = streaming
|
|
399
|
+
? await readStreamBody(response, chat, signal)
|
|
400
|
+
: validateJsonSuccess(parseJsonObject(await readResponseText(response, signal)), chat);
|
|
401
|
+
signal.throwIfAborted();
|
|
402
|
+
} finally {
|
|
403
|
+
await cancelResponseBody(response);
|
|
226
404
|
}
|
|
227
|
-
const json = parseResponseBody(text);
|
|
228
405
|
const citations = parseCitations(json);
|
|
229
406
|
const answer = textFromResponse(json);
|
|
230
407
|
const limit = params.limit ?? params.numSearchResults ?? 10;
|