@cursor/bdk 0.2.3 → 0.2.4
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/bin/agent-serve.js +9 -1
- package/dist/channels/slack/attachments.d.ts +2 -1
- package/dist/channels/slack/attachments.d.ts.map +1 -1
- package/dist/channels/slack/attachments.js +19 -9
- package/dist/channels/slack/dispatch.d.ts.map +1 -1
- package/dist/channels/slack/dispatch.js +26 -24
- package/dist/channels/slack/thread-context.d.ts +21 -11
- package/dist/channels/slack/thread-context.d.ts.map +1 -1
- package/dist/channels/slack/thread-context.js +75 -27
- package/dist/docs/404.html +2 -2
- package/dist/docs/assets/{app.BOIHhrKi.js → app.4kQ8Db_q.js} +4 -4
- package/dist/docs/assets/chunks/@localSearchIndexroot.CvuAJ0My.js +1 -0
- package/dist/docs/assets/chunks/{VPLocalSearchBox.D49zVZqM.js → VPLocalSearchBox.DY1RwB8Q.js} +1 -1
- package/dist/docs/assets/chunks/{arc.hmjb-sc4.js → arc.CxE_fSPK.js} +1 -1
- package/dist/docs/assets/chunks/{architectureDiagram-Q4EWVU46.CxEI1KqM.js → architectureDiagram-Q4EWVU46.CPX426ui.js} +1 -1
- package/dist/docs/assets/chunks/{baseUniq.DHHvBWoV.js → baseUniq.CB52JrKG.js} +1 -1
- package/dist/docs/assets/chunks/{blockDiagram-DXYQGD6D.DnXW-3bu.js → blockDiagram-DXYQGD6D.J0cNaQCL.js} +1 -1
- package/dist/docs/assets/chunks/{c4Diagram-AHTNJAMY.e-47O2jM.js → c4Diagram-AHTNJAMY.DJn3vEGT.js} +1 -1
- package/dist/docs/assets/chunks/channel.BoNycAoN.js +1 -0
- package/dist/docs/assets/chunks/{chunk-4BX2VUAB.3ry4pYXB.js → chunk-4BX2VUAB.Dao618F6.js} +1 -1
- package/dist/docs/assets/chunks/{chunk-4TB4RGXK.DGIZFRx6.js → chunk-4TB4RGXK.QW8Rhjai.js} +1 -1
- package/dist/docs/assets/chunks/{chunk-55IACEB6.DKBnqg9U.js → chunk-55IACEB6.DfRLLKF_.js} +1 -1
- package/dist/docs/assets/chunks/{chunk-EDXVE4YY.BIU8Ue5k.js → chunk-EDXVE4YY.CIV2ApKQ.js} +1 -1
- package/dist/docs/assets/chunks/{chunk-FMBD7UC4.DP-TFhjI.js → chunk-FMBD7UC4.BEheSuxp.js} +1 -1
- package/dist/docs/assets/chunks/{chunk-OYMX7WX6.Ux0OYj5v.js → chunk-OYMX7WX6.CUN88ENB.js} +1 -1
- package/dist/docs/assets/chunks/{chunk-QZHKN3VN.BzHMwYox.js → chunk-QZHKN3VN.CgqCs8b_.js} +1 -1
- package/dist/docs/assets/chunks/{chunk-YZCP3GAM.D4OGAsSP.js → chunk-YZCP3GAM.iCH0nnTJ.js} +1 -1
- package/dist/docs/assets/chunks/classDiagram-6PBFFD2Q.C4x07Gkj.js +1 -0
- package/dist/docs/assets/chunks/classDiagram-v2-HSJHXN6E.C4x07Gkj.js +1 -0
- package/dist/docs/assets/chunks/clone.Db22cH_-.js +1 -0
- package/dist/docs/assets/chunks/{cose-bilkent-S5V4N54A.Jq_7BUNx.js → cose-bilkent-S5V4N54A.BLcUxhWE.js} +1 -1
- package/dist/docs/assets/chunks/{dagre-KV5264BT.Di-skR2x.js → dagre-KV5264BT.Ep7LofOm.js} +1 -1
- package/dist/docs/assets/chunks/{diagram-5BDNPKRD.DeREHIdH.js → diagram-5BDNPKRD.Bzf4GSQ4.js} +1 -1
- package/dist/docs/assets/chunks/{diagram-G4DWMVQ6.C7Kcqxro.js → diagram-G4DWMVQ6.DD6Jh-eM.js} +1 -1
- package/dist/docs/assets/chunks/{diagram-MMDJMWI5.BK3eohyo.js → diagram-MMDJMWI5.oOIl8bWd.js} +1 -1
- package/dist/docs/assets/chunks/{diagram-TYMM5635.C6TyymXT.js → diagram-TYMM5635.DHs85Ade.js} +1 -1
- package/dist/docs/assets/chunks/{erDiagram-SMLLAGMA.DYGG-gGx.js → erDiagram-SMLLAGMA.BIb5ghCk.js} +1 -1
- package/dist/docs/assets/chunks/{flowDiagram-DWJPFMVM.C9nBcSV4.js → flowDiagram-DWJPFMVM.DV4paY9k.js} +1 -1
- package/dist/docs/assets/chunks/{ganttDiagram-T4ZO3ILL.wAg_ymsp.js → ganttDiagram-T4ZO3ILL.AyEKA6_v.js} +1 -1
- package/dist/docs/assets/chunks/{gitGraphDiagram-UUTBAWPF.B87j9Oeg.js → gitGraphDiagram-UUTBAWPF.BltiCDFo.js} +1 -1
- package/dist/docs/assets/chunks/{graph.CuFMj31w.js → graph.DzuEYGdC.js} +1 -1
- package/dist/docs/assets/chunks/{infoDiagram-42DDH7IO.P_mLGumP.js → infoDiagram-42DDH7IO.BV2l981J.js} +1 -1
- package/dist/docs/assets/chunks/{ishikawaDiagram-UXIWVN3A.DyuL_MsT.js → ishikawaDiagram-UXIWVN3A.BA4Izf-m.js} +1 -1
- package/dist/docs/assets/chunks/{journeyDiagram-VCZTEJTY.CtP09IoJ.js → journeyDiagram-VCZTEJTY.DjaFbFS3.js} +1 -1
- package/dist/docs/assets/chunks/{kanban-definition-6JOO6SKY.BoeSYPZo.js → kanban-definition-6JOO6SKY.CfTFieDs.js} +1 -1
- package/dist/docs/assets/chunks/{layout.B0lMMtNo.js → layout.DzfWqTBV.js} +1 -1
- package/dist/docs/assets/chunks/{linear.HxRBiAFX.js → linear.BO6mpulV.js} +1 -1
- package/dist/docs/assets/chunks/{min.BGlFFHwS.js → min.BGgTadgT.js} +1 -1
- package/dist/docs/assets/chunks/{mindmap-definition-QFDTVHPH.JyLBD9M8.js → mindmap-definition-QFDTVHPH.DPuIXVWY.js} +1 -1
- package/dist/docs/assets/chunks/{pieDiagram-DEJITSTG.DnSmNZF8.js → pieDiagram-DEJITSTG.BOnl3bBg.js} +1 -1
- package/dist/docs/assets/chunks/{quadrantDiagram-34T5L4WZ.CUCnbfCa.js → quadrantDiagram-34T5L4WZ.DNB6Ckdc.js} +1 -1
- package/dist/docs/assets/chunks/{requirementDiagram-MS252O5E.py0IVUn5.js → requirementDiagram-MS252O5E.D5-Qo7vb.js} +1 -1
- package/dist/docs/assets/chunks/{sankeyDiagram-XADWPNL6.Bkc-HWYp.js → sankeyDiagram-XADWPNL6.8t65cesf.js} +1 -1
- package/dist/docs/assets/chunks/{sequenceDiagram-FGHM5R23.Dqn8Mlv2.js → sequenceDiagram-FGHM5R23.CaG07BdS.js} +1 -1
- package/dist/docs/assets/chunks/{stateDiagram-FHFEXIEX.JikkoQUU.js → stateDiagram-FHFEXIEX.TKOweTB6.js} +1 -1
- package/dist/docs/assets/chunks/stateDiagram-v2-QKLJ7IA2.CuqmyQc4.js +1 -0
- package/dist/docs/assets/chunks/{theme.b6HQ6zG_.js → theme.Dx-JhpTB.js} +2 -2
- package/dist/docs/assets/chunks/{timeline-definition-GMOUNBTQ.BvpSXiBj.js → timeline-definition-GMOUNBTQ.fE53zQ2s.js} +1 -1
- package/dist/docs/assets/chunks/{vennDiagram-DHZGUBPP.CU7MVnZx.js → vennDiagram-DHZGUBPP.DJsZZaJg.js} +1 -1
- package/dist/docs/assets/chunks/{wardley-RL74JXVD.BKwC4ctG.js → wardley-RL74JXVD.844kyrjl.js} +1 -1
- package/dist/docs/assets/chunks/{wardleyDiagram-NUSXRM2D.BfaF6Uhe.js → wardleyDiagram-NUSXRM2D.CMZ-Ru_t.js} +1 -1
- package/dist/docs/assets/chunks/{xychartDiagram-5P7HB3ND.Bg5dcpj4.js → xychartDiagram-5P7HB3ND.XXrhBc7a.js} +1 -1
- package/dist/docs/assets/{deployment.md.BJ8i7Q6p.js → deployment.md.UhnJIMr-.js} +2 -2
- package/dist/docs/assets/{deployment.md.BJ8i7Q6p.lean.js → deployment.md.UhnJIMr-.lean.js} +1 -1
- package/dist/docs/assets/{guides_jev.md.BNDm14Gy.js → guides_jev.md.CRcgmjDb.js} +2 -2
- package/dist/docs/assets/{guides_jev.md.BNDm14Gy.lean.js → guides_jev.md.CRcgmjDb.lean.js} +1 -1
- package/dist/docs/assets/{reference_agent-config.md.DzGI777n.js → reference_agent-config.md.Cj5uBKp4.js} +1 -1
- package/dist/docs/assets/{reference_extensions.md.CPPrkWlJ.js → reference_extensions.md.pa2tN-e4.js} +4 -3
- package/dist/docs/assets/{reference_extensions.md.CPPrkWlJ.lean.js → reference_extensions.md.pa2tN-e4.lean.js} +1 -1
- package/dist/docs/building-with-agents.html +35 -35
- package/dist/docs/deployment.html +37 -37
- package/dist/docs/deployment.md +4 -1
- package/dist/docs/evals.html +35 -35
- package/dist/docs/guides/agent-to-agent.html +35 -35
- package/dist/docs/guides/bitbucket.html +35 -35
- package/dist/docs/guides/cloud-agents.html +35 -35
- package/dist/docs/guides/convert-automation.html +35 -35
- package/dist/docs/guides/github.html +35 -35
- package/dist/docs/guides/gitlab.html +35 -35
- 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 +37 -37
- package/dist/docs/guides/jev.md +7 -0
- package/dist/docs/guides/mcp-oauth.html +35 -35
- 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 +25 -2
- package/dist/docs/quickstart.html +35 -35
- package/dist/docs/reference/agent-config.html +37 -37
- package/dist/docs/reference/agent-config.md +1 -1
- package/dist/docs/reference/artifacts.html +35 -35
- package/dist/docs/reference/channels.html +35 -35
- package/dist/docs/reference/cli.html +35 -35
- package/dist/docs/reference/connections.html +35 -35
- package/dist/docs/reference/evals.html +35 -35
- package/dist/docs/reference/extensions.html +39 -38
- package/dist/docs/reference/extensions.md +13 -0
- 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/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 +35 -35
- package/dist/extensions/jev/extension.d.ts +3 -0
- package/dist/extensions/jev/extension.d.ts.map +1 -1
- package/dist/extensions/jev/extension.js +10 -1
- package/dist/extensions/jev/lib/evaluate.d.ts +4 -0
- package/dist/extensions/jev/lib/evaluate.d.ts.map +1 -1
- package/dist/extensions/jev/lib/evaluate.js +6 -2
- package/dist/extensions.d.ts +4 -2
- package/dist/extensions.d.ts.map +1 -1
- package/dist/extensions.js +5 -2
- package/dist/internal/cli-deploy.d.ts.map +1 -1
- package/dist/internal/cli-deploy.js +19 -5
- package/dist/internal/discovery/agent-config.d.ts +6 -5
- package/dist/internal/discovery/agent-config.d.ts.map +1 -1
- package/dist/internal/discovery/agent-config.js +29 -28
- package/dist/internal/discovery/agent.js +1 -1
- package/dist/internal/discovery/extensions.d.ts.map +1 -1
- package/dist/internal/discovery/extensions.js +12 -0
- package/dist/internal/hosting.d.ts +8 -0
- package/dist/internal/hosting.d.ts.map +1 -1
- package/dist/internal/hosting.js +24 -0
- package/dist/types.d.ts +18 -2
- package/dist/types.d.ts.map +1 -1
- package/docs/deployment.md +4 -1
- package/docs/guides/jev.md +7 -0
- package/docs/reference/agent-config.md +1 -1
- package/docs/reference/extensions.md +13 -0
- package/package.json +1 -9
- package/dist/docs/assets/chunks/@localSearchIndexroot.D5L-b34G.js +0 -1
- package/dist/docs/assets/chunks/channel.BbOGaJQP.js +0 -1
- package/dist/docs/assets/chunks/classDiagram-6PBFFD2Q.Db58HCb1.js +0 -1
- package/dist/docs/assets/chunks/classDiagram-v2-HSJHXN6E.Db58HCb1.js +0 -1
- package/dist/docs/assets/chunks/clone.Co4MBflG.js +0 -1
- package/dist/docs/assets/chunks/stateDiagram-v2-QKLJ7IA2.CMsKhrW0.js +0 -1
- package/src/artifacts.ts +0 -68
- package/src/bin/agent-serve.ts +0 -1854
- package/src/channels/bitbucket/api.ts +0 -891
- package/src/channels/bitbucket/binding.ts +0 -417
- package/src/channels/bitbucket/bitbucket-channel.ts +0 -162
- package/src/channels/bitbucket/bitbucket-webhook.ts +0 -519
- package/src/channels/bitbucket/checks.ts +0 -146
- package/src/channels/bitbucket/cursor-account.ts +0 -106
- package/src/channels/bitbucket/defaults.ts +0 -100
- package/src/channels/bitbucket/events.ts +0 -74
- package/src/channels/bitbucket/index.ts +0 -51
- package/src/channels/bitbucket/replay.ts +0 -421
- package/src/channels/bitbucket/state.ts +0 -59
- package/src/channels/bitbucket/types.ts +0 -261
- package/src/channels/change-monitors/change-monitors-channel.ts +0 -63
- package/src/channels/change-monitors/index.ts +0 -8
- package/src/channels/change-monitors/types.ts +0 -42
- package/src/channels/checks.ts +0 -185
- package/src/channels/deployments/deployments-channel.ts +0 -224
- package/src/channels/deployments/index.ts +0 -25
- package/src/channels/deployments/types.ts +0 -92
- package/src/channels/github/api.ts +0 -526
- package/src/channels/github/auth.ts +0 -293
- package/src/channels/github/binding.ts +0 -233
- package/src/channels/github/checks.ts +0 -145
- package/src/channels/github/cursor-account.ts +0 -303
- package/src/channels/github/defaults.ts +0 -168
- package/src/channels/github/events.ts +0 -67
- package/src/channels/github/forward.ts +0 -359
- package/src/channels/github/github-channel.ts +0 -2334
- package/src/channels/github/index.ts +0 -54
- package/src/channels/github/progress.ts +0 -365
- package/src/channels/github/replay.ts +0 -372
- package/src/channels/github/state.ts +0 -124
- package/src/channels/github/types.ts +0 -590
- package/src/channels/gitlab/api.ts +0 -329
- package/src/channels/gitlab/binding.ts +0 -231
- package/src/channels/gitlab/checks.ts +0 -228
- package/src/channels/gitlab/cursor-account.ts +0 -105
- package/src/channels/gitlab/defaults.ts +0 -80
- package/src/channels/gitlab/events.ts +0 -37
- package/src/channels/gitlab/gitlab-channel.ts +0 -160
- package/src/channels/gitlab/gitlab-webhook.ts +0 -509
- package/src/channels/gitlab/index.ts +0 -44
- package/src/channels/gitlab/replay.ts +0 -328
- package/src/channels/gitlab/state.ts +0 -55
- package/src/channels/gitlab/types.ts +0 -247
- package/src/channels/issues/index.ts +0 -9
- package/src/channels/issues/issues-channel.ts +0 -45
- package/src/channels/issues/types.ts +0 -38
- package/src/channels/origin/api.ts +0 -507
- package/src/channels/origin/binding.ts +0 -114
- package/src/channels/origin/checks.ts +0 -250
- package/src/channels/origin/cursor-account.ts +0 -58
- package/src/channels/origin/defaults.ts +0 -140
- package/src/channels/origin/events.ts +0 -35
- package/src/channels/origin/index.ts +0 -35
- package/src/channels/origin/origin-channel.ts +0 -815
- package/src/channels/origin/origin-webhook.ts +0 -296
- package/src/channels/origin/reactions.ts +0 -72
- package/src/channels/origin/state.ts +0 -54
- package/src/channels/origin/types.ts +0 -295
- package/src/channels/slack/agentic-delivery.ts +0 -634
- package/src/channels/slack/agentic-posted.ts +0 -135
- package/src/channels/slack/agentic-signals.ts +0 -231
- package/src/channels/slack/api.ts +0 -761
- package/src/channels/slack/approvals.ts +0 -279
- package/src/channels/slack/assistant.ts +0 -76
- package/src/channels/slack/attachments.ts +0 -596
- package/src/channels/slack/auth.ts +0 -127
- package/src/channels/slack/blocks.ts +0 -131
- package/src/channels/slack/bot-mentions.ts +0 -318
- package/src/channels/slack/channel-watch.ts +0 -314
- package/src/channels/slack/cli-project.ts +0 -249
- package/src/channels/slack/code-fences.ts +0 -171
- package/src/channels/slack/constants.ts +0 -38
- package/src/channels/slack/credentials.ts +0 -88
- package/src/channels/slack/defaults.ts +0 -714
- package/src/channels/slack/dispatch.ts +0 -1060
- package/src/channels/slack/doctor.ts +0 -338
- package/src/channels/slack/eval-directive.ts +0 -306
- package/src/channels/slack/event-id-dedupe.ts +0 -30
- package/src/channels/slack/external-policy.ts +0 -75
- package/src/channels/slack/footer.ts +0 -106
- package/src/channels/slack/inbound.ts +0 -416
- package/src/channels/slack/index.ts +0 -53
- package/src/channels/slack/init.ts +0 -169
- package/src/channels/slack/interactive.ts +0 -406
- package/src/channels/slack/links.ts +0 -23
- package/src/channels/slack/live-delivery.ts +0 -489
- package/src/channels/slack/log.ts +0 -70
- package/src/channels/slack/manifest.ts +0 -240
- package/src/channels/slack/message-body.ts +0 -82
- package/src/channels/slack/nudge-carrier.ts +0 -224
- package/src/channels/slack/nudge-store.ts +0 -334
- package/src/channels/slack/paint-start.ts +0 -93
- package/src/channels/slack/placeholder.ts +0 -358
- package/src/channels/slack/pr-ref.ts +0 -74
- package/src/channels/slack/progress-delivery.ts +0 -138
- package/src/channels/slack/reasoning-card.ts +0 -125
- package/src/channels/slack/reasoning-chip.ts +0 -41
- package/src/channels/slack/recording-sink.ts +0 -167
- package/src/channels/slack/redact.ts +0 -6
- package/src/channels/slack/reply-options.ts +0 -279
- package/src/channels/slack/setup.ts +0 -125
- package/src/channels/slack/slack-channel.ts +0 -744
- package/src/channels/slack/socket-mode.ts +0 -140
- package/src/channels/slack/stop.ts +0 -25
- package/src/channels/slack/stream.ts +0 -66
- package/src/channels/slack/thread-context.ts +0 -485
- package/src/channels/slack/tool-approval-events.ts +0 -233
- package/src/channels/slack/tool-cards.ts +0 -198
- package/src/channels/slack/tool-chip.ts +0 -34
- package/src/channels/slack/types.ts +0 -787
- package/src/channels/slack/upload.ts +0 -137
- package/src/channels.ts +0 -543
- package/src/connections.ts +0 -153
- package/src/dashboard-session-url.ts +0 -30
- package/src/evals/assertions.ts +0 -688
- package/src/evals/expect.ts +0 -250
- package/src/evals/judge.ts +0 -329
- package/src/evals/loaders.ts +0 -111
- package/src/evals/matchers.ts +0 -223
- package/src/evals/reporters.ts +0 -257
- package/src/evals/results.ts +0 -130
- package/src/evals/run-facts.ts +0 -306
- package/src/evals.ts +0 -709
- package/src/extensions/cursor-cloud-agents/extension.ts +0 -131
- package/src/extensions/cursor-cloud-agents/lib/backend.ts +0 -386
- package/src/extensions/cursor-cloud-agents/lib/channels.ts +0 -11
- package/src/extensions/cursor-cloud-agents/lib/fleet.ts +0 -98
- package/src/extensions/cursor-cloud-agents/lib/inputs.ts +0 -5
- package/src/extensions/cursor-cloud-agents/lib/repos.ts +0 -80
- package/src/extensions/cursor-cloud-agents/lib/transcript.ts +0 -19
- package/src/extensions/cursor-cloud-agents/skills/handoff.md +0 -37
- package/src/extensions/cursor-cloud-agents/tools/cancel.ts +0 -21
- package/src/extensions/cursor-cloud-agents/tools/dump.ts +0 -47
- package/src/extensions/cursor-cloud-agents/tools/get.ts +0 -18
- package/src/extensions/cursor-cloud-agents/tools/launch.ts +0 -62
- package/src/extensions/cursor-cloud-agents/tools/list.ts +0 -31
- package/src/extensions/cursor-cloud-agents/tools/reply.ts +0 -36
- package/src/extensions/cursor-grokbot-agents/extension.ts +0 -132
- package/src/extensions/cursor-grokbot-agents/lib/agents.ts +0 -42
- package/src/extensions/cursor-grokbot-agents/lib/backend.ts +0 -208
- package/src/extensions/cursor-grokbot-agents/lib/contacts.ts +0 -74
- package/src/extensions/cursor-grokbot-agents/lib/conversation.ts +0 -260
- package/src/extensions/cursor-grokbot-agents/lib/inputs.ts +0 -21
- package/src/extensions/cursor-grokbot-agents/lib/lock.ts +0 -26
- package/src/extensions/cursor-grokbot-agents/skills/consult.md +0 -40
- package/src/extensions/cursor-grokbot-agents/tools/ask.ts +0 -32
- package/src/extensions/cursor-grokbot-agents/tools/check.ts +0 -25
- package/src/extensions/cursor-grokbot-agents/tools/interrupt.ts +0 -17
- package/src/extensions/cursor-grokbot-agents/tools/list.ts +0 -26
- package/src/extensions/improve/extension.ts +0 -69
- package/src/extensions/improve/skills/yourself.ts +0 -50
- package/src/extensions/jev/extension.ts +0 -95
- package/src/extensions/jev/lib/evaluate.ts +0 -266
- package/src/extensions/jev/skills/gated-write.md +0 -25
- package/src/extensions/jev/skills/questions.md +0 -33
- package/src/extensions/jev/tools/evaluate.ts +0 -82
- package/src/extensions/slack-communication/evals/harness.ts +0 -705
- package/src/extensions/slack-communication/evals/slack-communication.eval.ts +0 -830
- package/src/extensions/slack-communication/evals/slack-placeholder.eval.ts +0 -172
- package/src/extensions/slack-communication/extension.ts +0 -44
- package/src/extensions/slack-communication/skills/slack-voice.ts +0 -56
- package/src/extensions/slack-communication/tools/delete-message.ts +0 -33
- package/src/extensions/slack-communication/tools/edit-message.ts +0 -42
- package/src/extensions/slack-communication/tools/post-card.ts +0 -28
- package/src/extensions/slack-communication/tools/post-file.ts +0 -82
- package/src/extensions/slack-communication/tools/post-update.ts +0 -40
- package/src/extensions/slack-communication/tools/react.ts +0 -30
- package/src/extensions/slack-communication/tools/set-status.ts +0 -21
- package/src/extensions.ts +0 -179
- package/src/files-backends/agent-store-presigned-url.ts +0 -11
- package/src/files-backends/cursor-hosted.ts +0 -1212
- package/src/files-backends/local-fs.ts +0 -163
- package/src/files.ts +0 -293
- package/src/filesystem.ts +0 -2005
- package/src/hooks.ts +0 -30
- package/src/index.ts +0 -259
- package/src/internal/advertise-tools.ts +0 -370
- package/src/internal/approval-gate.ts +0 -103
- package/src/internal/artifacts-store.ts +0 -836
- package/src/internal/as-of.ts +0 -257
- package/src/internal/auth.ts +0 -46
- package/src/internal/authored-alias-hooks.ts +0 -138
- package/src/internal/authored-loaders.ts +0 -188
- package/src/internal/bounded-int.ts +0 -24
- package/src/internal/bounded.ts +0 -25
- package/src/internal/brand.ts +0 -28
- package/src/internal/browser-origin-guard.ts +0 -67
- package/src/internal/builtin-tools/artifacts.ts +0 -62
- package/src/internal/builtin-tools/index.ts +0 -53
- package/src/internal/builtin-tools/reminders.ts +0 -145
- package/src/internal/channel-dispatch.ts +0 -129
- package/src/internal/channel-route-dispatch.ts +0 -58
- package/src/internal/channel-state.ts +0 -83
- package/src/internal/chat-client.ts +0 -594
- package/src/internal/cli-ax.ts +0 -2318
- package/src/internal/cli-bitbucket.ts +0 -438
- package/src/internal/cli-convert-automation.ts +0 -335
- package/src/internal/cli-cursor.ts +0 -282
- package/src/internal/cli-deploy.ts +0 -2519
- package/src/internal/cli-docs.ts +0 -192
- package/src/internal/cli-github.ts +0 -806
- package/src/internal/cli-gitlab.ts +0 -452
- package/src/internal/cli-images.ts +0 -672
- package/src/internal/cli-manifest.ts +0 -56
- package/src/internal/cli-mcp-oauth.ts +0 -396
- package/src/internal/cli-mcp.ts +0 -808
- package/src/internal/cli-skills.ts +0 -98
- package/src/internal/cli-slack-manual.ts +0 -418
- package/src/internal/cli-slack.ts +0 -874
- package/src/internal/cloud-merge.ts +0 -51
- package/src/internal/cloud-turn-cost.ts +0 -159
- package/src/internal/connection-env.ts +0 -106
- package/src/internal/continuation-channel.ts +0 -233
- package/src/internal/continuation-identity.ts +0 -935
- package/src/internal/conversation-mirror.ts +0 -423
- package/src/internal/convert-automation/convert-workflow.ts +0 -1377
- package/src/internal/convert-automation/slug.ts +0 -29
- package/src/internal/convert-automation/types.ts +0 -212
- package/src/internal/cron.ts +0 -76
- package/src/internal/cursor/account-mcp.ts +0 -692
- package/src/internal/cursor/backend-client.ts +0 -984
- package/src/internal/cursor/bound-secret-file.ts +0 -101
- package/src/internal/cursor/credentials.ts +0 -560
- package/src/internal/cursor/cursor-api-transport.ts +0 -65
- package/src/internal/cursor/github-credentials.ts +0 -228
- package/src/internal/cursor/hosted-bound-secrets.ts +0 -71
- package/src/internal/cursor/hosted-deployment-secrets.ts +0 -100
- package/src/internal/cursor/hosted-store-secrets.ts +0 -152
- package/src/internal/cursor/session-token.ts +0 -111
- package/src/internal/cursor/store-api-client.ts +0 -323
- package/src/internal/cursor-account-mcp-auth.ts +0 -303
- package/src/internal/cursor-agent-template.ts +0 -50
- package/src/internal/cursor-deployment-relay.ts +0 -315
- package/src/internal/cursor-event-relay.ts +0 -675
- package/src/internal/cursor-relay-core.ts +0 -563
- package/src/internal/deferred-channel-session.ts +0 -61
- package/src/internal/deploy-client.ts +0 -1574
- package/src/internal/deploy-manifest.ts +0 -361
- package/src/internal/deploy-source.ts +0 -144
- package/src/internal/describe-error.ts +0 -32
- package/src/internal/dev-mode.ts +0 -20
- package/src/internal/discovery/agent-config.ts +0 -288
- package/src/internal/discovery/agent.ts +0 -381
- package/src/internal/discovery/channels.ts +0 -100
- package/src/internal/discovery/connections.ts +0 -516
- package/src/internal/discovery/context.ts +0 -38
- package/src/internal/discovery/cursor-plugin.ts +0 -628
- package/src/internal/discovery/extension-overlay.ts +0 -247
- package/src/internal/discovery/extensions.ts +0 -490
- package/src/internal/discovery/fs.ts +0 -103
- package/src/internal/discovery/hooks.ts +0 -63
- package/src/internal/discovery/info.ts +0 -174
- package/src/internal/discovery/instructions.ts +0 -98
- package/src/internal/discovery/modules.ts +0 -107
- package/src/internal/discovery/names.ts +0 -45
- package/src/internal/discovery/project.ts +0 -319
- package/src/internal/discovery/reminders.ts +0 -65
- package/src/internal/discovery/runtime.ts +0 -158
- package/src/internal/discovery/schedules.ts +0 -120
- package/src/internal/discovery/seed-files.ts +0 -34
- package/src/internal/discovery/services.ts +0 -151
- package/src/internal/discovery/skills.ts +0 -174
- package/src/internal/discovery/subagent.ts +0 -138
- package/src/internal/discovery/tools.ts +0 -170
- package/src/internal/discovery.ts +0 -27
- package/src/internal/distribution.ts +0 -126
- package/src/internal/docs-site.ts +0 -248
- package/src/internal/duration.ts +0 -37
- package/src/internal/env-file.ts +0 -83
- package/src/internal/eval-judge-model.ts +0 -142
- package/src/internal/eval-run-store.ts +0 -585
- package/src/internal/eval-runner.ts +0 -823
- package/src/internal/evals-client.ts +0 -475
- package/src/internal/event-log.ts +0 -342
- package/src/internal/event-mapper.ts +0 -811
- package/src/internal/expected-delivery-failure.ts +0 -34
- package/src/internal/factory-resource-channel.ts +0 -103
- package/src/internal/filesystem/errors.ts +0 -207
- package/src/internal/filesystem/format.ts +0 -253
- package/src/internal/filesystem/merge.ts +0 -192
- package/src/internal/filesystem/nearest.ts +0 -112
- package/src/internal/filesystem/scratch.ts +0 -239
- package/src/internal/filesystem/sdk-schemas.ts +0 -204
- package/src/internal/filesystem/tools.ts +0 -804
- package/src/internal/filesystem/walk.ts +0 -366
- package/src/internal/fixtures/units-server.ts +0 -52
- package/src/internal/framework-file-storage.ts +0 -357
- package/src/internal/framework-storage-selection.ts +0 -156
- package/src/internal/frontmatter.ts +0 -108
- package/src/internal/github-fanout.ts +0 -144
- package/src/internal/guest-network.ts +0 -391
- package/src/internal/handleAgentServeTrigger.ts +0 -286
- package/src/internal/host-files.ts +0 -341
- package/src/internal/host-kv.ts +0 -81
- package/src/internal/host-otel.ts +0 -231
- package/src/internal/host-platforms.ts +0 -170
- package/src/internal/hosted-admission-adapter.ts +0 -47
- package/src/internal/hosted-admission-context.ts +0 -37
- package/src/internal/hosted-catch-protocol.ts +0 -112
- package/src/internal/hosted-catch.ts +0 -179
- package/src/internal/hosted-delivery-protocol.ts +0 -824
- package/src/internal/hosted-delivery.ts +0 -1410
- package/src/internal/hosted-execution-diag.ts +0 -291
- package/src/internal/hosted-execution-flush.ts +0 -136
- package/src/internal/hosted-execution-latency.ts +0 -301
- package/src/internal/hosted-managed-automation.ts +0 -116
- package/src/internal/hosting.ts +0 -114
- package/src/internal/http-channel-define.ts +0 -25
- package/src/internal/http-channel.ts +0 -669
- package/src/internal/http-control-plane-session.ts +0 -110
- package/src/internal/ids.ts +0 -39
- package/src/internal/incoming-headers-to-fetch.ts +0 -45
- package/src/internal/init-interview.ts +0 -360
- package/src/internal/init-project.ts +0 -711
- package/src/internal/init-scaffold.ts +0 -182
- package/src/internal/inline-stdio-define-stub.ts +0 -4
- package/src/internal/inline-stdio-mcp.ts +0 -230
- package/src/internal/install-cursor-skills.ts +0 -604
- package/src/internal/is-record.ts +0 -3
- package/src/internal/json-schema.ts +0 -95
- package/src/internal/legacy-command-guard.ts +0 -66
- package/src/internal/listen-port.ts +0 -85
- package/src/internal/local-control-plane.ts +0 -442
- package/src/internal/local-env.ts +0 -59
- package/src/internal/local-ingress.ts +0 -90
- package/src/internal/log-ring.ts +0 -59
- package/src/internal/logs-client.ts +0 -477
- package/src/internal/map-pool.ts +0 -39
- package/src/internal/mcp-endpoint.ts +0 -747
- package/src/internal/mcp-host.ts +0 -509
- package/src/internal/mcp-oauth-on-demand.ts +0 -337
- package/src/internal/mcp-oauth-persist.ts +0 -118
- package/src/internal/mcp-oauth.ts +0 -549
- package/src/internal/net.ts +0 -29
- package/src/internal/open-browser.ts +0 -41
- package/src/internal/otel/attrs.ts +0 -16
- package/src/internal/otel/collector.ts +0 -937
- package/src/internal/otel/config.ts +0 -287
- package/src/internal/otel/http.ts +0 -122
- package/src/internal/otel/mcp.ts +0 -56
- package/src/internal/otel/propagation.ts +0 -17
- package/src/internal/otel/runtime.ts +0 -441
- package/src/internal/package-inline-stdio.ts +0 -114
- package/src/internal/peer-connections.ts +0 -96
- package/src/internal/platform-schedule-sync.ts +0 -75
- package/src/internal/platform-timers.ts +0 -365
- package/src/internal/playground/static.ts +0 -278
- package/src/internal/playground/toolchain.ts +0 -270
- package/src/internal/playground-proxy.ts +0 -564
- package/src/internal/process-memory-telemetry.ts +0 -334
- package/src/internal/project-layout.ts +0 -31
- package/src/internal/prompt-context.ts +0 -116
- package/src/internal/reminder-control-plane-protocol.ts +0 -482
- package/src/internal/reminder-runner.ts +0 -1559
- package/src/internal/reminder-schedule.ts +0 -104
- package/src/internal/reminder-store.ts +0 -176
- package/src/internal/request-error-status.ts +0 -95
- package/src/internal/request-headers.ts +0 -21
- package/src/internal/resolve-prod-target.ts +0 -334
- package/src/internal/resolved-connections.ts +0 -190
- package/src/internal/router.ts +0 -143
- package/src/internal/run-client.ts +0 -354
- package/src/internal/runtime-dispatch-runner.ts +0 -50
- package/src/internal/sanitize-mcp-tool-name.ts +0 -31
- package/src/internal/schedule-runner.ts +0 -154
- package/src/internal/scm/pr-url.ts +0 -245
- package/src/internal/sdk-runner.ts +0 -959
- package/src/internal/serve-restart.ts +0 -113
- package/src/internal/server.ts +0 -3147
- package/src/internal/session-cost.ts +0 -208
- package/src/internal/session-engine.ts +0 -5622
- package/src/internal/session-links.ts +0 -84
- package/src/internal/session-run-log.ts +0 -535
- package/src/internal/session-store.ts +0 -307
- package/src/internal/session-urls.ts +0 -32
- package/src/internal/sessions-client.ts +0 -239
- package/src/internal/skill-catalog.ts +0 -66
- package/src/internal/skills-sync.ts +0 -55
- package/src/internal/slack-provision-client.ts +0 -544
- package/src/internal/slack-thread-key.ts +0 -11
- package/src/internal/sleep.ts +0 -3
- package/src/internal/start-log-store.ts +0 -164
- package/src/internal/steering.ts +0 -17
- package/src/internal/storage-coordinator.ts +0 -800
- package/src/internal/storage-roles.ts +0 -86
- package/src/internal/storage.ts +0 -1
- package/src/internal/store-api-protocol.ts +0 -205
- package/src/internal/store-mirror.ts +0 -73
- package/src/internal/stream-progress.ts +0 -294
- package/src/internal/terminal-style.ts +0 -133
- package/src/internal/testing/factory-resource-fixtures.ts +0 -84
- package/src/internal/testing/scm-continuation-fixtures.ts +0 -285
- package/src/internal/tool-catalog.ts +0 -104
- package/src/internal/tool-policy.ts +0 -222
- package/src/internal/tool-result.ts +0 -50
- package/src/internal/trajectory.ts +0 -418
- package/src/internal/turn-cost.ts +0 -136
- package/src/internal/turn-governor.ts +0 -145
- package/src/internal/turn-lease-store.ts +0 -144
- package/src/internal/turn-outbox.ts +0 -77
- package/src/internal/update-check.ts +0 -517
- package/src/internal/v2-hosting.ts +0 -52
- package/src/internal/workspace-sync.ts +0 -114
- package/src/internal/workspace.ts +0 -505
- package/src/kv/memory-kv.ts +0 -94
- package/src/kv.ts +0 -18
- package/src/memory.ts +0 -487
- package/src/otel-public.ts +0 -24
- package/src/otel.ts +0 -320
- package/src/prompt.ts +0 -80
- package/src/reminders.ts +0 -65
- package/src/schedules.ts +0 -31
- package/src/skills.ts +0 -27
- package/src/storage-backends/cursor-hosted-v2.ts +0 -204
- package/src/storage-backends/cursor-hosted.ts +0 -388
- package/src/storage-backends/file-kv.ts +0 -276
- package/src/storage-protocol.ts +0 -261
- package/src/storage.ts +0 -408
- package/src/tools.ts +0 -166
- package/src/types.ts +0 -3776
- /package/dist/docs/assets/{reference_agent-config.md.DzGI777n.lean.js → reference_agent-config.md.Cj5uBKp4.lean.js} +0 -0
|
@@ -1,335 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* `bdk convert-automation <url>` — export a Cursor Automation into a BDK
|
|
3
|
-
* project.
|
|
4
|
-
*
|
|
5
|
-
* Fetches the automation's workflow from the backend export endpoint
|
|
6
|
-
* (Bearer user API key, same credential chain as deploy), runs the pure
|
|
7
|
-
* converter, writes the converted files (wx — existing files are kept),
|
|
8
|
-
* fills in the init scaffold around them, and installs npm dependencies
|
|
9
|
-
* (like `init`). MCP servers convert to Cursor-account connections resolved
|
|
10
|
-
* at runtime (no URLs or credentials in the project; authorization is
|
|
11
|
-
* managed in Cursor, dashboard → MCP). The generated project is NEVER
|
|
12
|
-
* imported/executed here — it embeds server-derived data, so checking it is
|
|
13
|
-
* left to an explicit `validate` next step the user runs after review.
|
|
14
|
-
* Exit 0 even with warnings; nonzero only for bad args, auth/fetch
|
|
15
|
-
* failures, or filesystem write failures.
|
|
16
|
-
*/
|
|
17
|
-
|
|
18
|
-
import { mkdir, rm, writeFile } from "node:fs/promises";
|
|
19
|
-
import { dirname, join, resolve } from "node:path";
|
|
20
|
-
import { convertWorkflow } from "./convert-automation/convert-workflow.js";
|
|
21
|
-
import { slugify } from "./convert-automation/slug.js";
|
|
22
|
-
import type {
|
|
23
|
-
ConvertedMcpConnection,
|
|
24
|
-
ConvertWorkflowResult,
|
|
25
|
-
WorkflowJson,
|
|
26
|
-
} from "./convert-automation/types.js";
|
|
27
|
-
import { cursorExternalApiUrl, resolveApiKey, SIGN_IN_HINT } from "./cursor/credentials.js";
|
|
28
|
-
import { AgentServeDeployClient, type AutomationExport, DeployApiError } from "./deploy-client.js";
|
|
29
|
-
import { CLI_COMMAND_NAME as CLI } from "./distribution.js";
|
|
30
|
-
import {
|
|
31
|
-
formatCdCommand,
|
|
32
|
-
type InitFileEntry,
|
|
33
|
-
initProject,
|
|
34
|
-
installScaffoldDependencies,
|
|
35
|
-
isEexist,
|
|
36
|
-
} from "./init-project.js";
|
|
37
|
-
import { type ProjectRoot, projectPath, resolveProjectRoot } from "./project-layout.js";
|
|
38
|
-
import { stdoutPalette } from "./terminal-style.js";
|
|
39
|
-
|
|
40
|
-
export interface ConvertAutomationCliOptions {
|
|
41
|
-
/** Positional: automation URL or bare uuid. */
|
|
42
|
-
url?: string;
|
|
43
|
-
/** Target directory; defaults to ./<automation-name-slug>. */
|
|
44
|
-
dir?: string;
|
|
45
|
-
json?: boolean;
|
|
46
|
-
apiKey?: string;
|
|
47
|
-
/** Test seams. */
|
|
48
|
-
fetchImpl?: typeof fetch;
|
|
49
|
-
out?: (text: string) => void;
|
|
50
|
-
err?: (text: string) => void;
|
|
51
|
-
installImpl?: typeof installScaffoldDependencies;
|
|
52
|
-
cwd?: string;
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
const UUID_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
56
|
-
|
|
57
|
-
/**
|
|
58
|
-
* Extract the automation uuid from a dashboard URL
|
|
59
|
-
* (`/automations/<uuid>` or `/custom-agents/<uuid>`, any origin — dev
|
|
60
|
-
* hosts included) or a bare uuid. Undefined when nothing matches.
|
|
61
|
-
*/
|
|
62
|
-
export function parseAutomationRef(input: string): string | undefined {
|
|
63
|
-
const trimmed = input.trim();
|
|
64
|
-
if (UUID_PATTERN.test(trimmed)) {
|
|
65
|
-
return trimmed.toLowerCase();
|
|
66
|
-
}
|
|
67
|
-
let parsed: URL;
|
|
68
|
-
try {
|
|
69
|
-
parsed = new URL(trimmed);
|
|
70
|
-
} catch {
|
|
71
|
-
return undefined;
|
|
72
|
-
}
|
|
73
|
-
if (parsed.protocol !== "http:" && parsed.protocol !== "https:") {
|
|
74
|
-
return undefined;
|
|
75
|
-
}
|
|
76
|
-
const segments = parsed.pathname.split("/").filter(s => s !== "");
|
|
77
|
-
if (segments.length !== 2) {
|
|
78
|
-
return undefined;
|
|
79
|
-
}
|
|
80
|
-
const [kind, uuid] = segments;
|
|
81
|
-
if (kind !== "automations" && kind !== "custom-agents") {
|
|
82
|
-
return undefined;
|
|
83
|
-
}
|
|
84
|
-
if (uuid === undefined || !UUID_PATTERN.test(uuid)) {
|
|
85
|
-
return undefined;
|
|
86
|
-
}
|
|
87
|
-
return uuid.toLowerCase();
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
export async function cmdConvertAutomation(options: ConvertAutomationCliOptions): Promise<number> {
|
|
91
|
-
const out = options.out ?? ((text: string) => void process.stdout.write(text));
|
|
92
|
-
const err = options.err ?? ((text: string) => void process.stderr.write(text));
|
|
93
|
-
const json = options.json === true;
|
|
94
|
-
// Failures stay machine-readable under --json (stderr keeps the prose).
|
|
95
|
-
const fail = (message: string): 1 => {
|
|
96
|
-
if (json) {
|
|
97
|
-
out(`${JSON.stringify({ ok: false, error: message })}\n`);
|
|
98
|
-
}
|
|
99
|
-
err(`${message}\n`);
|
|
100
|
-
return 1;
|
|
101
|
-
};
|
|
102
|
-
|
|
103
|
-
if (options.url === undefined || options.url.trim() === "") {
|
|
104
|
-
return fail(
|
|
105
|
-
`Usage: ${CLI} convert-automation <automation-url-or-uuid> [--dir <path>] [--json]`,
|
|
106
|
-
);
|
|
107
|
-
}
|
|
108
|
-
const uuid = parseAutomationRef(options.url);
|
|
109
|
-
if (uuid === undefined) {
|
|
110
|
-
return fail(
|
|
111
|
-
`Could not parse ${JSON.stringify(options.url)} — expected an automation URL (https://cursor.com/automations/<uuid> or .../custom-agents/<uuid>) or a bare uuid.`,
|
|
112
|
-
);
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
const resolved = await resolveApiKey({ apiKey: options.apiKey });
|
|
116
|
-
if (resolved === undefined) {
|
|
117
|
-
return fail(`Not signed in to Cursor. ${SIGN_IN_HINT}`);
|
|
118
|
-
}
|
|
119
|
-
const client = new AgentServeDeployClient({
|
|
120
|
-
backendUrl: cursorExternalApiUrl(),
|
|
121
|
-
apiKey: resolved.apiKey,
|
|
122
|
-
fetchImpl: options.fetchImpl,
|
|
123
|
-
});
|
|
124
|
-
|
|
125
|
-
let payload: AutomationExport;
|
|
126
|
-
try {
|
|
127
|
-
payload = await client.exportAutomation({ uuid });
|
|
128
|
-
} catch (error) {
|
|
129
|
-
if (error instanceof DeployApiError) {
|
|
130
|
-
return fail(error.message);
|
|
131
|
-
}
|
|
132
|
-
throw error;
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
const displayDir = options.dir ?? `./${slugify(payload.automation.name, "automation")}`;
|
|
136
|
-
const rootDir = resolve(options.cwd ?? process.cwd(), displayDir);
|
|
137
|
-
const projectRoot = resolveProjectRoot(rootDir);
|
|
138
|
-
const result = convertWorkflow({
|
|
139
|
-
automation: payload.automation,
|
|
140
|
-
workflow: payload.workflow as WorkflowJson,
|
|
141
|
-
mcpServers: payload.mcpServers,
|
|
142
|
-
exportedAt: new Date().toISOString(),
|
|
143
|
-
projectRoot,
|
|
144
|
-
});
|
|
145
|
-
|
|
146
|
-
let files: InitFileEntry[];
|
|
147
|
-
try {
|
|
148
|
-
files = await writeProjectFiles(rootDir, result, projectRoot);
|
|
149
|
-
} catch (error) {
|
|
150
|
-
return fail(`Could not write project files under ${rootDir}: ${describe(error)}`);
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
// Same npm install as `init`, so the printed `validate` / `dev` next steps
|
|
154
|
-
// work immediately. Failure (npm exit or spawn error) is loud but never
|
|
155
|
-
// fails the conversion.
|
|
156
|
-
const install = options.installImpl ?? installScaffoldDependencies;
|
|
157
|
-
if (!json) {
|
|
158
|
-
out("\nInstalling npm packages\n");
|
|
159
|
-
}
|
|
160
|
-
let installed: Awaited<ReturnType<typeof installScaffoldDependencies>>;
|
|
161
|
-
try {
|
|
162
|
-
installed = await install(rootDir, {
|
|
163
|
-
stdio: json ? "pipe" : "inherit",
|
|
164
|
-
});
|
|
165
|
-
} catch (error) {
|
|
166
|
-
installed = { ok: false, exitCode: -1, stderr: describe(error) };
|
|
167
|
-
}
|
|
168
|
-
if (!installed.ok && !json) {
|
|
169
|
-
const reason = installed.stderr.trim() || `exit ${installed.exitCode}`;
|
|
170
|
-
err(
|
|
171
|
-
`npm install failed (${reason}); run \`npm install\` in ${displayDir} before \`${CLI} dev\`.\n`,
|
|
172
|
-
);
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
if (json) {
|
|
176
|
-
out(
|
|
177
|
-
`${JSON.stringify(
|
|
178
|
-
{
|
|
179
|
-
ok: true,
|
|
180
|
-
directory: rootDir,
|
|
181
|
-
files: files.map(({ path, action }) => ({ path, action })),
|
|
182
|
-
warnings: result.warnings,
|
|
183
|
-
setupSteps: result.setupSteps,
|
|
184
|
-
installed: installed.ok,
|
|
185
|
-
installError: installed.ok
|
|
186
|
-
? null
|
|
187
|
-
: installed.stderr.trim() || `npm install exited ${installed.exitCode}`,
|
|
188
|
-
mcpConnections: result.mcpConnections.map(connection => ({
|
|
189
|
-
name: connection.name,
|
|
190
|
-
kind: connection.kind,
|
|
191
|
-
})),
|
|
192
|
-
},
|
|
193
|
-
null,
|
|
194
|
-
2,
|
|
195
|
-
)}\n`,
|
|
196
|
-
);
|
|
197
|
-
return 0;
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
out(
|
|
201
|
-
renderSummary({
|
|
202
|
-
automationName: payload.automation.name,
|
|
203
|
-
displayDir,
|
|
204
|
-
rootDir,
|
|
205
|
-
cwd: options.cwd ?? process.cwd(),
|
|
206
|
-
files,
|
|
207
|
-
result,
|
|
208
|
-
}),
|
|
209
|
-
);
|
|
210
|
-
return 0;
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
/**
|
|
214
|
-
* Converter files first (wx — existing files are kept), then the init
|
|
215
|
-
* scaffold fills in around them with the same skip-existing semantics.
|
|
216
|
-
*/
|
|
217
|
-
async function writeProjectFiles(
|
|
218
|
-
rootDir: string,
|
|
219
|
-
result: ConvertWorkflowResult,
|
|
220
|
-
projectRoot: ProjectRoot,
|
|
221
|
-
): Promise<InitFileEntry[]> {
|
|
222
|
-
const entries: InitFileEntry[] = [];
|
|
223
|
-
const converterPaths = new Set<string>();
|
|
224
|
-
await mkdir(rootDir, { recursive: true });
|
|
225
|
-
for (const file of result.files) {
|
|
226
|
-
const path = file.path;
|
|
227
|
-
converterPaths.add(path);
|
|
228
|
-
const abs = join(rootDir, path);
|
|
229
|
-
await mkdir(dirname(abs), { recursive: true });
|
|
230
|
-
try {
|
|
231
|
-
await writeFile(abs, file.contents, { flag: "wx" });
|
|
232
|
-
entries.push({ path, action: "create" });
|
|
233
|
-
} catch (error) {
|
|
234
|
-
if (!isEexist(error)) {
|
|
235
|
-
throw error;
|
|
236
|
-
}
|
|
237
|
-
entries.push({ path, action: "exist" });
|
|
238
|
-
}
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
const init = await initProject({ dir: rootDir });
|
|
242
|
-
|
|
243
|
-
// Scaffold files that make sense in a fresh `init` but not in an exported
|
|
244
|
-
// automation: the default memory hook (only when the automation had memory
|
|
245
|
-
// enabled — the converter emits its own copy then) and the echo demo tool.
|
|
246
|
-
const dropPaths = new Set<string>();
|
|
247
|
-
for (const scaffoldPath of [
|
|
248
|
-
projectPath(projectRoot, "hooks/memory.ts"),
|
|
249
|
-
projectPath(projectRoot, "tools/echo.ts"),
|
|
250
|
-
]) {
|
|
251
|
-
if (!converterPaths.has(scaffoldPath) && init.created.includes(scaffoldPath)) {
|
|
252
|
-
dropPaths.add(scaffoldPath);
|
|
253
|
-
await rm(join(rootDir, scaffoldPath));
|
|
254
|
-
}
|
|
255
|
-
}
|
|
256
|
-
for (const entry of init.files) {
|
|
257
|
-
if (converterPaths.has(entry.path) || dropPaths.has(entry.path)) {
|
|
258
|
-
continue;
|
|
259
|
-
}
|
|
260
|
-
entries.push(entry);
|
|
261
|
-
}
|
|
262
|
-
return entries;
|
|
263
|
-
}
|
|
264
|
-
|
|
265
|
-
function renderSummary(args: {
|
|
266
|
-
automationName: string;
|
|
267
|
-
displayDir: string;
|
|
268
|
-
rootDir: string;
|
|
269
|
-
cwd: string;
|
|
270
|
-
files: InitFileEntry[];
|
|
271
|
-
result: ConvertWorkflowResult;
|
|
272
|
-
}): string {
|
|
273
|
-
const c = stdoutPalette();
|
|
274
|
-
const lines: string[] = [];
|
|
275
|
-
lines.push("");
|
|
276
|
-
lines.push(`Converted "${args.automationName}" → ${args.displayDir}`);
|
|
277
|
-
lines.push("");
|
|
278
|
-
let anyExisting = false;
|
|
279
|
-
for (const file of args.files) {
|
|
280
|
-
if (file.path.endsWith(".gitkeep")) {
|
|
281
|
-
continue;
|
|
282
|
-
}
|
|
283
|
-
anyExisting ||= file.action === "exist";
|
|
284
|
-
lines.push(c.dim(`${file.action.padStart(12)} ${file.path}`));
|
|
285
|
-
}
|
|
286
|
-
if (anyExisting) {
|
|
287
|
-
lines.push(c.dim(`\n "exist" files already existed and were kept as-is.`));
|
|
288
|
-
}
|
|
289
|
-
|
|
290
|
-
const warnings = args.result.warnings;
|
|
291
|
-
if (warnings.length > 0) {
|
|
292
|
-
lines.push("");
|
|
293
|
-
lines.push("Warnings:");
|
|
294
|
-
for (const warning of warnings) {
|
|
295
|
-
lines.push(` - ${warning}`);
|
|
296
|
-
}
|
|
297
|
-
}
|
|
298
|
-
|
|
299
|
-
if (args.result.setupSteps.length > 0) {
|
|
300
|
-
lines.push("");
|
|
301
|
-
lines.push("Setup steps:");
|
|
302
|
-
for (const [index, step] of args.result.setupSteps.entries()) {
|
|
303
|
-
lines.push(` ${index + 1}. ${step}`);
|
|
304
|
-
}
|
|
305
|
-
}
|
|
306
|
-
|
|
307
|
-
if (args.result.mcpConnections.length > 0) {
|
|
308
|
-
lines.push("");
|
|
309
|
-
lines.push("MCP connections:");
|
|
310
|
-
for (const connection of args.result.mcpConnections) {
|
|
311
|
-
lines.push(` - ${connection.name}: ${connectionStatus(connection)}`);
|
|
312
|
-
}
|
|
313
|
-
}
|
|
314
|
-
|
|
315
|
-
lines.push("");
|
|
316
|
-
lines.push("Next steps:");
|
|
317
|
-
const cd = formatCdCommand(args.cwd, args.rootDir);
|
|
318
|
-
const steps = [...(cd === undefined ? [] : [cd]), `${CLI} validate`, `${CLI} dev`];
|
|
319
|
-
for (const [index, step] of steps.entries()) {
|
|
320
|
-
lines.push(` ${index + 1}. ${step}`);
|
|
321
|
-
}
|
|
322
|
-
lines.push("");
|
|
323
|
-
return `${lines.join("\n")}\n`;
|
|
324
|
-
}
|
|
325
|
-
|
|
326
|
-
function connectionStatus(connection: ConvertedMcpConnection): string {
|
|
327
|
-
if (connection.kind === "cursorAccount") {
|
|
328
|
-
return "resolved from your Cursor account at runtime — manage authorization in Cursor (dashboard → MCP)";
|
|
329
|
-
}
|
|
330
|
-
return "needs manual setup — see the stub file and warnings above";
|
|
331
|
-
}
|
|
332
|
-
|
|
333
|
-
function describe(error: unknown): string {
|
|
334
|
-
return error instanceof Error ? error.message : String(error);
|
|
335
|
-
}
|
|
@@ -1,282 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* `agent-sdk login | logout | whoami` — the Cursor account CLI.
|
|
3
|
-
*
|
|
4
|
-
* `login` runs the same PKCE browser flow as `cursor-agent`, then uses the
|
|
5
|
-
* short-lived session exactly once to mint a named, dashboard-revocable
|
|
6
|
-
* user API key. Only the key is stored (see `../cursor/credentials.ts`);
|
|
7
|
-
* everything on the host — inference, cloud runtime, account MCP
|
|
8
|
-
* connections — flows from it.
|
|
9
|
-
*/
|
|
10
|
-
|
|
11
|
-
import { hostname } from "node:os";
|
|
12
|
-
import {
|
|
13
|
-
CursorBackendClient,
|
|
14
|
-
CursorBackendError,
|
|
15
|
-
type CursorIdentity,
|
|
16
|
-
createUserApiKeyWithSessionToken,
|
|
17
|
-
revokeMintedUserApiKey,
|
|
18
|
-
} from "./cursor/backend-client.js";
|
|
19
|
-
import {
|
|
20
|
-
type ApiKeySource,
|
|
21
|
-
clearStoredCredentials,
|
|
22
|
-
credentialsFilePath,
|
|
23
|
-
cursorBackendUrl,
|
|
24
|
-
type LoginPollResult,
|
|
25
|
-
pollForLoginTokens,
|
|
26
|
-
readStoredCredentials,
|
|
27
|
-
resolveApiKey,
|
|
28
|
-
SIGN_IN_HINT,
|
|
29
|
-
startBrowserLogin,
|
|
30
|
-
writeStoredCredentials,
|
|
31
|
-
} from "./cursor/credentials.js";
|
|
32
|
-
import { describeError } from "./describe-error.js";
|
|
33
|
-
import { CLI_COMMAND_NAME } from "./distribution.js";
|
|
34
|
-
import { openBrowser } from "./open-browser.js";
|
|
35
|
-
import { stderrPalette, stdoutPalette } from "./terminal-style.js";
|
|
36
|
-
|
|
37
|
-
export interface CursorCliOptions {
|
|
38
|
-
/** `login --api-key <key>`: store this key instead of browser login. */
|
|
39
|
-
apiKey?: string;
|
|
40
|
-
/** `login --key-name <name>`: label for the minted key. */
|
|
41
|
-
keyName?: string;
|
|
42
|
-
json?: boolean;
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
export async function cmdLogin(options: CursorCliOptions): Promise<number> {
|
|
46
|
-
const backendUrl = cursorBackendUrl();
|
|
47
|
-
const err = stderrPalette();
|
|
48
|
-
const out = stdoutPalette();
|
|
49
|
-
|
|
50
|
-
let apiKey: string;
|
|
51
|
-
// Set only on the browser-mint path; carries what the revoke-on-failure
|
|
52
|
-
// cleanup needs (the session token that minted the key + its label).
|
|
53
|
-
let minted: { keyName: string; sessionToken: string } | undefined;
|
|
54
|
-
if (options.apiKey !== undefined && options.apiKey.trim() !== "") {
|
|
55
|
-
// Headless path: the operator brings a key (dashboard → Integrations).
|
|
56
|
-
apiKey = options.apiKey.trim();
|
|
57
|
-
} else {
|
|
58
|
-
const { loginUrl, uuid, verifier } = startBrowserLogin();
|
|
59
|
-
process.stderr.write(
|
|
60
|
-
err.dim(
|
|
61
|
-
`Opening your browser to sign in to Cursor…\n\n ${loginUrl}\n\n(waiting for the browser sign-in to complete)\n`,
|
|
62
|
-
),
|
|
63
|
-
);
|
|
64
|
-
openBrowser(loginUrl);
|
|
65
|
-
const login = await pollForLoginTokens({
|
|
66
|
-
uuid,
|
|
67
|
-
verifier,
|
|
68
|
-
backendUrl,
|
|
69
|
-
logger: line => process.stderr.write(`warning: ${line}\n`),
|
|
70
|
-
});
|
|
71
|
-
if (login.status !== "signed_in") {
|
|
72
|
-
process.stderr.write(`${describeLoginPollFailure(login)}\n`);
|
|
73
|
-
return 1;
|
|
74
|
-
}
|
|
75
|
-
const requestedKeyName = options.keyName?.trim();
|
|
76
|
-
const keyName =
|
|
77
|
-
requestedKeyName === undefined || requestedKeyName === ""
|
|
78
|
-
? `${CLI_COMMAND_NAME} (${hostname()})`
|
|
79
|
-
: requestedKeyName;
|
|
80
|
-
try {
|
|
81
|
-
apiKey = await createUserApiKeyWithSessionToken({
|
|
82
|
-
backendUrl,
|
|
83
|
-
sessionToken: login.accessToken,
|
|
84
|
-
keyName,
|
|
85
|
-
});
|
|
86
|
-
} catch (error) {
|
|
87
|
-
if (error instanceof CursorBackendError && error.status === 401) {
|
|
88
|
-
// Team policy: non-admin members may be blocked from minting keys.
|
|
89
|
-
process.stderr.write(
|
|
90
|
-
`${error.message}\nYour team may restrict API key creation. Ask a team admin, or run \`${CLI_COMMAND_NAME} login --api-key <key>\` with a key from the Cursor dashboard.\n`,
|
|
91
|
-
);
|
|
92
|
-
return 1;
|
|
93
|
-
}
|
|
94
|
-
throw error;
|
|
95
|
-
}
|
|
96
|
-
minted = { keyName, sessionToken: login.accessToken };
|
|
97
|
-
process.stderr.write(err.dim(`Minted the "${keyName}" API key.\n`));
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
// Revoke the just-minted key when a later step fails, so a botched login
|
|
101
|
-
// never leaves an orphaned live credential (no-op on the headless path).
|
|
102
|
-
const rollbackMintedKey = async (): Promise<void> => {
|
|
103
|
-
if (minted !== undefined) {
|
|
104
|
-
await revokeMintedUserApiKey({
|
|
105
|
-
backendUrl,
|
|
106
|
-
keyName: minted.keyName,
|
|
107
|
-
apiKey,
|
|
108
|
-
sessionToken: minted.sessionToken,
|
|
109
|
-
}).catch(() => {});
|
|
110
|
-
}
|
|
111
|
-
};
|
|
112
|
-
|
|
113
|
-
// Prove the credential end-to-end (exchange + GetMe) before storing it.
|
|
114
|
-
const client = new CursorBackendClient({ backendUrl, apiKey });
|
|
115
|
-
let identity: CursorIdentity;
|
|
116
|
-
try {
|
|
117
|
-
identity = await client.getMe();
|
|
118
|
-
} catch (error) {
|
|
119
|
-
await rollbackMintedKey();
|
|
120
|
-
process.stderr.write(
|
|
121
|
-
`The API key did not authenticate against ${backendUrl}: ${describeError(error)}\n`,
|
|
122
|
-
);
|
|
123
|
-
return 1;
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
try {
|
|
127
|
-
await writeStoredCredentials({ backendUrl, apiKey });
|
|
128
|
-
} catch (error) {
|
|
129
|
-
await rollbackMintedKey();
|
|
130
|
-
process.stderr.write(
|
|
131
|
-
`Could not store credentials at ${credentialsFilePath()}: ${describeError(error)}\n`,
|
|
132
|
-
);
|
|
133
|
-
return 1;
|
|
134
|
-
}
|
|
135
|
-
process.stdout.write(
|
|
136
|
-
`Signed in as ${formatIdentity(identity)} (${backendUrl})\n${out.dim(
|
|
137
|
-
`Credentials stored at ${credentialsFilePath()}`,
|
|
138
|
-
)}\n`,
|
|
139
|
-
);
|
|
140
|
-
if (process.env.CURSOR_API_KEY !== undefined) {
|
|
141
|
-
process.stderr.write(
|
|
142
|
-
err.dim(
|
|
143
|
-
"note: CURSOR_API_KEY is set in this shell and takes precedence over the stored login.\n",
|
|
144
|
-
),
|
|
145
|
-
);
|
|
146
|
-
}
|
|
147
|
-
return 0;
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
/**
|
|
151
|
-
* Gate for commands that need a Cursor credential before they can do useful
|
|
152
|
-
* work (interactive `init`). Already-signed-in hosts
|
|
153
|
-
* (`--api-key` / `CURSOR_API_KEY` / `CURSOR_API_KEY_FILE` / stored login) return immediately.
|
|
154
|
-
* An interactive host runs {@link cmdLogin}; a non-interactive one (CI,
|
|
155
|
-
* Docker) fails fast with {@link SIGN_IN_HINT}
|
|
156
|
-
* instead of polling a browser that will never open.
|
|
157
|
-
*/
|
|
158
|
-
export async function ensureCursorLogin(
|
|
159
|
-
options: {
|
|
160
|
-
apiKey?: string;
|
|
161
|
-
/**
|
|
162
|
-
* Run the browser login flow when unsigned. Defaults to stderr being a
|
|
163
|
-
* TTY.
|
|
164
|
-
*/
|
|
165
|
-
interactive?: boolean;
|
|
166
|
-
/** Test seam. */
|
|
167
|
-
login?: (options: CursorCliOptions) => Promise<number>;
|
|
168
|
-
} = {},
|
|
169
|
-
): Promise<number> {
|
|
170
|
-
const resolved = await resolveApiKey({ apiKey: options.apiKey });
|
|
171
|
-
if (resolved !== undefined) {
|
|
172
|
-
return 0;
|
|
173
|
-
}
|
|
174
|
-
const interactive = options.interactive ?? process.stderr.isTTY === true;
|
|
175
|
-
if (!interactive) {
|
|
176
|
-
process.stderr.write(`Not signed in to Cursor. ${SIGN_IN_HINT}\n`);
|
|
177
|
-
return 1;
|
|
178
|
-
}
|
|
179
|
-
process.stdout.write("Signing you in to Cursor\n\n");
|
|
180
|
-
const login = options.login ?? cmdLogin;
|
|
181
|
-
return login({});
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
export async function cmdLogout(): Promise<number> {
|
|
185
|
-
const stored = await readStoredCredentials();
|
|
186
|
-
const removed = await clearStoredCredentials();
|
|
187
|
-
if (!removed || stored === undefined) {
|
|
188
|
-
process.stdout.write("No stored Cursor credentials.\n");
|
|
189
|
-
return 0;
|
|
190
|
-
}
|
|
191
|
-
process.stdout.write(
|
|
192
|
-
`Signed out (removed ${credentialsFilePath()}). The API key still exists — revoke it in the Cursor dashboard if it should stop working.\n`,
|
|
193
|
-
);
|
|
194
|
-
return 0;
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
export async function cmdWhoami(options: CursorCliOptions): Promise<number> {
|
|
198
|
-
const resolved = await resolveApiKey();
|
|
199
|
-
if (resolved === undefined) {
|
|
200
|
-
process.stderr.write(`Not signed in to Cursor. ${SIGN_IN_HINT}\n`);
|
|
201
|
-
return 1;
|
|
202
|
-
}
|
|
203
|
-
const client = new CursorBackendClient({
|
|
204
|
-
backendUrl: resolved.backendUrl,
|
|
205
|
-
apiKey: resolved.apiKey,
|
|
206
|
-
});
|
|
207
|
-
let identity: CursorIdentity;
|
|
208
|
-
try {
|
|
209
|
-
identity = await client.getMe();
|
|
210
|
-
} catch (error) {
|
|
211
|
-
process.stderr.write(
|
|
212
|
-
`The ${describeSource(resolved.source)} did not authenticate against ${resolved.backendUrl}: ${describeError(error)}\n`,
|
|
213
|
-
);
|
|
214
|
-
return 1;
|
|
215
|
-
}
|
|
216
|
-
if (options.json === true) {
|
|
217
|
-
process.stdout.write(
|
|
218
|
-
`${JSON.stringify(
|
|
219
|
-
{
|
|
220
|
-
email: identity.email ?? null,
|
|
221
|
-
authId: identity.authId ?? null,
|
|
222
|
-
teamName: identity.teamName ?? null,
|
|
223
|
-
backendUrl: resolved.backendUrl,
|
|
224
|
-
credentialSource: resolved.source,
|
|
225
|
-
},
|
|
226
|
-
null,
|
|
227
|
-
2,
|
|
228
|
-
)}\n`,
|
|
229
|
-
);
|
|
230
|
-
return 0;
|
|
231
|
-
}
|
|
232
|
-
process.stdout.write(
|
|
233
|
-
`${formatIdentity(identity)}\n backend: ${resolved.backendUrl}\n credential: ${describeSource(resolved.source)}\n`,
|
|
234
|
-
);
|
|
235
|
-
return 0;
|
|
236
|
-
}
|
|
237
|
-
|
|
238
|
-
function formatIdentity(identity: CursorIdentity): string {
|
|
239
|
-
const name = [identity.firstName, identity.lastName]
|
|
240
|
-
.filter(part => part !== undefined && part !== "")
|
|
241
|
-
.join(" ");
|
|
242
|
-
const email = identity.email ?? identity.authId ?? "(unknown user)";
|
|
243
|
-
const team = identity.teamName === undefined ? "" : ` — team ${identity.teamName}`;
|
|
244
|
-
return name === "" ? `${email}${team}` : `${name} <${email}>${team}`;
|
|
245
|
-
}
|
|
246
|
-
|
|
247
|
-
function describeSource(source: ApiKeySource): string {
|
|
248
|
-
switch (source) {
|
|
249
|
-
case "option":
|
|
250
|
-
return "explicit --api-key / serve({ apiKey })";
|
|
251
|
-
case "env":
|
|
252
|
-
return "CURSOR_API_KEY environment variable";
|
|
253
|
-
case "file":
|
|
254
|
-
return "CURSOR_API_KEY_FILE (task bind)";
|
|
255
|
-
case "service-account":
|
|
256
|
-
return "CURSOR_SERVICE_ACCOUNT_KEY environment variable";
|
|
257
|
-
case "login":
|
|
258
|
-
return `stored login (${credentialsFilePath()})`;
|
|
259
|
-
}
|
|
260
|
-
}
|
|
261
|
-
|
|
262
|
-
/**
|
|
263
|
-
* Never report a backend failure as a timeout: a wrong-verb poll used to print
|
|
264
|
-
* "Login timed out or was cancelled" ~200ms in, which reads as "you were too
|
|
265
|
-
* slow" and hides the actual 404.
|
|
266
|
-
*/
|
|
267
|
-
function describeLoginPollFailure(
|
|
268
|
-
result: Exclude<LoginPollResult, { status: "signed_in" }>,
|
|
269
|
-
): string {
|
|
270
|
-
switch (result.status) {
|
|
271
|
-
case "cancelled":
|
|
272
|
-
return "Login cancelled.";
|
|
273
|
-
case "timed_out":
|
|
274
|
-
return `Login timed out — the browser sign-in was never completed. Run \`${CLI_COMMAND_NAME} login\` to try again.`;
|
|
275
|
-
case "failed":
|
|
276
|
-
return [
|
|
277
|
-
`Login failed: ${result.message}`,
|
|
278
|
-
"This is not a timeout — the sign-in never got a chance to complete.",
|
|
279
|
-
`Sign in without the browser flow with \`${CLI_COMMAND_NAME} login --api-key <key>\` (Cursor dashboard → Integrations).`,
|
|
280
|
-
].join("\n");
|
|
281
|
-
}
|
|
282
|
-
}
|