@coseung2/opencodex 2.8.0-cs.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/LICENSE +21 -0
- package/README.md +219 -0
- package/assets/architecture.png +0 -0
- package/assets/banner.png +0 -0
- package/assets/claude-code-models.gif +0 -0
- package/assets/codex-app-picker.png +0 -0
- package/bin/ocx-notch.mjs +78 -0
- package/bin/ocx.mjs +454 -0
- package/bin/package-main.mjs +9 -0
- package/gui/dist/assets/index-CAnnes06.js +67 -0
- package/gui/dist/assets/index-OY43ubAq.css +1 -0
- package/gui/dist/favicon.png +0 -0
- package/gui/dist/icons.svg +24 -0
- package/gui/dist/index.html +25 -0
- package/gui/dist/logo.png +0 -0
- package/gui/dist/provider-icons/alibaba-color.svg +1 -0
- package/gui/dist/provider-icons/antigravity-color.svg +1 -0
- package/gui/dist/provider-icons/antigravity.svg +1 -0
- package/gui/dist/provider-icons/claude-color.svg +1 -0
- package/gui/dist/provider-icons/claude.svg +1 -0
- package/gui/dist/provider-icons/cloudflare-ai-gateway-color.svg +1 -0
- package/gui/dist/provider-icons/copilot-color.svg +1 -0
- package/gui/dist/provider-icons/copilot.svg +1 -0
- package/gui/dist/provider-icons/cursor-color.svg +2 -0
- package/gui/dist/provider-icons/cursor.svg +2 -0
- package/gui/dist/provider-icons/deepseek-color.svg +1 -0
- package/gui/dist/provider-icons/discord.svg +1 -0
- package/gui/dist/provider-icons/firepass-color.svg +1 -0
- package/gui/dist/provider-icons/fireworks-color.svg +1 -0
- package/gui/dist/provider-icons/gemini-color.svg +1 -0
- package/gui/dist/provider-icons/gemini.svg +1 -0
- package/gui/dist/provider-icons/github-copilot-color.svg +1 -0
- package/gui/dist/provider-icons/gitlab-duo-color.svg +1 -0
- package/gui/dist/provider-icons/grok-color.svg +1 -0
- package/gui/dist/provider-icons/grok.svg +1 -0
- package/gui/dist/provider-icons/groq-color.svg +1 -0
- package/gui/dist/provider-icons/huggingface-color.svg +1 -0
- package/gui/dist/provider-icons/kimi-color.svg +1 -0
- package/gui/dist/provider-icons/kiro-color.svg +15 -0
- package/gui/dist/provider-icons/kiro.svg +14 -0
- package/gui/dist/provider-icons/lm-studio-color.svg +1 -0
- package/gui/dist/provider-icons/mistral-color.svg +1 -0
- package/gui/dist/provider-icons/moonshot-color.svg +1 -0
- package/gui/dist/provider-icons/nvidia-color.svg +1 -0
- package/gui/dist/provider-icons/ollama-color.svg +1 -0
- package/gui/dist/provider-icons/openai.svg +1 -0
- package/gui/dist/provider-icons/opencode.svg +1 -0
- package/gui/dist/provider-icons/openrouter-color.svg +1 -0
- package/gui/dist/provider-icons/pi.svg +21 -0
- package/gui/dist/provider-icons/qianfan-color.svg +1 -0
- package/gui/dist/provider-icons/qwen-portal-color.svg +1 -0
- package/gui/dist/provider-icons/telegram.svg +1 -0
- package/gui/dist/provider-icons/vercel-ai-gateway-color.svg +1 -0
- package/gui/dist/provider-icons/vllm-color.svg +1 -0
- package/gui/dist/provider-icons/xiaomi-color.svg +1 -0
- package/package.json +107 -0
- package/packages/ocx-notch/README.md +55 -0
- package/packages/ocx-notch/THIRD_PARTY_NOTICES.md +45 -0
- package/src/AGENTS.md +28 -0
- package/src/adapters/anthropic-image-guard.ts +251 -0
- package/src/adapters/anthropic-image-normalize.ts +518 -0
- package/src/adapters/anthropic.ts +1003 -0
- package/src/adapters/azure.ts +36 -0
- package/src/adapters/base.ts +72 -0
- package/src/adapters/client-fingerprint.ts +59 -0
- package/src/adapters/cursor/arg-codec.ts +38 -0
- package/src/adapters/cursor/arg-normalize.ts +104 -0
- package/src/adapters/cursor/cursor-errors.ts +165 -0
- package/src/adapters/cursor/discovery.ts +276 -0
- package/src/adapters/cursor/effort-map.ts +127 -0
- package/src/adapters/cursor/exec-policy.ts +88 -0
- package/src/adapters/cursor/framing.ts +211 -0
- package/src/adapters/cursor/gen/agent_pb.ts +15274 -0
- package/src/adapters/cursor/kv-store.ts +52 -0
- package/src/adapters/cursor/live-models.ts +153 -0
- package/src/adapters/cursor/live-smoke-gate.ts +41 -0
- package/src/adapters/cursor/live-transport.ts +1214 -0
- package/src/adapters/cursor/mcp-config.ts +42 -0
- package/src/adapters/cursor/mcp-manager.ts +333 -0
- package/src/adapters/cursor/message-mapper.ts +49 -0
- package/src/adapters/cursor/native-exec-common.ts +55 -0
- package/src/adapters/cursor/native-exec-desktop.ts +184 -0
- package/src/adapters/cursor/native-exec-fs.ts +329 -0
- package/src/adapters/cursor/native-exec-mcp.ts +153 -0
- package/src/adapters/cursor/native-exec-network.ts +43 -0
- package/src/adapters/cursor/native-exec-shell.ts +548 -0
- package/src/adapters/cursor/native-exec-tools.ts +118 -0
- package/src/adapters/cursor/native-exec.ts +576 -0
- package/src/adapters/cursor/protobuf-events.ts +563 -0
- package/src/adapters/cursor/protobuf-request.ts +714 -0
- package/src/adapters/cursor/request-builder.ts +255 -0
- package/src/adapters/cursor/thread-continuity.ts +67 -0
- package/src/adapters/cursor/tool-definitions.ts +505 -0
- package/src/adapters/cursor/transport-retry.ts +132 -0
- package/src/adapters/cursor/transport.ts +57 -0
- package/src/adapters/cursor/types.ts +52 -0
- package/src/adapters/cursor.ts +196 -0
- package/src/adapters/google-antigravity-replay.ts +303 -0
- package/src/adapters/google-antigravity-wire.ts +108 -0
- package/src/adapters/google-errors.ts +85 -0
- package/src/adapters/google-http.ts +100 -0
- package/src/adapters/google-tool-schema.ts +173 -0
- package/src/adapters/google-truncation.ts +13 -0
- package/src/adapters/google-wire-compiler.ts +232 -0
- package/src/adapters/google.ts +758 -0
- package/src/adapters/identity.ts +44 -0
- package/src/adapters/image.ts +23 -0
- package/src/adapters/kiro-constants.ts +16 -0
- package/src/adapters/kiro-errors.ts +197 -0
- package/src/adapters/kiro-events.ts +179 -0
- package/src/adapters/kiro-images.ts +129 -0
- package/src/adapters/kiro-retry.ts +312 -0
- package/src/adapters/kiro-thinking.ts +96 -0
- package/src/adapters/kiro-tool-fallback.ts +36 -0
- package/src/adapters/kiro-tools.ts +215 -0
- package/src/adapters/kiro-truncation.ts +33 -0
- package/src/adapters/kiro-wire.ts +129 -0
- package/src/adapters/kiro.ts +1898 -0
- package/src/adapters/mimo-free.ts +263 -0
- package/src/adapters/openai-chat.ts +1005 -0
- package/src/adapters/openai-responses.ts +1137 -0
- package/src/adapters/run-turn-queue.ts +114 -0
- package/src/adapters/tool-catalog-nudge.ts +71 -0
- package/src/adapters/upstream-http-error.ts +48 -0
- package/src/bridge.ts +1619 -0
- package/src/chat/inbound.ts +295 -0
- package/src/chat/outbound.ts +765 -0
- package/src/claude/agents-inject.ts +243 -0
- package/src/claude/alias.ts +149 -0
- package/src/claude/auth-detect.ts +229 -0
- package/src/claude/auth-mode-migration.ts +32 -0
- package/src/claude/auth-mode.ts +62 -0
- package/src/claude/context-windows.ts +189 -0
- package/src/claude/desktop-3p-guard.ts +35 -0
- package/src/claude/desktop-3p-paths.ts +84 -0
- package/src/claude/desktop-3p.ts +381 -0
- package/src/claude/desktop-health.ts +26 -0
- package/src/claude/desktop-profile.ts +263 -0
- package/src/claude/gateway-cache.ts +70 -0
- package/src/claude/inbound-debug.ts +163 -0
- package/src/claude/inbound.ts +509 -0
- package/src/claude/model-info.ts +151 -0
- package/src/claude/outbound.ts +872 -0
- package/src/cli/access.ts +108 -0
- package/src/cli/account-api.ts +268 -0
- package/src/cli/account-auth.ts +223 -0
- package/src/cli/account-extended.ts +350 -0
- package/src/cli/account.ts +275 -0
- package/src/cli/agent-driven.ts +70 -0
- package/src/cli/agent.ts +184 -0
- package/src/cli/catalog-prewarm.ts +27 -0
- package/src/cli/claude-desktop.ts +188 -0
- package/src/cli/claude.ts +286 -0
- package/src/cli/codex-shim-autorestore.ts +45 -0
- package/src/cli/combo.ts +119 -0
- package/src/cli/config-command.ts +145 -0
- package/src/cli/debug.ts +228 -0
- package/src/cli/doctor.ts +930 -0
- package/src/cli/export-command.ts +187 -0
- package/src/cli/help.ts +330 -0
- package/src/cli/index.ts +1103 -0
- package/src/cli/init.ts +224 -0
- package/src/cli/integrations.ts +142 -0
- package/src/cli/interactive-confirm.ts +133 -0
- package/src/cli/internal-dispatch.ts +20 -0
- package/src/cli/models-runtime.ts +212 -0
- package/src/cli/models.ts +336 -0
- package/src/cli/observe.ts +117 -0
- package/src/cli/opencode.ts +586 -0
- package/src/cli/provider-runtime.ts +162 -0
- package/src/cli/provider.ts +463 -0
- package/src/cli/runtime-api.ts +325 -0
- package/src/cli/star-prompt.ts +134 -0
- package/src/cli/status-oauth.ts +78 -0
- package/src/cli/status.ts +321 -0
- package/src/cli/system-command.ts +114 -0
- package/src/cli/tray-proxy.ts +52 -0
- package/src/cli/v2.ts +173 -0
- package/src/cli.ts +10 -0
- package/src/clients/config-export.ts +377 -0
- package/src/codex/account-id.ts +34 -0
- package/src/codex/account-label.ts +34 -0
- package/src/codex/account-lifecycle.ts +55 -0
- package/src/codex/account-namespace-match.ts +63 -0
- package/src/codex/account-namespaces.ts +149 -0
- package/src/codex/account-pause.ts +20 -0
- package/src/codex/account-runtime-state.ts +31 -0
- package/src/codex/account-store.ts +517 -0
- package/src/codex/account-usability.ts +20 -0
- package/src/codex/app-server-processes.ts +756 -0
- package/src/codex/auth-api.ts +1540 -0
- package/src/codex/auth-collision.ts +107 -0
- package/src/codex/auth-context.ts +352 -0
- package/src/codex/autostart-health.ts +149 -0
- package/src/codex/catalog/aggregation.ts +378 -0
- package/src/codex/catalog/bundled.ts +251 -0
- package/src/codex/catalog/effort.ts +355 -0
- package/src/codex/catalog/metadata.ts +180 -0
- package/src/codex/catalog/parsing.ts +456 -0
- package/src/codex/catalog/provider-fetch.ts +902 -0
- package/src/codex/catalog/sync.ts +620 -0
- package/src/codex/catalog.ts +12 -0
- package/src/codex/data/upstream-models.json +830 -0
- package/src/codex/exec-invocation.ts +22 -0
- package/src/codex/features.ts +969 -0
- package/src/codex/history-migration-guardian.ts +102 -0
- package/src/codex/history-provider.ts +776 -0
- package/src/codex/home.ts +206 -0
- package/src/codex/inject.ts +799 -0
- package/src/codex/injected-marker.ts +72 -0
- package/src/codex/journal.ts +163 -0
- package/src/codex/main-account-cache.ts +32 -0
- package/src/codex/main-account.ts +40 -0
- package/src/codex/model-cache.ts +227 -0
- package/src/codex/paths.ts +65 -0
- package/src/codex/plugins-doctor.ts +242 -0
- package/src/codex/pool-rotation.ts +225 -0
- package/src/codex/project-config-warnings.ts +411 -0
- package/src/codex/quota.ts +411 -0
- package/src/codex/refresh.ts +53 -0
- package/src/codex/routing.ts +1477 -0
- package/src/codex/runtime.ts +538 -0
- package/src/codex/shim.ts +1189 -0
- package/src/codex/subagent-defaults.ts +550 -0
- package/src/codex/subagent-model-fallback.ts +469 -0
- package/src/codex/sync.ts +130 -0
- package/src/codex/warmup.ts +192 -0
- package/src/codex/websocket-registry.ts +100 -0
- package/src/combos/failover.ts +140 -0
- package/src/combos/index.ts +41 -0
- package/src/combos/request.ts +62 -0
- package/src/combos/resolve.ts +232 -0
- package/src/combos/types.ts +326 -0
- package/src/config.ts +2355 -0
- package/src/generated/jawcode-model-metadata.ts +104 -0
- package/src/github/star-state.ts +203 -0
- package/src/grok/inject.ts +519 -0
- package/src/grok/status.ts +121 -0
- package/src/grok/sync.ts +66 -0
- package/src/images/artifacts.ts +516 -0
- package/src/images/fulfill-video.ts +163 -0
- package/src/images/fulfill.ts +149 -0
- package/src/images/index.ts +4 -0
- package/src/images/loop.ts +829 -0
- package/src/images/plan.ts +133 -0
- package/src/images/synthetic-tool.ts +133 -0
- package/src/images/types.ts +41 -0
- package/src/images/xai-client.ts +141 -0
- package/src/images/xai-video-client.ts +163 -0
- package/src/index.ts +22 -0
- package/src/lib/abort.ts +146 -0
- package/src/lib/admin-secrets.ts +25 -0
- package/src/lib/admission.ts +83 -0
- package/src/lib/app-owned-memory-stores.ts +173 -0
- package/src/lib/app-owned-memory.ts +265 -0
- package/src/lib/bounded-body.ts +202 -0
- package/src/lib/bun-binary-validator.d.mts +3 -0
- package/src/lib/bun-binary-validator.mjs +18 -0
- package/src/lib/bun-runtime.ts +71 -0
- package/src/lib/bun-stream-caps.ts +126 -0
- package/src/lib/config-ownership.ts +360 -0
- package/src/lib/crash-guard.ts +344 -0
- package/src/lib/debug-log-buffer.ts +83 -0
- package/src/lib/debug-settings.ts +108 -0
- package/src/lib/debug.ts +31 -0
- package/src/lib/destination-policy.ts +316 -0
- package/src/lib/errors.ts +364 -0
- package/src/lib/eventstream-decoder.ts +253 -0
- package/src/lib/gcp-adc.ts +341 -0
- package/src/lib/injection-debug-log.ts +58 -0
- package/src/lib/open-url.ts +25 -0
- package/src/lib/pinned-http.ts +151 -0
- package/src/lib/privacy.ts +20 -0
- package/src/lib/process-control.ts +165 -0
- package/src/lib/provider-outbound.ts +170 -0
- package/src/lib/provider-url.ts +14 -0
- package/src/lib/proxy-env.ts +18 -0
- package/src/lib/redact.ts +105 -0
- package/src/lib/retry-after.ts +55 -0
- package/src/lib/service-secrets.ts +25 -0
- package/src/lib/shadow-call.ts +30 -0
- package/src/lib/sidecar-tracker.ts +52 -0
- package/src/lib/sse-decoder.ts +323 -0
- package/src/lib/state-store-registrations.ts +109 -0
- package/src/lib/state-store-sweeper.ts +184 -0
- package/src/lib/test-home-guard.ts +90 -0
- package/src/lib/token-estimate.ts +69 -0
- package/src/lib/translator-budget.ts +356 -0
- package/src/lib/upstream-retry.ts +239 -0
- package/src/lib/win-exec.ts +115 -0
- package/src/lib/win-paths.ts +68 -0
- package/src/lib/windows-elevation.ts +705 -0
- package/src/lib/windows-secret-acl.ts +514 -0
- package/src/lib/winsw.ts +375 -0
- package/src/oauth/anthropic-routing.ts +594 -0
- package/src/oauth/anthropic.ts +177 -0
- package/src/oauth/callback-server.ts +294 -0
- package/src/oauth/chatgpt.ts +150 -0
- package/src/oauth/cursor.ts +211 -0
- package/src/oauth/github-copilot.ts +428 -0
- package/src/oauth/google-antigravity.ts +230 -0
- package/src/oauth/health.ts +399 -0
- package/src/oauth/index.ts +1173 -0
- package/src/oauth/key-providers.ts +108 -0
- package/src/oauth/kimi.ts +213 -0
- package/src/oauth/kiro-credentials.ts +726 -0
- package/src/oauth/kiro.ts +577 -0
- package/src/oauth/local-token-detect.ts +121 -0
- package/src/oauth/log.ts +48 -0
- package/src/oauth/login-cli.ts +163 -0
- package/src/oauth/pkce.ts +15 -0
- package/src/oauth/store.ts +630 -0
- package/src/oauth/token-guardian.ts +303 -0
- package/src/oauth/types.ts +62 -0
- package/src/oauth/xai.ts +241 -0
- package/src/providers/alibaba-region-backup.ts +75 -0
- package/src/providers/alibaba-region-migration.ts +156 -0
- package/src/providers/alibaba-region-startup.ts +36 -0
- package/src/providers/antigravity-models.ts +205 -0
- package/src/providers/api-keys.ts +140 -0
- package/src/providers/base-url-choices.ts +64 -0
- package/src/providers/context-cap.ts +65 -0
- package/src/providers/derive.ts +339 -0
- package/src/providers/free-directory.ts +184 -0
- package/src/providers/github-copilot-transport.ts +56 -0
- package/src/providers/key-failover.ts +203 -0
- package/src/providers/kiro-models.ts +67 -0
- package/src/providers/label.ts +19 -0
- package/src/providers/model-discovery.ts +356 -0
- package/src/providers/openai-sidecar.ts +175 -0
- package/src/providers/openai-tier-startup.ts +27 -0
- package/src/providers/openai-tiers.ts +301 -0
- package/src/providers/openai-virtual-models.ts +82 -0
- package/src/providers/openrouter-routing.ts +102 -0
- package/src/providers/provider-id-rewrite.ts +150 -0
- package/src/providers/quota.ts +1045 -0
- package/src/providers/registry.ts +1600 -0
- package/src/providers/slug-codec.ts +67 -0
- package/src/providers/xai-transport.ts +141 -0
- package/src/reasoning-effort.ts +135 -0
- package/src/responses/compaction.ts +117 -0
- package/src/responses/parser.ts +656 -0
- package/src/responses/reasoning-envelope.ts +52 -0
- package/src/responses/schema.ts +159 -0
- package/src/responses/spill-store.ts +394 -0
- package/src/responses/state.ts +895 -0
- package/src/responses/tool-groups.ts +19 -0
- package/src/router.ts +425 -0
- package/src/server/adapter-resolve.ts +80 -0
- package/src/server/auth-cors.ts +530 -0
- package/src/server/chat-completions.ts +368 -0
- package/src/server/claude-messages.ts +914 -0
- package/src/server/effort-policy.ts +172 -0
- package/src/server/gui-static.ts +123 -0
- package/src/server/image-retry.ts +42 -0
- package/src/server/images.ts +476 -0
- package/src/server/index.ts +1126 -0
- package/src/server/lifecycle.ts +305 -0
- package/src/server/live.ts +598 -0
- package/src/server/management/agent-settings-routes.ts +1039 -0
- package/src/server/management/api-access.ts +141 -0
- package/src/server/management/api-key-usage.ts +167 -0
- package/src/server/management/body.ts +35 -0
- package/src/server/management/combo-routes.ts +220 -0
- package/src/server/management/config-routes.ts +422 -0
- package/src/server/management/context.ts +31 -0
- package/src/server/management/logs-usage-routes.ts +516 -0
- package/src/server/management/model-routes.ts +525 -0
- package/src/server/management/oauth-account-routes.ts +561 -0
- package/src/server/management/provider-routes.ts +556 -0
- package/src/server/management/shared.ts +277 -0
- package/src/server/management/sidebar-routes.ts +88 -0
- package/src/server/management/system-restart.ts +179 -0
- package/src/server/management/system-routes.ts +117 -0
- package/src/server/management/usage-summary-cache.ts +86 -0
- package/src/server/management-api.ts +211 -0
- package/src/server/management-auth.ts +267 -0
- package/src/server/memory-watchdog.ts +156 -0
- package/src/server/port-reclaim.ts +307 -0
- package/src/server/ports.ts +116 -0
- package/src/server/proxy-liveness.ts +201 -0
- package/src/server/relay-eager.ts +313 -0
- package/src/server/relay.ts +1060 -0
- package/src/server/request-decompress.ts +132 -0
- package/src/server/request-log-conversation.ts +168 -0
- package/src/server/request-log.ts +1046 -0
- package/src/server/responses/collaboration.ts +354 -0
- package/src/server/responses/compact.ts +384 -0
- package/src/server/responses/core.ts +2756 -0
- package/src/server/responses/encrypted-payload.ts +308 -0
- package/src/server/responses/fetch-helpers.ts +157 -0
- package/src/server/responses/passthrough-error.ts +78 -0
- package/src/server/responses/terminal-guard.ts +230 -0
- package/src/server/responses/upstream-error.ts +48 -0
- package/src/server/responses-image-gen-repair.ts +132 -0
- package/src/server/responses-item-id-repair.ts +224 -0
- package/src/server/responses.ts +9 -0
- package/src/server/search.ts +136 -0
- package/src/server/sse-payload-rewrite.ts +175 -0
- package/src/server/startup-action-control.ts +308 -0
- package/src/server/startup-health-cache.ts +113 -0
- package/src/server/system-env.ts +413 -0
- package/src/server/windows-tcp-drop.ts +184 -0
- package/src/server/windows-tray-control.ts +41 -0
- package/src/server/ws-bridge.ts +471 -0
- package/src/service.ts +2554 -0
- package/src/stall-timeout.ts +20 -0
- package/src/storage/cleanup-job.ts +57 -0
- package/src/storage/cleanup.ts +3085 -0
- package/src/storage/policy-job.ts +457 -0
- package/src/storage/policy-scheduler.ts +40 -0
- package/src/storage/policy-worker.ts +59 -0
- package/src/storage/policy.ts +527 -0
- package/src/storage/restore-job.ts +299 -0
- package/src/storage/restore-worker.ts +58 -0
- package/src/storage/scanner.ts +238 -0
- package/src/storage/storage-mutation-coordinator.ts +139 -0
- package/src/storage/worker-lifecycle.ts +215 -0
- package/src/tray/assets/opencodex-tray-offline.ico +0 -0
- package/src/tray/assets/opencodex-tray-online.ico +0 -0
- package/src/tray/assets/opencodex-tray-warning.ico +0 -0
- package/src/tray/assets/opencodex-tray.png +0 -0
- package/src/tray/windows-tray.ps1 +290 -0
- package/src/tray/windows.ts +730 -0
- package/src/types.ts +1237 -0
- package/src/update/badge.ts +72 -0
- package/src/update/index.ts +392 -0
- package/src/update/job.ts +1513 -0
- package/src/update/notify.ts +257 -0
- package/src/update/npm-invocation.d.mts +23 -0
- package/src/update/npm-invocation.mjs +94 -0
- package/src/update/tray-update-plan.d.mts +18 -0
- package/src/update/tray-update-plan.mjs +38 -0
- package/src/usage/cost.ts +0 -0
- package/src/usage/debug.ts +97 -0
- package/src/usage/expected-prices.ts +164 -0
- package/src/usage/log.ts +658 -0
- package/src/usage/summary.ts +585 -0
- package/src/usage/totals.ts +14 -0
- package/src/vision/anthropic-describe.ts +185 -0
- package/src/vision/describe.ts +125 -0
- package/src/vision/index.ts +467 -0
- package/src/web-search/anthropic-executor.ts +189 -0
- package/src/web-search/executor.ts +105 -0
- package/src/web-search/format-result.ts +89 -0
- package/src/web-search/index.ts +196 -0
- package/src/web-search/loop.ts +664 -0
- package/src/web-search/parse.ts +220 -0
- package/src/web-search/progress-stream.ts +342 -0
- package/src/web-search/synthetic-tool.ts +47 -0
- package/vendor/ocx-notch/win32-x64/ocx-notch.exe +0 -0
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
import { pathToFileURL } from "node:url";
|
|
2
|
+
import type { VideoBridgePlan, VideoCallResult } from "./types";
|
|
3
|
+
import { submitVideoJob, pollVideoJob } from "./xai-video-client";
|
|
4
|
+
import { downloadVideoToArtifact, createVideoBudget, type VideoBudget } from "./artifacts";
|
|
5
|
+
|
|
6
|
+
/** Parsed arguments from the model's video_gen tool call. */
|
|
7
|
+
export interface ParsedVideoArgs {
|
|
8
|
+
ok: true;
|
|
9
|
+
prompt: string;
|
|
10
|
+
duration?: number;
|
|
11
|
+
resolution?: string;
|
|
12
|
+
aspectRatio?: string;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
const INITIAL_POLL_INTERVAL_MS = 5_000;
|
|
16
|
+
const MAX_POLL_INTERVAL_MS = 15_000;
|
|
17
|
+
const POLL_BACKOFF = 1.5;
|
|
18
|
+
const DEFAULT_VIDEO_TIMEOUT_MS = 300_000; // 5 min
|
|
19
|
+
|
|
20
|
+
export type SleepFn = (ms: number, signal?: AbortSignal) => Promise<void>;
|
|
21
|
+
export type PollVideoJobFn = (
|
|
22
|
+
requestId: string,
|
|
23
|
+
auth: { baseUrl: string; token: string },
|
|
24
|
+
signal?: AbortSignal,
|
|
25
|
+
) => ReturnType<typeof pollVideoJob>;
|
|
26
|
+
|
|
27
|
+
export function sleep(ms: number, signal?: AbortSignal): Promise<void> {
|
|
28
|
+
if (signal?.aborted) return Promise.reject(new Error("aborted"));
|
|
29
|
+
return new Promise((resolve, reject) => {
|
|
30
|
+
const onAbort = (): void => { clearTimeout(timer); reject(new Error("aborted")); };
|
|
31
|
+
const timer = setTimeout(() => { signal?.removeEventListener("abort", onAbort); resolve(); }, ms);
|
|
32
|
+
signal?.addEventListener("abort", onAbort, { once: true });
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Parse the JSON arguments string from a video_gen tool call. Mirrors fulfillImageCall's
|
|
38
|
+
* defensive parsing: invalid JSON or missing prompt returns an error result.
|
|
39
|
+
*/
|
|
40
|
+
export function parseVideoCallArgs(raw: string):
|
|
41
|
+
| ParsedVideoArgs
|
|
42
|
+
| { ok: false; error: string } {
|
|
43
|
+
let args: unknown;
|
|
44
|
+
try {
|
|
45
|
+
args = JSON.parse(raw || "{}");
|
|
46
|
+
} catch {
|
|
47
|
+
return { ok: false, error: "invalid arguments JSON" };
|
|
48
|
+
}
|
|
49
|
+
if (typeof args !== "object" || args === null) {
|
|
50
|
+
return { ok: false, error: "invalid arguments JSON" };
|
|
51
|
+
}
|
|
52
|
+
const obj = args as Record<string, unknown>;
|
|
53
|
+
|
|
54
|
+
const prompt =
|
|
55
|
+
typeof obj.prompt === "string" ? obj.prompt : typeof obj.input === "string" ? obj.input : "";
|
|
56
|
+
if (!prompt) {
|
|
57
|
+
return { ok: false, error: "missing prompt" };
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
const result: ParsedVideoArgs = { ok: true, prompt };
|
|
61
|
+
|
|
62
|
+
// duration: clamp to 1-15
|
|
63
|
+
if (typeof obj.duration === "number") {
|
|
64
|
+
result.duration = Math.max(1, Math.min(15, Math.floor(obj.duration)));
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
if (typeof obj.resolution === "string" && (obj.resolution === "480p" || obj.resolution === "720p")) {
|
|
68
|
+
result.resolution = obj.resolution;
|
|
69
|
+
}
|
|
70
|
+
if (typeof obj.aspect_ratio === "string") {
|
|
71
|
+
const VALID_RATIOS = ["16:9", "9:16", "1:1", "4:3", "3:4", "3:2", "2:3"];
|
|
72
|
+
if (VALID_RATIOS.includes(obj.aspect_ratio)) result.aspectRatio = obj.aspect_ratio;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
return result;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Poll a video generation job, yielding heartbeats with elapsed-time messages so the
|
|
80
|
+
* caller can forward them to the SSE stream. Returns the final result when the job
|
|
81
|
+
* completes or fails/times out.
|
|
82
|
+
*/
|
|
83
|
+
export async function* pollVideoWithHeartbeats(
|
|
84
|
+
requestId: string,
|
|
85
|
+
auth: { baseUrl: string; token: string },
|
|
86
|
+
signal: AbortSignal,
|
|
87
|
+
timeoutMs: number = DEFAULT_VIDEO_TIMEOUT_MS,
|
|
88
|
+
/** Test seams — avoid mock.module / global setTimeout (both poison parallel Bun CI). */
|
|
89
|
+
sleepFn: SleepFn = sleep,
|
|
90
|
+
pollFn: PollVideoJobFn = pollVideoJob,
|
|
91
|
+
): AsyncGenerator<
|
|
92
|
+
{ type: "heartbeat"; message: string },
|
|
93
|
+
{ ok: true; videoUrl: string } | { ok: false; error: string }
|
|
94
|
+
> {
|
|
95
|
+
const start = Date.now();
|
|
96
|
+
let interval = INITIAL_POLL_INTERVAL_MS;
|
|
97
|
+
const timeoutStr = `video generation timed out after ${Math.floor(timeoutMs / 1000)}s`;
|
|
98
|
+
|
|
99
|
+
for (;;) {
|
|
100
|
+
if (Date.now() - start >= timeoutMs) {
|
|
101
|
+
return { ok: false, error: timeoutStr };
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
try {
|
|
105
|
+
const poll = await pollFn(requestId, auth, signal);
|
|
106
|
+
if (poll.status === "done") {
|
|
107
|
+
if (poll.videoUrl) {
|
|
108
|
+
return { ok: true, videoUrl: poll.videoUrl };
|
|
109
|
+
}
|
|
110
|
+
return { ok: false, error: "video generation completed but no video URL was returned" };
|
|
111
|
+
}
|
|
112
|
+
if (poll.status === "failed") {
|
|
113
|
+
return { ok: false, error: "video generation failed" };
|
|
114
|
+
}
|
|
115
|
+
if (poll.status === "expired") {
|
|
116
|
+
return { ok: false, error: "video generation expired" };
|
|
117
|
+
}
|
|
118
|
+
// still processing — continue with backoff
|
|
119
|
+
} catch (e) {
|
|
120
|
+
// Distinguish deadline-expiry from client-cancel.
|
|
121
|
+
// AbortSignal.timeout sets signal.reason to a TimeoutError.
|
|
122
|
+
const isDeadline = signal.aborted && e instanceof Error && e.name === "TimeoutError";
|
|
123
|
+
if (isDeadline) return { ok: false, error: timeoutStr };
|
|
124
|
+
if (signal.aborted) return { ok: false, error: "client closed request during video generation" };
|
|
125
|
+
const status = (e as Error & { status?: number }).status;
|
|
126
|
+
if (status && status >= 400 && status < 500 && status !== 429) {
|
|
127
|
+
return { ok: false, error: `video poll failed permanently: HTTP ${status}` };
|
|
128
|
+
}
|
|
129
|
+
console.warn(`[videos] poll error (will retry): ${e instanceof Error ? e.message : String(e)}`);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
const elapsed = Math.floor((Date.now() - start) / 1000);
|
|
133
|
+
yield { type: "heartbeat", message: `Generating video... ${elapsed}s` };
|
|
134
|
+
|
|
135
|
+
try {
|
|
136
|
+
await sleepFn(interval, signal);
|
|
137
|
+
} catch {
|
|
138
|
+
const isDeadline = signal.aborted && signal.reason instanceof Error && signal.reason.name === "TimeoutError";
|
|
139
|
+
if (isDeadline) return { ok: false, error: timeoutStr };
|
|
140
|
+
return { ok: false, error: "client closed request during video generation" };
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
interval = Math.min(MAX_POLL_INTERVAL_MS, Math.floor(interval * POLL_BACKOFF));
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* Build a success VideoCallResult after the video has been downloaded to disk.
|
|
149
|
+
*/
|
|
150
|
+
export function buildVideoResult(path: string, prompt: string, model: string): VideoCallResult {
|
|
151
|
+
return {
|
|
152
|
+
ok: true,
|
|
153
|
+
model,
|
|
154
|
+
prompt,
|
|
155
|
+
path,
|
|
156
|
+
files: [path],
|
|
157
|
+
count: 1,
|
|
158
|
+
markdown: `[video](${pathToFileURL(path).href})`,
|
|
159
|
+
};
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
export type { VideoBudget };
|
|
163
|
+
export { createVideoBudget };
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
import { existsSync } from "node:fs";
|
|
2
|
+
import { pathToFileURL } from "node:url";
|
|
3
|
+
import type { ImageBridgePlan, ImageCallResult } from "./types";
|
|
4
|
+
import { callXaiImages } from "./xai-client";
|
|
5
|
+
import {
|
|
6
|
+
materializeInlineImage,
|
|
7
|
+
downloadImageToArtifact,
|
|
8
|
+
pruneArtifacts,
|
|
9
|
+
type ImageBudget,
|
|
10
|
+
} from "./artifacts";
|
|
11
|
+
import { MAX_PENDING_IMAGE_FULFILLMENTS } from "../lib/translator-budget";
|
|
12
|
+
|
|
13
|
+
const fulfillmentEncoder = new TextEncoder();
|
|
14
|
+
let pendingFulfillments = 0;
|
|
15
|
+
let fulfillmentCurrentBytes = 0;
|
|
16
|
+
let fulfillmentHighWaterBytes = 0;
|
|
17
|
+
|
|
18
|
+
function addFulfillmentBytes(bytes: number): void {
|
|
19
|
+
fulfillmentCurrentBytes += bytes;
|
|
20
|
+
fulfillmentHighWaterBytes = Math.max(fulfillmentHighWaterBytes, fulfillmentCurrentBytes);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function releaseFulfillmentBytes(bytes: number): void {
|
|
24
|
+
fulfillmentCurrentBytes = Math.max(0, fulfillmentCurrentBytes - bytes);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export function imageFulfillmentTailSnapshot(): { currentBytes: number; highWaterBytes: number; active: number } {
|
|
28
|
+
return { currentBytes: fulfillmentCurrentBytes, highWaterBytes: fulfillmentHighWaterBytes, active: pendingFulfillments };
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/** Serialize write→prune→retain across concurrent fulfillments sharing artifacts/. */
|
|
32
|
+
let retentionTail: Promise<void> = Promise.resolve();
|
|
33
|
+
|
|
34
|
+
async function retainAfterBatch(paths: string[], keepCount?: number): Promise<string[]> {
|
|
35
|
+
const retainedBytes = paths.reduce((total, path) => total + fulfillmentEncoder.encode(path).byteLength, 0);
|
|
36
|
+
addFulfillmentBytes(retainedBytes);
|
|
37
|
+
const run = retentionTail.then(() => {
|
|
38
|
+
pruneArtifacts(keepCount);
|
|
39
|
+
return paths.filter((p) => existsSync(p));
|
|
40
|
+
});
|
|
41
|
+
retentionTail = run.then(
|
|
42
|
+
() => undefined,
|
|
43
|
+
() => undefined,
|
|
44
|
+
);
|
|
45
|
+
try {
|
|
46
|
+
return await run;
|
|
47
|
+
} finally {
|
|
48
|
+
releaseFulfillmentBytes(retainedBytes);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Fulfill ONE image-generation tool call end-to-end: parse args, call xAI, materialize the returned
|
|
54
|
+
* images to disk, and return a structured result. NEVER throws — all errors become `{ ok: false }`
|
|
55
|
+
* so the caller can inject the error as a tool result and let the model respond gracefully.
|
|
56
|
+
*/
|
|
57
|
+
export async function fulfillImageCall(
|
|
58
|
+
call: { id: string; name: string; arguments: string },
|
|
59
|
+
plan: ImageBridgePlan,
|
|
60
|
+
budget: ImageBudget,
|
|
61
|
+
signal?: AbortSignal,
|
|
62
|
+
): Promise<ImageCallResult> {
|
|
63
|
+
if (pendingFulfillments >= MAX_PENDING_IMAGE_FULFILLMENTS) {
|
|
64
|
+
return { ok: false, model: plan.model, prompt: "", files: [], count: 0, error: "image_fulfillment_busy" };
|
|
65
|
+
}
|
|
66
|
+
pendingFulfillments += 1;
|
|
67
|
+
const callBytes = fulfillmentEncoder.encode(call.id).byteLength
|
|
68
|
+
+ fulfillmentEncoder.encode(call.name).byteLength
|
|
69
|
+
+ fulfillmentEncoder.encode(call.arguments).byteLength;
|
|
70
|
+
addFulfillmentBytes(callBytes);
|
|
71
|
+
try {
|
|
72
|
+
let args: unknown;
|
|
73
|
+
try {
|
|
74
|
+
args = JSON.parse(call.arguments || "{}");
|
|
75
|
+
} catch {
|
|
76
|
+
return { ok: false, model: plan.model, prompt: "", files: [], count: 0, error: "invalid arguments JSON" };
|
|
77
|
+
}
|
|
78
|
+
if (typeof args !== "object" || args === null) {
|
|
79
|
+
return { ok: false, model: plan.model, prompt: "", files: [], count: 0, error: "invalid arguments JSON" };
|
|
80
|
+
}
|
|
81
|
+
const obj = args as Record<string, unknown>;
|
|
82
|
+
|
|
83
|
+
const prompt =
|
|
84
|
+
typeof obj.prompt === "string" ? obj.prompt : typeof obj.input === "string" ? obj.input : "";
|
|
85
|
+
if (!prompt) {
|
|
86
|
+
return { ok: false, model: plan.model, prompt: "", files: [], count: 0, error: "missing prompt" };
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
const n = typeof obj.n === "number" ? Math.max(1, Math.min(4, Math.floor(obj.n))) : 1;
|
|
90
|
+
const imageUrl =
|
|
91
|
+
typeof obj.image_url === "string" ? obj.image_url : typeof obj.image === "string" ? obj.image : undefined;
|
|
92
|
+
const size = typeof obj.size === "string" ? obj.size : plan.defaultSize;
|
|
93
|
+
const quality = typeof obj.quality === "string" ? obj.quality : plan.defaultQuality;
|
|
94
|
+
|
|
95
|
+
let result;
|
|
96
|
+
try {
|
|
97
|
+
result = await callXaiImages(
|
|
98
|
+
{ prompt, model: plan.model, n, imageUrl, size, quality },
|
|
99
|
+
plan.auth,
|
|
100
|
+
signal,
|
|
101
|
+
plan.timeoutMs,
|
|
102
|
+
);
|
|
103
|
+
} catch (e) {
|
|
104
|
+
const error = e instanceof Error ? e.message : String(e);
|
|
105
|
+
return { ok: false, model: plan.model, prompt, files: [], count: 0, error };
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
const files: string[] = [];
|
|
109
|
+
for (const img of result.images ?? []) {
|
|
110
|
+
try {
|
|
111
|
+
if (img.b64_json) {
|
|
112
|
+
files.push(await materializeInlineImage(img.b64_json, budget));
|
|
113
|
+
} else if (img.url) {
|
|
114
|
+
files.push(await downloadImageToArtifact(img.url, budget, signal));
|
|
115
|
+
}
|
|
116
|
+
} catch {
|
|
117
|
+
// Keep warnings URL-free — error messages may embed provider CDN URLs.
|
|
118
|
+
// Partial success is OK — silently skip this image and continue.
|
|
119
|
+
console.warn("[images] failed to materialize image");
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
// Prune only after the full batch is on disk so a tight keepCount cannot delete
|
|
124
|
+
// an earlier image from this same call before we return its path. Concurrent
|
|
125
|
+
// fulfillments share one retention chain so they cannot prune each other's
|
|
126
|
+
// just-written paths mid-filter.
|
|
127
|
+
const retained = await retainAfterBatch(files, plan.artifactsKeepCount);
|
|
128
|
+
|
|
129
|
+
if (retained.length === 0) {
|
|
130
|
+
return { ok: false, model: plan.model, prompt, files: [], count: 0, error: "image generation returned no usable images" };
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
const primary = retained[0]!;
|
|
134
|
+
return {
|
|
135
|
+
ok: true,
|
|
136
|
+
model: plan.model,
|
|
137
|
+
prompt,
|
|
138
|
+
path: primary,
|
|
139
|
+
files: retained,
|
|
140
|
+
count: retained.length,
|
|
141
|
+
// Keep path/files as native FS paths; Markdown needs a file: URI so Windows
|
|
142
|
+
// backslashes are not treated as escapes by renderers.
|
|
143
|
+
markdown: `.href})`,
|
|
144
|
+
};
|
|
145
|
+
} finally {
|
|
146
|
+
releaseFulfillmentBytes(callBytes);
|
|
147
|
+
pendingFulfillments -= 1;
|
|
148
|
+
}
|
|
149
|
+
}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export { planImageBridge, planVideoBridge, findXaiProvider, resolveXaiImageApiKey } from "./plan";
|
|
2
|
+
export { runWithImageBridge, clampImageMaxRounds, DEFAULT_MAX_ROUNDS, MAX_ROUNDS_HARD_LIMIT } from "./loop";
|
|
3
|
+
export type { ImageBridgePlan, ImageCallResult, VideoBridgePlan, VideoCallResult } from "./types";
|
|
4
|
+
export { buildImageTool, buildVideoTool, extractHostedImageGeneration, IMAGE_GEN_TOOL_NAME, VIDEO_GEN_TOOL_NAME, isImageGenName, isVideoGenName } from "./synthetic-tool";
|