lastlight 0.1.8 → 0.2.0
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/README.md +265 -118
- package/agent-context/rules.md +62 -9
- package/agent-context/security.md +69 -0
- package/config/default.yaml +89 -0
- package/deploy/.env.production.example +20 -2
- package/deploy/entrypoint.sh +16 -17
- package/deploy/native/README.md +160 -0
- package/deploy/native/install.sh +110 -0
- package/deploy/native/lastlight.env.example +95 -0
- package/deploy/native/lastlight.service +50 -0
- package/deploy/sandbox-entrypoint.sh +59 -42
- package/dist/admin/auth.d.ts +1 -1
- package/dist/admin/auth.js +3 -1
- package/dist/admin/auth.js.map +1 -1
- package/dist/admin/chat-session-reader.d.ts +11 -14
- package/dist/admin/chat-session-reader.js +27 -51
- package/dist/admin/chat-session-reader.js.map +1 -1
- package/dist/admin/docker.d.ts +37 -0
- package/dist/admin/docker.js +86 -1
- package/dist/admin/docker.js.map +1 -1
- package/dist/admin/index.js +38 -3
- package/dist/admin/index.js.map +1 -1
- package/dist/admin/log-search.test.d.ts +1 -0
- package/dist/admin/log-search.test.js +78 -0
- package/dist/admin/log-search.test.js.map +1 -0
- package/dist/admin/routes.d.ts +52 -3
- package/dist/admin/routes.js +780 -63
- package/dist/admin/routes.js.map +1 -1
- package/dist/admin/routes.test.js +680 -14
- package/dist/admin/routes.test.js.map +1 -1
- package/dist/admin/server-logs.test.d.ts +1 -0
- package/dist/admin/server-logs.test.js +58 -0
- package/dist/admin/server-logs.test.js.map +1 -0
- package/dist/admin/sessions.d.ts +26 -39
- package/dist/admin/sessions.js +86 -310
- package/dist/admin/sessions.js.map +1 -1
- package/dist/admin/sessions.test.d.ts +1 -0
- package/dist/admin/sessions.test.js +78 -0
- package/dist/admin/sessions.test.js.map +1 -0
- package/dist/admin/version.d.ts +15 -0
- package/dist/admin/version.js +73 -0
- package/dist/admin/version.js.map +1 -0
- package/dist/admin/version.test.d.ts +1 -0
- package/dist/admin/version.test.js +71 -0
- package/dist/admin/version.test.js.map +1 -0
- package/dist/cli-config.d.ts +55 -0
- package/dist/cli-config.js +119 -0
- package/dist/cli-config.js.map +1 -0
- package/dist/cli-config.test.d.ts +1 -0
- package/dist/cli-config.test.js +92 -0
- package/dist/cli-config.test.js.map +1 -0
- package/dist/cli-format.d.ts +19 -0
- package/dist/cli-format.js +107 -0
- package/dist/cli-format.js.map +1 -0
- package/dist/cli-server.d.ts +73 -0
- package/dist/cli-server.js +347 -0
- package/dist/cli-server.js.map +1 -0
- package/dist/cli-server.test.d.ts +1 -0
- package/dist/cli-server.test.js +38 -0
- package/dist/cli-server.test.js.map +1 -0
- package/dist/cli-timeline.d.ts +35 -0
- package/dist/cli-timeline.js +373 -0
- package/dist/cli-timeline.js.map +1 -0
- package/dist/cli-timeline.test.d.ts +1 -0
- package/dist/cli-timeline.test.js +104 -0
- package/dist/cli-timeline.test.js.map +1 -0
- package/dist/cli.d.ts +0 -19
- package/dist/cli.js +910 -194
- package/dist/cli.js.map +1 -1
- package/dist/config-overlay.test.d.ts +1 -0
- package/dist/config-overlay.test.js +112 -0
- package/dist/config-overlay.test.js.map +1 -0
- package/dist/config-resolve.d.ts +28 -0
- package/dist/config-resolve.js +47 -0
- package/dist/config-resolve.js.map +1 -0
- package/dist/config-resolve.test.d.ts +1 -0
- package/dist/config-resolve.test.js +68 -0
- package/dist/config-resolve.test.js.map +1 -0
- package/dist/config.d.ts +62 -49
- package/dist/config.js +452 -76
- package/dist/config.js.map +1 -1
- package/dist/config.test.js +201 -32
- package/dist/config.test.js.map +1 -1
- package/dist/connectors/github-webhook.js +83 -5
- package/dist/connectors/github-webhook.js.map +1 -1
- package/dist/connectors/github-webhook.test.d.ts +1 -0
- package/dist/connectors/github-webhook.test.js +156 -0
- package/dist/connectors/github-webhook.test.js.map +1 -0
- package/dist/connectors/messaging/session-manager.d.ts +18 -0
- package/dist/connectors/messaging/session-manager.js +83 -2
- package/dist/connectors/messaging/session-manager.js.map +1 -1
- package/dist/connectors/messaging/session-manager.test.d.ts +1 -0
- package/dist/connectors/messaging/session-manager.test.js +144 -0
- package/dist/connectors/messaging/session-manager.test.js.map +1 -0
- package/dist/connectors/slack/connector.d.ts +9 -0
- package/dist/connectors/slack/connector.js +15 -0
- package/dist/connectors/slack/connector.js.map +1 -1
- package/dist/connectors/slack/mrkdwn.js +81 -0
- package/dist/connectors/slack/mrkdwn.js.map +1 -1
- package/dist/connectors/slack/mrkdwn.test.js +49 -0
- package/dist/connectors/slack/mrkdwn.test.js.map +1 -1
- package/dist/connectors/types.d.ts +1 -1
- package/dist/cron/fanout.d.ts +33 -0
- package/dist/cron/fanout.js +55 -0
- package/dist/cron/fanout.js.map +1 -0
- package/dist/cron/fanout.test.d.ts +1 -0
- package/dist/cron/fanout.test.js +73 -0
- package/dist/cron/fanout.test.js.map +1 -0
- package/dist/cron/jobs.d.ts +5 -0
- package/dist/cron/jobs.js +10 -3
- package/dist/cron/jobs.js.map +1 -1
- package/dist/cron/scheduler.d.ts +12 -0
- package/dist/cron/scheduler.js +27 -1
- package/dist/cron/scheduler.js.map +1 -1
- package/dist/engine/agent-executor.d.ts +158 -0
- package/dist/engine/agent-executor.js +1140 -0
- package/dist/engine/agent-executor.js.map +1 -0
- package/dist/engine/agent-executor.test.d.ts +1 -0
- package/dist/engine/agent-executor.test.js +395 -0
- package/dist/engine/agent-executor.test.js.map +1 -0
- package/dist/engine/chat-runner.d.ts +123 -0
- package/dist/engine/chat-runner.js +379 -0
- package/dist/engine/chat-runner.js.map +1 -0
- package/dist/engine/chat-runner.test.d.ts +1 -0
- package/dist/engine/chat-runner.test.js +104 -0
- package/dist/engine/chat-runner.test.js.map +1 -0
- package/dist/engine/chat-skills.d.ts +45 -0
- package/dist/engine/chat-skills.js +184 -0
- package/dist/engine/chat-skills.js.map +1 -0
- package/dist/engine/chat-skills.test.d.ts +1 -0
- package/dist/engine/chat-skills.test.js +20 -0
- package/dist/engine/chat-skills.test.js.map +1 -0
- package/dist/engine/chat.d.ts +20 -23
- package/dist/engine/chat.js +251 -155
- package/dist/engine/chat.js.map +1 -1
- package/dist/engine/chat.test.d.ts +1 -0
- package/dist/engine/chat.test.js +42 -0
- package/dist/engine/chat.test.js.map +1 -0
- package/dist/engine/classifier.d.ts +35 -2
- package/dist/engine/classifier.js +170 -31
- package/dist/engine/classifier.js.map +1 -1
- package/dist/engine/classifier.test.d.ts +1 -0
- package/dist/engine/classifier.test.js +115 -0
- package/dist/engine/classifier.test.js.map +1 -0
- package/dist/engine/dispatcher.d.ts +60 -0
- package/dist/engine/dispatcher.js +601 -0
- package/dist/engine/dispatcher.js.map +1 -0
- package/dist/engine/dispatcher.test.d.ts +1 -0
- package/dist/engine/dispatcher.test.js +511 -0
- package/dist/engine/dispatcher.test.js.map +1 -0
- package/dist/engine/event-shim.d.ts +117 -0
- package/dist/engine/event-shim.js +435 -0
- package/dist/engine/event-shim.js.map +1 -0
- package/dist/engine/event-shim.test.d.ts +1 -0
- package/dist/engine/event-shim.test.js +194 -0
- package/dist/engine/event-shim.test.js.map +1 -0
- package/dist/engine/git-auth.d.ts +13 -17
- package/dist/engine/git-auth.js +99 -42
- package/dist/engine/git-auth.js.map +1 -1
- package/dist/engine/git-auth.test.d.ts +1 -0
- package/dist/engine/git-auth.test.js +117 -0
- package/dist/engine/git-auth.test.js.map +1 -0
- package/dist/engine/github-app-client.d.ts +7 -0
- package/dist/engine/github-app-client.js +16 -0
- package/dist/engine/github-app-client.js.map +1 -0
- package/dist/engine/github-app-client.test.d.ts +1 -0
- package/dist/engine/github-app-client.test.js +44 -0
- package/dist/engine/github-app-client.test.js.map +1 -0
- package/dist/engine/github-tools.d.ts +12 -0
- package/dist/engine/github-tools.js +261 -0
- package/dist/engine/github-tools.js.map +1 -0
- package/dist/engine/github.d.ts +1027 -43
- package/dist/engine/github.js +153 -14
- package/dist/engine/github.js.map +1 -1
- package/dist/engine/llm.d.ts +47 -0
- package/dist/engine/llm.js +221 -0
- package/dist/engine/llm.js.map +1 -0
- package/dist/engine/llm.test.d.ts +1 -0
- package/dist/engine/llm.test.js +189 -0
- package/dist/engine/llm.test.js.map +1 -0
- package/dist/engine/profiles.d.ts +249 -0
- package/dist/engine/profiles.js +42 -0
- package/dist/engine/profiles.js.map +1 -0
- package/dist/engine/router.d.ts +12 -6
- package/dist/engine/router.js +339 -81
- package/dist/engine/router.js.map +1 -1
- package/dist/engine/router.test.js +428 -78
- package/dist/engine/router.test.js.map +1 -1
- package/dist/engine/screen.d.ts +41 -0
- package/dist/engine/screen.js +93 -0
- package/dist/engine/screen.js.map +1 -0
- package/dist/engine/screen.test.d.ts +1 -0
- package/dist/engine/screen.test.js +82 -0
- package/dist/engine/screen.test.js.map +1 -0
- package/dist/index.js +423 -437
- package/dist/index.js.map +1 -1
- package/dist/managed-repos.d.ts +7 -9
- package/dist/managed-repos.js +12 -15
- package/dist/managed-repos.js.map +1 -1
- package/dist/managed-repos.test.js +24 -19
- package/dist/managed-repos.test.js.map +1 -1
- package/dist/notify/index.d.ts +15 -0
- package/dist/notify/index.js +6 -0
- package/dist/notify/index.js.map +1 -0
- package/dist/notify/model.d.ts +57 -0
- package/dist/notify/model.js +89 -0
- package/dist/notify/model.js.map +1 -0
- package/dist/notify/model.test.d.ts +1 -0
- package/dist/notify/model.test.js +109 -0
- package/dist/notify/model.test.js.map +1 -0
- package/dist/notify/notifier.d.ts +17 -0
- package/dist/notify/notifier.js +87 -0
- package/dist/notify/notifier.js.map +1 -0
- package/dist/notify/notifier.test.d.ts +1 -0
- package/dist/notify/notifier.test.js +100 -0
- package/dist/notify/notifier.test.js.map +1 -0
- package/dist/notify/render.d.ts +21 -0
- package/dist/notify/render.js +59 -0
- package/dist/notify/render.js.map +1 -0
- package/dist/notify/render.test.d.ts +1 -0
- package/dist/notify/render.test.js +65 -0
- package/dist/notify/render.test.js.map +1 -0
- package/dist/notify/transports/github.d.ts +26 -0
- package/dist/notify/transports/github.js +26 -0
- package/dist/notify/transports/github.js.map +1 -0
- package/dist/notify/transports/slack.d.ts +26 -0
- package/dist/notify/transports/slack.js +28 -0
- package/dist/notify/transports/slack.js.map +1 -0
- package/dist/notify/transports.test.d.ts +1 -0
- package/dist/notify/transports.test.js +71 -0
- package/dist/notify/transports.test.js.map +1 -0
- package/dist/notify/types.d.ts +95 -0
- package/dist/notify/types.js +16 -0
- package/dist/notify/types.js.map +1 -0
- package/dist/sandbox/docker-compose.test.d.ts +1 -0
- package/dist/sandbox/docker-compose.test.js +128 -0
- package/dist/sandbox/docker-compose.test.js.map +1 -0
- package/dist/sandbox/docker.d.ts +97 -9
- package/dist/sandbox/docker.js +192 -41
- package/dist/sandbox/docker.js.map +1 -1
- package/dist/sandbox/docker.test.d.ts +1 -0
- package/dist/sandbox/docker.test.js +137 -0
- package/dist/sandbox/docker.test.js.map +1 -0
- package/dist/sandbox/egress-allowlist.d.ts +69 -0
- package/dist/sandbox/egress-allowlist.js +164 -0
- package/dist/sandbox/egress-allowlist.js.map +1 -0
- package/dist/sandbox/egress-allowlist.test.d.ts +1 -0
- package/dist/sandbox/egress-allowlist.test.js +65 -0
- package/dist/sandbox/egress-allowlist.test.js.map +1 -0
- package/dist/sandbox/egress-firewall-config.d.ts +127 -0
- package/dist/sandbox/egress-firewall-config.js +434 -0
- package/dist/sandbox/egress-firewall-config.js.map +1 -0
- package/dist/sandbox/egress-firewall-config.test.d.ts +1 -0
- package/dist/sandbox/egress-firewall-config.test.js +244 -0
- package/dist/sandbox/egress-firewall-config.test.js.map +1 -0
- package/dist/sandbox/images.d.ts +23 -0
- package/dist/sandbox/images.js +55 -0
- package/dist/sandbox/images.js.map +1 -0
- package/dist/sandbox/index.d.ts +82 -3
- package/dist/sandbox/index.js +223 -93
- package/dist/sandbox/index.js.map +1 -1
- package/dist/sandbox/index.test.d.ts +1 -0
- package/dist/sandbox/index.test.js +157 -0
- package/dist/sandbox/index.test.js.map +1 -0
- package/dist/session-log.d.ts +63 -0
- package/dist/session-log.js +290 -0
- package/dist/session-log.js.map +1 -0
- package/dist/session-log.test.d.ts +1 -0
- package/dist/session-log.test.js +85 -0
- package/dist/session-log.test.js.map +1 -0
- package/dist/setup.d.ts +31 -12
- package/dist/setup.js +516 -174
- package/dist/setup.js.map +1 -1
- package/dist/setup.test.js +138 -6
- package/dist/setup.test.js.map +1 -1
- package/dist/state/approval-store.d.ts +86 -0
- package/dist/state/approval-store.js +140 -0
- package/dist/state/approval-store.js.map +1 -0
- package/dist/state/build-assets.d.ts +50 -0
- package/dist/state/build-assets.js +154 -0
- package/dist/state/build-assets.js.map +1 -0
- package/dist/state/build-assets.test.d.ts +1 -0
- package/dist/state/build-assets.test.js +106 -0
- package/dist/state/build-assets.test.js.map +1 -0
- package/dist/state/db.d.ts +65 -333
- package/dist/state/db.js +112 -835
- package/dist/state/db.js.map +1 -1
- package/dist/state/db.test.js +127 -91
- package/dist/state/db.test.js.map +1 -1
- package/dist/state/execution-store.d.ts +257 -0
- package/dist/state/execution-store.js +527 -0
- package/dist/state/execution-store.js.map +1 -0
- package/dist/state/migrate.d.ts +15 -0
- package/dist/state/migrate.js +175 -0
- package/dist/state/migrate.js.map +1 -0
- package/dist/state/workflow-run-store.d.ts +195 -0
- package/dist/state/workflow-run-store.js +363 -0
- package/dist/state/workflow-run-store.js.map +1 -0
- package/dist/state/workflow-run-store.test.d.ts +1 -0
- package/dist/state/workflow-run-store.test.js +264 -0
- package/dist/state/workflow-run-store.test.js.map +1 -0
- package/dist/telemetry/index.d.ts +38 -0
- package/dist/telemetry/index.js +253 -0
- package/dist/telemetry/index.js.map +1 -0
- package/dist/telemetry/index.test.d.ts +1 -0
- package/dist/telemetry/index.test.js +73 -0
- package/dist/telemetry/index.test.js.map +1 -0
- package/dist/telemetry/pi-events.d.ts +12 -0
- package/dist/telemetry/pi-events.js +134 -0
- package/dist/telemetry/pi-events.js.map +1 -0
- package/dist/telemetry/pi-events.test.d.ts +1 -0
- package/dist/telemetry/pi-events.test.js +69 -0
- package/dist/telemetry/pi-events.test.js.map +1 -0
- package/dist/workflows/dag.d.ts +13 -1
- package/dist/workflows/dag.js +7 -3
- package/dist/workflows/dag.js.map +1 -1
- package/dist/workflows/dag.test.js +22 -0
- package/dist/workflows/dag.test.js.map +1 -1
- package/dist/workflows/golden-build.test.d.ts +1 -0
- package/dist/workflows/golden-build.test.js +45 -0
- package/dist/workflows/golden-build.test.js.map +1 -0
- package/dist/workflows/loader-overlay.test.d.ts +1 -0
- package/dist/workflows/loader-overlay.test.js +101 -0
- package/dist/workflows/loader-overlay.test.js.map +1 -0
- package/dist/workflows/loader.d.ts +36 -11
- package/dist/workflows/loader.js +311 -87
- package/dist/workflows/loader.js.map +1 -1
- package/dist/workflows/loader.test.js +114 -10
- package/dist/workflows/loader.test.js.map +1 -1
- package/dist/workflows/loop-eval.js +2 -0
- package/dist/workflows/loop-eval.js.map +1 -1
- package/dist/workflows/loop-eval.test.js +14 -0
- package/dist/workflows/loop-eval.test.js.map +1 -1
- package/dist/workflows/phase-executor.d.ts +145 -0
- package/dist/workflows/phase-executor.js +691 -0
- package/dist/workflows/phase-executor.js.map +1 -0
- package/dist/workflows/phase-executor.test.d.ts +1 -0
- package/dist/workflows/phase-executor.test.js +434 -0
- package/dist/workflows/phase-executor.test.js.map +1 -0
- package/dist/workflows/phase-ref.d.ts +44 -0
- package/dist/workflows/phase-ref.js +78 -0
- package/dist/workflows/phase-ref.js.map +1 -0
- package/dist/workflows/phase-ref.test.d.ts +1 -0
- package/dist/workflows/phase-ref.test.js +24 -0
- package/dist/workflows/phase-ref.test.js.map +1 -0
- package/dist/workflows/resume.d.ts +5 -11
- package/dist/workflows/resume.js +88 -7
- package/dist/workflows/resume.js.map +1 -1
- package/dist/workflows/runner.d.ts +34 -27
- package/dist/workflows/runner.js +252 -930
- package/dist/workflows/runner.js.map +1 -1
- package/dist/workflows/runner.test.js +346 -35
- package/dist/workflows/runner.test.js.map +1 -1
- package/dist/workflows/schema.d.ts +52 -10
- package/dist/workflows/schema.js +147 -7
- package/dist/workflows/schema.js.map +1 -1
- package/dist/workflows/simple.d.ts +67 -3
- package/dist/workflows/simple.js +248 -87
- package/dist/workflows/simple.js.map +1 -1
- package/dist/workflows/simple.test.d.ts +1 -0
- package/dist/workflows/simple.test.js +107 -0
- package/dist/workflows/simple.test.js.map +1 -0
- package/dist/workflows/templates.d.ts +29 -0
- package/dist/workflows/templates.js +42 -4
- package/dist/workflows/templates.js.map +1 -1
- package/dist/workflows/templates.test.js +103 -0
- package/dist/workflows/templates.test.js.map +1 -1
- package/dist/workflows/triggers.d.ts +21 -0
- package/dist/workflows/triggers.js +44 -0
- package/dist/workflows/triggers.js.map +1 -0
- package/dist/workflows/verdict.d.ts +19 -0
- package/dist/workflows/verdict.js +30 -0
- package/dist/workflows/verdict.js.map +1 -0
- package/dist/workflows/verdict.test.d.ts +1 -0
- package/dist/workflows/verdict.test.js +44 -0
- package/dist/workflows/verdict.test.js.map +1 -0
- package/dist/worktree/manager.d.ts +1 -1
- package/dist/worktree/manager.js +14 -14
- package/dist/worktree/manager.js.map +1 -1
- package/dist/worktree/manager.test.d.ts +1 -0
- package/dist/worktree/manager.test.js +87 -0
- package/dist/worktree/manager.test.js.map +1 -0
- package/docker-compose.yml +206 -5
- package/package.json +19 -7
- package/sandbox.Dockerfile +97 -18
- package/skills/README.md +40 -0
- package/skills/browser-qa/SKILL.md +193 -0
- package/skills/browser-qa/scripts/agent-browser.mjs +380 -0
- package/skills/building/SKILL.md +95 -0
- package/skills/chat/SKILL.md +30 -11
- package/skills/code-review/SKILL.md +59 -0
- package/skills/debug-production/SKILL.md +108 -0
- package/skills/demo/SKILL.md +194 -0
- package/skills/demo/scripts/compose-demo.sh +205 -0
- package/skills/issue-answer/SKILL.md +90 -0
- package/skills/issue-comment/SKILL.md +38 -24
- package/skills/issue-triage/SKILL.md +103 -37
- package/skills/issue-triage/references/AGENT-BRIEF.md +61 -0
- package/skills/pr-comment/SKILL.md +64 -0
- package/skills/pr-review/SKILL.md +65 -49
- package/skills/qa-test/SKILL.md +97 -0
- package/skills/repo-health/SKILL.md +48 -45
- package/skills/security-feedback/SKILL.md +173 -0
- package/skills/security-feedback/references/templates.md +77 -0
- package/skills/security-review/SKILL.md +213 -0
- package/skills/security-review/references/issue-format.md +302 -0
- package/skills/verify/SKILL.md +118 -0
- package/workflows/answer.yaml +37 -0
- package/workflows/build.yaml +32 -22
- package/workflows/cron-security.yaml +6 -0
- package/workflows/demo.yaml +55 -0
- package/workflows/explore.yaml +9 -0
- package/workflows/pr-comment.yaml +16 -0
- package/workflows/pr-fix.yaml +3 -0
- package/workflows/pr-review.yaml +4 -1
- package/workflows/prompts/answer.md +67 -0
- package/workflows/prompts/architect.md +24 -7
- package/workflows/prompts/demo.md +100 -0
- package/workflows/prompts/executor.md +29 -20
- package/workflows/prompts/explore-ask.md +51 -22
- package/workflows/prompts/explore-publish.md +2 -2
- package/workflows/prompts/explore-read.md +24 -10
- package/workflows/prompts/explore-synthesize.md +15 -8
- package/workflows/prompts/fix.md +9 -10
- package/workflows/prompts/guardrails.md +26 -8
- package/workflows/prompts/pr-fix.md +6 -7
- package/workflows/prompts/pr.md +11 -10
- package/workflows/prompts/qa-browser.md +95 -0
- package/workflows/prompts/qa-synth.md +44 -0
- package/workflows/prompts/qa-test.md +60 -0
- package/workflows/prompts/re-reviewer.md +8 -9
- package/workflows/prompts/reviewer.md +10 -9
- package/workflows/prompts/verify-browser.md +93 -0
- package/workflows/prompts/verify-synth.md +44 -0
- package/workflows/prompts/verify.md +63 -0
- package/workflows/qa-test.yaml +87 -0
- package/workflows/security-feedback.yaml +25 -0
- package/workflows/security-review.yaml +29 -0
- package/workflows/verify.yaml +85 -0
- package/deploy/mcp-config.tmpl.json +0 -14
- package/dist/cron/rate-limits.d.ts +0 -26
- package/dist/cron/rate-limits.js +0 -193
- package/dist/cron/rate-limits.js.map +0 -1
- package/dist/engine/executor.d.ts +0 -75
- package/dist/engine/executor.js +0 -292
- package/dist/engine/executor.js.map +0 -1
- package/mcp-github-app/package.json +0 -18
- package/mcp-github-app/src/auth.js +0 -66
- package/mcp-github-app/src/github.js +0 -371
- package/mcp-github-app/src/index.js +0 -534
- package/skills/devops/webhook-subscriptions/SKILL.md +0 -180
- package/skills/github/DESCRIPTION.md +0 -3
- package/skills/github/codebase-inspection/SKILL.md +0 -115
- package/skills/github/github-auth/SKILL.md +0 -54
- package/skills/github/github-auth/scripts/gh-env.sh +0 -66
- package/skills/github/github-code-review/SKILL.md +0 -480
- package/skills/github/github-code-review/references/review-output-template.md +0 -74
- package/skills/github/github-issues/SKILL.md +0 -369
- package/skills/github/github-issues/templates/bug-report.md +0 -35
- package/skills/github/github-issues/templates/feature-request.md +0 -31
- package/skills/github/github-pr-workflow/SKILL.md +0 -395
- package/skills/github/github-pr-workflow/references/ci-troubleshooting.md +0 -183
- package/skills/github/github-pr-workflow/references/conventional-commits.md +0 -71
- package/skills/github/github-pr-workflow/templates/pr-body-bugfix.md +0 -35
- package/skills/github/github-pr-workflow/templates/pr-body-feature.md +0 -33
- package/skills/github/github-repo-management/SKILL.md +0 -515
- package/skills/github/github-repo-management/references/github-api-cheatsheet.md +0 -161
- package/skills/github-orchestrator/SKILL.md +0 -103
- package/skills/mcp/DESCRIPTION.md +0 -3
- package/skills/mcp/mcporter/SKILL.md +0 -122
- package/skills/mcp/native-mcp/SKILL.md +0 -356
- package/skills/software-development/architect/SKILL.md +0 -154
- package/skills/software-development/assure-guardrails/SKILL.md +0 -239
- package/skills/software-development/plan/SKILL.md +0 -64
- package/skills/software-development/requesting-code-review/SKILL.md +0 -291
- package/skills/software-development/subagent-driven-development/SKILL.md +0 -433
- package/skills/software-development/systematic-debugging/SKILL.md +0 -366
- package/skills/software-development/test-driven-development/SKILL.md +0 -342
|
@@ -0,0 +1,379 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* In-process chat agent for Slack/Discord threads. Replaces the
|
|
3
|
+
* `opencode serve` HTTP supervisor with a direct pi-ai conversation:
|
|
4
|
+
*
|
|
5
|
+
* - One pi-ai conversation per messaging thread.
|
|
6
|
+
* - Conversation state lives in our existing `messaging_messages` DB
|
|
7
|
+
* table — rehydrated on every turn so harness restarts are transparent.
|
|
8
|
+
* - Tools are limited to read-only GitHub (see github-tools.ts). No bash,
|
|
9
|
+
* no edit, no file system, no MCP.
|
|
10
|
+
* - Per-thread in-flight chain so two messages in the same thread
|
|
11
|
+
* serialize cleanly while different threads stay parallel.
|
|
12
|
+
*/
|
|
13
|
+
import { randomUUID } from "node:crypto";
|
|
14
|
+
import { Octokit } from "octokit";
|
|
15
|
+
import { completeSimple, getModel, } from "@earendil-works/pi-ai";
|
|
16
|
+
import { buildChatGitHubTools } from "./github-tools.js";
|
|
17
|
+
const MAX_TOOL_ROUNDS = 8;
|
|
18
|
+
/**
|
|
19
|
+
* Exponential backoff schedule (ms) for transient chat-model failures —
|
|
20
|
+
* rate limits (429) and provider hiccups (5xx / overloaded / transient
|
|
21
|
+
* network). pi-ai disables the provider SDK's own retries (`maxRetries: 0`),
|
|
22
|
+
* so without this a single 429 from the model would kill the whole turn.
|
|
23
|
+
* The sandbox path already retries via pi-coding-agent's auto-retry; the
|
|
24
|
+
* chat path drives pi-ai directly, so it needs its own.
|
|
25
|
+
*/
|
|
26
|
+
const CHAT_RETRY_BACKOFF_MS = [10_000, 30_000, 60_000];
|
|
27
|
+
/**
|
|
28
|
+
* Match transient, retryable model errors. Deliberately conservative: auth /
|
|
29
|
+
* validation / context-overflow / other 4xx (anything but 429) are NOT
|
|
30
|
+
* retried — only rate limits, server errors, and transient network faults.
|
|
31
|
+
*/
|
|
32
|
+
export function isRetryableModelError(message) {
|
|
33
|
+
const m = message.toLowerCase();
|
|
34
|
+
return (/\b429\b/.test(m) ||
|
|
35
|
+
m.includes("rate limit") ||
|
|
36
|
+
m.includes("rate_limit") ||
|
|
37
|
+
m.includes("too many requests") ||
|
|
38
|
+
m.includes("overloaded") ||
|
|
39
|
+
/\b50[0234]\b/.test(m) || // 500 / 502 / 503 / 504
|
|
40
|
+
m.includes("service unavailable") ||
|
|
41
|
+
m.includes("timeout") ||
|
|
42
|
+
m.includes("etimedout") ||
|
|
43
|
+
m.includes("econnreset") ||
|
|
44
|
+
m.includes("fetch failed"));
|
|
45
|
+
}
|
|
46
|
+
const sleepMs = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
47
|
+
/**
|
|
48
|
+
* Call `complete`, retrying transient failures with exponential backoff.
|
|
49
|
+
* Handles both shapes pi-ai surfaces a failure as: a thrown error, and a
|
|
50
|
+
* returned AssistantMessage with `stopReason === "error"`. Non-retryable
|
|
51
|
+
* outcomes (and the final attempt) are returned/thrown unchanged so the
|
|
52
|
+
* caller's existing error handling still applies. Dependency-injected for
|
|
53
|
+
* testing (`delaysMs` / `sleepFn` / `onRetry`).
|
|
54
|
+
*/
|
|
55
|
+
export async function completeWithRetry(complete, model, context, opts, deps = {}) {
|
|
56
|
+
const delays = deps.delaysMs ?? CHAT_RETRY_BACKOFF_MS;
|
|
57
|
+
const doSleep = deps.sleepFn ?? sleepMs;
|
|
58
|
+
let attempt = 0;
|
|
59
|
+
for (;;) {
|
|
60
|
+
let assistant;
|
|
61
|
+
let errMsg;
|
|
62
|
+
let thrown;
|
|
63
|
+
try {
|
|
64
|
+
assistant = await complete(model, context, opts);
|
|
65
|
+
if (assistant.stopReason !== "error")
|
|
66
|
+
return assistant;
|
|
67
|
+
errMsg = assistant.errorMessage ?? "error";
|
|
68
|
+
}
|
|
69
|
+
catch (err) {
|
|
70
|
+
thrown = err;
|
|
71
|
+
errMsg = err instanceof Error ? err.message : String(err);
|
|
72
|
+
}
|
|
73
|
+
if (attempt >= delays.length || !isRetryableModelError(errMsg)) {
|
|
74
|
+
if (thrown !== undefined)
|
|
75
|
+
throw thrown; // preserve the original error
|
|
76
|
+
return assistant; // non-retryable / exhausted errored assistant
|
|
77
|
+
}
|
|
78
|
+
const delayMs = delays[attempt];
|
|
79
|
+
deps.onRetry?.({ attempt: attempt + 1, delayMs, reason: errMsg });
|
|
80
|
+
await doSleep(delayMs);
|
|
81
|
+
attempt++;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
export class ChatRunner {
|
|
85
|
+
cfg;
|
|
86
|
+
sessionManager;
|
|
87
|
+
tools;
|
|
88
|
+
extraTools;
|
|
89
|
+
/** Concatenated tool list passed to pi-ai (github + extra). */
|
|
90
|
+
mergedTools;
|
|
91
|
+
/**
|
|
92
|
+
* Resolved lazily on the first chat turn. A bad chat model spec
|
|
93
|
+
* (unknown id) MUST NOT crash the whole harness — webhooks, crons and
|
|
94
|
+
* workflows don't depend on it.
|
|
95
|
+
*/
|
|
96
|
+
model;
|
|
97
|
+
modelError;
|
|
98
|
+
chains = new Map();
|
|
99
|
+
constructor(cfg, sessionManager) {
|
|
100
|
+
this.cfg = cfg;
|
|
101
|
+
this.sessionManager = sessionManager;
|
|
102
|
+
if (cfg.github) {
|
|
103
|
+
this.tools = buildChatGitHubTools(cfg.github);
|
|
104
|
+
}
|
|
105
|
+
this.extraTools = cfg.extraTools;
|
|
106
|
+
const merged = [
|
|
107
|
+
...(this.tools?.tools ?? []),
|
|
108
|
+
...(this.extraTools?.tools ?? []),
|
|
109
|
+
];
|
|
110
|
+
this.mergedTools = merged.length > 0 ? merged : undefined;
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Dispatch a tool call to whichever toolset registered it. Github
|
|
114
|
+
* tools take precedence (they're registered first); fall back to the
|
|
115
|
+
* extra toolset for anything not in the github name set.
|
|
116
|
+
*/
|
|
117
|
+
async dispatchTool(call) {
|
|
118
|
+
if (this.tools?.tools.some((t) => t.name === call.name)) {
|
|
119
|
+
return this.tools.execute(call);
|
|
120
|
+
}
|
|
121
|
+
if (this.extraTools?.tools.some((t) => t.name === call.name)) {
|
|
122
|
+
return this.extraTools.execute(call);
|
|
123
|
+
}
|
|
124
|
+
return {
|
|
125
|
+
content: JSON.stringify({ error: `unknown tool: ${call.name}` }),
|
|
126
|
+
isError: true,
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
resolveModelLazy() {
|
|
130
|
+
if (this.model)
|
|
131
|
+
return this.model;
|
|
132
|
+
if (this.modelError)
|
|
133
|
+
return undefined;
|
|
134
|
+
try {
|
|
135
|
+
this.model = resolveModel(this.cfg.model);
|
|
136
|
+
return this.model;
|
|
137
|
+
}
|
|
138
|
+
catch (err) {
|
|
139
|
+
this.modelError = err instanceof Error ? err.message : String(err);
|
|
140
|
+
console.error(`[chat] ${this.modelError}`);
|
|
141
|
+
return undefined;
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* Run one chat turn. Each messagingSessionId maps to a stable pi-ai
|
|
146
|
+
* `agentSessionId` (a UUID we mint on first turn) which the dashboard
|
|
147
|
+
* uses to look up the JSONL on disk.
|
|
148
|
+
*/
|
|
149
|
+
async turn(messagingSessionId, prompt) {
|
|
150
|
+
const prev = this.chains.get(messagingSessionId) ?? Promise.resolve();
|
|
151
|
+
const next = prev
|
|
152
|
+
.catch(() => undefined)
|
|
153
|
+
.then(() => this.doTurn(messagingSessionId, prompt));
|
|
154
|
+
this.chains.set(messagingSessionId, next);
|
|
155
|
+
const cleanup = () => {
|
|
156
|
+
if (this.chains.get(messagingSessionId) === next) {
|
|
157
|
+
this.chains.delete(messagingSessionId);
|
|
158
|
+
}
|
|
159
|
+
};
|
|
160
|
+
next.then(cleanup, cleanup);
|
|
161
|
+
return next;
|
|
162
|
+
}
|
|
163
|
+
async doTurn(messagingSessionId, prompt) {
|
|
164
|
+
// Resolve (or mint) the stable agentSessionId pinned to this thread.
|
|
165
|
+
const session = this.sessionManager.getSession(messagingSessionId);
|
|
166
|
+
let agentSessionId = session?.agentSessionId || null;
|
|
167
|
+
if (!agentSessionId) {
|
|
168
|
+
agentSessionId = randomUUID();
|
|
169
|
+
this.sessionManager.setAgentSessionId(messagingSessionId, agentSessionId);
|
|
170
|
+
}
|
|
171
|
+
// Bail with a clear error if the chat model spec is unknown to pi-ai.
|
|
172
|
+
// Done here rather than in the constructor so a misconfigured chat
|
|
173
|
+
// model only fails chat turns, not the whole server.
|
|
174
|
+
const model = this.resolveModelLazy();
|
|
175
|
+
if (!model) {
|
|
176
|
+
return {
|
|
177
|
+
text: "",
|
|
178
|
+
agentSessionId,
|
|
179
|
+
tokens: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
|
|
180
|
+
costUsd: 0,
|
|
181
|
+
modelTurns: 0,
|
|
182
|
+
finish: "error",
|
|
183
|
+
errors: [this.modelError ?? "chat model not configured"],
|
|
184
|
+
assistantMessages: [],
|
|
185
|
+
toolResults: [],
|
|
186
|
+
modelId: this.cfg.model,
|
|
187
|
+
};
|
|
188
|
+
}
|
|
189
|
+
// Rehydrate conversation context from the DB. Messages were stored
|
|
190
|
+
// text-only on prior turns; we replay them as alternating user /
|
|
191
|
+
// assistant text messages. Tool calls/results inside a single turn
|
|
192
|
+
// never persist (they only live for that turn's loop) — that's a
|
|
193
|
+
// deliberate simplification: the agent gets a clean conversation
|
|
194
|
+
// history and can re-tool if asked again.
|
|
195
|
+
const history = this.sessionManager.getHistory(messagingSessionId, 50);
|
|
196
|
+
const messages = history.map((h) => textMessage(h.role, h.content, h.timestamp));
|
|
197
|
+
messages.push(textMessage("user", prompt, new Date().toISOString()));
|
|
198
|
+
const context = {
|
|
199
|
+
systemPrompt: this.cfg.systemPrompt,
|
|
200
|
+
messages,
|
|
201
|
+
tools: this.mergedTools,
|
|
202
|
+
};
|
|
203
|
+
const errors = [];
|
|
204
|
+
const assistantMessages = [];
|
|
205
|
+
const toolResults = [];
|
|
206
|
+
const opts = {
|
|
207
|
+
reasoning: pickReasoning(this.cfg.thinking),
|
|
208
|
+
timeoutMs: this.cfg.timeoutMs ?? 120_000,
|
|
209
|
+
};
|
|
210
|
+
let finish = "stop";
|
|
211
|
+
let tokensIn = 0;
|
|
212
|
+
let tokensOut = 0;
|
|
213
|
+
let cacheRead = 0;
|
|
214
|
+
let cacheWrite = 0;
|
|
215
|
+
let costUsd = 0;
|
|
216
|
+
let modelTurns = 0;
|
|
217
|
+
let finalText = "";
|
|
218
|
+
for (let round = 0; round < MAX_TOOL_ROUNDS + 1; round++) {
|
|
219
|
+
modelTurns++;
|
|
220
|
+
let assistant;
|
|
221
|
+
try {
|
|
222
|
+
assistant = await completeWithRetry(completeSimple, model, context, opts, {
|
|
223
|
+
onRetry: ({ attempt, delayMs, reason }) => console.warn(`[chat] transient model error (retry ${attempt}/${CHAT_RETRY_BACKOFF_MS.length} ` +
|
|
224
|
+
`in ${delayMs / 1000}s): ${reason}`),
|
|
225
|
+
});
|
|
226
|
+
}
|
|
227
|
+
catch (err) {
|
|
228
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
229
|
+
errors.push(msg);
|
|
230
|
+
finish = "error";
|
|
231
|
+
break;
|
|
232
|
+
}
|
|
233
|
+
assistantMessages.push(assistant);
|
|
234
|
+
context.messages.push(assistant);
|
|
235
|
+
tokensIn += assistant.usage.input;
|
|
236
|
+
tokensOut += assistant.usage.output;
|
|
237
|
+
cacheRead += assistant.usage.cacheRead;
|
|
238
|
+
cacheWrite += assistant.usage.cacheWrite;
|
|
239
|
+
costUsd += assistant.usage.cost.total;
|
|
240
|
+
if (assistant.stopReason === "error" || assistant.stopReason === "aborted") {
|
|
241
|
+
errors.push(assistant.errorMessage ?? assistant.stopReason);
|
|
242
|
+
finish = "error";
|
|
243
|
+
break;
|
|
244
|
+
}
|
|
245
|
+
// Pull text out (last text block wins — same convention as pi-ai's run() helper).
|
|
246
|
+
const text = assistant.content
|
|
247
|
+
.filter((c) => c.type === "text" && typeof c.text === "string")
|
|
248
|
+
.map((c) => c.text)
|
|
249
|
+
.join("");
|
|
250
|
+
if (text)
|
|
251
|
+
finalText = text;
|
|
252
|
+
// Tool calls? Execute and loop.
|
|
253
|
+
const toolCalls = assistant.content.filter((c) => c.type === "toolCall");
|
|
254
|
+
if (toolCalls.length === 0) {
|
|
255
|
+
finish = "stop";
|
|
256
|
+
break;
|
|
257
|
+
}
|
|
258
|
+
if (!this.mergedTools) {
|
|
259
|
+
// Model emitted a tool call without any tools registered — shouldn't
|
|
260
|
+
// happen, but bail out rather than loop forever.
|
|
261
|
+
errors.push("Model called a tool, but no tools are registered for chat.");
|
|
262
|
+
finish = "error";
|
|
263
|
+
break;
|
|
264
|
+
}
|
|
265
|
+
for (const call of toolCalls) {
|
|
266
|
+
const { content, isError } = await this.dispatchTool(call);
|
|
267
|
+
const tr = {
|
|
268
|
+
role: "toolResult",
|
|
269
|
+
toolCallId: call.id,
|
|
270
|
+
toolName: call.name,
|
|
271
|
+
content: [{ type: "text", text: content }],
|
|
272
|
+
isError,
|
|
273
|
+
timestamp: Date.now(),
|
|
274
|
+
};
|
|
275
|
+
toolResults.push(tr);
|
|
276
|
+
context.messages.push(tr);
|
|
277
|
+
if (isError)
|
|
278
|
+
errors.push(`${call.name}: ${content}`);
|
|
279
|
+
}
|
|
280
|
+
if (round === MAX_TOOL_ROUNDS) {
|
|
281
|
+
finish = "max-rounds";
|
|
282
|
+
errors.push(`Hit MAX_TOOL_ROUNDS (${MAX_TOOL_ROUNDS}); giving up on this turn.`);
|
|
283
|
+
break;
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
// Persist this turn's user + final assistant text. We do NOT persist
|
|
287
|
+
// tool calls or intermediate model responses — only the human-visible
|
|
288
|
+
// turn boundaries — to keep the rehydrated context compact.
|
|
289
|
+
this.sessionManager.addMessage(messagingSessionId, "user", prompt);
|
|
290
|
+
if (finalText) {
|
|
291
|
+
this.sessionManager.addMessage(messagingSessionId, "assistant", finalText);
|
|
292
|
+
}
|
|
293
|
+
this.sessionManager.touchSession(messagingSessionId);
|
|
294
|
+
return {
|
|
295
|
+
text: finalText,
|
|
296
|
+
agentSessionId,
|
|
297
|
+
tokens: {
|
|
298
|
+
input: tokensIn,
|
|
299
|
+
output: tokensOut,
|
|
300
|
+
cacheRead,
|
|
301
|
+
cacheWrite,
|
|
302
|
+
},
|
|
303
|
+
costUsd,
|
|
304
|
+
modelTurns,
|
|
305
|
+
finish,
|
|
306
|
+
errors,
|
|
307
|
+
assistantMessages,
|
|
308
|
+
toolResults,
|
|
309
|
+
modelId: this.cfg.model,
|
|
310
|
+
};
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
// ── Helpers ─────────────────────────────────────────────────────────
|
|
314
|
+
function resolveModel(spec) {
|
|
315
|
+
const idx = spec.indexOf("/");
|
|
316
|
+
if (idx < 0)
|
|
317
|
+
throw new Error(`model spec must be 'provider/id', got '${spec}'`);
|
|
318
|
+
const provider = spec.slice(0, idx);
|
|
319
|
+
const modelId = spec.slice(idx + 1);
|
|
320
|
+
// pi-ai's getModel is typed against its static registry; at runtime it
|
|
321
|
+
// accepts arbitrary strings AND returns undefined for unknown ids rather
|
|
322
|
+
// than throwing. Without this guard the first chat turn crashes deep in
|
|
323
|
+
// the provider stack with "Cannot read properties of undefined (reading
|
|
324
|
+
// 'api')" — surface a clear, actionable error instead.
|
|
325
|
+
const model = getModel(provider, modelId);
|
|
326
|
+
if (!model) {
|
|
327
|
+
throw new Error(`Unknown chat model '${spec}'. pi-ai's registry has no '${modelId}' for provider '${provider}'. ` +
|
|
328
|
+
`Set LASTLIGHT_MODELS (or LASTLIGHT_MODEL) to a registered model id.`);
|
|
329
|
+
}
|
|
330
|
+
return model;
|
|
331
|
+
}
|
|
332
|
+
function textMessage(role, content, timestamp) {
|
|
333
|
+
const ts = parseTimestamp(timestamp);
|
|
334
|
+
if (role === "user") {
|
|
335
|
+
const m = { role: "user", content, timestamp: ts };
|
|
336
|
+
return m;
|
|
337
|
+
}
|
|
338
|
+
// Treat any non-user historical role as assistant text.
|
|
339
|
+
const m = {
|
|
340
|
+
role: "assistant",
|
|
341
|
+
content: [{ type: "text", text: content }],
|
|
342
|
+
api: "openai-completions",
|
|
343
|
+
provider: "history",
|
|
344
|
+
model: "history",
|
|
345
|
+
usage: zeroUsage(),
|
|
346
|
+
stopReason: "stop",
|
|
347
|
+
timestamp: ts,
|
|
348
|
+
};
|
|
349
|
+
return m;
|
|
350
|
+
}
|
|
351
|
+
function parseTimestamp(raw) {
|
|
352
|
+
const ms = Date.parse(raw);
|
|
353
|
+
return Number.isFinite(ms) ? ms : Date.now();
|
|
354
|
+
}
|
|
355
|
+
function zeroUsage() {
|
|
356
|
+
return {
|
|
357
|
+
input: 0,
|
|
358
|
+
output: 0,
|
|
359
|
+
cacheRead: 0,
|
|
360
|
+
cacheWrite: 0,
|
|
361
|
+
totalTokens: 0,
|
|
362
|
+
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 },
|
|
363
|
+
};
|
|
364
|
+
}
|
|
365
|
+
function pickReasoning(level) {
|
|
366
|
+
// pi-ai's SimpleStreamOptions.reasoning excludes "off" — pi-ai default
|
|
367
|
+
// is no reasoning, so we pass undefined for "off".
|
|
368
|
+
if (!level || level === "off")
|
|
369
|
+
return undefined;
|
|
370
|
+
return level;
|
|
371
|
+
}
|
|
372
|
+
/**
|
|
373
|
+
* Octokit is bundled here only because github-tools.ts imports it at module
|
|
374
|
+
* load. Re-export so callers can probe whether the integration is wired
|
|
375
|
+
* without round-tripping through that file. Typed as `unknown` to avoid
|
|
376
|
+
* dragging the Octokit type chain into the published .d.ts.
|
|
377
|
+
*/
|
|
378
|
+
export const __octokitForTest = Octokit;
|
|
379
|
+
//# sourceMappingURL=chat-runner.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chat-runner.js","sourceRoot":"","sources":["../../src/engine/chat-runner.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import { describe, it, expect, vi } from "vitest";
|
|
2
|
+
import { completeWithRetry, isRetryableModelError } from "./chat-runner.js";
|
|
3
|
+
// Minimal stand-ins — the helper only ever forwards these to `complete`.
|
|
4
|
+
const model = {};
|
|
5
|
+
const context = { messages: [] };
|
|
6
|
+
const opts = {};
|
|
7
|
+
function ok(text = "hi") {
|
|
8
|
+
return {
|
|
9
|
+
role: "assistant",
|
|
10
|
+
content: [{ type: "text", text }],
|
|
11
|
+
stopReason: "stop",
|
|
12
|
+
usage: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, cost: { total: 0 } },
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
function erroredAssistant(message) {
|
|
16
|
+
return {
|
|
17
|
+
role: "assistant",
|
|
18
|
+
content: [],
|
|
19
|
+
stopReason: "error",
|
|
20
|
+
errorMessage: message,
|
|
21
|
+
usage: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, cost: { total: 0 } },
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
const noSleep = () => Promise.resolve();
|
|
25
|
+
const delays = [10, 20, 30];
|
|
26
|
+
describe("isRetryableModelError", () => {
|
|
27
|
+
it("matches rate limits and transient server/network errors", () => {
|
|
28
|
+
for (const m of [
|
|
29
|
+
'429 {"error":{"code":"RATE_LIMIT_EXCEEDED"}}',
|
|
30
|
+
"You have exceeded your rate limit for this API",
|
|
31
|
+
"Error: overloaded_error",
|
|
32
|
+
"503 Service Unavailable",
|
|
33
|
+
"502 Bad Gateway",
|
|
34
|
+
"fetch failed",
|
|
35
|
+
"ETIMEDOUT",
|
|
36
|
+
]) {
|
|
37
|
+
expect(isRetryableModelError(m)).toBe(true);
|
|
38
|
+
}
|
|
39
|
+
});
|
|
40
|
+
it("does NOT match auth / validation / overflow (non-transient)", () => {
|
|
41
|
+
for (const m of [
|
|
42
|
+
"401 Unauthorized",
|
|
43
|
+
"403 Resource not accessible by integration",
|
|
44
|
+
"400 invalid_request_error",
|
|
45
|
+
"context length exceeded",
|
|
46
|
+
"Unknown chat model",
|
|
47
|
+
]) {
|
|
48
|
+
expect(isRetryableModelError(m)).toBe(false);
|
|
49
|
+
}
|
|
50
|
+
});
|
|
51
|
+
});
|
|
52
|
+
describe("completeWithRetry", () => {
|
|
53
|
+
it("returns immediately on success (no retries)", async () => {
|
|
54
|
+
const complete = vi.fn().mockResolvedValue(ok());
|
|
55
|
+
const onRetry = vi.fn();
|
|
56
|
+
const res = await completeWithRetry(complete, model, context, opts, { delaysMs: delays, sleepFn: noSleep, onRetry });
|
|
57
|
+
expect(res.stopReason).toBe("stop");
|
|
58
|
+
expect(complete).toHaveBeenCalledTimes(1);
|
|
59
|
+
expect(onRetry).not.toHaveBeenCalled();
|
|
60
|
+
});
|
|
61
|
+
it("retries a thrown 429 then succeeds, backing off per the schedule", async () => {
|
|
62
|
+
const complete = vi
|
|
63
|
+
.fn()
|
|
64
|
+
.mockRejectedValueOnce(new Error('429 {"code":"RATE_LIMIT_EXCEEDED"}'))
|
|
65
|
+
.mockResolvedValueOnce(ok("recovered"));
|
|
66
|
+
const slept = [];
|
|
67
|
+
const sleepFn = (ms) => { slept.push(ms); return Promise.resolve(); };
|
|
68
|
+
const res = await completeWithRetry(complete, model, context, opts, { delaysMs: delays, sleepFn });
|
|
69
|
+
expect(res.stopReason).toBe("stop");
|
|
70
|
+
expect(complete).toHaveBeenCalledTimes(2);
|
|
71
|
+
expect(slept).toEqual([10]); // first backoff only
|
|
72
|
+
});
|
|
73
|
+
it("retries an errored-assistant 429 (non-throw shape)", async () => {
|
|
74
|
+
const complete = vi
|
|
75
|
+
.fn()
|
|
76
|
+
.mockResolvedValueOnce(erroredAssistant("rate limit exceeded"))
|
|
77
|
+
.mockResolvedValueOnce(ok());
|
|
78
|
+
const res = await completeWithRetry(complete, model, context, opts, { delaysMs: delays, sleepFn: noSleep });
|
|
79
|
+
expect(res.stopReason).toBe("stop");
|
|
80
|
+
expect(complete).toHaveBeenCalledTimes(2);
|
|
81
|
+
});
|
|
82
|
+
it("does NOT retry a non-retryable thrown error", async () => {
|
|
83
|
+
const complete = vi.fn().mockRejectedValue(new Error("401 Unauthorized"));
|
|
84
|
+
await expect(completeWithRetry(complete, model, context, opts, { delaysMs: delays, sleepFn: noSleep })).rejects.toThrow("401");
|
|
85
|
+
expect(complete).toHaveBeenCalledTimes(1);
|
|
86
|
+
});
|
|
87
|
+
it("gives up after exhausting the backoff schedule and rethrows the last error", async () => {
|
|
88
|
+
const complete = vi.fn().mockRejectedValue(new Error("429 rate limit"));
|
|
89
|
+
const slept = [];
|
|
90
|
+
await expect(completeWithRetry(complete, model, context, opts, {
|
|
91
|
+
delaysMs: delays,
|
|
92
|
+
sleepFn: (ms) => { slept.push(ms); return Promise.resolve(); },
|
|
93
|
+
})).rejects.toThrow("429");
|
|
94
|
+
expect(complete).toHaveBeenCalledTimes(delays.length + 1); // initial + 3 retries
|
|
95
|
+
expect(slept).toEqual(delays);
|
|
96
|
+
});
|
|
97
|
+
it("returns the errored assistant unchanged when retries are exhausted (non-throw shape)", async () => {
|
|
98
|
+
const complete = vi.fn().mockResolvedValue(erroredAssistant("429 rate limit"));
|
|
99
|
+
const res = await completeWithRetry(complete, model, context, opts, { delaysMs: [5], sleepFn: noSleep });
|
|
100
|
+
expect(res.stopReason).toBe("error");
|
|
101
|
+
expect(complete).toHaveBeenCalledTimes(2); // initial + 1 retry, then surfaces the errored assistant
|
|
102
|
+
});
|
|
103
|
+
});
|
|
104
|
+
//# sourceMappingURL=chat-runner.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chat-runner.test.js","sourceRoot":"","sources":["../../src/engine/chat-runner.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import type { Tool, ToolCall } from "@earendil-works/pi-ai";
|
|
2
|
+
/**
|
|
3
|
+
* Minimal subset of pi-coding-agent's `Skill` shape — only the fields
|
|
4
|
+
* the chat catalogue + read tool actually use.
|
|
5
|
+
*/
|
|
6
|
+
export interface ChatSkill {
|
|
7
|
+
name: string;
|
|
8
|
+
description: string;
|
|
9
|
+
filePath: string;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Skills exposed to chat threads. `chat` is the always-on persona;
|
|
13
|
+
* the others let chat assist with one-off lookups that map to these
|
|
14
|
+
* domains without delegating to a full workflow run.
|
|
15
|
+
*/
|
|
16
|
+
export declare const CHAT_SKILL_NAMES: readonly ["chat", "issue-triage", "pr-review", "repo-health"];
|
|
17
|
+
export interface ChatSkillCatalogue {
|
|
18
|
+
/** Skills the chat agent can read on demand, keyed by name. */
|
|
19
|
+
skills: ChatSkill[];
|
|
20
|
+
/**
|
|
21
|
+
* XML block describing each skill (name + description) suitable for
|
|
22
|
+
* prepending to the chat system prompt. Empty string if no skills
|
|
23
|
+
* resolved cleanly.
|
|
24
|
+
*/
|
|
25
|
+
catalogueXml: string;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Load the curated chat skill catalogue from `<repo>/skills/`.
|
|
29
|
+
* Skills missing `name` or `description` frontmatter are silently
|
|
30
|
+
* dropped, matching pi-coding-agent's behaviour on the sandbox path.
|
|
31
|
+
*/
|
|
32
|
+
export declare function loadChatSkillCatalogue(): ChatSkillCatalogue;
|
|
33
|
+
/**
|
|
34
|
+
* Build the `read_skill` tool that chat uses to pull a SKILL.md on
|
|
35
|
+
* demand. Returns the pi-ai `Tool` definition plus a name-keyed
|
|
36
|
+
* dispatcher the chat-runner's toolset can merge into its `execute`.
|
|
37
|
+
*/
|
|
38
|
+
export interface ReadSkillToolset {
|
|
39
|
+
tool: Tool;
|
|
40
|
+
execute(call: ToolCall): {
|
|
41
|
+
content: string;
|
|
42
|
+
isError: boolean;
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
export declare function buildReadSkillTool(skills: ChatSkill[]): ReadSkillToolset;
|