@cursor/bdk 0.2.9 → 0.2.11
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/dist/artifacts.js +3 -5
- package/dist/bin/agent-serve.js +803 -812
- package/dist/channels/bitbucket/api.js +305 -321
- package/dist/channels/bitbucket/binding.js +97 -61
- package/dist/channels/bitbucket/bitbucket-channel.d.ts +15 -1
- package/dist/channels/bitbucket/bitbucket-channel.d.ts.map +1 -1
- package/dist/channels/bitbucket/bitbucket-channel.js +95 -42
- package/dist/channels/bitbucket/bitbucket-webhook.d.ts +11 -0
- package/dist/channels/bitbucket/bitbucket-webhook.d.ts.map +1 -1
- package/dist/channels/bitbucket/bitbucket-webhook.js +214 -204
- package/dist/channels/bitbucket/checks.js +9 -21
- package/dist/channels/bitbucket/cursor-account.js +1 -1
- package/dist/channels/bitbucket/defaults.js +14 -4
- package/dist/channels/bitbucket/events.js +1 -2
- package/dist/channels/bitbucket/index.d.ts +6 -2
- package/dist/channels/bitbucket/index.d.ts.map +1 -1
- package/dist/channels/bitbucket/index.js +6 -2
- package/dist/channels/bitbucket/replay.js +80 -56
- package/dist/channels/bitbucket/state.js +16 -7
- package/dist/channels/bitbucket/types.d.ts +11 -2
- package/dist/channels/bitbucket/types.d.ts.map +1 -1
- package/dist/channels/checks.js +18 -28
- package/dist/channels/deployments/deployments-channel.js +26 -34
- package/dist/channels/github/api.js +216 -210
- package/dist/channels/github/auth.d.ts +5 -1
- package/dist/channels/github/auth.d.ts.map +1 -1
- package/dist/channels/github/auth.js +157 -174
- package/dist/channels/github/binding.js +48 -39
- package/dist/channels/github/checks.js +9 -14
- package/dist/channels/github/cursor-account.js +6 -11
- package/dist/channels/github/defaults.js +105 -130
- package/dist/channels/github/forward.js +13 -17
- package/dist/channels/github/github-channel.d.ts +43 -2
- package/dist/channels/github/github-channel.d.ts.map +1 -1
- package/dist/channels/github/github-channel.js +1228 -958
- package/dist/channels/github/progress.js +145 -146
- package/dist/channels/github/replay.js +30 -39
- package/dist/channels/github/state.js +40 -16
- package/dist/channels/github/types.d.ts +30 -6
- package/dist/channels/github/types.d.ts.map +1 -1
- package/dist/channels/gitlab/api.js +100 -114
- package/dist/channels/gitlab/binding.js +52 -33
- package/dist/channels/gitlab/checks.js +28 -29
- package/dist/channels/gitlab/cursor-account.js +1 -1
- package/dist/channels/gitlab/defaults.js +9 -3
- package/dist/channels/gitlab/gitlab-channel.d.ts +16 -1
- package/dist/channels/gitlab/gitlab-channel.d.ts.map +1 -1
- package/dist/channels/gitlab/gitlab-channel.js +95 -42
- package/dist/channels/gitlab/gitlab-webhook.d.ts +10 -1
- package/dist/channels/gitlab/gitlab-webhook.d.ts.map +1 -1
- package/dist/channels/gitlab/gitlab-webhook.js +282 -249
- package/dist/channels/gitlab/index.d.ts +6 -2
- package/dist/channels/gitlab/index.d.ts.map +1 -1
- package/dist/channels/gitlab/index.js +6 -2
- package/dist/channels/gitlab/replay.js +50 -27
- package/dist/channels/gitlab/state.js +14 -6
- package/dist/channels/gitlab/types.d.ts +13 -2
- package/dist/channels/gitlab/types.d.ts.map +1 -1
- package/dist/channels/origin/api.js +100 -116
- package/dist/channels/origin/binding.js +15 -16
- package/dist/channels/origin/checks.js +30 -28
- package/dist/channels/origin/defaults.js +50 -65
- package/dist/channels/origin/origin-channel.js +266 -272
- package/dist/channels/origin/origin-webhook.js +70 -88
- package/dist/channels/origin/reactions.js +9 -21
- package/dist/channels/origin/state.js +13 -5
- package/dist/channels/slack/agentic-delivery.js +426 -478
- package/dist/channels/slack/agentic-posted.js +9 -10
- package/dist/channels/slack/agentic-signals.js +2 -3
- package/dist/channels/slack/api.js +417 -427
- package/dist/channels/slack/approvals.js +1 -1
- package/dist/channels/slack/assistant.js +37 -47
- package/dist/channels/slack/attachments.js +188 -206
- package/dist/channels/slack/auth.js +8 -6
- package/dist/channels/slack/bot-mentions.js +31 -45
- package/dist/channels/slack/channel-watch.js +42 -48
- package/dist/channels/slack/cli-project.js +112 -137
- package/dist/channels/slack/code-fences.js +3 -5
- package/dist/channels/slack/constants.js +2 -2
- package/dist/channels/slack/credentials.js +23 -38
- package/dist/channels/slack/defaults.js +292 -331
- package/dist/channels/slack/dispatch.d.ts.map +1 -1
- package/dist/channels/slack/dispatch.js +533 -460
- package/dist/channels/slack/doctor.js +200 -214
- package/dist/channels/slack/eval-directive.js +79 -96
- package/dist/channels/slack/event-id-dedupe.js +1 -1
- package/dist/channels/slack/external-policy.js +26 -39
- package/dist/channels/slack/footer.js +28 -41
- package/dist/channels/slack/inbound.d.ts +1 -0
- package/dist/channels/slack/inbound.d.ts.map +1 -1
- package/dist/channels/slack/inbound.js +50 -31
- package/dist/channels/slack/init.d.ts +1 -5
- package/dist/channels/slack/init.d.ts.map +1 -1
- package/dist/channels/slack/init.js +42 -59
- package/dist/channels/slack/interactive.d.ts +9 -3
- package/dist/channels/slack/interactive.d.ts.map +1 -1
- package/dist/channels/slack/interactive.js +160 -162
- package/dist/channels/slack/links.js +1 -2
- package/dist/channels/slack/live-delivery.js +172 -190
- package/dist/channels/slack/manifest.d.ts.map +1 -1
- package/dist/channels/slack/manifest.js +44 -23
- package/dist/channels/slack/message-body.js +2 -2
- package/dist/channels/slack/nudge-carrier.js +30 -42
- package/dist/channels/slack/nudge-store.js +164 -191
- package/dist/channels/slack/paint-start.js +66 -81
- package/dist/channels/slack/placeholder.js +123 -152
- package/dist/channels/slack/pr-ref.js +1 -1
- package/dist/channels/slack/progress-delivery.js +65 -78
- package/dist/channels/slack/reasoning-card.js +36 -49
- package/dist/channels/slack/recording-sink.js +12 -24
- package/dist/channels/slack/reply-options.js +7 -12
- package/dist/channels/slack/self-identity.js +27 -35
- package/dist/channels/slack/sender-name.d.ts +12 -3
- package/dist/channels/slack/sender-name.d.ts.map +1 -1
- package/dist/channels/slack/sender-name.js +57 -61
- package/dist/channels/slack/setup.js +2 -4
- package/dist/channels/slack/slack-channel.d.ts +6 -4
- package/dist/channels/slack/slack-channel.d.ts.map +1 -1
- package/dist/channels/slack/slack-channel.js +441 -308
- package/dist/channels/slack/socket-mode.js +38 -52
- package/dist/channels/slack/thread-context.js +143 -160
- package/dist/channels/slack/tool-approval-events.js +149 -166
- package/dist/channels/slack/tool-cards.js +6 -11
- package/dist/channels/slack/tool-chip.js +1 -2
- package/dist/channels/slack/types.d.ts +15 -17
- package/dist/channels/slack/types.d.ts.map +1 -1
- package/dist/channels/slack/upload.js +84 -97
- package/dist/channels/slack/user-info.js +27 -41
- package/dist/channels.js +9 -20
- package/dist/dashboard-session-url.js +3 -4
- package/dist/docs/404.html +2 -2
- package/dist/docs/assets/{app.BNhEdGa8.js → app.DXI7bwox.js} +4 -4
- package/dist/docs/assets/{building-with-agents.md.BPjPFxFg.js → building-with-agents.md.Df87rAe1.js} +1 -1
- package/dist/docs/assets/chunks/@localSearchIndexroot.CtLtpWcx.js +1 -0
- package/dist/docs/assets/chunks/{VPLocalSearchBox.DIdUV1Ph.js → VPLocalSearchBox.BrbO5mEe.js} +1 -1
- package/dist/docs/assets/chunks/{arc.lELI4_SR.js → arc.BOG1yms8.js} +1 -1
- package/dist/docs/assets/chunks/{architectureDiagram-Q4EWVU46.iCMdvuoM.js → architectureDiagram-Q4EWVU46.C0hsMZnZ.js} +1 -1
- package/dist/docs/assets/chunks/{baseUniq.C1-nDJBf.js → baseUniq.H044KjKs.js} +1 -1
- package/dist/docs/assets/chunks/{blockDiagram-DXYQGD6D.ClemzBox.js → blockDiagram-DXYQGD6D.BsRW6GoB.js} +1 -1
- package/dist/docs/assets/chunks/{c4Diagram-AHTNJAMY.BqTak6cR.js → c4Diagram-AHTNJAMY.B9HV5PFR.js} +1 -1
- package/dist/docs/assets/chunks/channel.CBwrU9rP.js +1 -0
- package/dist/docs/assets/chunks/{chunk-4BX2VUAB.CUS3qs_R.js → chunk-4BX2VUAB.CPoT_ajl.js} +1 -1
- package/dist/docs/assets/chunks/{chunk-4TB4RGXK.dz5fdHcl.js → chunk-4TB4RGXK.DZBwWuCL.js} +1 -1
- package/dist/docs/assets/chunks/{chunk-55IACEB6.D6BEBmve.js → chunk-55IACEB6.CZ3yTiyq.js} +1 -1
- package/dist/docs/assets/chunks/{chunk-EDXVE4YY.B5uK4ID9.js → chunk-EDXVE4YY.6DfvHSd8.js} +1 -1
- package/dist/docs/assets/chunks/{chunk-FMBD7UC4.PgOJgNQs.js → chunk-FMBD7UC4.CpBj8HfK.js} +1 -1
- package/dist/docs/assets/chunks/{chunk-OYMX7WX6.CvkTrCii.js → chunk-OYMX7WX6.BdKo8YqS.js} +1 -1
- package/dist/docs/assets/chunks/{chunk-QZHKN3VN.BnSfKYsB.js → chunk-QZHKN3VN.BnXNyxJx.js} +1 -1
- package/dist/docs/assets/chunks/{chunk-YZCP3GAM.MZH6v5UC.js → chunk-YZCP3GAM.Cg1OcF8G.js} +1 -1
- package/dist/docs/assets/chunks/classDiagram-6PBFFD2Q.CbC_mrvB.js +1 -0
- package/dist/docs/assets/chunks/classDiagram-v2-HSJHXN6E.CbC_mrvB.js +1 -0
- package/dist/docs/assets/chunks/clone.BTvFyY1a.js +1 -0
- package/dist/docs/assets/chunks/{cose-bilkent-S5V4N54A.BBbw_YZi.js → cose-bilkent-S5V4N54A.1SP8al9c.js} +1 -1
- package/dist/docs/assets/chunks/{dagre-KV5264BT.CNJB2l7E.js → dagre-KV5264BT.DS1L6hJt.js} +1 -1
- package/dist/docs/assets/chunks/{diagram-5BDNPKRD.BQzlnFfq.js → diagram-5BDNPKRD.ChsausbG.js} +1 -1
- package/dist/docs/assets/chunks/{diagram-G4DWMVQ6.DkgqqZMz.js → diagram-G4DWMVQ6.3XsptNWj.js} +1 -1
- package/dist/docs/assets/chunks/{diagram-MMDJMWI5.DIT8L7H_.js → diagram-MMDJMWI5.DPA9Dk_P.js} +1 -1
- package/dist/docs/assets/chunks/{diagram-TYMM5635.3xLPZWGJ.js → diagram-TYMM5635.BVswXWrB.js} +1 -1
- package/dist/docs/assets/chunks/{erDiagram-SMLLAGMA.5_IHz8jF.js → erDiagram-SMLLAGMA.BSak5OSP.js} +1 -1
- package/dist/docs/assets/chunks/{flowDiagram-DWJPFMVM.BGUCXz8A.js → flowDiagram-DWJPFMVM.CQgN4TTz.js} +1 -1
- package/dist/docs/assets/chunks/{ganttDiagram-T4ZO3ILL.DbfFavS1.js → ganttDiagram-T4ZO3ILL.GrT0kA4a.js} +1 -1
- package/dist/docs/assets/chunks/{gitGraphDiagram-UUTBAWPF.D2yKdeNW.js → gitGraphDiagram-UUTBAWPF.CdS7Ucll.js} +1 -1
- package/dist/docs/assets/chunks/{graph.CSCxwHba.js → graph.BVqKRmRo.js} +1 -1
- package/dist/docs/assets/chunks/{infoDiagram-42DDH7IO.FDeb6xHY.js → infoDiagram-42DDH7IO.C3C9FRto.js} +1 -1
- package/dist/docs/assets/chunks/{ishikawaDiagram-UXIWVN3A.DbeYs9VL.js → ishikawaDiagram-UXIWVN3A.2FuAh_Zj.js} +1 -1
- package/dist/docs/assets/chunks/{journeyDiagram-VCZTEJTY.CWjKINpx.js → journeyDiagram-VCZTEJTY.CaHMfK4b.js} +1 -1
- package/dist/docs/assets/chunks/{kanban-definition-6JOO6SKY.B4FrAlwz.js → kanban-definition-6JOO6SKY.CjhIUwcA.js} +1 -1
- package/dist/docs/assets/chunks/{layout.DFGxQ9ab.js → layout.CGU3gfSf.js} +1 -1
- package/dist/docs/assets/chunks/{linear.BmjZ-G59.js → linear.DaihpW_n.js} +1 -1
- package/dist/docs/assets/chunks/{min.DZSxulMW.js → min.BS-j8kHQ.js} +1 -1
- package/dist/docs/assets/chunks/{mindmap-definition-QFDTVHPH.CHLi3-aN.js → mindmap-definition-QFDTVHPH.BVJ1Bbnk.js} +1 -1
- package/dist/docs/assets/chunks/{pieDiagram-DEJITSTG.DteG-CkU.js → pieDiagram-DEJITSTG.Cz1WIv9r.js} +1 -1
- package/dist/docs/assets/chunks/{quadrantDiagram-34T5L4WZ.D458ipN3.js → quadrantDiagram-34T5L4WZ.DKLFxcjy.js} +1 -1
- package/dist/docs/assets/chunks/{requirementDiagram-MS252O5E.DcFgUxst.js → requirementDiagram-MS252O5E.BHegiK7x.js} +1 -1
- package/dist/docs/assets/chunks/{sankeyDiagram-XADWPNL6.BwQAMmSA.js → sankeyDiagram-XADWPNL6.DYkY6yPc.js} +1 -1
- package/dist/docs/assets/chunks/{sequenceDiagram-FGHM5R23.B_Xdsrh9.js → sequenceDiagram-FGHM5R23.DYQ1QUrI.js} +1 -1
- package/dist/docs/assets/chunks/{stateDiagram-FHFEXIEX.CdfDW6-C.js → stateDiagram-FHFEXIEX.Iru8BsFo.js} +1 -1
- package/dist/docs/assets/chunks/stateDiagram-v2-QKLJ7IA2.BYXl4LW6.js +1 -0
- package/dist/docs/assets/chunks/{theme.sfdL3srp.js → theme.DaplWQhQ.js} +2 -2
- package/dist/docs/assets/chunks/{timeline-definition-GMOUNBTQ.56-4hXaC.js → timeline-definition-GMOUNBTQ.BwFA8hiX.js} +1 -1
- package/dist/docs/assets/chunks/{vennDiagram-DHZGUBPP.CvZSQBO7.js → vennDiagram-DHZGUBPP.CZ60W1C_.js} +1 -1
- package/dist/docs/assets/chunks/{wardley-RL74JXVD.C9qc8k39.js → wardley-RL74JXVD.iXazD3Z7.js} +1 -1
- package/dist/docs/assets/chunks/{wardleyDiagram-NUSXRM2D.D9s0nihi.js → wardleyDiagram-NUSXRM2D.B69D2r8-.js} +1 -1
- package/dist/docs/assets/chunks/{xychartDiagram-5P7HB3ND.BVJSpYrC.js → xychartDiagram-5P7HB3ND.CLPZEIU9.js} +1 -1
- package/dist/docs/assets/{deployment.md.BdqTiGdc.js → deployment.md.BYuEcDBv.js} +2 -2
- package/dist/docs/assets/{guides_bitbucket.md.BB6fqD-M.js → guides_bitbucket.md.CKUayYtD.js} +3 -3
- package/dist/docs/assets/{guides_bitbucket.md.BB6fqD-M.lean.js → guides_bitbucket.md.CKUayYtD.lean.js} +1 -1
- package/dist/docs/assets/{guides_github.md.Cr1Xlf-m.js → guides_github.md.TuNiZAOQ.js} +4 -4
- package/dist/docs/assets/{guides_github.md.Cr1Xlf-m.lean.js → guides_github.md.TuNiZAOQ.lean.js} +1 -1
- package/dist/docs/assets/{guides_gitlab.md.CMpmFi4M.js → guides_gitlab.md.CtNI4fSH.js} +4 -4
- package/dist/docs/assets/{guides_gitlab.md.CMpmFi4M.lean.js → guides_gitlab.md.CtNI4fSH.lean.js} +1 -1
- package/dist/docs/assets/guides_migrate.md.sCAvvlC6.js +7 -0
- package/dist/docs/assets/guides_migrate.md.sCAvvlC6.lean.js +1 -0
- package/dist/docs/assets/{reference_cli.md.GwugN3n-.js → reference_cli.md.dYCAL2lB.js} +4 -3
- package/dist/docs/assets/reference_cli.md.dYCAL2lB.lean.js +1 -0
- package/dist/docs/assets/troubleshooting.md.x-GBa7wN.js +1 -0
- package/dist/docs/assets/{troubleshooting.md.Bscj6ODe.lean.js → troubleshooting.md.x-GBa7wN.lean.js} +1 -1
- package/dist/docs/building-with-agents.html +37 -37
- package/dist/docs/building-with-agents.md +2 -0
- package/dist/docs/deployment.html +38 -38
- package/dist/docs/deployment.md +7 -0
- package/dist/docs/evals.html +36 -36
- package/dist/docs/guides/agent-to-agent.html +35 -35
- package/dist/docs/guides/bitbucket.html +38 -38
- package/dist/docs/guides/bitbucket.md +9 -1
- package/dist/docs/guides/cloud-agents.html +35 -35
- package/dist/docs/guides/convert-automation.html +35 -35
- package/dist/docs/guides/github.html +39 -39
- package/dist/docs/guides/github.md +20 -4
- package/dist/docs/guides/gitlab.html +38 -38
- package/dist/docs/guides/gitlab.md +9 -1
- package/dist/docs/guides/grokbot-agents.html +35 -35
- package/dist/docs/guides/hooks.html +35 -35
- package/dist/docs/guides/improve.html +35 -35
- package/dist/docs/guides/jev.html +35 -35
- package/dist/docs/guides/mcp-oauth.html +35 -35
- package/dist/docs/guides/migrate.html +66 -0
- package/dist/docs/guides/migrate.md +122 -0
- package/dist/docs/guides/opentelemetry.html +35 -35
- package/dist/docs/guides/slack.html +35 -35
- package/dist/docs/guides/webhooks.html +35 -35
- package/dist/docs/hashmap.json +1 -1
- package/dist/docs/hillclimbing.html +35 -35
- package/dist/docs/index.html +35 -35
- package/dist/docs/llms-full.txt +214 -6
- package/dist/docs/llms.txt +1 -0
- package/dist/docs/quickstart.html +35 -35
- package/dist/docs/reference/agent-config.html +35 -35
- package/dist/docs/reference/artifacts.html +35 -35
- package/dist/docs/reference/channels.html +35 -35
- package/dist/docs/reference/cli.html +39 -38
- package/dist/docs/reference/cli.md +39 -0
- package/dist/docs/reference/connections.html +35 -35
- package/dist/docs/reference/evals.html +35 -35
- package/dist/docs/reference/extensions.html +35 -35
- package/dist/docs/reference/hooks.html +35 -35
- package/dist/docs/reference/http-api.html +35 -35
- package/dist/docs/reference/instructions.html +35 -35
- package/dist/docs/reference/playground.html +35 -35
- package/dist/docs/reference/project-layout.html +35 -35
- package/dist/docs/reference/prompt.html +35 -35
- package/dist/docs/reference/schedules.html +35 -35
- package/dist/docs/reference/sessions.html +35 -35
- package/dist/docs/reference/skills.html +35 -35
- package/dist/docs/reference/subagents.html +35 -35
- package/dist/docs/reference/tools.html +35 -35
- package/dist/docs/templates/agentic-owners.html +35 -35
- package/dist/docs/templates/grokbot-agents.html +35 -35
- package/dist/docs/templates/security-reviewer.html +35 -35
- package/dist/docs/templates/thermo-quality-review.html +35 -35
- package/dist/docs/templates/thermo-review.html +35 -35
- package/dist/docs/templates/triage.html +35 -35
- package/dist/docs/troubleshooting.html +36 -36
- package/dist/docs/troubleshooting.md +1 -0
- package/dist/evals/assertions.js +20 -34
- package/dist/evals/expect.js +3 -6
- package/dist/evals/judge.js +5 -8
- package/dist/evals/loaders.js +45 -62
- package/dist/evals/matchers.js +2 -3
- package/dist/evals/reporters.js +43 -67
- package/dist/evals/results.js +1 -1
- package/dist/evals/run-facts.js +5 -6
- package/dist/evals.js +27 -15
- package/dist/extensions/cursor-cloud-agents/extension.js +4 -1
- package/dist/extensions/cursor-cloud-agents/lib/backend.js +100 -126
- package/dist/extensions/cursor-cloud-agents/lib/fleet.js +22 -38
- package/dist/extensions/cursor-cloud-agents/lib/repos.js +8 -10
- package/dist/extensions/cursor-cloud-agents/lib/transcript.js +2 -3
- package/dist/extensions/cursor-cloud-agents/lib/watch.js +52 -66
- package/dist/extensions/cursor-cloud-agents/reminders/cloud-agent-stop-watch.js +29 -40
- package/dist/extensions/cursor-cloud-agents/tools/cancel.js +6 -17
- package/dist/extensions/cursor-cloud-agents/tools/dump.js +25 -36
- package/dist/extensions/cursor-cloud-agents/tools/get.js +3 -14
- package/dist/extensions/cursor-cloud-agents/tools/launch.js +13 -21
- package/dist/extensions/cursor-cloud-agents/tools/list.js +8 -19
- package/dist/extensions/cursor-cloud-agents/tools/reply.js +5 -16
- package/dist/extensions/cursor-grokbot-agents/extension.js +4 -1
- package/dist/extensions/cursor-grokbot-agents/lib/agents.js +3 -3
- package/dist/extensions/cursor-grokbot-agents/lib/backend.js +53 -73
- package/dist/extensions/cursor-grokbot-agents/lib/contacts.js +10 -23
- package/dist/extensions/cursor-grokbot-agents/lib/conversation.js +112 -132
- package/dist/extensions/cursor-grokbot-agents/lib/lock.js +1 -2
- package/dist/extensions/cursor-grokbot-agents/tools/ask.js +5 -16
- package/dist/extensions/cursor-grokbot-agents/tools/check.js +4 -15
- package/dist/extensions/cursor-grokbot-agents/tools/interrupt.js +2 -13
- package/dist/extensions/cursor-grokbot-agents/tools/list.js +11 -23
- package/dist/extensions/jev/extension.js +3 -3
- package/dist/extensions/jev/lib/evaluate.js +43 -60
- package/dist/extensions/jev/tools/evaluate.js +6 -17
- package/dist/extensions/slack-communication/tools/post-file.js +1 -1
- package/dist/extensions.js +3 -5
- package/dist/files-backends/cursor-hosted.js +504 -523
- package/dist/files-backends/local-fs.js +72 -134
- package/dist/files.js +3 -3
- package/dist/filesystem.js +562 -861
- package/dist/index.js +16 -35
- package/dist/internal/advertise-tools.js +74 -86
- package/dist/internal/artifacts-store.js +298 -361
- package/dist/internal/as-of.js +2 -4
- package/dist/internal/authored-alias-hooks.js +6 -4
- package/dist/internal/authored-loaders.js +37 -52
- package/dist/internal/bounded-int.js +1 -2
- package/dist/internal/bounded.js +13 -24
- package/dist/internal/brand.js +1 -1
- package/dist/internal/browser-origin-guard.js +4 -4
- package/dist/internal/builtin-tools/artifacts.js +15 -27
- package/dist/internal/builtin-tools/index.js +2 -3
- package/dist/internal/builtin-tools/reminders.js +33 -52
- package/dist/internal/channel-architecture.d.ts +21 -0
- package/dist/internal/channel-architecture.d.ts.map +1 -0
- package/dist/internal/channel-architecture.js +41 -0
- package/dist/internal/channel-dispatch.js +3 -4
- package/dist/internal/channel-route-dispatch.js +40 -51
- package/dist/internal/channel-state.js +1 -1
- package/dist/internal/chat-client.js +319 -340
- package/dist/internal/cli-ax.js +1262 -1294
- package/dist/internal/cli-bitbucket.js +244 -272
- package/dist/internal/cli-convert-automation.js +137 -151
- package/dist/internal/cli-cursor.js +126 -147
- package/dist/internal/cli-deploy.d.ts.map +1 -1
- package/dist/internal/cli-deploy.js +1457 -1507
- package/dist/internal/cli-docs.js +130 -147
- package/dist/internal/cli-github.js +437 -476
- package/dist/internal/cli-gitlab.js +259 -288
- package/dist/internal/cli-images.js +266 -334
- package/dist/internal/cli-manifest.js +25 -37
- package/dist/internal/cli-mcp-oauth.js +228 -247
- package/dist/internal/cli-mcp.js +358 -383
- package/dist/internal/cli-migrate.js +73 -90
- package/dist/internal/cli-skills.js +35 -47
- package/dist/internal/cli-slack-manual.d.ts +0 -1
- package/dist/internal/cli-slack-manual.d.ts.map +1 -1
- package/dist/internal/cli-slack-manual.js +175 -204
- package/dist/internal/cli-slack.d.ts +1 -1
- package/dist/internal/cli-slack.d.ts.map +1 -1
- package/dist/internal/cli-slack.js +416 -456
- package/dist/internal/cloud-merge.js +7 -3
- package/dist/internal/cloud-turn-cost.js +8 -1
- package/dist/internal/connection-env.js +5 -6
- package/dist/internal/continuation-channel.js +10 -7
- package/dist/internal/continuation-identity.js +85 -67
- package/dist/internal/conversation-mirror.js +112 -131
- package/dist/internal/convert-automation/convert-workflow.js +21 -31
- package/dist/internal/cron.js +3 -3
- package/dist/internal/cursor/account-mcp.js +147 -146
- package/dist/internal/cursor/backend-client.js +290 -320
- package/dist/internal/cursor/bound-secret-file.js +3 -3
- package/dist/internal/cursor/credentials.js +127 -142
- package/dist/internal/cursor/cursor-api-transport.js +4 -8
- package/dist/internal/cursor/github-credentials.js +91 -108
- package/dist/internal/cursor/hosted-bound-secrets.js +3 -4
- package/dist/internal/cursor/hosted-deployment-secrets.js +1 -1
- package/dist/internal/cursor/hosted-store-secrets.js +5 -9
- package/dist/internal/cursor/session-token.js +36 -48
- package/dist/internal/cursor/store-api-client.js +77 -92
- package/dist/internal/cursor-account-mcp-auth.js +132 -149
- package/dist/internal/cursor-agent-template.js +1 -1
- package/dist/internal/cursor-deployment-relay.js +33 -54
- package/dist/internal/cursor-event-relay.js +65 -59
- package/dist/internal/cursor-relay-core.js +258 -286
- package/dist/internal/deferred-channel-session.js +3 -12
- package/dist/internal/deploy-client.d.ts.map +1 -1
- package/dist/internal/deploy-client.js +413 -475
- package/dist/internal/deploy-manifest.d.ts +17 -0
- package/dist/internal/deploy-manifest.d.ts.map +1 -1
- package/dist/internal/deploy-manifest.js +71 -21
- package/dist/internal/deploy-source.js +31 -43
- package/dist/internal/discovery/agent-config.js +45 -59
- package/dist/internal/discovery/agent.js +276 -280
- package/dist/internal/discovery/channels.js +67 -80
- package/dist/internal/discovery/connections.js +286 -296
- package/dist/internal/discovery/context.js +2 -13
- package/dist/internal/discovery/cursor-plugin.js +223 -259
- package/dist/internal/discovery/extension-overlay.js +104 -131
- package/dist/internal/discovery/extensions.js +276 -281
- package/dist/internal/discovery/fs.js +56 -79
- package/dist/internal/discovery/hooks.js +39 -50
- package/dist/internal/discovery/info.js +17 -19
- package/dist/internal/discovery/instructions.js +58 -71
- package/dist/internal/discovery/modules.js +45 -58
- package/dist/internal/discovery/project.d.ts.map +1 -1
- package/dist/internal/discovery/project.js +192 -215
- package/dist/internal/discovery/reminders.js +41 -52
- package/dist/internal/discovery/runtime.js +1 -1
- package/dist/internal/discovery/schedules.js +71 -82
- package/dist/internal/discovery/seed-files.js +21 -32
- package/dist/internal/discovery/services.js +74 -96
- package/dist/internal/discovery/skills.js +77 -94
- package/dist/internal/discovery/subagent.js +79 -95
- package/dist/internal/discovery/tools.js +12 -23
- package/dist/internal/distribution.js +2 -2
- package/dist/internal/docs-site.js +30 -45
- package/dist/internal/duration.js +1 -1
- package/dist/internal/env-file.js +48 -64
- package/dist/internal/eval-judge-model.js +17 -28
- package/dist/internal/eval-run-store.js +265 -254
- package/dist/internal/eval-runner.d.ts +8 -0
- package/dist/internal/eval-runner.d.ts.map +1 -1
- package/dist/internal/eval-runner.js +406 -408
- package/dist/internal/eval-transport.d.ts +24 -0
- package/dist/internal/eval-transport.d.ts.map +1 -0
- package/dist/internal/eval-transport.js +22 -0
- package/dist/internal/evals-client.js +242 -246
- package/dist/internal/event-log.js +72 -120
- package/dist/internal/event-mapper.js +30 -31
- package/dist/internal/factory-resource-channel.js +16 -30
- package/dist/internal/filesystem/errors.js +6 -6
- package/dist/internal/filesystem/format.js +10 -13
- package/dist/internal/filesystem/merge.js +52 -94
- package/dist/internal/filesystem/nearest.js +15 -27
- package/dist/internal/filesystem/scratch.js +65 -85
- package/dist/internal/filesystem/tools.js +221 -241
- package/dist/internal/filesystem/walk.js +76 -143
- package/dist/internal/framework-file-storage.js +118 -139
- package/dist/internal/framework-storage-selection.js +21 -13
- package/dist/internal/frontmatter.js +4 -6
- package/dist/internal/github-fanout.js +50 -64
- package/dist/internal/guest-network.js +96 -109
- package/dist/internal/handleAgentServeTrigger.js +121 -126
- package/dist/internal/host-files.js +73 -88
- package/dist/internal/host-kv.js +21 -36
- package/dist/internal/host-otel.js +22 -19
- package/dist/internal/host-platforms.js +49 -63
- package/dist/internal/hosted-catch-protocol.d.ts +1 -0
- package/dist/internal/hosted-catch-protocol.d.ts.map +1 -1
- package/dist/internal/hosted-catch-protocol.js +1 -0
- package/dist/internal/hosted-catch.d.ts +5 -3
- package/dist/internal/hosted-catch.d.ts.map +1 -1
- package/dist/internal/hosted-catch.js +84 -93
- package/dist/internal/hosted-delivery-protocol.js +32 -8
- package/dist/internal/hosted-delivery.d.ts +13 -1
- package/dist/internal/hosted-delivery.d.ts.map +1 -1
- package/dist/internal/hosted-delivery.js +614 -584
- package/dist/internal/hosted-eval-cases.d.ts +21 -0
- package/dist/internal/hosted-eval-cases.d.ts.map +1 -0
- package/dist/internal/hosted-eval-cases.js +162 -0
- package/dist/internal/hosted-execution-diag.js +38 -30
- package/dist/internal/hosted-execution-flush.js +75 -66
- package/dist/internal/hosted-execution-latency.js +16 -8
- package/dist/internal/hosted-managed-automation.js +2 -2
- package/dist/internal/hosting.js +2 -3
- package/dist/internal/http-channel-define.js +4 -1
- package/dist/internal/http-channel.js +101 -112
- package/dist/internal/http-control-plane-session.d.ts +18 -1
- package/dist/internal/http-control-plane-session.d.ts.map +1 -1
- package/dist/internal/http-control-plane-session.js +66 -32
- package/dist/internal/incoming-headers-to-fetch.js +1 -2
- package/dist/internal/init-interview.js +73 -93
- package/dist/internal/init-project.js +182 -214
- package/dist/internal/init-scaffold.js +10 -21
- package/dist/internal/inline-stdio-mcp.js +80 -86
- package/dist/internal/install-cursor-skills.js +231 -273
- package/dist/internal/legacy-command-guard.js +18 -31
- package/dist/internal/listen-port.js +34 -45
- package/dist/internal/local-control-plane.js +293 -307
- package/dist/internal/local-env.js +1 -1
- package/dist/internal/local-ingress.js +15 -9
- package/dist/internal/log-ring.js +1 -2
- package/dist/internal/logs-client.js +207 -227
- package/dist/internal/map-pool.js +24 -38
- package/dist/internal/mcp-endpoint.js +204 -180
- package/dist/internal/mcp-host.js +165 -168
- package/dist/internal/mcp-oauth-on-demand.js +170 -207
- package/dist/internal/mcp-oauth-persist.js +15 -29
- package/dist/internal/mcp-oauth.js +209 -266
- package/dist/internal/named-webhook-secret.d.ts +39 -0
- package/dist/internal/named-webhook-secret.d.ts.map +1 -0
- package/dist/internal/named-webhook-secret.js +47 -0
- package/dist/internal/open-browser.js +2 -3
- package/dist/internal/otel/collector.js +104 -68
- package/dist/internal/otel/config.js +24 -37
- package/dist/internal/otel/http.js +5 -7
- package/dist/internal/otel/mcp.js +3 -12
- package/dist/internal/otel/runtime.js +69 -83
- package/dist/internal/package-inline-stdio.js +57 -65
- package/dist/internal/peer-connections.js +9 -5
- package/dist/internal/platform-schedule-sync.js +39 -54
- package/dist/internal/platform-timers.js +176 -210
- package/dist/internal/playground/static.js +1 -2
- package/dist/internal/playground/toolchain.js +37 -53
- package/dist/internal/playground-proxy.js +230 -270
- package/dist/internal/process-memory-telemetry.js +33 -51
- package/dist/internal/prompt-context.js +3 -6
- package/dist/internal/reminder-control-plane-protocol.js +46 -13
- package/dist/internal/reminder-runner.js +770 -785
- package/dist/internal/reminder-schedule.js +1 -1
- package/dist/internal/reminder-store.js +57 -78
- package/dist/internal/request-error-status.js +1 -3
- package/dist/internal/request-headers.js +2 -2
- package/dist/internal/resolve-prod-target.js +119 -135
- package/dist/internal/resolved-connections.js +16 -6
- package/dist/internal/run-client.js +221 -229
- package/dist/internal/runtime-dispatch-runner.js +18 -43
- package/dist/internal/schedule-runner.js +49 -58
- package/dist/internal/scm/pr-url.js +7 -6
- package/dist/internal/sdk-runner.js +388 -363
- package/dist/internal/serve-restart.js +26 -39
- package/dist/internal/server.d.ts.map +1 -1
- package/dist/internal/server.js +1283 -1244
- package/dist/internal/session-cost.js +7 -9
- package/dist/internal/session-engine.d.ts +3 -1
- package/dist/internal/session-engine.d.ts.map +1 -1
- package/dist/internal/session-engine.js +2801 -2777
- package/dist/internal/session-links.js +12 -16
- package/dist/internal/session-run-log.js +134 -82
- package/dist/internal/session-store.js +133 -164
- package/dist/internal/sessions-client.js +97 -118
- package/dist/internal/skill-catalog.js +18 -23
- package/dist/internal/skills-sync.js +16 -30
- package/dist/internal/slack-provision-client.js +90 -116
- package/dist/internal/start-log-store.js +48 -67
- package/dist/internal/steering.js +1 -2
- package/dist/internal/storage-coordinator.js +160 -196
- package/dist/internal/store-mirror.js +16 -30
- package/dist/internal/stream-progress.js +6 -8
- package/dist/internal/terminal-style.js +3 -4
- package/dist/internal/testing/scm-continuation-fixtures.js +6 -2
- package/dist/internal/testing/slack-continuation-fixtures.d.ts +26 -0
- package/dist/internal/testing/slack-continuation-fixtures.d.ts.map +1 -0
- package/dist/internal/testing/slack-continuation-fixtures.js +136 -0
- package/dist/internal/tool-catalog.js +11 -5
- package/dist/internal/tool-result.js +1 -1
- package/dist/internal/trajectory.js +19 -22
- package/dist/internal/turn-cost.js +52 -62
- package/dist/internal/turn-governor.js +5 -8
- package/dist/internal/turn-lease-store.js +85 -105
- package/dist/internal/turn-outbox.js +28 -43
- package/dist/internal/update-check.js +231 -259
- package/dist/internal/v2-hosting.js +1 -2
- package/dist/internal/workspace-sync.js +25 -41
- package/dist/internal/workspace.js +111 -139
- package/dist/kv/memory-kv.js +27 -51
- package/dist/memory.js +106 -148
- package/dist/otel.js +5 -8
- package/dist/playground/assets/{index-Co4CUVTQ.js → index-Be0-1hw2.js} +45 -45
- package/dist/playground/assets/index-Clz6uHj9.css +1 -0
- package/dist/playground/index.html +2 -2
- package/dist/prompt.js +2 -4
- package/dist/storage-backends/cursor-hosted-v2.js +53 -83
- package/dist/storage-backends/cursor-hosted.js +105 -145
- package/dist/storage-backends/file-kv.js +100 -128
- package/dist/storage-protocol.js +3 -5
- package/dist/storage.js +17 -26
- package/dist/types.d.ts +68 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +20 -18
- package/docs/building-with-agents.md +2 -0
- package/docs/deployment.md +7 -0
- package/docs/guides/bitbucket.md +9 -1
- package/docs/guides/github.md +20 -4
- package/docs/guides/gitlab.md +9 -1
- package/docs/guides/migrate.md +127 -0
- package/docs/reference/cli.md +39 -0
- package/docs/troubleshooting.md +1 -0
- package/package.json +1 -1
- package/skills/debug/SKILL.md +1 -0
- package/skills/github/SKILL.md +23 -0
- package/skills/migrate-v2/SKILL.md +51 -10
- package/dist/docs/assets/chunks/@localSearchIndexroot.BJ8UZggu.js +0 -1
- package/dist/docs/assets/chunks/channel.BTJ5J9FI.js +0 -1
- package/dist/docs/assets/chunks/classDiagram-6PBFFD2Q.D4BZ3cVV.js +0 -1
- package/dist/docs/assets/chunks/classDiagram-v2-HSJHXN6E.D4BZ3cVV.js +0 -1
- package/dist/docs/assets/chunks/clone.62tX-O-1.js +0 -1
- package/dist/docs/assets/chunks/stateDiagram-v2-QKLJ7IA2.DkTs1aEU.js +0 -1
- package/dist/docs/assets/reference_cli.md.GwugN3n-.lean.js +0 -1
- package/dist/docs/assets/troubleshooting.md.Bscj6ODe.js +0 -1
- package/dist/playground/assets/index-C1g_PTTZ.css +0 -1
- /package/dist/docs/assets/{building-with-agents.md.BPjPFxFg.lean.js → building-with-agents.md.Df87rAe1.lean.js} +0 -0
- /package/dist/docs/assets/{deployment.md.BdqTiGdc.lean.js → deployment.md.BYuEcDBv.lean.js} +0 -0
package/dist/internal/cli-ax.js
CHANGED
|
@@ -5,15 +5,6 @@
|
|
|
5
5
|
* Coding agents get JSON-first output, ephemeral local servers, and
|
|
6
6
|
* filesystem-first evals under evals/ (*.eval.ts).
|
|
7
7
|
*/
|
|
8
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
9
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
10
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
11
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
12
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
13
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
14
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
15
|
-
});
|
|
16
|
-
};
|
|
17
8
|
import { mkdir, mkdtemp, writeFile } from "node:fs/promises";
|
|
18
9
|
import { tmpdir } from "node:os";
|
|
19
10
|
import { dirname, join, resolve } from "node:path";
|
|
@@ -68,182 +59,182 @@ function pickAgentUrl(handle, slug) {
|
|
|
68
59
|
return match.url;
|
|
69
60
|
}
|
|
70
61
|
const root = handle.agents.find(a => a.slug === "");
|
|
71
|
-
return (root
|
|
62
|
+
return (root ?? handle.agents[0]).url;
|
|
72
63
|
}
|
|
73
|
-
function startEphemeral(
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
64
|
+
async function startEphemeral(options, evals = false) {
|
|
65
|
+
const dir = resolve(options.cwd ?? process.cwd(), options.dir);
|
|
66
|
+
const stateRoot = options.stateRoot ?? (await mkdtemp(join(tmpdir(), "agent-serve-ax-")));
|
|
67
|
+
const serveOptions = {
|
|
68
|
+
host: "127.0.0.1",
|
|
69
|
+
port: 0,
|
|
70
|
+
stateRoot,
|
|
71
|
+
playground: false,
|
|
72
|
+
schedules: false,
|
|
73
|
+
evals,
|
|
74
|
+
// Keep host/tool timing off stdout so `run`/`eval` JSON stays clean.
|
|
75
|
+
logger: (line) => {
|
|
76
|
+
process.stderr.write(`${line}\n`);
|
|
77
|
+
},
|
|
78
|
+
...(options.bearerToken === undefined ? {} : { authToken: options.bearerToken }),
|
|
79
|
+
};
|
|
80
|
+
const handle = await serve(dir, serveOptions);
|
|
81
|
+
return {
|
|
82
|
+
agentUrl: pickAgentUrl(handle, options.slug),
|
|
83
|
+
close: async () => {
|
|
84
|
+
// engine.close() can hang on open SDK streams; don't block the CLI.
|
|
85
|
+
await Promise.race([
|
|
86
|
+
handle.close(),
|
|
87
|
+
new Promise(resolve => setTimeout(resolve, 2_000)),
|
|
88
|
+
]);
|
|
89
|
+
},
|
|
90
|
+
};
|
|
95
91
|
}
|
|
96
|
-
export function resolveTarget(options) {
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
return startEphemeral(options);
|
|
116
|
-
});
|
|
92
|
+
export async function resolveTarget(options) {
|
|
93
|
+
if (options.prod === true && options.url !== undefined) {
|
|
94
|
+
die("--prod and --url are mutually exclusive");
|
|
95
|
+
}
|
|
96
|
+
if (options.url !== undefined) {
|
|
97
|
+
return { agentUrl: options.url.replace(/\/$/, "") };
|
|
98
|
+
}
|
|
99
|
+
if (options.prod === true) {
|
|
100
|
+
const prod = await resolveProdTarget({
|
|
101
|
+
dir: options.dir,
|
|
102
|
+
cwd: options.cwd,
|
|
103
|
+
slug: options.slug,
|
|
104
|
+
team: options.team,
|
|
105
|
+
apiKey: options.apiKey,
|
|
106
|
+
fetchImpl: options.fetchImpl,
|
|
107
|
+
});
|
|
108
|
+
return { agentUrl: prod.agentUrl, headers: prod.headers };
|
|
109
|
+
}
|
|
110
|
+
return startEphemeral(options);
|
|
117
111
|
}
|
|
118
|
-
export function cmdInit(options) {
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
if (
|
|
130
|
-
|
|
131
|
-
if (!template.ok) {
|
|
132
|
-
process.stderr.write(`${template.message}\n`);
|
|
133
|
-
return 1;
|
|
134
|
-
}
|
|
135
|
-
templateDir = template.dir;
|
|
136
|
-
overlayDir = template.overlayDir;
|
|
137
|
-
templateName = template.name;
|
|
138
|
-
}
|
|
139
|
-
const cwd = (_a = options.cwd) !== null && _a !== void 0 ? _a : process.cwd();
|
|
140
|
-
const dir = resolve(cwd, target);
|
|
141
|
-
const targetCheck = checkInitTarget(dir, options.template);
|
|
142
|
-
if (!targetCheck.ok) {
|
|
143
|
-
process.stderr.write(`${targetCheck.message}\n`);
|
|
112
|
+
export async function cmdInit(options) {
|
|
113
|
+
const target = options.initTarget;
|
|
114
|
+
if (target === undefined || target === "") {
|
|
115
|
+
printInitGuide();
|
|
116
|
+
return 0;
|
|
117
|
+
}
|
|
118
|
+
let templateDir;
|
|
119
|
+
let overlayDir;
|
|
120
|
+
let templateName;
|
|
121
|
+
if (options.template !== undefined) {
|
|
122
|
+
const template = resolveTemplate(options.template);
|
|
123
|
+
if (!template.ok) {
|
|
124
|
+
process.stderr.write(`${template.message}\n`);
|
|
144
125
|
return 1;
|
|
145
126
|
}
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
const result = yield initProject({
|
|
162
|
-
dir,
|
|
127
|
+
templateDir = template.dir;
|
|
128
|
+
overlayDir = template.overlayDir;
|
|
129
|
+
templateName = template.name;
|
|
130
|
+
}
|
|
131
|
+
const cwd = options.cwd ?? process.cwd();
|
|
132
|
+
const dir = resolve(cwd, target);
|
|
133
|
+
const targetCheck = checkInitTarget(dir, options.template);
|
|
134
|
+
if (!targetCheck.ok) {
|
|
135
|
+
process.stderr.write(`${targetCheck.message}\n`);
|
|
136
|
+
return 1;
|
|
137
|
+
}
|
|
138
|
+
let answers;
|
|
139
|
+
let initSpec;
|
|
140
|
+
if (templateDir !== undefined) {
|
|
141
|
+
const interview = await runTemplateInit({
|
|
163
142
|
templateDir,
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
answers,
|
|
167
|
-
initSpec,
|
|
168
|
-
});
|
|
169
|
-
let signedIn = (yield resolveApiKey()) !== undefined;
|
|
170
|
-
// Machine-readable path: install deps (piped), never block on browser login.
|
|
171
|
-
if (options.json) {
|
|
172
|
-
const install = yield installScaffoldDependencies(result.rootDir, {
|
|
173
|
-
stdio: "pipe",
|
|
174
|
-
});
|
|
175
|
-
const linked = install.ok
|
|
176
|
-
? yield linkCliOntoPath(result.rootDir, { stdio: "pipe" })
|
|
177
|
-
: undefined;
|
|
178
|
-
const cliOnPath = (linked === null || linked === void 0 ? void 0 : linked.ok) === true;
|
|
179
|
-
process.stdout.write(`${JSON.stringify({
|
|
180
|
-
ok: install.ok,
|
|
181
|
-
directory: result.rootDir,
|
|
182
|
-
template: (_b = options.template) !== null && _b !== void 0 ? _b : null,
|
|
183
|
-
created: result.created,
|
|
184
|
-
skipped: result.skipped,
|
|
185
|
-
installed: install.ok,
|
|
186
|
-
installError: install.ok
|
|
187
|
-
? null
|
|
188
|
-
: install.stderr.trim() || `npm install exited ${install.exitCode}`,
|
|
189
|
-
cliOnPath,
|
|
190
|
-
cliLinkError: install.ok && linked !== undefined && !linked.ok
|
|
191
|
-
? linked.stderr.trim() || `npm install -g exited ${linked.exitCode}`
|
|
192
|
-
: null,
|
|
193
|
-
next: initNextCommands({
|
|
194
|
-
rootDir: result.rootDir,
|
|
195
|
-
cwd,
|
|
196
|
-
signedIn,
|
|
197
|
-
cliOnPath,
|
|
198
|
-
}),
|
|
199
|
-
}, null, 2)}\n`);
|
|
200
|
-
return install.ok ? 0 : 1;
|
|
201
|
-
}
|
|
202
|
-
process.stdout.write(formatInitScaffoldSummary({
|
|
203
|
-
rootDir: result.rootDir,
|
|
204
|
-
files: result.files,
|
|
205
|
-
}));
|
|
206
|
-
process.stdout.write("Installing npm packages\n\n");
|
|
207
|
-
const install = yield installScaffoldDependencies(result.rootDir, {
|
|
208
|
-
stdio: "inherit",
|
|
143
|
+
vars: options.vars,
|
|
144
|
+
interactive: options.json !== true && process.stdin.isTTY === true && process.stdout.isTTY === true,
|
|
209
145
|
});
|
|
210
|
-
if (!
|
|
211
|
-
process.stderr.write(
|
|
212
|
-
return
|
|
213
|
-
}
|
|
214
|
-
process.stdout.write("\n");
|
|
215
|
-
process.stdout.write(`Installing ${CLI_COMMAND_NAME} on your PATH\n\n`);
|
|
216
|
-
const linked = yield linkCliOntoPath(result.rootDir, { stdio: "inherit" });
|
|
217
|
-
const cliOnPath = linked.ok;
|
|
218
|
-
if (!cliOnPath) {
|
|
219
|
-
process.stderr.write(`\nCould not put ${CLI_COMMAND_NAME} on PATH (${linked.stderr.trim() || `exit ${linked.exitCode}`}). Next steps use npx ${PACKAGE_NAME} instead.\n\n`);
|
|
220
|
-
}
|
|
221
|
-
else {
|
|
222
|
-
process.stdout.write("\n");
|
|
223
|
-
}
|
|
224
|
-
// Personal Cursor skills so coding agents can pick up create-agent / debug / …
|
|
225
|
-
try {
|
|
226
|
-
yield offerInstallCursorSkills();
|
|
227
|
-
}
|
|
228
|
-
catch (err) {
|
|
229
|
-
const message = err instanceof Error ? err.message : String(err);
|
|
230
|
-
process.stderr.write(`\nCould not install Cursor skills (${message}). Continuing init.\n\n`);
|
|
231
|
-
}
|
|
232
|
-
let loginExit = 0;
|
|
233
|
-
if (!signedIn) {
|
|
234
|
-
// init always offers the browser flow (the --json path above skipped it).
|
|
235
|
-
loginExit = yield ensureCursorLogin({ interactive: true });
|
|
236
|
-
signedIn = loginExit === 0 && (yield resolveApiKey()) !== undefined;
|
|
237
|
-
process.stdout.write("\n");
|
|
146
|
+
if (!interview.ok) {
|
|
147
|
+
process.stderr.write(`${interview.error}\n`);
|
|
148
|
+
return 1;
|
|
238
149
|
}
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
150
|
+
answers = interview.answers;
|
|
151
|
+
initSpec = interview.spec;
|
|
152
|
+
}
|
|
153
|
+
const result = await initProject({
|
|
154
|
+
dir,
|
|
155
|
+
templateDir,
|
|
156
|
+
overlayDir,
|
|
157
|
+
templateName,
|
|
158
|
+
answers,
|
|
159
|
+
initSpec,
|
|
160
|
+
});
|
|
161
|
+
let signedIn = (await resolveApiKey()) !== undefined;
|
|
162
|
+
// Machine-readable path: install deps (piped), never block on browser login.
|
|
163
|
+
if (options.json) {
|
|
164
|
+
const install = await installScaffoldDependencies(result.rootDir, {
|
|
165
|
+
stdio: "pipe",
|
|
166
|
+
});
|
|
167
|
+
const linked = install.ok
|
|
168
|
+
? await linkCliOntoPath(result.rootDir, { stdio: "pipe" })
|
|
169
|
+
: undefined;
|
|
170
|
+
const cliOnPath = linked?.ok === true;
|
|
171
|
+
process.stdout.write(`${JSON.stringify({
|
|
172
|
+
ok: install.ok,
|
|
173
|
+
directory: result.rootDir,
|
|
174
|
+
template: options.template ?? null,
|
|
175
|
+
created: result.created,
|
|
176
|
+
skipped: result.skipped,
|
|
177
|
+
installed: install.ok,
|
|
178
|
+
installError: install.ok
|
|
179
|
+
? null
|
|
180
|
+
: install.stderr.trim() || `npm install exited ${install.exitCode}`,
|
|
243
181
|
cliOnPath,
|
|
244
|
-
|
|
245
|
-
|
|
182
|
+
cliLinkError: install.ok && linked !== undefined && !linked.ok
|
|
183
|
+
? linked.stderr.trim() || `npm install -g exited ${linked.exitCode}`
|
|
184
|
+
: null,
|
|
185
|
+
next: initNextCommands({
|
|
186
|
+
rootDir: result.rootDir,
|
|
187
|
+
cwd,
|
|
188
|
+
signedIn,
|
|
189
|
+
cliOnPath,
|
|
190
|
+
}),
|
|
191
|
+
}, null, 2)}\n`);
|
|
192
|
+
return install.ok ? 0 : 1;
|
|
193
|
+
}
|
|
194
|
+
process.stdout.write(formatInitScaffoldSummary({
|
|
195
|
+
rootDir: result.rootDir,
|
|
196
|
+
files: result.files,
|
|
197
|
+
}));
|
|
198
|
+
process.stdout.write("Installing npm packages\n\n");
|
|
199
|
+
const install = await installScaffoldDependencies(result.rootDir, {
|
|
200
|
+
stdio: "inherit",
|
|
246
201
|
});
|
|
202
|
+
if (!install.ok) {
|
|
203
|
+
process.stderr.write(`\nnpm install failed (exit ${install.exitCode}). Fix the install, then retry init.\n`);
|
|
204
|
+
return install.exitCode || 1;
|
|
205
|
+
}
|
|
206
|
+
process.stdout.write("\n");
|
|
207
|
+
process.stdout.write(`Installing ${CLI_COMMAND_NAME} on your PATH\n\n`);
|
|
208
|
+
const linked = await linkCliOntoPath(result.rootDir, { stdio: "inherit" });
|
|
209
|
+
const cliOnPath = linked.ok;
|
|
210
|
+
if (!cliOnPath) {
|
|
211
|
+
process.stderr.write(`\nCould not put ${CLI_COMMAND_NAME} on PATH (${linked.stderr.trim() || `exit ${linked.exitCode}`}). Next steps use npx ${PACKAGE_NAME} instead.\n\n`);
|
|
212
|
+
}
|
|
213
|
+
else {
|
|
214
|
+
process.stdout.write("\n");
|
|
215
|
+
}
|
|
216
|
+
// Personal Cursor skills so coding agents can pick up create-agent / debug / …
|
|
217
|
+
try {
|
|
218
|
+
await offerInstallCursorSkills();
|
|
219
|
+
}
|
|
220
|
+
catch (err) {
|
|
221
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
222
|
+
process.stderr.write(`\nCould not install Cursor skills (${message}). Continuing init.\n\n`);
|
|
223
|
+
}
|
|
224
|
+
let loginExit = 0;
|
|
225
|
+
if (!signedIn) {
|
|
226
|
+
// init always offers the browser flow (the --json path above skipped it).
|
|
227
|
+
loginExit = await ensureCursorLogin({ interactive: true });
|
|
228
|
+
signedIn = loginExit === 0 && (await resolveApiKey()) !== undefined;
|
|
229
|
+
process.stdout.write("\n");
|
|
230
|
+
}
|
|
231
|
+
process.stdout.write(formatInitNextSteps({
|
|
232
|
+
rootDir: result.rootDir,
|
|
233
|
+
cwd,
|
|
234
|
+
signedIn,
|
|
235
|
+
cliOnPath,
|
|
236
|
+
}));
|
|
237
|
+
return loginExit;
|
|
247
238
|
}
|
|
248
239
|
/**
|
|
249
240
|
* `resume [sessionId]` — reattach the interactive chat REPL to an existing
|
|
@@ -254,14 +245,19 @@ export function cmdInit(options) {
|
|
|
254
245
|
* `--message`, `--json`, …). `--session` is accepted as a redundant
|
|
255
246
|
* alias for the positional id.
|
|
256
247
|
*/
|
|
257
|
-
export function cmdResume(sessionId, options) {
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
248
|
+
export async function cmdResume(sessionId, options) {
|
|
249
|
+
const resolved = trimNonEmpty(sessionId) ?? trimNonEmpty(options.sessionId);
|
|
250
|
+
if (resolved !== undefined) {
|
|
251
|
+
return cmdChat({
|
|
252
|
+
...options,
|
|
253
|
+
sessionId: resolved,
|
|
254
|
+
resume: false,
|
|
255
|
+
});
|
|
256
|
+
}
|
|
257
|
+
return cmdChat({
|
|
258
|
+
...options,
|
|
259
|
+
sessionId: undefined,
|
|
260
|
+
resume: true,
|
|
265
261
|
});
|
|
266
262
|
}
|
|
267
263
|
function trimNonEmpty(value) {
|
|
@@ -275,205 +271,201 @@ function trimNonEmpty(value) {
|
|
|
275
271
|
* `chat` — talk to a running (or `--prod` hosted) agent. With `--json`,
|
|
276
272
|
* prints a trajectory instead of the interactive UI.
|
|
277
273
|
*/
|
|
278
|
-
export function cmdChat(options) {
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
274
|
+
export async function cmdChat(options) {
|
|
275
|
+
const message = options.messages?.[0];
|
|
276
|
+
// chat never starts an ephemeral server — default to local serve URL.
|
|
277
|
+
const target = await resolveTarget({
|
|
278
|
+
...options,
|
|
279
|
+
url: options.prod === true ? undefined : (options.url ?? "http://127.0.0.1:3000"),
|
|
280
|
+
});
|
|
281
|
+
let sessionId = trimNonEmpty(options.sessionId);
|
|
282
|
+
// `--resume` without an id → most recently updated followable session.
|
|
283
|
+
// An explicit `--session` / positional id always wins.
|
|
284
|
+
if (options.resume === true && sessionId === undefined) {
|
|
285
|
+
try {
|
|
286
|
+
const previous = await resolvePreviousSessionId({
|
|
287
|
+
baseUrl: target.agentUrl,
|
|
288
|
+
auth: {
|
|
289
|
+
bearerToken: options.bearerToken,
|
|
290
|
+
headers: target.headers,
|
|
291
|
+
},
|
|
292
|
+
fetchImpl: options.fetchImpl,
|
|
293
|
+
});
|
|
294
|
+
if (previous === undefined) {
|
|
295
|
+
process.stderr.write("No previous followable session found. Start one with " +
|
|
296
|
+
`\`${CLI_COMMAND_NAME} chat\` or pass a session id.\n`);
|
|
297
|
+
return 1;
|
|
298
|
+
}
|
|
299
|
+
sessionId = previous;
|
|
300
|
+
}
|
|
301
|
+
catch (error) {
|
|
302
|
+
process.stderr.write(`${error instanceof Error ? error.message : String(error)}\n`);
|
|
303
|
+
return 1;
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
if (options.json) {
|
|
307
|
+
if (message === undefined) {
|
|
308
|
+
process.stderr.write("chat --json requires --message\n");
|
|
309
|
+
return 2;
|
|
310
|
+
}
|
|
311
|
+
let continuationToken = options.continuationToken;
|
|
312
|
+
if (sessionId !== undefined && (continuationToken === undefined || continuationToken === "")) {
|
|
289
313
|
try {
|
|
290
|
-
|
|
314
|
+
continuationToken = await lookupSessionContinuation({
|
|
291
315
|
baseUrl: target.agentUrl,
|
|
316
|
+
sessionId,
|
|
292
317
|
auth: {
|
|
293
318
|
bearerToken: options.bearerToken,
|
|
294
319
|
headers: target.headers,
|
|
295
320
|
},
|
|
296
|
-
fetchImpl: options.fetchImpl,
|
|
297
321
|
});
|
|
298
|
-
if (previous === undefined) {
|
|
299
|
-
process.stderr.write("No previous followable session found. Start one with " +
|
|
300
|
-
`\`${CLI_COMMAND_NAME} chat\` or pass a session id.\n`);
|
|
301
|
-
return 1;
|
|
302
|
-
}
|
|
303
|
-
sessionId = previous;
|
|
304
322
|
}
|
|
305
323
|
catch (error) {
|
|
306
324
|
process.stderr.write(`${error instanceof Error ? error.message : String(error)}\n`);
|
|
307
325
|
return 1;
|
|
308
326
|
}
|
|
309
327
|
}
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
sessionId,
|
|
321
|
-
auth: {
|
|
322
|
-
bearerToken: options.bearerToken,
|
|
323
|
-
headers: target.headers,
|
|
324
|
-
},
|
|
325
|
-
});
|
|
326
|
-
}
|
|
327
|
-
catch (error) {
|
|
328
|
-
process.stderr.write(`${error instanceof Error ? error.message : String(error)}\n`);
|
|
329
|
-
return 1;
|
|
330
|
-
}
|
|
331
|
-
}
|
|
332
|
-
const result = yield runSession({
|
|
333
|
-
baseUrl: target.agentUrl,
|
|
334
|
-
messages: [message],
|
|
335
|
-
sessionId,
|
|
336
|
-
continuationToken,
|
|
337
|
-
bearerToken: options.bearerToken,
|
|
338
|
-
headers: target.headers,
|
|
339
|
-
});
|
|
340
|
-
if (options.text) {
|
|
341
|
-
process.stdout.write(formatTrajectoryText(result.trajectory));
|
|
342
|
-
}
|
|
343
|
-
else {
|
|
344
|
-
console.log(JSON.stringify({
|
|
345
|
-
ok: result.ok,
|
|
346
|
-
sessionId: result.sessionId,
|
|
347
|
-
continuationToken: (_c = result.continuationToken) !== null && _c !== void 0 ? _c : null,
|
|
348
|
-
trajectory: result.trajectory,
|
|
349
|
-
}, null, 2));
|
|
350
|
-
}
|
|
351
|
-
return result.ok ? 0 : 1;
|
|
352
|
-
}
|
|
353
|
-
try {
|
|
354
|
-
yield runChat({
|
|
355
|
-
baseUrl: target.agentUrl,
|
|
356
|
-
message,
|
|
357
|
-
sessionId,
|
|
358
|
-
continuationToken: options.continuationToken,
|
|
359
|
-
bearerToken: options.bearerToken,
|
|
360
|
-
headers: target.headers,
|
|
361
|
-
noColor: options.noColor,
|
|
362
|
-
});
|
|
363
|
-
return 0;
|
|
364
|
-
}
|
|
365
|
-
catch (error) {
|
|
366
|
-
process.stderr.write(`${error instanceof Error ? error.message : String(error)}\n`);
|
|
367
|
-
return 1;
|
|
328
|
+
const result = await runSession({
|
|
329
|
+
baseUrl: target.agentUrl,
|
|
330
|
+
messages: [message],
|
|
331
|
+
sessionId,
|
|
332
|
+
continuationToken,
|
|
333
|
+
bearerToken: options.bearerToken,
|
|
334
|
+
headers: target.headers,
|
|
335
|
+
});
|
|
336
|
+
if (options.text) {
|
|
337
|
+
process.stdout.write(formatTrajectoryText(result.trajectory));
|
|
368
338
|
}
|
|
369
|
-
|
|
339
|
+
else {
|
|
340
|
+
console.log(JSON.stringify({
|
|
341
|
+
ok: result.ok,
|
|
342
|
+
sessionId: result.sessionId,
|
|
343
|
+
continuationToken: result.continuationToken ?? null,
|
|
344
|
+
trajectory: result.trajectory,
|
|
345
|
+
}, null, 2));
|
|
346
|
+
}
|
|
347
|
+
return result.ok ? 0 : 1;
|
|
348
|
+
}
|
|
349
|
+
try {
|
|
350
|
+
await runChat({
|
|
351
|
+
baseUrl: target.agentUrl,
|
|
352
|
+
message,
|
|
353
|
+
sessionId,
|
|
354
|
+
continuationToken: options.continuationToken,
|
|
355
|
+
bearerToken: options.bearerToken,
|
|
356
|
+
headers: target.headers,
|
|
357
|
+
noColor: options.noColor,
|
|
358
|
+
});
|
|
359
|
+
return 0;
|
|
360
|
+
}
|
|
361
|
+
catch (error) {
|
|
362
|
+
process.stderr.write(`${error instanceof Error ? error.message : String(error)}\n`);
|
|
363
|
+
return 1;
|
|
364
|
+
}
|
|
370
365
|
}
|
|
371
|
-
export function cmdRun(options) {
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
if (
|
|
378
|
-
|
|
379
|
-
if (started !== "fallback") {
|
|
380
|
-
return started;
|
|
381
|
-
}
|
|
382
|
-
}
|
|
383
|
-
const messages = (_a = options.messages) !== null && _a !== void 0 ? _a : [];
|
|
384
|
-
if (messages.length === 0) {
|
|
385
|
-
die("Provide --message (repeatable) or --messages-file");
|
|
366
|
+
export async function cmdRun(options) {
|
|
367
|
+
// Only a v2-shaped request tries the control plane; every v1 `run --prod`
|
|
368
|
+
// form (multi-turn, continuation token, local session id, --url) keeps its
|
|
369
|
+
// engine-alias path untouched.
|
|
370
|
+
if (options.prod === true && hostedSessionRejection(options) === undefined) {
|
|
371
|
+
const started = await cmdHostedSession(options);
|
|
372
|
+
if (started !== "fallback") {
|
|
373
|
+
return started;
|
|
386
374
|
}
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
375
|
+
}
|
|
376
|
+
const messages = options.messages ?? [];
|
|
377
|
+
if (messages.length === 0) {
|
|
378
|
+
die("Provide --message (repeatable) or --messages-file");
|
|
379
|
+
}
|
|
380
|
+
const stream = shouldStreamProgress(options);
|
|
381
|
+
const progress = stream ? createStreamProgress() : undefined;
|
|
382
|
+
const target = await resolveTarget(options);
|
|
383
|
+
try {
|
|
384
|
+
if (stream) {
|
|
385
|
+
process.stderr.write(`→ ${target.agentUrl}\n`);
|
|
386
|
+
}
|
|
387
|
+
const result = await runSession({
|
|
388
|
+
baseUrl: target.agentUrl,
|
|
389
|
+
messages,
|
|
390
|
+
sessionId: options.sessionId,
|
|
391
|
+
continuationToken: options.continuationToken,
|
|
392
|
+
bearerToken: options.bearerToken,
|
|
393
|
+
headers: target.headers,
|
|
394
|
+
timeoutMs: options.timeoutMs,
|
|
395
|
+
onEvent: progress === undefined ? undefined : e => progress.onEvent(e),
|
|
396
|
+
});
|
|
397
|
+
let eventsPath;
|
|
398
|
+
const writeEvents = options.events !== false;
|
|
399
|
+
if (writeEvents) {
|
|
400
|
+
if (typeof options.events === "string") {
|
|
401
|
+
eventsPath = resolve(options.events);
|
|
393
402
|
}
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
bearerToken: options.bearerToken,
|
|
400
|
-
headers: target.headers,
|
|
401
|
-
timeoutMs: options.timeoutMs,
|
|
402
|
-
onEvent: progress === undefined ? undefined : e => progress.onEvent(e),
|
|
403
|
-
});
|
|
404
|
-
let eventsPath;
|
|
405
|
-
const writeEvents = options.events !== false;
|
|
406
|
-
if (writeEvents) {
|
|
407
|
-
if (typeof options.events === "string") {
|
|
408
|
-
eventsPath = resolve(options.events);
|
|
409
|
-
}
|
|
410
|
-
else {
|
|
411
|
-
const root = resolve((_b = options.cwd) !== null && _b !== void 0 ? _b : process.cwd(), options.dir);
|
|
412
|
-
const tracesDir = join(root, ".agent-serve", "traces");
|
|
413
|
-
yield mkdir(tracesDir, { recursive: true });
|
|
414
|
-
eventsPath = join(tracesDir, `${result.sessionId}.ndjson`);
|
|
415
|
-
}
|
|
416
|
-
yield writeFile(eventsPath, `${result.events.map(e => JSON.stringify(e)).join("\n")}\n`, "utf8");
|
|
403
|
+
else {
|
|
404
|
+
const root = resolve(options.cwd ?? process.cwd(), options.dir);
|
|
405
|
+
const tracesDir = join(root, ".agent-serve", "traces");
|
|
406
|
+
await mkdir(tracesDir, { recursive: true });
|
|
407
|
+
eventsPath = join(tracesDir, `${result.sessionId}.ndjson`);
|
|
417
408
|
}
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
? [
|
|
425
|
-
CLI_COMMAND_NAME,
|
|
426
|
-
"playground",
|
|
427
|
-
"--prod",
|
|
428
|
-
...(options.slug !== undefined && options.slug.trim() !== ""
|
|
429
|
-
? ["--slug", options.slug.trim()]
|
|
430
|
-
: []),
|
|
431
|
-
...(options.team !== undefined && options.team.trim() !== ""
|
|
432
|
-
? ["--team", options.team.trim()]
|
|
433
|
-
: []),
|
|
434
|
-
"--session",
|
|
435
|
-
result.sessionId,
|
|
436
|
-
].join(" ")
|
|
409
|
+
await writeFile(eventsPath, `${result.events.map(e => JSON.stringify(e)).join("\n")}\n`, "utf8");
|
|
410
|
+
}
|
|
411
|
+
const playgroundUrl = options.prod === true
|
|
412
|
+
? null
|
|
413
|
+
: options.url !== undefined
|
|
414
|
+
? `${target.agentUrl.replace(/\/$/, "")}/playground?sessionId=${encodeURIComponent(result.sessionId)}`
|
|
437
415
|
: null;
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
416
|
+
const playgroundHint = options.prod === true
|
|
417
|
+
? [
|
|
418
|
+
CLI_COMMAND_NAME,
|
|
419
|
+
"playground",
|
|
420
|
+
"--prod",
|
|
421
|
+
...(options.slug !== undefined && options.slug.trim() !== ""
|
|
422
|
+
? ["--slug", options.slug.trim()]
|
|
423
|
+
: []),
|
|
424
|
+
...(options.team !== undefined && options.team.trim() !== ""
|
|
425
|
+
? ["--team", options.team.trim()]
|
|
426
|
+
: []),
|
|
427
|
+
"--session",
|
|
428
|
+
result.sessionId,
|
|
429
|
+
].join(" ")
|
|
430
|
+
: null;
|
|
431
|
+
if (options.text) {
|
|
432
|
+
process.stdout.write(formatTrajectoryText(result.trajectory));
|
|
433
|
+
if (eventsPath !== undefined) {
|
|
434
|
+
process.stderr.write(`\ntrace: ${eventsPath}\n`);
|
|
449
435
|
}
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
ok: result.ok,
|
|
453
|
-
sessionId: result.sessionId,
|
|
454
|
-
continuationToken: (_c = result.continuationToken) !== null && _c !== void 0 ? _c : null,
|
|
455
|
-
trace: eventsPath !== null && eventsPath !== void 0 ? eventsPath : null,
|
|
456
|
-
playgroundUrl,
|
|
457
|
-
playgroundHint,
|
|
458
|
-
visualize: playgroundHint !== null
|
|
459
|
-
? `Run ${playgroundHint}`
|
|
460
|
-
: playgroundUrl !== null
|
|
461
|
-
? `Open ${playgroundUrl}`
|
|
462
|
-
: eventsPath !== undefined
|
|
463
|
-
? `${CLI_COMMAND_NAME} trajectory --events ${eventsPath}`
|
|
464
|
-
: null,
|
|
465
|
-
trajectory: result.trajectory,
|
|
466
|
-
}, null, 2));
|
|
436
|
+
if (playgroundUrl !== null) {
|
|
437
|
+
process.stderr.write(`playground: ${playgroundUrl}\n`);
|
|
467
438
|
}
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
finally {
|
|
471
|
-
progress === null || progress === void 0 ? void 0 : progress.close();
|
|
472
|
-
if (target.close !== undefined) {
|
|
473
|
-
yield target.close();
|
|
439
|
+
else if (playgroundHint !== null) {
|
|
440
|
+
process.stderr.write(`playground: ${playgroundHint}\n`);
|
|
474
441
|
}
|
|
475
442
|
}
|
|
476
|
-
|
|
443
|
+
else {
|
|
444
|
+
console.log(JSON.stringify({
|
|
445
|
+
ok: result.ok,
|
|
446
|
+
sessionId: result.sessionId,
|
|
447
|
+
continuationToken: result.continuationToken ?? null,
|
|
448
|
+
trace: eventsPath ?? null,
|
|
449
|
+
playgroundUrl,
|
|
450
|
+
playgroundHint,
|
|
451
|
+
visualize: playgroundHint !== null
|
|
452
|
+
? `Run ${playgroundHint}`
|
|
453
|
+
: playgroundUrl !== null
|
|
454
|
+
? `Open ${playgroundUrl}`
|
|
455
|
+
: eventsPath !== undefined
|
|
456
|
+
? `${CLI_COMMAND_NAME} trajectory --events ${eventsPath}`
|
|
457
|
+
: null,
|
|
458
|
+
trajectory: result.trajectory,
|
|
459
|
+
}, null, 2));
|
|
460
|
+
}
|
|
461
|
+
return result.ok ? 0 : 1;
|
|
462
|
+
}
|
|
463
|
+
finally {
|
|
464
|
+
progress?.close();
|
|
465
|
+
if (target.close !== undefined) {
|
|
466
|
+
await target.close();
|
|
467
|
+
}
|
|
468
|
+
}
|
|
477
469
|
}
|
|
478
470
|
const HOSTED_SESSION_ID_RE = /^ses_[a-f0-9]{24}$/;
|
|
479
471
|
/**
|
|
@@ -485,13 +477,11 @@ const HOSTED_SESSION_ID_RE = /^ses_[a-f0-9]{24}$/;
|
|
|
485
477
|
*/
|
|
486
478
|
/** Why these options cannot be a hosted v2 session start, if they cannot. */
|
|
487
479
|
function hostedSessionRejection(options) {
|
|
488
|
-
var _a;
|
|
489
|
-
var _b;
|
|
490
480
|
if (options.url !== undefined) {
|
|
491
481
|
return "--prod session start talks to the agentsdk control plane; do not pass --url";
|
|
492
482
|
}
|
|
493
|
-
const messages =
|
|
494
|
-
if (messages.length !== 1 ||
|
|
483
|
+
const messages = options.messages ?? [];
|
|
484
|
+
if (messages.length !== 1 || messages[0]?.trim() === "") {
|
|
495
485
|
return "Provide exactly one --message (the wake). Multi-turn runs are local-only.";
|
|
496
486
|
}
|
|
497
487
|
if (trimNonEmpty(options.continuationToken) !== undefined) {
|
|
@@ -503,74 +493,69 @@ function hostedSessionRejection(options) {
|
|
|
503
493
|
}
|
|
504
494
|
return undefined;
|
|
505
495
|
}
|
|
506
|
-
function cmdHostedSession(options) {
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
496
|
+
async function cmdHostedSession(options) {
|
|
497
|
+
const rejection = hostedSessionRejection(options);
|
|
498
|
+
if (rejection !== undefined) {
|
|
499
|
+
die(rejection);
|
|
500
|
+
}
|
|
501
|
+
const messages = options.messages ?? [];
|
|
502
|
+
const sessionId = trimNonEmpty(options.sessionId);
|
|
503
|
+
const auth = await resolveDeployAuth({
|
|
504
|
+
team: options.team,
|
|
505
|
+
apiKey: options.apiKey,
|
|
506
|
+
fetchImpl: options.fetchImpl,
|
|
507
|
+
});
|
|
508
|
+
if (typeof auth === "number") {
|
|
509
|
+
return auth;
|
|
510
|
+
}
|
|
511
|
+
const slug = resolveProdSlug(options);
|
|
512
|
+
try {
|
|
513
|
+
const accepted = await auth.client.startSession({
|
|
514
|
+
teamId: auth.teamId,
|
|
515
|
+
slug,
|
|
516
|
+
message: messages[0].trim(),
|
|
517
|
+
sessionId,
|
|
518
|
+
dryRun: options.dryRun,
|
|
519
|
+
asOf: options.asOf,
|
|
520
|
+
componentKey: trimNonEmpty(options.componentKey),
|
|
519
521
|
});
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
const slug = resolveProdSlug(options);
|
|
524
|
-
try {
|
|
525
|
-
const accepted = yield auth.client.startSession({
|
|
526
|
-
teamId: auth.teamId,
|
|
527
|
-
slug,
|
|
528
|
-
message: messages[0].trim(),
|
|
529
|
-
sessionId,
|
|
530
|
-
dryRun: options.dryRun,
|
|
531
|
-
asOf: options.asOf,
|
|
532
|
-
componentKey: trimNonEmpty(options.componentKey),
|
|
533
|
-
});
|
|
534
|
-
console.log(JSON.stringify(accepted, null, 2));
|
|
535
|
-
if (accepted.sessionId === undefined) {
|
|
536
|
-
process.stderr.write(`${v2HostedVerifyHint(slug)}\n`);
|
|
537
|
-
}
|
|
538
|
-
return 0;
|
|
522
|
+
console.log(JSON.stringify(accepted, null, 2));
|
|
523
|
+
if (accepted.sessionId === undefined) {
|
|
524
|
+
process.stderr.write(`${v2HostedVerifyHint(slug)}\n`);
|
|
539
525
|
}
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
return 1;
|
|
526
|
+
return 0;
|
|
527
|
+
}
|
|
528
|
+
catch (error) {
|
|
529
|
+
if (error instanceof DeployApiError && error.status === 404) {
|
|
530
|
+
return "fallback";
|
|
546
531
|
}
|
|
547
|
-
|
|
532
|
+
process.stderr.write(`${error instanceof Error ? error.message : String(error)}\n`);
|
|
533
|
+
return 1;
|
|
534
|
+
}
|
|
548
535
|
}
|
|
549
536
|
/**
|
|
550
537
|
* Shared deterministic-route fetch (`call`, `skill`): engine headers,
|
|
551
538
|
* bearer auth, and JSON. The payload is `undefined` when the body does
|
|
552
539
|
* not decode; callers print `invalid_response` and fail.
|
|
553
540
|
*/
|
|
554
|
-
function fetchAgentJson(
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
body: args.body,
|
|
570
|
-
});
|
|
571
|
-
const payload = yield response.json().catch(() => undefined);
|
|
572
|
-
return { response, payload };
|
|
541
|
+
async function fetchAgentJson(target, path, args = {}) {
|
|
542
|
+
const headers = {};
|
|
543
|
+
if (target.headers !== undefined) {
|
|
544
|
+
Object.assign(headers, target.headers);
|
|
545
|
+
}
|
|
546
|
+
if (args.body !== undefined) {
|
|
547
|
+
headers["content-type"] = "application/json";
|
|
548
|
+
}
|
|
549
|
+
if (args.bearerToken !== undefined) {
|
|
550
|
+
headers.authorization = `Bearer ${args.bearerToken}`;
|
|
551
|
+
}
|
|
552
|
+
const response = await fetch(`${target.agentUrl}${path}`, {
|
|
553
|
+
method: args.method,
|
|
554
|
+
headers,
|
|
555
|
+
body: args.body,
|
|
573
556
|
});
|
|
557
|
+
const payload = await response.json().catch(() => undefined);
|
|
558
|
+
return { response, payload };
|
|
574
559
|
}
|
|
575
560
|
function printInvalidResponse() {
|
|
576
561
|
console.log(JSON.stringify({ ok: false, error: "invalid_response" }, null, 2));
|
|
@@ -579,108 +564,102 @@ function printInvalidResponse() {
|
|
|
579
564
|
* `agent-sdk call <tool>` — deterministic tool invocation over
|
|
580
565
|
* `POST /v1/tools/:toolName` (ephemeral local server unless --url).
|
|
581
566
|
*/
|
|
582
|
-
export function cmdCall(options) {
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
if (options.toolInput !== undefined) {
|
|
590
|
-
try {
|
|
591
|
-
input = JSON.parse(options.toolInput);
|
|
592
|
-
}
|
|
593
|
-
catch (error) {
|
|
594
|
-
die(`--input must be valid JSON: ${error instanceof Error ? error.message : String(error)}`);
|
|
595
|
-
}
|
|
596
|
-
}
|
|
597
|
-
let target;
|
|
567
|
+
export async function cmdCall(options) {
|
|
568
|
+
const toolName = options.toolName;
|
|
569
|
+
if (toolName === undefined || toolName === "") {
|
|
570
|
+
die(`Provide a tool name: ${CLI_COMMAND_NAME} call <tool> [--input '{...}']`);
|
|
571
|
+
}
|
|
572
|
+
let input = {};
|
|
573
|
+
if (options.toolInput !== undefined) {
|
|
598
574
|
try {
|
|
599
|
-
|
|
575
|
+
input = JSON.parse(options.toolInput);
|
|
600
576
|
}
|
|
601
577
|
catch (error) {
|
|
602
|
-
|
|
603
|
-
return 1;
|
|
578
|
+
die(`--input must be valid JSON: ${error instanceof Error ? error.message : String(error)}`);
|
|
604
579
|
}
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
}
|
|
619
|
-
console.log(JSON.stringify(payload, null, 2));
|
|
620
|
-
const ok = response.ok &&
|
|
621
|
-
typeof payload === "object" &&
|
|
622
|
-
payload !== null &&
|
|
623
|
-
payload.ok === true;
|
|
624
|
-
return ok ? 0 : 1;
|
|
580
|
+
}
|
|
581
|
+
let target;
|
|
582
|
+
try {
|
|
583
|
+
target = await resolveTarget(options);
|
|
584
|
+
}
|
|
585
|
+
catch (error) {
|
|
586
|
+
process.stderr.write(`${sanitizeCustomerError(error instanceof Error ? error.message : String(error))}\n`);
|
|
587
|
+
return 1;
|
|
588
|
+
}
|
|
589
|
+
try {
|
|
590
|
+
const body = { input };
|
|
591
|
+
if (options.sessionId !== undefined) {
|
|
592
|
+
body.sessionId = options.sessionId;
|
|
625
593
|
}
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
594
|
+
const { response, payload } = await fetchAgentJson(target, `/v1/tools/${encodeURIComponent(toolName)}`, {
|
|
595
|
+
method: "POST",
|
|
596
|
+
body: JSON.stringify(body),
|
|
597
|
+
bearerToken: options.bearerToken,
|
|
598
|
+
});
|
|
599
|
+
if (payload === undefined) {
|
|
600
|
+
printInvalidResponse();
|
|
601
|
+
return 1;
|
|
630
602
|
}
|
|
631
|
-
|
|
603
|
+
console.log(JSON.stringify(payload, null, 2));
|
|
604
|
+
const ok = response.ok &&
|
|
605
|
+
typeof payload === "object" &&
|
|
606
|
+
payload !== null &&
|
|
607
|
+
payload.ok === true;
|
|
608
|
+
return ok ? 0 : 1;
|
|
609
|
+
}
|
|
610
|
+
finally {
|
|
611
|
+
if (target.close !== undefined) {
|
|
612
|
+
await target.close();
|
|
613
|
+
}
|
|
614
|
+
}
|
|
632
615
|
}
|
|
633
616
|
/**
|
|
634
617
|
* `agent-sdk skill <name>` — deterministic skill read over
|
|
635
618
|
* `GET /v1/skills/:skillName` (ephemeral local server unless --url).
|
|
636
619
|
* `--text` prints the rendered SKILL.md instead of JSON.
|
|
637
620
|
*/
|
|
638
|
-
export function cmdSkill(skillName, options) {
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
621
|
+
export async function cmdSkill(skillName, options) {
|
|
622
|
+
if (skillName === undefined || skillName === "") {
|
|
623
|
+
process.stderr.write(`Usage: ${CLI_COMMAND_NAME} skill <name> [--dir <path> | --url <baseUrl> | --prod]\n`);
|
|
624
|
+
return 2;
|
|
625
|
+
}
|
|
626
|
+
const target = await resolveTarget(options);
|
|
627
|
+
try {
|
|
628
|
+
const { response, payload } = await fetchAgentJson(target, `/v1/skills/${encodeURIComponent(skillName)}`, { bearerToken: options.bearerToken });
|
|
629
|
+
if (payload === undefined) {
|
|
630
|
+
printInvalidResponse();
|
|
631
|
+
return 1;
|
|
643
632
|
}
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
if (payload === undefined) {
|
|
633
|
+
if (options.text === true && response.ok) {
|
|
634
|
+
const skillMd = payload.skillMd;
|
|
635
|
+
if (typeof skillMd !== "string") {
|
|
648
636
|
printInvalidResponse();
|
|
649
637
|
return 1;
|
|
650
638
|
}
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
if (typeof skillMd !== "string") {
|
|
654
|
-
printInvalidResponse();
|
|
655
|
-
return 1;
|
|
656
|
-
}
|
|
657
|
-
process.stdout.write(skillMd.endsWith("\n") ? skillMd : `${skillMd}\n`);
|
|
658
|
-
return 0;
|
|
659
|
-
}
|
|
660
|
-
console.log(JSON.stringify(payload, null, 2));
|
|
661
|
-
return response.ok ? 0 : 1;
|
|
639
|
+
process.stdout.write(skillMd.endsWith("\n") ? skillMd : `${skillMd}\n`);
|
|
640
|
+
return 0;
|
|
662
641
|
}
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
642
|
+
console.log(JSON.stringify(payload, null, 2));
|
|
643
|
+
return response.ok ? 0 : 1;
|
|
644
|
+
}
|
|
645
|
+
finally {
|
|
646
|
+
if (target.close !== undefined) {
|
|
647
|
+
await target.close();
|
|
667
648
|
}
|
|
668
|
-
}
|
|
649
|
+
}
|
|
669
650
|
}
|
|
670
|
-
export function cmdTrajectory(options) {
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
return trajectory.ok ? 0 : 1;
|
|
683
|
-
});
|
|
651
|
+
export async function cmdTrajectory(options) {
|
|
652
|
+
if (typeof options.events !== "string") {
|
|
653
|
+
die(`trajectory requires --events <file.ndjson> (write one with: ${CLI_COMMAND_NAME} run --events …)`);
|
|
654
|
+
}
|
|
655
|
+
const trajectory = await loadTrajectoryFromEventsFile(resolve(options.events));
|
|
656
|
+
if (options.text) {
|
|
657
|
+
process.stdout.write(formatTrajectoryText(trajectory));
|
|
658
|
+
}
|
|
659
|
+
else {
|
|
660
|
+
console.log(JSON.stringify(trajectory, null, 2));
|
|
661
|
+
}
|
|
662
|
+
return trajectory.ok ? 0 : 1;
|
|
684
663
|
}
|
|
685
664
|
/**
|
|
686
665
|
* Which surface `eval` should target: an ephemeral local server by default,
|
|
@@ -696,199 +675,193 @@ export function resolveEvalTargetMode(options) {
|
|
|
696
675
|
return options.url === undefined ? "local" : "url";
|
|
697
676
|
}
|
|
698
677
|
/** Resolve the eval target; prints a CLI-ready error and returns an exit code on failure. */
|
|
699
|
-
function resolveEvalTarget(options) {
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
678
|
+
async function resolveEvalTarget(options) {
|
|
679
|
+
const mode = resolveEvalTargetMode(options);
|
|
680
|
+
if (typeof mode === "object") {
|
|
681
|
+
process.stderr.write(`${mode.error}\n`);
|
|
682
|
+
return 2;
|
|
683
|
+
}
|
|
684
|
+
if (mode === "url") {
|
|
685
|
+
return { agentUrl: options.url.replace(/\/$/, "") };
|
|
686
|
+
}
|
|
687
|
+
return startEphemeral(options, true);
|
|
688
|
+
}
|
|
689
|
+
export async function cmdEval(options) {
|
|
690
|
+
const projectRoot = resolve(options.cwd ?? process.cwd(), options.dir);
|
|
691
|
+
const mode = resolveEvalTargetMode(options);
|
|
692
|
+
if (typeof mode === "object") {
|
|
693
|
+
process.stderr.write(`${mode.error}\n`);
|
|
694
|
+
return 2;
|
|
695
|
+
}
|
|
696
|
+
if (options.noWait === true) {
|
|
697
|
+
if (options.list === true) {
|
|
698
|
+
process.stderr.write("--no-wait and --list are mutually exclusive\n");
|
|
704
699
|
return 2;
|
|
705
700
|
}
|
|
706
|
-
if (mode === "
|
|
707
|
-
|
|
701
|
+
if (mode === "local") {
|
|
702
|
+
process.stderr.write("--no-wait requires --url (not the default local target)\n");
|
|
703
|
+
return 2;
|
|
708
704
|
}
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
714
|
-
var _a;
|
|
715
|
-
var _b;
|
|
716
|
-
const projectRoot = resolve((_b = options.cwd) !== null && _b !== void 0 ? _b : process.cwd(), options.dir);
|
|
717
|
-
const mode = resolveEvalTargetMode(options);
|
|
718
|
-
if (typeof mode === "object") {
|
|
719
|
-
process.stderr.write(`${mode.error}\n`);
|
|
705
|
+
}
|
|
706
|
+
if (trimNonEmpty(options.out) !== undefined) {
|
|
707
|
+
if (options.list === true) {
|
|
708
|
+
process.stderr.write("--out and --list are mutually exclusive\n");
|
|
720
709
|
return 2;
|
|
721
710
|
}
|
|
722
711
|
if (options.noWait === true) {
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
return 2;
|
|
726
|
-
}
|
|
727
|
-
if (mode === "local") {
|
|
728
|
-
process.stderr.write("--no-wait requires --url (not the default local target)\n");
|
|
729
|
-
return 2;
|
|
730
|
-
}
|
|
712
|
+
process.stderr.write(`--out needs the finished results; drop --no-wait, or poll later with ${CLI_COMMAND_NAME} eval status <evalId> --out <path>\n`);
|
|
713
|
+
return 2;
|
|
731
714
|
}
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
}
|
|
715
|
+
}
|
|
716
|
+
const filterIds = options.evalIds === undefined || options.evalIds.length === 0 ? undefined : options.evalIds;
|
|
717
|
+
const tags = options.tags === undefined || options.tags.length === 0 ? undefined : options.tags;
|
|
718
|
+
if (options.list) {
|
|
719
|
+
// List the same surface a run will execute: local filesystem by default,
|
|
720
|
+
// GET /v1/dev/evals on --url.
|
|
721
|
+
if (mode === "local") {
|
|
722
|
+
return listLocalEvals(projectRoot, options, filterIds, tags);
|
|
741
723
|
}
|
|
742
|
-
const
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
724
|
+
const target = await resolveEvalTarget(options);
|
|
725
|
+
if (typeof target === "number") {
|
|
726
|
+
return target;
|
|
727
|
+
}
|
|
728
|
+
try {
|
|
729
|
+
const listed = await listRemoteEvals({
|
|
730
|
+
baseUrl: target.agentUrl,
|
|
731
|
+
auth: {
|
|
732
|
+
bearerToken: options.bearerToken,
|
|
733
|
+
headers: target.headers,
|
|
734
|
+
},
|
|
735
|
+
fetchImpl: options.fetchImpl,
|
|
736
|
+
filterIds,
|
|
737
|
+
tags,
|
|
738
|
+
});
|
|
739
|
+
return printListedEvals(listed.map(e => ({
|
|
740
|
+
id: e.id,
|
|
741
|
+
fileId: e.fileId,
|
|
742
|
+
description: e.description,
|
|
743
|
+
tags: e.tags ?? [],
|
|
744
|
+
})), options, `No evals on ${target.agentUrl}`);
|
|
745
|
+
}
|
|
746
|
+
catch (error) {
|
|
747
|
+
process.stderr.write(`${sanitizeCustomerError(error instanceof Error ? error.message : String(error))}\n`);
|
|
748
|
+
return 1;
|
|
749
|
+
}
|
|
750
|
+
finally {
|
|
751
|
+
if (target.close !== undefined) {
|
|
752
|
+
await target.close();
|
|
753
753
|
}
|
|
754
|
+
}
|
|
755
|
+
}
|
|
756
|
+
const target = await resolveEvalTarget(options);
|
|
757
|
+
if (typeof target === "number") {
|
|
758
|
+
return target;
|
|
759
|
+
}
|
|
760
|
+
const stream = shouldStreamProgress(options);
|
|
761
|
+
try {
|
|
762
|
+
if (options.verbose || stream) {
|
|
763
|
+
process.stderr.write(`eval target: ${target.agentUrl}\n`);
|
|
764
|
+
}
|
|
765
|
+
// Default local: ephemeral in-process harness against local eval sources.
|
|
766
|
+
// --url: run on the serve process via /v1/dev/evals/runs so the
|
|
767
|
+
// batch lands in playground history and defineStorage evals (when set).
|
|
768
|
+
if (mode === "local") {
|
|
769
|
+
const progress = stream ? createStreamProgress() : undefined;
|
|
770
|
+
const artifactsDir = resolveEvalArtifactsDir(projectRoot, options);
|
|
754
771
|
try {
|
|
755
|
-
const
|
|
772
|
+
const results = await runDiscoveredEvals({
|
|
773
|
+
projectRoot,
|
|
756
774
|
baseUrl: target.agentUrl,
|
|
757
|
-
auth: {
|
|
758
|
-
bearerToken: options.bearerToken,
|
|
759
|
-
headers: target.headers,
|
|
760
|
-
},
|
|
761
|
-
fetchImpl: options.fetchImpl,
|
|
762
775
|
filterIds,
|
|
763
776
|
tags,
|
|
777
|
+
timeoutMs: options.timeoutMs,
|
|
778
|
+
maxConcurrency: options.maxConcurrency,
|
|
779
|
+
strict: options.strict === true,
|
|
780
|
+
skipReport: options.skipReport === true,
|
|
781
|
+
reporters: buildCliEvalReporters(options, artifactsDir),
|
|
782
|
+
target: { baseUrl: target.agentUrl, mode: "local" },
|
|
783
|
+
bearerToken: options.bearerToken,
|
|
784
|
+
headers: target.headers,
|
|
785
|
+
verbose: Boolean(options.verbose) || stream,
|
|
786
|
+
onEvent: progress === undefined ? undefined : e => progress.onEvent(e),
|
|
764
787
|
});
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
}); }), options, `No evals on ${target.agentUrl}`);
|
|
771
|
-
}
|
|
772
|
-
catch (error) {
|
|
773
|
-
process.stderr.write(`${sanitizeCustomerError(error instanceof Error ? error.message : String(error))}\n`);
|
|
774
|
-
return 1;
|
|
788
|
+
if (results.length === 0) {
|
|
789
|
+
process.stderr.write("No matching evals found.\n");
|
|
790
|
+
return 2;
|
|
791
|
+
}
|
|
792
|
+
return await printEvalResults(results, options, undefined, artifactsDir);
|
|
775
793
|
}
|
|
776
794
|
finally {
|
|
777
|
-
|
|
778
|
-
yield target.close();
|
|
779
|
-
}
|
|
795
|
+
progress?.close();
|
|
780
796
|
}
|
|
781
797
|
}
|
|
782
|
-
const target = yield resolveEvalTarget(options);
|
|
783
|
-
if (typeof target === "number") {
|
|
784
|
-
return target;
|
|
785
|
-
}
|
|
786
|
-
const stream = shouldStreamProgress(options);
|
|
787
798
|
try {
|
|
788
|
-
if (options.
|
|
789
|
-
|
|
790
|
-
}
|
|
791
|
-
// Default local: ephemeral in-process harness against local eval sources.
|
|
792
|
-
// --url: run on the serve process via /v1/dev/evals/runs so the
|
|
793
|
-
// batch lands in playground history and defineStorage evals (when set).
|
|
794
|
-
if (mode === "local") {
|
|
795
|
-
const progress = stream ? createStreamProgress() : undefined;
|
|
796
|
-
const artifactsDir = resolveEvalArtifactsDir(projectRoot, options);
|
|
797
|
-
try {
|
|
798
|
-
const results = yield runDiscoveredEvals({
|
|
799
|
-
projectRoot,
|
|
800
|
-
baseUrl: target.agentUrl,
|
|
801
|
-
filterIds,
|
|
802
|
-
tags,
|
|
803
|
-
timeoutMs: options.timeoutMs,
|
|
804
|
-
maxConcurrency: options.maxConcurrency,
|
|
805
|
-
strict: options.strict === true,
|
|
806
|
-
skipReport: options.skipReport === true,
|
|
807
|
-
reporters: buildCliEvalReporters(options, artifactsDir),
|
|
808
|
-
target: { baseUrl: target.agentUrl, mode: "local" },
|
|
809
|
-
bearerToken: options.bearerToken,
|
|
810
|
-
headers: target.headers,
|
|
811
|
-
verbose: Boolean(options.verbose) || stream,
|
|
812
|
-
onEvent: progress === undefined ? undefined : e => progress.onEvent(e),
|
|
813
|
-
});
|
|
814
|
-
if (results.length === 0) {
|
|
815
|
-
process.stderr.write("No matching evals found.\n");
|
|
816
|
-
return 2;
|
|
817
|
-
}
|
|
818
|
-
return yield printEvalResults(results, options, undefined, artifactsDir);
|
|
819
|
-
}
|
|
820
|
-
finally {
|
|
821
|
-
progress === null || progress === void 0 ? void 0 : progress.close();
|
|
822
|
-
}
|
|
823
|
-
}
|
|
824
|
-
try {
|
|
825
|
-
if (options.noWait === true) {
|
|
826
|
-
const started = yield startRemoteEvalRun({
|
|
827
|
-
baseUrl: target.agentUrl,
|
|
828
|
-
filterIds,
|
|
829
|
-
tags,
|
|
830
|
-
timeoutMs: options.timeoutMs,
|
|
831
|
-
verbose: Boolean(options.verbose),
|
|
832
|
-
auth: {
|
|
833
|
-
bearerToken: options.bearerToken,
|
|
834
|
-
headers: target.headers,
|
|
835
|
-
},
|
|
836
|
-
fetchImpl: options.fetchImpl,
|
|
837
|
-
});
|
|
838
|
-
return printEvalAccepted(started, options, target.agentUrl);
|
|
839
|
-
}
|
|
840
|
-
const progress = createRemoteEvalProgress(options.verbose === true || stream);
|
|
841
|
-
// Start first so we can print the Eval ID before the (often long) wait.
|
|
842
|
-
const started = yield startRemoteEvalRun({
|
|
799
|
+
if (options.noWait === true) {
|
|
800
|
+
const started = await startRemoteEvalRun({
|
|
843
801
|
baseUrl: target.agentUrl,
|
|
844
802
|
filterIds,
|
|
845
803
|
tags,
|
|
846
804
|
timeoutMs: options.timeoutMs,
|
|
847
|
-
verbose: Boolean(options.verbose)
|
|
848
|
-
auth: {
|
|
849
|
-
bearerToken: options.bearerToken,
|
|
850
|
-
headers: target.headers,
|
|
851
|
-
},
|
|
852
|
-
fetchImpl: options.fetchImpl,
|
|
853
|
-
});
|
|
854
|
-
printEvalIdBanner(started, options, target.agentUrl);
|
|
855
|
-
(_a = progress === null || progress === void 0 ? void 0 : progress.onSnapshot) === null || _a === void 0 ? void 0 : _a.call(progress, started);
|
|
856
|
-
const snapshot = yield pollRemoteEvalRun({
|
|
857
|
-
baseUrl: target.agentUrl,
|
|
858
|
-
runId: started.runId,
|
|
805
|
+
verbose: Boolean(options.verbose),
|
|
859
806
|
auth: {
|
|
860
807
|
bearerToken: options.bearerToken,
|
|
861
808
|
headers: target.headers,
|
|
862
809
|
},
|
|
863
810
|
fetchImpl: options.fetchImpl,
|
|
864
|
-
onSnapshot: progress === undefined ? undefined : progress.onSnapshot,
|
|
865
|
-
});
|
|
866
|
-
const results = snapshotToEvalRunResults(snapshot);
|
|
867
|
-
if (results.length === 0 && snapshot.status !== "failed") {
|
|
868
|
-
process.stderr.write("No matching evals found.\n");
|
|
869
|
-
return 2;
|
|
870
|
-
}
|
|
871
|
-
return yield printEvalResults(results, options, {
|
|
872
|
-
runId: snapshot.runId,
|
|
873
|
-
status: snapshot.status,
|
|
874
|
-
error: snapshot.error,
|
|
875
811
|
});
|
|
812
|
+
return printEvalAccepted(started, options, target.agentUrl);
|
|
876
813
|
}
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
814
|
+
const progress = createRemoteEvalProgress(options.verbose === true || stream);
|
|
815
|
+
// Start first so we can print the Eval ID before the (often long) wait.
|
|
816
|
+
const started = await startRemoteEvalRun({
|
|
817
|
+
baseUrl: target.agentUrl,
|
|
818
|
+
filterIds,
|
|
819
|
+
tags,
|
|
820
|
+
timeoutMs: options.timeoutMs,
|
|
821
|
+
verbose: Boolean(options.verbose) || stream,
|
|
822
|
+
auth: {
|
|
823
|
+
bearerToken: options.bearerToken,
|
|
824
|
+
headers: target.headers,
|
|
825
|
+
},
|
|
826
|
+
fetchImpl: options.fetchImpl,
|
|
827
|
+
});
|
|
828
|
+
printEvalIdBanner(started, options, target.agentUrl);
|
|
829
|
+
progress?.onSnapshot?.(started);
|
|
830
|
+
const snapshot = await pollRemoteEvalRun({
|
|
831
|
+
baseUrl: target.agentUrl,
|
|
832
|
+
runId: started.runId,
|
|
833
|
+
auth: {
|
|
834
|
+
bearerToken: options.bearerToken,
|
|
835
|
+
headers: target.headers,
|
|
836
|
+
},
|
|
837
|
+
fetchImpl: options.fetchImpl,
|
|
838
|
+
onSnapshot: progress === undefined ? undefined : progress.onSnapshot,
|
|
839
|
+
});
|
|
840
|
+
const results = snapshotToEvalRunResults(snapshot);
|
|
841
|
+
if (results.length === 0 && snapshot.status !== "failed") {
|
|
842
|
+
process.stderr.write("No matching evals found.\n");
|
|
843
|
+
return 2;
|
|
884
844
|
}
|
|
845
|
+
return await printEvalResults(results, options, {
|
|
846
|
+
runId: snapshot.runId,
|
|
847
|
+
status: snapshot.status,
|
|
848
|
+
error: snapshot.error,
|
|
849
|
+
});
|
|
885
850
|
}
|
|
886
|
-
|
|
887
|
-
if (
|
|
888
|
-
|
|
851
|
+
catch (error) {
|
|
852
|
+
if (error instanceof RemoteEvalError && error.code === "no_matching_evals") {
|
|
853
|
+
process.stderr.write(`${error.message}\n`);
|
|
854
|
+
return 2;
|
|
889
855
|
}
|
|
856
|
+
process.stderr.write(`${sanitizeCustomerError(error instanceof Error ? error.message : String(error))}\n`);
|
|
857
|
+
return 1;
|
|
890
858
|
}
|
|
891
|
-
}
|
|
859
|
+
}
|
|
860
|
+
finally {
|
|
861
|
+
if (target.close !== undefined) {
|
|
862
|
+
await target.close();
|
|
863
|
+
}
|
|
864
|
+
}
|
|
892
865
|
}
|
|
893
866
|
/** Print Eval ID + cancel/status hints after a remote batch is accepted. */
|
|
894
867
|
function printEvalIdBanner(started, options, agentUrl) {
|
|
@@ -897,7 +870,14 @@ function printEvalIdBanner(started, options, agentUrl) {
|
|
|
897
870
|
const playgroundUrl = evalPlaygroundDeepLink(started.runId, agentUrl);
|
|
898
871
|
if (options.json) {
|
|
899
872
|
// Waiters still want the id on stderr so progress text stays readable.
|
|
900
|
-
process.stderr.write(`${JSON.stringify(
|
|
873
|
+
process.stderr.write(`${JSON.stringify({
|
|
874
|
+
evalId: started.runId,
|
|
875
|
+
runId: started.runId,
|
|
876
|
+
status: started.status,
|
|
877
|
+
summary: started.summary,
|
|
878
|
+
pollUrl: pollPath,
|
|
879
|
+
...(playgroundUrl === undefined ? {} : { playgroundUrl }),
|
|
880
|
+
})}\n`);
|
|
901
881
|
return;
|
|
902
882
|
}
|
|
903
883
|
const durable = started.config.durableRuns === true ? " (persisted)" : "";
|
|
@@ -914,7 +894,17 @@ function printEvalAccepted(started, options, agentUrl) {
|
|
|
914
894
|
const statusFlags = ` --url ${agentUrl.replace(/\/$/, "")}`;
|
|
915
895
|
const playgroundUrl = evalPlaygroundDeepLink(started.runId, agentUrl);
|
|
916
896
|
if (options.json) {
|
|
917
|
-
process.stdout.write(`${JSON.stringify(
|
|
897
|
+
process.stdout.write(`${JSON.stringify({
|
|
898
|
+
ok: true,
|
|
899
|
+
accepted: true,
|
|
900
|
+
evalId: started.runId,
|
|
901
|
+
runId: started.runId,
|
|
902
|
+
status: started.status,
|
|
903
|
+
summary: started.summary,
|
|
904
|
+
pollUrl: pollPath,
|
|
905
|
+
durableRuns: started.config.durableRuns === true,
|
|
906
|
+
...(playgroundUrl === undefined ? {} : { playgroundUrl }),
|
|
907
|
+
}, null, 2)}\n`);
|
|
918
908
|
}
|
|
919
909
|
else {
|
|
920
910
|
const durable = started.config.durableRuns === true ? " (persisted)" : "";
|
|
@@ -939,64 +929,62 @@ function evalPlaygroundDeepLink(runId, agentUrl) {
|
|
|
939
929
|
url.searchParams.set("evalRunId", runId);
|
|
940
930
|
return url.toString();
|
|
941
931
|
}
|
|
942
|
-
catch
|
|
932
|
+
catch {
|
|
943
933
|
return undefined;
|
|
944
934
|
}
|
|
945
935
|
}
|
|
946
936
|
/**
|
|
947
937
|
* `eval cancel <runId>` — cancel a running remote batch by Eval ID.
|
|
948
938
|
*/
|
|
949
|
-
export function cmdEvalCancel(runId, options) {
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
process.stdout.write(`${JSON.stringify(snap, null, 2)}\n`);
|
|
984
|
-
}
|
|
985
|
-
else {
|
|
986
|
-
process.stdout.write(`Cancelled Eval ID ${snap.runId} (${snap.summary.done}/${snap.summary.total} cases finalized)\n`);
|
|
987
|
-
}
|
|
988
|
-
return 0;
|
|
939
|
+
export async function cmdEvalCancel(runId, options) {
|
|
940
|
+
const mode = resolveEvalTargetMode(options);
|
|
941
|
+
if (typeof mode === "object") {
|
|
942
|
+
process.stderr.write(`${mode.error}\n`);
|
|
943
|
+
return 2;
|
|
944
|
+
}
|
|
945
|
+
if (mode === "local") {
|
|
946
|
+
process.stderr.write("eval cancel requires --url (not the default local target)\n");
|
|
947
|
+
return 2;
|
|
948
|
+
}
|
|
949
|
+
if (runId === undefined || runId === "") {
|
|
950
|
+
process.stderr.write("usage: eval cancel <evalId> --url <baseUrl>\n");
|
|
951
|
+
return 2;
|
|
952
|
+
}
|
|
953
|
+
if (options.list === true || options.noWait === true) {
|
|
954
|
+
process.stderr.write("eval cancel does not accept --list or --no-wait\n");
|
|
955
|
+
return 2;
|
|
956
|
+
}
|
|
957
|
+
const target = await resolveEvalTarget(options);
|
|
958
|
+
if (typeof target === "number") {
|
|
959
|
+
return target;
|
|
960
|
+
}
|
|
961
|
+
try {
|
|
962
|
+
const snap = await cancelRemoteEvalRun({
|
|
963
|
+
baseUrl: target.agentUrl,
|
|
964
|
+
runId,
|
|
965
|
+
auth: {
|
|
966
|
+
bearerToken: options.bearerToken,
|
|
967
|
+
headers: target.headers,
|
|
968
|
+
},
|
|
969
|
+
fetchImpl: options.fetchImpl,
|
|
970
|
+
});
|
|
971
|
+
if (options.json) {
|
|
972
|
+
process.stdout.write(`${JSON.stringify(snap, null, 2)}\n`);
|
|
989
973
|
}
|
|
990
|
-
|
|
991
|
-
process.
|
|
992
|
-
return 1;
|
|
974
|
+
else {
|
|
975
|
+
process.stdout.write(`Cancelled Eval ID ${snap.runId} (${snap.summary.done}/${snap.summary.total} cases finalized)\n`);
|
|
993
976
|
}
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
977
|
+
return 0;
|
|
978
|
+
}
|
|
979
|
+
catch (error) {
|
|
980
|
+
process.stderr.write(`${sanitizeCustomerError(error instanceof Error ? error.message : String(error))}\n`);
|
|
981
|
+
return 1;
|
|
982
|
+
}
|
|
983
|
+
finally {
|
|
984
|
+
if (target.close !== undefined) {
|
|
985
|
+
await target.close();
|
|
998
986
|
}
|
|
999
|
-
}
|
|
987
|
+
}
|
|
1000
988
|
}
|
|
1001
989
|
/**
|
|
1002
990
|
* `eval status [runId]` — fetch one batch (or list recent) on the `--url`
|
|
@@ -1004,122 +992,118 @@ export function cmdEvalCancel(runId, options) {
|
|
|
1004
992
|
* `1` when failed / any case failed / unknown, `2` for usage errors, `3` when
|
|
1005
993
|
* the batch is still running (for poll loops after `--no-wait`).
|
|
1006
994
|
*/
|
|
1007
|
-
export function cmdEvalStatus(runId, options) {
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
const { runs, activeRunId } = yield listRemoteEvalRuns({
|
|
1037
|
-
baseUrl: target.agentUrl,
|
|
1038
|
-
auth,
|
|
1039
|
-
fetchImpl: options.fetchImpl,
|
|
1040
|
-
});
|
|
1041
|
-
if (options.json) {
|
|
1042
|
-
process.stdout.write(`${JSON.stringify({ runs, activeRunId }, null, 2)}\n`);
|
|
1043
|
-
}
|
|
1044
|
-
else if (runs.length === 0) {
|
|
1045
|
-
process.stdout.write("No eval runs on this agent.\n");
|
|
1046
|
-
}
|
|
1047
|
-
else {
|
|
1048
|
-
if (activeRunId !== undefined) {
|
|
1049
|
-
process.stdout.write(`active: ${activeRunId}\n`);
|
|
1050
|
-
}
|
|
1051
|
-
for (const run of runs) {
|
|
1052
|
-
process.stdout.write(`${formatEvalRunSummaryLine(run)}\n`);
|
|
1053
|
-
}
|
|
1054
|
-
}
|
|
1055
|
-
return 0;
|
|
1056
|
-
}
|
|
1057
|
-
const snap = yield getRemoteEvalRun({
|
|
995
|
+
export async function cmdEvalStatus(runId, options) {
|
|
996
|
+
const mode = resolveEvalTargetMode(options);
|
|
997
|
+
if (typeof mode === "object") {
|
|
998
|
+
process.stderr.write(`${mode.error}\n`);
|
|
999
|
+
return 2;
|
|
1000
|
+
}
|
|
1001
|
+
if (mode === "local") {
|
|
1002
|
+
process.stderr.write("eval status requires --url (not the default local target)\n");
|
|
1003
|
+
return 2;
|
|
1004
|
+
}
|
|
1005
|
+
if (options.list === true || options.noWait === true) {
|
|
1006
|
+
process.stderr.write("eval status does not accept --list or --no-wait\n");
|
|
1007
|
+
return 2;
|
|
1008
|
+
}
|
|
1009
|
+
if (trimNonEmpty(options.out) !== undefined && (runId === undefined || runId === "")) {
|
|
1010
|
+
process.stderr.write("eval status --out requires an eval id\n");
|
|
1011
|
+
return 2;
|
|
1012
|
+
}
|
|
1013
|
+
const target = await resolveEvalTarget(options);
|
|
1014
|
+
if (typeof target === "number") {
|
|
1015
|
+
return target;
|
|
1016
|
+
}
|
|
1017
|
+
const auth = {
|
|
1018
|
+
bearerToken: options.bearerToken,
|
|
1019
|
+
headers: target.headers,
|
|
1020
|
+
};
|
|
1021
|
+
try {
|
|
1022
|
+
if (runId === undefined || runId === "") {
|
|
1023
|
+
const { runs, activeRunId } = await listRemoteEvalRuns({
|
|
1058
1024
|
baseUrl: target.agentUrl,
|
|
1059
|
-
runId,
|
|
1060
1025
|
auth,
|
|
1061
1026
|
fetchImpl: options.fetchImpl,
|
|
1062
1027
|
});
|
|
1063
|
-
const outPath = yield writeJsonOutFile(options.out, snap);
|
|
1064
1028
|
if (options.json) {
|
|
1065
|
-
process.stdout.write(`${JSON.stringify(
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1029
|
+
process.stdout.write(`${JSON.stringify({ runs, activeRunId }, null, 2)}\n`);
|
|
1030
|
+
}
|
|
1031
|
+
else if (runs.length === 0) {
|
|
1032
|
+
process.stdout.write("No eval runs on this agent.\n");
|
|
1069
1033
|
}
|
|
1070
1034
|
else {
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
process.stdout.write(`error: ${snap.error}\n`);
|
|
1035
|
+
if (activeRunId !== undefined) {
|
|
1036
|
+
process.stdout.write(`active: ${activeRunId}\n`);
|
|
1074
1037
|
}
|
|
1075
|
-
for (const
|
|
1076
|
-
|
|
1077
|
-
const dur = c.durationMs === undefined ? "" : ` (${(c.durationMs / 1000).toFixed(1)}s)`;
|
|
1078
|
-
process.stdout.write(` ${mark} ${c.id}${dur}\n`);
|
|
1079
|
-
if (c.error !== undefined && c.error !== "") {
|
|
1080
|
-
process.stdout.write(` error: ${c.error}\n`);
|
|
1081
|
-
}
|
|
1038
|
+
for (const run of runs) {
|
|
1039
|
+
process.stdout.write(`${formatEvalRunSummaryLine(run)}\n`);
|
|
1082
1040
|
}
|
|
1083
|
-
|
|
1084
|
-
|
|
1041
|
+
}
|
|
1042
|
+
return 0;
|
|
1043
|
+
}
|
|
1044
|
+
const snap = await getRemoteEvalRun({
|
|
1045
|
+
baseUrl: target.agentUrl,
|
|
1046
|
+
runId,
|
|
1047
|
+
auth,
|
|
1048
|
+
fetchImpl: options.fetchImpl,
|
|
1049
|
+
});
|
|
1050
|
+
const outPath = await writeJsonOutFile(options.out, snap);
|
|
1051
|
+
if (options.json) {
|
|
1052
|
+
process.stdout.write(`${JSON.stringify(snap, null, 2)}\n`);
|
|
1053
|
+
if (outPath !== undefined) {
|
|
1054
|
+
process.stderr.write(`results: ${outPath}\n`);
|
|
1055
|
+
}
|
|
1056
|
+
}
|
|
1057
|
+
else {
|
|
1058
|
+
process.stdout.write(`${formatEvalRunSummaryLine(snap)}\n`);
|
|
1059
|
+
if (snap.error !== undefined && snap.error !== "") {
|
|
1060
|
+
process.stdout.write(`error: ${snap.error}\n`);
|
|
1061
|
+
}
|
|
1062
|
+
for (const c of snap.cases) {
|
|
1063
|
+
const mark = c.status !== "done" ? c.status : c.ok === true ? "PASS" : "FAIL";
|
|
1064
|
+
const dur = c.durationMs === undefined ? "" : ` (${(c.durationMs / 1000).toFixed(1)}s)`;
|
|
1065
|
+
process.stdout.write(` ${mark} ${c.id}${dur}\n`);
|
|
1066
|
+
if (c.error !== undefined && c.error !== "") {
|
|
1067
|
+
process.stdout.write(` error: ${c.error}\n`);
|
|
1085
1068
|
}
|
|
1086
1069
|
}
|
|
1087
|
-
if (
|
|
1088
|
-
|
|
1070
|
+
if (outPath !== undefined) {
|
|
1071
|
+
process.stdout.write(`results: ${outPath}\n`);
|
|
1089
1072
|
}
|
|
1090
|
-
const failed = snap.status === "failed" ||
|
|
1091
|
-
snap.status === "cancelled" ||
|
|
1092
|
-
snap.cases.some(c => c.ok !== true);
|
|
1093
|
-
return failed ? 1 : 0;
|
|
1094
1073
|
}
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
return 1;
|
|
1074
|
+
if (snap.status === "running") {
|
|
1075
|
+
return 3;
|
|
1098
1076
|
}
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1077
|
+
const failed = snap.status === "failed" ||
|
|
1078
|
+
snap.status === "cancelled" ||
|
|
1079
|
+
snap.cases.some(c => c.ok !== true);
|
|
1080
|
+
return failed ? 1 : 0;
|
|
1081
|
+
}
|
|
1082
|
+
catch (error) {
|
|
1083
|
+
process.stderr.write(`${sanitizeCustomerError(error instanceof Error ? error.message : String(error))}\n`);
|
|
1084
|
+
return 1;
|
|
1085
|
+
}
|
|
1086
|
+
finally {
|
|
1087
|
+
if (target.close !== undefined) {
|
|
1088
|
+
await target.close();
|
|
1103
1089
|
}
|
|
1104
|
-
}
|
|
1090
|
+
}
|
|
1105
1091
|
}
|
|
1106
1092
|
function formatEvalRunSummaryLine(run) {
|
|
1107
1093
|
const { passed, failed, total, done } = run.summary;
|
|
1108
1094
|
const durable = run.config.durableRuns === true ? " persisted" : "";
|
|
1109
1095
|
return `${run.runId} ${run.status} ${done}/${total} done (${passed} passed, ${failed} failed)${durable}`;
|
|
1110
1096
|
}
|
|
1111
|
-
function listLocalEvals(projectRoot, options, filterIds, tags) {
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
}); }), options, `No evals under ${projectRoot}/evals`);
|
|
1122
|
-
});
|
|
1097
|
+
async function listLocalEvals(projectRoot, options, filterIds, tags) {
|
|
1098
|
+
const { evals } = await discoverEvals(projectRoot);
|
|
1099
|
+
const listed = filterDiscoveredEvals(evals, { filterIds, tags });
|
|
1100
|
+
return printListedEvals(listed.map(e => ({
|
|
1101
|
+
id: e.id,
|
|
1102
|
+
fileId: e.fileId,
|
|
1103
|
+
path: e.path,
|
|
1104
|
+
description: e.definition.description,
|
|
1105
|
+
tags: e.definition.tags ?? [],
|
|
1106
|
+
})), options, `No evals under ${projectRoot}/evals`);
|
|
1123
1107
|
}
|
|
1124
1108
|
function printListedEvals(listed, options, emptyMessage) {
|
|
1125
1109
|
if (options.json) {
|
|
@@ -1149,7 +1133,6 @@ function createRemoteEvalProgress(enabled) {
|
|
|
1149
1133
|
const seenCaseKeys = new Set();
|
|
1150
1134
|
return {
|
|
1151
1135
|
onSnapshot(snap) {
|
|
1152
|
-
var _a, _b;
|
|
1153
1136
|
// Eval ID is printed by printEvalIdBanner / printEvalAccepted.
|
|
1154
1137
|
const summaryKey = `${snap.status}:${snap.summary.done}:${snap.summary.passed}:${snap.summary.failed}`;
|
|
1155
1138
|
if (summaryKey !== lastSummaryKey) {
|
|
@@ -1161,13 +1144,13 @@ function createRemoteEvalProgress(enabled) {
|
|
|
1161
1144
|
if (c.status !== "done") {
|
|
1162
1145
|
continue;
|
|
1163
1146
|
}
|
|
1164
|
-
const caseKey = `${c.id}:${c.ok === true ? "pass" : "fail"}:${
|
|
1147
|
+
const caseKey = `${c.id}:${c.ok === true ? "pass" : "fail"}:${c.durationMs ?? 0}`;
|
|
1165
1148
|
if (seenCaseKeys.has(caseKey)) {
|
|
1166
1149
|
continue;
|
|
1167
1150
|
}
|
|
1168
1151
|
seenCaseKeys.add(caseKey);
|
|
1169
1152
|
process.stderr.write(` eval ${c.id}: ${c.ok === true ? "PASS" : "FAIL"}${c.error !== undefined ? ` — ${c.error}` : ""}\n`);
|
|
1170
|
-
for (const line of
|
|
1153
|
+
for (const line of c.logs ?? []) {
|
|
1171
1154
|
process.stderr.write(` ${line}\n`);
|
|
1172
1155
|
}
|
|
1173
1156
|
}
|
|
@@ -1203,8 +1186,7 @@ function buildCliEvalReporters(options, artifactsDir) {
|
|
|
1203
1186
|
return reporters;
|
|
1204
1187
|
}
|
|
1205
1188
|
function evalVerdictOf(result) {
|
|
1206
|
-
|
|
1207
|
-
return (_a = result.verdict) !== null && _a !== void 0 ? _a : (result.ok ? "passed" : "failed");
|
|
1189
|
+
return result.verdict ?? (result.ok ? "passed" : "failed");
|
|
1208
1190
|
}
|
|
1209
1191
|
const EVAL_VERDICT_LABEL = {
|
|
1210
1192
|
passed: "PASS",
|
|
@@ -1212,98 +1194,103 @@ const EVAL_VERDICT_LABEL = {
|
|
|
1212
1194
|
scored: "SCORED",
|
|
1213
1195
|
skipped: "SKIP",
|
|
1214
1196
|
};
|
|
1215
|
-
function printEvalResults(results, options, batch, artifactsDir) {
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1197
|
+
async function printEvalResults(results, options, batch, artifactsDir) {
|
|
1198
|
+
const strict = options.strict === true;
|
|
1199
|
+
const counts = { passed: 0, failed: 0, scored: 0, skipped: 0 };
|
|
1200
|
+
for (const result of results) {
|
|
1201
|
+
counts[evalVerdictOf(result)]++;
|
|
1202
|
+
}
|
|
1203
|
+
const batchFailed = batch?.status === "failed";
|
|
1204
|
+
const ok = counts.failed === 0 && !(strict && counts.scored > 0) && !batchFailed;
|
|
1205
|
+
if (batch?.error !== undefined && batch.error !== "" && !options.json) {
|
|
1206
|
+
// Always surface harness-level failures (not only --verbose).
|
|
1207
|
+
process.stderr.write(`eval run error: ${batch.error}\n`);
|
|
1208
|
+
}
|
|
1209
|
+
const payload = {
|
|
1210
|
+
ok,
|
|
1211
|
+
passed: counts.passed,
|
|
1212
|
+
failed: counts.failed,
|
|
1213
|
+
scored: counts.scored,
|
|
1214
|
+
skipped: counts.skipped,
|
|
1215
|
+
strict,
|
|
1216
|
+
results,
|
|
1217
|
+
...(artifactsDir === undefined ? {} : { artifactsDir }),
|
|
1218
|
+
...(batch?.runId === undefined ? {} : { runId: batch.runId }),
|
|
1219
|
+
...(batch?.status === undefined ? {} : { status: batch.status }),
|
|
1220
|
+
...(batch?.error === undefined || batch.error === "" ? {} : { error: batch.error }),
|
|
1221
|
+
};
|
|
1222
|
+
const outPath = await writeJsonOutFile(options.out, payload);
|
|
1223
|
+
if (options.json) {
|
|
1224
|
+
process.stdout.write(`${JSON.stringify(payload, null, 2)}\n`);
|
|
1225
|
+
if (outPath !== undefined) {
|
|
1226
|
+
// stdout stays pure JSON; report the file on stderr.
|
|
1227
|
+
process.stderr.write(`results: ${outPath}\n`);
|
|
1238
1228
|
}
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
}
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
}
|
|
1250
|
-
for (const a of r.assertions) {
|
|
1251
|
-
process.stdout.write(` ${formatEvalAssertionLine(a)}\n`);
|
|
1252
|
-
}
|
|
1253
|
-
for (const [name, value] of Object.entries((_a = r.metrics) !== null && _a !== void 0 ? _a : {})) {
|
|
1254
|
-
process.stdout.write(` metric ${name}=${String(value)}\n`);
|
|
1255
|
-
}
|
|
1256
|
-
for (const line of (_b = r.logs) !== null && _b !== void 0 ? _b : []) {
|
|
1257
|
-
process.stdout.write(` ${line}\n`);
|
|
1258
|
-
}
|
|
1259
|
-
if (r.error !== undefined) {
|
|
1260
|
-
process.stdout.write(` error: ${r.error}\n`);
|
|
1261
|
-
}
|
|
1262
|
-
if (options.verbose && r.finalText !== undefined) {
|
|
1263
|
-
process.stdout.write(` reply: ${r.finalText.slice(0, 200).replace(/\s+/g, " ")}\n`);
|
|
1264
|
-
}
|
|
1229
|
+
}
|
|
1230
|
+
else {
|
|
1231
|
+
for (const r of results) {
|
|
1232
|
+
const verdict = evalVerdictOf(r);
|
|
1233
|
+
process.stdout.write(`${EVAL_VERDICT_LABEL[verdict]} ${r.id} (${(r.durationMs / 1000).toFixed(1)}s)`);
|
|
1234
|
+
if (r.description !== undefined) {
|
|
1235
|
+
process.stdout.write(` — ${r.description}`);
|
|
1236
|
+
}
|
|
1237
|
+
process.stdout.write("\n");
|
|
1238
|
+
if (r.skipReason !== undefined) {
|
|
1239
|
+
process.stdout.write(` skipped: ${r.skipReason}\n`);
|
|
1265
1240
|
}
|
|
1266
|
-
const
|
|
1267
|
-
|
|
1268
|
-
extra.push(`${counts.scored} scored${strict ? " (fatal: --strict)" : ""}`);
|
|
1241
|
+
for (const a of r.assertions) {
|
|
1242
|
+
process.stdout.write(` ${formatEvalAssertionLine(a)}\n`);
|
|
1269
1243
|
}
|
|
1270
|
-
|
|
1271
|
-
|
|
1244
|
+
for (const [name, value] of Object.entries(r.metrics ?? {})) {
|
|
1245
|
+
process.stdout.write(` metric ${name}=${String(value)}\n`);
|
|
1272
1246
|
}
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
process.stdout.write(`artifacts: ${artifactsDir}\n`);
|
|
1247
|
+
for (const line of r.logs ?? []) {
|
|
1248
|
+
process.stdout.write(` ${line}\n`);
|
|
1276
1249
|
}
|
|
1277
|
-
if (
|
|
1278
|
-
process.stdout.write(`
|
|
1250
|
+
if (r.error !== undefined) {
|
|
1251
|
+
process.stdout.write(` error: ${r.error}\n`);
|
|
1252
|
+
}
|
|
1253
|
+
if (options.verbose && r.finalText !== undefined) {
|
|
1254
|
+
process.stdout.write(` reply: ${r.finalText.slice(0, 200).replace(/\s+/g, " ")}\n`);
|
|
1279
1255
|
}
|
|
1280
1256
|
}
|
|
1281
|
-
|
|
1282
|
-
|
|
1257
|
+
const extra = [];
|
|
1258
|
+
if (counts.scored > 0) {
|
|
1259
|
+
extra.push(`${counts.scored} scored${strict ? " (fatal: --strict)" : ""}`);
|
|
1260
|
+
}
|
|
1261
|
+
if (counts.skipped > 0) {
|
|
1262
|
+
extra.push(`${counts.skipped} skipped`);
|
|
1263
|
+
}
|
|
1264
|
+
process.stdout.write(`\n${counts.passed} passed, ${counts.failed} failed${extra.length === 0 ? "" : `, ${extra.join(", ")}`}, ${results.length} total\n`);
|
|
1265
|
+
if (artifactsDir !== undefined) {
|
|
1266
|
+
process.stdout.write(`artifacts: ${artifactsDir}\n`);
|
|
1267
|
+
}
|
|
1268
|
+
if (outPath !== undefined) {
|
|
1269
|
+
process.stdout.write(`results: ${outPath}\n`);
|
|
1270
|
+
}
|
|
1271
|
+
}
|
|
1272
|
+
return ok ? 0 : 1;
|
|
1283
1273
|
}
|
|
1284
1274
|
/**
|
|
1285
1275
|
* `--out <path>`: write a JSON payload (results / run snapshot), creating
|
|
1286
1276
|
* parent directories. Returns the resolved path, or undefined when unset.
|
|
1287
1277
|
*/
|
|
1288
|
-
function writeJsonOutFile(out, payload) {
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
return target;
|
|
1298
|
-
});
|
|
1278
|
+
async function writeJsonOutFile(out, payload) {
|
|
1279
|
+
const trimmed = trimNonEmpty(out);
|
|
1280
|
+
if (trimmed === undefined) {
|
|
1281
|
+
return undefined;
|
|
1282
|
+
}
|
|
1283
|
+
const target = resolve(trimmed);
|
|
1284
|
+
await mkdir(dirname(target), { recursive: true });
|
|
1285
|
+
await writeFile(target, `${JSON.stringify(payload, null, 2)}\n`, "utf8");
|
|
1286
|
+
return target;
|
|
1299
1287
|
}
|
|
1300
1288
|
/**
|
|
1301
1289
|
* One assertion line. Soft assertions read `~` rather than `✗` when they miss,
|
|
1302
1290
|
* so a tracked score is visibly different from a failed gate.
|
|
1303
1291
|
*/
|
|
1304
1292
|
export function formatEvalAssertionLine(assertion) {
|
|
1305
|
-
|
|
1306
|
-
const soft = ((_a = assertion.severity) !== null && _a !== void 0 ? _a : "gate") === "soft";
|
|
1293
|
+
const soft = (assertion.severity ?? "gate") === "soft";
|
|
1307
1294
|
const mark = assertion.passed ? "✓" : soft ? "~" : "✗";
|
|
1308
1295
|
const parts = [];
|
|
1309
1296
|
if (assertion.score !== undefined) {
|
|
@@ -1320,245 +1307,233 @@ export function formatEvalAssertionLine(assertion) {
|
|
|
1320
1307
|
* Local / `--url` tails `/v1/logs` only. On architecture v2, `--prod` tails
|
|
1321
1308
|
* the output of the deployment's recent sessions, or one with `--session`.
|
|
1322
1309
|
*/
|
|
1323
|
-
export function cmdLogs(options) {
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
|
|
1348
|
-
|
|
1349
|
-
|
|
1350
|
-
|
|
1351
|
-
|
|
1352
|
-
|
|
1353
|
-
|
|
1354
|
-
|
|
1355
|
-
|
|
1356
|
-
|
|
1357
|
-
|
|
1358
|
-
|
|
1359
|
-
|
|
1360
|
-
|
|
1361
|
-
if (architecture === "v2") {
|
|
1362
|
-
yield followHostedLogs({
|
|
1363
|
-
slug,
|
|
1364
|
-
read: signal => auth.client.getAgentkitDeploymentLogs({ teamId: auth.teamId, slug, sessionId, signal }),
|
|
1365
|
-
scoped: sessionId !== undefined,
|
|
1366
|
-
once: options.once === true,
|
|
1367
|
-
json: options.json === true,
|
|
1368
|
-
signal: controller.signal,
|
|
1369
|
-
});
|
|
1370
|
-
return 0;
|
|
1371
|
-
}
|
|
1372
|
-
if (sessionId !== undefined) {
|
|
1373
|
-
process.stderr.write(`A session id needs an architecture v2 deployment; "${slug}" is v1\n`);
|
|
1374
|
-
return 2;
|
|
1375
|
-
}
|
|
1376
|
-
yield runLogsTail({
|
|
1377
|
-
prod: true,
|
|
1378
|
-
dir: options.dir,
|
|
1379
|
-
cwd: options.cwd,
|
|
1310
|
+
export async function cmdLogs(options) {
|
|
1311
|
+
if (options.prod === true && options.url !== undefined) {
|
|
1312
|
+
process.stderr.write("--prod and --url are mutually exclusive\n");
|
|
1313
|
+
return 2;
|
|
1314
|
+
}
|
|
1315
|
+
const sessionId = trimNonEmpty(options.sessionId);
|
|
1316
|
+
if (sessionId !== undefined && options.prod !== true) {
|
|
1317
|
+
process.stderr.write("A session id needs --prod on an architecture v2 deployment\n");
|
|
1318
|
+
return 2;
|
|
1319
|
+
}
|
|
1320
|
+
const controller = new AbortController();
|
|
1321
|
+
const onSignal = () => {
|
|
1322
|
+
controller.abort();
|
|
1323
|
+
};
|
|
1324
|
+
process.on("SIGINT", onSignal);
|
|
1325
|
+
process.on("SIGTERM", onSignal);
|
|
1326
|
+
try {
|
|
1327
|
+
if (options.prod === true) {
|
|
1328
|
+
const slug = resolveProdSlug({
|
|
1329
|
+
dir: options.dir,
|
|
1330
|
+
cwd: options.cwd,
|
|
1331
|
+
slug: options.slug,
|
|
1332
|
+
});
|
|
1333
|
+
const auth = await resolveDeployAuth({
|
|
1334
|
+
team: options.team,
|
|
1335
|
+
apiKey: options.apiKey,
|
|
1336
|
+
fetchImpl: options.fetchImpl,
|
|
1337
|
+
});
|
|
1338
|
+
if (typeof auth === "number") {
|
|
1339
|
+
return auth;
|
|
1340
|
+
}
|
|
1341
|
+
const architecture = await deploymentArchitecture({
|
|
1342
|
+
client: auth.client,
|
|
1343
|
+
teamId: auth.teamId,
|
|
1344
|
+
slug,
|
|
1345
|
+
});
|
|
1346
|
+
if (architecture === "v2") {
|
|
1347
|
+
await followHostedLogs({
|
|
1380
1348
|
slug,
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
json: options.json,
|
|
1386
|
-
fetchImpl: options.fetchImpl,
|
|
1349
|
+
read: signal => auth.client.getAgentkitDeploymentLogs({ teamId: auth.teamId, slug, sessionId, signal }),
|
|
1350
|
+
scoped: sessionId !== undefined,
|
|
1351
|
+
once: options.once === true,
|
|
1352
|
+
json: options.json === true,
|
|
1387
1353
|
signal: controller.signal,
|
|
1388
|
-
getDeployment: () => auth.client.getDeployment({ teamId: auth.teamId, slug }),
|
|
1389
|
-
resolveRuntime: () => __awaiter(this, void 0, void 0, function* () {
|
|
1390
|
-
const target = yield resolveProdTarget({
|
|
1391
|
-
dir: options.dir,
|
|
1392
|
-
cwd: options.cwd,
|
|
1393
|
-
slug,
|
|
1394
|
-
team: options.team,
|
|
1395
|
-
apiKey: options.apiKey,
|
|
1396
|
-
fetchImpl: options.fetchImpl,
|
|
1397
|
-
err: () => { },
|
|
1398
|
-
skipLegacyArchitectureCheck: true,
|
|
1399
|
-
});
|
|
1400
|
-
return { agentUrl: target.agentUrl, headers: target.headers };
|
|
1401
|
-
}),
|
|
1402
1354
|
});
|
|
1403
1355
|
return 0;
|
|
1404
1356
|
}
|
|
1405
|
-
|
|
1357
|
+
if (sessionId !== undefined) {
|
|
1358
|
+
process.stderr.write(`A session id needs an architecture v2 deployment; "${slug}" is v1\n`);
|
|
1359
|
+
return 2;
|
|
1360
|
+
}
|
|
1361
|
+
await runLogsTail({
|
|
1362
|
+
prod: true,
|
|
1406
1363
|
dir: options.dir,
|
|
1407
1364
|
cwd: options.cwd,
|
|
1408
|
-
|
|
1365
|
+
slug,
|
|
1366
|
+
team: options.team,
|
|
1367
|
+
apiKey: options.apiKey,
|
|
1409
1368
|
bearerToken: options.bearerToken,
|
|
1410
1369
|
once: options.once,
|
|
1411
1370
|
json: options.json,
|
|
1412
1371
|
fetchImpl: options.fetchImpl,
|
|
1413
1372
|
signal: controller.signal,
|
|
1373
|
+
getDeployment: () => auth.client.getDeployment({ teamId: auth.teamId, slug }),
|
|
1374
|
+
resolveRuntime: async () => {
|
|
1375
|
+
const target = await resolveProdTarget({
|
|
1376
|
+
dir: options.dir,
|
|
1377
|
+
cwd: options.cwd,
|
|
1378
|
+
slug,
|
|
1379
|
+
team: options.team,
|
|
1380
|
+
apiKey: options.apiKey,
|
|
1381
|
+
fetchImpl: options.fetchImpl,
|
|
1382
|
+
err: () => { },
|
|
1383
|
+
skipLegacyArchitectureCheck: true,
|
|
1384
|
+
});
|
|
1385
|
+
return { agentUrl: target.agentUrl, headers: target.headers };
|
|
1386
|
+
},
|
|
1414
1387
|
});
|
|
1415
1388
|
return 0;
|
|
1416
1389
|
}
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
|
|
1420
|
-
|
|
1421
|
-
|
|
1422
|
-
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
|
|
1390
|
+
await runLogsTail({
|
|
1391
|
+
dir: options.dir,
|
|
1392
|
+
cwd: options.cwd,
|
|
1393
|
+
url: options.url ?? "http://127.0.0.1:3000",
|
|
1394
|
+
bearerToken: options.bearerToken,
|
|
1395
|
+
once: options.once,
|
|
1396
|
+
json: options.json,
|
|
1397
|
+
fetchImpl: options.fetchImpl,
|
|
1398
|
+
signal: controller.signal,
|
|
1399
|
+
});
|
|
1400
|
+
return 0;
|
|
1401
|
+
}
|
|
1402
|
+
catch (error) {
|
|
1403
|
+
if (controller.signal.aborted) {
|
|
1404
|
+
return 0;
|
|
1428
1405
|
}
|
|
1429
|
-
|
|
1406
|
+
const raw = error instanceof Error ? error.message : String(error);
|
|
1407
|
+
process.stderr.write(`${sanitizeCustomerError(raw)}\n`);
|
|
1408
|
+
return 1;
|
|
1409
|
+
}
|
|
1410
|
+
finally {
|
|
1411
|
+
process.off("SIGINT", onSignal);
|
|
1412
|
+
process.off("SIGTERM", onSignal);
|
|
1413
|
+
}
|
|
1430
1414
|
}
|
|
1431
1415
|
/** Resolve local / `--url` / `--prod` agent base URL + request headers. */
|
|
1432
|
-
function resolveSessionTarget(options) {
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
}
|
|
1439
|
-
if (options.prod === true) {
|
|
1440
|
-
try {
|
|
1441
|
-
const target = yield resolveProdTarget({
|
|
1442
|
-
dir: options.dir,
|
|
1443
|
-
cwd: options.cwd,
|
|
1444
|
-
slug: options.slug,
|
|
1445
|
-
team: options.team,
|
|
1446
|
-
apiKey: options.apiKey,
|
|
1447
|
-
fetchImpl: options.fetchImpl,
|
|
1448
|
-
});
|
|
1449
|
-
return { agentUrl: target.agentUrl, headers: target.headers };
|
|
1450
|
-
}
|
|
1451
|
-
catch (error) {
|
|
1452
|
-
process.stderr.write(`${sanitizeCustomerError(error instanceof Error ? error.message : String(error))}\n`);
|
|
1453
|
-
return 1;
|
|
1454
|
-
}
|
|
1455
|
-
}
|
|
1456
|
-
return {
|
|
1457
|
-
agentUrl: ((_a = options.url) !== null && _a !== void 0 ? _a : "http://127.0.0.1:3000").replace(/\/$/, ""),
|
|
1458
|
-
};
|
|
1459
|
-
});
|
|
1460
|
-
}
|
|
1461
|
-
/**
|
|
1462
|
-
* `sessions` — list sessions on a running (or `--prod` hosted) agent.
|
|
1463
|
-
*/
|
|
1464
|
-
export function cmdSessions(options) {
|
|
1465
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
1466
|
-
const target = yield resolveSessionTarget(options);
|
|
1467
|
-
if (typeof target === "number") {
|
|
1468
|
-
return target;
|
|
1469
|
-
}
|
|
1416
|
+
async function resolveSessionTarget(options) {
|
|
1417
|
+
if (options.prod === true && options.url !== undefined) {
|
|
1418
|
+
process.stderr.write("--prod and --url are mutually exclusive\n");
|
|
1419
|
+
return 2;
|
|
1420
|
+
}
|
|
1421
|
+
if (options.prod === true) {
|
|
1470
1422
|
try {
|
|
1471
|
-
const
|
|
1472
|
-
|
|
1473
|
-
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
|
|
1423
|
+
const target = await resolveProdTarget({
|
|
1424
|
+
dir: options.dir,
|
|
1425
|
+
cwd: options.cwd,
|
|
1426
|
+
slug: options.slug,
|
|
1427
|
+
team: options.team,
|
|
1428
|
+
apiKey: options.apiKey,
|
|
1477
1429
|
fetchImpl: options.fetchImpl,
|
|
1478
1430
|
});
|
|
1479
|
-
|
|
1480
|
-
const payload = listed.source === undefined
|
|
1481
|
-
? { sessions: listed.sessions }
|
|
1482
|
-
: { sessions: listed.sessions, source: listed.source };
|
|
1483
|
-
process.stdout.write(`${JSON.stringify(payload, null, 2)}\n`);
|
|
1484
|
-
return 0;
|
|
1485
|
-
}
|
|
1486
|
-
process.stdout.write(formatSessionsTable(listed.sessions, { source: listed.source }));
|
|
1487
|
-
return 0;
|
|
1431
|
+
return { agentUrl: target.agentUrl, headers: target.headers };
|
|
1488
1432
|
}
|
|
1489
1433
|
catch (error) {
|
|
1490
1434
|
process.stderr.write(`${sanitizeCustomerError(error instanceof Error ? error.message : String(error))}\n`);
|
|
1491
1435
|
return 1;
|
|
1492
1436
|
}
|
|
1493
|
-
}
|
|
1437
|
+
}
|
|
1438
|
+
return {
|
|
1439
|
+
agentUrl: (options.url ?? "http://127.0.0.1:3000").replace(/\/$/, ""),
|
|
1440
|
+
};
|
|
1441
|
+
}
|
|
1442
|
+
/**
|
|
1443
|
+
* `sessions` — list sessions on a running (or `--prod` hosted) agent.
|
|
1444
|
+
*/
|
|
1445
|
+
export async function cmdSessions(options) {
|
|
1446
|
+
const target = await resolveSessionTarget(options);
|
|
1447
|
+
if (typeof target === "number") {
|
|
1448
|
+
return target;
|
|
1449
|
+
}
|
|
1450
|
+
try {
|
|
1451
|
+
const listed = await listSessionsWithSource({
|
|
1452
|
+
baseUrl: target.agentUrl,
|
|
1453
|
+
auth: {
|
|
1454
|
+
bearerToken: options.bearerToken,
|
|
1455
|
+
headers: target.headers,
|
|
1456
|
+
},
|
|
1457
|
+
fetchImpl: options.fetchImpl,
|
|
1458
|
+
});
|
|
1459
|
+
if (options.json === true) {
|
|
1460
|
+
const payload = listed.source === undefined
|
|
1461
|
+
? { sessions: listed.sessions }
|
|
1462
|
+
: { sessions: listed.sessions, source: listed.source };
|
|
1463
|
+
process.stdout.write(`${JSON.stringify(payload, null, 2)}\n`);
|
|
1464
|
+
return 0;
|
|
1465
|
+
}
|
|
1466
|
+
process.stdout.write(formatSessionsTable(listed.sessions, { source: listed.source }));
|
|
1467
|
+
return 0;
|
|
1468
|
+
}
|
|
1469
|
+
catch (error) {
|
|
1470
|
+
process.stderr.write(`${sanitizeCustomerError(error instanceof Error ? error.message : String(error))}\n`);
|
|
1471
|
+
return 1;
|
|
1472
|
+
}
|
|
1494
1473
|
}
|
|
1495
1474
|
export const HOSTED_RUNS_LAG_NOTE = "Turn running; runs may lag behind events.";
|
|
1496
1475
|
function formatHostedSessionRuns(sessionId, runs, events) {
|
|
1497
|
-
var _a, _b, _c, _d;
|
|
1498
|
-
var _e, _f, _g;
|
|
1499
1476
|
const lines = [`Session ${sessionId}`, `Hosted executions: ${runs.executions.length}`];
|
|
1500
1477
|
for (const run of runs.executions) {
|
|
1501
|
-
const failure =
|
|
1478
|
+
const failure = run.error?.message ?? run.message ?? "";
|
|
1502
1479
|
lines.push("", `${run.executionId} ${run.turnStatus} ${run.durationMs}ms ${run.writtenAt} ${failure}`.trimEnd(), ...run.logs.map(log => ` ${log.line}`));
|
|
1503
1480
|
}
|
|
1504
|
-
const latestType =
|
|
1481
|
+
const latestType = events?.events.at(-1)?.type;
|
|
1505
1482
|
if (events !== undefined && events.events.length > 0) {
|
|
1506
1483
|
const latest = latestType === undefined ? "" : ` (latest ${latestType})`;
|
|
1507
1484
|
lines.push("", `Events: ${events.events.length}${latest}`);
|
|
1508
1485
|
}
|
|
1509
|
-
const turnRunning =
|
|
1510
|
-
(runs.executions.length === 0 &&
|
|
1511
|
-
if (turnRunning && (
|
|
1486
|
+
const turnRunning = runs.executions.at(-1)?.turnStatus === "running" ||
|
|
1487
|
+
(runs.executions.length === 0 && events?.execution?.turnStatus === "running");
|
|
1488
|
+
if (turnRunning && (events?.events.length ?? 0) > 0) {
|
|
1512
1489
|
lines.push(HOSTED_RUNS_LAG_NOTE);
|
|
1513
1490
|
}
|
|
1514
1491
|
return `${lines.join("\n")}\n`;
|
|
1515
1492
|
}
|
|
1516
1493
|
/** Read the v2 runs surface; only its 404 falls through to the v1 engine. */
|
|
1517
|
-
function readHostedSessionRuns(sessionId, options) {
|
|
1518
|
-
|
|
1519
|
-
|
|
1520
|
-
|
|
1521
|
-
|
|
1522
|
-
|
|
1494
|
+
async function readHostedSessionRuns(sessionId, options) {
|
|
1495
|
+
const auth = await resolveDeployAuth({
|
|
1496
|
+
team: options.team,
|
|
1497
|
+
apiKey: options.apiKey,
|
|
1498
|
+
fetchImpl: options.fetchImpl,
|
|
1499
|
+
});
|
|
1500
|
+
if (typeof auth === "number") {
|
|
1501
|
+
return auth;
|
|
1502
|
+
}
|
|
1503
|
+
try {
|
|
1504
|
+
const slug = resolveProdSlug(options);
|
|
1505
|
+
const runs = await auth.client.getAgentkitSessionRuns({
|
|
1506
|
+
teamId: auth.teamId,
|
|
1507
|
+
slug,
|
|
1508
|
+
sessionId,
|
|
1523
1509
|
});
|
|
1524
|
-
if (
|
|
1525
|
-
|
|
1510
|
+
if (options.rawEvents === true || trimNonEmpty(options.out) !== undefined) {
|
|
1511
|
+
process.stderr.write("--events and --out need an engine trajectory.\n");
|
|
1512
|
+
return 2;
|
|
1526
1513
|
}
|
|
1527
|
-
|
|
1528
|
-
|
|
1529
|
-
|
|
1514
|
+
const latest = runs.executions.at(-1);
|
|
1515
|
+
const events = runs.executions.length === 0 || latest?.turnStatus === "running"
|
|
1516
|
+
? await auth.client
|
|
1517
|
+
.getAgentkitSessionEvents({
|
|
1530
1518
|
teamId: auth.teamId,
|
|
1531
1519
|
slug,
|
|
1532
1520
|
sessionId,
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
|
|
1536
|
-
|
|
1537
|
-
|
|
1538
|
-
|
|
1539
|
-
|
|
1540
|
-
|
|
1541
|
-
|
|
1542
|
-
|
|
1543
|
-
|
|
1544
|
-
|
|
1545
|
-
afterEventIndex: -1,
|
|
1546
|
-
})
|
|
1547
|
-
.catch(() => undefined)
|
|
1548
|
-
: undefined;
|
|
1549
|
-
process.stdout.write(options.json === true
|
|
1550
|
-
? `${JSON.stringify(Object.assign({ sessionId }, runs), null, 2)}\n`
|
|
1551
|
-
: formatHostedSessionRuns(sessionId, runs, events));
|
|
1552
|
-
return 0;
|
|
1553
|
-
}
|
|
1554
|
-
catch (error) {
|
|
1555
|
-
if (error instanceof DeployApiError && error.status === 404) {
|
|
1556
|
-
return "v1";
|
|
1557
|
-
}
|
|
1558
|
-
process.stderr.write(`${sanitizeCustomerError(error instanceof Error ? error.message : String(error))}\n`);
|
|
1559
|
-
return 1;
|
|
1521
|
+
afterEventIndex: -1,
|
|
1522
|
+
})
|
|
1523
|
+
.catch(() => undefined)
|
|
1524
|
+
: undefined;
|
|
1525
|
+
process.stdout.write(options.json === true
|
|
1526
|
+
? `${JSON.stringify({ sessionId, ...runs }, null, 2)}\n`
|
|
1527
|
+
: formatHostedSessionRuns(sessionId, runs, events));
|
|
1528
|
+
return 0;
|
|
1529
|
+
}
|
|
1530
|
+
catch (error) {
|
|
1531
|
+
if (error instanceof DeployApiError && error.status === 404) {
|
|
1532
|
+
return "v1";
|
|
1560
1533
|
}
|
|
1561
|
-
|
|
1534
|
+
process.stderr.write(`${sanitizeCustomerError(error instanceof Error ? error.message : String(error))}\n`);
|
|
1535
|
+
return 1;
|
|
1536
|
+
}
|
|
1562
1537
|
}
|
|
1563
1538
|
/**
|
|
1564
1539
|
* `session <id>` — view a full session (trajectory text by default).
|
|
@@ -1567,75 +1542,74 @@ function readHostedSessionRuns(sessionId, options) {
|
|
|
1567
1542
|
* (same format as `run --events` and the playground download).
|
|
1568
1543
|
* Interactive reattach: `resume [id]` / `chat --resume` (or `chat --session`).
|
|
1569
1544
|
*/
|
|
1570
|
-
export function cmdSession(sessionId, options) {
|
|
1571
|
-
|
|
1572
|
-
|
|
1573
|
-
|
|
1574
|
-
|
|
1575
|
-
|
|
1576
|
-
|
|
1577
|
-
|
|
1578
|
-
|
|
1579
|
-
|
|
1580
|
-
|
|
1581
|
-
|
|
1582
|
-
}
|
|
1583
|
-
return started;
|
|
1584
|
-
}
|
|
1585
|
-
if (sessionId === undefined || sessionId.trim() === "") {
|
|
1586
|
-
process.stderr.write(`Usage: ${CLI_COMMAND_NAME} session <ses_> [--url | --prod] [--slug <slug>] [--json | --text | --events] [--out <file.ndjson>]\n` +
|
|
1587
|
-
` or: ${CLI_COMMAND_NAME} session --prod [<sessionId>] --slug <slug> --message "…" [--dry-run] [--as-of <instant>]\n`);
|
|
1588
|
-
return 2;
|
|
1589
|
-
}
|
|
1590
|
-
if (options.rawEvents === true && options.json === true) {
|
|
1591
|
-
process.stderr.write("--events and --json are mutually exclusive\n");
|
|
1592
|
-
return 2;
|
|
1545
|
+
export async function cmdSession(sessionId, options) {
|
|
1546
|
+
if (options.prod === true && (options.messages?.length ?? 0) > 0) {
|
|
1547
|
+
// `session --prod [ses_…] --message` is the same hosted start as
|
|
1548
|
+
// `run --prod`, with the positional id as the session to resume. Unlike
|
|
1549
|
+
// `run`, a 404 is an error here: this form is explicitly v2.
|
|
1550
|
+
const started = await cmdHostedSession({
|
|
1551
|
+
...options,
|
|
1552
|
+
sessionId: trimNonEmpty(sessionId) ?? options.sessionId,
|
|
1553
|
+
});
|
|
1554
|
+
if (started === "fallback") {
|
|
1555
|
+
process.stderr.write(`Hosted session start returned 404 for slug ${resolveProdSlug(options)}: deploy a running AgentSDK v2 agent, or use \`${CLI_COMMAND_NAME} run --prod\` (falls back to the v1 engine).\n`);
|
|
1556
|
+
return 1;
|
|
1593
1557
|
}
|
|
1594
|
-
|
|
1595
|
-
|
|
1596
|
-
|
|
1597
|
-
|
|
1598
|
-
}
|
|
1558
|
+
return started;
|
|
1559
|
+
}
|
|
1560
|
+
if (sessionId === undefined || sessionId.trim() === "") {
|
|
1561
|
+
process.stderr.write(`Usage: ${CLI_COMMAND_NAME} session <ses_> [--url | --prod] [--slug <slug>] [--json | --text | --events] [--out <file.ndjson>]\n` +
|
|
1562
|
+
` or: ${CLI_COMMAND_NAME} session --prod [<sessionId>] --slug <slug> --message "…" [--dry-run] [--as-of <instant>]\n`);
|
|
1563
|
+
return 2;
|
|
1564
|
+
}
|
|
1565
|
+
if (options.rawEvents === true && options.json === true) {
|
|
1566
|
+
process.stderr.write("--events and --json are mutually exclusive\n");
|
|
1567
|
+
return 2;
|
|
1568
|
+
}
|
|
1569
|
+
if (options.prod === true && options.url === undefined) {
|
|
1570
|
+
const hosted = await readHostedSessionRuns(sessionId, options);
|
|
1571
|
+
if (hosted !== "v1") {
|
|
1572
|
+
return hosted;
|
|
1599
1573
|
}
|
|
1600
|
-
|
|
1601
|
-
|
|
1602
|
-
|
|
1574
|
+
}
|
|
1575
|
+
const target = await resolveSessionTarget(options);
|
|
1576
|
+
if (typeof target === "number") {
|
|
1577
|
+
return target;
|
|
1578
|
+
}
|
|
1579
|
+
try {
|
|
1580
|
+
const events = await fetchSessionEvents({
|
|
1581
|
+
baseUrl: target.agentUrl,
|
|
1582
|
+
sessionId,
|
|
1583
|
+
auth: {
|
|
1584
|
+
bearerToken: options.bearerToken,
|
|
1585
|
+
headers: target.headers,
|
|
1586
|
+
},
|
|
1587
|
+
fetchImpl: options.fetchImpl,
|
|
1588
|
+
});
|
|
1589
|
+
const outPath = trimNonEmpty(options.out);
|
|
1590
|
+
if (outPath !== undefined) {
|
|
1591
|
+
const targetPath = resolve(outPath);
|
|
1592
|
+
await mkdir(dirname(targetPath), { recursive: true });
|
|
1593
|
+
await writeFile(targetPath, `${events.map(e => JSON.stringify(e)).join("\n")}\n`, "utf8");
|
|
1594
|
+
process.stdout.write(`trace: ${targetPath} (${events.length} events)\n`);
|
|
1595
|
+
return 0;
|
|
1603
1596
|
}
|
|
1604
|
-
|
|
1605
|
-
|
|
1606
|
-
baseUrl: target.agentUrl,
|
|
1607
|
-
sessionId,
|
|
1608
|
-
auth: {
|
|
1609
|
-
bearerToken: options.bearerToken,
|
|
1610
|
-
headers: target.headers,
|
|
1611
|
-
},
|
|
1612
|
-
fetchImpl: options.fetchImpl,
|
|
1613
|
-
});
|
|
1614
|
-
const outPath = trimNonEmpty(options.out);
|
|
1615
|
-
if (outPath !== undefined) {
|
|
1616
|
-
const targetPath = resolve(outPath);
|
|
1617
|
-
yield mkdir(dirname(targetPath), { recursive: true });
|
|
1618
|
-
yield writeFile(targetPath, `${events.map(e => JSON.stringify(e)).join("\n")}\n`, "utf8");
|
|
1619
|
-
process.stdout.write(`trace: ${targetPath} (${events.length} events)\n`);
|
|
1620
|
-
return 0;
|
|
1621
|
-
}
|
|
1622
|
-
if (options.rawEvents === true) {
|
|
1623
|
-
process.stdout.write(`${JSON.stringify({ sessionId, events }, null, 2)}\n`);
|
|
1624
|
-
return 0;
|
|
1625
|
-
}
|
|
1626
|
-
const trajectory = buildTrajectory(events);
|
|
1627
|
-
if (options.json === true) {
|
|
1628
|
-
process.stdout.write(`${JSON.stringify(trajectory, null, 2)}\n`);
|
|
1629
|
-
return 0;
|
|
1630
|
-
}
|
|
1631
|
-
process.stdout.write(formatTrajectoryText(trajectory));
|
|
1597
|
+
if (options.rawEvents === true) {
|
|
1598
|
+
process.stdout.write(`${JSON.stringify({ sessionId, events }, null, 2)}\n`);
|
|
1632
1599
|
return 0;
|
|
1633
1600
|
}
|
|
1634
|
-
|
|
1635
|
-
|
|
1636
|
-
|
|
1601
|
+
const trajectory = buildTrajectory(events);
|
|
1602
|
+
if (options.json === true) {
|
|
1603
|
+
process.stdout.write(`${JSON.stringify(trajectory, null, 2)}\n`);
|
|
1604
|
+
return 0;
|
|
1637
1605
|
}
|
|
1638
|
-
|
|
1606
|
+
process.stdout.write(formatTrajectoryText(trajectory));
|
|
1607
|
+
return 0;
|
|
1608
|
+
}
|
|
1609
|
+
catch (error) {
|
|
1610
|
+
process.stderr.write(`${sanitizeCustomerError(error instanceof Error ? error.message : String(error))}\n`);
|
|
1611
|
+
return 1;
|
|
1612
|
+
}
|
|
1639
1613
|
}
|
|
1640
1614
|
/** Sessions fetched concurrently when `cost` aggregates every session. */
|
|
1641
1615
|
const COST_FETCH_CONCURRENCY = 4;
|
|
@@ -1649,71 +1623,69 @@ const COST_FETCH_CONCURRENCY = 4;
|
|
|
1649
1623
|
* (billed usage when available). Turns persisted before cost tracking simply
|
|
1650
1624
|
* count as unpriced.
|
|
1651
1625
|
*/
|
|
1652
|
-
export function cmdCost(sessionId, options) {
|
|
1653
|
-
|
|
1654
|
-
|
|
1655
|
-
|
|
1656
|
-
|
|
1657
|
-
|
|
1658
|
-
|
|
1659
|
-
|
|
1660
|
-
|
|
1661
|
-
|
|
1662
|
-
|
|
1663
|
-
|
|
1664
|
-
|
|
1665
|
-
const events = yield fetchSessionEvents({
|
|
1666
|
-
baseUrl: target.agentUrl,
|
|
1667
|
-
sessionId: resolved,
|
|
1668
|
-
auth,
|
|
1669
|
-
fetchImpl: options.fetchImpl,
|
|
1670
|
-
});
|
|
1671
|
-
const report = buildSessionCostReport(events);
|
|
1672
|
-
if (report.sessionId === "") {
|
|
1673
|
-
report.sessionId = resolved;
|
|
1674
|
-
}
|
|
1675
|
-
if (options.json === true) {
|
|
1676
|
-
process.stdout.write(`${JSON.stringify(report, null, 2)}\n`);
|
|
1677
|
-
}
|
|
1678
|
-
else {
|
|
1679
|
-
process.stdout.write(formatSessionCostText(report));
|
|
1680
|
-
}
|
|
1681
|
-
return 0;
|
|
1682
|
-
}
|
|
1683
|
-
const listed = yield listSessionsWithSource({
|
|
1626
|
+
export async function cmdCost(sessionId, options) {
|
|
1627
|
+
const target = await resolveSessionTarget(options);
|
|
1628
|
+
if (typeof target === "number") {
|
|
1629
|
+
return target;
|
|
1630
|
+
}
|
|
1631
|
+
const auth = {
|
|
1632
|
+
bearerToken: options.bearerToken,
|
|
1633
|
+
headers: target.headers,
|
|
1634
|
+
};
|
|
1635
|
+
try {
|
|
1636
|
+
const resolved = trimNonEmpty(sessionId);
|
|
1637
|
+
if (resolved !== undefined) {
|
|
1638
|
+
const events = await fetchSessionEvents({
|
|
1684
1639
|
baseUrl: target.agentUrl,
|
|
1640
|
+
sessionId: resolved,
|
|
1685
1641
|
auth,
|
|
1686
1642
|
fetchImpl: options.fetchImpl,
|
|
1687
1643
|
});
|
|
1688
|
-
const
|
|
1689
|
-
|
|
1690
|
-
|
|
1691
|
-
|
|
1692
|
-
auth,
|
|
1693
|
-
fetchImpl: options.fetchImpl,
|
|
1694
|
-
});
|
|
1695
|
-
const report = buildSessionCostReport(events);
|
|
1696
|
-
return {
|
|
1697
|
-
sessionId: session.sessionId,
|
|
1698
|
-
channelId: session.channelId,
|
|
1699
|
-
title: session.title,
|
|
1700
|
-
updatedAt: session.updatedAt,
|
|
1701
|
-
totals: report.totals,
|
|
1702
|
-
};
|
|
1703
|
-
}));
|
|
1644
|
+
const report = buildSessionCostReport(events);
|
|
1645
|
+
if (report.sessionId === "") {
|
|
1646
|
+
report.sessionId = resolved;
|
|
1647
|
+
}
|
|
1704
1648
|
if (options.json === true) {
|
|
1705
|
-
process.stdout.write(`${JSON.stringify(
|
|
1649
|
+
process.stdout.write(`${JSON.stringify(report, null, 2)}\n`);
|
|
1706
1650
|
}
|
|
1707
1651
|
else {
|
|
1708
|
-
process.stdout.write(
|
|
1652
|
+
process.stdout.write(formatSessionCostText(report));
|
|
1709
1653
|
}
|
|
1710
1654
|
return 0;
|
|
1711
1655
|
}
|
|
1712
|
-
|
|
1713
|
-
|
|
1714
|
-
|
|
1656
|
+
const listed = await listSessionsWithSource({
|
|
1657
|
+
baseUrl: target.agentUrl,
|
|
1658
|
+
auth,
|
|
1659
|
+
fetchImpl: options.fetchImpl,
|
|
1660
|
+
});
|
|
1661
|
+
const rows = await mapPool(listed.sessions, COST_FETCH_CONCURRENCY, async (session) => {
|
|
1662
|
+
const events = await fetchSessionEvents({
|
|
1663
|
+
baseUrl: target.agentUrl,
|
|
1664
|
+
sessionId: session.sessionId,
|
|
1665
|
+
auth,
|
|
1666
|
+
fetchImpl: options.fetchImpl,
|
|
1667
|
+
});
|
|
1668
|
+
const report = buildSessionCostReport(events);
|
|
1669
|
+
return {
|
|
1670
|
+
sessionId: session.sessionId,
|
|
1671
|
+
channelId: session.channelId,
|
|
1672
|
+
title: session.title,
|
|
1673
|
+
updatedAt: session.updatedAt,
|
|
1674
|
+
totals: report.totals,
|
|
1675
|
+
};
|
|
1676
|
+
});
|
|
1677
|
+
if (options.json === true) {
|
|
1678
|
+
process.stdout.write(`${JSON.stringify({ sessions: rows }, null, 2)}\n`);
|
|
1715
1679
|
}
|
|
1716
|
-
|
|
1680
|
+
else {
|
|
1681
|
+
process.stdout.write(formatSessionsCostText(rows));
|
|
1682
|
+
}
|
|
1683
|
+
return 0;
|
|
1684
|
+
}
|
|
1685
|
+
catch (error) {
|
|
1686
|
+
process.stderr.write(`${sanitizeCustomerError(error instanceof Error ? error.message : String(error))}\n`);
|
|
1687
|
+
return 1;
|
|
1688
|
+
}
|
|
1717
1689
|
}
|
|
1718
1690
|
/**
|
|
1719
1691
|
* `playground` — open the local web UI, v1 hosted alias, or v2 portal UI.
|
|
@@ -1722,115 +1694,111 @@ export function cmdCost(sessionId, options) {
|
|
|
1722
1694
|
* (and other injected headers) on local targets still run a loopback reverse
|
|
1723
1695
|
* proxy — Ctrl-C stops that proxy.
|
|
1724
1696
|
*/
|
|
1725
|
-
export function cmdPlayground(options) {
|
|
1726
|
-
|
|
1727
|
-
|
|
1728
|
-
|
|
1729
|
-
|
|
1730
|
-
|
|
1731
|
-
|
|
1732
|
-
|
|
1733
|
-
|
|
1734
|
-
|
|
1735
|
-
|
|
1736
|
-
let resolved;
|
|
1737
|
-
try {
|
|
1738
|
-
resolved = yield resolveProdPlaygroundUrl({
|
|
1739
|
-
dir: options.dir,
|
|
1740
|
-
cwd: options.cwd,
|
|
1741
|
-
slug: options.slug,
|
|
1742
|
-
team: options.team,
|
|
1743
|
-
apiKey: options.apiKey,
|
|
1744
|
-
fetchImpl: options.fetchImpl,
|
|
1745
|
-
sessionId,
|
|
1746
|
-
});
|
|
1747
|
-
}
|
|
1748
|
-
catch (error) {
|
|
1749
|
-
process.stderr.write(`${sanitizeCustomerError(error instanceof Error ? error.message : String(error))}\n`);
|
|
1750
|
-
return 1;
|
|
1751
|
-
}
|
|
1752
|
-
process.stdout.write(`${resolved.playgroundUrl}\n`);
|
|
1753
|
-
if (options.print !== true) {
|
|
1754
|
-
openBrowser(resolved.playgroundUrl);
|
|
1755
|
-
}
|
|
1756
|
-
return 0;
|
|
1757
|
-
}
|
|
1758
|
-
const target = yield resolveSessionTarget(options);
|
|
1759
|
-
if (typeof target === "number") {
|
|
1760
|
-
return target;
|
|
1761
|
-
}
|
|
1762
|
-
const needsProxy = (target.headers !== undefined && Object.keys(target.headers).length > 0) ||
|
|
1763
|
-
(options.bearerToken !== undefined && options.bearerToken.trim() !== "");
|
|
1764
|
-
if (!needsProxy) {
|
|
1765
|
-
const base = `${target.agentUrl.replace(/\/$/, "")}/playground`;
|
|
1766
|
-
const playgroundUrl = sessionId === undefined ? base : `${base}?sessionId=${encodeURIComponent(sessionId)}`;
|
|
1767
|
-
process.stdout.write(`${playgroundUrl}\n`);
|
|
1768
|
-
if (options.print !== true) {
|
|
1769
|
-
openBrowser(playgroundUrl);
|
|
1770
|
-
}
|
|
1771
|
-
return 0;
|
|
1772
|
-
}
|
|
1773
|
-
let proxy;
|
|
1697
|
+
export async function cmdPlayground(options) {
|
|
1698
|
+
if (options.prod === true && options.url !== undefined) {
|
|
1699
|
+
process.stderr.write("--prod and --url are mutually exclusive\n");
|
|
1700
|
+
return 2;
|
|
1701
|
+
}
|
|
1702
|
+
const sessionId = options.sessionId !== undefined && options.sessionId.trim() !== ""
|
|
1703
|
+
? options.sessionId.trim()
|
|
1704
|
+
: undefined;
|
|
1705
|
+
// Hosted v1 opens the alias playground; v2 opens the portal-hosted shell.
|
|
1706
|
+
if (options.prod === true) {
|
|
1707
|
+
let resolved;
|
|
1774
1708
|
try {
|
|
1775
|
-
|
|
1776
|
-
|
|
1777
|
-
|
|
1778
|
-
|
|
1709
|
+
resolved = await resolveProdPlaygroundUrl({
|
|
1710
|
+
dir: options.dir,
|
|
1711
|
+
cwd: options.cwd,
|
|
1712
|
+
slug: options.slug,
|
|
1713
|
+
team: options.team,
|
|
1714
|
+
apiKey: options.apiKey,
|
|
1715
|
+
fetchImpl: options.fetchImpl,
|
|
1716
|
+
sessionId,
|
|
1779
1717
|
});
|
|
1780
1718
|
}
|
|
1781
1719
|
catch (error) {
|
|
1782
1720
|
process.stderr.write(`${sanitizeCustomerError(error instanceof Error ? error.message : String(error))}\n`);
|
|
1783
1721
|
return 1;
|
|
1784
1722
|
}
|
|
1785
|
-
|
|
1786
|
-
|
|
1787
|
-
|
|
1788
|
-
|
|
1789
|
-
|
|
1790
|
-
|
|
1791
|
-
|
|
1792
|
-
|
|
1793
|
-
|
|
1794
|
-
|
|
1795
|
-
|
|
1796
|
-
|
|
1723
|
+
process.stdout.write(`${resolved.playgroundUrl}\n`);
|
|
1724
|
+
if (options.print !== true) {
|
|
1725
|
+
openBrowser(resolved.playgroundUrl);
|
|
1726
|
+
}
|
|
1727
|
+
return 0;
|
|
1728
|
+
}
|
|
1729
|
+
const target = await resolveSessionTarget(options);
|
|
1730
|
+
if (typeof target === "number") {
|
|
1731
|
+
return target;
|
|
1732
|
+
}
|
|
1733
|
+
const needsProxy = (target.headers !== undefined && Object.keys(target.headers).length > 0) ||
|
|
1734
|
+
(options.bearerToken !== undefined && options.bearerToken.trim() !== "");
|
|
1735
|
+
if (!needsProxy) {
|
|
1736
|
+
const base = `${target.agentUrl.replace(/\/$/, "")}/playground`;
|
|
1737
|
+
const playgroundUrl = sessionId === undefined ? base : `${base}?sessionId=${encodeURIComponent(sessionId)}`;
|
|
1797
1738
|
process.stdout.write(`${playgroundUrl}\n`);
|
|
1798
|
-
|
|
1799
|
-
if (args.print !== true) {
|
|
1739
|
+
if (options.print !== true) {
|
|
1800
1740
|
openBrowser(playgroundUrl);
|
|
1801
1741
|
}
|
|
1802
|
-
|
|
1803
|
-
|
|
1742
|
+
return 0;
|
|
1743
|
+
}
|
|
1744
|
+
let proxy;
|
|
1745
|
+
try {
|
|
1746
|
+
proxy = await startPlaygroundProxy({
|
|
1747
|
+
upstreamUrl: target.agentUrl,
|
|
1748
|
+
headers: target.headers,
|
|
1749
|
+
bearerToken: options.bearerToken,
|
|
1750
|
+
});
|
|
1751
|
+
}
|
|
1752
|
+
catch (error) {
|
|
1753
|
+
process.stderr.write(`${sanitizeCustomerError(error instanceof Error ? error.message : String(error))}\n`);
|
|
1754
|
+
return 1;
|
|
1755
|
+
}
|
|
1756
|
+
return await runPlaygroundProxySession({
|
|
1757
|
+
proxy,
|
|
1758
|
+
sessionId,
|
|
1759
|
+
print: options.print === true,
|
|
1760
|
+
signal: options.signal,
|
|
1761
|
+
});
|
|
1762
|
+
}
|
|
1763
|
+
async function runPlaygroundProxySession(args) {
|
|
1764
|
+
const { proxy } = args;
|
|
1765
|
+
const playgroundUrl = proxy.playgroundUrl(args.sessionId);
|
|
1766
|
+
process.stdout.write(`${playgroundUrl}\n`);
|
|
1767
|
+
process.stderr.write(`Playground proxy on loopback (Ctrl-C to stop).\n`);
|
|
1768
|
+
if (args.print !== true) {
|
|
1769
|
+
openBrowser(playgroundUrl);
|
|
1770
|
+
}
|
|
1771
|
+
const controller = new AbortController();
|
|
1772
|
+
const onSignal = () => {
|
|
1773
|
+
controller.abort();
|
|
1774
|
+
};
|
|
1775
|
+
process.on("SIGINT", onSignal);
|
|
1776
|
+
process.on("SIGTERM", onSignal);
|
|
1777
|
+
const external = args.signal;
|
|
1778
|
+
if (external !== undefined) {
|
|
1779
|
+
if (external.aborted) {
|
|
1804
1780
|
controller.abort();
|
|
1805
|
-
};
|
|
1806
|
-
process.on("SIGINT", onSignal);
|
|
1807
|
-
process.on("SIGTERM", onSignal);
|
|
1808
|
-
const external = args.signal;
|
|
1809
|
-
if (external !== undefined) {
|
|
1810
|
-
if (external.aborted) {
|
|
1811
|
-
controller.abort();
|
|
1812
|
-
}
|
|
1813
|
-
else {
|
|
1814
|
-
external.addEventListener("abort", onSignal, { once: true });
|
|
1815
|
-
}
|
|
1816
|
-
}
|
|
1817
|
-
try {
|
|
1818
|
-
yield new Promise(resolve => {
|
|
1819
|
-
if (controller.signal.aborted) {
|
|
1820
|
-
resolve();
|
|
1821
|
-
return;
|
|
1822
|
-
}
|
|
1823
|
-
controller.signal.addEventListener("abort", () => resolve(), {
|
|
1824
|
-
once: true,
|
|
1825
|
-
});
|
|
1826
|
-
});
|
|
1827
|
-
return 0;
|
|
1828
1781
|
}
|
|
1829
|
-
|
|
1830
|
-
|
|
1831
|
-
process.off("SIGTERM", onSignal);
|
|
1832
|
-
external === null || external === void 0 ? void 0 : external.removeEventListener("abort", onSignal);
|
|
1833
|
-
yield proxy.close().catch(() => { });
|
|
1782
|
+
else {
|
|
1783
|
+
external.addEventListener("abort", onSignal, { once: true });
|
|
1834
1784
|
}
|
|
1835
|
-
}
|
|
1785
|
+
}
|
|
1786
|
+
try {
|
|
1787
|
+
await new Promise(resolve => {
|
|
1788
|
+
if (controller.signal.aborted) {
|
|
1789
|
+
resolve();
|
|
1790
|
+
return;
|
|
1791
|
+
}
|
|
1792
|
+
controller.signal.addEventListener("abort", () => resolve(), {
|
|
1793
|
+
once: true,
|
|
1794
|
+
});
|
|
1795
|
+
});
|
|
1796
|
+
return 0;
|
|
1797
|
+
}
|
|
1798
|
+
finally {
|
|
1799
|
+
process.off("SIGINT", onSignal);
|
|
1800
|
+
process.off("SIGTERM", onSignal);
|
|
1801
|
+
external?.removeEventListener("abort", onSignal);
|
|
1802
|
+
await proxy.close().catch(() => { });
|
|
1803
|
+
}
|
|
1836
1804
|
}
|