@camerontaylor/paseo-server 0.8.0-fork.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/.env.example +31 -0
- package/README.md +111 -0
- package/dist/scripts/dev-runner.js +37 -0
- package/dist/scripts/mcp-stdio-socket-bridge-cli.mjs +62 -0
- package/dist/scripts/supervisor-entrypoint.js +160 -0
- package/dist/scripts/supervisor-log-config.js +31 -0
- package/dist/scripts/supervisor.js +313 -0
- package/dist/server/executable-resolution/executable-resolution.d.ts +10 -0
- package/dist/server/executable-resolution/executable-resolution.js +121 -0
- package/dist/server/executable-resolution/windows.d.ts +18 -0
- package/dist/server/executable-resolution/windows.js +65 -0
- package/dist/server/server/agent/activity-curator.d.ts +40 -0
- package/dist/server/server/agent/activity-curator.js +243 -0
- package/dist/server/server/agent/agent-archive.d.ts +11 -0
- package/dist/server/server/agent/agent-archive.js +16 -0
- package/dist/server/server/agent/agent-configuration-validator.d.ts +18 -0
- package/dist/server/server/agent/agent-configuration-validator.js +42 -0
- package/dist/server/server/agent/agent-loading.d.ts +17 -0
- package/dist/server/server/agent/agent-loading.js +88 -0
- package/dist/server/server/agent/agent-manager.d.ts +555 -0
- package/dist/server/server/agent/agent-manager.js +3930 -0
- package/dist/server/server/agent/agent-owner.d.ts +12 -0
- package/dist/server/server/agent/agent-owner.js +12 -0
- package/dist/server/server/agent/agent-projections.d.ts +26 -0
- package/dist/server/server/agent/agent-projections.js +414 -0
- package/dist/server/server/agent/agent-prompt.d.ts +91 -0
- package/dist/server/server/agent/agent-prompt.js +359 -0
- package/dist/server/server/agent/agent-response-loop.d.ts +72 -0
- package/dist/server/server/agent/agent-response-loop.js +336 -0
- package/dist/server/server/agent/agent-run-state.d.ts +76 -0
- package/dist/server/server/agent/agent-run-state.js +212 -0
- package/dist/server/server/agent/agent-sdk-types.d.ts +742 -0
- package/dist/server/server/agent/agent-sdk-types.js +25 -0
- package/dist/server/server/agent/agent-storage.d.ts +148 -0
- package/dist/server/server/agent/agent-storage.js +401 -0
- package/dist/server/server/agent/agent-stream-coalescer.d.ts +43 -0
- package/dist/server/server/agent/agent-stream-coalescer.js +187 -0
- package/dist/server/server/agent/agent-timeline-content.d.ts +6 -0
- package/dist/server/server/agent/agent-timeline-content.js +62 -0
- package/dist/server/server/agent/agent-timeline-store-types.d.ts +54 -0
- package/dist/server/server/agent/agent-timeline-store-types.js +2 -0
- package/dist/server/server/agent/agent-timeline-store.d.ts +31 -0
- package/dist/server/server/agent/agent-timeline-store.js +249 -0
- package/dist/server/server/agent/audio-utils.d.ts +3 -0
- package/dist/server/server/agent/audio-utils.js +19 -0
- package/dist/server/server/agent/create-agent/create.d.ts +102 -0
- package/dist/server/server/agent/create-agent/create.js +362 -0
- package/dist/server/server/agent/create-agent/intent.d.ts +25 -0
- package/dist/server/server/agent/create-agent/intent.js +30 -0
- package/dist/server/server/agent/create-agent-lifecycle-dispatch.d.ts +65 -0
- package/dist/server/server/agent/create-agent-lifecycle-dispatch.js +166 -0
- package/dist/server/server/agent/create-agent-mode.d.ts +13 -0
- package/dist/server/server/agent/create-agent-mode.js +65 -0
- package/dist/server/server/agent/create-agent-title.d.ts +10 -0
- package/dist/server/server/agent/create-agent-title.js +34 -0
- package/dist/server/server/agent/dictation-debug.d.ts +13 -0
- package/dist/server/server/agent/dictation-debug.js +50 -0
- package/dist/server/server/agent/import-sessions.d.ts +57 -0
- package/dist/server/server/agent/import-sessions.js +240 -0
- package/dist/server/server/agent/lifecycle-command.d.ts +73 -0
- package/dist/server/server/agent/lifecycle-command.js +99 -0
- package/dist/server/server/agent/mcp-server.d.ts +5 -0
- package/dist/server/server/agent/mcp-server.js +31 -0
- package/dist/server/server/agent/mcp-shared.d.ts +181 -0
- package/dist/server/server/agent/mcp-shared.js +199 -0
- package/dist/server/server/agent/mutable-provider-config-owner.d.ts +8 -0
- package/dist/server/server/agent/mutable-provider-config-owner.js +35 -0
- package/dist/server/server/agent/paseo-tool-policy.d.ts +9 -0
- package/dist/server/server/agent/paseo-tool-policy.js +16 -0
- package/dist/server/server/agent/pcm16-resampler.d.ts +14 -0
- package/dist/server/server/agent/pcm16-resampler.js +63 -0
- package/dist/server/server/agent/permission-response.d.ts +15 -0
- package/dist/server/server/agent/permission-response.js +14 -0
- package/dist/server/server/agent/plugin-provider.d.ts +16 -0
- package/dist/server/server/agent/plugin-provider.js +1356 -0
- package/dist/server/server/agent/prompt-attachments.d.ts +12 -0
- package/dist/server/server/agent/prompt-attachments.js +182 -0
- package/dist/server/server/agent/provider-history-timestamps.d.ts +2 -0
- package/dist/server/server/agent/provider-history-timestamps.js +16 -0
- package/dist/server/server/agent/provider-launch-config.d.ts +43 -0
- package/dist/server/server/agent/provider-launch-config.js +167 -0
- package/dist/server/server/agent/provider-notices.d.ts +4 -0
- package/dist/server/server/agent/provider-notices.js +9 -0
- package/dist/server/server/agent/provider-options.d.ts +19 -0
- package/dist/server/server/agent/provider-options.js +53 -0
- package/dist/server/server/agent/provider-refresh-deadline.d.ts +11 -0
- package/dist/server/server/agent/provider-refresh-deadline.js +65 -0
- package/dist/server/server/agent/provider-registry.d.ts +72 -0
- package/dist/server/server/agent/provider-registry.js +604 -0
- package/dist/server/server/agent/provider-runtime.d.ts +16 -0
- package/dist/server/server/agent/provider-runtime.js +35 -0
- package/dist/server/server/agent/provider-session-import.d.ts +10 -0
- package/dist/server/server/agent/provider-session-import.js +55 -0
- package/dist/server/server/agent/provider-snapshot-manager.d.ts +166 -0
- package/dist/server/server/agent/provider-snapshot-manager.js +843 -0
- package/dist/server/server/agent/provider-subagents/store.d.ts +68 -0
- package/dist/server/server/agent/provider-subagents/store.js +111 -0
- package/dist/server/server/agent/providers/acp-agent.d.ts +703 -0
- package/dist/server/server/agent/providers/acp-agent.js +3412 -0
- package/dist/server/server/agent/providers/claude/agent.d.ts +74 -0
- package/dist/server/server/agent/providers/claude/agent.js +5236 -0
- package/dist/server/server/agent/providers/claude/feature-definitions.d.ts +8 -0
- package/dist/server/server/agent/providers/claude/feature-definitions.js +24 -0
- package/dist/server/server/agent/providers/claude/hooks.d.ts +12 -0
- package/dist/server/server/agent/providers/claude/hooks.js +20 -0
- package/dist/server/server/agent/providers/claude/model-manifest.d.ts +147 -0
- package/dist/server/server/agent/providers/claude/model-manifest.js +342 -0
- package/dist/server/server/agent/providers/claude/models.d.ts +28 -0
- package/dist/server/server/agent/providers/claude/models.js +141 -0
- package/dist/server/server/agent/providers/claude/options.d.ts +85 -0
- package/dist/server/server/agent/providers/claude/options.js +93 -0
- package/dist/server/server/agent/providers/claude/partial-json.d.ts +5 -0
- package/dist/server/server/agent/providers/claude/partial-json.js +306 -0
- package/dist/server/server/agent/providers/claude/project-dir.d.ts +6 -0
- package/dist/server/server/agent/providers/claude/project-dir.js +57 -0
- package/dist/server/server/agent/providers/claude/query.d.ts +17 -0
- package/dist/server/server/agent/providers/claude/query.js +86 -0
- package/dist/server/server/agent/providers/claude/rewind.d.ts +30 -0
- package/dist/server/server/agent/providers/claude/rewind.js +30 -0
- package/dist/server/server/agent/providers/claude/side-question.d.ts +16 -0
- package/dist/server/server/agent/providers/claude/side-question.js +57 -0
- package/dist/server/server/agent/providers/claude/sidechain-tracker.d.ts +35 -0
- package/dist/server/server/agent/providers/claude/sidechain-tracker.js +392 -0
- package/dist/server/server/agent/providers/claude/subagents/live-source.d.ts +161 -0
- package/dist/server/server/agent/providers/claude/subagents/live-source.js +415 -0
- package/dist/server/server/agent/providers/claude/subagents/observation.d.ts +53 -0
- package/dist/server/server/agent/providers/claude/subagents/observation.js +57 -0
- package/dist/server/server/agent/providers/claude/subagents/presentation.d.ts +12 -0
- package/dist/server/server/agent/providers/claude/subagents/presentation.js +41 -0
- package/dist/server/server/agent/providers/claude/subagents/replay-source.d.ts +70 -0
- package/dist/server/server/agent/providers/claude/subagents/replay-source.js +305 -0
- package/dist/server/server/agent/providers/claude/subagents/workflow-output.d.ts +4 -0
- package/dist/server/server/agent/providers/claude/subagents/workflow-output.js +86 -0
- package/dist/server/server/agent/providers/claude/subagents/workflow-replay-source.d.ts +38 -0
- package/dist/server/server/agent/providers/claude/subagents/workflow-replay-source.js +225 -0
- package/dist/server/server/agent/providers/claude/task-notification-tool-call.d.ts +37 -0
- package/dist/server/server/agent/providers/claude/task-notification-tool-call.js +296 -0
- package/dist/server/server/agent/providers/claude/task-state.d.ts +18 -0
- package/dist/server/server/agent/providers/claude/task-state.js +185 -0
- package/dist/server/server/agent/providers/claude/test-rewind-claude-sdk.d.ts +24 -0
- package/dist/server/server/agent/providers/claude/test-rewind-claude-sdk.js +23 -0
- package/dist/server/server/agent/providers/claude/tool-call-detail-parser.d.ts +3 -0
- package/dist/server/server/agent/providers/claude/tool-call-detail-parser.js +130 -0
- package/dist/server/server/agent/providers/claude/tool-call-mapper.d.ts +16 -0
- package/dist/server/server/agent/providers/claude/tool-call-mapper.js +129 -0
- package/dist/server/server/agent/providers/codex/app-server-transport.d.ts +101 -0
- package/dist/server/server/agent/providers/codex/app-server-transport.js +290 -0
- package/dist/server/server/agent/providers/codex/async-questions.d.ts +18 -0
- package/dist/server/server/agent/providers/codex/async-questions.js +135 -0
- package/dist/server/server/agent/providers/codex/options.d.ts +59 -0
- package/dist/server/server/agent/providers/codex/options.js +82 -0
- package/dist/server/server/agent/providers/codex/rewind.d.ts +24 -0
- package/dist/server/server/agent/providers/codex/rewind.js +77 -0
- package/dist/server/server/agent/providers/codex/tool-call-detail-parser.d.ts +12 -0
- package/dist/server/server/agent/providers/codex/tool-call-detail-parser.js +104 -0
- package/dist/server/server/agent/providers/codex/tool-call-mapper.d.ts +24 -0
- package/dist/server/server/agent/providers/codex/tool-call-mapper.js +909 -0
- package/dist/server/server/agent/providers/codex-app-server-agent.d.ts +384 -0
- package/dist/server/server/agent/providers/codex-app-server-agent.js +5877 -0
- package/dist/server/server/agent/providers/codex-feature-definitions.d.ts +11 -0
- package/dist/server/server/agent/providers/codex-feature-definitions.js +55 -0
- package/dist/server/server/agent/providers/copilot-acp-agent.d.ts +26 -0
- package/dist/server/server/agent/providers/copilot-acp-agent.js +187 -0
- package/dist/server/server/agent/providers/cursor-acp-agent.d.ts +17 -0
- package/dist/server/server/agent/providers/cursor-acp-agent.js +31 -0
- package/dist/server/server/agent/providers/diagnostic-utils.d.ts +36 -0
- package/dist/server/server/agent/providers/diagnostic-utils.js +356 -0
- package/dist/server/server/agent/providers/generic-acp-agent.d.ts +55 -0
- package/dist/server/server/agent/providers/generic-acp-agent.js +178 -0
- package/dist/server/server/agent/providers/gjc-acp-agent.d.ts +155 -0
- package/dist/server/server/agent/providers/gjc-acp-agent.js +588 -0
- package/dist/server/server/agent/providers/jsonl-frame-decoder.d.ts +17 -0
- package/dist/server/server/agent/providers/jsonl-frame-decoder.js +149 -0
- package/dist/server/server/agent/providers/jsonl-rpc-process.d.ts +63 -0
- package/dist/server/server/agent/providers/jsonl-rpc-process.js +207 -0
- package/dist/server/server/agent/providers/kimi-acp-agent.d.ts +35 -0
- package/dist/server/server/agent/providers/kimi-acp-agent.js +65 -0
- package/dist/server/server/agent/providers/kiro-acp-agent.d.ts +17 -0
- package/dist/server/server/agent/providers/kiro-acp-agent.js +78 -0
- package/dist/server/server/agent/providers/mock-load-test-agent.d.ts +111 -0
- package/dist/server/server/agent/providers/mock-load-test-agent.js +1340 -0
- package/dist/server/server/agent/providers/mock-slow-provider.d.ts +14 -0
- package/dist/server/server/agent/providers/mock-slow-provider.js +40 -0
- package/dist/server/server/agent/providers/omp/advisor-message.d.ts +11 -0
- package/dist/server/server/agent/providers/omp/advisor-message.js +80 -0
- package/dist/server/server/agent/providers/omp/agent.d.ts +178 -0
- package/dist/server/server/agent/providers/omp/agent.js +1952 -0
- package/dist/server/server/agent/providers/omp/cli-runtime.d.ts +22 -0
- package/dist/server/server/agent/providers/omp/cli-runtime.js +208 -0
- package/dist/server/server/agent/providers/omp/commands.d.ts +8 -0
- package/dist/server/server/agent/providers/omp/commands.js +62 -0
- package/dist/server/server/agent/providers/omp/custom-message.d.ts +7 -0
- package/dist/server/server/agent/providers/omp/custom-message.js +4 -0
- package/dist/server/server/agent/providers/omp/event-mapper.d.ts +13 -0
- package/dist/server/server/agent/providers/omp/event-mapper.js +267 -0
- package/dist/server/server/agent/providers/omp/history-hooks.d.ts +3 -0
- package/dist/server/server/agent/providers/omp/history-hooks.js +13 -0
- package/dist/server/server/agent/providers/omp/history.d.ts +19 -0
- package/dist/server/server/agent/providers/omp/history.js +306 -0
- package/dist/server/server/agent/providers/omp/host-tools.d.ts +14 -0
- package/dist/server/server/agent/providers/omp/host-tools.js +196 -0
- package/dist/server/server/agent/providers/omp/map-omp-model.d.ts +11 -0
- package/dist/server/server/agent/providers/omp/map-omp-model.js +67 -0
- package/dist/server/server/agent/providers/omp/message-history.d.ts +38 -0
- package/dist/server/server/agent/providers/omp/message-history.js +216 -0
- package/dist/server/server/agent/providers/omp/protocol-session.d.ts +13 -0
- package/dist/server/server/agent/providers/omp/protocol-session.js +39 -0
- package/dist/server/server/agent/providers/omp/provider-config.d.ts +43 -0
- package/dist/server/server/agent/providers/omp/provider-config.js +120 -0
- package/dist/server/server/agent/providers/omp/rpc-types.d.ts +2040 -0
- package/dist/server/server/agent/providers/omp/rpc-types.js +551 -0
- package/dist/server/server/agent/providers/omp/rpc-ui-permission-mapper.d.ts +24 -0
- package/dist/server/server/agent/providers/omp/rpc-ui-permission-mapper.js +156 -0
- package/dist/server/server/agent/providers/omp/runtime.d.ts +85 -0
- package/dist/server/server/agent/providers/omp/runtime.js +62 -0
- package/dist/server/server/agent/providers/omp/session-descriptor.d.ts +16 -0
- package/dist/server/server/agent/providers/omp/session-descriptor.js +389 -0
- package/dist/server/server/agent/providers/omp/subagent-card-tracker.d.ts +33 -0
- package/dist/server/server/agent/providers/omp/subagent-card-tracker.js +264 -0
- package/dist/server/server/agent/providers/omp/subagent-index.d.ts +13 -0
- package/dist/server/server/agent/providers/omp/subagent-index.js +111 -0
- package/dist/server/server/agent/providers/omp/subagent-title.d.ts +2 -0
- package/dist/server/server/agent/providers/omp/subagent-title.js +14 -0
- package/dist/server/server/agent/providers/omp/system-notice.d.ts +8 -0
- package/dist/server/server/agent/providers/omp/system-notice.js +68 -0
- package/dist/server/server/agent/providers/omp/todo-mapper.d.ts +9 -0
- package/dist/server/server/agent/providers/omp/todo-mapper.js +52 -0
- package/dist/server/server/agent/providers/omp/tool-call-detail.d.ts +110 -0
- package/dist/server/server/agent/providers/omp/tool-call-detail.js +288 -0
- package/dist/server/server/agent/providers/omp/tool-call-id.d.ts +4 -0
- package/dist/server/server/agent/providers/omp/tool-call-id.js +34 -0
- package/dist/server/server/agent/providers/omp/tool-call-mapper.d.ts +7 -0
- package/dist/server/server/agent/providers/omp/tool-call-mapper.js +98 -0
- package/dist/server/server/agent/providers/omp/usage-poller.d.ts +32 -0
- package/dist/server/server/agent/providers/omp/usage-poller.js +141 -0
- package/dist/server/server/agent/providers/opencode/bridge-plugin.bundle.mjs +14678 -0
- package/dist/server/server/agent/providers/opencode/bridge.d.ts +39 -0
- package/dist/server/server/agent/providers/opencode/bridge.js +249 -0
- package/dist/server/server/agent/providers/opencode/event-consumer.d.ts +60 -0
- package/dist/server/server/agent/providers/opencode/event-consumer.js +221 -0
- package/dist/server/server/agent/providers/opencode/options.d.ts +156 -0
- package/dist/server/server/agent/providers/opencode/options.js +62 -0
- package/dist/server/server/agent/providers/opencode/paths.d.ts +2 -0
- package/dist/server/server/agent/providers/opencode/paths.js +7 -0
- package/dist/server/server/agent/providers/opencode/rewind.d.ts +18 -0
- package/dist/server/server/agent/providers/opencode/rewind.js +14 -0
- package/dist/server/server/agent/providers/opencode/server-manager.d.ts +101 -0
- package/dist/server/server/agent/providers/opencode/server-manager.js +513 -0
- package/dist/server/server/agent/providers/opencode/side-question.d.ts +78 -0
- package/dist/server/server/agent/providers/opencode/side-question.js +172 -0
- package/dist/server/server/agent/providers/opencode/subagent-presentation.d.ts +36 -0
- package/dist/server/server/agent/providers/opencode/subagent-presentation.js +62 -0
- package/dist/server/server/agent/providers/opencode/test-server-manager.d.ts +22 -0
- package/dist/server/server/agent/providers/opencode/test-server-manager.js +43 -0
- package/dist/server/server/agent/providers/opencode/tool-call-detail-parser.d.ts +3 -0
- package/dist/server/server/agent/providers/opencode/tool-call-detail-parser.js +256 -0
- package/dist/server/server/agent/providers/opencode/tool-call-mapper.d.ts +13 -0
- package/dist/server/server/agent/providers/opencode/tool-call-mapper.js +53 -0
- package/dist/server/server/agent/providers/opencode-agent.d.ts +393 -0
- package/dist/server/server/agent/providers/opencode-agent.js +4106 -0
- package/dist/server/server/agent/providers/pi/agent.d.ts +164 -0
- package/dist/server/server/agent/providers/pi/agent.js +2236 -0
- package/dist/server/server/agent/providers/pi/cli-runtime.d.ts +21 -0
- package/dist/server/server/agent/providers/pi/cli-runtime.js +177 -0
- package/dist/server/server/agent/providers/pi/history-mapper.d.ts +36 -0
- package/dist/server/server/agent/providers/pi/history-mapper.js +212 -0
- package/dist/server/server/agent/providers/pi/rewind.d.ts +8 -0
- package/dist/server/server/agent/providers/pi/rewind.js +8 -0
- package/dist/server/server/agent/providers/pi/rpc-types.d.ts +252 -0
- package/dist/server/server/agent/providers/pi/rpc-types.js +2 -0
- package/dist/server/server/agent/providers/pi/runtime.d.ts +77 -0
- package/dist/server/server/agent/providers/pi/runtime.js +65 -0
- package/dist/server/server/agent/providers/pi/session-descriptor.d.ts +16 -0
- package/dist/server/server/agent/providers/pi/session-descriptor.js +355 -0
- package/dist/server/server/agent/providers/pi/tool-call-mapper.d.ts +113 -0
- package/dist/server/server/agent/providers/pi/tool-call-mapper.js +340 -0
- package/dist/server/server/agent/providers/pi/usage-poller.d.ts +32 -0
- package/dist/server/server/agent/providers/pi/usage-poller.js +141 -0
- package/dist/server/server/agent/providers/provider-image-output.d.ts +25 -0
- package/dist/server/server/agent/providers/provider-image-output.js +165 -0
- package/dist/server/server/agent/providers/provider-runner.d.ts +27 -0
- package/dist/server/server/agent/providers/provider-runner.js +81 -0
- package/dist/server/server/agent/providers/tool-call-detail-primitives.d.ts +884 -0
- package/dist/server/server/agent/providers/tool-call-detail-primitives.js +778 -0
- package/dist/server/server/agent/providers/tool-call-mapper-utils.d.ts +25 -0
- package/dist/server/server/agent/providers/tool-call-mapper-utils.js +208 -0
- package/dist/server/server/agent/providers/trae-acp-agent.d.ts +15 -0
- package/dist/server/server/agent/providers/trae-acp-agent.js +18 -0
- package/dist/server/server/agent/recordings-debug.d.ts +3 -0
- package/dist/server/server/agent/recordings-debug.js +19 -0
- package/dist/server/server/agent/rewind/rewind.d.ts +10 -0
- package/dist/server/server/agent/rewind/rewind.js +29 -0
- package/dist/server/server/agent/rewind/test-rewind-session.d.ts +48 -0
- package/dist/server/server/agent/rewind/test-rewind-session.js +88 -0
- package/dist/server/server/agent/runtime-mcp-config.d.ts +14 -0
- package/dist/server/server/agent/runtime-mcp-config.js +53 -0
- package/dist/server/server/agent/side-conversations/store.d.ts +33 -0
- package/dist/server/server/agent/side-conversations/store.js +62 -0
- package/dist/server/server/agent/stale-provider-session-error.d.ts +6 -0
- package/dist/server/server/agent/stale-provider-session-error.js +11 -0
- package/dist/server/server/agent/structured-generation-providers.d.ts +29 -0
- package/dist/server/server/agent/structured-generation-providers.js +193 -0
- package/dist/server/server/agent/stt-debug.d.ts +10 -0
- package/dist/server/server/agent/stt-debug.js +33 -0
- package/dist/server/server/agent/stt-manager.d.ts +38 -0
- package/dist/server/server/agent/stt-manager.js +246 -0
- package/dist/server/server/agent/system-prompt.d.ts +2 -0
- package/dist/server/server/agent/system-prompt.js +8 -0
- package/dist/server/server/agent/timeline-append.d.ts +10 -0
- package/dist/server/server/agent/timeline-append.js +27 -0
- package/dist/server/server/agent/timeline-page-bounds.d.ts +19 -0
- package/dist/server/server/agent/timeline-page-bounds.js +37 -0
- package/dist/server/server/agent/timeline-projection.d.ts +74 -0
- package/dist/server/server/agent/timeline-projection.js +467 -0
- package/dist/server/server/agent/timeline-prompt-index.d.ts +12 -0
- package/dist/server/server/agent/timeline-prompt-index.js +23 -0
- package/dist/server/server/agent/tools/paseo-tool-serialization.d.ts +4 -0
- package/dist/server/server/agent/tools/paseo-tool-serialization.js +58 -0
- package/dist/server/server/agent/tools/paseo-tools.d.ts +62 -0
- package/dist/server/server/agent/tools/paseo-tools.js +2445 -0
- package/dist/server/server/agent/tools/types.d.ts +39 -0
- package/dist/server/server/agent/tools/types.js +2 -0
- package/dist/server/server/agent/tts-debug.d.ts +8 -0
- package/dist/server/server/agent/tts-debug.js +24 -0
- package/dist/server/server/agent/tts-manager.d.ts +41 -0
- package/dist/server/server/agent/tts-manager.js +375 -0
- package/dist/server/server/agent-attention-policy.d.ts +29 -0
- package/dist/server/server/agent-attention-policy.js +36 -0
- package/dist/server/server/agent-history-search.d.ts +48 -0
- package/dist/server/server/agent-history-search.js +129 -0
- package/dist/server/server/atomic-file.d.ts +3 -0
- package/dist/server/server/atomic-file.js +19 -0
- package/dist/server/server/auth.d.ts +38 -0
- package/dist/server/server/auth.js +122 -0
- package/dist/server/server/authorization/index.d.ts +18 -0
- package/dist/server/server/authorization/index.js +47 -0
- package/dist/server/server/authorization/operation-permissions.d.ts +8 -0
- package/dist/server/server/authorization/operation-permissions.js +438 -0
- package/dist/server/server/auto-archive-on-merge/archive-if-safe.d.ts +40 -0
- package/dist/server/server/auto-archive-on-merge/archive-if-safe.js +64 -0
- package/dist/server/server/auto-archive-on-merge/index.d.ts +13 -0
- package/dist/server/server/auto-archive-on-merge/index.js +77 -0
- package/dist/server/server/bootstrap.d.ts +166 -0
- package/dist/server/server/bootstrap.js +1388 -0
- package/dist/server/server/browser-tools/broker.d.ts +45 -0
- package/dist/server/server/browser-tools/broker.js +390 -0
- package/dist/server/server/browser-tools/errors.d.ts +22 -0
- package/dist/server/server/browser-tools/errors.js +27 -0
- package/dist/server/server/browser-tools/policy.d.ts +10 -0
- package/dist/server/server/browser-tools/policy.js +16 -0
- package/dist/server/server/browser-tools/tools.d.ts +16 -0
- package/dist/server/server/browser-tools/tools.js +796 -0
- package/dist/server/server/checkout/status-projection.d.ts +19 -0
- package/dist/server/server/checkout/status-projection.js +127 -0
- package/dist/server/server/checkout-diff-manager.d.ts +48 -0
- package/dist/server/server/checkout-diff-manager.js +284 -0
- package/dist/server/server/checkout-git-utils.d.ts +11 -0
- package/dist/server/server/checkout-git-utils.js +34 -0
- package/dist/server/server/client-message-id.d.ts +3 -0
- package/dist/server/server/client-message-id.js +12 -0
- package/dist/server/server/config.d.ts +26 -0
- package/dist/server/server/config.js +594 -0
- package/dist/server/server/connection-offer.d.ts +20 -0
- package/dist/server/server/connection-offer.js +59 -0
- package/dist/server/server/creation/index.d.ts +41 -0
- package/dist/server/server/creation/index.js +250 -0
- package/dist/server/server/daemon-config-store.d.ts +63 -0
- package/dist/server/server/daemon-config-store.js +524 -0
- package/dist/server/server/daemon-keypair.d.ts +8 -0
- package/dist/server/server/daemon-keypair.js +42 -0
- package/dist/server/server/daemon-version.d.ts +5 -0
- package/dist/server/server/daemon-version.js +22 -0
- package/dist/server/server/daemon-worker.d.ts +2 -0
- package/dist/server/server/daemon-worker.js +287 -0
- package/dist/server/server/dictation/dictation-stream-manager.d.ts +88 -0
- package/dist/server/server/dictation/dictation-stream-manager.js +578 -0
- package/dist/server/server/directory-sync/index.d.ts +45 -0
- package/dist/server/server/directory-sync/index.js +98 -0
- package/dist/server/server/directory-sync/internal/versioned-collection.d.ts +56 -0
- package/dist/server/server/directory-sync/internal/versioned-collection.js +94 -0
- package/dist/server/server/exports.d.ts +24 -0
- package/dist/server/server/exports.js +24 -0
- package/dist/server/server/file-download/token-store.d.ts +24 -0
- package/dist/server/server/file-download/token-store.js +40 -0
- package/dist/server/server/file-explorer/observer.d.ts +32 -0
- package/dist/server/server/file-explorer/observer.js +130 -0
- package/dist/server/server/file-explorer/service.d.ts +125 -0
- package/dist/server/server/file-explorer/service.js +663 -0
- package/dist/server/server/file-observer/index.d.ts +43 -0
- package/dist/server/server/file-observer/index.js +114 -0
- package/dist/server/server/file-observer/internal/contracts.d.ts +26 -0
- package/dist/server/server/file-observer/internal/contracts.js +2 -0
- package/dist/server/server/file-observer/internal/linux.d.ts +4 -0
- package/dist/server/server/file-observer/internal/linux.js +260 -0
- package/dist/server/server/file-observer/internal/native-recursive.d.ts +9 -0
- package/dist/server/server/file-observer/internal/native-recursive.js +577 -0
- package/dist/server/server/file-observer/internal/observation.d.ts +21 -0
- package/dist/server/server/file-observer/internal/observation.js +129 -0
- package/dist/server/server/file-observer/internal/paths.d.ts +10 -0
- package/dist/server/server/file-observer/internal/paths.js +43 -0
- package/dist/server/server/file-upload/index.d.ts +27 -0
- package/dist/server/server/file-upload/index.js +158 -0
- package/dist/server/server/git-metadata-event-rules.d.ts +123 -0
- package/dist/server/server/git-metadata-event-rules.js +152 -0
- package/dist/server/server/hostnames.d.ts +13 -0
- package/dist/server/server/hostnames.js +94 -0
- package/dist/server/server/hub/daemon-executions.d.ts +89 -0
- package/dist/server/server/hub/daemon-executions.js +287 -0
- package/dist/server/server/hub/execution-controller.d.ts +30 -0
- package/dist/server/server/hub/execution-controller.js +220 -0
- package/dist/server/server/hub/relationship-controller.d.ts +116 -0
- package/dist/server/server/hub/relationship-controller.js +534 -0
- package/dist/server/server/hub/relationship-remote.d.ts +68 -0
- package/dist/server/server/hub/relationship-remote.js +159 -0
- package/dist/server/server/hub/relationship-retry.d.ts +7 -0
- package/dist/server/server/hub/relationship-retry.js +15 -0
- package/dist/server/server/json-utils.d.ts +11 -0
- package/dist/server/server/json-utils.js +45 -0
- package/dist/server/server/lifecycle-reasons.d.ts +4 -0
- package/dist/server/server/lifecycle-reasons.js +6 -0
- package/dist/server/server/logger.d.ts +29 -0
- package/dist/server/server/logger.js +127 -0
- package/dist/server/server/managed-processes/managed-processes.d.ts +76 -0
- package/dist/server/server/managed-processes/managed-processes.js +326 -0
- package/dist/server/server/messages.d.ts +9 -0
- package/dist/server/server/messages.js +29 -0
- package/dist/server/server/migrations/backfill-workspace-id.migration.d.ts +9 -0
- package/dist/server/server/migrations/backfill-workspace-id.migration.js +64 -0
- package/dist/server/server/orchestration-skills/index.d.ts +18 -0
- package/dist/server/server/orchestration-skills/index.js +18 -0
- package/dist/server/server/orchestration-skills/internal/controller.d.ts +39 -0
- package/dist/server/server/orchestration-skills/internal/controller.js +108 -0
- package/dist/server/server/orchestration-skills/internal/operations.d.ts +43 -0
- package/dist/server/server/orchestration-skills/internal/operations.js +178 -0
- package/dist/server/server/orchestration-skills/internal/paths.d.ts +4 -0
- package/dist/server/server/orchestration-skills/internal/paths.js +21 -0
- package/dist/server/server/orchestration-skills/internal/selection-store.d.ts +12 -0
- package/dist/server/server/orchestration-skills/internal/selection-store.js +39 -0
- package/dist/server/server/orchestration-skills/internal/sync.d.ts +21 -0
- package/dist/server/server/orchestration-skills/internal/sync.js +177 -0
- package/dist/server/server/orchestration-skills/internal/transaction.d.ts +22 -0
- package/dist/server/server/orchestration-skills/internal/transaction.js +483 -0
- package/dist/server/server/package-version.d.ts +19 -0
- package/dist/server/server/package-version.js +60 -0
- package/dist/server/server/pagination/cursor.d.ts +16 -0
- package/dist/server/server/pagination/cursor.js +62 -0
- package/dist/server/server/pagination/sortable-pager.d.ts +24 -0
- package/dist/server/server/pagination/sortable-pager.js +68 -0
- package/dist/server/server/pairing-offer.d.ts +18 -0
- package/dist/server/server/pairing-offer.js +47 -0
- package/dist/server/server/pairing-qr.d.ts +2 -0
- package/dist/server/server/pairing-qr.js +15 -0
- package/dist/server/server/paseo-env.d.ts +13 -0
- package/dist/server/server/paseo-env.js +54 -0
- package/dist/server/server/paseo-home.d.ts +2 -0
- package/dist/server/server/paseo-home.js +19 -0
- package/dist/server/server/paseo-worktree-service.d.ts +45 -0
- package/dist/server/server/paseo-worktree-service.js +191 -0
- package/dist/server/server/path-utils.d.ts +5 -0
- package/dist/server/server/path-utils.js +34 -0
- package/dist/server/server/persisted-config.d.ts +397 -0
- package/dist/server/server/persisted-config.js +411 -0
- package/dist/server/server/persistence-hooks.d.ts +32 -0
- package/dist/server/server/persistence-hooks.js +96 -0
- package/dist/server/server/pid-lock.d.ts +44 -0
- package/dist/server/server/pid-lock.js +285 -0
- package/dist/server/server/plugins/compiler-imports.d.ts +13 -0
- package/dist/server/server/plugins/compiler-imports.js +90 -0
- package/dist/server/server/plugins/compiler.d.ts +10 -0
- package/dist/server/server/plugins/compiler.js +354 -0
- package/dist/server/server/plugins/daemon-transport.d.ts +9 -0
- package/dist/server/server/plugins/daemon-transport.js +68 -0
- package/dist/server/server/plugins/index.d.ts +102 -0
- package/dist/server/server/plugins/index.js +575 -0
- package/dist/server/server/plugins/lifecycle/index.d.ts +40 -0
- package/dist/server/server/plugins/lifecycle/index.js +200 -0
- package/dist/server/server/plugins/managed-source.d.ts +50 -0
- package/dist/server/server/plugins/managed-source.js +327 -0
- package/dist/server/server/plugins/manifest.d.ts +12 -0
- package/dist/server/server/plugins/manifest.js +26 -0
- package/dist/server/server/plugins/plugin-process-protocol.d.ts +120 -0
- package/dist/server/server/plugins/plugin-process-protocol.js +154 -0
- package/dist/server/server/plugins/plugin-process.d.ts +2 -0
- package/dist/server/server/plugins/plugin-process.js +419 -0
- package/dist/server/server/plugins/plugin-sdk-specifiers.d.ts +5 -0
- package/dist/server/server/plugins/plugin-sdk-specifiers.js +23 -0
- package/dist/server/server/plugins/plugin-session-identity.d.ts +4 -0
- package/dist/server/server/plugins/plugin-session-identity.js +11 -0
- package/dist/server/server/plugins/preparation.d.ts +4 -0
- package/dist/server/server/plugins/preparation.js +49 -0
- package/dist/server/server/plugins/provider-icon.d.ts +2 -0
- package/dist/server/server/plugins/provider-icon.js +55 -0
- package/dist/server/server/plugins/runtime.d.ts +83 -0
- package/dist/server/server/plugins/runtime.js +836 -0
- package/dist/server/server/plugins/session-socket.d.ts +23 -0
- package/dist/server/server/plugins/session-socket.js +82 -0
- package/dist/server/server/plugins/settings/index.d.ts +96 -0
- package/dist/server/server/plugins/settings/index.js +115 -0
- package/dist/server/server/private-files.d.ts +6 -0
- package/dist/server/server/private-files.js +37 -0
- package/dist/server/server/process-diagnostics.d.ts +17 -0
- package/dist/server/server/process-diagnostics.js +22 -0
- package/dist/server/server/project-directory-service.d.ts +30 -0
- package/dist/server/server/project-directory-service.js +120 -0
- package/dist/server/server/project-key.d.ts +14 -0
- package/dist/server/server/project-key.js +44 -0
- package/dist/server/server/push/index.d.ts +16 -0
- package/dist/server/server/push/index.js +26 -0
- package/dist/server/server/push/push-service.d.ts +19 -0
- package/dist/server/server/push/push-service.js +66 -0
- package/dist/server/server/push/token-store.d.ts +22 -0
- package/dist/server/server/push/token-store.js +125 -0
- package/dist/server/server/relay-runtime.d.ts +27 -0
- package/dist/server/server/relay-runtime.js +46 -0
- package/dist/server/server/relay-transport.d.ts +33 -0
- package/dist/server/server/relay-transport.js +481 -0
- package/dist/server/server/request-receipts/index.d.ts +33 -0
- package/dist/server/server/request-receipts/index.js +131 -0
- package/dist/server/server/resolve-workspace-id-for-path.d.ts +3 -0
- package/dist/server/server/resolve-workspace-id-for-path.js +41 -0
- package/dist/server/server/resolve-worktree-creation-intent.d.ts +44 -0
- package/dist/server/server/resolve-worktree-creation-intent.js +186 -0
- package/dist/server/server/schedule/cron.d.ts +4 -0
- package/dist/server/server/schedule/cron.js +83 -0
- package/dist/server/server/schedule/service.d.ts +75 -0
- package/dist/server/server/schedule/service.js +810 -0
- package/dist/server/server/schedule/store.d.ts +27 -0
- package/dist/server/server/schedule/store.js +190 -0
- package/dist/server/server/script-health-monitor.d.ts +39 -0
- package/dist/server/server/script-health-monitor.js +159 -0
- package/dist/server/server/script-proxy.d.ts +3 -0
- package/dist/server/server/script-proxy.js +2 -0
- package/dist/server/server/script-route-branch-handler.d.ts +10 -0
- package/dist/server/server/script-route-branch-handler.js +11 -0
- package/dist/server/server/script-status-projection.d.ts +36 -0
- package/dist/server/server/script-status-projection.js +200 -0
- package/dist/server/server/server-id.d.ts +17 -0
- package/dist/server/server/server-id.js +68 -0
- package/dist/server/server/service-proxy.d.ts +237 -0
- package/dist/server/server/service-proxy.js +679 -0
- package/dist/server/server/session/agent-config/agent-config-session.d.ts +75 -0
- package/dist/server/server/session/agent-config/agent-config-session.js +151 -0
- package/dist/server/server/session/agent-updates/agent-updates-service.d.ts +65 -0
- package/dist/server/server/session/agent-updates/agent-updates-service.js +266 -0
- package/dist/server/server/session/checkout/checkout-session.d.ts +150 -0
- package/dist/server/server/session/checkout/checkout-session.js +1187 -0
- package/dist/server/server/session/checkout/git-metadata-generator.d.ts +53 -0
- package/dist/server/server/session/checkout/git-metadata-generator.js +159 -0
- package/dist/server/server/session/daemon/daemon-self-update-session-controller.d.ts +34 -0
- package/dist/server/server/session/daemon/daemon-self-update-session-controller.js +90 -0
- package/dist/server/server/session/daemon/daemon-self-updater.d.ts +33 -0
- package/dist/server/server/session/daemon/daemon-self-updater.js +60 -0
- package/dist/server/server/session/daemon/daemon-session.d.ts +90 -0
- package/dist/server/server/session/daemon/daemon-session.js +224 -0
- package/dist/server/server/session/daemon/diagnostics.d.ts +41 -0
- package/dist/server/server/session/daemon/diagnostics.js +431 -0
- package/dist/server/server/session/daemon/install-origin.d.ts +7 -0
- package/dist/server/server/session/daemon/install-origin.js +64 -0
- package/dist/server/server/session/daemon/npm-global-cli.d.ts +29 -0
- package/dist/server/server/session/daemon/npm-global-cli.js +98 -0
- package/dist/server/server/session/files/workspace-files-session.d.ts +55 -0
- package/dist/server/server/session/files/workspace-files-session.js +359 -0
- package/dist/server/server/session/git-mutation/git-mutation-service.d.ts +32 -0
- package/dist/server/server/session/git-mutation/git-mutation-service.js +74 -0
- package/dist/server/server/session/project-config/project-config-session.d.ts +35 -0
- package/dist/server/server/session/project-config/project-config-session.js +143 -0
- package/dist/server/server/session/project-config/worktree-setup-commit-status.d.ts +6 -0
- package/dist/server/server/session/project-config/worktree-setup-commit-status.js +38 -0
- package/dist/server/server/session/provider/provider-catalog-session.d.ts +78 -0
- package/dist/server/server/session/provider/provider-catalog-session.js +388 -0
- package/dist/server/server/session/schedule/schedule-session.d.ts +47 -0
- package/dist/server/server/session/schedule/schedule-session.js +188 -0
- package/dist/server/server/session/voice/voice-session.d.ts +166 -0
- package/dist/server/server/session/voice/voice-session.js +904 -0
- package/dist/server/server/session/voice/voice-turn-controller.d.ts +38 -0
- package/dist/server/server/session/voice/voice-turn-controller.js +393 -0
- package/dist/server/server/session/workspace-git-observer/workspace-git-observer-service.d.ts +42 -0
- package/dist/server/server/session/workspace-git-observer/workspace-git-observer-service.js +170 -0
- package/dist/server/server/session/workspace-provisioning/workspace-provisioning-service.d.ts +59 -0
- package/dist/server/server/session/workspace-provisioning/workspace-provisioning-service.js +326 -0
- package/dist/server/server/session/workspace-recovery/workspace-recovery-service.d.ts +30 -0
- package/dist/server/server/session/workspace-recovery/workspace-recovery-service.js +178 -0
- package/dist/server/server/session/workspace-scripts/workspace-scripts-service.d.ts +54 -0
- package/dist/server/server/session/workspace-scripts/workspace-scripts-service.js +156 -0
- package/dist/server/server/session.d.ts +555 -0
- package/dist/server/server/session.js +6540 -0
- package/dist/server/server/speech/audio.d.ts +10 -0
- package/dist/server/server/speech/audio.js +101 -0
- package/dist/server/server/speech/provider-resolver.d.ts +3 -0
- package/dist/server/server/speech/provider-resolver.js +7 -0
- package/dist/server/server/speech/providers/local/config.d.ts +30 -0
- package/dist/server/server/speech/providers/local/config.js +134 -0
- package/dist/server/server/speech/providers/local/models.d.ts +12 -0
- package/dist/server/server/speech/providers/local/models.js +18 -0
- package/dist/server/server/speech/providers/local/runtime.d.ts +31 -0
- package/dist/server/server/speech/providers/local/runtime.js +135 -0
- package/dist/server/server/speech/providers/local/sherpa/assets/silero_vad.onnx +0 -0
- package/dist/server/server/speech/providers/local/sherpa/model-catalog.d.ts +56 -0
- package/dist/server/server/speech/providers/local/sherpa/model-catalog.js +74 -0
- package/dist/server/server/speech/providers/local/sherpa/model-downloader.d.ts +17 -0
- package/dist/server/server/speech/providers/local/sherpa/model-downloader.js +145 -0
- package/dist/server/server/speech/providers/local/sherpa/sherpa-offline-recognizer.d.ts +49 -0
- package/dist/server/server/speech/providers/local/sherpa/sherpa-offline-recognizer.js +73 -0
- package/dist/server/server/speech/providers/local/sherpa/sherpa-onnx-node-loader.d.ts +9 -0
- package/dist/server/server/speech/providers/local/sherpa/sherpa-onnx-node-loader.js +107 -0
- package/dist/server/server/speech/providers/local/sherpa/sherpa-parakeet-realtime-session.d.ts +28 -0
- package/dist/server/server/speech/providers/local/sherpa/sherpa-parakeet-realtime-session.js +137 -0
- package/dist/server/server/speech/providers/local/sherpa/sherpa-parakeet-stt.d.ts +21 -0
- package/dist/server/server/speech/providers/local/sherpa/sherpa-parakeet-stt.js +133 -0
- package/dist/server/server/speech/providers/local/sherpa/sherpa-runtime-env.d.ts +18 -0
- package/dist/server/server/speech/providers/local/sherpa/sherpa-runtime-env.js +84 -0
- package/dist/server/server/speech/providers/local/sherpa/sherpa-tts.d.ts +21 -0
- package/dist/server/server/speech/providers/local/sherpa/sherpa-tts.js +101 -0
- package/dist/server/server/speech/providers/local/sherpa/silero-vad-provider.d.ts +19 -0
- package/dist/server/server/speech/providers/local/sherpa/silero-vad-provider.js +49 -0
- package/dist/server/server/speech/providers/local/sherpa/silero-vad-session.d.ts +38 -0
- package/dist/server/server/speech/providers/local/sherpa/silero-vad-session.js +176 -0
- package/dist/server/server/speech/providers/local/worker-bytes.d.ts +4 -0
- package/dist/server/server/speech/providers/local/worker-bytes.js +9 -0
- package/dist/server/server/speech/providers/local/worker-client.d.ts +93 -0
- package/dist/server/server/speech/providers/local/worker-client.js +590 -0
- package/dist/server/server/speech/providers/local/worker-process.d.ts +2 -0
- package/dist/server/server/speech/providers/local/worker-process.js +270 -0
- package/dist/server/server/speech/providers/local/worker-protocol.d.ts +95 -0
- package/dist/server/server/speech/providers/local/worker-protocol.js +2 -0
- package/dist/server/server/speech/providers/openai/config.d.ts +19 -0
- package/dist/server/server/speech/providers/openai/config.js +148 -0
- package/dist/server/server/speech/providers/openai/runtime.d.ts +29 -0
- package/dist/server/server/speech/providers/openai/runtime.js +102 -0
- package/dist/server/server/speech/providers/openai/stt.d.ts +23 -0
- package/dist/server/server/speech/providers/openai/stt.js +209 -0
- package/dist/server/server/speech/providers/openai/tts.d.ts +19 -0
- package/dist/server/server/speech/providers/openai/tts.js +48 -0
- package/dist/server/server/speech/speech-config-resolver.d.ts +11 -0
- package/dist/server/server/speech/speech-config-resolver.js +132 -0
- package/dist/server/server/speech/speech-provider.d.ts +59 -0
- package/dist/server/server/speech/speech-provider.js +2 -0
- package/dist/server/server/speech/speech-runtime.d.ts +45 -0
- package/dist/server/server/speech/speech-runtime.js +571 -0
- package/dist/server/server/speech/speech-types.d.ts +22 -0
- package/dist/server/server/speech/speech-types.js +8 -0
- package/dist/server/server/speech/turn-detection-provider.d.ts +23 -0
- package/dist/server/server/speech/turn-detection-provider.js +2 -0
- package/dist/server/server/utils/diff-highlighter.d.ts +57 -0
- package/dist/server/server/utils/diff-highlighter.js +304 -0
- package/dist/server/server/voice-config.d.ts +15 -0
- package/dist/server/server/voice-config.js +54 -0
- package/dist/server/server/voice-permission-policy.d.ts +4 -0
- package/dist/server/server/voice-permission-policy.js +13 -0
- package/dist/server/server/voice-types.d.ts +12 -0
- package/dist/server/server/voice-types.js +2 -0
- package/dist/server/server/watcher-liveness-canary.d.ts +11 -0
- package/dist/server/server/watcher-liveness-canary.js +53 -0
- package/dist/server/server/web-ui.d.ts +10 -0
- package/dist/server/server/web-ui.js +205 -0
- package/dist/server/server/websocket/encrypted-relay-socket.d.ts +23 -0
- package/dist/server/server/websocket/encrypted-relay-socket.js +64 -0
- package/dist/server/server/websocket/physical-socket.d.ts +36 -0
- package/dist/server/server/websocket/physical-socket.js +95 -0
- package/dist/server/server/websocket/runtime-metrics.d.ts +95 -0
- package/dist/server/server/websocket/runtime-metrics.js +148 -0
- package/dist/server/server/websocket-server.d.ts +214 -0
- package/dist/server/server/websocket-server.js +2258 -0
- package/dist/server/server/workspace-archive-service.d.ts +63 -0
- package/dist/server/server/workspace-archive-service.js +355 -0
- package/dist/server/server/workspace-auto-name.d.ts +55 -0
- package/dist/server/server/workspace-auto-name.js +127 -0
- package/dist/server/server/workspace-automation-gate.d.ts +16 -0
- package/dist/server/server/workspace-automation-gate.js +35 -0
- package/dist/server/server/workspace-bootstrap-dedupe.d.ts +34 -0
- package/dist/server/server/workspace-bootstrap-dedupe.js +23 -0
- package/dist/server/server/workspace-directory.d.ts +99 -0
- package/dist/server/server/workspace-directory.js +467 -0
- package/dist/server/server/workspace-git-fetch.d.ts +33 -0
- package/dist/server/server/workspace-git-fetch.js +108 -0
- package/dist/server/server/workspace-git-metadata.d.ts +8 -0
- package/dist/server/server/workspace-git-metadata.js +24 -0
- package/dist/server/server/workspace-git-service.d.ts +348 -0
- package/dist/server/server/workspace-git-service.js +2534 -0
- package/dist/server/server/workspace-labels/index.d.ts +14 -0
- package/dist/server/server/workspace-labels/index.js +10 -0
- package/dist/server/server/workspace-labels/internal/catalog-store.d.ts +50 -0
- package/dist/server/server/workspace-labels/internal/catalog-store.js +203 -0
- package/dist/server/server/workspace-labels/internal/sequence.d.ts +43 -0
- package/dist/server/server/workspace-labels/internal/sequence.js +80 -0
- package/dist/server/server/workspace-labels/internal/service.d.ts +57 -0
- package/dist/server/server/workspace-labels/internal/service.js +224 -0
- package/dist/server/server/workspace-reconciliation-service.d.ts +103 -0
- package/dist/server/server/workspace-reconciliation-service.js +379 -0
- package/dist/server/server/workspace-registry-bootstrap-legacy.d.ts +21 -0
- package/dist/server/server/workspace-registry-bootstrap-legacy.js +57 -0
- package/dist/server/server/workspace-registry-bootstrap.d.ts +14 -0
- package/dist/server/server/workspace-registry-bootstrap.js +155 -0
- package/dist/server/server/workspace-registry-model.d.ts +56 -0
- package/dist/server/server/workspace-registry-model.js +150 -0
- package/dist/server/server/workspace-registry.d.ts +228 -0
- package/dist/server/server/workspace-registry.js +468 -0
- package/dist/server/server/workspace-script-runtime-store.d.ts +28 -0
- package/dist/server/server/workspace-script-runtime-store.js +78 -0
- package/dist/server/server/workspace-service-env.d.ts +18 -0
- package/dist/server/server/workspace-service-env.js +85 -0
- package/dist/server/server/workspace-service-port-allocator.d.ts +11 -0
- package/dist/server/server/workspace-service-port-allocator.js +89 -0
- package/dist/server/server/workspace-service-port-registry.d.ts +24 -0
- package/dist/server/server/workspace-service-port-registry.js +172 -0
- package/dist/server/server/workspace-setup-runtime.d.ts +7 -0
- package/dist/server/server/workspace-setup-runtime.js +30 -0
- package/dist/server/server/workspace-source.d.ts +7 -0
- package/dist/server/server/workspace-source.js +15 -0
- package/dist/server/server/worktree/commands.d.ts +55 -0
- package/dist/server/server/worktree/commands.js +99 -0
- package/dist/server/server/worktree-bootstrap.d.ts +86 -0
- package/dist/server/server/worktree-bootstrap.js +753 -0
- package/dist/server/server/worktree-branch-name-generator.d.ts +35 -0
- package/dist/server/server/worktree-branch-name-generator.js +89 -0
- package/dist/server/server/worktree-core.d.ts +32 -0
- package/dist/server/server/worktree-core.js +114 -0
- package/dist/server/server/worktree-errors.d.ts +12 -0
- package/dist/server/server/worktree-errors.js +28 -0
- package/dist/server/server/worktree-session.d.ts +165 -0
- package/dist/server/server/worktree-session.js +594 -0
- package/dist/server/services/forge-cli-command.d.ts +128 -0
- package/dist/server/services/forge-cli-command.js +212 -0
- package/dist/server/services/forge-registry.d.ts +25 -0
- package/dist/server/services/forge-registry.js +155 -0
- package/dist/server/services/forge-resolver.d.ts +38 -0
- package/dist/server/services/forge-resolver.js +191 -0
- package/dist/server/services/forge-service.d.ts +430 -0
- package/dist/server/services/forge-service.js +50 -0
- package/dist/server/services/gitea-facts.d.ts +11 -0
- package/dist/server/services/gitea-facts.js +4 -0
- package/dist/server/services/gitea-service.d.ts +62 -0
- package/dist/server/services/gitea-service.js +1844 -0
- package/dist/server/services/github-facts.d.ts +27 -0
- package/dist/server/services/github-facts.js +4 -0
- package/dist/server/services/github-service.d.ts +76 -0
- package/dist/server/services/github-service.js +3297 -0
- package/dist/server/services/gitlab-facts.d.ts +26 -0
- package/dist/server/services/gitlab-facts.js +4 -0
- package/dist/server/services/gitlab-service.d.ts +43 -0
- package/dist/server/services/gitlab-service.js +1092 -0
- package/dist/server/services/quota-fetcher/manifest.d.ts +5 -0
- package/dist/server/services/quota-fetcher/manifest.js +118 -0
- package/dist/server/services/quota-fetcher/provider.d.ts +18 -0
- package/dist/server/services/quota-fetcher/provider.js +2 -0
- package/dist/server/services/quota-fetcher/providers/claude.d.ts +40 -0
- package/dist/server/services/quota-fetcher/providers/claude.js +389 -0
- package/dist/server/services/quota-fetcher/providers/codex.d.ts +23 -0
- package/dist/server/services/quota-fetcher/providers/codex.js +167 -0
- package/dist/server/services/quota-fetcher/providers/copilot.d.ts +21 -0
- package/dist/server/services/quota-fetcher/providers/copilot.js +77 -0
- package/dist/server/services/quota-fetcher/providers/cursor.d.ts +19 -0
- package/dist/server/services/quota-fetcher/providers/cursor.js +185 -0
- package/dist/server/services/quota-fetcher/providers/grok.d.ts +23 -0
- package/dist/server/services/quota-fetcher/providers/grok.js +137 -0
- package/dist/server/services/quota-fetcher/providers/kimi.d.ts +23 -0
- package/dist/server/services/quota-fetcher/providers/kimi.js +260 -0
- package/dist/server/services/quota-fetcher/providers/minimax.d.ts +29 -0
- package/dist/server/services/quota-fetcher/providers/minimax.js +227 -0
- package/dist/server/services/quota-fetcher/providers/zai.d.ts +17 -0
- package/dist/server/services/quota-fetcher/providers/zai.js +58 -0
- package/dist/server/services/quota-fetcher/service.d.ts +34 -0
- package/dist/server/services/quota-fetcher/service.js +74 -0
- package/dist/server/services/quota-fetcher/usage.d.ts +39 -0
- package/dist/server/services/quota-fetcher/usage.js +78 -0
- package/dist/server/skills/paseo/SKILL.md +129 -0
- package/dist/server/skills/paseo-advisor/SKILL.md +63 -0
- package/dist/server/skills/paseo-committee/SKILL.md +46 -0
- package/dist/server/skills/paseo-handoff/SKILL.md +65 -0
- package/dist/server/skills/paseo-help/SKILL.md +92 -0
- package/dist/server/skills/paseo-plugin/SKILL.md +639 -0
- package/dist/server/terminal/activity/terminal-activity-tracker.d.ts +21 -0
- package/dist/server/terminal/activity/terminal-activity-tracker.js +65 -0
- package/dist/server/terminal/agent-hooks/agent-hook-installer.d.ts +62 -0
- package/dist/server/terminal/agent-hooks/agent-hook-installer.js +117 -0
- package/dist/server/terminal/agent-hooks/claude/claude-settings.d.ts +7 -0
- package/dist/server/terminal/agent-hooks/claude/claude-settings.js +88 -0
- package/dist/server/terminal/agent-hooks/claude/claude.d.ts +4 -0
- package/dist/server/terminal/agent-hooks/claude/claude.js +47 -0
- package/dist/server/terminal/agent-hooks/codex/codex-settings.d.ts +7 -0
- package/dist/server/terminal/agent-hooks/codex/codex-settings.js +99 -0
- package/dist/server/terminal/agent-hooks/codex/codex.d.ts +4 -0
- package/dist/server/terminal/agent-hooks/codex/codex.js +30 -0
- package/dist/server/terminal/agent-hooks/opencode/opencode-plugin.d.ts +4 -0
- package/dist/server/terminal/agent-hooks/opencode/opencode-plugin.js +81 -0
- package/dist/server/terminal/agent-hooks/opencode/opencode.d.ts +3 -0
- package/dist/server/terminal/agent-hooks/opencode/opencode.js +23 -0
- package/dist/server/terminal/agent-hooks/provider-registry.d.ts +24 -0
- package/dist/server/terminal/agent-hooks/provider-registry.js +36 -0
- package/dist/server/terminal/agent-hooks/terminal-agent-hook-setting.d.ts +10 -0
- package/dist/server/terminal/agent-hooks/terminal-agent-hook-setting.js +26 -0
- package/dist/server/terminal/shell-integration/zsh/.zshenv +17 -0
- package/dist/server/terminal/shell-integration/zsh/paseo-integration.zsh +32 -0
- package/dist/server/terminal/terminal-capture.d.ts +12 -0
- package/dist/server/terminal/terminal-capture.js +43 -0
- package/dist/server/terminal/terminal-manager-factory.d.ts +6 -0
- package/dist/server/terminal/terminal-manager-factory.js +5 -0
- package/dist/server/terminal/terminal-manager.d.ts +80 -0
- package/dist/server/terminal/terminal-manager.js +321 -0
- package/dist/server/terminal/terminal-output-coalescer.d.ts +34 -0
- package/dist/server/terminal/terminal-output-coalescer.js +73 -0
- package/dist/server/terminal/terminal-restore.d.ts +18 -0
- package/dist/server/terminal/terminal-restore.js +52 -0
- package/dist/server/terminal/terminal-session-controller.d.ts +90 -0
- package/dist/server/terminal/terminal-session-controller.js +849 -0
- package/dist/server/terminal/terminal-size-ownership.d.ts +9 -0
- package/dist/server/terminal/terminal-size-ownership.js +23 -0
- package/dist/server/terminal/terminal-ts-loader.mjs +20 -0
- package/dist/server/terminal/terminal-worker-process.d.ts +2 -0
- package/dist/server/terminal/terminal-worker-process.js +308 -0
- package/dist/server/terminal/terminal-worker-protocol.d.ts +121 -0
- package/dist/server/terminal/terminal-worker-protocol.js +2 -0
- package/dist/server/terminal/terminal.d.ts +151 -0
- package/dist/server/terminal/terminal.js +1234 -0
- package/dist/server/terminal/worker-terminal-manager.d.ts +20 -0
- package/dist/server/terminal/worker-terminal-manager.js +688 -0
- package/dist/server/utils/build-metadata-prompt.d.ts +19 -0
- package/dist/server/utils/build-metadata-prompt.js +29 -0
- package/dist/server/utils/checkout-git.d.ts +317 -0
- package/dist/server/utils/checkout-git.js +2886 -0
- package/dist/server/utils/directory-suggestions.d.ts +29 -0
- package/dist/server/utils/directory-suggestions.js +596 -0
- package/dist/server/utils/git-command-runtime-metrics.d.ts +67 -0
- package/dist/server/utils/git-command-runtime-metrics.js +126 -0
- package/dist/server/utils/git-command-trace.d.ts +29 -0
- package/dist/server/utils/git-command-trace.js +74 -0
- package/dist/server/utils/git-process-scheduler.d.ts +34 -0
- package/dist/server/utils/git-process-scheduler.js +112 -0
- package/dist/server/utils/git-rev-parse-path.d.ts +3 -0
- package/dist/server/utils/git-rev-parse-path.js +21 -0
- package/dist/server/utils/paseo-config-file.d.ts +30 -0
- package/dist/server/utils/paseo-config-file.js +90 -0
- package/dist/server/utils/path.d.ts +27 -0
- package/dist/server/utils/path.js +156 -0
- package/dist/server/utils/project-custom-icon.d.ts +40 -0
- package/dist/server/utils/project-custom-icon.js +144 -0
- package/dist/server/utils/project-icon.d.ts +54 -0
- package/dist/server/utils/project-icon.js +445 -0
- package/dist/server/utils/promise-timeout.d.ts +9 -0
- package/dist/server/utils/promise-timeout.js +25 -0
- package/dist/server/utils/run-git-command.d.ts +59 -0
- package/dist/server/utils/run-git-command.js +393 -0
- package/dist/server/utils/spawn.d.ts +26 -0
- package/dist/server/utils/spawn.js +60 -0
- package/dist/server/utils/ssh-hostname.d.ts +8 -0
- package/dist/server/utils/ssh-hostname.js +60 -0
- package/dist/server/utils/string-command-shell.d.ts +13 -0
- package/dist/server/utils/string-command-shell.js +37 -0
- package/dist/server/utils/tree-kill.d.ts +19 -0
- package/dist/server/utils/tree-kill.js +77 -0
- package/dist/server/utils/windows-command.d.ts +15 -0
- package/dist/server/utils/windows-command.js +41 -0
- package/dist/server/utils/worktree-metadata.d.ts +77 -0
- package/dist/server/utils/worktree-metadata.js +280 -0
- package/dist/server/utils/worktree.d.ts +232 -0
- package/dist/server/utils/worktree.js +1193 -0
- package/dist/server/web-ui/_expo/static/css/xterm-3bb1704bf6cb0876640973dc0244b4cb.css +1 -0
- package/dist/server/web-ui/_expo/static/css/xterm-3bb1704bf6cb0876640973dc0244b4cb.css.br +0 -0
- package/dist/server/web-ui/_expo/static/css/xterm-3bb1704bf6cb0876640973dc0244b4cb.css.gz +0 -0
- package/dist/server/web-ui/_expo/static/js/web/desktop-attachment-bridge-29f33408b1a3c5b435c5202d62a36719.js +1 -0
- package/dist/server/web-ui/_expo/static/js/web/desktop-attachment-bridge-29f33408b1a3c5b435c5202d62a36719.js.br +0 -0
- package/dist/server/web-ui/_expo/static/js/web/desktop-attachment-bridge-29f33408b1a3c5b435c5202d62a36719.js.gz +0 -0
- package/dist/server/web-ui/_expo/static/js/web/desktop-attachment-store-41547ee520dfff946caa727824742a5c.js +1 -0
- package/dist/server/web-ui/_expo/static/js/web/desktop-attachment-store-41547ee520dfff946caa727824742a5c.js.br +0 -0
- package/dist/server/web-ui/_expo/static/js/web/desktop-attachment-store-41547ee520dfff946caa727824742a5c.js.gz +0 -0
- package/dist/server/web-ui/_expo/static/js/web/index-03b99be4265ac4a2bc5a6d602fd59cc4.js +16819 -0
- package/dist/server/web-ui/_expo/static/js/web/index-03b99be4265ac4a2bc5a6d602fd59cc4.js.br +0 -0
- package/dist/server/web-ui/_expo/static/js/web/index-03b99be4265ac4a2bc5a6d602fd59cc4.js.gz +0 -0
- package/dist/server/web-ui/_expo/static/js/web/indexeddb-attachment-store-5444610146b0794f1e7d9edad4522d41.js +1 -0
- package/dist/server/web-ui/_expo/static/js/web/indexeddb-attachment-store-5444610146b0794f1e7d9edad4522d41.js.br +0 -0
- package/dist/server/web-ui/_expo/static/js/web/indexeddb-attachment-store-5444610146b0794f1e7d9edad4522d41.js.gz +0 -0
- package/dist/server/web-ui/_expo/static/js/web/native-file-attachment-store-88b083190031a44788be59103814f511.js +3 -0
- package/dist/server/web-ui/_expo/static/js/web/native-file-attachment-store-88b083190031a44788be59103814f511.js.br +0 -0
- package/dist/server/web-ui/_expo/static/js/web/native-file-attachment-store-88b083190031a44788be59103814f511.js.gz +0 -0
- package/dist/server/web-ui/apple-touch-icon.png +0 -0
- package/dist/server/web-ui/assets/__node_modules/@react-navigation/elements/lib/module/assets/back-icon-mask.0a328cd9c1afd0afe8e3b1ec5165b1b4.png +0 -0
- package/dist/server/web-ui/assets/__node_modules/@react-navigation/elements/lib/module/assets/back-icon.35ba0eaec5a4f5ed12ca16fabeae451d.png +0 -0
- package/dist/server/web-ui/assets/__node_modules/@react-navigation/elements/lib/module/assets/clear-icon.c94f6478e7ae0cdd9f15de1fcb9e5e55.png +0 -0
- package/dist/server/web-ui/assets/__node_modules/@react-navigation/elements/lib/module/assets/clear-icon.c94f6478e7ae0cdd9f15de1fcb9e5e55@2x.png +0 -0
- package/dist/server/web-ui/assets/__node_modules/@react-navigation/elements/lib/module/assets/clear-icon.c94f6478e7ae0cdd9f15de1fcb9e5e55@3x.png +0 -0
- package/dist/server/web-ui/assets/__node_modules/@react-navigation/elements/lib/module/assets/clear-icon.c94f6478e7ae0cdd9f15de1fcb9e5e55@4x.png +0 -0
- package/dist/server/web-ui/assets/__node_modules/@react-navigation/elements/lib/module/assets/close-icon.808e1b1b9b53114ec2838071a7e6daa7.png +0 -0
- package/dist/server/web-ui/assets/__node_modules/@react-navigation/elements/lib/module/assets/close-icon.808e1b1b9b53114ec2838071a7e6daa7@2x.png +0 -0
- package/dist/server/web-ui/assets/__node_modules/@react-navigation/elements/lib/module/assets/close-icon.808e1b1b9b53114ec2838071a7e6daa7@3x.png +0 -0
- package/dist/server/web-ui/assets/__node_modules/@react-navigation/elements/lib/module/assets/close-icon.808e1b1b9b53114ec2838071a7e6daa7@4x.png +0 -0
- package/dist/server/web-ui/assets/__node_modules/@react-navigation/elements/lib/module/assets/search-icon.286d67d3f74808a60a78d3ebf1a5fb57.png +0 -0
- package/dist/server/web-ui/assets/__node_modules/expo-router/assets/arrow_down.017bc6ba3fc25503e5eb5e53826d48a8.png +0 -0
- package/dist/server/web-ui/assets/__node_modules/expo-router/assets/error.d1ea1496f9057eb392d5bbf3732a61b7.png +0 -0
- package/dist/server/web-ui/assets/__node_modules/expo-router/assets/file.19eeb73b9593a38f8e9f418337fc7d10.png +0 -0
- package/dist/server/web-ui/assets/__node_modules/expo-router/assets/forward.d8b800c443b8972542883e0b9de2bdc6.png +0 -0
- package/dist/server/web-ui/assets/__node_modules/expo-router/assets/pkg.ab19f4cbc543357183a20571f68380a3.png +0 -0
- package/dist/server/web-ui/assets/__node_modules/expo-router/assets/sitemap.412dd9275b6b48ad28f5e3d81bb1f626.png +0 -0
- package/dist/server/web-ui/assets/__node_modules/expo-router/assets/unmatched.20e71bdf79e3a97bf55fd9e164041578.png +0 -0
- package/dist/server/web-ui/assets/assets/images/favicon-dark-attention.882b3a27dcb2073e9e31b334f9ed9728.png +0 -0
- package/dist/server/web-ui/assets/assets/images/favicon-dark-running.8112342ff0d39e047a7f8d4fad9402f3.png +0 -0
- package/dist/server/web-ui/assets/assets/images/favicon-dark.8005ed36ac07a5a7c60de25780897bd4.png +0 -0
- package/dist/server/web-ui/assets/assets/images/favicon-light-attention.882b3a27dcb2073e9e31b334f9ed9728.png +0 -0
- package/dist/server/web-ui/assets/assets/images/favicon-light-running.8112342ff0d39e047a7f8d4fad9402f3.png +0 -0
- package/dist/server/web-ui/assets/assets/images/favicon-light.8005ed36ac07a5a7c60de25780897bd4.png +0 -0
- package/dist/server/web-ui/assets/assets/images/notification-icon.3bf81d33ddbf380606bdd248ba83e158.png +0 -0
- package/dist/server/web-ui/favicon.ico +0 -0
- package/dist/server/web-ui/index.html +90 -0
- package/dist/server/web-ui/index.html.br +0 -0
- package/dist/server/web-ui/index.html.gz +0 -0
- package/dist/server/web-ui/manifest.json +27 -0
- package/dist/server/web-ui/manifest.json.br +0 -0
- package/dist/server/web-ui/manifest.json.gz +0 -0
- package/dist/server/web-ui/metadata.json +1 -0
- package/dist/server/web-ui/metadata.json.br +1 -0
- package/dist/server/web-ui/metadata.json.gz +0 -0
- package/dist/server/web-ui/pwa-icon-192.png +0 -0
- package/dist/server/web-ui/pwa-icon-512.png +0 -0
- package/dist/server/web-ui/robots.txt +2 -0
- package/dist/src/executable-resolution/executable-resolution.js +121 -0
- package/dist/src/executable-resolution/windows.js +65 -0
- package/dist/src/server/agent/provider-launch-config.js +167 -0
- package/dist/src/server/paseo-env.js +54 -0
- package/dist/src/server/paseo-home.js +19 -0
- package/dist/src/server/persisted-config.js +411 -0
- package/dist/src/server/pid-lock.js +285 -0
- package/dist/src/server/private-files.js +37 -0
- package/dist/src/server/speech/providers/local/sherpa/sherpa-runtime-env.js +84 -0
- package/dist/src/terminal/shell-integration/zsh/.zshenv +17 -0
- package/dist/src/terminal/shell-integration/zsh/paseo-integration.zsh +32 -0
- package/dist/src/utils/spawn.js +60 -0
- package/dist/src/utils/tree-kill.js +77 -0
- package/dist/src/utils/windows-command.js +41 -0
- package/package.json +125 -0
|
@@ -0,0 +1,1844 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { CHECK_TRAIT_ACTION_REQUIRED, CHECK_TRAIT_WARNING } from "@camerontaylor/paseo-protocol/check-traits";
|
|
3
|
+
import { mapGiteaCommitState } from "@camerontaylor/paseo-protocol/gitea-status";
|
|
4
|
+
import pLimit from "p-limit";
|
|
5
|
+
import { parseGitHubRemoteIdentity, parseGitRemoteLocation } from "@camerontaylor/paseo-protocol/git-remote";
|
|
6
|
+
import { findExecutable } from "../executable-resolution/executable-resolution.js";
|
|
7
|
+
import { runGitCommand } from "../utils/run-git-command.js";
|
|
8
|
+
import { execCommand } from "../utils/spawn.js";
|
|
9
|
+
import { createCachedCliPathResolver, createForgeCliRunner, ForgeAuthenticationError, ForgeCliMissingError, CLI_AUTH_PROBE_TIMEOUT_MS, defaultResolveRemoteUrl, parseCliJsonOutput, ForgeCommandError, } from "./forge-cli-command.js";
|
|
10
|
+
import { computeChecksStatus, compareTimelineItems, createUnavailableSearchResult, normalizeForgeSearchKinds, parseOptionalTime, } from "./forge-service.js";
|
|
11
|
+
import { isGiteaStatusFacts } from "./gitea-facts.js";
|
|
12
|
+
const TEA_ENV = {
|
|
13
|
+
GIT_TERMINAL_PROMPT: "0",
|
|
14
|
+
};
|
|
15
|
+
const TEA_COMMAND_TIMEOUT_MS = 30000;
|
|
16
|
+
// The timeline's per-review comment fan-out spawns one `tea api` process per
|
|
17
|
+
// review that has comments; an unbounded Promise.allSettled over a PR with
|
|
18
|
+
// dozens of reviews would launch that many processes at once.
|
|
19
|
+
const REVIEW_COMMENTS_FAN_OUT_CONCURRENCY = 5;
|
|
20
|
+
const reviewCommentsLimit = pLimit(REVIEW_COMMENTS_FAN_OUT_CONCURRENCY);
|
|
21
|
+
// The client polls getCheckDetails every ~15s while a pipeline runs; without a
|
|
22
|
+
// short cache, each poll re-derives the PR head SHA from scratch (branch name +
|
|
23
|
+
// PR lookup + PR view). The TTL keeps a new push visible within one poll cycle.
|
|
24
|
+
const CURRENT_PR_HEAD_SHA_CACHE_TTL_MS = 30000;
|
|
25
|
+
// 50 is the page-size cap Gitea enforces on list endpoints; five pages bounds
|
|
26
|
+
// the sweep to the 250 most recent Actions tasks.
|
|
27
|
+
const GITEA_ACTION_PAGE_LIMIT = 50;
|
|
28
|
+
const GITEA_ACTION_MAX_PAGES = 5;
|
|
29
|
+
/**
|
|
30
|
+
* Fields requested from `tea pr list -o json`. tea's default field set omits the
|
|
31
|
+
* ones the neutral mapping needs (url, mergeable, base, head, ci, body), so they
|
|
32
|
+
* must be requested explicitly — otherwise tea silently emits the short default
|
|
33
|
+
* set and the mapping loses data.
|
|
34
|
+
*/
|
|
35
|
+
const PR_LIST_FIELDS = "index,state,author,url,title,body,mergeable,base,head,created,updated,labels,comments,ci";
|
|
36
|
+
const ISSUE_LIST_FIELDS = "index,state,author,url,title,body,labels,comments,created,updated";
|
|
37
|
+
const CURRENT_PR_LOOKUP_PAGE_SIZE = 50;
|
|
38
|
+
const CURRENT_PR_OPEN_LOOKUP_MAX_PAGES = 4;
|
|
39
|
+
const TIMELINE_PAGE_SIZE = 50;
|
|
40
|
+
const TIMELINE_MAX_PAGES_PER_BUCKET = 4;
|
|
41
|
+
export class TeaCliMissingError extends ForgeCliMissingError {
|
|
42
|
+
constructor() {
|
|
43
|
+
super("Gitea CLI (tea) is not installed or not in PATH");
|
|
44
|
+
this.name = "TeaCliMissingError";
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
export class TeaAuthenticationError extends ForgeAuthenticationError {
|
|
48
|
+
constructor(params) {
|
|
49
|
+
super("Gitea CLI authentication failed", params);
|
|
50
|
+
this.name = "TeaAuthenticationError";
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
export class TeaCommandError extends ForgeCommandError {
|
|
54
|
+
constructor(params) {
|
|
55
|
+
super({ brand: "Gitea", binary: "tea" }, params);
|
|
56
|
+
this.name = "TeaCommandError";
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* `tea pr list -o json` flattens every value to a string (e.g. `index:"5"`,
|
|
61
|
+
* `mergeable:"false"`, `comments:"0"`), unlike the single-PR view which is
|
|
62
|
+
* natively typed. The list schema therefore parses strings and the mapping
|
|
63
|
+
* coerces; `.passthrough()` tolerates the extra fields tea always includes.
|
|
64
|
+
*/
|
|
65
|
+
const GiteaPrListItemSchema = z
|
|
66
|
+
.object({
|
|
67
|
+
index: z.string(),
|
|
68
|
+
state: z.string(),
|
|
69
|
+
url: z.string(),
|
|
70
|
+
title: z.string(),
|
|
71
|
+
body: z.string().optional().default(""),
|
|
72
|
+
mergeable: z.string().optional(),
|
|
73
|
+
base: z.string().optional(),
|
|
74
|
+
head: z.string().optional(),
|
|
75
|
+
created: z.string().optional(),
|
|
76
|
+
updated: z.string().optional(),
|
|
77
|
+
labels: z.string().optional(),
|
|
78
|
+
ci: z.string().optional(),
|
|
79
|
+
})
|
|
80
|
+
.passthrough();
|
|
81
|
+
const GiteaIssueListItemSchema = z
|
|
82
|
+
.object({
|
|
83
|
+
index: z.string(),
|
|
84
|
+
state: z.string(),
|
|
85
|
+
url: z.string(),
|
|
86
|
+
title: z.string(),
|
|
87
|
+
body: z.string().optional().default(""),
|
|
88
|
+
labels: z.string().optional(),
|
|
89
|
+
updated: z.string().optional(),
|
|
90
|
+
})
|
|
91
|
+
.passthrough();
|
|
92
|
+
const GiteaLoginSchema = z
|
|
93
|
+
.object({
|
|
94
|
+
name: z.string().optional(),
|
|
95
|
+
url: z.string().optional(),
|
|
96
|
+
ssh_host: z.string().optional(),
|
|
97
|
+
})
|
|
98
|
+
.passthrough();
|
|
99
|
+
const GiteaUserSchema = z
|
|
100
|
+
.object({
|
|
101
|
+
login: z.string().optional(),
|
|
102
|
+
full_name: z.string().optional(),
|
|
103
|
+
avatar_url: z.string().nullable().optional(),
|
|
104
|
+
html_url: z.string().nullable().optional(),
|
|
105
|
+
})
|
|
106
|
+
.passthrough();
|
|
107
|
+
const GiteaPullRequestViewSchema = z
|
|
108
|
+
.object({
|
|
109
|
+
index: z.number(),
|
|
110
|
+
url: z.string(),
|
|
111
|
+
headSha: z.string().optional(),
|
|
112
|
+
title: z.string().optional().default(""),
|
|
113
|
+
state: z.string().optional().default("open"),
|
|
114
|
+
body: z.string().nullable().optional(),
|
|
115
|
+
base: z.string().optional(),
|
|
116
|
+
head: z.string().optional(),
|
|
117
|
+
mergeable: z.boolean().optional(),
|
|
118
|
+
hasMerged: z.boolean().optional(),
|
|
119
|
+
updated: z.string().optional(),
|
|
120
|
+
// tea emits labels as an array of label objects (or strings on older builds);
|
|
121
|
+
// tolerate both and extract the display name.
|
|
122
|
+
labels: z.array(z.union([z.string(), z.object({ name: z.string() }).passthrough()])).optional(),
|
|
123
|
+
})
|
|
124
|
+
.passthrough();
|
|
125
|
+
/**
|
|
126
|
+
* Subset of the Gitea/Forgejo REST PR object (`GET repos/{owner}/{repo}/pulls/{index}`)
|
|
127
|
+
* that `tea pr -o json` flattens away: the head/base repositories. Comparing their
|
|
128
|
+
* ids tells a fork PR (cross-repo) from a same-repo PR, and the head repo carries
|
|
129
|
+
* the contributor remote we push back to. `head.repo` is null when the fork was
|
|
130
|
+
* deleted, which we treat as same-repo.
|
|
131
|
+
*/
|
|
132
|
+
const GiteaPullRequestRepoSchema = z
|
|
133
|
+
.object({
|
|
134
|
+
id: z.number().optional(),
|
|
135
|
+
ssh_url: z.string().nullable().optional(),
|
|
136
|
+
html_url: z.string().nullable().optional(),
|
|
137
|
+
owner: z.object({ login: z.string().optional() }).passthrough().nullable().optional(),
|
|
138
|
+
})
|
|
139
|
+
.passthrough();
|
|
140
|
+
const GiteaPullRequestApiSchema = z
|
|
141
|
+
.object({
|
|
142
|
+
head: z
|
|
143
|
+
.object({ repo: GiteaPullRequestRepoSchema.nullable().optional() })
|
|
144
|
+
.passthrough()
|
|
145
|
+
.optional(),
|
|
146
|
+
base: z
|
|
147
|
+
.object({ repo: GiteaPullRequestRepoSchema.nullable().optional() })
|
|
148
|
+
.passthrough()
|
|
149
|
+
.optional(),
|
|
150
|
+
})
|
|
151
|
+
.passthrough();
|
|
152
|
+
const GiteaCurrentPullRequestApiSchema = z
|
|
153
|
+
.object({
|
|
154
|
+
number: z.number(),
|
|
155
|
+
html_url: z.string(),
|
|
156
|
+
title: z.string(),
|
|
157
|
+
body: z.string().nullable().optional(),
|
|
158
|
+
state: z.string(),
|
|
159
|
+
merged: z.boolean().optional(),
|
|
160
|
+
mergeable: z.boolean().nullable().optional(),
|
|
161
|
+
updated_at: z.string().optional(),
|
|
162
|
+
labels: z
|
|
163
|
+
.array(z.object({ name: z.string() }).passthrough())
|
|
164
|
+
.optional()
|
|
165
|
+
.default([]),
|
|
166
|
+
head: z
|
|
167
|
+
.object({
|
|
168
|
+
ref: z.string(),
|
|
169
|
+
sha: z.string(),
|
|
170
|
+
repo: GiteaPullRequestRepoSchema.nullable().optional(),
|
|
171
|
+
})
|
|
172
|
+
.passthrough(),
|
|
173
|
+
base: z
|
|
174
|
+
.object({
|
|
175
|
+
ref: z.string(),
|
|
176
|
+
repo: GiteaPullRequestRepoSchema.nullable().optional(),
|
|
177
|
+
})
|
|
178
|
+
.passthrough(),
|
|
179
|
+
})
|
|
180
|
+
.passthrough();
|
|
181
|
+
const GiteaCommitStatusSchema = z
|
|
182
|
+
.object({
|
|
183
|
+
id: z.number(),
|
|
184
|
+
status: z.string(),
|
|
185
|
+
target_url: z.string().nullable().optional(),
|
|
186
|
+
description: z.string().nullable().optional(),
|
|
187
|
+
url: z.string().nullable().optional(),
|
|
188
|
+
context: z.string().optional().default(""),
|
|
189
|
+
creator: z.unknown().nullable().optional(),
|
|
190
|
+
})
|
|
191
|
+
.passthrough();
|
|
192
|
+
const GiteaCombinedCommitStatusSchema = z
|
|
193
|
+
.object({
|
|
194
|
+
state: z.string().optional().default(""),
|
|
195
|
+
sha: z.string().optional(),
|
|
196
|
+
total_count: z.number().optional(),
|
|
197
|
+
statuses: z.array(GiteaCommitStatusSchema).optional().default([]),
|
|
198
|
+
})
|
|
199
|
+
.passthrough();
|
|
200
|
+
const GiteaActionTaskSchema = z
|
|
201
|
+
.object({
|
|
202
|
+
id: z.number(),
|
|
203
|
+
name: z.string().nullable().optional(),
|
|
204
|
+
head_branch: z.string().nullable().optional(),
|
|
205
|
+
head_sha: z.string(),
|
|
206
|
+
run_number: z.number().optional(),
|
|
207
|
+
event: z.string().nullable().optional(),
|
|
208
|
+
display_title: z.string().nullable().optional(),
|
|
209
|
+
status: z.string(),
|
|
210
|
+
need_approval: z.boolean().optional().default(false),
|
|
211
|
+
workflow_id: z.string().nullable().optional(),
|
|
212
|
+
url: z.string().nullable().optional(),
|
|
213
|
+
created_at: z.string().nullable().optional(),
|
|
214
|
+
run_started_at: z.string().nullable().optional(),
|
|
215
|
+
})
|
|
216
|
+
.passthrough();
|
|
217
|
+
// The item shape is validated per-task rather than as `z.array(GiteaActionTaskSchema)`
|
|
218
|
+
// so one malformed task (missing id/status/head_sha) drops only itself instead of
|
|
219
|
+
// throwing out the whole page and zeroing every Actions check for the PR.
|
|
220
|
+
const GiteaActionsListResponseSchema = z
|
|
221
|
+
.object({
|
|
222
|
+
workflow_runs: z.array(z.unknown()).optional().default([]),
|
|
223
|
+
total_count: z.number().optional(),
|
|
224
|
+
})
|
|
225
|
+
.passthrough();
|
|
226
|
+
const GiteaActionRunPullRequestRefSchema = z
|
|
227
|
+
.object({
|
|
228
|
+
repo: z.object({ id: z.number().optional() }).passthrough().nullable().optional(),
|
|
229
|
+
})
|
|
230
|
+
.passthrough();
|
|
231
|
+
const GiteaActionRunMetadataSchema = z
|
|
232
|
+
.object({
|
|
233
|
+
id: z.number().optional(),
|
|
234
|
+
run_number: z.number().optional(),
|
|
235
|
+
index_in_repo: z.number().optional(),
|
|
236
|
+
head_sha: z.string().optional(),
|
|
237
|
+
commit_sha: z.string().optional(),
|
|
238
|
+
status: z.string().optional(),
|
|
239
|
+
need_approval: z.boolean().optional().default(false),
|
|
240
|
+
pull_requests: z
|
|
241
|
+
.array(z
|
|
242
|
+
.object({
|
|
243
|
+
head: GiteaActionRunPullRequestRefSchema.optional(),
|
|
244
|
+
base: GiteaActionRunPullRequestRefSchema.optional(),
|
|
245
|
+
})
|
|
246
|
+
.passthrough())
|
|
247
|
+
.nullable()
|
|
248
|
+
.optional(),
|
|
249
|
+
})
|
|
250
|
+
.passthrough();
|
|
251
|
+
const GiteaIssueCommentSchema = z
|
|
252
|
+
.object({
|
|
253
|
+
id: z.number(),
|
|
254
|
+
html_url: z.string().optional(),
|
|
255
|
+
user: GiteaUserSchema.nullable().optional(),
|
|
256
|
+
body: z.string().optional().default(""),
|
|
257
|
+
created_at: z.string().optional(),
|
|
258
|
+
type: z.string().optional(),
|
|
259
|
+
})
|
|
260
|
+
.passthrough();
|
|
261
|
+
const GiteaReviewSchema = z
|
|
262
|
+
.object({
|
|
263
|
+
id: z.number(),
|
|
264
|
+
user: GiteaUserSchema.nullable().optional(),
|
|
265
|
+
state: z.string(),
|
|
266
|
+
body: z.string().optional().default(""),
|
|
267
|
+
comments_count: z.number().optional().default(0),
|
|
268
|
+
submitted_at: z.string().optional(),
|
|
269
|
+
updated_at: z.string().optional(),
|
|
270
|
+
html_url: z.string().optional(),
|
|
271
|
+
})
|
|
272
|
+
.passthrough();
|
|
273
|
+
const GiteaReviewCommentSchema = z
|
|
274
|
+
.object({
|
|
275
|
+
id: z.number(),
|
|
276
|
+
body: z.string().optional().default(""),
|
|
277
|
+
user: GiteaUserSchema.nullable().optional(),
|
|
278
|
+
pull_request_review_id: z.number().optional(),
|
|
279
|
+
created_at: z.string().optional(),
|
|
280
|
+
updated_at: z.string().optional(),
|
|
281
|
+
path: z.string().optional(),
|
|
282
|
+
position: z.number().optional(),
|
|
283
|
+
original_position: z.number().optional(),
|
|
284
|
+
resolver: GiteaUserSchema.nullable().optional(),
|
|
285
|
+
html_url: z.string().optional(),
|
|
286
|
+
})
|
|
287
|
+
.passthrough();
|
|
288
|
+
async function resolveTeaPath() {
|
|
289
|
+
return findExecutable("tea");
|
|
290
|
+
}
|
|
291
|
+
const teaCliRunner = createForgeCliRunner({
|
|
292
|
+
binary: "tea",
|
|
293
|
+
envOverlay: TEA_ENV,
|
|
294
|
+
timeoutMs: TEA_COMMAND_TIMEOUT_MS,
|
|
295
|
+
isAuthFailureText,
|
|
296
|
+
errorClasses: {
|
|
297
|
+
isAlreadyClassified: (candidate) => candidate instanceof TeaAuthenticationError || candidate instanceof TeaCliMissingError,
|
|
298
|
+
isCommandError: (candidate) => candidate instanceof TeaCommandError,
|
|
299
|
+
createAuthError: (stderr) => new TeaAuthenticationError({ stderr }),
|
|
300
|
+
createMissingError: () => new TeaCliMissingError(),
|
|
301
|
+
createCommandError: (params) => new TeaCommandError(params),
|
|
302
|
+
},
|
|
303
|
+
});
|
|
304
|
+
async function runTeaCommand(args, options) {
|
|
305
|
+
return teaCliRunner.run(args, options);
|
|
306
|
+
}
|
|
307
|
+
async function defaultResolveCurrentBranch(cwd) {
|
|
308
|
+
try {
|
|
309
|
+
const { stdout } = await runGitCommand(["branch", "--show-current"], { cwd });
|
|
310
|
+
const branch = stdout.trim();
|
|
311
|
+
return branch.length > 0 ? branch : null;
|
|
312
|
+
}
|
|
313
|
+
catch {
|
|
314
|
+
return null;
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
export function parseGiteaHostFromRemoteUrl(url) {
|
|
318
|
+
return parseGitRemoteLocation(url)?.host ?? null;
|
|
319
|
+
}
|
|
320
|
+
/**
|
|
321
|
+
* tea numeric fields arrive as strings in list output. Returns null for a
|
|
322
|
+
* missing/non-numeric value so callers can decide on a fallback.
|
|
323
|
+
*/
|
|
324
|
+
function parseGiteaInt(value) {
|
|
325
|
+
if (value === undefined || value.trim() === "") {
|
|
326
|
+
return null;
|
|
327
|
+
}
|
|
328
|
+
const parsed = Number.parseInt(value, 10);
|
|
329
|
+
return Number.isFinite(parsed) ? parsed : null;
|
|
330
|
+
}
|
|
331
|
+
function parseGiteaBool(value) {
|
|
332
|
+
return value?.trim().toLowerCase() === "true";
|
|
333
|
+
}
|
|
334
|
+
function timelineApiPath(input, suffix) {
|
|
335
|
+
const owner = encodeURIComponent(input.repoOwner);
|
|
336
|
+
const repo = encodeURIComponent(input.repoName);
|
|
337
|
+
return `repos/${owner}/${repo}/${suffix}`;
|
|
338
|
+
}
|
|
339
|
+
function timelinePageQuery(page) {
|
|
340
|
+
return `page=${page}&limit=${TIMELINE_PAGE_SIZE}`;
|
|
341
|
+
}
|
|
342
|
+
function giteaUserLogin(user) {
|
|
343
|
+
return user?.login ?? user?.full_name ?? "unknown";
|
|
344
|
+
}
|
|
345
|
+
function giteaUserUrl(user) {
|
|
346
|
+
return user?.html_url ?? null;
|
|
347
|
+
}
|
|
348
|
+
function giteaUserAvatar(user) {
|
|
349
|
+
return user?.avatar_url ?? null;
|
|
350
|
+
}
|
|
351
|
+
function isGiteaSystemComment(comment) {
|
|
352
|
+
return comment.type !== undefined && comment.type !== "comment";
|
|
353
|
+
}
|
|
354
|
+
function toGiteaReviewState(state) {
|
|
355
|
+
switch (state.trim().toUpperCase()) {
|
|
356
|
+
case "APPROVED":
|
|
357
|
+
case "APPROVE":
|
|
358
|
+
return "approved";
|
|
359
|
+
case "REQUEST_CHANGES":
|
|
360
|
+
case "REQUESTED_CHANGES":
|
|
361
|
+
case "CHANGES_REQUESTED":
|
|
362
|
+
return "changes_requested";
|
|
363
|
+
default:
|
|
364
|
+
return "commented";
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
function toGiteaTimelineComment(comment, pr) {
|
|
368
|
+
if (isGiteaSystemComment(comment)) {
|
|
369
|
+
return null;
|
|
370
|
+
}
|
|
371
|
+
return {
|
|
372
|
+
kind: "comment",
|
|
373
|
+
id: String(comment.id),
|
|
374
|
+
author: giteaUserLogin(comment.user),
|
|
375
|
+
authorUrl: giteaUserUrl(comment.user),
|
|
376
|
+
avatarUrl: giteaUserAvatar(comment.user),
|
|
377
|
+
body: comment.body,
|
|
378
|
+
createdAt: parseOptionalTime(comment.created_at),
|
|
379
|
+
url: comment.html_url ?? `${pr.url}#issuecomment-${comment.id}`,
|
|
380
|
+
};
|
|
381
|
+
}
|
|
382
|
+
function toGiteaTimelineReview(review) {
|
|
383
|
+
return {
|
|
384
|
+
kind: "review",
|
|
385
|
+
id: String(review.id),
|
|
386
|
+
author: giteaUserLogin(review.user),
|
|
387
|
+
authorUrl: giteaUserUrl(review.user),
|
|
388
|
+
avatarUrl: giteaUserAvatar(review.user),
|
|
389
|
+
body: review.body,
|
|
390
|
+
createdAt: parseOptionalTime(review.submitted_at ?? review.updated_at),
|
|
391
|
+
url: review.html_url ?? "",
|
|
392
|
+
reviewState: toGiteaReviewState(review.state),
|
|
393
|
+
};
|
|
394
|
+
}
|
|
395
|
+
/**
|
|
396
|
+
* Gitea/Forgejo expose no stable review-thread id, so distinct inline locations
|
|
397
|
+
* within one review all share a single `pull_request_review_id`. Keying threads
|
|
398
|
+
* on that id collapses unrelated file/line comments into one card. Instead key
|
|
399
|
+
* on the diff position (path + position), which a reply to the same inline
|
|
400
|
+
* thread reuses, so distinct locations stay separate while same-location replies
|
|
401
|
+
* still group, matching GitHub's review-thread grouping as closely as the API
|
|
402
|
+
* allows. Without a diff position (comment scrolled out of the current diff),
|
|
403
|
+
* fall back to the comment's own id so unrelated comments never merge.
|
|
404
|
+
*/
|
|
405
|
+
function giteaReviewCommentThreadId(comment) {
|
|
406
|
+
const position = comment.position ?? comment.original_position ?? null;
|
|
407
|
+
const anchor = position != null ? `pos-${position}` : `comment-${comment.id}`;
|
|
408
|
+
return `${comment.path}#${anchor}`;
|
|
409
|
+
}
|
|
410
|
+
/**
|
|
411
|
+
* Gitea/Forgejo set `resolver` to the user who resolved an inline review thread,
|
|
412
|
+
* or null when it is still open. Older servers omit the field entirely; treat
|
|
413
|
+
* absence as "unknown" and leave `isResolved` off rather than guessing unresolved.
|
|
414
|
+
*/
|
|
415
|
+
function giteaReviewCommentResolved(comment) {
|
|
416
|
+
if (!("resolver" in comment)) {
|
|
417
|
+
return undefined;
|
|
418
|
+
}
|
|
419
|
+
return comment.resolver != null;
|
|
420
|
+
}
|
|
421
|
+
function toGiteaReviewCommentLocation(comment) {
|
|
422
|
+
if (!comment.path) {
|
|
423
|
+
return undefined;
|
|
424
|
+
}
|
|
425
|
+
const isResolved = giteaReviewCommentResolved(comment);
|
|
426
|
+
return {
|
|
427
|
+
path: comment.path,
|
|
428
|
+
...(comment.position != null ? { line: comment.position } : {}),
|
|
429
|
+
threadId: giteaReviewCommentThreadId(comment),
|
|
430
|
+
...(isResolved !== undefined ? { isResolved } : {}),
|
|
431
|
+
};
|
|
432
|
+
}
|
|
433
|
+
function toGiteaTimelineReviewComment(comment) {
|
|
434
|
+
const location = toGiteaReviewCommentLocation(comment);
|
|
435
|
+
return {
|
|
436
|
+
kind: "comment",
|
|
437
|
+
id: String(comment.id),
|
|
438
|
+
author: giteaUserLogin(comment.user),
|
|
439
|
+
authorUrl: giteaUserUrl(comment.user),
|
|
440
|
+
avatarUrl: giteaUserAvatar(comment.user),
|
|
441
|
+
body: comment.body,
|
|
442
|
+
createdAt: parseOptionalTime(comment.created_at ?? comment.updated_at),
|
|
443
|
+
url: comment.html_url ?? "",
|
|
444
|
+
...(comment.pull_request_review_id != null
|
|
445
|
+
? { reviewId: String(comment.pull_request_review_id) }
|
|
446
|
+
: {}),
|
|
447
|
+
...(location ? { location } : {}),
|
|
448
|
+
};
|
|
449
|
+
}
|
|
450
|
+
function splitGiteaLabels(value) {
|
|
451
|
+
if (!value) {
|
|
452
|
+
return [];
|
|
453
|
+
}
|
|
454
|
+
return value
|
|
455
|
+
.split(",")
|
|
456
|
+
.map((label) => label.trim())
|
|
457
|
+
.filter((label) => label.length > 0);
|
|
458
|
+
}
|
|
459
|
+
/**
|
|
460
|
+
* tea reports a PR head as `owner:branch` for cross-repo PRs and a bare branch
|
|
461
|
+
* for same-repo ones. The neutral head ref is always just the branch name.
|
|
462
|
+
*/
|
|
463
|
+
function stripHeadOwner(head) {
|
|
464
|
+
if (!head) {
|
|
465
|
+
return "";
|
|
466
|
+
}
|
|
467
|
+
const colon = head.indexOf(":");
|
|
468
|
+
return colon >= 0 ? head.slice(colon + 1) : head;
|
|
469
|
+
}
|
|
470
|
+
function headHasOwner(head) {
|
|
471
|
+
return head !== undefined && head.indexOf(":") >= 0;
|
|
472
|
+
}
|
|
473
|
+
/**
|
|
474
|
+
* The head repo owner for a PR list item: the `owner:` prefix for a cross-repo
|
|
475
|
+
* (fork) head, otherwise the base repo owner parsed from the item URL, since a
|
|
476
|
+
* same-repo head arrives as a bare branch. Returns null when neither is known.
|
|
477
|
+
*/
|
|
478
|
+
function giteaHeadOwner(item) {
|
|
479
|
+
const head = item.head;
|
|
480
|
+
if (head) {
|
|
481
|
+
const colon = head.indexOf(":");
|
|
482
|
+
if (colon >= 0) {
|
|
483
|
+
return head.slice(0, colon);
|
|
484
|
+
}
|
|
485
|
+
}
|
|
486
|
+
return parseGiteaRepoFromUrl(item.url).owner ?? null;
|
|
487
|
+
}
|
|
488
|
+
/**
|
|
489
|
+
* Match a PR list item to the checkout's current head. Two open PRs from
|
|
490
|
+
* different forks can share a branch name (`alice:fix` vs `bob:fix`), so the
|
|
491
|
+
* branch alone is ambiguous. When the checkout's head owner is known, require
|
|
492
|
+
* the head repo owner to match it too; when it cannot be determined, accept only
|
|
493
|
+
* a same-repo (bare) head so a colliding cross-fork PR is never picked blindly.
|
|
494
|
+
*/
|
|
495
|
+
function matchesCurrentHeadRef(item, headRef, expectedHeadOwner) {
|
|
496
|
+
if (stripHeadOwner(item.head) !== headRef) {
|
|
497
|
+
return false;
|
|
498
|
+
}
|
|
499
|
+
if (expectedHeadOwner === null) {
|
|
500
|
+
return !headHasOwner(item.head);
|
|
501
|
+
}
|
|
502
|
+
return giteaHeadOwner(item) === expectedHeadOwner;
|
|
503
|
+
}
|
|
504
|
+
function mapGiteaState(state) {
|
|
505
|
+
const normalized = state.toLowerCase();
|
|
506
|
+
if (normalized === "open") {
|
|
507
|
+
return "open";
|
|
508
|
+
}
|
|
509
|
+
if (normalized === "merged") {
|
|
510
|
+
return "merged";
|
|
511
|
+
}
|
|
512
|
+
return "closed";
|
|
513
|
+
}
|
|
514
|
+
function mapGiteaMergeable(item) {
|
|
515
|
+
if (item.mergeable === undefined) {
|
|
516
|
+
return "UNKNOWN";
|
|
517
|
+
}
|
|
518
|
+
return parseGiteaBool(item.mergeable) ? "MERGEABLE" : "CONFLICTING";
|
|
519
|
+
}
|
|
520
|
+
function mapGiteaCiStatus(ci) {
|
|
521
|
+
switch (ci?.toLowerCase()) {
|
|
522
|
+
case "success":
|
|
523
|
+
return "success";
|
|
524
|
+
case "failure":
|
|
525
|
+
case "error":
|
|
526
|
+
// Gitea's "warning" is a terminal, NON-passing state: IsSuccess() is false,
|
|
527
|
+
// it fails required-status checks, and Gitea itself blocks the merge on it.
|
|
528
|
+
// Our neutral enum has no yellow/neutral bucket, so surface it as failure —
|
|
529
|
+
// never success (misleading green) or pending (never-resolving poll).
|
|
530
|
+
case "warning":
|
|
531
|
+
return "failure";
|
|
532
|
+
case "pending":
|
|
533
|
+
case "running":
|
|
534
|
+
return "pending";
|
|
535
|
+
default:
|
|
536
|
+
return "none";
|
|
537
|
+
}
|
|
538
|
+
}
|
|
539
|
+
function mapGiteaActionTaskStatus(status) {
|
|
540
|
+
switch (status.toLowerCase()) {
|
|
541
|
+
case "success":
|
|
542
|
+
return "success";
|
|
543
|
+
case "failure":
|
|
544
|
+
case "failed":
|
|
545
|
+
case "error":
|
|
546
|
+
return "failure";
|
|
547
|
+
case "cancelled":
|
|
548
|
+
case "canceled":
|
|
549
|
+
return "cancelled";
|
|
550
|
+
case "skipped":
|
|
551
|
+
return "skipped";
|
|
552
|
+
case "pending":
|
|
553
|
+
case "queued":
|
|
554
|
+
case "waiting":
|
|
555
|
+
case "requested":
|
|
556
|
+
case "running":
|
|
557
|
+
case "in_progress":
|
|
558
|
+
case "blocked":
|
|
559
|
+
return "pending";
|
|
560
|
+
default:
|
|
561
|
+
return "pending";
|
|
562
|
+
}
|
|
563
|
+
}
|
|
564
|
+
function toGiteaPullRequestCheck(status, actionRequiredRunIds) {
|
|
565
|
+
const rawStatus = status.status.toLowerCase();
|
|
566
|
+
const runId = getGiteaActionRunIdFromUrl(status.target_url);
|
|
567
|
+
if (runId !== null && actionRequiredRunIds.has(runId)) {
|
|
568
|
+
// The Actions run behind this shadow status is held awaiting approval; the
|
|
569
|
+
// raw shadow reads plain pending, so surface the gate as a neutral trait.
|
|
570
|
+
return {
|
|
571
|
+
name: status.context || `status-${status.id}`,
|
|
572
|
+
status: "pending",
|
|
573
|
+
traits: [CHECK_TRAIT_ACTION_REQUIRED],
|
|
574
|
+
url: status.target_url ?? null,
|
|
575
|
+
checkRunId: status.id,
|
|
576
|
+
};
|
|
577
|
+
}
|
|
578
|
+
return {
|
|
579
|
+
name: status.context || `status-${status.id}`,
|
|
580
|
+
status: mapGiteaCommitState(rawStatus),
|
|
581
|
+
...(rawStatus === "warning" ? { traits: [CHECK_TRAIT_WARNING] } : {}),
|
|
582
|
+
url: status.target_url ?? null,
|
|
583
|
+
checkRunId: status.id,
|
|
584
|
+
};
|
|
585
|
+
}
|
|
586
|
+
/**
|
|
587
|
+
* A Gitea Actions run is awaiting approval when it explicitly reports
|
|
588
|
+
* need_approval (self-hosted instances that expose it) OR when it is held in a
|
|
589
|
+
* non-terminal `waiting`/`blocked` state for a cross-repo fork PR. gitea.com
|
|
590
|
+
* does not set need_approval and represents the approval gate as a `waiting`
|
|
591
|
+
* run with no tasks, so the cross-repo signal is what disambiguates an approval
|
|
592
|
+
* hold from a run merely queued for a runner.
|
|
593
|
+
*/
|
|
594
|
+
function isGiteaRunAwaitingApproval(run) {
|
|
595
|
+
if (run.need_approval)
|
|
596
|
+
return true;
|
|
597
|
+
const status = (run.status ?? "").toLowerCase();
|
|
598
|
+
if (status !== "waiting" && status !== "blocked")
|
|
599
|
+
return false;
|
|
600
|
+
const pr = run.pull_requests?.[0];
|
|
601
|
+
const headRepoId = pr?.head?.repo?.id;
|
|
602
|
+
const baseRepoId = pr?.base?.repo?.id;
|
|
603
|
+
return headRepoId !== undefined && baseRepoId !== undefined && headRepoId !== baseRepoId;
|
|
604
|
+
}
|
|
605
|
+
function deriveGiteaActionRequiredRunIds(runs, sha) {
|
|
606
|
+
const runIds = new Set();
|
|
607
|
+
for (const raw of runs) {
|
|
608
|
+
const parsed = GiteaActionRunMetadataSchema.safeParse(raw);
|
|
609
|
+
if (!parsed.success)
|
|
610
|
+
continue;
|
|
611
|
+
const run = parsed.data;
|
|
612
|
+
if (run.id === undefined)
|
|
613
|
+
continue;
|
|
614
|
+
if ((run.head_sha ?? run.commit_sha) !== sha)
|
|
615
|
+
continue;
|
|
616
|
+
if (isGiteaRunAwaitingApproval(run))
|
|
617
|
+
runIds.add(run.id);
|
|
618
|
+
}
|
|
619
|
+
return runIds;
|
|
620
|
+
}
|
|
621
|
+
function getGiteaActionTaskName(task) {
|
|
622
|
+
return task.name || task.display_title || task.workflow_id || `actions-${task.id}`;
|
|
623
|
+
}
|
|
624
|
+
function toGiteaActionTaskCheck(task) {
|
|
625
|
+
const rawStatus = task.status.toLowerCase();
|
|
626
|
+
return {
|
|
627
|
+
name: getGiteaActionTaskName(task),
|
|
628
|
+
status: mapGiteaActionTaskStatus(rawStatus),
|
|
629
|
+
...(rawStatus === "blocked" && task.need_approval
|
|
630
|
+
? { traits: [CHECK_TRAIT_ACTION_REQUIRED] }
|
|
631
|
+
: {}),
|
|
632
|
+
url: task.url ?? null,
|
|
633
|
+
workflowRunId: task.id,
|
|
634
|
+
};
|
|
635
|
+
}
|
|
636
|
+
function getGiteaActionWorkflowIdentity(task) {
|
|
637
|
+
if (task.workflow_id) {
|
|
638
|
+
return `workflow\u0000${task.workflow_id}`;
|
|
639
|
+
}
|
|
640
|
+
// Instances that omit workflow_id (older Gitea/Forgejo payloads) still need
|
|
641
|
+
// reruns of the same job collapsed to the latest execution, so fall back to
|
|
642
|
+
// the job name before treating the task as its own group.
|
|
643
|
+
const name = task.name || task.display_title;
|
|
644
|
+
if (name) {
|
|
645
|
+
return `name\u0000${name}`;
|
|
646
|
+
}
|
|
647
|
+
return `task\u0000${getGiteaActionExecutionIdentity(task)}`;
|
|
648
|
+
}
|
|
649
|
+
function getGiteaActionExecutionIdentity(task) {
|
|
650
|
+
if (task.run_number !== undefined)
|
|
651
|
+
return `run-number\u0000${task.run_number}`;
|
|
652
|
+
const runId = getGiteaActionRunIdFromUrl(task.url);
|
|
653
|
+
if (runId !== null)
|
|
654
|
+
return `run-id\u0000${runId}`;
|
|
655
|
+
if (task.url)
|
|
656
|
+
return `url\u0000${task.url}`;
|
|
657
|
+
return `task\u0000${task.id}`;
|
|
658
|
+
}
|
|
659
|
+
function parseGiteaActionTaskTime(task) {
|
|
660
|
+
const timestamp = task.created_at ?? task.run_started_at ?? null;
|
|
661
|
+
if (!timestamp) {
|
|
662
|
+
return 0;
|
|
663
|
+
}
|
|
664
|
+
const time = Date.parse(timestamp);
|
|
665
|
+
return Number.isNaN(time) ? 0 : time;
|
|
666
|
+
}
|
|
667
|
+
function compareGiteaActionTaskRecency(left, right) {
|
|
668
|
+
const leftRunNumber = left.run_number ?? 0;
|
|
669
|
+
const rightRunNumber = right.run_number ?? 0;
|
|
670
|
+
if (leftRunNumber !== rightRunNumber) {
|
|
671
|
+
return leftRunNumber - rightRunNumber;
|
|
672
|
+
}
|
|
673
|
+
const leftTime = parseGiteaActionTaskTime(left);
|
|
674
|
+
const rightTime = parseGiteaActionTaskTime(right);
|
|
675
|
+
if (leftTime !== rightTime) {
|
|
676
|
+
return leftTime - rightTime;
|
|
677
|
+
}
|
|
678
|
+
return left.id - right.id;
|
|
679
|
+
}
|
|
680
|
+
function parseGiteaActionTasks(rawTasks) {
|
|
681
|
+
const tasks = [];
|
|
682
|
+
for (const raw of rawTasks) {
|
|
683
|
+
const parsed = GiteaActionTaskSchema.safeParse(raw);
|
|
684
|
+
if (parsed.success) {
|
|
685
|
+
tasks.push(parsed.data);
|
|
686
|
+
}
|
|
687
|
+
}
|
|
688
|
+
return tasks;
|
|
689
|
+
}
|
|
690
|
+
function latestGiteaActionTasksByWorkflow(tasks) {
|
|
691
|
+
const latestExecutions = new Map();
|
|
692
|
+
for (const task of tasks) {
|
|
693
|
+
const identity = getGiteaActionWorkflowIdentity(task);
|
|
694
|
+
const current = latestExecutions.get(identity);
|
|
695
|
+
if (!current || compareGiteaActionTaskRecency(current, task) < 0) {
|
|
696
|
+
latestExecutions.set(identity, task);
|
|
697
|
+
}
|
|
698
|
+
}
|
|
699
|
+
return tasks.filter((task) => {
|
|
700
|
+
const latest = latestExecutions.get(getGiteaActionWorkflowIdentity(task));
|
|
701
|
+
return (latest !== undefined &&
|
|
702
|
+
getGiteaActionExecutionIdentity(task) === getGiteaActionExecutionIdentity(latest));
|
|
703
|
+
});
|
|
704
|
+
}
|
|
705
|
+
function getUrlOrigin(value) {
|
|
706
|
+
if (!value)
|
|
707
|
+
return null;
|
|
708
|
+
try {
|
|
709
|
+
return new URL(value).origin;
|
|
710
|
+
}
|
|
711
|
+
catch {
|
|
712
|
+
return null;
|
|
713
|
+
}
|
|
714
|
+
}
|
|
715
|
+
const GITEA_RELATIVE_URL_ORIGIN = "https://gitea.invalid";
|
|
716
|
+
function getGiteaActionRunIdFromUrl(value) {
|
|
717
|
+
if (!value)
|
|
718
|
+
return null;
|
|
719
|
+
try {
|
|
720
|
+
const url = new URL(value, GITEA_RELATIVE_URL_ORIGIN);
|
|
721
|
+
const match = url.pathname.match(/\/actions\/runs\/(\d+)(?:\/jobs\/\d+)?\/?$/);
|
|
722
|
+
return match?.[1] ? Number.parseInt(match[1], 10) : null;
|
|
723
|
+
}
|
|
724
|
+
catch {
|
|
725
|
+
return null;
|
|
726
|
+
}
|
|
727
|
+
}
|
|
728
|
+
function isNativeActionJobUrl(targetUrl, nativeOrigins, nativeRunIds) {
|
|
729
|
+
if (!targetUrl)
|
|
730
|
+
return false;
|
|
731
|
+
try {
|
|
732
|
+
const url = new URL(targetUrl, GITEA_RELATIVE_URL_ORIGIN);
|
|
733
|
+
if (!/\/actions\/runs\/\d+\/jobs\/\d+\/?$/.test(url.pathname))
|
|
734
|
+
return false;
|
|
735
|
+
if (url.origin !== GITEA_RELATIVE_URL_ORIGIN && !nativeOrigins.has(url.origin))
|
|
736
|
+
return false;
|
|
737
|
+
const runId = getGiteaActionRunIdFromUrl(targetUrl);
|
|
738
|
+
return runId !== null && nativeRunIds.has(runId);
|
|
739
|
+
}
|
|
740
|
+
catch {
|
|
741
|
+
return false;
|
|
742
|
+
}
|
|
743
|
+
}
|
|
744
|
+
// A "shadow" is the commit status Gitea synthesizes to mirror one of its own
|
|
745
|
+
// Actions jobs; keeping both would double-report every job. Detection is purely
|
|
746
|
+
// structural: Gitea always creates these statuses with a target_url of the form
|
|
747
|
+
// "<run link>/jobs/<job id>" (services/actions/commit_status.go upstream), so a
|
|
748
|
+
// status is a shadow exactly when its URL points at a job of a run we actually
|
|
749
|
+
// fetched from the Actions API. Anything else - external CI, URL-less statuses,
|
|
750
|
+
// contexts that merely look like "<workflow> / <job> (<event>)" - is kept.
|
|
751
|
+
function isGiteaActionShadowStatus(status, nativeOrigins, nativeRunIds) {
|
|
752
|
+
return isNativeActionJobUrl(status.target_url, nativeOrigins, nativeRunIds);
|
|
753
|
+
}
|
|
754
|
+
function combineGiteaChecks(commitStatuses, actionTasks, actionRequiredRunIds = new Set()) {
|
|
755
|
+
const nativeOrigins = new Set(actionTasks
|
|
756
|
+
.map((task) => getUrlOrigin(task.url))
|
|
757
|
+
.filter((origin) => !!origin));
|
|
758
|
+
// Shadow target_urls and task urls both embed run.ID (run.Link() upstream);
|
|
759
|
+
// run_number is the unrelated per-repo run.Index, so only URL-derived ids can
|
|
760
|
+
// match here.
|
|
761
|
+
const nativeRunIds = new Set(actionTasks
|
|
762
|
+
.map((task) => getGiteaActionRunIdFromUrl(task.url))
|
|
763
|
+
.filter((runId) => runId !== null));
|
|
764
|
+
const checks = commitStatuses
|
|
765
|
+
.filter((status) => !isGiteaActionShadowStatus(status, nativeOrigins, nativeRunIds))
|
|
766
|
+
.map((status) => toGiteaPullRequestCheck(status, actionRequiredRunIds));
|
|
767
|
+
const seenTaskIds = new Set();
|
|
768
|
+
for (const task of actionTasks) {
|
|
769
|
+
if (seenTaskIds.has(task.id))
|
|
770
|
+
continue;
|
|
771
|
+
checks.push(toGiteaActionTaskCheck(task));
|
|
772
|
+
seenTaskIds.add(task.id);
|
|
773
|
+
}
|
|
774
|
+
return checks;
|
|
775
|
+
}
|
|
776
|
+
function applyGiteaChecks(status, combined, actionTasks, actionRequiredRunIds = new Set()) {
|
|
777
|
+
const checks = combineGiteaChecks(combined.statuses, actionTasks, actionRequiredRunIds);
|
|
778
|
+
if (checks.length === 0) {
|
|
779
|
+
return status;
|
|
780
|
+
}
|
|
781
|
+
// Aggregate over the union of commit statuses AND Actions runs. Gitea's
|
|
782
|
+
// combined.state summarizes commit statuses only, so trusting it would let a
|
|
783
|
+
// failing/pending Actions run be reported as success. computeChecksStatus
|
|
784
|
+
// applies failure > pending > success precedence across every check.
|
|
785
|
+
return {
|
|
786
|
+
...status,
|
|
787
|
+
checks,
|
|
788
|
+
checksStatus: computeChecksStatus(checks),
|
|
789
|
+
};
|
|
790
|
+
}
|
|
791
|
+
/** Parse owner/name from a Gitea PR/issue URL (`https://host/owner/repo/pulls/N`). */
|
|
792
|
+
function parseGiteaRepoFromUrl(url) {
|
|
793
|
+
try {
|
|
794
|
+
const segments = new URL(url).pathname.split("/").filter((segment) => segment.length > 0);
|
|
795
|
+
if (segments.length >= 2) {
|
|
796
|
+
return { owner: segments[0], name: segments[1] };
|
|
797
|
+
}
|
|
798
|
+
}
|
|
799
|
+
catch {
|
|
800
|
+
// fall through
|
|
801
|
+
}
|
|
802
|
+
return {};
|
|
803
|
+
}
|
|
804
|
+
function currentPullRequestApiToListItem(item) {
|
|
805
|
+
const headOwner = item.head.repo?.owner?.login;
|
|
806
|
+
const baseOwner = item.base.repo?.owner?.login;
|
|
807
|
+
const head = headOwner && headOwner !== baseOwner ? `${headOwner}:${item.head.ref}` : item.head.ref;
|
|
808
|
+
return {
|
|
809
|
+
index: String(item.number),
|
|
810
|
+
state: item.merged ? "merged" : item.state,
|
|
811
|
+
url: item.html_url,
|
|
812
|
+
title: item.title,
|
|
813
|
+
body: item.body ?? "",
|
|
814
|
+
...(item.mergeable != null ? { mergeable: String(item.mergeable) } : {}),
|
|
815
|
+
base: item.base.ref,
|
|
816
|
+
head,
|
|
817
|
+
updated: item.updated_at,
|
|
818
|
+
labels: item.labels.map((label) => label.name).join(","),
|
|
819
|
+
};
|
|
820
|
+
}
|
|
821
|
+
function toPullRequestSummary(item) {
|
|
822
|
+
const { owner, name } = parseGiteaRepoFromUrl(item.url);
|
|
823
|
+
return {
|
|
824
|
+
number: parseGiteaInt(item.index) ?? 0,
|
|
825
|
+
title: item.title,
|
|
826
|
+
url: item.url,
|
|
827
|
+
state: mapGiteaState(item.state),
|
|
828
|
+
body: item.body || null,
|
|
829
|
+
...(owner && name ? { projectPath: `${owner}/${name}` } : {}),
|
|
830
|
+
baseRefName: item.base ?? "",
|
|
831
|
+
headRefName: stripHeadOwner(item.head),
|
|
832
|
+
labels: splitGiteaLabels(item.labels),
|
|
833
|
+
updatedAt: item.updated ?? "",
|
|
834
|
+
};
|
|
835
|
+
}
|
|
836
|
+
function viewToPullRequestSummary(view) {
|
|
837
|
+
const { owner, name } = parseGiteaRepoFromUrl(view.url);
|
|
838
|
+
return {
|
|
839
|
+
number: view.index,
|
|
840
|
+
title: view.title,
|
|
841
|
+
url: view.url,
|
|
842
|
+
state: view.hasMerged ? "merged" : mapGiteaState(view.state),
|
|
843
|
+
body: view.body || null,
|
|
844
|
+
...(owner && name ? { projectPath: `${owner}/${name}` } : {}),
|
|
845
|
+
baseRefName: view.base ?? "",
|
|
846
|
+
headRefName: stripHeadOwner(view.head),
|
|
847
|
+
labels: (view.labels ?? []).map((label) => (typeof label === "string" ? label : label.name)),
|
|
848
|
+
updatedAt: view.updated ?? "",
|
|
849
|
+
};
|
|
850
|
+
}
|
|
851
|
+
function toIssueSummary(item) {
|
|
852
|
+
const { owner, name } = parseGiteaRepoFromUrl(item.url);
|
|
853
|
+
return {
|
|
854
|
+
number: parseGiteaInt(item.index) ?? 0,
|
|
855
|
+
title: item.title,
|
|
856
|
+
url: item.url,
|
|
857
|
+
state: mapGiteaState(item.state),
|
|
858
|
+
body: item.body || null,
|
|
859
|
+
...(owner && name ? { projectPath: `${owner}/${name}` } : {}),
|
|
860
|
+
labels: splitGiteaLabels(item.labels),
|
|
861
|
+
updatedAt: item.updated ?? "",
|
|
862
|
+
};
|
|
863
|
+
}
|
|
864
|
+
function toGiteaStatusFacts(item) {
|
|
865
|
+
return {
|
|
866
|
+
mergeable: parseGiteaBool(item.mergeable),
|
|
867
|
+
hasMerged: mapGiteaState(item.state) === "merged",
|
|
868
|
+
ciStatus: item.ci && item.ci.length > 0 ? item.ci : null,
|
|
869
|
+
};
|
|
870
|
+
}
|
|
871
|
+
function toCurrentPullRequestStatus(item) {
|
|
872
|
+
const { owner, name } = parseGiteaRepoFromUrl(item.url);
|
|
873
|
+
const state = mapGiteaState(item.state);
|
|
874
|
+
return {
|
|
875
|
+
number: parseGiteaInt(item.index) ?? undefined,
|
|
876
|
+
...(owner ? { repoOwner: owner } : {}),
|
|
877
|
+
...(name ? { repoName: name } : {}),
|
|
878
|
+
...(owner && name ? { projectPath: `${owner}/${name}` } : {}),
|
|
879
|
+
url: item.url,
|
|
880
|
+
title: item.title,
|
|
881
|
+
state,
|
|
882
|
+
baseRefName: item.base ?? "",
|
|
883
|
+
headRefName: stripHeadOwner(item.head),
|
|
884
|
+
isMerged: state === "merged",
|
|
885
|
+
mergeable: mapGiteaMergeable(item),
|
|
886
|
+
checks: [],
|
|
887
|
+
checksStatus: mapGiteaCiStatus(item.ci),
|
|
888
|
+
reviewDecision: null,
|
|
889
|
+
// The whole Gitea family (gitea, forgejo, codeberg) tags its facts with the
|
|
890
|
+
// family id "gitea" — they share one facts shape and one guard. This is the
|
|
891
|
+
// facts-family tag, distinct from the workspace's brand-specific forge id.
|
|
892
|
+
forgeSpecific: { forge: "gitea", ...toGiteaStatusFacts(item) },
|
|
893
|
+
};
|
|
894
|
+
}
|
|
895
|
+
/**
|
|
896
|
+
* Server-side guard for a Gitea direct merge, mirroring the gh/glab adapters:
|
|
897
|
+
* refuse the merge unless Gitea reports the PR as mergeable. The resolved status
|
|
898
|
+
* can go stale between the client check and execution, and the RPC can be called
|
|
899
|
+
* directly, so the guard lives here rather than only in the UI policy.
|
|
900
|
+
*/
|
|
901
|
+
function assertGiteaDirectMergeReady(input) {
|
|
902
|
+
const facts = input.status?.forgeSpecific;
|
|
903
|
+
if (!isGiteaStatusFacts(facts)) {
|
|
904
|
+
throw new Error("Gitea merge facts are unavailable for this pull request");
|
|
905
|
+
}
|
|
906
|
+
if (facts.hasMerged) {
|
|
907
|
+
throw new Error("This pull request is already merged");
|
|
908
|
+
}
|
|
909
|
+
if (!facts.mergeable) {
|
|
910
|
+
throw new Error("Gitea does not report this pull request as ready for direct merge");
|
|
911
|
+
}
|
|
912
|
+
}
|
|
913
|
+
function isAuthFailureText(text) {
|
|
914
|
+
return /\b(401|unauthorized|not logged in|authentication failed|no token|invalid token|no logins?)\b/i.test(text);
|
|
915
|
+
}
|
|
916
|
+
function classifyGiteaTimelineErrorKind(stderr) {
|
|
917
|
+
const normalized = stderr.toLowerCase();
|
|
918
|
+
if (normalized.includes("404") || normalized.includes("not found")) {
|
|
919
|
+
return "not_found";
|
|
920
|
+
}
|
|
921
|
+
if (normalized.includes("403") || normalized.includes("forbidden") || isAuthFailureText(stderr)) {
|
|
922
|
+
return "forbidden";
|
|
923
|
+
}
|
|
924
|
+
return "unknown";
|
|
925
|
+
}
|
|
926
|
+
/**
|
|
927
|
+
* Re-throw only tea auth / CLI-missing failures, letting every other error be
|
|
928
|
+
* swallowed by a best-effort caller. Background status polling wraps its checks
|
|
929
|
+
* load in its own catch, so this stays invisible there; on the explicit,
|
|
930
|
+
* user-triggered check-details path it lets an expired token surface the real
|
|
931
|
+
* remediation instead of a misleading "check not found".
|
|
932
|
+
*/
|
|
933
|
+
function rethrowTeaAuthFailure(error) {
|
|
934
|
+
if (error instanceof TeaAuthenticationError || error instanceof TeaCliMissingError) {
|
|
935
|
+
throw error;
|
|
936
|
+
}
|
|
937
|
+
}
|
|
938
|
+
function mapGiteaTimelineError(error) {
|
|
939
|
+
if (error instanceof TeaAuthenticationError || error instanceof TeaCliMissingError) {
|
|
940
|
+
return { kind: "forbidden", message: error.message };
|
|
941
|
+
}
|
|
942
|
+
if (error instanceof TeaCommandError) {
|
|
943
|
+
return {
|
|
944
|
+
kind: classifyGiteaTimelineErrorKind(error.stderr),
|
|
945
|
+
message: error.stderr || error.message,
|
|
946
|
+
};
|
|
947
|
+
}
|
|
948
|
+
return { kind: "unknown", message: error instanceof Error ? error.message : String(error) };
|
|
949
|
+
}
|
|
950
|
+
function extractPullRequestUrl(stdout) {
|
|
951
|
+
const match = stdout.match(/https?:\/\/\S+\/pulls\/\d+/);
|
|
952
|
+
return match ? match[0] : null;
|
|
953
|
+
}
|
|
954
|
+
function parseIndexFromUrl(url) {
|
|
955
|
+
const match = url.match(/\/pulls\/(\d+)/);
|
|
956
|
+
return match ? Number(match[1]) : null;
|
|
957
|
+
}
|
|
958
|
+
// Flags whose values carry user/generated content (a PR title or body may
|
|
959
|
+
// contain a secret). The value that follows any of these in argv is replaced
|
|
960
|
+
// before argv is embedded in a client-facing error.
|
|
961
|
+
const TEA_SENSITIVE_FLAGS = new Set(["--title", "--description", "--body"]);
|
|
962
|
+
const TEA_REDACTED_VALUE = "<redacted>";
|
|
963
|
+
/**
|
|
964
|
+
* Redact the values of sensitive flags in a tea argv so a command failure that
|
|
965
|
+
* surfaces to the remote/mobile client never echoes a PR title or body. The
|
|
966
|
+
* real argv still runs; only the copy stored on the error is scrubbed.
|
|
967
|
+
*/
|
|
968
|
+
function redactTeaArgs(args) {
|
|
969
|
+
return args.map((arg, index) => index > 0 && TEA_SENSITIVE_FLAGS.has(args[index - 1]) ? TEA_REDACTED_VALUE : arg);
|
|
970
|
+
}
|
|
971
|
+
/**
|
|
972
|
+
* Probe whether a host is a Gitea instance Paseo can talk to. tea has no
|
|
973
|
+
* per-repo auth check (it keeps per-instance logins), so a configured tea login
|
|
974
|
+
* for the host is the signal: it means tea both recognizes the host as Gitea and
|
|
975
|
+
* holds a usable token for it. Mirrors the role of `glab auth status` for GitLab.
|
|
976
|
+
*/
|
|
977
|
+
export async function probeGiteaHost(host) {
|
|
978
|
+
const teaPath = await findExecutable("tea");
|
|
979
|
+
if (!teaPath) {
|
|
980
|
+
return false;
|
|
981
|
+
}
|
|
982
|
+
try {
|
|
983
|
+
const { stdout } = await execCommand("tea", ["login", "list", "-o", "json"], {
|
|
984
|
+
envOverlay: TEA_ENV,
|
|
985
|
+
timeout: CLI_AUTH_PROBE_TIMEOUT_MS,
|
|
986
|
+
});
|
|
987
|
+
return hostHasLogin(stdout, host);
|
|
988
|
+
}
|
|
989
|
+
catch {
|
|
990
|
+
return false;
|
|
991
|
+
}
|
|
992
|
+
}
|
|
993
|
+
function findTeaLoginNameForHost(stdout, host) {
|
|
994
|
+
let data;
|
|
995
|
+
try {
|
|
996
|
+
data = JSON.parse(stdout);
|
|
997
|
+
}
|
|
998
|
+
catch {
|
|
999
|
+
return null;
|
|
1000
|
+
}
|
|
1001
|
+
const parsed = z.array(GiteaLoginSchema).safeParse(data);
|
|
1002
|
+
if (!parsed.success) {
|
|
1003
|
+
return null;
|
|
1004
|
+
}
|
|
1005
|
+
const target = host.toLowerCase();
|
|
1006
|
+
const match = parsed.data.find((login) => {
|
|
1007
|
+
const candidates = [login.ssh_host, login.name];
|
|
1008
|
+
if (login.url) {
|
|
1009
|
+
try {
|
|
1010
|
+
candidates.push(new URL(login.url).hostname);
|
|
1011
|
+
}
|
|
1012
|
+
catch {
|
|
1013
|
+
// ignore malformed login url
|
|
1014
|
+
}
|
|
1015
|
+
}
|
|
1016
|
+
return candidates.some((candidate) => candidate?.toLowerCase() === target);
|
|
1017
|
+
});
|
|
1018
|
+
return match?.name ?? null;
|
|
1019
|
+
}
|
|
1020
|
+
function hostHasLogin(stdout, host) {
|
|
1021
|
+
return findTeaLoginNameForHost(stdout, host) !== null;
|
|
1022
|
+
}
|
|
1023
|
+
/**
|
|
1024
|
+
* The Forgejo REST namespace exists only on Forgejo; Gitea's router returns 404
|
|
1025
|
+
* for it. We check it only through authenticated tea so the resolver never makes
|
|
1026
|
+
* anonymous HTTP requests to a remote-derived host.
|
|
1027
|
+
*/
|
|
1028
|
+
const FORGEJO_VERSION_PATH = "/api/forgejo/v1/version";
|
|
1029
|
+
const GITEA_SOFTWARE_PROBE_TIMEOUT_MS = 5000;
|
|
1030
|
+
async function defaultRunTea(args) {
|
|
1031
|
+
const { stdout, stderr } = await execCommand("tea", args, {
|
|
1032
|
+
envOverlay: TEA_ENV,
|
|
1033
|
+
timeout: GITEA_SOFTWARE_PROBE_TIMEOUT_MS,
|
|
1034
|
+
});
|
|
1035
|
+
return { stdout, stderr };
|
|
1036
|
+
}
|
|
1037
|
+
const HTTP_STATUS_LINE = /^HTTP\/\d(?:\.\d)?\s+(\d{3})/m;
|
|
1038
|
+
function parseHttpStatus(headerDump) {
|
|
1039
|
+
const match = headerDump.match(HTTP_STATUS_LINE);
|
|
1040
|
+
return match ? Number(match[1]) : null;
|
|
1041
|
+
}
|
|
1042
|
+
/**
|
|
1043
|
+
* Probe the Forgejo namespace through an authenticated `tea` request. `tea api`
|
|
1044
|
+
* exits 0 regardless of HTTP status, so the verdict is read from the status line
|
|
1045
|
+
* `tea api -i` emits. Different tea builds print that line on stdout or stderr,
|
|
1046
|
+
* so both streams are parsed. When `-i` is unsupported no status line appears
|
|
1047
|
+
* (or the call errors) and the probe is inconclusive (null), leaving the Gitea
|
|
1048
|
+
* default in place — the branch is always non-fatal.
|
|
1049
|
+
*
|
|
1050
|
+
* Not verified against a live self-hosted Forgejo instance; QA follow-up.
|
|
1051
|
+
*/
|
|
1052
|
+
async function probeForgejoNamespaceByTea(host, runTea) {
|
|
1053
|
+
let loginName;
|
|
1054
|
+
try {
|
|
1055
|
+
const { stdout } = await runTea(["login", "list", "-o", "json"]);
|
|
1056
|
+
loginName = findTeaLoginNameForHost(stdout, host);
|
|
1057
|
+
}
|
|
1058
|
+
catch {
|
|
1059
|
+
return null;
|
|
1060
|
+
}
|
|
1061
|
+
if (!loginName) {
|
|
1062
|
+
return null;
|
|
1063
|
+
}
|
|
1064
|
+
try {
|
|
1065
|
+
const { stdout, stderr } = await runTea([
|
|
1066
|
+
"api",
|
|
1067
|
+
"--login",
|
|
1068
|
+
loginName,
|
|
1069
|
+
"-i",
|
|
1070
|
+
FORGEJO_VERSION_PATH,
|
|
1071
|
+
]);
|
|
1072
|
+
const status = parseHttpStatus(stderr) ?? parseHttpStatus(stdout);
|
|
1073
|
+
if (status === 404) {
|
|
1074
|
+
return false;
|
|
1075
|
+
}
|
|
1076
|
+
if (status !== null && status >= 200 && status < 300) {
|
|
1077
|
+
return true;
|
|
1078
|
+
}
|
|
1079
|
+
return null;
|
|
1080
|
+
}
|
|
1081
|
+
catch {
|
|
1082
|
+
return null;
|
|
1083
|
+
}
|
|
1084
|
+
}
|
|
1085
|
+
/**
|
|
1086
|
+
* Decide whether a Gitea-family host runs Forgejo or Gitea through authenticated
|
|
1087
|
+
* tea only. Inconclusive detection keeps the historical Gitea default.
|
|
1088
|
+
*/
|
|
1089
|
+
export async function detectGiteaFamilySoftware(host, options = {}) {
|
|
1090
|
+
const runTea = options.runTea ?? defaultRunTea;
|
|
1091
|
+
const viaTea = await probeForgejoNamespaceByTea(host, runTea);
|
|
1092
|
+
if (viaTea !== null) {
|
|
1093
|
+
return viaTea ? "forgejo" : "gitea";
|
|
1094
|
+
}
|
|
1095
|
+
return "gitea";
|
|
1096
|
+
}
|
|
1097
|
+
const inFlightFamilyProbes = new Map();
|
|
1098
|
+
/**
|
|
1099
|
+
* Resolve which Gitea-family forge id a host maps to for the open registry:
|
|
1100
|
+
* null when there is no usable `tea` login (Paseo cannot operate the host),
|
|
1101
|
+
* otherwise the detected software. Concurrent calls for the same host — the
|
|
1102
|
+
* gitea and forgejo registrations probing in parallel — share one probe so
|
|
1103
|
+
* detection runs once.
|
|
1104
|
+
*/
|
|
1105
|
+
export function resolveGiteaFamilyForge(host) {
|
|
1106
|
+
const existing = inFlightFamilyProbes.get(host);
|
|
1107
|
+
if (existing) {
|
|
1108
|
+
return existing;
|
|
1109
|
+
}
|
|
1110
|
+
const pending = (async () => {
|
|
1111
|
+
if (!(await probeGiteaHost(host))) {
|
|
1112
|
+
return null;
|
|
1113
|
+
}
|
|
1114
|
+
return detectGiteaFamilySoftware(host);
|
|
1115
|
+
})().finally(() => {
|
|
1116
|
+
inFlightFamilyProbes.delete(host);
|
|
1117
|
+
});
|
|
1118
|
+
inFlightFamilyProbes.set(host, pending);
|
|
1119
|
+
return pending;
|
|
1120
|
+
}
|
|
1121
|
+
function isTeaSearchAuthFailure(reason) {
|
|
1122
|
+
return reason instanceof TeaCliMissingError || reason instanceof TeaAuthenticationError;
|
|
1123
|
+
}
|
|
1124
|
+
function getTeaUnavailableSearchAuthState(results) {
|
|
1125
|
+
if (results.length === 0 ||
|
|
1126
|
+
!results.every((result) => result.status === "rejected" && isTeaSearchAuthFailure(result.reason))) {
|
|
1127
|
+
return null;
|
|
1128
|
+
}
|
|
1129
|
+
return results.some((result) => result.status === "rejected" && result.reason instanceof TeaCliMissingError)
|
|
1130
|
+
? "cli_missing"
|
|
1131
|
+
: "unauthenticated";
|
|
1132
|
+
}
|
|
1133
|
+
function throwFirstNonTeaAuthSearchRejection(results) {
|
|
1134
|
+
const failed = results.find((result) => result.status === "rejected" && !isTeaSearchAuthFailure(result.reason));
|
|
1135
|
+
if (failed) {
|
|
1136
|
+
throw failed.reason;
|
|
1137
|
+
}
|
|
1138
|
+
}
|
|
1139
|
+
export function createGiteaService(options = {}) {
|
|
1140
|
+
const runner = options.runner ?? runTeaCommand;
|
|
1141
|
+
const resolveTea = createCachedCliPathResolver(options.resolveTeaPath ?? resolveTeaPath);
|
|
1142
|
+
const resolveRemoteUrl = options.resolveRemoteUrl ?? defaultResolveRemoteUrl;
|
|
1143
|
+
const resolveCurrentBranch = options.resolveCurrentBranch ?? defaultResolveCurrentBranch;
|
|
1144
|
+
const now = options.now ?? Date.now;
|
|
1145
|
+
const currentPrHeadShaCache = new Map();
|
|
1146
|
+
async function run(args, runOptions) {
|
|
1147
|
+
const teaPath = await resolveTea();
|
|
1148
|
+
if (!teaPath) {
|
|
1149
|
+
throw new TeaCliMissingError();
|
|
1150
|
+
}
|
|
1151
|
+
try {
|
|
1152
|
+
const result = await runner(args, runOptions);
|
|
1153
|
+
return result.stdout.trim();
|
|
1154
|
+
}
|
|
1155
|
+
catch (error) {
|
|
1156
|
+
throw teaCliRunner.normalizeError(error, { args: redactTeaArgs(args), cwd: runOptions.cwd });
|
|
1157
|
+
}
|
|
1158
|
+
}
|
|
1159
|
+
function runJsonParse(args, runOptions, stdout, schema) {
|
|
1160
|
+
return parseCliJsonOutput({
|
|
1161
|
+
commandName: "tea",
|
|
1162
|
+
args,
|
|
1163
|
+
cwd: runOptions.cwd,
|
|
1164
|
+
stdout,
|
|
1165
|
+
schema,
|
|
1166
|
+
createCommandError: (params) => new TeaCommandError(params),
|
|
1167
|
+
});
|
|
1168
|
+
}
|
|
1169
|
+
async function runJsonArray(args, runOptions, itemSchema) {
|
|
1170
|
+
const stdout = await run(args, runOptions);
|
|
1171
|
+
if (!stdout) {
|
|
1172
|
+
return [];
|
|
1173
|
+
}
|
|
1174
|
+
return runJsonParse(args, runOptions, stdout, z.array(itemSchema));
|
|
1175
|
+
}
|
|
1176
|
+
async function runJson(args, runOptions, schema) {
|
|
1177
|
+
const stdout = await run(args, runOptions);
|
|
1178
|
+
return runJsonParse(args, runOptions, stdout, schema);
|
|
1179
|
+
}
|
|
1180
|
+
async function resolveForkCheckoutFacts(cwd, summary) {
|
|
1181
|
+
const sameRepo = {
|
|
1182
|
+
isCrossRepository: false,
|
|
1183
|
+
headOwnerLogin: null,
|
|
1184
|
+
headRepositorySshUrl: null,
|
|
1185
|
+
headRepositoryUrl: null,
|
|
1186
|
+
};
|
|
1187
|
+
const { owner, name } = parseGiteaRepoFromUrl(summary.url);
|
|
1188
|
+
if (!owner || !name) {
|
|
1189
|
+
return sameRepo;
|
|
1190
|
+
}
|
|
1191
|
+
const pr = await runJson([
|
|
1192
|
+
"api",
|
|
1193
|
+
`repos/${encodeURIComponent(owner)}/${encodeURIComponent(name)}/pulls/${summary.number}`,
|
|
1194
|
+
], { cwd }, GiteaPullRequestApiSchema);
|
|
1195
|
+
const headRepo = pr.head?.repo ?? null;
|
|
1196
|
+
const baseRepo = pr.base?.repo ?? null;
|
|
1197
|
+
if (headRepo?.id == null || baseRepo?.id == null || headRepo.id === baseRepo.id) {
|
|
1198
|
+
return sameRepo;
|
|
1199
|
+
}
|
|
1200
|
+
return {
|
|
1201
|
+
isCrossRepository: true,
|
|
1202
|
+
headOwnerLogin: headRepo.owner?.login ?? null,
|
|
1203
|
+
headRepositorySshUrl: headRepo.ssh_url ?? null,
|
|
1204
|
+
headRepositoryUrl: headRepo.html_url ?? null,
|
|
1205
|
+
};
|
|
1206
|
+
}
|
|
1207
|
+
async function listPullRequestItems(input) {
|
|
1208
|
+
const args = ["pr", "list", "--fields", PR_LIST_FIELDS, "--state", input.state, "-o", "json"];
|
|
1209
|
+
if (typeof input.limit === "number") {
|
|
1210
|
+
args.push("--limit", String(input.limit));
|
|
1211
|
+
}
|
|
1212
|
+
if (typeof input.page === "number") {
|
|
1213
|
+
args.push("--page", String(input.page));
|
|
1214
|
+
}
|
|
1215
|
+
const items = await runJsonArray(args, { cwd: input.cwd }, GiteaPrListItemSchema);
|
|
1216
|
+
const query = input.query?.trim().toLowerCase();
|
|
1217
|
+
if (!query) {
|
|
1218
|
+
return items;
|
|
1219
|
+
}
|
|
1220
|
+
return items.filter((item) => item.title.toLowerCase().includes(query));
|
|
1221
|
+
}
|
|
1222
|
+
async function runIssueList(input) {
|
|
1223
|
+
const args = ["issue", "list", "--fields", ISSUE_LIST_FIELDS, "--state", "open", "-o", "json"];
|
|
1224
|
+
if (typeof input.limit === "number") {
|
|
1225
|
+
args.push("--limit", String(input.limit));
|
|
1226
|
+
}
|
|
1227
|
+
const items = await runJsonArray(args, { cwd: input.cwd }, GiteaIssueListItemSchema);
|
|
1228
|
+
const query = input.query?.trim().toLowerCase();
|
|
1229
|
+
const filtered = query
|
|
1230
|
+
? items.filter((item) => item.title.toLowerCase().includes(query))
|
|
1231
|
+
: items;
|
|
1232
|
+
return filtered.map(toIssueSummary);
|
|
1233
|
+
}
|
|
1234
|
+
async function listPullRequestReviewComments(input) {
|
|
1235
|
+
return listTimelineBucketPages(input, `pulls/${input.prNumber}/reviews/${input.reviewId}/comments`, GiteaReviewCommentSchema);
|
|
1236
|
+
}
|
|
1237
|
+
async function listTimelineBucketPages(input, suffix, itemSchema) {
|
|
1238
|
+
const items = [];
|
|
1239
|
+
for (let page = 1; page <= TIMELINE_MAX_PAGES_PER_BUCKET; page += 1) {
|
|
1240
|
+
const pageItems = await runJsonArray(["api", timelineApiPath(input, `${suffix}?${timelinePageQuery(page)}`)], { cwd: input.cwd }, itemSchema);
|
|
1241
|
+
items.push(...pageItems);
|
|
1242
|
+
if (pageItems.length < TIMELINE_PAGE_SIZE) {
|
|
1243
|
+
return { items, truncated: false };
|
|
1244
|
+
}
|
|
1245
|
+
}
|
|
1246
|
+
return { items, truncated: true };
|
|
1247
|
+
}
|
|
1248
|
+
async function loadCurrentPullRequestStatus(input) {
|
|
1249
|
+
const match = await findCurrentPullRequestForHeadRef(input);
|
|
1250
|
+
if (!match) {
|
|
1251
|
+
return null;
|
|
1252
|
+
}
|
|
1253
|
+
const status = toCurrentPullRequestStatus(match);
|
|
1254
|
+
return loadCurrentPullRequestChecks(input.cwd, match, status);
|
|
1255
|
+
}
|
|
1256
|
+
async function resolveCurrentRepoIdentity(cwd) {
|
|
1257
|
+
const remoteUrl = await resolveRemoteUrl(cwd);
|
|
1258
|
+
if (!remoteUrl) {
|
|
1259
|
+
return null;
|
|
1260
|
+
}
|
|
1261
|
+
const location = parseGitRemoteLocation(remoteUrl);
|
|
1262
|
+
if (!location) {
|
|
1263
|
+
return null;
|
|
1264
|
+
}
|
|
1265
|
+
const identity = parseGitHubRemoteIdentity(location.path);
|
|
1266
|
+
return identity ? { owner: identity.owner, name: identity.name } : null;
|
|
1267
|
+
}
|
|
1268
|
+
async function findCurrentPullRequestForHeadRef(input) {
|
|
1269
|
+
const repoIdentity = await resolveCurrentRepoIdentity(input.cwd);
|
|
1270
|
+
const expectedHeadOwner = repoIdentity?.owner ?? null;
|
|
1271
|
+
const openMatch = await findOpenPullRequestForHeadRef(input, expectedHeadOwner);
|
|
1272
|
+
if (openMatch) {
|
|
1273
|
+
return openMatch;
|
|
1274
|
+
}
|
|
1275
|
+
// tea discovers repository context from any configured git remote, while
|
|
1276
|
+
// the default remote resolver reads origin only. Preserve that broader
|
|
1277
|
+
// discovery for repositories whose primary remote has another name.
|
|
1278
|
+
const repoPath = repoIdentity
|
|
1279
|
+
? `repos/${encodeURIComponent(repoIdentity.owner)}/${encodeURIComponent(repoIdentity.name)}`
|
|
1280
|
+
: "repos/{owner}/{repo}";
|
|
1281
|
+
const recentItems = await runJsonArray([
|
|
1282
|
+
"api",
|
|
1283
|
+
`${repoPath}/pulls?state=all&sort=recentupdate&page=1&limit=${CURRENT_PR_LOOKUP_PAGE_SIZE}`,
|
|
1284
|
+
], { cwd: input.cwd }, GiteaCurrentPullRequestApiSchema);
|
|
1285
|
+
const candidates = recentItems.filter((item) => {
|
|
1286
|
+
if (matchesCurrentHeadRef(currentPullRequestApiToListItem(item), input.headRef, expectedHeadOwner)) {
|
|
1287
|
+
return true;
|
|
1288
|
+
}
|
|
1289
|
+
// A cross-fork PR carries the fork owner in its head, so the checkout-owner
|
|
1290
|
+
// gate excludes it even though the PR lives in this base repo. The head sha
|
|
1291
|
+
// is an unambiguous identity, so accept a match on it regardless of owner —
|
|
1292
|
+
// this mirrors the GitLab adapter, which resolves fork MRs without an
|
|
1293
|
+
// owner gate.
|
|
1294
|
+
return input.headSha !== undefined && item.head.sha === input.headSha;
|
|
1295
|
+
});
|
|
1296
|
+
const match = candidates.find((item) => mapGiteaState(item.state) === "open") ??
|
|
1297
|
+
candidates.find((item) => mapGiteaState(item.state) !== "open" &&
|
|
1298
|
+
input.headSha !== undefined &&
|
|
1299
|
+
item.head.sha === input.headSha) ??
|
|
1300
|
+
null;
|
|
1301
|
+
return match ? currentPullRequestApiToListItem(match) : null;
|
|
1302
|
+
}
|
|
1303
|
+
async function findOpenPullRequestForHeadRef(input, expectedHeadOwner) {
|
|
1304
|
+
for (let page = 1; page <= CURRENT_PR_OPEN_LOOKUP_MAX_PAGES; page += 1) {
|
|
1305
|
+
const items = await listPullRequestItems({
|
|
1306
|
+
cwd: input.cwd,
|
|
1307
|
+
state: "open",
|
|
1308
|
+
limit: CURRENT_PR_LOOKUP_PAGE_SIZE,
|
|
1309
|
+
page,
|
|
1310
|
+
});
|
|
1311
|
+
const match = items.find((item) => matchesCurrentHeadRef(item, input.headRef, expectedHeadOwner));
|
|
1312
|
+
if (match) {
|
|
1313
|
+
return match;
|
|
1314
|
+
}
|
|
1315
|
+
if (items.length < CURRENT_PR_LOOKUP_PAGE_SIZE) {
|
|
1316
|
+
return null;
|
|
1317
|
+
}
|
|
1318
|
+
}
|
|
1319
|
+
return null;
|
|
1320
|
+
}
|
|
1321
|
+
async function loadCurrentPullRequestChecks(cwd, item, status) {
|
|
1322
|
+
const number = parseGiteaInt(item.index);
|
|
1323
|
+
if (number === null || !status.repoOwner || !status.repoName) {
|
|
1324
|
+
return status;
|
|
1325
|
+
}
|
|
1326
|
+
try {
|
|
1327
|
+
const pr = await runJson(["pr", String(number), "-o", "json"], { cwd }, GiteaPullRequestViewSchema);
|
|
1328
|
+
if (!pr.headSha) {
|
|
1329
|
+
return status;
|
|
1330
|
+
}
|
|
1331
|
+
const checksInput = {
|
|
1332
|
+
cwd,
|
|
1333
|
+
repoOwner: status.repoOwner,
|
|
1334
|
+
repoName: status.repoName,
|
|
1335
|
+
sha: pr.headSha,
|
|
1336
|
+
};
|
|
1337
|
+
const [combined, actionTasks] = await Promise.all([
|
|
1338
|
+
loadCombinedCommitStatusBestEffort(checksInput),
|
|
1339
|
+
loadActionTasksBestEffort(checksInput),
|
|
1340
|
+
]);
|
|
1341
|
+
const actionRequiredRunIds = await loadActionRequiredRunIdsBestEffort(checksInput, combined, actionTasks);
|
|
1342
|
+
return applyGiteaChecks(status, combined, actionTasks, actionRequiredRunIds);
|
|
1343
|
+
}
|
|
1344
|
+
catch {
|
|
1345
|
+
return status;
|
|
1346
|
+
}
|
|
1347
|
+
}
|
|
1348
|
+
async function loadCombinedCommitStatusBestEffort(input) {
|
|
1349
|
+
try {
|
|
1350
|
+
return await loadCombinedCommitStatus(input);
|
|
1351
|
+
}
|
|
1352
|
+
catch (error) {
|
|
1353
|
+
rethrowTeaAuthFailure(error);
|
|
1354
|
+
return { state: "", statuses: [], total_count: 0 };
|
|
1355
|
+
}
|
|
1356
|
+
}
|
|
1357
|
+
async function loadCombinedCommitStatus(input) {
|
|
1358
|
+
const owner = encodeURIComponent(input.repoOwner);
|
|
1359
|
+
const repo = encodeURIComponent(input.repoName);
|
|
1360
|
+
const sha = encodeURIComponent(input.sha);
|
|
1361
|
+
return runJson(["api", `repos/${owner}/${repo}/commits/${sha}/status`], { cwd: input.cwd }, GiteaCombinedCommitStatusSchema);
|
|
1362
|
+
}
|
|
1363
|
+
// Only fetch runs when there is a pending Actions shadow status whose run has
|
|
1364
|
+
// no corresponding task: that is the approval-hold signature on gitea.com
|
|
1365
|
+
// (waiting run, no tasks, pending shadows). Skipping the fetch otherwise keeps
|
|
1366
|
+
// the common running/finished path at two requests.
|
|
1367
|
+
async function loadActionRequiredRunIdsBestEffort(input, combined, actionTasks) {
|
|
1368
|
+
const taskRunIds = new Set(actionTasks
|
|
1369
|
+
.map((task) => getGiteaActionRunIdFromUrl(task.url))
|
|
1370
|
+
.filter((runId) => runId !== null));
|
|
1371
|
+
const hasUncoveredPendingShadow = combined.statuses.some((status) => {
|
|
1372
|
+
const runId = getGiteaActionRunIdFromUrl(status.target_url);
|
|
1373
|
+
return (runId !== null &&
|
|
1374
|
+
!taskRunIds.has(runId) &&
|
|
1375
|
+
mapGiteaCommitState(status.status.toLowerCase()) === "pending");
|
|
1376
|
+
});
|
|
1377
|
+
if (!hasUncoveredPendingShadow)
|
|
1378
|
+
return new Set();
|
|
1379
|
+
try {
|
|
1380
|
+
const sha = encodeURIComponent(input.sha);
|
|
1381
|
+
const runs = await loadGiteaActionPages(input, "runs", `head_sha=${sha}`);
|
|
1382
|
+
return deriveGiteaActionRequiredRunIds(runs, input.sha);
|
|
1383
|
+
}
|
|
1384
|
+
catch (error) {
|
|
1385
|
+
rethrowTeaAuthFailure(error);
|
|
1386
|
+
return new Set();
|
|
1387
|
+
}
|
|
1388
|
+
}
|
|
1389
|
+
async function loadActionTasksBestEffort(input) {
|
|
1390
|
+
try {
|
|
1391
|
+
const tasks = await loadActionTasks(input);
|
|
1392
|
+
const matchingTasks = tasks.filter((task) => task.head_sha === input.sha);
|
|
1393
|
+
const latestTasks = latestGiteaActionTasksByWorkflow(matchingTasks);
|
|
1394
|
+
return await enrichActionTaskApprovalsBestEffort(input, latestTasks);
|
|
1395
|
+
}
|
|
1396
|
+
catch (error) {
|
|
1397
|
+
rethrowTeaAuthFailure(error);
|
|
1398
|
+
return [];
|
|
1399
|
+
}
|
|
1400
|
+
}
|
|
1401
|
+
async function enrichActionTaskApprovalsBestEffort(input, tasks) {
|
|
1402
|
+
if (!tasks.some((task) => task.status.toLowerCase() === "blocked"))
|
|
1403
|
+
return tasks;
|
|
1404
|
+
try {
|
|
1405
|
+
const sha = encodeURIComponent(input.sha);
|
|
1406
|
+
const approvalRunNumbers = new Set();
|
|
1407
|
+
const runs = await loadGiteaActionPages(input, "runs", `head_sha=${sha}`);
|
|
1408
|
+
for (const rawRun of runs) {
|
|
1409
|
+
const parsed = GiteaActionRunMetadataSchema.safeParse(rawRun);
|
|
1410
|
+
if (!parsed.success || !parsed.data.need_approval)
|
|
1411
|
+
continue;
|
|
1412
|
+
const metadata = parsed.data;
|
|
1413
|
+
const runSha = metadata.head_sha ?? metadata.commit_sha;
|
|
1414
|
+
const runNumber = metadata.run_number ?? metadata.index_in_repo;
|
|
1415
|
+
if (runSha === input.sha && runNumber !== undefined)
|
|
1416
|
+
approvalRunNumbers.add(runNumber);
|
|
1417
|
+
}
|
|
1418
|
+
return tasks.map((task) => task.status.toLowerCase() === "blocked" &&
|
|
1419
|
+
task.run_number !== undefined &&
|
|
1420
|
+
approvalRunNumbers.has(task.run_number)
|
|
1421
|
+
? { ...task, need_approval: true }
|
|
1422
|
+
: task);
|
|
1423
|
+
}
|
|
1424
|
+
catch (error) {
|
|
1425
|
+
rethrowTeaAuthFailure(error);
|
|
1426
|
+
return tasks;
|
|
1427
|
+
}
|
|
1428
|
+
}
|
|
1429
|
+
// The tasks endpoint pages at a small server default (10 on gitea.com) and a
|
|
1430
|
+
// self-hosted cap can sit below our requested 50; it also cannot filter by ref
|
|
1431
|
+
// or sha server-side. A short page therefore does NOT mean the last page —
|
|
1432
|
+
// conflating the two drops the current PR's run on a capped instance. Page on
|
|
1433
|
+
// until total_count is exhausted, a page comes back empty, or the bounded
|
|
1434
|
+
// max-pages cap is hit. SHA matches need not be contiguous across pages.
|
|
1435
|
+
async function loadGiteaActionPages(input, endpoint, query) {
|
|
1436
|
+
const owner = encodeURIComponent(input.repoOwner);
|
|
1437
|
+
const repo = encodeURIComponent(input.repoName);
|
|
1438
|
+
const items = [];
|
|
1439
|
+
let fetched = 0;
|
|
1440
|
+
for (let page = 1; page <= GITEA_ACTION_MAX_PAGES; page += 1) {
|
|
1441
|
+
const queryPrefix = query ? `${query}&` : "";
|
|
1442
|
+
const response = await runJson([
|
|
1443
|
+
"api",
|
|
1444
|
+
`repos/${owner}/${repo}/actions/${endpoint}?${queryPrefix}limit=${GITEA_ACTION_PAGE_LIMIT}&page=${page}`,
|
|
1445
|
+
], { cwd: input.cwd }, GiteaActionsListResponseSchema);
|
|
1446
|
+
if (response.workflow_runs.length === 0)
|
|
1447
|
+
break;
|
|
1448
|
+
fetched += response.workflow_runs.length;
|
|
1449
|
+
items.push(...response.workflow_runs);
|
|
1450
|
+
if (response.total_count !== undefined && fetched >= response.total_count)
|
|
1451
|
+
break;
|
|
1452
|
+
}
|
|
1453
|
+
return items;
|
|
1454
|
+
}
|
|
1455
|
+
async function loadActionTasks(input) {
|
|
1456
|
+
return parseGiteaActionTasks(await loadGiteaActionPages(input, "tasks"));
|
|
1457
|
+
}
|
|
1458
|
+
async function resolveCurrentPullRequestHeadSha(cwd) {
|
|
1459
|
+
const headRef = await resolveCurrentBranch(cwd);
|
|
1460
|
+
if (!headRef) {
|
|
1461
|
+
throw new Error("Gitea check details require a current branch");
|
|
1462
|
+
}
|
|
1463
|
+
const cacheKey = `${cwd}:branch:${headRef}`;
|
|
1464
|
+
const cached = currentPrHeadShaCache.get(cacheKey);
|
|
1465
|
+
const nowMs = now();
|
|
1466
|
+
if (cached && cached.expiresAt > nowMs) {
|
|
1467
|
+
return cached.sha;
|
|
1468
|
+
}
|
|
1469
|
+
const match = await findCurrentPullRequestForHeadRef({ cwd, headRef });
|
|
1470
|
+
const number = match ? parseGiteaInt(match.index) : null;
|
|
1471
|
+
if (!match || number === null) {
|
|
1472
|
+
throw new Error(`Gitea pull request for branch ${headRef} was not found`);
|
|
1473
|
+
}
|
|
1474
|
+
const pr = await runJson(["pr", String(number), "-o", "json"], { cwd }, GiteaPullRequestViewSchema);
|
|
1475
|
+
if (!pr.headSha) {
|
|
1476
|
+
throw new Error(`Gitea pull request #${number} did not include a head SHA`);
|
|
1477
|
+
}
|
|
1478
|
+
currentPrHeadShaCache.set(cacheKey, {
|
|
1479
|
+
sha: pr.headSha,
|
|
1480
|
+
expiresAt: nowMs + CURRENT_PR_HEAD_SHA_CACHE_TTL_MS,
|
|
1481
|
+
});
|
|
1482
|
+
return pr.headSha;
|
|
1483
|
+
}
|
|
1484
|
+
// Resolve the head SHA of a specific PR by its number. The current branch's
|
|
1485
|
+
// head can move (a push right after a run was listed), so a user-triggered
|
|
1486
|
+
// check-details request for a known PR must resolve against that PR's head,
|
|
1487
|
+
// not the branch's, or the requested run no longer maps to the SHA.
|
|
1488
|
+
async function resolvePullRequestHeadShaByNumber(cwd, number) {
|
|
1489
|
+
const cacheKey = `${cwd}:pr:${number}`;
|
|
1490
|
+
const cached = currentPrHeadShaCache.get(cacheKey);
|
|
1491
|
+
const nowMs = now();
|
|
1492
|
+
if (cached && cached.expiresAt > nowMs) {
|
|
1493
|
+
return cached.sha;
|
|
1494
|
+
}
|
|
1495
|
+
const pr = await runJson(["pr", String(number), "-o", "json"], { cwd }, GiteaPullRequestViewSchema);
|
|
1496
|
+
if (!pr.headSha) {
|
|
1497
|
+
throw new Error(`Gitea pull request #${number} did not include a head SHA`);
|
|
1498
|
+
}
|
|
1499
|
+
currentPrHeadShaCache.set(cacheKey, {
|
|
1500
|
+
sha: pr.headSha,
|
|
1501
|
+
expiresAt: nowMs + CURRENT_PR_HEAD_SHA_CACHE_TTL_MS,
|
|
1502
|
+
});
|
|
1503
|
+
return pr.headSha;
|
|
1504
|
+
}
|
|
1505
|
+
function toGiteaCheckDetails(status) {
|
|
1506
|
+
return {
|
|
1507
|
+
checkRunId: status.id,
|
|
1508
|
+
name: status.context || `status-${status.id}`,
|
|
1509
|
+
status: status.status,
|
|
1510
|
+
conclusion: mapGiteaCommitState(status.status),
|
|
1511
|
+
url: status.target_url ?? null,
|
|
1512
|
+
detailsUrl: status.url ?? null,
|
|
1513
|
+
output: status.description != null
|
|
1514
|
+
? {
|
|
1515
|
+
title: status.context || null,
|
|
1516
|
+
summary: status.description,
|
|
1517
|
+
text: null,
|
|
1518
|
+
}
|
|
1519
|
+
: null,
|
|
1520
|
+
annotations: [],
|
|
1521
|
+
failedJobs: [],
|
|
1522
|
+
truncated: false,
|
|
1523
|
+
};
|
|
1524
|
+
}
|
|
1525
|
+
function toGiteaActionTaskDetails(task) {
|
|
1526
|
+
const conclusion = mapGiteaActionTaskStatus(task.status);
|
|
1527
|
+
return {
|
|
1528
|
+
checkRunId: task.id,
|
|
1529
|
+
workflowRunId: task.id,
|
|
1530
|
+
name: getGiteaActionTaskName(task),
|
|
1531
|
+
status: task.status,
|
|
1532
|
+
conclusion,
|
|
1533
|
+
url: task.url ?? null,
|
|
1534
|
+
detailsUrl: task.url ?? null,
|
|
1535
|
+
output: {
|
|
1536
|
+
title: task.display_title ?? task.name ?? task.workflow_id ?? null,
|
|
1537
|
+
summary: task.workflow_id ?? null,
|
|
1538
|
+
text: null,
|
|
1539
|
+
},
|
|
1540
|
+
annotations: [],
|
|
1541
|
+
failedJobs: [],
|
|
1542
|
+
truncated: false,
|
|
1543
|
+
};
|
|
1544
|
+
}
|
|
1545
|
+
function notSupported(method) {
|
|
1546
|
+
throw new Error(`${method} is not supported on Gitea yet`);
|
|
1547
|
+
}
|
|
1548
|
+
return {
|
|
1549
|
+
async isAuthenticated(input) {
|
|
1550
|
+
const teaPath = await resolveTea();
|
|
1551
|
+
if (!teaPath) {
|
|
1552
|
+
return false;
|
|
1553
|
+
}
|
|
1554
|
+
const remoteUrl = await resolveRemoteUrl(input.cwd);
|
|
1555
|
+
const host = remoteUrl ? parseGiteaHostFromRemoteUrl(remoteUrl) : null;
|
|
1556
|
+
if (!host) {
|
|
1557
|
+
return false;
|
|
1558
|
+
}
|
|
1559
|
+
try {
|
|
1560
|
+
const stdout = await run(["login", "list", "-o", "json"], { cwd: input.cwd });
|
|
1561
|
+
return hostHasLogin(stdout, host);
|
|
1562
|
+
}
|
|
1563
|
+
catch {
|
|
1564
|
+
return false;
|
|
1565
|
+
}
|
|
1566
|
+
},
|
|
1567
|
+
getCurrentPullRequestStatus(input) {
|
|
1568
|
+
return loadCurrentPullRequestStatus({
|
|
1569
|
+
cwd: input.cwd,
|
|
1570
|
+
headRef: input.headRef,
|
|
1571
|
+
headSha: input.headSha,
|
|
1572
|
+
});
|
|
1573
|
+
},
|
|
1574
|
+
async getPullRequest(input) {
|
|
1575
|
+
// Fetch the single PR by number (like gh `pr view <n>` / glab MR view) so
|
|
1576
|
+
// PRs outside the recent-list window are reachable; tea errors surface as
|
|
1577
|
+
// a not-found rather than silently missing.
|
|
1578
|
+
const view = await runJson(["pr", String(input.number), "-o", "json"], { cwd: input.cwd }, GiteaPullRequestViewSchema);
|
|
1579
|
+
return viewToPullRequestSummary(view);
|
|
1580
|
+
},
|
|
1581
|
+
async getPullRequestHeadRef(input) {
|
|
1582
|
+
const summary = await this.getPullRequest(input);
|
|
1583
|
+
return summary.headRefName;
|
|
1584
|
+
},
|
|
1585
|
+
async getPullRequestCheckoutTarget(input) {
|
|
1586
|
+
const summary = await this.getPullRequest(input);
|
|
1587
|
+
const checkoutRefs = [
|
|
1588
|
+
{ remoteName: "origin", remoteRef: `refs/pull/${summary.number}/head` },
|
|
1589
|
+
];
|
|
1590
|
+
if (summary.headRefName) {
|
|
1591
|
+
checkoutRefs.push({ remoteName: "origin", remoteRef: `refs/heads/${summary.headRefName}` });
|
|
1592
|
+
}
|
|
1593
|
+
const fork = await resolveForkCheckoutFacts(input.cwd, summary);
|
|
1594
|
+
return {
|
|
1595
|
+
number: summary.number,
|
|
1596
|
+
baseRefName: summary.baseRefName,
|
|
1597
|
+
headRefName: summary.headRefName,
|
|
1598
|
+
checkoutRefs,
|
|
1599
|
+
headOwnerLogin: fork.headOwnerLogin,
|
|
1600
|
+
headRepositorySshUrl: fork.headRepositorySshUrl,
|
|
1601
|
+
headRepositoryUrl: fork.headRepositoryUrl,
|
|
1602
|
+
isCrossRepository: fork.isCrossRepository,
|
|
1603
|
+
};
|
|
1604
|
+
},
|
|
1605
|
+
listPullRequests(input) {
|
|
1606
|
+
return listPullRequestItems({
|
|
1607
|
+
cwd: input.cwd,
|
|
1608
|
+
state: "open",
|
|
1609
|
+
query: input.query,
|
|
1610
|
+
limit: input.limit,
|
|
1611
|
+
}).then((items) => items.map(toPullRequestSummary));
|
|
1612
|
+
},
|
|
1613
|
+
listIssues(input) {
|
|
1614
|
+
return runIssueList(input);
|
|
1615
|
+
},
|
|
1616
|
+
async createPullRequest(input) {
|
|
1617
|
+
const args = [
|
|
1618
|
+
"pr",
|
|
1619
|
+
"create",
|
|
1620
|
+
"--title",
|
|
1621
|
+
input.title,
|
|
1622
|
+
"--description",
|
|
1623
|
+
input.body ?? "",
|
|
1624
|
+
"--head",
|
|
1625
|
+
input.head,
|
|
1626
|
+
"--base",
|
|
1627
|
+
input.base,
|
|
1628
|
+
];
|
|
1629
|
+
const stdout = await run(args, { cwd: input.cwd });
|
|
1630
|
+
const url = extractPullRequestUrl(stdout);
|
|
1631
|
+
if (!url) {
|
|
1632
|
+
throw new TeaCommandError({
|
|
1633
|
+
args: redactTeaArgs(args),
|
|
1634
|
+
cwd: input.cwd,
|
|
1635
|
+
exitCode: null,
|
|
1636
|
+
stderr: "tea reported a created pull request but returned no URL",
|
|
1637
|
+
});
|
|
1638
|
+
}
|
|
1639
|
+
const number = parseIndexFromUrl(url);
|
|
1640
|
+
if (number === null) {
|
|
1641
|
+
throw new TeaCommandError({
|
|
1642
|
+
args: redactTeaArgs(args),
|
|
1643
|
+
cwd: input.cwd,
|
|
1644
|
+
exitCode: null,
|
|
1645
|
+
stderr: `tea returned a pull request URL without an index: ${url}`,
|
|
1646
|
+
});
|
|
1647
|
+
}
|
|
1648
|
+
return { url, number };
|
|
1649
|
+
},
|
|
1650
|
+
async mergePullRequest(input) {
|
|
1651
|
+
assertGiteaDirectMergeReady(input);
|
|
1652
|
+
const args = ["pr", "merge", String(input.prNumber), "--style", input.mergeMethod];
|
|
1653
|
+
await run(args, { cwd: input.cwd });
|
|
1654
|
+
return { success: true };
|
|
1655
|
+
},
|
|
1656
|
+
async getPullRequestTimeline(input) {
|
|
1657
|
+
const identity = {
|
|
1658
|
+
prNumber: input.prNumber,
|
|
1659
|
+
repoOwner: input.repoOwner,
|
|
1660
|
+
repoName: input.repoName,
|
|
1661
|
+
};
|
|
1662
|
+
try {
|
|
1663
|
+
const pr = await runJson(["pr", String(input.prNumber), "-o", "json"], { cwd: input.cwd }, GiteaPullRequestViewSchema);
|
|
1664
|
+
const [commentsResult, reviewsResult] = await Promise.allSettled([
|
|
1665
|
+
listTimelineBucketPages(input, `issues/${input.prNumber}/comments`, GiteaIssueCommentSchema),
|
|
1666
|
+
listTimelineBucketPages(input, `pulls/${input.prNumber}/reviews`, GiteaReviewSchema),
|
|
1667
|
+
]);
|
|
1668
|
+
if (commentsResult.status === "rejected" && reviewsResult.status === "rejected") {
|
|
1669
|
+
return {
|
|
1670
|
+
...identity,
|
|
1671
|
+
items: [],
|
|
1672
|
+
truncated: false,
|
|
1673
|
+
error: mapGiteaTimelineError(commentsResult.reason),
|
|
1674
|
+
};
|
|
1675
|
+
}
|
|
1676
|
+
const commentsBucket = commentsResult.status === "fulfilled"
|
|
1677
|
+
? commentsResult.value
|
|
1678
|
+
: { items: [], truncated: false };
|
|
1679
|
+
const reviewsBucket = reviewsResult.status === "fulfilled"
|
|
1680
|
+
? reviewsResult.value
|
|
1681
|
+
: { items: [], truncated: false };
|
|
1682
|
+
const comments = commentsBucket.items;
|
|
1683
|
+
const reviews = reviewsBucket.items;
|
|
1684
|
+
const reviewsWithComments = reviews.filter((review) => review.comments_count > 0);
|
|
1685
|
+
const reviewCommentResults = await Promise.allSettled(reviewsWithComments.map((review) => reviewCommentsLimit(() => listPullRequestReviewComments({
|
|
1686
|
+
cwd: input.cwd,
|
|
1687
|
+
repoOwner: input.repoOwner,
|
|
1688
|
+
repoName: input.repoName,
|
|
1689
|
+
prNumber: input.prNumber,
|
|
1690
|
+
reviewId: review.id,
|
|
1691
|
+
}))));
|
|
1692
|
+
const reviewCommentGroups = reviewCommentResults.flatMap((result, index) => result.status === "fulfilled"
|
|
1693
|
+
? [
|
|
1694
|
+
{
|
|
1695
|
+
reviewId: reviewsWithComments[index].id,
|
|
1696
|
+
comments: result.value.items,
|
|
1697
|
+
truncated: result.value.truncated,
|
|
1698
|
+
},
|
|
1699
|
+
]
|
|
1700
|
+
: []);
|
|
1701
|
+
const reviewComments = reviewCommentGroups.flatMap((group) => group.comments);
|
|
1702
|
+
const items = [
|
|
1703
|
+
...comments.map((comment) => toGiteaTimelineComment(comment, pr)),
|
|
1704
|
+
...reviews.map(toGiteaTimelineReview),
|
|
1705
|
+
...reviewComments.map(toGiteaTimelineReviewComment),
|
|
1706
|
+
]
|
|
1707
|
+
.filter((item) => item !== null)
|
|
1708
|
+
.sort(compareTimelineItems);
|
|
1709
|
+
const truncated = commentsBucket.truncated ||
|
|
1710
|
+
reviewsBucket.truncated ||
|
|
1711
|
+
reviewCommentGroups.some((group) => group.truncated);
|
|
1712
|
+
return {
|
|
1713
|
+
...identity,
|
|
1714
|
+
items,
|
|
1715
|
+
truncated,
|
|
1716
|
+
error: null,
|
|
1717
|
+
};
|
|
1718
|
+
}
|
|
1719
|
+
catch (error) {
|
|
1720
|
+
return { ...identity, items: [], truncated: false, error: mapGiteaTimelineError(error) };
|
|
1721
|
+
}
|
|
1722
|
+
},
|
|
1723
|
+
async getCheckDetails(input) {
|
|
1724
|
+
if (!input.repoOwner || !input.repoName) {
|
|
1725
|
+
throw new Error("Gitea getCheckDetails requires repoOwner and repoName");
|
|
1726
|
+
}
|
|
1727
|
+
if (input.checkRunId === undefined && input.workflowRunId === undefined) {
|
|
1728
|
+
throw new Error("Gitea getCheckDetails requires a checkRunId or workflowRunId");
|
|
1729
|
+
}
|
|
1730
|
+
const sha = input.changeRequestNumber !== undefined
|
|
1731
|
+
? await resolvePullRequestHeadShaByNumber(input.cwd, input.changeRequestNumber)
|
|
1732
|
+
: await resolveCurrentPullRequestHeadSha(input.cwd);
|
|
1733
|
+
const combined = await loadCombinedCommitStatusBestEffort({
|
|
1734
|
+
cwd: input.cwd,
|
|
1735
|
+
repoOwner: input.repoOwner,
|
|
1736
|
+
repoName: input.repoName,
|
|
1737
|
+
sha,
|
|
1738
|
+
});
|
|
1739
|
+
const status = combined.statuses.find((entry) => entry.id === input.checkRunId);
|
|
1740
|
+
if (status) {
|
|
1741
|
+
return toGiteaCheckDetails(status);
|
|
1742
|
+
}
|
|
1743
|
+
const tasks = await loadActionTasksBestEffort({
|
|
1744
|
+
cwd: input.cwd,
|
|
1745
|
+
repoOwner: input.repoOwner,
|
|
1746
|
+
repoName: input.repoName,
|
|
1747
|
+
sha,
|
|
1748
|
+
});
|
|
1749
|
+
const workflowRunId = input.workflowRunId ?? input.checkRunId;
|
|
1750
|
+
const task = tasks.find((entry) => entry.id === workflowRunId);
|
|
1751
|
+
if (!task) {
|
|
1752
|
+
throw new Error(`Gitea check ${workflowRunId} was not found`);
|
|
1753
|
+
}
|
|
1754
|
+
return toGiteaActionTaskDetails(task);
|
|
1755
|
+
},
|
|
1756
|
+
async searchIssuesAndPrs(input) {
|
|
1757
|
+
if (input.force && !input.reason) {
|
|
1758
|
+
throw new Error("ForgeService forced read requires a reason");
|
|
1759
|
+
}
|
|
1760
|
+
const kinds = normalizeForgeSearchKinds(input.kinds);
|
|
1761
|
+
const shouldFetchIssues = kinds.includes("issue");
|
|
1762
|
+
const shouldFetchMergeRequests = kinds.includes("change_request");
|
|
1763
|
+
const [issuesResult, mergeRequestsResult] = await Promise.allSettled([
|
|
1764
|
+
shouldFetchIssues
|
|
1765
|
+
? runIssueList({ cwd: input.cwd, query: input.query, limit: input.limit })
|
|
1766
|
+
: Promise.resolve(null),
|
|
1767
|
+
shouldFetchMergeRequests
|
|
1768
|
+
? listPullRequestItems({
|
|
1769
|
+
cwd: input.cwd,
|
|
1770
|
+
state: "open",
|
|
1771
|
+
query: input.query,
|
|
1772
|
+
limit: input.limit,
|
|
1773
|
+
}).then((items) => items.map(toPullRequestSummary))
|
|
1774
|
+
: Promise.resolve(null),
|
|
1775
|
+
]);
|
|
1776
|
+
const requestedResults = [
|
|
1777
|
+
shouldFetchIssues ? issuesResult : null,
|
|
1778
|
+
shouldFetchMergeRequests ? mergeRequestsResult : null,
|
|
1779
|
+
].filter((result) => result !== null);
|
|
1780
|
+
const unavailableAuthState = getTeaUnavailableSearchAuthState(requestedResults);
|
|
1781
|
+
if (unavailableAuthState) {
|
|
1782
|
+
return createUnavailableSearchResult(unavailableAuthState);
|
|
1783
|
+
}
|
|
1784
|
+
throwFirstNonTeaAuthSearchRejection(requestedResults);
|
|
1785
|
+
const items = [];
|
|
1786
|
+
if (shouldFetchIssues && issuesResult.status === "fulfilled") {
|
|
1787
|
+
for (const issue of issuesResult.value ?? []) {
|
|
1788
|
+
items.push({
|
|
1789
|
+
kind: "issue",
|
|
1790
|
+
number: issue.number,
|
|
1791
|
+
title: issue.title,
|
|
1792
|
+
url: issue.url,
|
|
1793
|
+
state: issue.state,
|
|
1794
|
+
body: issue.body,
|
|
1795
|
+
labels: issue.labels,
|
|
1796
|
+
...(issue.projectPath ? { projectPath: issue.projectPath } : {}),
|
|
1797
|
+
baseRefName: null,
|
|
1798
|
+
headRefName: null,
|
|
1799
|
+
updatedAt: issue.updatedAt,
|
|
1800
|
+
});
|
|
1801
|
+
}
|
|
1802
|
+
}
|
|
1803
|
+
if (shouldFetchMergeRequests && mergeRequestsResult.status === "fulfilled") {
|
|
1804
|
+
for (const pullRequest of mergeRequestsResult.value ?? []) {
|
|
1805
|
+
items.push({
|
|
1806
|
+
kind: "change_request",
|
|
1807
|
+
number: pullRequest.number,
|
|
1808
|
+
title: pullRequest.title,
|
|
1809
|
+
url: pullRequest.url,
|
|
1810
|
+
state: pullRequest.state,
|
|
1811
|
+
body: pullRequest.body,
|
|
1812
|
+
labels: pullRequest.labels,
|
|
1813
|
+
...(pullRequest.projectPath ? { projectPath: pullRequest.projectPath } : {}),
|
|
1814
|
+
baseRefName: pullRequest.baseRefName,
|
|
1815
|
+
headRefName: pullRequest.headRefName,
|
|
1816
|
+
updatedAt: pullRequest.updatedAt,
|
|
1817
|
+
});
|
|
1818
|
+
}
|
|
1819
|
+
}
|
|
1820
|
+
items.sort((left, right) => parseOptionalTime(right.updatedAt) - parseOptionalTime(left.updatedAt));
|
|
1821
|
+
return {
|
|
1822
|
+
items,
|
|
1823
|
+
featuresEnabled: true,
|
|
1824
|
+
authState: "authenticated",
|
|
1825
|
+
githubFeaturesEnabled: true,
|
|
1826
|
+
};
|
|
1827
|
+
},
|
|
1828
|
+
enablePullRequestAutoMerge(_input) {
|
|
1829
|
+
return notSupported("enablePullRequestAutoMerge");
|
|
1830
|
+
},
|
|
1831
|
+
disablePullRequestAutoMerge(_input) {
|
|
1832
|
+
return notSupported("disablePullRequestAutoMerge");
|
|
1833
|
+
},
|
|
1834
|
+
invalidate(input) {
|
|
1835
|
+
const prefix = `${input.cwd}:`;
|
|
1836
|
+
for (const key of currentPrHeadShaCache.keys()) {
|
|
1837
|
+
if (key.startsWith(prefix)) {
|
|
1838
|
+
currentPrHeadShaCache.delete(key);
|
|
1839
|
+
}
|
|
1840
|
+
}
|
|
1841
|
+
},
|
|
1842
|
+
};
|
|
1843
|
+
}
|
|
1844
|
+
//# sourceMappingURL=gitea-service.js.map
|