@polderlabs/bizar 6.2.4 → 6.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/CLAUDE.md +15 -0
- package/.claude/agents/_shared/AGENT_BASELINE.md +168 -0
- package/.claude/agents/_shared/CLAUDE_TOOLS.md +412 -0
- package/.claude/agents/_shared/SKILLS.md +109 -0
- package/.claude/agents/agent-browser.md +80 -0
- package/.claude/agents/baldr.md +49 -0
- package/.claude/agents/forseti.md +51 -0
- package/.claude/agents/frigg.md +42 -0
- package/.claude/agents/heimdall.md +33 -0
- package/.claude/agents/hermod.md +53 -0
- package/.claude/agents/mimir.md +49 -0
- package/.claude/agents/odin.md +287 -0
- package/.claude/agents/quick.md +34 -0
- package/.claude/agents/semble-search.md +50 -0
- package/.claude/agents/thor.md +53 -0
- package/.claude/agents/tyr.md +56 -0
- package/.claude/agents/vidarr.md +54 -0
- package/.claude/agents/vor.md +53 -0
- package/.claude/commands/audit.md +25 -0
- package/.claude/commands/bizar.md +22 -0
- package/.claude/commands/explain.md +17 -0
- package/.claude/commands/init.md +29 -0
- package/.claude/commands/learn.md +44 -0
- package/.claude/commands/plan.md +35 -0
- package/.claude/commands/plow-through.md +50 -0
- package/.claude/commands/pr-review.md +49 -0
- package/.claude/commands/setup-provider.md +96 -0
- package/.claude/commands/tailscale-serve.md +100 -0
- package/.claude/commands/team.md +132 -0
- package/.claude/commands/test.md +62 -0
- package/.claude/commands/validate.md +68 -0
- package/.claude/commands/visual-plan.md +24 -0
- package/.claude/hooks/README.md +92 -0
- package/.claude/hooks/posttooluse-editwrite.mjs +91 -0
- package/.claude/hooks/pretooluse-bash.mjs +81 -0
- package/.claude/hooks/pretooluse-editwrite.mjs +139 -0
- package/.claude/hooks/sessionend-recall.mjs +74 -0
- package/.claude/hooks/sessionstart-prime.mjs +80 -0
- package/.claude/hooks/userpromptsubmit-tag.mjs +80 -0
- package/.claude/settings.json +116 -0
- package/.claude/skills/9router/SKILL.md +80 -0
- package/.claude/skills/9router-chat/SKILL.md +73 -0
- package/.claude/skills/9router-embeddings/SKILL.md +69 -0
- package/.claude/skills/9router-image/SKILL.md +86 -0
- package/.claude/skills/9router-stt/SKILL.md +79 -0
- package/.claude/skills/9router-tts/SKILL.md +80 -0
- package/.claude/skills/9router-web-fetch/SKILL.md +99 -0
- package/.claude/skills/9router-web-search/SKILL.md +91 -0
- package/.claude/skills/bizar/README.md +9 -0
- package/.claude/skills/bizar/SKILL.md +450 -0
- package/.claude/skills/cpp-coding-standards/README.md +28 -0
- package/.claude/skills/cpp-coding-standards/SKILL.md +634 -0
- package/.claude/skills/cpp-coding-standards/references/concurrency.md +320 -0
- package/.claude/skills/cpp-coding-standards/references/error-handling.md +229 -0
- package/.claude/skills/cpp-coding-standards/references/memory-safety.md +216 -0
- package/.claude/skills/cpp-coding-standards/references/modern-idioms.md +282 -0
- package/.claude/skills/cpp-coding-standards/references/review-checklist.md +96 -0
- package/.claude/skills/cpp-testing/README.md +28 -0
- package/.claude/skills/cpp-testing/SKILL.md +304 -0
- package/.claude/skills/cpp-testing/references/coverage.md +370 -0
- package/.claude/skills/cpp-testing/references/framework-compare.md +175 -0
- package/.claude/skills/cpp-testing/references/host-test-for-embedded.md +499 -0
- package/.claude/skills/cpp-testing/references/mocking.md +364 -0
- package/.claude/skills/cpp-testing/references/tdd-workflow.md +308 -0
- package/.claude/skills/cubesandbox/SKILL.md +148 -0
- package/.claude/skills/embedded-esp-idf/README.md +41 -0
- package/.claude/skills/embedded-esp-idf/SKILL.md +439 -0
- package/.claude/skills/embedded-esp-idf/references/freertos-patterns.md +214 -0
- package/.claude/skills/embedded-esp-idf/references/host-tests.md +164 -0
- package/.claude/skills/embedded-esp-idf/references/idf-py-commands.md +157 -0
- package/.claude/skills/embedded-esp-idf/references/kconfig.md +159 -0
- package/.claude/skills/embedded-esp-idf/references/logging-discipline.md +118 -0
- package/.claude/skills/embedded-esp-idf/references/memory-and-iram.md +137 -0
- package/.claude/skills/embedded-esp-idf/references/nvs.md +121 -0
- package/.claude/skills/embedded-esp-idf/references/packed-structs.md +192 -0
- package/.claude/skills/embedded-esp-idf/scripts/idf_env.sh +47 -0
- package/.claude/skills/embedded-esp-idf/scripts/size_check.sh +77 -0
- package/.claude/skills/glyph/SKILL.md +163 -0
- package/.claude/skills/harness-engineering/SKILL.md +143 -0
- package/.claude/skills/lightrag/SKILL.md +81 -0
- package/.claude/skills/memory-protocol/SKILL.md +105 -0
- package/.claude/skills/obsidian/SKILL.md +306 -0
- package/.claude/skills/read-the-damn-docs/SKILL.md +113 -0
- package/.claude/skills/self-improvement/SKILL.md +64 -0
- package/README.md +87 -59
- package/bizar-dash/dist/assets/{EnvVarsSection-DXM8gRm_.js → EnvVarsSection-B58aiJiE.js} +1 -1
- package/bizar-dash/dist/assets/{EnvVarsSection-DXM8gRm_.js.map → EnvVarsSection-B58aiJiE.js.map} +1 -1
- package/bizar-dash/dist/assets/{MobileChat-BnKN_Ks_.js → MobileChat-BJrqwVDd.js} +1 -1
- package/bizar-dash/dist/assets/{MobileChat-BnKN_Ks_.js.map → MobileChat-BJrqwVDd.js.map} +1 -1
- package/bizar-dash/dist/assets/{MobileSettings-DjCPxC-Q.js → MobileSettings-CEQNJNLJ.js} +1 -1
- package/bizar-dash/dist/assets/{MobileSettings-DjCPxC-Q.js.map → MobileSettings-CEQNJNLJ.js.map} +1 -1
- package/bizar-dash/dist/assets/{main-DYiZqMrn.js → main-IvfQAOfy.js} +1 -1
- package/bizar-dash/dist/assets/{main-DYiZqMrn.js.map → main-IvfQAOfy.js.map} +1 -1
- package/bizar-dash/dist/assets/{markdown-C6mXtQxD.js → markdown-tOLaD6nm.js} +1 -1
- package/bizar-dash/dist/assets/{markdown-C6mXtQxD.js.map → markdown-tOLaD6nm.js.map} +1 -1
- package/bizar-dash/dist/assets/{mobile-CMHqtLV2.js → mobile-DYCHcUpq.js} +1 -1
- package/bizar-dash/dist/assets/{mobile-CMHqtLV2.js.map → mobile-DYCHcUpq.js.map} +1 -1
- package/bizar-dash/dist/assets/{mobile-layout-3jIhHX_p.js → mobile-layout-CBHjpwsb.js} +2 -2
- package/bizar-dash/dist/assets/{mobile-layout-3jIhHX_p.js.map → mobile-layout-CBHjpwsb.js.map} +1 -1
- package/bizar-dash/dist/assets/{useSlashCommands-DtITw8Xv.js → useSlashCommands-Bd7_FA6U.js} +2 -2
- package/bizar-dash/dist/assets/{useSlashCommands-DtITw8Xv.js.map → useSlashCommands-Bd7_FA6U.js.map} +1 -1
- package/bizar-dash/dist/assets/{vendor-CeHGtduv.js → vendor-C843201K.js} +12 -12
- package/bizar-dash/dist/assets/vendor-C843201K.js.map +1 -0
- package/bizar-dash/dist/index.html +6 -6
- package/bizar-dash/dist/mobile.html +2 -2
- package/bizar-dash/node_modules/.vite/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json +1 -1
- package/bizar-dash/src/server/api.mjs +4 -4
- package/bizar-dash/src/server/background-store.mjs +15 -16
- package/bizar-dash/src/server/bg-poller.mjs +25 -35
- package/bizar-dash/src/server/bg-retry.mjs +66 -194
- package/bizar-dash/src/server/claude-bg-spawner.mjs +390 -0
- package/bizar-dash/src/server/claude-info.mjs +412 -0
- package/bizar-dash/src/server/{cline-runner.mjs → claude-runner.mjs} +53 -48
- package/bizar-dash/src/server/claude-sdk.mjs +191 -0
- package/bizar-dash/src/server/providers-store.mjs +22 -49
- package/bizar-dash/src/server/routes/background.mjs +24 -20
- package/bizar-dash/src/server/routes/chat.mjs +223 -326
- package/bizar-dash/src/server/routes/claude-session-detail.mjs +329 -0
- package/bizar-dash/src/server/routes/claude-sessions.mjs +259 -0
- package/bizar-dash/src/server/routes/tasks.mjs +20 -28
- package/bizar-dash/src/server/task-delegator.mjs +76 -77
- package/bizar-dash/src/web/components/chat/useChat.ts +23 -27
- package/bizar-dash/src/web/views/Chat.tsx +8 -8
- package/cli/bin.mjs +31 -18
- package/cli/commands/claude-cmd.mjs +348 -0
- package/cli/commands/install.mjs +12 -11
- package/cli/commands/sandbox.mjs +220 -0
- package/cli/commands/validate.mjs +252 -288
- package/cli/dev-link.test.mjs +11 -11
- package/cli/doctor.mjs +131 -213
- package/cli/install.mjs +33 -37
- package/cli/install.test.mjs +9 -9
- package/cli/provision-claude.mjs +893 -0
- package/cli/provision.mjs +330 -226
- package/cli/provision.test.mjs +102 -0
- package/cli/utils.mjs +72 -58
- package/config/AGENTS.md +28 -28
- package/config/agents/_shared/AGENT_BASELINE.md +104 -684
- package/config/skills/bizar/SKILL.md +197 -0
- package/config/skills/cubesandbox/SKILL.md +148 -0
- package/config/skills/harness-engineering/SKILL.md +142 -0
- package/install.sh +66 -44
- package/package.json +19 -11
- package/packages/sdk/ARCHITECTURE.md +40 -36
- package/packages/sdk/package-lock.json +32 -0
- package/packages/sdk/package.json +15 -5
- package/{plugins/bizar → packages/sdk}/src/dangerous-patterns.ts +6 -28
- package/packages/sdk/src/fingerprint.ts +0 -0
- package/packages/sdk/src/index.ts +38 -73
- package/packages/sdk/src/mcp/bin.ts +51 -0
- package/packages/sdk/src/mcp/server.ts +498 -0
- package/{plugins/bizar/src/memory-vault.ts → packages/sdk/src/memory/index.ts} +18 -21
- package/packages/sdk/tests/sdk.test.mjs +148 -0
- package/packages/sdk/vitest.config.ts +1 -1
- package/scripts/bh-full-e2e.mjs +166 -363
- package/scripts/check-deps.mjs +28 -46
- package/scripts/mirror-claude-md.sh +78 -0
- package/scripts/test-in-container.sh +157 -0
- package/templates/clean-state-checklist.md +3 -3
- package/templates/sprint-contract.md +2 -2
- package/bizar-dash/.bizar/activity.log +0 -3
- package/bizar-dash/.omx/logs/omx-2026-07-07.jsonl +0 -1
- package/bizar-dash/.omx/state/session.json +0 -10
- package/bizar-dash/bizar-design/EXPLANATION.md +0 -307
- package/bizar-dash/bizar-design/INSTRUCTIONS.md +0 -149
- package/bizar-dash/bizar-design/canvas.html +0 -281
- package/bizar-dash/bizar-design/canvas.html.artifact.json +0 -19
- package/bizar-dash/bizar-design/components.css +0 -1665
- package/bizar-dash/bizar-design/components.html +0 -557
- package/bizar-dash/bizar-design/components.html.artifact.json +0 -19
- package/bizar-dash/bizar-design/desktop/agents.html +0 -74
- package/bizar-dash/bizar-design/desktop/agents.html.artifact.json +0 -19
- package/bizar-dash/bizar-design/desktop/memory.html +0 -75
- package/bizar-dash/bizar-design/desktop/memory.html.artifact.json +0 -19
- package/bizar-dash/bizar-design/desktop/metrics.html +0 -63
- package/bizar-dash/bizar-design/desktop/metrics.html.artifact.json +0 -19
- package/bizar-dash/bizar-design/desktop/overview.html +0 -95
- package/bizar-dash/bizar-design/desktop/overview.html.artifact.json +0 -19
- package/bizar-dash/bizar-design/desktop/settings.html +0 -70
- package/bizar-dash/bizar-design/desktop/settings.html.artifact.json +0 -19
- package/bizar-dash/bizar-design/icons.svg +0 -44
- package/bizar-dash/bizar-design/index.html +0 -192
- package/bizar-dash/bizar-design/index.html.artifact.json +0 -19
- package/bizar-dash/bizar-design/mobile/agents.html +0 -29
- package/bizar-dash/bizar-design/mobile/agents.html.artifact.json +0 -19
- package/bizar-dash/bizar-design/mobile/memory.html +0 -28
- package/bizar-dash/bizar-design/mobile/memory.html.artifact.json +0 -19
- package/bizar-dash/bizar-design/mobile/metrics.html +0 -29
- package/bizar-dash/bizar-design/mobile/metrics.html.artifact.json +0 -19
- package/bizar-dash/bizar-design/mobile/overview.html +0 -33
- package/bizar-dash/bizar-design/mobile/overview.html.artifact.json +0 -19
- package/bizar-dash/bizar-design/mobile/settings.html +0 -28
- package/bizar-dash/bizar-design/mobile/settings.html.artifact.json +0 -19
- package/bizar-dash/bizar-design/prototype.js +0 -114
- package/bizar-dash/bizar-design/tokens.css +0 -106
- package/bizar-dash/dist/assets/vendor-CeHGtduv.js.map +0 -1
- package/bizar-dash/node_modules/.package-lock.json +0 -6
- package/bizar-dash/package-lock.json +0 -6
- package/bizar-dash/src/server/cline-sdk.mjs +0 -132
- package/bizar-dash/src/server/routes/cline-session-detail.mjs +0 -559
- package/bizar-dash/src/server/routes/cline-sessions.mjs +0 -291
- package/cli/commands/cline-cmd.mjs +0 -289
- package/cli/commands/validate.test.mjs +0 -344
- package/cli/doctor.test.mjs +0 -350
- package/config/cline.json.template +0 -342
- package/packages/sdk/src/client.ts +0 -188
- package/packages/sdk/src/cline-events.ts +0 -134
- package/packages/sdk/src/cline-types.ts +0 -66
- package/packages/sdk/src/cline.ts +0 -339
- package/packages/sdk/src/errors.ts +0 -129
- package/packages/sdk/src/events.ts +0 -153
- package/packages/sdk/src/types.ts +0 -176
- package/packages/sdk/tests/client.test.ts +0 -217
- package/packages/sdk/tests/errors.test.ts +0 -108
- package/packages/sdk/tests/events.test.ts +0 -139
- package/packages/sdk/tests/fixtures/fetch-mock.ts +0 -152
- package/packages/sdk/tests/fixtures/sse-mock.ts +0 -30
- package/plugins/bizar/ARCHITECTURE.md +0 -142
- package/plugins/bizar/CONSTRAINTS.md +0 -67
- package/plugins/bizar/LICENSE +0 -21
- package/plugins/bizar/README.md +0 -448
- package/plugins/bizar/index.ts +0 -872
- package/plugins/bizar/package.json +0 -39
- package/plugins/bizar/scripts/check-forbidden-imports.sh +0 -33
- package/plugins/bizar/src/background-state.ts +0 -641
- package/plugins/bizar/src/background.ts +0 -1806
- package/plugins/bizar/src/cline-runner.ts +0 -203
- package/plugins/bizar/src/clineruntime.ts +0 -227
- package/plugins/bizar/src/commands-impl.ts +0 -151
- package/plugins/bizar/src/commands.ts +0 -1799
- package/plugins/bizar/src/compaction.d.mts +0 -48
- package/plugins/bizar/src/compaction.mjs +0 -192
- package/plugins/bizar/src/dashboard-client.ts +0 -233
- package/plugins/bizar/src/event-stream.ts +0 -606
- package/plugins/bizar/src/fingerprint.ts +0 -120
- package/plugins/bizar/src/handoff.ts +0 -79
- package/plugins/bizar/src/hooks/memory-flush-on-compact.ts +0 -123
- package/plugins/bizar/src/hooks/memory-inject.ts +0 -247
- package/plugins/bizar/src/hooks/memory-write-on-end.ts +0 -188
- package/plugins/bizar/src/hooks/skill-curator.ts +0 -180
- package/plugins/bizar/src/http-client.ts +0 -467
- package/plugins/bizar/src/key-rotation.ts +0 -218
- package/plugins/bizar/src/logger.ts +0 -144
- package/plugins/bizar/src/loop-engineering.ts +0 -241
- package/plugins/bizar/src/loop.ts +0 -176
- package/plugins/bizar/src/mistake-recovery.ts +0 -98
- package/plugins/bizar/src/odin.ts +0 -227
- package/plugins/bizar/src/options.ts +0 -470
- package/plugins/bizar/src/plan-fs.ts +0 -323
- package/plugins/bizar/src/reasoning-clean.ts +0 -454
- package/plugins/bizar/src/report.ts +0 -178
- package/plugins/bizar/src/research-prompt.ts +0 -35
- package/plugins/bizar/src/serve-info.ts +0 -228
- package/plugins/bizar/src/serve.ts +0 -496
- package/plugins/bizar/src/settings.ts +0 -349
- package/plugins/bizar/src/state.ts +0 -298
- package/plugins/bizar/src/tool-discipline.ts +0 -105
- package/plugins/bizar/src/tools/agent-browser.ts +0 -315
- package/plugins/bizar/src/tools/bg-collect.ts +0 -131
- package/plugins/bizar/src/tools/bg-get-comments.ts +0 -266
- package/plugins/bizar/src/tools/bg-kill.ts +0 -116
- package/plugins/bizar/src/tools/bg-pause.ts +0 -99
- package/plugins/bizar/src/tools/bg-report-progress.ts +0 -115
- package/plugins/bizar/src/tools/bg-resume.ts +0 -94
- package/plugins/bizar/src/tools/bg-send-message.ts +0 -223
- package/plugins/bizar/src/tools/bg-spawn.ts +0 -502
- package/plugins/bizar/src/tools/bg-status.ts +0 -130
- package/plugins/bizar/src/tools/graph-query.ts +0 -278
- package/plugins/bizar/src/tools/loop-engineering.ts +0 -193
- package/plugins/bizar/src/tools/memory-list.ts +0 -43
- package/plugins/bizar/src/tools/memory-read.ts +0 -69
- package/plugins/bizar/src/tools/memory-search.ts +0 -47
- package/plugins/bizar/src/tools/memory-write.ts +0 -54
- package/plugins/bizar/src/tools/open-kb.ts +0 -198
- package/plugins/bizar/src/tools/plan-action.ts +0 -785
- package/plugins/bizar/src/tools/read-glyph-feedback.ts +0 -191
- package/plugins/bizar/src/tools/team-spawn.ts +0 -73
- package/plugins/bizar/src/tools/team-status.ts +0 -76
- package/plugins/bizar/src/tools/wait-for-feedback.ts +0 -415
- package/plugins/bizar/src/trajectory.ts +0 -104
- package/plugins/bizar/tests/README.md +0 -99
- package/plugins/bizar/tests/attach-handler-bug.test.ts +0 -169
- package/plugins/bizar/tests/background-state.test.ts +0 -277
- package/plugins/bizar/tests/background.test.ts +0 -402
- package/plugins/bizar/tests/block.test.ts +0 -195
- package/plugins/bizar/tests/canonical-key-order.test.ts +0 -75
- package/plugins/bizar/tests/clineruntime-config.test.ts +0 -283
- package/plugins/bizar/tests/commands-impl.test.ts +0 -316
- package/plugins/bizar/tests/commands.test.ts +0 -584
- package/plugins/bizar/tests/compaction.test.ts +0 -264
- package/plugins/bizar/tests/config.test.ts +0 -128
- package/plugins/bizar/tests/dashboard-client.test.ts +0 -159
- package/plugins/bizar/tests/dispose.test.ts +0 -336
- package/plugins/bizar/tests/event-stream.test.ts +0 -409
- package/plugins/bizar/tests/event.test.ts +0 -262
- package/plugins/bizar/tests/fingerprint.test.ts +0 -162
- package/plugins/bizar/tests/http-client.test.ts +0 -404
- package/plugins/bizar/tests/init-helpers.test.ts +0 -203
- package/plugins/bizar/tests/integration/slash-command.test.ts +0 -349
- package/plugins/bizar/tests/integration/tool-routing.test.ts +0 -98
- package/plugins/bizar/tests/key-rotation.test.ts +0 -396
- package/plugins/bizar/tests/loop-engineering.test.ts +0 -168
- package/plugins/bizar/tests/loop.test.ts +0 -397
- package/plugins/bizar/tests/memory-write-on-end.test.ts +0 -92
- package/plugins/bizar/tests/mistake-recovery.test.ts +0 -116
- package/plugins/bizar/tests/odin.test.ts +0 -125
- package/plugins/bizar/tests/options.test.ts +0 -329
- package/plugins/bizar/tests/reasoning-clean.test.ts +0 -422
- package/plugins/bizar/tests/safety.test.ts +0 -256
- package/plugins/bizar/tests/serve.test.ts +0 -339
- package/plugins/bizar/tests/settings.test.ts +0 -351
- package/plugins/bizar/tests/stall-think.test.ts +0 -750
- package/plugins/bizar/tests/state.test.ts +0 -276
- package/plugins/bizar/tests/tool-discipline.test.ts +0 -77
- package/plugins/bizar/tests/tools/agent-browser.test.ts +0 -98
- package/plugins/bizar/tests/tools/bg-collect.test.ts +0 -337
- package/plugins/bizar/tests/tools/bg-get-comments.test.ts +0 -485
- package/plugins/bizar/tests/tools/bg-kill.test.ts +0 -235
- package/plugins/bizar/tests/tools/bg-pause.test.ts +0 -61
- package/plugins/bizar/tests/tools/bg-report-progress.test.ts +0 -79
- package/plugins/bizar/tests/tools/bg-resume.test.ts +0 -40
- package/plugins/bizar/tests/tools/bg-send-message.test.ts +0 -116
- package/plugins/bizar/tests/tools/bg-spawn-delegation.test.ts +0 -147
- package/plugins/bizar/tests/tools/bg-spawn-http.test.ts +0 -233
- package/plugins/bizar/tests/tools/bg-spawn.test.ts +0 -311
- package/plugins/bizar/tests/tools/bg-status.test.ts +0 -217
- package/plugins/bizar/tests/tools/cline-runner.test.ts +0 -115
- package/plugins/bizar/tests/tools/plan-action.test.ts +0 -599
- package/plugins/bizar/tests/tools/read-glyph-feedback.test.ts +0 -253
- package/plugins/bizar/tests/tools/wait-for-feedback.test.ts +0 -390
- package/plugins/bizar/tests/update-deadlock.test.ts +0 -151
- package/plugins/bizar/tsconfig.json +0 -29
|
@@ -1,66 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Typed wrappers for cline SDK entities.
|
|
3
|
-
*
|
|
4
|
-
* We declare shapes structurally so that:
|
|
5
|
-
* 1. The package compiles even when `@cline/sdk` is not installed.
|
|
6
|
-
* 2. The shapes are stable regardless of which version of the upstream
|
|
7
|
-
* SDK is installed (the upstream types are very complex and couple us
|
|
8
|
-
* to internal class structure we don't need).
|
|
9
|
-
*/
|
|
10
|
-
|
|
11
|
-
export interface ClineSession {
|
|
12
|
-
id: string;
|
|
13
|
-
slug?: string;
|
|
14
|
-
projectID?: string;
|
|
15
|
-
workspaceID?: string;
|
|
16
|
-
directory?: string;
|
|
17
|
-
path?: string;
|
|
18
|
-
parentID?: string;
|
|
19
|
-
title?: string;
|
|
20
|
-
agent?: string;
|
|
21
|
-
model?: {
|
|
22
|
-
id: string;
|
|
23
|
-
providerID: string;
|
|
24
|
-
variant?: string;
|
|
25
|
-
};
|
|
26
|
-
time?: {
|
|
27
|
-
created: number;
|
|
28
|
-
updated: number;
|
|
29
|
-
compacting?: number;
|
|
30
|
-
archived?: number;
|
|
31
|
-
};
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
export interface ClineMessage {
|
|
35
|
-
info?: {
|
|
36
|
-
id?: string;
|
|
37
|
-
role?: string;
|
|
38
|
-
time?: {
|
|
39
|
-
created?: number;
|
|
40
|
-
};
|
|
41
|
-
};
|
|
42
|
-
id?: string;
|
|
43
|
-
role?: string;
|
|
44
|
-
parts?: ClinePart[];
|
|
45
|
-
text?: string;
|
|
46
|
-
content?: string;
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
export type ClinePart =
|
|
50
|
-
| { type: "text"; text: string }
|
|
51
|
-
| { type: "reasoning"; text: string }
|
|
52
|
-
| { type: "tool_call"; name: string; input: unknown }
|
|
53
|
-
| { type: "tool_result"; toolCallId: string; result: unknown }
|
|
54
|
-
| { type: "agent"; text: string }
|
|
55
|
-
| { type: "subtask"; text: string }
|
|
56
|
-
| { type: "file"; path: string; content?: string }
|
|
57
|
-
| { type: "step_start" | "step_finish" | "snapshot" | "patch" | "retry" | "compaction"; [key: string]: unknown };
|
|
58
|
-
|
|
59
|
-
export interface ClineEvent {
|
|
60
|
-
type: string;
|
|
61
|
-
sessionID?: string;
|
|
62
|
-
messageID?: string;
|
|
63
|
-
part?: ClinePart;
|
|
64
|
-
data?: Record<string, unknown>;
|
|
65
|
-
properties?: Record<string, unknown>;
|
|
66
|
-
}
|
|
@@ -1,339 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Cline SDK factory.
|
|
3
|
-
*
|
|
4
|
-
* Tries to load `@cline/sdk` dynamically. If the package is
|
|
5
|
-
* installed, `createClineClient` from that package is used and its
|
|
6
|
-
* result is re-wrapped. If the import fails (package not installed), a
|
|
7
|
-
* thin fetch-based fallback is returned that hits the same REST endpoints.
|
|
8
|
-
*
|
|
9
|
-
* Auth: `Basic base64("cline:<password>")` — matches the convention
|
|
10
|
-
* used by the cline serve child.
|
|
11
|
-
*
|
|
12
|
-
* Reference: https://docs.cline.bot/docs/sdk/
|
|
13
|
-
*/
|
|
14
|
-
|
|
15
|
-
import { parseSseStream } from "./events.js";
|
|
16
|
-
import { connectionErrorFrom, type BizarError } from "./errors.js";
|
|
17
|
-
import type { EventSubscription } from "./events.js";
|
|
18
|
-
import type { ClineEventEnvelope } from "./cline-events.js";
|
|
19
|
-
|
|
20
|
-
export interface ClineSdkConfig {
|
|
21
|
-
baseUrl: string;
|
|
22
|
-
/** Password for the cline serve child. */
|
|
23
|
-
password?: string;
|
|
24
|
-
/** Injectable fetch for testing. */
|
|
25
|
-
fetch?: typeof fetch;
|
|
26
|
-
/** When true, errors are thrown; default false (return BizarError). */
|
|
27
|
-
throwOnError?: boolean;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
/**
|
|
31
|
-
* Thin fetch-based cline client, used when `@cline/sdk` is not
|
|
32
|
-
* installed in the consumer's project.
|
|
33
|
-
*/
|
|
34
|
-
interface FallbackClineClient {
|
|
35
|
-
sessions: {
|
|
36
|
-
list(): Promise<unknown[]>;
|
|
37
|
-
get(input: { sessionId: string }): Promise<unknown>;
|
|
38
|
-
create(input: { title: string; agent: string }): Promise<{ id: string }>;
|
|
39
|
-
abort(input: { sessionId: string }): Promise<null>;
|
|
40
|
-
messages(input: { sessionId: string }): Promise<unknown[]>;
|
|
41
|
-
prompt(input: {
|
|
42
|
-
sessionId: string;
|
|
43
|
-
body: { text: string };
|
|
44
|
-
messageId?: string;
|
|
45
|
-
}): Promise<{ messageId: string }>;
|
|
46
|
-
promptAsync(input: { sessionId: string; body: { text: string } }): Promise<null>;
|
|
47
|
-
};
|
|
48
|
-
events: {
|
|
49
|
-
subscribe(opts?: {
|
|
50
|
-
signal?: AbortSignal;
|
|
51
|
-
sessionID?: string;
|
|
52
|
-
since?: number;
|
|
53
|
-
}): Promise<EventSubscription & { sessionID?: string }>;
|
|
54
|
-
};
|
|
55
|
-
health: {
|
|
56
|
-
check(): Promise<{ ok: boolean } | BizarError>;
|
|
57
|
-
};
|
|
58
|
-
server: {
|
|
59
|
-
close?(): void;
|
|
60
|
-
};
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
/**
|
|
64
|
-
* The SDK instance returned by `createClineSdk`.
|
|
65
|
-
*/
|
|
66
|
-
export interface ClineSdk {
|
|
67
|
-
sessions: FallbackClineClient["sessions"];
|
|
68
|
-
events: FallbackClineClient["events"];
|
|
69
|
-
health: FallbackClineClient["health"];
|
|
70
|
-
server: FallbackClineClient["server"];
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
function makeAuthHeader(password: string): string {
|
|
74
|
-
const encoded = Buffer.from(`cline:${password}`, "utf-8").toString("base64");
|
|
75
|
-
return `Basic ${encoded}`;
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
async function fetchJson<T>(
|
|
79
|
-
url: string,
|
|
80
|
-
init: RequestInit,
|
|
81
|
-
fetchImpl: typeof fetch,
|
|
82
|
-
throwOnError: boolean,
|
|
83
|
-
): Promise<T | BizarError> {
|
|
84
|
-
let response: Response;
|
|
85
|
-
try {
|
|
86
|
-
response = await fetchImpl(url, init);
|
|
87
|
-
} catch (err) {
|
|
88
|
-
const e = connectionErrorFrom(err);
|
|
89
|
-
if (throwOnError) throw e;
|
|
90
|
-
return e;
|
|
91
|
-
}
|
|
92
|
-
if (response.status === 204) return null as T;
|
|
93
|
-
const text = await response.text();
|
|
94
|
-
if (!response.ok) {
|
|
95
|
-
const err: BizarError = {
|
|
96
|
-
name: "APIError",
|
|
97
|
-
data: {
|
|
98
|
-
statusCode: response.status,
|
|
99
|
-
isRetryable: response.status >= 500 || response.status === 429,
|
|
100
|
-
message: `cline API returned ${response.status}`,
|
|
101
|
-
responseBody: text,
|
|
102
|
-
},
|
|
103
|
-
};
|
|
104
|
-
if (throwOnError) throw err;
|
|
105
|
-
return err;
|
|
106
|
-
}
|
|
107
|
-
try {
|
|
108
|
-
return JSON.parse(text) as T;
|
|
109
|
-
} catch {
|
|
110
|
-
return null as T;
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
function createFallbackClient(config: ClineSdkConfig): FallbackClineClient {
|
|
115
|
-
const { baseUrl, password = "", fetch: fetchImpl = fetch, throwOnError = false } = config;
|
|
116
|
-
const auth = makeAuthHeader(password);
|
|
117
|
-
|
|
118
|
-
async function request<T>(
|
|
119
|
-
method: string,
|
|
120
|
-
path: string,
|
|
121
|
-
body?: unknown,
|
|
122
|
-
): Promise<T | BizarError> {
|
|
123
|
-
const url = `${baseUrl}${path}`;
|
|
124
|
-
const headers: Record<string, string> = {
|
|
125
|
-
Authorization: auth,
|
|
126
|
-
"Content-Type": "application/json",
|
|
127
|
-
Accept: "application/json",
|
|
128
|
-
};
|
|
129
|
-
return fetchJson<T>(
|
|
130
|
-
url,
|
|
131
|
-
{
|
|
132
|
-
method,
|
|
133
|
-
headers,
|
|
134
|
-
body: body != null ? JSON.stringify(body) : undefined,
|
|
135
|
-
},
|
|
136
|
-
fetchImpl,
|
|
137
|
-
throwOnError,
|
|
138
|
-
);
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
return {
|
|
142
|
-
sessions: {
|
|
143
|
-
list: () => request<unknown[]>("GET", "/api/session") as Promise<unknown[]>,
|
|
144
|
-
get: ({ sessionId }) =>
|
|
145
|
-
request<unknown>("GET", `/api/session/${encodeURIComponent(sessionId)}`),
|
|
146
|
-
create: (input) =>
|
|
147
|
-
request<{ id: string }>("POST", "/api/session", input) as Promise<{ id: string }>,
|
|
148
|
-
abort: ({ sessionId }) =>
|
|
149
|
-
request<null>(
|
|
150
|
-
"POST",
|
|
151
|
-
`/api/session/${encodeURIComponent(sessionId)}/abort`,
|
|
152
|
-
) as Promise<null>,
|
|
153
|
-
messages: ({ sessionId }) =>
|
|
154
|
-
request<unknown[]>(
|
|
155
|
-
"GET",
|
|
156
|
-
`/api/session/${encodeURIComponent(sessionId)}/message`,
|
|
157
|
-
) as Promise<unknown[]>,
|
|
158
|
-
prompt: ({ sessionId, body, messageId }) =>
|
|
159
|
-
request<{ messageId: string }>(
|
|
160
|
-
"POST",
|
|
161
|
-
`/api/session/${encodeURIComponent(sessionId)}/prompt`,
|
|
162
|
-
{ id: messageId, prompt: body },
|
|
163
|
-
) as Promise<{ messageId: string }>,
|
|
164
|
-
promptAsync: ({ sessionId, body }) =>
|
|
165
|
-
request<null>(
|
|
166
|
-
"POST",
|
|
167
|
-
`/api/session/${encodeURIComponent(sessionId)}/prompt_async`,
|
|
168
|
-
body,
|
|
169
|
-
) as Promise<null>,
|
|
170
|
-
},
|
|
171
|
-
events: {
|
|
172
|
-
subscribe: async (opts = {}) => {
|
|
173
|
-
const { signal, sessionID, since } = opts;
|
|
174
|
-
const url = new URL("/event", baseUrl);
|
|
175
|
-
if (typeof since === "number") {
|
|
176
|
-
url.searchParams.set("since", String(since));
|
|
177
|
-
}
|
|
178
|
-
const controller = new AbortController();
|
|
179
|
-
if (signal) {
|
|
180
|
-
signal.addEventListener("abort", () => controller.abort(), { once: true });
|
|
181
|
-
}
|
|
182
|
-
const response = await fetchImpl(url.toString(), {
|
|
183
|
-
method: "GET",
|
|
184
|
-
headers: {
|
|
185
|
-
Authorization: auth,
|
|
186
|
-
Accept: "text/event-stream",
|
|
187
|
-
},
|
|
188
|
-
signal: controller.signal,
|
|
189
|
-
});
|
|
190
|
-
if (!response.ok || !response.body) {
|
|
191
|
-
throw new Error(`event subscribe failed: ${response.status}`);
|
|
192
|
-
}
|
|
193
|
-
const sub: EventSubscription & { sessionID?: string } = {
|
|
194
|
-
sessionID,
|
|
195
|
-
// Cast through unknown to satisfy the AsyncIterable<DashboardEvent> constraint
|
|
196
|
-
// from the existing events.ts EventSubscription type. The actual yielded
|
|
197
|
-
// values are ClineEventEnvelope objects which are compatible.
|
|
198
|
-
stream: parseSseStream<ClineEventEnvelope>(
|
|
199
|
-
response.body,
|
|
200
|
-
controller,
|
|
201
|
-
) as unknown as EventSubscription["stream"],
|
|
202
|
-
close: () => controller.abort(),
|
|
203
|
-
};
|
|
204
|
-
return sub;
|
|
205
|
-
},
|
|
206
|
-
},
|
|
207
|
-
health: {
|
|
208
|
-
check: async () => {
|
|
209
|
-
const url = `${baseUrl}/health`;
|
|
210
|
-
try {
|
|
211
|
-
const r = await fetchImpl(url, { method: "GET" });
|
|
212
|
-
if (!r.ok) {
|
|
213
|
-
const text = await r.text().catch(() => "");
|
|
214
|
-
const err: BizarError = {
|
|
215
|
-
name: "APIError",
|
|
216
|
-
data: {
|
|
217
|
-
statusCode: r.status,
|
|
218
|
-
isRetryable: r.status >= 500 || r.status === 429,
|
|
219
|
-
message: `cline health check returned ${r.status}`,
|
|
220
|
-
responseBody: text,
|
|
221
|
-
},
|
|
222
|
-
};
|
|
223
|
-
if (throwOnError) throw err;
|
|
224
|
-
return err;
|
|
225
|
-
}
|
|
226
|
-
return { ok: true } as const;
|
|
227
|
-
} catch (err) {
|
|
228
|
-
const e = connectionErrorFrom(err);
|
|
229
|
-
if (throwOnError) throw e;
|
|
230
|
-
return e;
|
|
231
|
-
}
|
|
232
|
-
},
|
|
233
|
-
},
|
|
234
|
-
server: {},
|
|
235
|
-
};
|
|
236
|
-
}
|
|
237
|
-
|
|
238
|
-
/**
|
|
239
|
-
* Create an cline SDK instance.
|
|
240
|
-
*
|
|
241
|
-
* Tries to use `@cline/sdk`'s `createClineClient` if installed;
|
|
242
|
-
* falls back to a thin fetch-based client otherwise.
|
|
243
|
-
*
|
|
244
|
-
* @param opts `{ baseUrl, password?, fetch?, throwOnError? }`
|
|
245
|
-
*/
|
|
246
|
-
export async function createClineSdk(
|
|
247
|
-
opts: ClineSdkConfig,
|
|
248
|
-
): Promise<ClineSdk> {
|
|
249
|
-
try {
|
|
250
|
-
// `@cline/sdk` is an optional peer dep. If absent, the dynamic import
|
|
251
|
-
// resolves to a rejected promise and we fall back to the fetch wrapper
|
|
252
|
-
// below. TODO(cline-migration): rewrite this body to use Cline's
|
|
253
|
-
// in-process `Agent` / `ClineCore` APIs from `@cline/sdk` instead of
|
|
254
|
-
// mirroring the Cline v2 client shape.
|
|
255
|
-
const mod = await import("@cline/sdk") as any;
|
|
256
|
-
const createClient = mod.createClineClient;
|
|
257
|
-
if (typeof createClient !== "function") throw new Error("not a function");
|
|
258
|
-
|
|
259
|
-
const headers: Record<string, string> = {};
|
|
260
|
-
if (opts.password) {
|
|
261
|
-
headers["Authorization"] = makeAuthHeader(opts.password);
|
|
262
|
-
}
|
|
263
|
-
|
|
264
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
265
|
-
const inner = createClient({
|
|
266
|
-
baseUrl: opts.baseUrl,
|
|
267
|
-
fetch: opts.fetch as any,
|
|
268
|
-
headers,
|
|
269
|
-
// The upstream SDK accepts different options; ignore unknown ones.
|
|
270
|
-
} as any) as any;
|
|
271
|
-
|
|
272
|
-
// The @cline/sdk client has a very different internal structure
|
|
273
|
-
// (HeyApi pattern with .session.list(), .session.create(), etc.).
|
|
274
|
-
// We wrap it to match the FallbackClineClient interface expected
|
|
275
|
-
// by the dashboard.
|
|
276
|
-
const wrapped: ClineSdk = {
|
|
277
|
-
sessions: {
|
|
278
|
-
list: async () => {
|
|
279
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
280
|
-
const r = await (inner.session?.list?.() ?? inner.sessions?.list?.()) as any;
|
|
281
|
-
return r ?? [];
|
|
282
|
-
},
|
|
283
|
-
get: async ({ sessionId }) => {
|
|
284
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
285
|
-
return (await (inner.session?.get?.({ sessionID: sessionId } as any) ?? inner.sessions?.get?.({ sessionId } as any))) as unknown;
|
|
286
|
-
},
|
|
287
|
-
create: async (input) => {
|
|
288
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
289
|
-
const r = await (inner.session?.create?.(input as any) ?? inner.sessions?.create?.(input as any)) as any;
|
|
290
|
-
return { id: r?.data?.id ?? r?.id ?? "" };
|
|
291
|
-
},
|
|
292
|
-
abort: async ({ sessionId }) => {
|
|
293
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
294
|
-
return (await (inner.session?.abort?.({ sessionID: sessionId } as any) ?? inner.sessions?.abort?.({ sessionId } as any))) as null;
|
|
295
|
-
},
|
|
296
|
-
messages: async ({ sessionId }) => {
|
|
297
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
298
|
-
const r = await (inner.session?.messages?.({ sessionID: sessionId } as any) ?? inner.sessions?.messages?.({ sessionId } as any)) as any;
|
|
299
|
-
return r?.data ?? r ?? [];
|
|
300
|
-
},
|
|
301
|
-
prompt: async ({ sessionId, body, messageId }) => {
|
|
302
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
303
|
-
const r = await (inner.session?.prompt?.({ sessionID: sessionId, prompt: body, id: messageId } as any) ?? inner.sessions?.prompt?.({ sessionId, body, messageId } as any)) as any;
|
|
304
|
-
return { messageId: r?.messageId ?? messageId ?? "" };
|
|
305
|
-
},
|
|
306
|
-
promptAsync: async ({ sessionId, body }) => {
|
|
307
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
308
|
-
return (await (inner.session?.promptAsync?.({ sessionID: sessionId, prompt: body } as any) ?? inner.sessions?.promptAsync?.({ sessionId, body } as any))) as null;
|
|
309
|
-
},
|
|
310
|
-
},
|
|
311
|
-
events: {
|
|
312
|
-
subscribe: async (opts = {}) => {
|
|
313
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
314
|
-
const sub = await (inner.event?.subscribe?.(opts as any) ?? inner.events?.subscribe?.(opts as any)) as any;
|
|
315
|
-
return {
|
|
316
|
-
stream: sub?.stream as EventSubscription["stream"],
|
|
317
|
-
close: () => sub?.close?.(),
|
|
318
|
-
};
|
|
319
|
-
},
|
|
320
|
-
},
|
|
321
|
-
health: {
|
|
322
|
-
check: async () => {
|
|
323
|
-
try {
|
|
324
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
325
|
-
const r = await (inner.global?.health?.() ?? inner.health?.check?.()) as any;
|
|
326
|
-
return { ok: r?.ok !== false };
|
|
327
|
-
} catch {
|
|
328
|
-
return { ok: false };
|
|
329
|
-
}
|
|
330
|
-
},
|
|
331
|
-
},
|
|
332
|
-
server: inner.server ?? {},
|
|
333
|
-
};
|
|
334
|
-
return wrapped;
|
|
335
|
-
} catch {
|
|
336
|
-
// `@cline/sdk` not installed or incompatible — use the fallback.
|
|
337
|
-
return createFallbackClient(opts);
|
|
338
|
-
}
|
|
339
|
-
}
|
|
@@ -1,129 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Discriminated error model for the BizarHarness SDK.
|
|
3
|
-
*
|
|
4
|
-
* Errors are RETURNED (not thrown) by default, matching the cline SDK
|
|
5
|
-
* pattern. Set `throwOnError: true` in the client config to opt into
|
|
6
|
-
* throwing.
|
|
7
|
-
*
|
|
8
|
-
* Discriminate via the `name` field:
|
|
9
|
-
*
|
|
10
|
-
* const result = await client.sessions.get({ sessionId });
|
|
11
|
-
* if (isBizarError(result)) {
|
|
12
|
-
* switch (result.name) {
|
|
13
|
-
* case "DashboardError": ...
|
|
14
|
-
* case "ConnectionError": ...
|
|
15
|
-
* case "APIError": ...
|
|
16
|
-
* }
|
|
17
|
-
* }
|
|
18
|
-
*/
|
|
19
|
-
|
|
20
|
-
export type PluginError = {
|
|
21
|
-
name: "PluginError";
|
|
22
|
-
data: {
|
|
23
|
-
code: string;
|
|
24
|
-
message: string;
|
|
25
|
-
};
|
|
26
|
-
};
|
|
27
|
-
|
|
28
|
-
export type DashboardError = {
|
|
29
|
-
name: "DashboardError";
|
|
30
|
-
data: {
|
|
31
|
-
statusCode: number;
|
|
32
|
-
message: string;
|
|
33
|
-
};
|
|
34
|
-
};
|
|
35
|
-
|
|
36
|
-
export type ConnectionError = {
|
|
37
|
-
name: "ConnectionError";
|
|
38
|
-
data: {
|
|
39
|
-
message: string;
|
|
40
|
-
cause?: unknown;
|
|
41
|
-
};
|
|
42
|
-
};
|
|
43
|
-
|
|
44
|
-
export type APIError = {
|
|
45
|
-
name: "APIError";
|
|
46
|
-
data: {
|
|
47
|
-
statusCode: number;
|
|
48
|
-
isRetryable: boolean;
|
|
49
|
-
message: string;
|
|
50
|
-
responseBody?: string;
|
|
51
|
-
};
|
|
52
|
-
};
|
|
53
|
-
|
|
54
|
-
export type ClineConnectionError = {
|
|
55
|
-
name: "ClineConnectionError";
|
|
56
|
-
data: {
|
|
57
|
-
message: string;
|
|
58
|
-
cause?: unknown;
|
|
59
|
-
};
|
|
60
|
-
};
|
|
61
|
-
|
|
62
|
-
export type BizarError = PluginError | DashboardError | ConnectionError | APIError | ClineConnectionError;
|
|
63
|
-
|
|
64
|
-
/**
|
|
65
|
-
* Type guard: narrows `unknown` to `BizarError`.
|
|
66
|
-
*/
|
|
67
|
-
export function isBizarError(value: unknown): value is BizarError {
|
|
68
|
-
if (typeof value !== "object" || value === null) return false;
|
|
69
|
-
const v = value as { name?: unknown };
|
|
70
|
-
if (typeof v.name !== "string") return false;
|
|
71
|
-
return (
|
|
72
|
-
v.name === "PluginError" ||
|
|
73
|
-
v.name === "DashboardError" ||
|
|
74
|
-
v.name === "ConnectionError" ||
|
|
75
|
-
v.name === "APIError" ||
|
|
76
|
-
v.name === "ClineConnectionError"
|
|
77
|
-
);
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
/**
|
|
81
|
-
* Convenience: build a ConnectionError from a thrown fetch failure.
|
|
82
|
-
*/
|
|
83
|
-
export function connectionErrorFrom(err: unknown): ConnectionError {
|
|
84
|
-
if (err instanceof Error) {
|
|
85
|
-
return {
|
|
86
|
-
name: "ConnectionError",
|
|
87
|
-
data: { message: err.message, cause: err },
|
|
88
|
-
};
|
|
89
|
-
}
|
|
90
|
-
return {
|
|
91
|
-
name: "ConnectionError",
|
|
92
|
-
data: { message: String(err), cause: err },
|
|
93
|
-
};
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
/**
|
|
97
|
-
* Convenience: build a DashboardError from a non-OK HTTP response.
|
|
98
|
-
*/
|
|
99
|
-
export function dashboardErrorFrom(status: number, body: string): DashboardError {
|
|
100
|
-
let message = `HTTP ${status}`;
|
|
101
|
-
try {
|
|
102
|
-
const parsed = JSON.parse(body) as { data?: { message?: string }; message?: string };
|
|
103
|
-
if (parsed.data?.message) message = parsed.data.message;
|
|
104
|
-
else if (parsed.message) message = parsed.message;
|
|
105
|
-
} catch {
|
|
106
|
-
// body wasn't JSON; fall back to status-only message
|
|
107
|
-
}
|
|
108
|
-
return {
|
|
109
|
-
name: "DashboardError",
|
|
110
|
-
data: { statusCode: status, message },
|
|
111
|
-
};
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
/**
|
|
115
|
-
* Convenience: build an APIError from a 5xx or specific 4xx response.
|
|
116
|
-
* 5xx and 429 are retryable.
|
|
117
|
-
*/
|
|
118
|
-
export function apiErrorFrom(status: number, body: string): APIError {
|
|
119
|
-
const isRetryable = status >= 500 || status === 429;
|
|
120
|
-
return {
|
|
121
|
-
name: "APIError",
|
|
122
|
-
data: {
|
|
123
|
-
statusCode: status,
|
|
124
|
-
isRetryable,
|
|
125
|
-
message: `Dashboard API returned ${status}`,
|
|
126
|
-
responseBody: body,
|
|
127
|
-
},
|
|
128
|
-
};
|
|
129
|
-
}
|
|
@@ -1,153 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* SSE event subscriber for the BizarHarness SDK.
|
|
3
|
-
*
|
|
4
|
-
* Wraps the cline-style SSE format:
|
|
5
|
-
*
|
|
6
|
-
* event: <type>
|
|
7
|
-
* data: {"type": "<type>", "properties": { ... }}
|
|
8
|
-
*
|
|
9
|
-
* Returns an async iterable + close handle.
|
|
10
|
-
*
|
|
11
|
-
* Reference: cline SDK pattern (`for await (const event of events.stream)`).
|
|
12
|
-
*/
|
|
13
|
-
|
|
14
|
-
import type { DashboardEvent } from "./types.js";
|
|
15
|
-
|
|
16
|
-
export interface EventSubscriptionOptions {
|
|
17
|
-
signal?: AbortSignal;
|
|
18
|
-
/** Replay events from this sequence number (buffered by dashboard). */
|
|
19
|
-
since?: number;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
export interface EventSubscription {
|
|
23
|
-
stream: AsyncIterable<DashboardEvent>;
|
|
24
|
-
close(): void;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
/**
|
|
28
|
-
* Subscribe to dashboard events. The returned stream yields parsed
|
|
29
|
-
* `DashboardEvent` instances.
|
|
30
|
-
*
|
|
31
|
-
* If `signal` aborts, the underlying fetch is aborted and the stream ends.
|
|
32
|
-
*/
|
|
33
|
-
export async function subscribeEvents(
|
|
34
|
-
baseUrl: string,
|
|
35
|
-
authHeader: string,
|
|
36
|
-
opts: EventSubscriptionOptions = {},
|
|
37
|
-
fetchImpl: typeof fetch = fetch,
|
|
38
|
-
): Promise<EventSubscription> {
|
|
39
|
-
const url = new URL("/event", baseUrl);
|
|
40
|
-
if (typeof opts.since === "number") {
|
|
41
|
-
url.searchParams.set("since", String(opts.since));
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
const controller = new AbortController();
|
|
45
|
-
if (opts.signal) {
|
|
46
|
-
opts.signal.addEventListener("abort", () => controller.abort(), { once: true });
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
const response = await fetchImpl(url.toString(), {
|
|
50
|
-
method: "GET",
|
|
51
|
-
headers: {
|
|
52
|
-
Authorization: authHeader,
|
|
53
|
-
Accept: "text/event-stream",
|
|
54
|
-
},
|
|
55
|
-
signal: controller.signal,
|
|
56
|
-
});
|
|
57
|
-
|
|
58
|
-
if (!response.ok || !response.body) {
|
|
59
|
-
throw new Error(
|
|
60
|
-
`SSE subscribe failed: ${response.status} ${response.statusText}`,
|
|
61
|
-
);
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
const stream = parseSseStream<DashboardEvent>(response.body, controller);
|
|
65
|
-
return {
|
|
66
|
-
stream,
|
|
67
|
-
close: () => controller.abort(),
|
|
68
|
-
};
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
/**
|
|
72
|
-
* Parse an SSE byte stream into a typed async iterable.
|
|
73
|
-
*
|
|
74
|
-
* Handles the cline SSE format: lines starting with `event:` and `data:`.
|
|
75
|
-
* Lines beginning with `:` are comments (ignored). Empty lines delimit events.
|
|
76
|
-
*
|
|
77
|
-
* Yields parsed events as `{ type, properties, ... }` objects (the JSON
|
|
78
|
-
* decoded value of the `data:` line).
|
|
79
|
-
*/
|
|
80
|
-
export async function* parseSseStream<T extends { type: string }>(
|
|
81
|
-
body: ReadableStream<Uint8Array>,
|
|
82
|
-
controller: AbortController,
|
|
83
|
-
): AsyncIterable<T> {
|
|
84
|
-
const reader = body.getReader();
|
|
85
|
-
const decoder = new TextDecoder("utf-8");
|
|
86
|
-
let buffer = "";
|
|
87
|
-
|
|
88
|
-
try {
|
|
89
|
-
while (true) {
|
|
90
|
-
const { done, value } = await reader.read();
|
|
91
|
-
if (done) break;
|
|
92
|
-
|
|
93
|
-
buffer += decoder.decode(value, { stream: true });
|
|
94
|
-
|
|
95
|
-
// SSE events are delimited by a blank line.
|
|
96
|
-
let boundary = buffer.indexOf("\n\n");
|
|
97
|
-
while (boundary !== -1) {
|
|
98
|
-
const raw = buffer.slice(0, boundary);
|
|
99
|
-
buffer = buffer.slice(boundary + 2);
|
|
100
|
-
const parsed = parseSseEvent(raw);
|
|
101
|
-
if (parsed !== null) {
|
|
102
|
-
yield parsed as T;
|
|
103
|
-
}
|
|
104
|
-
boundary = buffer.indexOf("\n\n");
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
// Flush any trailing event without a blank line terminator.
|
|
109
|
-
if (buffer.trim().length > 0) {
|
|
110
|
-
const parsed = parseSseEvent(buffer);
|
|
111
|
-
if (parsed !== null) yield parsed as T;
|
|
112
|
-
}
|
|
113
|
-
} finally {
|
|
114
|
-
reader.releaseLock();
|
|
115
|
-
controller.abort();
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
function parseSseEvent(raw: string): unknown | null {
|
|
120
|
-
let eventType: string | null = null;
|
|
121
|
-
const dataLines: string[] = [];
|
|
122
|
-
|
|
123
|
-
for (const line of raw.split("\n")) {
|
|
124
|
-
if (line.length === 0) continue;
|
|
125
|
-
if (line.startsWith(":")) continue; // comment
|
|
126
|
-
const colonIdx = line.indexOf(":");
|
|
127
|
-
if (colonIdx === -1) continue;
|
|
128
|
-
const field = line.slice(0, colonIdx);
|
|
129
|
-
let value = line.slice(colonIdx + 1);
|
|
130
|
-
if (value.startsWith(" ")) value = value.slice(1);
|
|
131
|
-
|
|
132
|
-
if (field === "event") {
|
|
133
|
-
eventType = value;
|
|
134
|
-
} else if (field === "data") {
|
|
135
|
-
dataLines.push(value);
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
if (dataLines.length === 0) return null;
|
|
140
|
-
const data = dataLines.join("\n");
|
|
141
|
-
|
|
142
|
-
try {
|
|
143
|
-
const parsed = JSON.parse(data) as { type?: string; properties?: unknown };
|
|
144
|
-
// Prefer the SSE `event:` line; fall back to JSON's `type` field.
|
|
145
|
-
if (eventType && parsed.type !== eventType) {
|
|
146
|
-
return { ...parsed, type: eventType };
|
|
147
|
-
}
|
|
148
|
-
return parsed;
|
|
149
|
-
} catch {
|
|
150
|
-
// Malformed JSON — skip this event rather than crash the stream.
|
|
151
|
-
return null;
|
|
152
|
-
}
|
|
153
|
-
}
|