@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,357 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Framework-level file storage for v2 hosted engines.
|
|
3
|
-
*
|
|
4
|
-
* Hosted deployments carry two file stores with different audiences:
|
|
5
|
-
*
|
|
6
|
-
* - the **user-level** store (`AGENT_SERVE_STORE_SOURCE_ID`) holds
|
|
7
|
-
* author-facing bytes — `ctx.host.files`, skills, memory, artifacts — and
|
|
8
|
-
* is browsable from the dashboard and mountable on cloud-runtime VMs;
|
|
9
|
-
* - the **framework-level** store (`AGENT_SERVE_FRAMEWORK_STORE_SOURCE_ID`)
|
|
10
|
-
* holds engine-owned session state — session records, event transcripts,
|
|
11
|
-
* hosted-execution run logs, the continuation index, and the SDK
|
|
12
|
-
* conversation mirror — and is never mounted into author code or models.
|
|
13
|
-
* The authenticated dashboard may read diagnostic families, but never the
|
|
14
|
-
* continuation index.
|
|
15
|
-
*
|
|
16
|
-
* This module puts framework session state on the framework store. The
|
|
17
|
-
* {@link storageKeys} scheme was designed for exactly this: keys are a
|
|
18
|
-
* stable versioned contract that sinks may route on, so
|
|
19
|
-
* {@link composeFrameworkStorage} splits one {@link StorageConfig} by key
|
|
20
|
-
* kind — `session` / `session-events` / `session-runs` / `logs` /
|
|
21
|
-
* `continuation` go to the framework file store (file-shaped; the store
|
|
22
|
-
* accepts values up to 64 MiB per
|
|
23
|
-
* object without chunking, versus the KV proxy's 1 MiB row cap), while
|
|
24
|
-
* author `kv`, eval runs, and conditional writes stay on the control-plane
|
|
25
|
-
* KV proxy (the dashboard reads them there, and CAS needs a database).
|
|
26
|
-
*
|
|
27
|
-
* v2 only, by construction: the composite is selected in
|
|
28
|
-
* framework-storage-selection.ts, which v1 never reaches with a
|
|
29
|
-
* platform-selected definition.
|
|
30
|
-
*/
|
|
31
|
-
|
|
32
|
-
import type { FileSink } from "../files.js";
|
|
33
|
-
import type { StorageConfig, StorageEntry } from "../storage.js";
|
|
34
|
-
import { AGENTSDK_STORAGE_KEY_ROOT } from "../storage-protocol.js";
|
|
35
|
-
import type { JsonValue } from "../types.js";
|
|
36
|
-
import { mapBounded } from "./bounded.js";
|
|
37
|
-
|
|
38
|
-
/**
|
|
39
|
-
* Key kinds (`agentsdk/v1/{agent}/{kind}/…`) that live on the framework
|
|
40
|
-
* file store. Everything else stays on the KV sink.
|
|
41
|
-
*/
|
|
42
|
-
const FRAMEWORK_FILE_KINDS: ReadonlySet<string> = new Set([
|
|
43
|
-
"session",
|
|
44
|
-
"session-events",
|
|
45
|
-
"session-runs",
|
|
46
|
-
"logs",
|
|
47
|
-
"continuation",
|
|
48
|
-
]);
|
|
49
|
-
|
|
50
|
-
/**
|
|
51
|
-
* Whether a framework-minted key (or list prefix) belongs on the framework
|
|
52
|
-
* file store. Prefixes used by the coordinator are always at least
|
|
53
|
-
* kind-scoped (`…/{agent}/session/`), so a prefix routes wholly to one side.
|
|
54
|
-
*/
|
|
55
|
-
export function isFrameworkFileKey(key: string): boolean {
|
|
56
|
-
if (!key.startsWith(`${AGENTSDK_STORAGE_KEY_ROOT}/`)) {
|
|
57
|
-
return false;
|
|
58
|
-
}
|
|
59
|
-
const rest = key.slice(AGENTSDK_STORAGE_KEY_ROOT.length + 1);
|
|
60
|
-
const agentEnd = rest.indexOf("/");
|
|
61
|
-
if (agentEnd === -1) {
|
|
62
|
-
return false;
|
|
63
|
-
}
|
|
64
|
-
const afterAgent = rest.slice(agentEnd + 1);
|
|
65
|
-
const kindEnd = afterAgent.indexOf("/");
|
|
66
|
-
const kind = kindEnd === -1 ? afterAgent : afterAgent.slice(0, kindEnd);
|
|
67
|
-
return FRAMEWORK_FILE_KINDS.has(kind);
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
/**
|
|
71
|
-
* The KV core over a {@link FileSink}: one JSON document per key.
|
|
72
|
-
* `putMany` stays optional — the KV-proxy core has no batch write, and the
|
|
73
|
-
* composite falls back to sequential puts on a side without one.
|
|
74
|
-
*/
|
|
75
|
-
export type FileSinkStorageCore = Required<Pick<StorageConfig, "put" | "get" | "delete" | "list">> &
|
|
76
|
-
Pick<StorageConfig, "putMany">;
|
|
77
|
-
|
|
78
|
-
/** Parallel per-key reads backing `list` (each is presign + object GET). */
|
|
79
|
-
const LIST_READ_CONCURRENCY = 8;
|
|
80
|
-
|
|
81
|
-
/**
|
|
82
|
-
* A storage key whose path the file store cannot represent (an empty, `.`,
|
|
83
|
-
* or `..` segment — possible only through caller-controlled segments such
|
|
84
|
-
* as continuation tokens or a caller-supplied session id). Such an object
|
|
85
|
-
* can never exist in the store, so reads are a definitive miss rather than
|
|
86
|
-
* a per-request 400 that the lazy-restore path would propagate forever.
|
|
87
|
-
*/
|
|
88
|
-
function isUnrepresentableFileKey(key: string): boolean {
|
|
89
|
-
return key.split("/").some(segment => segment === "" || segment === "." || segment === "..");
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
/**
|
|
93
|
-
* Adapt a {@link FileSink} to the `defineStorage` KV core. Storage keys are
|
|
94
|
-
* framework-minted (URI-encoded, length-bounded segments — see
|
|
95
|
-
* {@link storageKeys}), so they are used as file keys verbatim; values are
|
|
96
|
-
* stored as JSON bytes. Parse failures throw: on the lazy-restore path a
|
|
97
|
-
* corrupt document must fail the follow-up rather than read as a miss, and
|
|
98
|
-
* the startup bulk restore already logs-and-skips a throwing `list`.
|
|
99
|
-
*/
|
|
100
|
-
export function fileSinkStorageCore(sink: FileSink): FileSinkStorageCore {
|
|
101
|
-
return {
|
|
102
|
-
async put(key, value): Promise<void> {
|
|
103
|
-
if (isUnrepresentableFileKey(key)) {
|
|
104
|
-
// Loud rather than silent: the coordinator logs and drops failed
|
|
105
|
-
// mirror writes (at-most-once), and awaited callers must not
|
|
106
|
-
// believe an impossible write landed.
|
|
107
|
-
throw new Error(
|
|
108
|
-
`framework file storage: key "${key}" has a path segment the store cannot represent`,
|
|
109
|
-
);
|
|
110
|
-
}
|
|
111
|
-
await sink.put(key, encodeDocument(key, value));
|
|
112
|
-
},
|
|
113
|
-
async putMany(entries): Promise<Array<{ key: string; error?: unknown }>> {
|
|
114
|
-
const results: Array<{ key: string; error?: unknown }> = entries.map(entry => ({
|
|
115
|
-
key: entry.key,
|
|
116
|
-
}));
|
|
117
|
-
const writable: Array<{ index: number; key: string; body: Uint8Array }> = [];
|
|
118
|
-
for (let index = 0; index < entries.length; index += 1) {
|
|
119
|
-
const entry = entries[index];
|
|
120
|
-
if (entry === undefined) {
|
|
121
|
-
continue;
|
|
122
|
-
}
|
|
123
|
-
if (isUnrepresentableFileKey(entry.key)) {
|
|
124
|
-
results[index] = {
|
|
125
|
-
key: entry.key,
|
|
126
|
-
error: new Error(
|
|
127
|
-
`framework file storage: key "${entry.key}" has a path segment the store cannot represent`,
|
|
128
|
-
),
|
|
129
|
-
};
|
|
130
|
-
continue;
|
|
131
|
-
}
|
|
132
|
-
writable.push({
|
|
133
|
-
index,
|
|
134
|
-
key: entry.key,
|
|
135
|
-
body: encodeDocument(entry.key, entry.value),
|
|
136
|
-
});
|
|
137
|
-
}
|
|
138
|
-
if (writable.length === 0) {
|
|
139
|
-
return results;
|
|
140
|
-
}
|
|
141
|
-
if (sink.putMany !== undefined) {
|
|
142
|
-
// The point of the batch: one backend round trip for the flush.
|
|
143
|
-
const settled = await sink.putMany(writable.map(({ key, body }) => ({ key, body })));
|
|
144
|
-
for (let i = 0; i < writable.length; i += 1) {
|
|
145
|
-
const target = writable[i];
|
|
146
|
-
const outcome = settled[i];
|
|
147
|
-
if (target === undefined) {
|
|
148
|
-
continue;
|
|
149
|
-
}
|
|
150
|
-
if (outcome?.status === "rejected") {
|
|
151
|
-
results[target.index] = { key: target.key, error: outcome.reason };
|
|
152
|
-
}
|
|
153
|
-
}
|
|
154
|
-
return results;
|
|
155
|
-
}
|
|
156
|
-
// No batch support: sequential puts, preserving the sink's strict
|
|
157
|
-
// one-at-a-time ordering contract.
|
|
158
|
-
for (const target of writable) {
|
|
159
|
-
try {
|
|
160
|
-
await sink.put(target.key, target.body);
|
|
161
|
-
} catch (error) {
|
|
162
|
-
results[target.index] = { key: target.key, error };
|
|
163
|
-
}
|
|
164
|
-
}
|
|
165
|
-
return results;
|
|
166
|
-
},
|
|
167
|
-
async get(key): Promise<JsonValue | undefined> {
|
|
168
|
-
if (isUnrepresentableFileKey(key)) {
|
|
169
|
-
return undefined;
|
|
170
|
-
}
|
|
171
|
-
const body = await sink.get(key);
|
|
172
|
-
if (body === undefined) {
|
|
173
|
-
return undefined;
|
|
174
|
-
}
|
|
175
|
-
return decodeDocument(key, body instanceof Uint8Array ? body : body.body);
|
|
176
|
-
},
|
|
177
|
-
async delete(key): Promise<void> {
|
|
178
|
-
if (isUnrepresentableFileKey(key)) {
|
|
179
|
-
return;
|
|
180
|
-
}
|
|
181
|
-
await sink.delete(key);
|
|
182
|
-
},
|
|
183
|
-
async list(prefix): Promise<StorageEntry[]> {
|
|
184
|
-
const entries = await sink.list(prefix);
|
|
185
|
-
// FileSink.list returns metadata only, so the values are their own
|
|
186
|
-
// reads. Prefer the sink's batched read — on the hosted sink that is
|
|
187
|
-
// one control-plane call per 100 keys instead of one per key, which is
|
|
188
|
-
// what keeps a big restore under the store's per-deployment rate
|
|
189
|
-
// budget — and fall back to bounded per-key gets elsewhere.
|
|
190
|
-
const bodies =
|
|
191
|
-
sink.getMany !== undefined
|
|
192
|
-
? await sink.getMany(entries.map(entry => entry.key))
|
|
193
|
-
: await mapBounded(entries, LIST_READ_CONCURRENCY, entry => sink.get(entry.key));
|
|
194
|
-
const out: StorageEntry[] = [];
|
|
195
|
-
for (let index = 0; index < entries.length; index += 1) {
|
|
196
|
-
const entry = entries[index];
|
|
197
|
-
const body = bodies[index];
|
|
198
|
-
if (entry === undefined || body === undefined) {
|
|
199
|
-
// Deleted between list and read; a miss is not corruption.
|
|
200
|
-
continue;
|
|
201
|
-
}
|
|
202
|
-
out.push({
|
|
203
|
-
key: entry.key,
|
|
204
|
-
value: decodeDocument(entry.key, body instanceof Uint8Array ? body : body.body),
|
|
205
|
-
});
|
|
206
|
-
}
|
|
207
|
-
return out;
|
|
208
|
-
},
|
|
209
|
-
};
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
function frameworkFileKind(key: string): string | undefined {
|
|
213
|
-
if (!key.startsWith(`${AGENTSDK_STORAGE_KEY_ROOT}/`)) {
|
|
214
|
-
return undefined;
|
|
215
|
-
}
|
|
216
|
-
const rest = key.slice(AGENTSDK_STORAGE_KEY_ROOT.length + 1);
|
|
217
|
-
const agentEnd = rest.indexOf("/");
|
|
218
|
-
if (agentEnd === -1) {
|
|
219
|
-
return undefined;
|
|
220
|
-
}
|
|
221
|
-
const afterAgent = rest.slice(agentEnd + 1);
|
|
222
|
-
const kindEnd = afterAgent.indexOf("/");
|
|
223
|
-
return kindEnd === -1 ? afterAgent : afterAgent.slice(0, kindEnd);
|
|
224
|
-
}
|
|
225
|
-
|
|
226
|
-
function isLogKey(key: string): boolean {
|
|
227
|
-
return frameworkFileKind(key) === "logs";
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
function encodeDocument(key: string, value: JsonValue): Uint8Array {
|
|
231
|
-
// start.log is raw UTF-8, not a JSON document. Stringify would quote
|
|
232
|
-
// every line and store a JSON string literal instead of the tee.
|
|
233
|
-
if (isLogKey(key)) {
|
|
234
|
-
return new TextEncoder().encode(typeof value === "string" ? value : JSON.stringify(value));
|
|
235
|
-
}
|
|
236
|
-
return new TextEncoder().encode(JSON.stringify(value));
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
function decodeDocument(key: string, bytes: Uint8Array): JsonValue {
|
|
240
|
-
const text = new TextDecoder().decode(bytes);
|
|
241
|
-
if (isLogKey(key)) {
|
|
242
|
-
return text;
|
|
243
|
-
}
|
|
244
|
-
try {
|
|
245
|
-
return JSON.parse(text) as JsonValue;
|
|
246
|
-
} catch (error) {
|
|
247
|
-
throw new Error(
|
|
248
|
-
`framework file storage: stored document at "${key}" is not JSON (${
|
|
249
|
-
error instanceof Error ? error.message : String(error)
|
|
250
|
-
})`,
|
|
251
|
-
);
|
|
252
|
-
}
|
|
253
|
-
}
|
|
254
|
-
|
|
255
|
-
/**
|
|
256
|
-
* Split one storage core by key kind: framework session state to `files`,
|
|
257
|
-
* everything else to `kv`. Spread over the KV backend when building the
|
|
258
|
-
* full definition so its `evals` group (and the cursor-hosted marker)
|
|
259
|
-
* rides along untouched; wrap the KV `cas` group with
|
|
260
|
-
* {@link frameworkGuardedCas} rather than spreading it as-is.
|
|
261
|
-
*/
|
|
262
|
-
export function composeFrameworkStorage(input: {
|
|
263
|
-
kv: FileSinkStorageCore;
|
|
264
|
-
files: FileSinkStorageCore;
|
|
265
|
-
}): FileSinkStorageCore & Pick<StorageConfig, "listNewest"> {
|
|
266
|
-
const route = (key: string): FileSinkStorageCore =>
|
|
267
|
-
isFrameworkFileKey(key) ? input.files : input.kv;
|
|
268
|
-
return {
|
|
269
|
-
put: (key, value, ctx) => route(key).put(key, value, ctx),
|
|
270
|
-
async putMany(entries, ctx) {
|
|
271
|
-
// Partition by destination store, batch each side, and reassemble
|
|
272
|
-
// per-entry outcomes in input order.
|
|
273
|
-
const indexed = entries.map((entry, index) => ({ entry, index }));
|
|
274
|
-
const results: Array<{ key: string; error?: unknown }> = entries.map(entry => ({
|
|
275
|
-
key: entry.key,
|
|
276
|
-
}));
|
|
277
|
-
for (const core of [input.files, input.kv]) {
|
|
278
|
-
const side = indexed.filter(({ entry }) => route(entry.key) === core);
|
|
279
|
-
if (side.length === 0) {
|
|
280
|
-
continue;
|
|
281
|
-
}
|
|
282
|
-
if (core.putMany === undefined) {
|
|
283
|
-
// No batch write on this side (the KV proxy): sequential puts,
|
|
284
|
-
// preserving the strict one-at-a-time ordering it promises.
|
|
285
|
-
for (const { entry, index } of side) {
|
|
286
|
-
try {
|
|
287
|
-
await core.put(entry.key, entry.value, ctx);
|
|
288
|
-
} catch (error) {
|
|
289
|
-
results[index] = { key: entry.key, error };
|
|
290
|
-
}
|
|
291
|
-
}
|
|
292
|
-
continue;
|
|
293
|
-
}
|
|
294
|
-
const settled = await core.putMany(
|
|
295
|
-
side.map(({ entry }) => entry),
|
|
296
|
-
ctx,
|
|
297
|
-
);
|
|
298
|
-
for (let i = 0; i < side.length; i += 1) {
|
|
299
|
-
const target = side[i];
|
|
300
|
-
const outcome = settled[i];
|
|
301
|
-
if (target !== undefined && outcome !== undefined) {
|
|
302
|
-
results[target.index] = outcome;
|
|
303
|
-
}
|
|
304
|
-
}
|
|
305
|
-
}
|
|
306
|
-
return results;
|
|
307
|
-
},
|
|
308
|
-
get: (key, ctx) => route(key).get(key, ctx),
|
|
309
|
-
delete: (key, ctx) => route(key).delete(key, ctx),
|
|
310
|
-
list: (prefix, ctx) => route(prefix).list(prefix, ctx),
|
|
311
|
-
// Session records — the only `listNewest` consumer — are framework file
|
|
312
|
-
// keys, and the file store has no write-time ordering. Spreading the KV
|
|
313
|
-
// backend's `listNewest` through would query rows that live elsewhere
|
|
314
|
-
// (stale KV leftovers, or nothing), so the composed core explicitly has
|
|
315
|
-
// none and the engine falls back to the routed `list`.
|
|
316
|
-
listNewest: undefined,
|
|
317
|
-
};
|
|
318
|
-
}
|
|
319
|
-
|
|
320
|
-
/**
|
|
321
|
-
* The KV backend's conditional writes, refusing framework-file keys.
|
|
322
|
-
*
|
|
323
|
-
* CAS runs on the KV proxy (a database row version); the plain core routes
|
|
324
|
-
* framework session state to the file store. A future coordination path
|
|
325
|
-
* that CASes a `session/` or `continuation/` key would otherwise read and
|
|
326
|
-
* write a different store than the plain path — silent split-brain. Fail
|
|
327
|
-
* loudly instead; nothing in the package CASes those kinds today.
|
|
328
|
-
*/
|
|
329
|
-
export function frameworkGuardedCas(
|
|
330
|
-
cas: NonNullable<StorageConfig["cas"]>,
|
|
331
|
-
): NonNullable<StorageConfig["cas"]> {
|
|
332
|
-
const refuse = (key: string): void => {
|
|
333
|
-
if (isFrameworkFileKey(key)) {
|
|
334
|
-
throw new Error(
|
|
335
|
-
`framework file storage: conditional writes are KV-only, but "${key}" routes to the framework file store`,
|
|
336
|
-
);
|
|
337
|
-
}
|
|
338
|
-
};
|
|
339
|
-
return {
|
|
340
|
-
getWithVersion: (key, ctx) => {
|
|
341
|
-
refuse(key);
|
|
342
|
-
return cas.getWithVersion(key, ctx);
|
|
343
|
-
},
|
|
344
|
-
putIfAbsent: (key, value, ctx) => {
|
|
345
|
-
refuse(key);
|
|
346
|
-
return cas.putIfAbsent(key, value, ctx);
|
|
347
|
-
},
|
|
348
|
-
putIfVersion: (key, value, expectedVersion, ctx) => {
|
|
349
|
-
refuse(key);
|
|
350
|
-
return cas.putIfVersion(key, value, expectedVersion, ctx);
|
|
351
|
-
},
|
|
352
|
-
listKeys: (prefix, ctx) => {
|
|
353
|
-
refuse(prefix);
|
|
354
|
-
return cas.listKeys(prefix, ctx);
|
|
355
|
-
},
|
|
356
|
-
};
|
|
357
|
-
}
|
|
@@ -1,156 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Which backend framework session state is mirrored to.
|
|
3
|
-
*
|
|
4
|
-
* Framework state — session records, event chunks, the continuation index —
|
|
5
|
-
* is how a session outlives the process that served it. On architecture v1
|
|
6
|
-
* that mirror exists only when the agent author wrote `agent/storage.ts`,
|
|
7
|
-
* which makes platform durability an agent-level decision: of the
|
|
8
|
-
* first-party agents, some choose `cursorHostedStorage()` and some choose
|
|
9
|
-
* `fileKv()` (pod-local disk, lost on pod replacement), and one selects
|
|
10
|
-
* between them at runtime by reading the deployment-id environment variable
|
|
11
|
-
* itself.
|
|
12
|
-
*
|
|
13
|
-
* That selection is a hosting-mode question, not an authoring question.
|
|
14
|
-
* Architecture v2 moves it here: `agent/storage.ts` is rejected at
|
|
15
|
-
* discovery (error diagnostic, so serve and deploy fail early), and the
|
|
16
|
-
* platform picks the default. Architecture v1 with no authored file now
|
|
17
|
-
* uses the same hosted-vs-self-hosted split, so deleting `agent/storage.ts`
|
|
18
|
-
* (required to deploy the same tree onto v2) does not drop the Cursor-hosted
|
|
19
|
-
* session mirror on a still-v1 pod.
|
|
20
|
-
*
|
|
21
|
-
* - **Cursor-managed hosting** (the deployment-generation environment
|
|
22
|
-
* variable is set, same signal that registers `GET /v1/manifest`):
|
|
23
|
-
* the deployment's **framework-level file store**
|
|
24
|
-
* (`AGENT_SERVE_FRAMEWORK_STORE_SOURCE_ID`, bound at task time) holds
|
|
25
|
-
* session records, event transcripts, and the continuation index —
|
|
26
|
-
* file-shaped state on file storage, apart from the author-facing user
|
|
27
|
-
* store. Author `host.kv`, eval runs, and conditional writes ride the
|
|
28
|
-
* AgentSDK v2 KV proxy (cursor-hosted-v2.ts), which resolves the
|
|
29
|
-
* pod service account to the factorydb deployment row (the v1 Bugbot
|
|
30
|
-
* proxy cannot resolve v2 pods at all). Framework session state never
|
|
31
|
-
* routes to the KV proxy — the composite splits by key kind — so
|
|
32
|
-
* transcripts stay off the author-reachable KV namespace. The API key
|
|
33
|
-
* resolves through the full credential chain on every call because hosted
|
|
34
|
-
* freeze snapshots listen unsigned and the binder drops the key file
|
|
35
|
-
* after restore.
|
|
36
|
-
* - **Self-hosted**: no mirror. `--state-root` is the durable copy, which
|
|
37
|
-
* is correct when the operator owns the disk.
|
|
38
|
-
*
|
|
39
|
-
* v1 still honors an authored `agent/storage.ts` when present. Hosted v1
|
|
40
|
-
* pods with no authored file get the Cursor-hosted lazy mirror (gated on
|
|
41
|
-
* `AGENT_SERVE_DEPLOYMENT_ID`, the same signal the previous authored sinks
|
|
42
|
-
* used). Self-hosted v1 with no authored file stays disk-only.
|
|
43
|
-
*
|
|
44
|
-
* Local disk is not part of this decision. `<stateRoot>/sessions/<id>/`
|
|
45
|
-
* already holds `session.json` and `events.ndjson` unconditionally, through
|
|
46
|
-
* the session store; what this selects is the durable mirror *beyond* the
|
|
47
|
-
* pod's filesystem.
|
|
48
|
-
*/
|
|
49
|
-
|
|
50
|
-
import { cursorHostedFiles } from "../files-backends/cursor-hosted.js";
|
|
51
|
-
import { defineStorage, type StorageDefinition } from "../storage.js";
|
|
52
|
-
import {
|
|
53
|
-
AGENT_SERVE_DEPLOYMENT_ID_ENV_VAR,
|
|
54
|
-
cursorHostedStorage,
|
|
55
|
-
} from "../storage-backends/cursor-hosted.js";
|
|
56
|
-
import { cursorHostedStorageV2 } from "../storage-backends/cursor-hosted-v2.js";
|
|
57
|
-
import type { AgentArchitecture } from "../types.js";
|
|
58
|
-
import { resolveApiKeySync } from "./cursor/credentials.js";
|
|
59
|
-
import {
|
|
60
|
-
composeFrameworkStorage,
|
|
61
|
-
fileSinkStorageCore,
|
|
62
|
-
frameworkGuardedCas,
|
|
63
|
-
} from "./framework-file-storage.js";
|
|
64
|
-
import { resolveAgentV2Hosting } from "./v2-hosting.js";
|
|
65
|
-
|
|
66
|
-
export interface FrameworkStorageSelectionInput {
|
|
67
|
-
/** `agent/storage.ts`, when the author wrote one (v1 only: discovery rejects it on v2). */
|
|
68
|
-
readonly authored: StorageDefinition | undefined;
|
|
69
|
-
/** {@link AgentConfig.architecture}; discovery fills `"v2"` when omitted. */
|
|
70
|
-
readonly architecture?: AgentArchitecture | undefined;
|
|
71
|
-
/** Environment override for tests; defaults to `process.env`. */
|
|
72
|
-
readonly env?: Record<string, string | undefined>;
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
/**
|
|
76
|
-
* Pick the backend for framework session state.
|
|
77
|
-
*
|
|
78
|
-
* Returns `undefined` when there is no mirror, in which case the pod's local
|
|
79
|
-
* disk is the only copy.
|
|
80
|
-
*/
|
|
81
|
-
export function selectFrameworkStorageDefinition(
|
|
82
|
-
input: FrameworkStorageSelectionInput,
|
|
83
|
-
): StorageDefinition | undefined {
|
|
84
|
-
if (input.architecture !== "v2") {
|
|
85
|
-
if (input.authored !== undefined) {
|
|
86
|
-
return input.authored;
|
|
87
|
-
}
|
|
88
|
-
const env = input.env ?? process.env;
|
|
89
|
-
if ((env[AGENT_SERVE_DEPLOYMENT_ID_ENV_VAR] ?? "").trim() !== "") {
|
|
90
|
-
// Hosted v1 pod with no authored sink: keep the Cursor-hosted
|
|
91
|
-
// mirror (lazy restore) so agents can delete `agent/storage.ts`
|
|
92
|
-
// without losing durability while they still run architecture v1.
|
|
93
|
-
return defineStorage({
|
|
94
|
-
name: "cursor-hosted (lazy restore)",
|
|
95
|
-
policy: { restore: "off" },
|
|
96
|
-
...cursorHostedStorage(),
|
|
97
|
-
});
|
|
98
|
-
}
|
|
99
|
-
return undefined;
|
|
100
|
-
}
|
|
101
|
-
if (input.authored !== undefined) {
|
|
102
|
-
// Discovery rejects agent/storage.ts on v2 before an engine is built;
|
|
103
|
-
// an authored definition reaching this point is a wiring bug. Raise
|
|
104
|
-
// rather than silently discard what the author believes is configured.
|
|
105
|
-
throw new Error(
|
|
106
|
-
'defineStorage (agent/storage.ts) is not supported on architecture "v2": storage is platform-selected. Delete the file.',
|
|
107
|
-
);
|
|
108
|
-
}
|
|
109
|
-
const hosting = resolveAgentV2Hosting({
|
|
110
|
-
architecture: input.architecture,
|
|
111
|
-
env: input.env as NodeJS.ProcessEnv | undefined,
|
|
112
|
-
});
|
|
113
|
-
if (hosting.kind !== "cursor-managed") {
|
|
114
|
-
// Self-hosted v2: the state root is the durable copy.
|
|
115
|
-
return undefined;
|
|
116
|
-
}
|
|
117
|
-
// Hosted v2 pods wake per delivery: bulk-restoring up to the default
|
|
118
|
-
// 1000 sessions on every boot is waste (and against the file-store
|
|
119
|
-
// backend it is per-key HTTP round trips before the listener even
|
|
120
|
-
// comes up). Follow-ups restore lazily by continuation or session id;
|
|
121
|
-
// GET /v1/sessions lists from the sink either way.
|
|
122
|
-
//
|
|
123
|
-
// Events flush at turn end. drainSessionDurability still forces the
|
|
124
|
-
// record onto the sink before the execution reply.
|
|
125
|
-
const policy = {
|
|
126
|
-
restore: "off",
|
|
127
|
-
} as const;
|
|
128
|
-
// Full chain (env → bind file → stored login): frozen engines listen
|
|
129
|
-
// unsigned and bind store ids + CURSOR_API_KEY at task time, after this
|
|
130
|
-
// definition is constructed.
|
|
131
|
-
const resolveApiKey = (): string | undefined => resolveApiKeySync()?.apiKey;
|
|
132
|
-
// v2 pods carry a factorydb-bound service account, which the v1 Bugbot
|
|
133
|
-
// storage proxy cannot resolve; author KV, CAS coordination, and the
|
|
134
|
-
// eval/A-B tables speak the AgentSDK v2 KV proxy instead. It also carries
|
|
135
|
-
// the cursor-hosted marker, so GET /v1/sessions prefers the durable list
|
|
136
|
-
// (session records are on the framework store, which the composed core
|
|
137
|
-
// lists).
|
|
138
|
-
const kv = cursorHostedStorageV2({ resolveApiKey });
|
|
139
|
-
return defineStorage({
|
|
140
|
-
name: "cursor-hosted (framework files)",
|
|
141
|
-
policy,
|
|
142
|
-
...kv,
|
|
143
|
-
...composeFrameworkStorage({
|
|
144
|
-
kv,
|
|
145
|
-
files: fileSinkStorageCore(
|
|
146
|
-
cursorHostedFiles({
|
|
147
|
-
resolveStoreSourceId: () => hosting.resolveStoreIds().frameworkStoreSourceId,
|
|
148
|
-
resolveApiKey,
|
|
149
|
-
}),
|
|
150
|
-
),
|
|
151
|
-
}),
|
|
152
|
-
// CAS stays on the KV proxy but must refuse framework-file keys, or a
|
|
153
|
-
// future coordination path would split-brain against the plain core.
|
|
154
|
-
cas: frameworkGuardedCas(kv.cas),
|
|
155
|
-
});
|
|
156
|
-
}
|
|
@@ -1,108 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Frontmatter parsers. Authored markdown (skill descriptions, schedule cron
|
|
3
|
-
* expressions) uses the flat `key: value` scalar subset; Cursor plugin
|
|
4
|
-
* markdown is full YAML (folded descriptions, lists).
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
import { JSON_SCHEMA, load as parseYaml } from "js-yaml";
|
|
8
|
-
|
|
9
|
-
export interface ParsedFrontmatter {
|
|
10
|
-
data: Record<string, string>;
|
|
11
|
-
body: string;
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
export interface ParsedYamlFrontmatter {
|
|
15
|
-
data: Record<string, unknown>;
|
|
16
|
-
body: string;
|
|
17
|
-
/** Why the block did not parse as a YAML mapping; `data` is then empty. */
|
|
18
|
-
error?: string;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
const FRONTMATTER_OPEN = /^---\s*$/;
|
|
22
|
-
const YAML_FRONTMATTER = /^---\r?\n([\s\S]*?)\r?\n---(?:\r?\n|$)([\s\S]*)$/;
|
|
23
|
-
|
|
24
|
-
/** YAML frontmatter with the JSON schema (no custom tags). */
|
|
25
|
-
export function parseYamlFrontmatter(source: string): ParsedYamlFrontmatter {
|
|
26
|
-
const match = YAML_FRONTMATTER.exec(source);
|
|
27
|
-
if (match === null) {
|
|
28
|
-
return { data: {}, body: source };
|
|
29
|
-
}
|
|
30
|
-
const body = match[2] ?? "";
|
|
31
|
-
let data: unknown;
|
|
32
|
-
try {
|
|
33
|
-
data = parseYaml(match[1] ?? "", { schema: JSON_SCHEMA });
|
|
34
|
-
} catch (error) {
|
|
35
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
36
|
-
return { data: {}, body, error: message };
|
|
37
|
-
}
|
|
38
|
-
if (data === undefined || data === null) {
|
|
39
|
-
return { data: {}, body };
|
|
40
|
-
}
|
|
41
|
-
if (typeof data !== "object" || Array.isArray(data)) {
|
|
42
|
-
return { data: {}, body, error: "frontmatter is not a mapping" };
|
|
43
|
-
}
|
|
44
|
-
return { data: data as Record<string, unknown>, body };
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
export function parseFrontmatter(source: string): ParsedFrontmatter {
|
|
48
|
-
const lines = source.split(/\r?\n/);
|
|
49
|
-
if (lines.length === 0 || !FRONTMATTER_OPEN.test(lines[0] ?? "")) {
|
|
50
|
-
return { data: {}, body: source };
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
let closeIndex = -1;
|
|
54
|
-
for (let i = 1; i < lines.length; i++) {
|
|
55
|
-
if (FRONTMATTER_OPEN.test(lines[i] ?? "")) {
|
|
56
|
-
closeIndex = i;
|
|
57
|
-
break;
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
if (closeIndex === -1) {
|
|
61
|
-
return { data: {}, body: source };
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
const data: Record<string, string> = {};
|
|
65
|
-
for (const line of lines.slice(1, closeIndex)) {
|
|
66
|
-
if (line.trim() === "" || line.trim().startsWith("#")) {
|
|
67
|
-
continue;
|
|
68
|
-
}
|
|
69
|
-
const separator = line.indexOf(":");
|
|
70
|
-
if (separator === -1) {
|
|
71
|
-
continue;
|
|
72
|
-
}
|
|
73
|
-
const key = line.slice(0, separator).trim();
|
|
74
|
-
if (key === "") {
|
|
75
|
-
continue;
|
|
76
|
-
}
|
|
77
|
-
data[key] = unquote(line.slice(separator + 1).trim());
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
const body = lines
|
|
81
|
-
.slice(closeIndex + 1)
|
|
82
|
-
.join("\n")
|
|
83
|
-
.replace(/^\n+/, "");
|
|
84
|
-
return { data, body };
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
export function serializeFrontmatter(data: Record<string, string>): string {
|
|
88
|
-
const lines = Object.entries(data).map(([key, value]) => `${key}: ${quoteIfNeeded(value)}`);
|
|
89
|
-
return `---\n${lines.join("\n")}\n---\n`;
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
function unquote(value: string): string {
|
|
93
|
-
if (
|
|
94
|
-
value.length >= 2 &&
|
|
95
|
-
((value.startsWith('"') && value.endsWith('"')) ||
|
|
96
|
-
(value.startsWith("'") && value.endsWith("'")))
|
|
97
|
-
) {
|
|
98
|
-
return value.slice(1, -1);
|
|
99
|
-
}
|
|
100
|
-
return value;
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
function quoteIfNeeded(value: string): string {
|
|
104
|
-
if (/[:#'"\n]/.test(value)) {
|
|
105
|
-
return JSON.stringify(value);
|
|
106
|
-
}
|
|
107
|
-
return value;
|
|
108
|
-
}
|