@remodex/rmx 1.0.2
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/AGENTS_INSTALL.md +91 -0
- package/LICENSE +21 -0
- package/README.md +242 -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.mjs +584 -0
- package/bin/package-main.mjs +9 -0
- package/gui/dist/assets/index-CZqebSPQ.css +1 -0
- package/gui/dist/assets/index-CkETtt7P.js +71 -0
- package/gui/dist/favicon.png +0 -0
- package/gui/dist/fonts/google-sans-cyrillic.woff2 +0 -0
- package/gui/dist/fonts/google-sans-latin.woff2 +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/claude-color.svg +1 -0
- package/gui/dist/provider-icons/cline-color.svg +16 -0
- package/gui/dist/provider-icons/cloudflare-ai-gateway-color.svg +1 -0
- package/gui/dist/provider-icons/commandcode-color.svg +1 -0
- package/gui/dist/provider-icons/copilot-color.svg +1 -0
- package/gui/dist/provider-icons/cursor-color.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/github-copilot-color.svg +1 -0
- package/gui/dist/provider-icons/gitlab-duo-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/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 +2 -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 +118 -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 +1205 -0
- package/src/adapters/azure.ts +36 -0
- package/src/adapters/base.ts +83 -0
- package/src/adapters/client-fingerprint.ts +59 -0
- package/src/adapters/command-code.ts +453 -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 +139 -0
- package/src/adapters/cursor/exec-policy.ts +88 -0
- package/src/adapters/cursor/framing.ts +250 -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 +1235 -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 +59 -0
- package/src/adapters/cursor/native-exec-desktop.ts +184 -0
- package/src/adapters/cursor/native-exec-fs.ts +332 -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 +604 -0
- package/src/adapters/cursor/protobuf-events.ts +735 -0
- package/src/adapters/cursor/protobuf-request.ts +719 -0
- package/src/adapters/cursor/request-builder.ts +280 -0
- package/src/adapters/cursor/thread-continuity.ts +67 -0
- package/src/adapters/cursor/tool-definitions.ts +621 -0
- package/src/adapters/cursor/transport-retry.ts +132 -0
- package/src/adapters/cursor/transport.ts +57 -0
- package/src/adapters/cursor/types.ts +59 -0
- package/src/adapters/cursor.ts +196 -0
- package/src/adapters/google-antigravity-replay.ts +520 -0
- package/src/adapters/google-antigravity-wire.ts +140 -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 +24 -0
- package/src/adapters/google-wire-compiler.ts +232 -0
- package/src/adapters/google.ts +859 -0
- package/src/adapters/identity.ts +77 -0
- package/src/adapters/image.ts +23 -0
- package/src/adapters/kiro-constants.ts +16 -0
- package/src/adapters/kiro-errors.ts +208 -0
- package/src/adapters/kiro-events.ts +197 -0
- package/src/adapters/kiro-images.ts +129 -0
- package/src/adapters/kiro-retry.ts +312 -0
- package/src/adapters/kiro-thinking.ts +104 -0
- package/src/adapters/kiro-tool-fallback.ts +36 -0
- package/src/adapters/kiro-tools.ts +224 -0
- package/src/adapters/kiro-truncation.ts +33 -0
- package/src/adapters/kiro-wire.ts +129 -0
- package/src/adapters/kiro.ts +1924 -0
- package/src/adapters/mimo-free.ts +263 -0
- package/src/adapters/openai-chat.ts +1265 -0
- package/src/adapters/openai-responses.ts +1309 -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/android-remote/assets.ts +218 -0
- package/src/android-remote/attachments.ts +168 -0
- package/src/android-remote/auth.ts +237 -0
- package/src/android-remote/cloudflare-provisioning.ts +409 -0
- package/src/android-remote/cloudflare-secret.ts +106 -0
- package/src/android-remote/cloudflare-tunnel.ts +488 -0
- package/src/android-remote/cloudflared.ts +286 -0
- package/src/android-remote/codex-app-server.ts +565 -0
- package/src/android-remote/desktop-history-page.ts +936 -0
- package/src/android-remote/desktop-ipc.ts +3643 -0
- package/src/android-remote/desktop-ownership-store.ts +98 -0
- package/src/android-remote/desktop-project-registration.ts +129 -0
- package/src/android-remote/desktop-session-stream.ts +1110 -0
- package/src/android-remote/desktop-workspace-state.ts +443 -0
- package/src/android-remote/file-change-parser.ts +112 -0
- package/src/android-remote/gateway.ts +9108 -0
- package/src/android-remote/mutation-store.ts +299 -0
- package/src/android-remote/projection.ts +1780 -0
- package/src/android-remote/queued-turn-store.ts +248 -0
- package/src/android-remote/session-command-recovery.ts +1384 -0
- package/src/android-remote/store.ts +466 -0
- package/src/android-remote/thread-reconciliation.ts +133 -0
- package/src/android-remote/thread-source-paths.ts +307 -0
- package/src/android-remote/thread-stream.ts +546 -0
- package/src/android-remote/turn-activity.ts +235 -0
- package/src/android-remote/user-message-identity.ts +94 -0
- package/src/bridge.ts +1793 -0
- package/src/chat/inbound.ts +295 -0
- package/src/chat/outbound.ts +821 -0
- package/src/claude/agents-inject.ts +267 -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 +601 -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 +519 -0
- package/src/claude/model-info.ts +154 -0
- package/src/claude/outbound.ts +898 -0
- package/src/cli/access.ts +108 -0
- package/src/cli/account-api.ts +296 -0
- package/src/cli/account-auth.ts +250 -0
- package/src/cli/account-catalog-refresh.ts +14 -0
- package/src/cli/account-extended.ts +476 -0
- package/src/cli/account-main.ts +317 -0
- package/src/cli/account.ts +297 -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 +211 -0
- package/src/cli/claude.ts +302 -0
- package/src/cli/codex-shim-autorestore.ts +45 -0
- package/src/cli/codex-shim-readiness.ts +69 -0
- package/src/cli/combo.ts +124 -0
- package/src/cli/config-command.ts +183 -0
- package/src/cli/debug.ts +228 -0
- package/src/cli/desktop-first-run.ts +25 -0
- package/src/cli/doctor.ts +1022 -0
- package/src/cli/export-command.ts +201 -0
- package/src/cli/help.ts +370 -0
- package/src/cli/index.ts +1565 -0
- package/src/cli/init.ts +224 -0
- package/src/cli/integrations.ts +225 -0
- package/src/cli/interactive-confirm.ts +133 -0
- package/src/cli/internal-dispatch.ts +35 -0
- package/src/cli/launcher-context.ts +77 -0
- package/src/cli/models-runtime.ts +224 -0
- package/src/cli/models.ts +340 -0
- package/src/cli/observe.ts +170 -0
- package/src/cli/opencode.ts +587 -0
- package/src/cli/provider-runtime.ts +179 -0
- package/src/cli/provider.ts +476 -0
- package/src/cli/ready.ts +301 -0
- package/src/cli/route-policy.ts +92 -0
- package/src/cli/runtime-api.ts +328 -0
- package/src/cli/star-prompt.ts +211 -0
- package/src/cli/status-oauth.ts +78 -0
- package/src/cli/status.ts +321 -0
- package/src/cli/system-command.ts +196 -0
- package/src/cli/system-restart-client.ts +146 -0
- package/src/cli/tray-proxy.ts +205 -0
- package/src/cli/v2.ts +200 -0
- package/src/cli.ts +10 -0
- package/src/clients/config-export.ts +1109 -0
- package/src/codex/account-id.ts +34 -0
- package/src/codex/account-label.ts +34 -0
- package/src/codex/account-lifecycle.ts +172 -0
- package/src/codex/account-namespace-match.ts +63 -0
- package/src/codex/account-namespaces.ts +195 -0
- package/src/codex/account-pause.ts +20 -0
- package/src/codex/account-priority.ts +83 -0
- package/src/codex/account-runtime-state.ts +31 -0
- package/src/codex/account-store.ts +517 -0
- package/src/codex/account-usability.ts +40 -0
- package/src/codex/admission.ts +263 -0
- package/src/codex/app-server-processes.ts +799 -0
- package/src/codex/auth-api.ts +2098 -0
- package/src/codex/auth-collision.ts +107 -0
- package/src/codex/auth-context.ts +480 -0
- package/src/codex/autostart-health.ts +156 -0
- package/src/codex/catalog/account-models.ts +67 -0
- package/src/codex/catalog/aggregation.ts +471 -0
- package/src/codex/catalog/bundled.ts +533 -0
- package/src/codex/catalog/effort.ts +432 -0
- package/src/codex/catalog/filesystem-evidence.ts +302 -0
- package/src/codex/catalog/kinds.ts +2 -0
- package/src/codex/catalog/metadata.ts +287 -0
- package/src/codex/catalog/native-models.ts +7 -0
- package/src/codex/catalog/parsing.ts +503 -0
- package/src/codex/catalog/provider-fetch.ts +2267 -0
- package/src/codex/catalog/sync.ts +1606 -0
- package/src/codex/catalog-admission.ts +197 -0
- package/src/codex/catalog-refresh-status.ts +87 -0
- package/src/codex/catalog-write-serialization.ts +242 -0
- package/src/codex/catalog.ts +15 -0
- package/src/codex/codex-write-lock.ts +384 -0
- package/src/codex/convergence-types.ts +593 -0
- package/src/codex/convergence.ts +580 -0
- package/src/codex/custom-model-catalog-migration.ts +176 -0
- package/src/codex/data/upstream-models.json +830 -0
- package/src/codex/desired-state.ts +230 -0
- package/src/codex/desktop-client-processes.ts +521 -0
- package/src/codex/exec-invocation.ts +22 -0
- package/src/codex/features.ts +1091 -0
- package/src/codex/generation.ts +202 -0
- package/src/codex/history-job.ts +347 -0
- package/src/codex/history-lock.ts +242 -0
- package/src/codex/history-migration-guardian.ts +115 -0
- package/src/codex/history-provider.ts +1075 -0
- package/src/codex/history-transition.ts +105 -0
- package/src/codex/history-worker.ts +204 -0
- package/src/codex/home.ts +206 -0
- package/src/codex/inject-coordination.ts +257 -0
- package/src/codex/inject.ts +1857 -0
- package/src/codex/injected-marker.ts +79 -0
- package/src/codex/integration-record.ts +266 -0
- package/src/codex/internal/catalog-writer.ts +203 -0
- package/src/codex/internal/history-writer.ts +105 -0
- package/src/codex/journal.ts +172 -0
- package/src/codex/main-account-cache.ts +56 -0
- package/src/codex/main-account.ts +40 -0
- package/src/codex/management-convergence.ts +114 -0
- package/src/codex/model-cache.ts +267 -0
- package/src/codex/native-main-admission.ts +47 -0
- package/src/codex/native-main-auth-temp.ts +187 -0
- package/src/codex/native-main-claim.ts +167 -0
- package/src/codex/native-main-lock-file.ts +162 -0
- package/src/codex/native-main-owner.ts +329 -0
- package/src/codex/native-profile-api.ts +247 -0
- package/src/codex/native-profile-manager.ts +1531 -0
- package/src/codex/native-profile-processes.ts +121 -0
- package/src/codex/native-profile-recovery.ts +99 -0
- package/src/codex/native-profile-stage-store.ts +387 -0
- package/src/codex/native-profile-startup.ts +348 -0
- package/src/codex/native-profile-store.ts +855 -0
- package/src/codex/native-profile-types.ts +120 -0
- package/src/codex/native-residue.ts +691 -0
- package/src/codex/paths.ts +78 -0
- package/src/codex/plugins-doctor.ts +242 -0
- package/src/codex/pool-rotation.ts +295 -0
- package/src/codex/project-config-warnings.ts +426 -0
- package/src/codex/prompt-journal.ts +311 -0
- package/src/codex/prompt-layers.ts +967 -0
- package/src/codex/prompt-lock.ts +143 -0
- package/src/codex/provider-adoption.ts +242 -0
- package/src/codex/quota-rejection.ts +224 -0
- package/src/codex/quota.ts +494 -0
- package/src/codex/refresh.ts +60 -0
- package/src/codex/routing.ts +1855 -0
- package/src/codex/runtime.ts +659 -0
- package/src/codex/shim.ts +1215 -0
- package/src/codex/subagent-defaults.ts +557 -0
- package/src/codex/subagent-model-fallback.ts +560 -0
- package/src/codex/sync.ts +238 -0
- package/src/codex/transition-state.ts +612 -0
- package/src/codex/upstream-host-health.ts +368 -0
- package/src/codex/user-identity.ts +374 -0
- package/src/codex/warmup.ts +192 -0
- package/src/codex/websocket-registry.ts +100 -0
- package/src/codex/write-coordination.ts +114 -0
- package/src/combos/failover.ts +140 -0
- package/src/combos/index.ts +44 -0
- package/src/combos/request.ts +64 -0
- package/src/combos/resolve.ts +232 -0
- package/src/combos/types.ts +392 -0
- package/src/config.ts +3270 -0
- package/src/generated/model-metadata.ts +144 -0
- package/src/github/star-state.ts +203 -0
- package/src/grok/inject.ts +540 -0
- package/src/grok/inspect.ts +45 -0
- package/src/grok/status.ts +127 -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 +922 -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/integrations/config-io.ts +151 -0
- package/src/integrations/journal.ts +315 -0
- package/src/integrations/merge.ts +135 -0
- package/src/integrations/native/ownership-preflight.ts +202 -0
- package/src/integrations/ownership.ts +111 -0
- package/src/integrations/registry.ts +108 -0
- package/src/integrations/serialize.ts +235 -0
- package/src/integrations/state.ts +290 -0
- package/src/integrations/store.ts +103 -0
- package/src/integrations/writer.ts +492 -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 +242 -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 +184 -0
- package/src/lib/bun-stream-caps.ts +127 -0
- package/src/lib/config-ownership.ts +438 -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/local-management-attestation.ts +51 -0
- package/src/lib/open-url.ts +25 -0
- package/src/lib/pinned-http.ts +182 -0
- package/src/lib/privacy.ts +20 -0
- package/src/lib/process-control.ts +168 -0
- package/src/lib/provider-environment.ts +470 -0
- package/src/lib/provider-outbound.ts +203 -0
- package/src/lib/provider-url.ts +14 -0
- package/src/lib/proxy-env.ts +18 -0
- package/src/lib/redact.ts +510 -0
- package/src/lib/remodex-home.ts +616 -0
- package/src/lib/retry-after.ts +55 -0
- package/src/lib/service-secrets.ts +178 -0
- package/src/lib/shadow-call.ts +54 -0
- package/src/lib/sidecar-tracker.ts +52 -0
- package/src/lib/sse-decoder.ts +364 -0
- package/src/lib/state-store-registrations.ts +109 -0
- package/src/lib/state-store-sweeper.ts +184 -0
- package/src/lib/system-restart-contract.ts +73 -0
- package/src/lib/test-home-guard.ts +98 -0
- package/src/lib/token-estimate.ts +69 -0
- package/src/lib/translator-budget.ts +366 -0
- package/src/lib/upstream-reachability.ts +91 -0
- package/src/lib/upstream-retry.ts +508 -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 +817 -0
- package/src/lib/windows-user-principal.ts +283 -0
- package/src/lib/winsw.ts +402 -0
- package/src/model-sources.ts +73 -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/command-code.ts +239 -0
- package/src/oauth/cursor.ts +231 -0
- package/src/oauth/github-copilot.ts +428 -0
- package/src/oauth/google-antigravity.ts +230 -0
- package/src/oauth/health.ts +443 -0
- package/src/oauth/index.ts +1280 -0
- package/src/oauth/key-providers.ts +128 -0
- package/src/oauth/kimi.ts +213 -0
- package/src/oauth/kiro-credentials.ts +726 -0
- package/src/oauth/kiro.ts +621 -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 +655 -0
- package/src/oauth/token-guardian.ts +309 -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 +317 -0
- package/src/providers/api-keys.ts +140 -0
- package/src/providers/base-url-choices.ts +64 -0
- package/src/providers/codex-capacity.ts +288 -0
- package/src/providers/command-code-efforts.ts +85 -0
- package/src/providers/context-cap.ts +73 -0
- package/src/providers/derive.ts +451 -0
- package/src/providers/free-directory.ts +187 -0
- package/src/providers/github-copilot-transport.ts +56 -0
- package/src/providers/google-vertex-location.ts +14 -0
- package/src/providers/key-failover.ts +271 -0
- package/src/providers/kiro-models.ts +67 -0
- package/src/providers/label.ts +19 -0
- package/src/providers/model-discovery-limits.ts +16 -0
- package/src/providers/model-discovery.ts +361 -0
- package/src/providers/openai-sidecar.ts +235 -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 +83 -0
- package/src/providers/openrouter-routing.ts +102 -0
- package/src/providers/provider-id-rewrite.ts +179 -0
- package/src/providers/quota.ts +1942 -0
- package/src/providers/reasoning-capabilities.ts +336 -0
- package/src/providers/registry.ts +2375 -0
- package/src/providers/slug-codec.ts +74 -0
- package/src/providers/xai-transport.ts +149 -0
- package/src/reasoning-effort.ts +243 -0
- package/src/responses/compaction.ts +124 -0
- package/src/responses/hosted-tool-policy.ts +9 -0
- package/src/responses/parser.ts +714 -0
- package/src/responses/reasoning-envelope.ts +60 -0
- package/src/responses/reasoning-replay-cache.ts +106 -0
- package/src/responses/schema.ts +159 -0
- package/src/responses/spill-store.ts +431 -0
- package/src/responses/state.ts +1039 -0
- package/src/responses/tool-groups.ts +19 -0
- package/src/router.ts +802 -0
- package/src/routing/analytics.ts +377 -0
- package/src/routing/capability.ts +205 -0
- package/src/routing/cost.ts +77 -0
- package/src/routing/evaluator.ts +444 -0
- package/src/routing/health.ts +401 -0
- package/src/routing/history/cursor.ts +43 -0
- package/src/routing/history/indexer.ts +605 -0
- package/src/routing/history/schema.ts +72 -0
- package/src/routing/profile-namespace.ts +15 -0
- package/src/routing/profile.ts +424 -0
- package/src/routing/quota.ts +145 -0
- package/src/routing/request-evidence.ts +45 -0
- package/src/routing/trace.ts +686 -0
- package/src/server/adapter-resolve.ts +83 -0
- package/src/server/auth-cors.ts +606 -0
- package/src/server/chat-completions.ts +379 -0
- package/src/server/claude-messages.ts +980 -0
- package/src/server/effort-policy.ts +251 -0
- package/src/server/github-copilot-responses-repair.ts +338 -0
- package/src/server/gui-static.ts +152 -0
- package/src/server/image-retry.ts +42 -0
- package/src/server/images.ts +485 -0
- package/src/server/index.ts +1633 -0
- package/src/server/lifecycle.ts +482 -0
- package/src/server/live.ts +609 -0
- package/src/server/management/agent-settings-routes.ts +1180 -0
- package/src/server/management/android-remote-routes.ts +390 -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 +244 -0
- package/src/server/management/config-routes.ts +602 -0
- package/src/server/management/context.ts +88 -0
- package/src/server/management/integration-routes.ts +538 -0
- package/src/server/management/logs-usage-routes.ts +516 -0
- package/src/server/management/model-routes.ts +519 -0
- package/src/server/management/model-rows.ts +143 -0
- package/src/server/management/native-integration-routes.ts +781 -0
- package/src/server/management/oauth-account-routes.ts +573 -0
- package/src/server/management/provider-routes.ts +781 -0
- package/src/server/management/request-history-routes.ts +191 -0
- package/src/server/management/routing-analytics-routes.ts +74 -0
- package/src/server/management/routing-profile-routes.ts +384 -0
- package/src/server/management/shared.ts +277 -0
- package/src/server/management/sidebar-routes.ts +106 -0
- package/src/server/management/sync-response.ts +69 -0
- package/src/server/management/system-restart.ts +433 -0
- package/src/server/management/system-routes.ts +141 -0
- package/src/server/management/usage-summary-cache.ts +86 -0
- package/src/server/management-api.ts +269 -0
- package/src/server/management-auth.ts +353 -0
- package/src/server/memory-watchdog.ts +156 -0
- package/src/server/port-reclaim.ts +307 -0
- package/src/server/ports.ts +156 -0
- package/src/server/proxy-liveness.ts +326 -0
- package/src/server/proxy-stop.ts +92 -0
- package/src/server/readiness.ts +99 -0
- package/src/server/relay-eager.ts +353 -0
- package/src/server/relay.ts +1179 -0
- package/src/server/request-decompress.ts +132 -0
- package/src/server/request-log-conversation.ts +168 -0
- package/src/server/request-log.ts +1072 -0
- package/src/server/responses/collaboration.ts +409 -0
- package/src/server/responses/compact.ts +710 -0
- package/src/server/responses/core.ts +3561 -0
- package/src/server/responses/encrypted-payload.ts +308 -0
- package/src/server/responses/fetch-helpers.ts +171 -0
- package/src/server/responses/passthrough-error.ts +78 -0
- package/src/server/responses/policy-fallback.ts +152 -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 +272 -0
- package/src/server/responses-json-events.ts +52 -0
- package/src/server/responses-model-rewrite.ts +29 -0
- package/src/server/responses-snapshot-repair.ts +621 -0
- package/src/server/responses.ts +10 -0
- package/src/server/search.ts +181 -0
- package/src/server/sse-frame-buffer.ts +292 -0
- package/src/server/sse-payload-rewrite.ts +263 -0
- package/src/server/startup-action-control.ts +308 -0
- package/src/server/startup-health-cache.ts +119 -0
- package/src/server/system-env.ts +418 -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 +470 -0
- package/src/service-manager-probe.ts +824 -0
- package/src/service.ts +3011 -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 +364 -0
- package/src/tray/windows.ts +738 -0
- package/src/types.ts +1531 -0
- package/src/update/badge.ts +72 -0
- package/src/update/desktop-release.ts +1620 -0
- package/src/update/index.ts +402 -0
- package/src/update/job.ts +1906 -0
- package/src/update/notify.ts +261 -0
- package/src/update/npm-cache-preflight.d.mts +47 -0
- package/src/update/npm-cache-preflight.mjs +201 -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 +283 -0
- package/src/usage/log.ts +695 -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 +127 -0
- package/src/vision/index.ts +558 -0
- package/src/vision/reasoning.ts +55 -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 +791 -0
- package/src/web-search/parse.ts +235 -0
- package/src/web-search/progress-stream.ts +342 -0
- package/src/web-search/synthetic-tool.ts +47 -0
|
@@ -0,0 +1,290 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* "What is on disk, and did we put it there?"
|
|
3
|
+
*
|
|
4
|
+
* The classifier is deliberately ordered, and the order is load-bearing: an
|
|
5
|
+
* unreadable file can never be reported as absent, and a foreign edit can never
|
|
6
|
+
* be reported as ordinary drift. Getting that wrong would let `disable` delete
|
|
7
|
+
* a user's own edits.
|
|
8
|
+
*
|
|
9
|
+
* Design of record: devlog/_fin/260802_client_toggle_api/021 §3.
|
|
10
|
+
*/
|
|
11
|
+
import { ClientPathError, EXPORT_CLIENTS, opencodeProxyBaseUrl, type ExportModel, type ManagedContribution } from "../clients/config-export";
|
|
12
|
+
import type { OcxConfig } from "../types";
|
|
13
|
+
import { PARSE_FAILED, loadTarget, parseConfig, type IntegrationIO } from "./config-io";
|
|
14
|
+
import { SNAPSHOT_RETENTION } from "./journal";
|
|
15
|
+
import { canonicalContribution, fingerprint, type OwnershipRecord } from "./ownership";
|
|
16
|
+
import { INTEGRATION_CLIENTS, type IntegrationClientId } from "./registry";
|
|
17
|
+
import { createIntegrationStateStore, type IntegrationStateStore } from "./store";
|
|
18
|
+
|
|
19
|
+
export type IntegrationState = "absent" | "current" | "stale" | "conflict" | "unsafe";
|
|
20
|
+
export type StateReason =
|
|
21
|
+
| "unparseable"
|
|
22
|
+
| "not-regular-file"
|
|
23
|
+
| "foreign-edit"
|
|
24
|
+
| "unowned-key"
|
|
25
|
+
/** A container we would have to write through holds a non-object value. */
|
|
26
|
+
| "blocked-container"
|
|
27
|
+
/** A path selector we cannot resolve, e.g. a relative OPENCLAW_CONFIG_PATH. */
|
|
28
|
+
| "unresolvable-path";
|
|
29
|
+
|
|
30
|
+
export interface IntegrationStatus {
|
|
31
|
+
clientId: IntegrationClientId;
|
|
32
|
+
state: IntegrationState;
|
|
33
|
+
installed: boolean;
|
|
34
|
+
configPath: string;
|
|
35
|
+
appliedAt?: string;
|
|
36
|
+
lastOpId?: string;
|
|
37
|
+
reason?: StateReason;
|
|
38
|
+
/** Snapshot files retained for this client; -1 when they cannot be inspected. */
|
|
39
|
+
snapshotCount: number;
|
|
40
|
+
/** Pruning is behind, so older (possibly credential-bearing) snapshots remain. */
|
|
41
|
+
retentionDegraded: boolean;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export function readPath(doc: unknown, path: readonly string[]): unknown {
|
|
45
|
+
let cursor: unknown = doc;
|
|
46
|
+
for (const key of path) {
|
|
47
|
+
if (typeof cursor !== "object" || cursor === null || Array.isArray(cursor)) return undefined;
|
|
48
|
+
cursor = (cursor as Record<string, unknown>)[key];
|
|
49
|
+
if (cursor === undefined) return undefined;
|
|
50
|
+
}
|
|
51
|
+
return cursor;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/** Does the document carry any fragment we would write? */
|
|
55
|
+
export function hasOurFragments(doc: unknown, contribution: ManagedContribution): boolean {
|
|
56
|
+
return contribution.fragments.some(fragment => readPath(doc, fragment.path) !== undefined);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* A container on one of our fragment paths that exists but is NOT an object.
|
|
61
|
+
*
|
|
62
|
+
* `setPath` replaces such a value with `{}` on the way to writing our leaf, so
|
|
63
|
+
* a user whose config held `providers: ["something"]` — legal in their schema,
|
|
64
|
+
* just not ours — lost it to an apply that reported success. The classifier
|
|
65
|
+
* called that document `absent` because our leaf was missing, which authorized
|
|
66
|
+
* the write. Detecting it here turns a silent overwrite into a refusal the
|
|
67
|
+
* user can act on; the snapshot exists, but "we backed up the thing we should
|
|
68
|
+
* not have destroyed" is not the promise this feature makes.
|
|
69
|
+
*/
|
|
70
|
+
export function blockedContainerPath(
|
|
71
|
+
doc: unknown,
|
|
72
|
+
contribution: ManagedContribution,
|
|
73
|
+
): readonly string[] | null {
|
|
74
|
+
for (const fragment of contribution.fragments) {
|
|
75
|
+
let cursor: unknown = doc;
|
|
76
|
+
for (let depth = 0; depth < fragment.path.length - 1; depth += 1) {
|
|
77
|
+
const key = fragment.path[depth]!;
|
|
78
|
+
/*
|
|
79
|
+
* ONLY `undefined` means absent. A missing file parses as `{}`, so an
|
|
80
|
+
* absent prefix reads `undefined` — but a parsed `null` is a value the
|
|
81
|
+
* user's file actually contains, and treating it as absent let a
|
|
82
|
+
* document that is literally `null` be replaced wholesale by a
|
|
83
|
+
* "successful" apply.
|
|
84
|
+
*/
|
|
85
|
+
if (cursor === undefined) break;
|
|
86
|
+
// `typeof null === "object"`, so null has to be named explicitly or it
|
|
87
|
+
// walks straight into the dereference below.
|
|
88
|
+
if (cursor === null || typeof cursor !== "object" || Array.isArray(cursor)) {
|
|
89
|
+
return fragment.path.slice(0, depth);
|
|
90
|
+
}
|
|
91
|
+
const next = (cursor as Record<string, unknown>)[key];
|
|
92
|
+
if (next === undefined) break;
|
|
93
|
+
if (typeof next !== "object" || next === null || Array.isArray(next)) {
|
|
94
|
+
return fragment.path.slice(0, depth + 1);
|
|
95
|
+
}
|
|
96
|
+
cursor = next;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
return null;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* The two-axis rule: the FILE hash proves nobody touched the file after us, and
|
|
104
|
+
* the BLOCK hash proves our content is still what we would write today.
|
|
105
|
+
*/
|
|
106
|
+
export function classifyIntegration(input: {
|
|
107
|
+
fileText: string | null;
|
|
108
|
+
fileIsRegular: boolean;
|
|
109
|
+
parsed: unknown | typeof PARSE_FAILED;
|
|
110
|
+
record: OwnershipRecord | null;
|
|
111
|
+
contribution: ManagedContribution;
|
|
112
|
+
/**
|
|
113
|
+
* The file being classified. A record only describes the file it was written
|
|
114
|
+
* for, so this is compared against `record.configPath` before any
|
|
115
|
+
* fingerprint is trusted.
|
|
116
|
+
*/
|
|
117
|
+
configPath?: string;
|
|
118
|
+
clientId?: IntegrationClientId;
|
|
119
|
+
}): { state: IntegrationState; reason?: StateReason } {
|
|
120
|
+
if (input.fileText !== null && !input.fileIsRegular) {
|
|
121
|
+
return { state: "unsafe", reason: "not-regular-file" };
|
|
122
|
+
}
|
|
123
|
+
if (input.parsed === PARSE_FAILED) return { state: "unsafe", reason: "unparseable" };
|
|
124
|
+
/*
|
|
125
|
+
* Checked BEFORE `absent`: our leaf is missing in exactly this case, so the
|
|
126
|
+
* absent branch would authorize an apply that replaces the user's value.
|
|
127
|
+
*/
|
|
128
|
+
if (blockedContainerPath(input.parsed, input.contribution)) {
|
|
129
|
+
return { state: "unsafe", reason: "blocked-container" };
|
|
130
|
+
}
|
|
131
|
+
if (!hasOurFragments(input.parsed, input.contribution)) return { state: "absent" };
|
|
132
|
+
if (!input.record) return { state: "conflict", reason: "unowned-key" };
|
|
133
|
+
/*
|
|
134
|
+
* A record proves ownership of ONE file. Change HOME, XDG_CONFIG_HOME,
|
|
135
|
+
* HERMES_HOME or KIMI_CODE_HOME and the same client resolves to a different
|
|
136
|
+
* path — whose contents may hash identically because we generate the same
|
|
137
|
+
* bytes. Trusting the fingerprint alone would let a record for path A grant
|
|
138
|
+
* `current` on path B, and the writer resolves the CURRENT path, so disable
|
|
139
|
+
* would then delete fragments from a file this record never owned.
|
|
140
|
+
*/
|
|
141
|
+
if (input.clientId !== undefined && input.record.clientId !== input.clientId) {
|
|
142
|
+
return { state: "conflict", reason: "unowned-key" };
|
|
143
|
+
}
|
|
144
|
+
if (input.configPath !== undefined && input.record.configPath !== input.configPath) {
|
|
145
|
+
return { state: "conflict", reason: "unowned-key" };
|
|
146
|
+
}
|
|
147
|
+
if (fingerprint(input.fileText ?? "") !== input.record.fileFingerprint) {
|
|
148
|
+
return { state: "conflict", reason: "foreign-edit" };
|
|
149
|
+
}
|
|
150
|
+
return input.record.blockFingerprint === fingerprint(canonicalContribution(input.contribution))
|
|
151
|
+
? { state: "current" }
|
|
152
|
+
: { state: "stale" };
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
export interface IntegrationStateInput {
|
|
156
|
+
clientId: IntegrationClientId;
|
|
157
|
+
models: readonly ExportModel[];
|
|
158
|
+
config: OcxConfig;
|
|
159
|
+
port: number;
|
|
160
|
+
env?: NodeJS.ProcessEnv;
|
|
161
|
+
home?: string;
|
|
162
|
+
/** The whole integration state store, bound to one root. */
|
|
163
|
+
store?: IntegrationStateStore;
|
|
164
|
+
io?: IntegrationIO;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
export function exportContextOf(input: {
|
|
168
|
+
models: readonly ExportModel[];
|
|
169
|
+
config: OcxConfig;
|
|
170
|
+
port: number;
|
|
171
|
+
}): { baseUrl: string; models: readonly ExportModel[]; config: OcxConfig } {
|
|
172
|
+
return {
|
|
173
|
+
/*
|
|
174
|
+
* Composed through the SAME helper `rmx export` uses. Interpolating the
|
|
175
|
+
* hostname by hand looked equivalent and was not: `::1` produced
|
|
176
|
+
* `http://::1:10100/v1` and `::` produced `http://:::10100/v1`, neither of
|
|
177
|
+
* which is a URL, and a `0.0.0.0` bind wrote a wildcard address no client
|
|
178
|
+
* can dial. `opencodeProxyBaseUrl` brackets IPv6 and maps wildcards to
|
|
179
|
+
* loopback, and every client we write into deserves the same answer the
|
|
180
|
+
* export command already gives.
|
|
181
|
+
*/
|
|
182
|
+
baseUrl: opencodeProxyBaseUrl(input.port, input.config.hostname),
|
|
183
|
+
models: input.models,
|
|
184
|
+
config: input.config,
|
|
185
|
+
};
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
let retriedThisProcess = false;
|
|
189
|
+
|
|
190
|
+
/**
|
|
191
|
+
* Retry pending prunes once per process for the default store, and always for
|
|
192
|
+
* an explicitly supplied one so tests stay order-independent. Never throws: a
|
|
193
|
+
* retry failure is a logged no-op, not a failed read.
|
|
194
|
+
*/
|
|
195
|
+
export function retryPendingPrunesOnce(store: IntegrationStateStore): void {
|
|
196
|
+
if (store.root === createIntegrationStateStore().root) {
|
|
197
|
+
if (retriedThisProcess) return;
|
|
198
|
+
retriedThisProcess = true;
|
|
199
|
+
}
|
|
200
|
+
try {
|
|
201
|
+
store.retryPendingPrunes();
|
|
202
|
+
} catch (error) {
|
|
203
|
+
console.error(`[integrations] prune retry failed: ${String(error)}`);
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
/**
|
|
208
|
+
* Retention is derived from what is ON DISK, not from the maintenance marker.
|
|
209
|
+
* The marker schedules retries and can itself fail to write; a promise about
|
|
210
|
+
* the user's credential-bearing backups must not depend on that.
|
|
211
|
+
*/
|
|
212
|
+
function retentionOf(
|
|
213
|
+
clientId: IntegrationClientId,
|
|
214
|
+
store: IntegrationStateStore,
|
|
215
|
+
): { snapshotCount: number; retentionDegraded: boolean } {
|
|
216
|
+
const counted = store.countSnapshots(clientId);
|
|
217
|
+
if (counted === null) {
|
|
218
|
+
// Cannot inspect: report degraded with -1 rather than a reassuring zero.
|
|
219
|
+
return { snapshotCount: -1, retentionDegraded: true };
|
|
220
|
+
}
|
|
221
|
+
const marked = store.readMaintenance().pruneFailures[clientId] !== undefined;
|
|
222
|
+
return { snapshotCount: counted, retentionDegraded: marked || counted > SNAPSHOT_RETENTION };
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
/** The ONE reader every surface uses. */
|
|
226
|
+
export function readIntegrationState(input: IntegrationStateInput): IntegrationStatus {
|
|
227
|
+
const store = input.store ?? createIntegrationStateStore();
|
|
228
|
+
retryPendingPrunesOnce(store);
|
|
229
|
+
const io = input.io ?? store.io();
|
|
230
|
+
const spec = INTEGRATION_CLIENTS[input.clientId];
|
|
231
|
+
const exportSpec = EXPORT_CLIENTS[input.clientId];
|
|
232
|
+
const retention = retentionOf(input.clientId, store);
|
|
233
|
+
/*
|
|
234
|
+
* Resolution can refuse — a relative OPENCLAW_* selector names a file whose
|
|
235
|
+
* meaning depends on a working directory we cannot know. The LIST route asks
|
|
236
|
+
* every client for its state, so letting that escape would answer 500 for
|
|
237
|
+
* the whole Integrations page because one client is misconfigured.
|
|
238
|
+
*/
|
|
239
|
+
let configPath: string;
|
|
240
|
+
let installed: boolean;
|
|
241
|
+
try {
|
|
242
|
+
configPath = spec.configPath(input.env, input.home);
|
|
243
|
+
installed = io.statKind(spec.detectDir(input.env, input.home)) === "dir";
|
|
244
|
+
} catch (error) {
|
|
245
|
+
if (!(error instanceof ClientPathError)) throw error;
|
|
246
|
+
return {
|
|
247
|
+
clientId: input.clientId,
|
|
248
|
+
state: "unsafe",
|
|
249
|
+
installed: false,
|
|
250
|
+
configPath: "",
|
|
251
|
+
reason: "unresolvable-path",
|
|
252
|
+
...retention,
|
|
253
|
+
};
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
const target = loadTarget(io, configPath);
|
|
257
|
+
if (!target.ok) {
|
|
258
|
+
return {
|
|
259
|
+
clientId: input.clientId,
|
|
260
|
+
state: "unsafe",
|
|
261
|
+
installed,
|
|
262
|
+
configPath,
|
|
263
|
+
reason: target.why === "read-failed" ? "unparseable" : "not-regular-file",
|
|
264
|
+
...retention,
|
|
265
|
+
};
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
const parsed = parseConfig(target.before, exportSpec.format);
|
|
269
|
+
const contribution = exportSpec.buildContribution(exportContextOf(input));
|
|
270
|
+
const record = store.readRecords()[input.clientId] ?? null;
|
|
271
|
+
const { state, reason } = classifyIntegration({
|
|
272
|
+
fileText: target.before,
|
|
273
|
+
fileIsRegular: true,
|
|
274
|
+
parsed,
|
|
275
|
+
record,
|
|
276
|
+
contribution,
|
|
277
|
+
configPath,
|
|
278
|
+
clientId: input.clientId,
|
|
279
|
+
});
|
|
280
|
+
|
|
281
|
+
return {
|
|
282
|
+
clientId: input.clientId,
|
|
283
|
+
state,
|
|
284
|
+
installed,
|
|
285
|
+
configPath,
|
|
286
|
+
...(reason ? { reason } : {}),
|
|
287
|
+
...(record ? { appliedAt: record.appliedAt, lastOpId: record.opId } : {}),
|
|
288
|
+
...retention,
|
|
289
|
+
};
|
|
290
|
+
}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* One store, bound once.
|
|
3
|
+
*
|
|
4
|
+
* Passing a directory per call was not enough: retention would honor it while
|
|
5
|
+
* records, the journal and snapshots still resolved the global root, so an
|
|
6
|
+
* operation that believed itself isolated could read and mutate the developer's
|
|
7
|
+
* real store. Every method here derives from one `root`, and `io()` binds the
|
|
8
|
+
* bookkeeping seams to that same store so the two can never point at different
|
|
9
|
+
* roots.
|
|
10
|
+
*
|
|
11
|
+
* Design of record: devlog/_fin/260802_client_toggle_api/006 §Config-dir seam.
|
|
12
|
+
*/
|
|
13
|
+
import {
|
|
14
|
+
appendOperation,
|
|
15
|
+
captureSnapshot,
|
|
16
|
+
clearPruneFailure,
|
|
17
|
+
countSnapshots,
|
|
18
|
+
findOperation,
|
|
19
|
+
listOperations,
|
|
20
|
+
markPruneFailure,
|
|
21
|
+
pruneSnapshots,
|
|
22
|
+
readMaintenance,
|
|
23
|
+
readSnapshot,
|
|
24
|
+
type JournalEntry,
|
|
25
|
+
type MaintenanceState,
|
|
26
|
+
type SnapshotRef,
|
|
27
|
+
} from "./journal";
|
|
28
|
+
import { fileIO, type IntegrationIO } from "./config-io";
|
|
29
|
+
import {
|
|
30
|
+
deleteRecord,
|
|
31
|
+
integrationsDir,
|
|
32
|
+
readRecords,
|
|
33
|
+
writeRecord,
|
|
34
|
+
type OwnershipRecord,
|
|
35
|
+
} from "./ownership";
|
|
36
|
+
import type { IntegrationClientId } from "./registry";
|
|
37
|
+
|
|
38
|
+
export interface IntegrationStateStore {
|
|
39
|
+
/** The integrations directory itself — never a config root to resolve again. */
|
|
40
|
+
readonly root: string;
|
|
41
|
+
readRecords(): Partial<Record<IntegrationClientId, OwnershipRecord>>;
|
|
42
|
+
putRecord(record: OwnershipRecord): void;
|
|
43
|
+
dropRecord(clientId: IntegrationClientId): void;
|
|
44
|
+
appendJournal(entry: JournalEntry): void;
|
|
45
|
+
listOperations(clientId?: IntegrationClientId, limit?: number): JournalEntry[];
|
|
46
|
+
findOperation(opId: string): JournalEntry | null;
|
|
47
|
+
captureSnapshot(clientId: IntegrationClientId, opId: string, text: string | null): SnapshotRef;
|
|
48
|
+
readSnapshot(entry: JournalEntry):
|
|
49
|
+
| { kind: "none" }
|
|
50
|
+
| { kind: "stored"; text: string; path: string }
|
|
51
|
+
| { kind: "expired" };
|
|
52
|
+
countSnapshots(clientId: IntegrationClientId): number | null;
|
|
53
|
+
pruneSnapshots(clientId: IntegrationClientId): { ok: true } | { ok: false; error: string };
|
|
54
|
+
readMaintenance(): MaintenanceState;
|
|
55
|
+
markPruneFailure(clientId: IntegrationClientId, error: string): void;
|
|
56
|
+
clearPruneFailure(clientId: IntegrationClientId): void;
|
|
57
|
+
retryPendingPrunes(): void;
|
|
58
|
+
/** Filesystem seam with bookkeeping bound to THIS store. */
|
|
59
|
+
io(): IntegrationIO;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Bind every integration state path to ONE root.
|
|
64
|
+
*
|
|
65
|
+
* Ownership-manifest note: writes go through `atomicWriteFile`, which records
|
|
66
|
+
* the target in the opencodex uninstall manifest. That registration is scoped
|
|
67
|
+
* by `manifestRelativePath` and refuses any path outside the process config
|
|
68
|
+
* dir, so a store rooted in a temp dir — the shape every test uses — touches
|
|
69
|
+
* no global state. A store rooted UNDER the real config dir does register its
|
|
70
|
+
* files there, which is correct: those files genuinely are Remodex-owned and
|
|
71
|
+
* should be removed on uninstall.
|
|
72
|
+
*/
|
|
73
|
+
export function createIntegrationStateStore(root: string = integrationsDir()): IntegrationStateStore {
|
|
74
|
+
const dir = root;
|
|
75
|
+
const store: IntegrationStateStore = {
|
|
76
|
+
root: dir,
|
|
77
|
+
readRecords: () => readRecords(dir),
|
|
78
|
+
putRecord: record => writeRecord(record, dir),
|
|
79
|
+
dropRecord: clientId => deleteRecord(clientId, dir),
|
|
80
|
+
appendJournal: entry => appendOperation(entry, dir),
|
|
81
|
+
listOperations: (clientId, limit) => listOperations(clientId, limit, dir),
|
|
82
|
+
findOperation: opId => findOperation(opId, dir),
|
|
83
|
+
captureSnapshot: (clientId, opId, text) => captureSnapshot(clientId, opId, text, dir),
|
|
84
|
+
readSnapshot: entry => readSnapshot(entry, dir),
|
|
85
|
+
countSnapshots: clientId => countSnapshots(clientId, dir),
|
|
86
|
+
pruneSnapshots: clientId => pruneSnapshots(clientId, dir),
|
|
87
|
+
readMaintenance: () => readMaintenance(dir),
|
|
88
|
+
markPruneFailure: (clientId, error) => markPruneFailure(clientId, error, dir),
|
|
89
|
+
clearPruneFailure: clientId => clearPruneFailure(clientId, dir),
|
|
90
|
+
retryPendingPrunes: () => {
|
|
91
|
+
for (const clientId of Object.keys(store.readMaintenance().pruneFailures) as IntegrationClientId[]) {
|
|
92
|
+
if (store.pruneSnapshots(clientId).ok) store.clearPruneFailure(clientId);
|
|
93
|
+
}
|
|
94
|
+
},
|
|
95
|
+
io: () => ({
|
|
96
|
+
...fileIO(),
|
|
97
|
+
appendJournal: entry => store.appendJournal(entry),
|
|
98
|
+
putRecord: record => store.putRecord(record),
|
|
99
|
+
dropRecord: clientId => store.dropRecord(clientId),
|
|
100
|
+
}),
|
|
101
|
+
};
|
|
102
|
+
return store;
|
|
103
|
+
}
|