vibepulse 0.2.2 → 0.3.0-beta.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/.next/BUILD_ID +1 -1
- package/.next/app-path-routes-manifest.json +1 -0
- package/.next/build-manifest.json +2 -2
- package/.next/cache/.previewinfo +1 -1
- package/.next/cache/.rscinfo +1 -1
- package/.next/cache/.tsbuildinfo +1 -1
- package/.next/cache/config.json +3 -3
- package/.next/fallback-build-manifest.json +2 -2
- package/.next/prerender-manifest.json +3 -3
- package/.next/routes-manifest.json +8 -0
- package/.next/server/app/_global-error/page.js +1 -1
- package/.next/server/app/_global-error/page.js.nft.json +1 -1
- package/.next/server/app/_global-error.html +2 -2
- package/.next/server/app/_global-error.rsc +1 -1
- package/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
- package/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/.next/server/app/_not-found/page.js +1 -1
- package/.next/server/app/_not-found/page.js.nft.json +1 -1
- package/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/.next/server/app/_not-found.html +1 -1
- package/.next/server/app/_not-found.rsc +2 -2
- package/.next/server/app/_not-found.segments/_full.segment.rsc +2 -2
- package/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
- package/.next/server/app/_not-found.segments/_index.segment.rsc +2 -2
- package/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
- package/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
- package/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -2
- package/.next/server/app/api/node/sessions/[id]/open-editor/route.js.nft.json +1 -1
- package/.next/server/app/api/node/sessions/route.js +5 -3
- package/.next/server/app/api/node/sessions/route.js.nft.json +1 -1
- package/.next/server/app/api/opencode-config/route.js.nft.json +1 -1
- package/.next/server/app/api/opencode-config/status/route.js.nft.json +1 -1
- package/.next/server/app/api/profiles/[id]/apply/route.js.nft.json +1 -1
- package/.next/server/app/api/profiles/[id]/export/route.js.nft.json +1 -1
- package/.next/server/app/api/profiles/[id]/route.js.nft.json +1 -1
- package/.next/server/app/api/profiles/import/route.js.nft.json +1 -1
- package/.next/server/app/api/profiles/route.js.nft.json +1 -1
- package/.next/server/app/api/sessions/[id]/archive/route.js +3 -2
- package/.next/server/app/api/sessions/[id]/archive/route.js.nft.json +1 -1
- package/.next/server/app/api/sessions/[id]/delete/route.js +3 -2
- package/.next/server/app/api/sessions/[id]/delete/route.js.nft.json +1 -1
- package/.next/server/app/api/sessions/[id]/open-editor/route.js +1 -1
- package/.next/server/app/api/sessions/[id]/open-editor/route.js.nft.json +1 -1
- package/.next/server/app/api/sessions/[id]/restore/route/app-paths-manifest.json +3 -0
- package/.next/server/app/api/sessions/[id]/restore/route/build-manifest.json +11 -0
- package/.next/server/app/api/sessions/[id]/restore/route/server-reference-manifest.json +4 -0
- package/.next/server/app/api/sessions/[id]/restore/route.js +8 -0
- package/.next/server/app/api/sessions/[id]/restore/route.js.map +5 -0
- package/.next/server/app/api/sessions/[id]/restore/route.js.nft.json +1 -0
- package/.next/server/app/api/sessions/[id]/restore/route_client-reference-manifest.js +2 -0
- package/.next/server/app/api/sessions/route.js +4 -2
- package/.next/server/app/api/sessions/route.js.nft.json +1 -1
- package/.next/server/app/index.html +1 -1
- package/.next/server/app/index.rsc +3 -3
- package/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
- package/.next/server/app/index.segments/_full.segment.rsc +3 -3
- package/.next/server/app/index.segments/_head.segment.rsc +1 -1
- package/.next/server/app/index.segments/_index.segment.rsc +2 -2
- package/.next/server/app/index.segments/_tree.segment.rsc +2 -2
- package/.next/server/app/page_client-reference-manifest.js +1 -1
- package/.next/server/app-paths-manifest.json +1 -0
- package/.next/server/chunks/[root-of-the-server]__31d19c5c._.js +3 -0
- package/.next/server/chunks/[root-of-the-server]__31d19c5c._.js.map +1 -0
- package/.next/server/chunks/[root-of-the-server]__56f5f249._.js +1 -1
- package/.next/server/chunks/[root-of-the-server]__56f5f249._.js.map +1 -1
- package/.next/server/chunks/[root-of-the-server]__5e0a0e38._.js +3 -0
- package/.next/server/chunks/[root-of-the-server]__5e0a0e38._.js.map +1 -0
- package/.next/server/chunks/[root-of-the-server]__98073dd6._.js +3 -0
- package/.next/server/chunks/[root-of-the-server]__98073dd6._.js.map +1 -0
- package/.next/server/chunks/[root-of-the-server]__b7b717eb._.js +3 -0
- package/.next/server/chunks/[root-of-the-server]__b7b717eb._.js.map +1 -0
- package/.next/server/chunks/[root-of-the-server]__d8e61048._.js +1 -1
- package/.next/server/chunks/[root-of-the-server]__d8e61048._.js.map +1 -1
- package/.next/server/chunks/[root-of-the-server]__f441109e._.js +3 -0
- package/.next/server/chunks/[root-of-the-server]__f441109e._.js.map +1 -0
- package/.next/server/chunks/_next-internal_server_app_api_sessions_[id]_restore_route_actions_af7d6b6c.js +3 -0
- package/.next/server/chunks/_next-internal_server_app_api_sessions_[id]_restore_route_actions_af7d6b6c.js.map +1 -0
- package/.next/server/chunks/node_modules_next_dist_esm_build_templates_app-route_2edc9589.js +3 -0
- package/.next/server/chunks/node_modules_next_dist_esm_build_templates_app-route_2edc9589.js.map +1 -0
- package/.next/server/chunks/node_modules_next_dist_esm_build_templates_app-route_7f178d4a.js +3 -0
- package/.next/server/chunks/node_modules_next_dist_esm_build_templates_app-route_7f178d4a.js.map +1 -0
- package/.next/server/chunks/node_modules_next_dist_esm_build_templates_app-route_aca45402.js +1 -1
- package/.next/server/chunks/node_modules_next_dist_esm_build_templates_app-route_aca45402.js.map +1 -1
- package/.next/server/chunks/node_modules_next_dist_esm_build_templates_app-route_b054aff3.js +1 -1
- package/.next/server/chunks/node_modules_next_dist_esm_build_templates_app-route_b054aff3.js.map +1 -1
- package/.next/server/chunks/node_modules_next_dist_esm_build_templates_app-route_d0c0f338.js +3 -0
- package/.next/server/chunks/node_modules_next_dist_esm_build_templates_app-route_d0c0f338.js.map +1 -0
- package/.next/server/chunks/src_lib_session-providers_claudeCode_ts_0f9590ed._.js +3 -0
- package/.next/server/chunks/src_lib_session-providers_claudeCode_ts_0f9590ed._.js.map +1 -0
- package/.next/server/chunks/ssr/{[root-of-the-server]__631e12d0._.js → [root-of-the-server]__c91a8380._.js} +2 -2
- package/.next/server/chunks/ssr/{[root-of-the-server]__631e12d0._.js.map → [root-of-the-server]__c91a8380._.js.map} +1 -1
- package/.next/server/chunks/ssr/src_app_page_tsx_a7111f3e._.js +3 -3
- package/.next/server/chunks/ssr/src_app_page_tsx_a7111f3e._.js.map +1 -1
- package/.next/server/pages/404.html +1 -1
- package/.next/server/pages/500.html +2 -2
- package/.next/server/server-reference-manifest.js +1 -1
- package/.next/server/server-reference-manifest.json +1 -1
- package/.next/standalone/.next/BUILD_ID +1 -1
- package/.next/standalone/.next/app-path-routes-manifest.json +1 -0
- package/.next/standalone/.next/build-manifest.json +2 -2
- package/.next/standalone/.next/prerender-manifest.json +3 -3
- package/.next/standalone/.next/routes-manifest.json +8 -0
- package/.next/standalone/.next/server/app/_global-error/page.js +1 -1
- package/.next/standalone/.next/server/app/_global-error/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/_global-error.html +2 -2
- package/.next/standalone/.next/server/app/_global-error.rsc +1 -1
- package/.next/standalone/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/_not-found/page.js +1 -1
- package/.next/standalone/.next/server/app/_not-found/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/_not-found.html +1 -1
- package/.next/standalone/.next/server/app/_not-found.rsc +2 -2
- package/.next/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/api/node/sessions/[id]/open-editor/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/node/sessions/route.js +5 -3
- package/.next/standalone/.next/server/app/api/node/sessions/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/opencode-config/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/opencode-config/status/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/profiles/[id]/apply/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/profiles/[id]/export/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/profiles/[id]/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/profiles/import/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/profiles/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/sessions/[id]/archive/route.js +3 -2
- package/.next/standalone/.next/server/app/api/sessions/[id]/archive/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/sessions/[id]/delete/route.js +3 -2
- package/.next/standalone/.next/server/app/api/sessions/[id]/delete/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/sessions/[id]/open-editor/route.js +1 -1
- package/.next/standalone/.next/server/app/api/sessions/[id]/open-editor/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/sessions/[id]/restore/route/app-paths-manifest.json +3 -0
- package/.next/standalone/.next/server/app/api/sessions/[id]/restore/route/build-manifest.json +11 -0
- package/.next/standalone/.next/server/app/api/sessions/[id]/restore/route/server-reference-manifest.json +4 -0
- package/.next/standalone/.next/server/app/api/sessions/[id]/restore/route.js +8 -0
- package/.next/standalone/.next/server/app/api/sessions/[id]/restore/route.js.map +5 -0
- package/.next/standalone/.next/server/app/api/sessions/[id]/restore/route.js.nft.json +1 -0
- package/.next/standalone/.next/server/app/api/sessions/[id]/restore/route_client-reference-manifest.js +2 -0
- package/.next/standalone/.next/server/app/api/sessions/route.js +4 -2
- package/.next/standalone/.next/server/app/api/sessions/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/index.html +1 -1
- package/.next/standalone/.next/server/app/index.rsc +3 -3
- package/.next/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/index.segments/_full.segment.rsc +3 -3
- package/.next/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/index.segments/_index.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/index.segments/_tree.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app-paths-manifest.json +1 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__31d19c5c._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__56f5f249._.js +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__5e0a0e38._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__98073dd6._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__b7b717eb._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__d8e61048._.js +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__f441109e._.js +3 -0
- package/.next/standalone/.next/server/chunks/_next-internal_server_app_api_sessions_[id]_restore_route_actions_af7d6b6c.js +3 -0
- package/.next/standalone/.next/server/chunks/node_modules_next_dist_esm_build_templates_app-route_2edc9589.js +3 -0
- package/.next/standalone/.next/server/chunks/node_modules_next_dist_esm_build_templates_app-route_7f178d4a.js +3 -0
- package/.next/standalone/.next/server/chunks/node_modules_next_dist_esm_build_templates_app-route_aca45402.js +1 -1
- package/.next/standalone/.next/server/chunks/node_modules_next_dist_esm_build_templates_app-route_b054aff3.js +1 -1
- package/.next/standalone/.next/server/chunks/node_modules_next_dist_esm_build_templates_app-route_d0c0f338.js +3 -0
- package/.next/standalone/.next/server/chunks/src_lib_session-providers_claudeCode_ts_0f9590ed._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__631e12d0._.js → [root-of-the-server]__c91a8380._.js} +2 -2
- package/.next/standalone/.next/server/chunks/ssr/src_app_page_tsx_a7111f3e._.js +3 -3
- package/.next/standalone/.next/server/pages/404.html +1 -1
- package/.next/standalone/.next/server/pages/500.html +2 -2
- package/.next/standalone/.next/server/server-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/server-reference-manifest.json +1 -1
- package/.next/standalone/.next/static/chunks/b3bc362202331708.css +3 -0
- package/.next/standalone/.next/static/chunks/{65d5354ba0add961.js → c1294e057d8d4681.js} +3 -3
- package/.next/standalone/README.md +29 -5
- package/.next/standalone/docs/session-status-detection.md +36 -0
- package/.next/standalone/docs/superpowers/specs/2026-04-09-claude-capability-alignment-design.md +39 -0
- package/.next/standalone/package-lock.json +2 -2
- package/.next/standalone/package.json +1 -1
- package/.next/standalone/src/app/api/node/sessions/[id]/archive/route.test.ts +60 -1
- package/.next/standalone/src/app/api/node/sessions/[id]/archive/route.ts +77 -22
- package/.next/standalone/src/app/api/node/sessions/route.test.ts +282 -0
- package/.next/standalone/src/app/api/node/sessions/route.ts +141 -17
- package/.next/standalone/src/app/api/opencode-events/route.test.ts +3 -1
- package/.next/standalone/src/app/api/sessions/[id]/archive/route.test.ts +101 -0
- package/.next/standalone/src/app/api/sessions/[id]/archive/route.ts +47 -12
- package/.next/standalone/src/app/api/sessions/[id]/delete/route.test.ts +92 -0
- package/.next/standalone/src/app/api/sessions/[id]/delete/route.ts +45 -10
- package/.next/standalone/src/app/api/sessions/[id]/open-editor/route.test.ts +74 -0
- package/.next/standalone/src/app/api/sessions/[id]/open-editor/route.ts +22 -2
- package/.next/standalone/src/app/api/sessions/[id]/restore/route.test.ts +186 -0
- package/.next/standalone/src/app/api/sessions/[id]/restore/route.ts +184 -0
- package/.next/standalone/src/app/api/sessions/route.test.ts +1889 -107
- package/.next/standalone/src/app/api/sessions/route.ts +365 -981
- package/.next/standalone/src/components/KanbanBoard.test.tsx +307 -1
- package/.next/standalone/src/components/KanbanBoard.tsx +105 -18
- package/.next/standalone/src/components/ProjectCard.test.tsx +416 -2
- package/.next/standalone/src/components/ProjectCard.tsx +238 -86
- package/.next/standalone/src/components/SessionCard.test.tsx +253 -2
- package/.next/standalone/src/components/SessionCard.tsx +182 -76
- package/.next/standalone/src/hooks/useOpencodeSync.test.ts +321 -1
- package/.next/standalone/src/hooks/useOpencodeSync.ts +16 -12
- package/.next/standalone/src/lib/claudeSessionOverrides.test.ts +75 -0
- package/.next/standalone/src/lib/claudeSessionOverrides.ts +169 -0
- package/.next/standalone/src/lib/session-providers/claudeCode.test.ts +2288 -0
- package/.next/standalone/src/lib/session-providers/claudeCode.ts +1083 -0
- package/.next/standalone/src/lib/session-providers/localAggregator.test.ts +322 -0
- package/.next/standalone/src/lib/session-providers/localAggregator.ts +302 -0
- package/.next/standalone/src/lib/session-providers/opencodeProvider.ts +723 -0
- package/.next/standalone/src/lib/session-providers/providerIds.test.ts +337 -0
- package/.next/standalone/src/lib/session-providers/providerIds.ts +176 -0
- package/.next/standalone/src/lib/session-providers/types.ts +131 -0
- package/.next/standalone/src/lib/transform.test.ts +253 -0
- package/.next/standalone/src/lib/transform.ts +96 -37
- package/.next/standalone/src/types/index.ts +23 -17
- package/.next/static/chunks/b3bc362202331708.css +3 -0
- package/.next/static/chunks/{65d5354ba0add961.js → c1294e057d8d4681.js} +3 -3
- package/.next/trace +1 -1
- package/.next/trace-build +1 -1
- package/.next/types/routes.d.ts +2 -1
- package/.next/types/validator.ts +9 -0
- package/README.md +29 -5
- package/package.json +1 -1
- package/.next/server/chunks/[root-of-the-server]__2f981540._.js +0 -3
- package/.next/server/chunks/[root-of-the-server]__2f981540._.js.map +0 -1
- package/.next/server/chunks/[root-of-the-server]__3745b314._.js +0 -3
- package/.next/server/chunks/[root-of-the-server]__3745b314._.js.map +0 -1
- package/.next/server/chunks/[root-of-the-server]__6c428a24._.js +0 -3
- package/.next/server/chunks/[root-of-the-server]__6c428a24._.js.map +0 -1
- package/.next/server/chunks/[root-of-the-server]__73a00b88._.js +0 -3
- package/.next/server/chunks/[root-of-the-server]__73a00b88._.js.map +0 -1
- package/.next/server/chunks/[root-of-the-server]__db285678._.js +0 -3
- package/.next/server/chunks/[root-of-the-server]__db285678._.js.map +0 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__2f981540._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__3745b314._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__6c428a24._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__73a00b88._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__db285678._.js +0 -3
- package/.next/standalone/.next/static/chunks/f42202943f6742e5.css +0 -3
- package/.next/static/chunks/f42202943f6742e5.css +0 -3
- /package/.next/standalone/.next/static/{5kq9DtuBFVxu4jsgmL5Q- → bsWNvgDS7Zp38Yt9q0DUg}/_buildManifest.js +0 -0
- /package/.next/standalone/.next/static/{5kq9DtuBFVxu4jsgmL5Q- → bsWNvgDS7Zp38Yt9q0DUg}/_clientMiddlewareManifest.json +0 -0
- /package/.next/standalone/.next/static/{5kq9DtuBFVxu4jsgmL5Q- → bsWNvgDS7Zp38Yt9q0DUg}/_ssgManifest.js +0 -0
- /package/.next/static/{5kq9DtuBFVxu4jsgmL5Q- → bsWNvgDS7Zp38Yt9q0DUg}/_buildManifest.js +0 -0
- /package/.next/static/{5kq9DtuBFVxu4jsgmL5Q- → bsWNvgDS7Zp38Yt9q0DUg}/_clientMiddlewareManifest.json +0 -0
- /package/.next/static/{5kq9DtuBFVxu4jsgmL5Q- → bsWNvgDS7Zp38Yt9q0DUg}/_ssgManifest.js +0 -0
|
@@ -33,6 +33,8 @@ function makeSession(overrides: SessionOverrides = {}): OpencodeSession {
|
|
|
33
33
|
rawSessionId: overrides.rawSessionId,
|
|
34
34
|
sourceSessionKey: overrides.sourceSessionKey,
|
|
35
35
|
readOnly: overrides.readOnly,
|
|
36
|
+
provider: overrides.provider,
|
|
37
|
+
providerRawId: overrides.providerRawId,
|
|
36
38
|
};
|
|
37
39
|
}
|
|
38
40
|
|
|
@@ -119,3 +121,254 @@ describe('transformSession archive precedence', () => {
|
|
|
119
121
|
expect(card.readOnly).toBe(false);
|
|
120
122
|
});
|
|
121
123
|
});
|
|
124
|
+
|
|
125
|
+
describe('transformSession provider propagation', () => {
|
|
126
|
+
it('defaults provider to opencode when not specified', () => {
|
|
127
|
+
const session = makeSession();
|
|
128
|
+
|
|
129
|
+
const card = transformSession(session);
|
|
130
|
+
|
|
131
|
+
expect(card.provider).toBe('opencode');
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
it('defaults readOnly to false for OpenCode sessions', () => {
|
|
135
|
+
const session = makeSession();
|
|
136
|
+
|
|
137
|
+
const card = transformSession(session);
|
|
138
|
+
|
|
139
|
+
expect(card.readOnly).toBe(false);
|
|
140
|
+
expect(card.capabilities).toEqual({
|
|
141
|
+
openProject: true,
|
|
142
|
+
openEditor: true,
|
|
143
|
+
archive: true,
|
|
144
|
+
delete: true,
|
|
145
|
+
});
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
it('preserves explicit claude-code provider', () => {
|
|
149
|
+
const session = makeSession({
|
|
150
|
+
provider: 'claude-code',
|
|
151
|
+
providerRawId: '550e8400-e29b-41d4-a716-446655440000',
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
const card = transformSession(session);
|
|
155
|
+
|
|
156
|
+
expect(card.provider).toBe('claude-code');
|
|
157
|
+
expect(card.providerRawId).toBe('550e8400-e29b-41d4-a716-446655440000');
|
|
158
|
+
});
|
|
159
|
+
|
|
160
|
+
it('preserves explicit readOnly true', () => {
|
|
161
|
+
const session = makeSession({ readOnly: true });
|
|
162
|
+
|
|
163
|
+
const card = transformSession(session);
|
|
164
|
+
|
|
165
|
+
expect(card.readOnly).toBe(true);
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
it('falls back to rawSessionId when providerRawId not specified', () => {
|
|
169
|
+
const session = makeSession({ rawSessionId: 'ses_123' });
|
|
170
|
+
|
|
171
|
+
const card = transformSession(session);
|
|
172
|
+
|
|
173
|
+
expect(card.providerRawId).toBe('ses_123');
|
|
174
|
+
});
|
|
175
|
+
|
|
176
|
+
it('uses providerRawId over rawSessionId when both specified', () => {
|
|
177
|
+
const session = makeSession({
|
|
178
|
+
rawSessionId: 'ses_123',
|
|
179
|
+
providerRawId: 'claude~550e8400-e29b-41d4-a716-446655440000',
|
|
180
|
+
});
|
|
181
|
+
|
|
182
|
+
const card = transformSession(session);
|
|
183
|
+
|
|
184
|
+
expect(card.providerRawId).toBe('claude~550e8400-e29b-41d4-a716-446655440000');
|
|
185
|
+
});
|
|
186
|
+
|
|
187
|
+
it('correctly handles Claude-backed sessions from provider properties', () => {
|
|
188
|
+
const session = makeSession({
|
|
189
|
+
provider: 'claude-code',
|
|
190
|
+
readOnly: true,
|
|
191
|
+
providerRawId: '550e8400-e29b-41d4-a716-446655440000',
|
|
192
|
+
});
|
|
193
|
+
|
|
194
|
+
const card = transformSession(session);
|
|
195
|
+
|
|
196
|
+
expect(card.provider).toBe('claude-code');
|
|
197
|
+
expect(card.readOnly).toBe(true);
|
|
198
|
+
expect(card.capabilities).toEqual({
|
|
199
|
+
openProject: true,
|
|
200
|
+
openEditor: false,
|
|
201
|
+
archive: true,
|
|
202
|
+
delete: true,
|
|
203
|
+
});
|
|
204
|
+
expect(card.providerRawId).toBe('550e8400-e29b-41d4-a716-446655440000');
|
|
205
|
+
});
|
|
206
|
+
});
|
|
207
|
+
|
|
208
|
+
describe('transformSession child roll-up semantics', () => {
|
|
209
|
+
it('pulls a Claude parent into busy when a verified Claude child is active', () => {
|
|
210
|
+
const now = Date.now();
|
|
211
|
+
const child = makeSession({
|
|
212
|
+
id: 'claude-child-1',
|
|
213
|
+
provider: 'claude-code',
|
|
214
|
+
parentID: 'claude-parent-1',
|
|
215
|
+
realTimeStatus: 'busy',
|
|
216
|
+
time: {
|
|
217
|
+
created: now - 10_000,
|
|
218
|
+
updated: now - 2_000,
|
|
219
|
+
},
|
|
220
|
+
});
|
|
221
|
+
|
|
222
|
+
const parent = makeSession({
|
|
223
|
+
id: 'claude-parent-1',
|
|
224
|
+
provider: 'claude-code',
|
|
225
|
+
realTimeStatus: 'idle',
|
|
226
|
+
children: [child],
|
|
227
|
+
});
|
|
228
|
+
|
|
229
|
+
const card = transformSession(parent);
|
|
230
|
+
|
|
231
|
+
expect(card.status).toBe('busy');
|
|
232
|
+
expect(card.opencodeStatus).toBe('busy');
|
|
233
|
+
expect(card.waitingForUser).toBe(false);
|
|
234
|
+
expect(card.debugReason).toBe('child_recent_activity');
|
|
235
|
+
});
|
|
236
|
+
|
|
237
|
+
it('pulls a Claude parent into review when a verified Claude child is idle but waiting for user', () => {
|
|
238
|
+
const now = Date.now();
|
|
239
|
+
const child = makeSession({
|
|
240
|
+
id: 'claude-child-2',
|
|
241
|
+
provider: 'claude-code',
|
|
242
|
+
parentID: 'claude-parent-2',
|
|
243
|
+
realTimeStatus: 'idle',
|
|
244
|
+
waitingForUser: true,
|
|
245
|
+
time: {
|
|
246
|
+
created: now - 12_000,
|
|
247
|
+
updated: now - 3_000,
|
|
248
|
+
},
|
|
249
|
+
});
|
|
250
|
+
|
|
251
|
+
const parent = makeSession({
|
|
252
|
+
id: 'claude-parent-2',
|
|
253
|
+
provider: 'claude-code',
|
|
254
|
+
realTimeStatus: 'idle',
|
|
255
|
+
children: [child],
|
|
256
|
+
});
|
|
257
|
+
|
|
258
|
+
const card = transformSession(parent);
|
|
259
|
+
const firstChild = card.children?.[0];
|
|
260
|
+
|
|
261
|
+
expect(card.status).toBe('review');
|
|
262
|
+
expect(card.opencodeStatus).toBe('busy');
|
|
263
|
+
expect(card.waitingForUser).toBe(true);
|
|
264
|
+
expect(card.debugReason).toBe('waiting_for_user');
|
|
265
|
+
expect(firstChild?.waitingForUser).toBe(true);
|
|
266
|
+
});
|
|
267
|
+
|
|
268
|
+
it('ignores malformed Claude child rows so unrelated parents stay idle', () => {
|
|
269
|
+
const now = Date.now();
|
|
270
|
+
const childWithoutParent = makeSession({
|
|
271
|
+
id: 'claude-child-missing-parent',
|
|
272
|
+
provider: 'claude-code',
|
|
273
|
+
realTimeStatus: 'busy',
|
|
274
|
+
waitingForUser: true,
|
|
275
|
+
time: {
|
|
276
|
+
created: now - 10_000,
|
|
277
|
+
updated: now - 1_000,
|
|
278
|
+
},
|
|
279
|
+
});
|
|
280
|
+
const childWithWrongParent = makeSession({
|
|
281
|
+
id: 'claude-child-wrong-parent',
|
|
282
|
+
provider: 'claude-code',
|
|
283
|
+
parentID: 'different-parent',
|
|
284
|
+
realTimeStatus: 'busy',
|
|
285
|
+
time: {
|
|
286
|
+
created: now - 10_000,
|
|
287
|
+
updated: now - 1_000,
|
|
288
|
+
},
|
|
289
|
+
});
|
|
290
|
+
const childWithoutTime = {
|
|
291
|
+
...makeSession({
|
|
292
|
+
id: 'claude-child-without-time',
|
|
293
|
+
provider: 'claude-code',
|
|
294
|
+
parentID: 'claude-parent-3',
|
|
295
|
+
realTimeStatus: 'busy',
|
|
296
|
+
waitingForUser: true,
|
|
297
|
+
}),
|
|
298
|
+
time: undefined,
|
|
299
|
+
} as unknown as OpencodeSession;
|
|
300
|
+
|
|
301
|
+
const parent = makeSession({
|
|
302
|
+
id: 'claude-parent-3',
|
|
303
|
+
provider: 'claude-code',
|
|
304
|
+
realTimeStatus: 'idle',
|
|
305
|
+
children: [childWithoutParent, childWithWrongParent, childWithoutTime],
|
|
306
|
+
});
|
|
307
|
+
|
|
308
|
+
const card = transformSession(parent);
|
|
309
|
+
|
|
310
|
+
expect(card.status).toBe('idle');
|
|
311
|
+
expect(card.opencodeStatus).toBe('idle');
|
|
312
|
+
expect(card.waitingForUser).toBe(false);
|
|
313
|
+
expect(card.debugReason).toBeUndefined();
|
|
314
|
+
expect(card.children).toEqual([]);
|
|
315
|
+
});
|
|
316
|
+
|
|
317
|
+
it('keeps existing OpenCode child roll-up behavior intact', () => {
|
|
318
|
+
const now = Date.now();
|
|
319
|
+
const child = makeSession({
|
|
320
|
+
id: 'opencode-child-1',
|
|
321
|
+
realTimeStatus: 'busy',
|
|
322
|
+
time: {
|
|
323
|
+
created: now - 10_000,
|
|
324
|
+
updated: now - 2_000,
|
|
325
|
+
},
|
|
326
|
+
});
|
|
327
|
+
|
|
328
|
+
const parent = makeSession({
|
|
329
|
+
id: 'opencode-parent-1',
|
|
330
|
+
realTimeStatus: 'idle',
|
|
331
|
+
children: [child],
|
|
332
|
+
});
|
|
333
|
+
|
|
334
|
+
const card = transformSession(parent);
|
|
335
|
+
|
|
336
|
+
expect(card.status).toBe('busy');
|
|
337
|
+
expect(card.opencodeStatus).toBe('busy');
|
|
338
|
+
expect(card.debugReason).toBe('child_recent_activity');
|
|
339
|
+
expect(card.children).toEqual([
|
|
340
|
+
expect.objectContaining({
|
|
341
|
+
id: 'opencode-child-1',
|
|
342
|
+
}),
|
|
343
|
+
]);
|
|
344
|
+
});
|
|
345
|
+
|
|
346
|
+
it('does not promote an OpenCode parent when a child is idle but waiting', () => {
|
|
347
|
+
const now = Date.now();
|
|
348
|
+
const child = makeSession({
|
|
349
|
+
id: 'opencode-child-idle-waiting',
|
|
350
|
+
realTimeStatus: 'idle',
|
|
351
|
+
waitingForUser: true,
|
|
352
|
+
time: {
|
|
353
|
+
created: now - 10_000,
|
|
354
|
+
updated: now - 2_000,
|
|
355
|
+
},
|
|
356
|
+
});
|
|
357
|
+
|
|
358
|
+
const parent = makeSession({
|
|
359
|
+
id: 'opencode-parent-idle-waiting',
|
|
360
|
+
realTimeStatus: 'idle',
|
|
361
|
+
children: [child],
|
|
362
|
+
});
|
|
363
|
+
|
|
364
|
+
const card = transformSession(parent);
|
|
365
|
+
const firstChild = card.children?.[0];
|
|
366
|
+
|
|
367
|
+
expect(card.status).toBe('idle');
|
|
368
|
+
expect(card.opencodeStatus).toBe('idle');
|
|
369
|
+
expect(card.waitingForUser).toBe(false);
|
|
370
|
+
expect(card.debugReason).toBeUndefined();
|
|
371
|
+
expect(firstChild?.waitingForUser).toBe(false);
|
|
372
|
+
expect(firstChild?.debugReason).toBeUndefined();
|
|
373
|
+
});
|
|
374
|
+
});
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { KanbanCard, OpencodeSession, KanbanColumn, SessionDebugReason } from '@/types';
|
|
1
|
+
import { KanbanCard, OpencodeSession, KanbanColumn, SessionDebugReason, SessionProvider } from '@/types';
|
|
2
|
+
import { DEFAULT_PROVIDER_CONTEXT, getDefaultProviderContext } from './session-providers/providerIds';
|
|
2
3
|
|
|
3
4
|
interface EnrichedSession extends OpencodeSession {
|
|
4
5
|
realTimeStatus?: 'idle' | 'busy' | 'retry';
|
|
@@ -10,22 +11,80 @@ interface EnrichedSession extends OpencodeSession {
|
|
|
10
11
|
type EnrichedChild = NonNullable<EnrichedSession['children']>[number];
|
|
11
12
|
|
|
12
13
|
const RECENT_ACTIVITY_FALLBACK_MS = 5 * 60 * 1000;
|
|
14
|
+
const CHILD_BLOCKER_STALENESS_MS = 10 * 60 * 1000;
|
|
15
|
+
|
|
16
|
+
function getChildActivityTimestamp(child: EnrichedChild | undefined): number | undefined {
|
|
17
|
+
const childUpdatedAt = child?.time?.updated || child?.time?.created;
|
|
18
|
+
return typeof childUpdatedAt === 'number' && childUpdatedAt > 0 ? childUpdatedAt : undefined;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function isVerifiedClaudeChild(parent: EnrichedSession, child: EnrichedChild | undefined): boolean {
|
|
22
|
+
if (!child || child.provider !== 'claude-code') {
|
|
23
|
+
return true;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const parentProvider = parent.provider ?? DEFAULT_PROVIDER_CONTEXT.provider;
|
|
27
|
+
if (parentProvider !== 'claude-code') {
|
|
28
|
+
return false;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
return (
|
|
32
|
+
typeof child.id === 'string' &&
|
|
33
|
+
child.id.length > 0 &&
|
|
34
|
+
child.id !== parent.id &&
|
|
35
|
+
child.parentID === parent.id &&
|
|
36
|
+
getChildActivityTimestamp(child) !== undefined
|
|
37
|
+
);
|
|
38
|
+
}
|
|
13
39
|
|
|
14
40
|
function isRecentlyUpdated(updatedAt: number | undefined, now: number): boolean {
|
|
15
41
|
return typeof updatedAt === 'number' && updatedAt > 0 && now - updatedAt <= RECENT_ACTIVITY_FALLBACK_MS;
|
|
16
42
|
}
|
|
17
43
|
|
|
18
|
-
function
|
|
44
|
+
function getChildProvider(parent: EnrichedSession, child: EnrichedChild | undefined): SessionProvider {
|
|
45
|
+
return child?.provider ?? parent.provider ?? DEFAULT_PROVIDER_CONTEXT.provider;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function shouldMarkChildWaitingForUser(parent: EnrichedSession, child: EnrichedChild | undefined): boolean {
|
|
49
|
+
if (!child) return false;
|
|
50
|
+
|
|
51
|
+
const childStatus = child.realTimeStatus || 'idle';
|
|
52
|
+
const childProvider = getChildProvider(parent, child);
|
|
53
|
+
|
|
54
|
+
return (
|
|
55
|
+
childStatus === 'retry' ||
|
|
56
|
+
(childProvider === 'claude-code'
|
|
57
|
+
? !!child.waitingForUser
|
|
58
|
+
: childStatus === 'busy' && !!child.waitingForUser)
|
|
59
|
+
);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
function isFreshWaitingChildBlocker(parent: EnrichedSession, child: EnrichedChild | undefined, now: number): boolean {
|
|
63
|
+
if (!child) return false;
|
|
64
|
+
|
|
65
|
+
if (!shouldMarkChildWaitingForUser(parent, child)) {
|
|
66
|
+
return false;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
const childUpdated = getChildActivityTimestamp(child);
|
|
70
|
+
return childUpdated !== undefined && (now - childUpdated) < CHILD_BLOCKER_STALENESS_MS;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
function deriveChildDebugReason(
|
|
74
|
+
parent: EnrichedSession,
|
|
75
|
+
child: EnrichedChild | undefined,
|
|
76
|
+
now: number
|
|
77
|
+
): SessionDebugReason | undefined {
|
|
19
78
|
if (!child) return undefined;
|
|
20
79
|
if (child.debugReason) return child.debugReason;
|
|
21
80
|
|
|
22
81
|
const childStatus = child.realTimeStatus || 'idle';
|
|
23
|
-
if (child
|
|
82
|
+
if (shouldMarkChildWaitingForUser(parent, child)) {
|
|
24
83
|
return 'waiting_for_user';
|
|
25
84
|
}
|
|
26
85
|
|
|
27
86
|
if (childStatus === 'busy') {
|
|
28
|
-
const childUpdatedAt = child
|
|
87
|
+
const childUpdatedAt = getChildActivityTimestamp(child);
|
|
29
88
|
return isRecentlyUpdated(childUpdatedAt, now) ? 'child_recent_activity' : 'child_unknown_fallback';
|
|
30
89
|
}
|
|
31
90
|
|
|
@@ -53,8 +112,8 @@ function deriveSessionDebugReason({
|
|
|
53
112
|
|
|
54
113
|
if (waitingForUser) {
|
|
55
114
|
return (
|
|
56
|
-
deriveChildDebugReason(firstWaitingChild, now) ||
|
|
57
|
-
deriveChildDebugReason(firstActiveChild, now) ||
|
|
115
|
+
deriveChildDebugReason(session, firstWaitingChild, now) ||
|
|
116
|
+
deriveChildDebugReason(session, firstActiveChild, now) ||
|
|
58
117
|
'waiting_for_user'
|
|
59
118
|
);
|
|
60
119
|
}
|
|
@@ -79,43 +138,35 @@ function deriveSessionDebugReason({
|
|
|
79
138
|
export function transformSession(session: EnrichedSession): KanbanCard {
|
|
80
139
|
let status: KanbanColumn;
|
|
81
140
|
const children = session.children || [];
|
|
141
|
+
const rollupChildren = children.filter((child) => isVerifiedClaudeChild(session, child));
|
|
82
142
|
const sessionSlug = typeof session.slug === 'string' ? session.slug : '';
|
|
83
143
|
|
|
84
|
-
// Staleness window: child blockers older than this don't keep parent in review
|
|
85
|
-
const CHILD_BLOCKER_STALENESS_MS = 10 * 60 * 1000; // 10 minutes
|
|
86
144
|
const now = Date.now();
|
|
87
145
|
|
|
88
146
|
const realTimeStatus = session.realTimeStatus || 'idle';
|
|
89
|
-
const
|
|
147
|
+
const hasBusyChildren = rollupChildren.some((child) => {
|
|
90
148
|
const childStatus = child.realTimeStatus || 'idle';
|
|
91
149
|
return childStatus === 'busy' || childStatus === 'retry';
|
|
92
150
|
});
|
|
151
|
+
const hasWaitingChildren = rollupChildren.some((child) => isFreshWaitingChildBlocker(session, child, now));
|
|
152
|
+
const hasActiveChildren = hasBusyChildren || hasWaitingChildren;
|
|
93
153
|
const effectiveStatus =
|
|
94
154
|
realTimeStatus === 'retry'
|
|
95
155
|
? 'retry'
|
|
96
156
|
: (realTimeStatus === 'busy' || hasActiveChildren)
|
|
97
157
|
? 'busy'
|
|
98
158
|
: 'idle';
|
|
99
|
-
const hasWaitingChildren = children.some((child) => {
|
|
100
|
-
const childStatus = child.realTimeStatus || 'idle';
|
|
101
|
-
const isBlocker = childStatus === 'retry' || (childStatus !== 'idle' && !!child.waitingForUser);
|
|
102
|
-
if (!isBlocker) return false;
|
|
103
|
-
// Only consider fresh blockers (within staleness window)
|
|
104
|
-
const childUpdated = child.time?.updated || now;
|
|
105
|
-
return (now - childUpdated) < CHILD_BLOCKER_STALENESS_MS;
|
|
106
|
-
});
|
|
107
159
|
const parentWaiting = !!session.waitingForUser;
|
|
108
160
|
const waitingForUser =
|
|
109
161
|
effectiveStatus === 'retry' ||
|
|
110
162
|
parentWaiting ||
|
|
111
|
-
|
|
112
|
-
const firstActiveChild =
|
|
163
|
+
hasWaitingChildren;
|
|
164
|
+
const firstActiveChild = rollupChildren.find((child) => {
|
|
113
165
|
const childStatus = child.realTimeStatus || 'idle';
|
|
114
166
|
return childStatus === 'busy' || childStatus === 'retry';
|
|
115
167
|
});
|
|
116
|
-
const firstWaitingChild =
|
|
117
|
-
|
|
118
|
-
return childStatus === 'retry' || (childStatus !== 'idle' && !!child.waitingForUser);
|
|
168
|
+
const firstWaitingChild = rollupChildren.find((child) => {
|
|
169
|
+
return isFreshWaitingChildBlocker(session, child, now);
|
|
119
170
|
});
|
|
120
171
|
const debugReason = deriveSessionDebugReason({
|
|
121
172
|
session,
|
|
@@ -136,8 +187,10 @@ export function transformSession(session: EnrichedSession): KanbanCard {
|
|
|
136
187
|
status = 'idle';
|
|
137
188
|
}
|
|
138
189
|
|
|
139
|
-
|
|
140
|
-
|
|
190
|
+
const providerDefaults = getDefaultProviderContext(session.provider ?? DEFAULT_PROVIDER_CONTEXT.provider);
|
|
191
|
+
|
|
192
|
+
return {
|
|
193
|
+
id: session.id,
|
|
141
194
|
sessionSlug,
|
|
142
195
|
title: session.title || 'Untitled Session',
|
|
143
196
|
directory: session.directory,
|
|
@@ -161,19 +214,25 @@ export function transformSession(session: EnrichedSession): KanbanCard {
|
|
|
161
214
|
hostBaseUrl: session.hostBaseUrl,
|
|
162
215
|
rawSessionId: session.rawSessionId,
|
|
163
216
|
sourceSessionKey: session.sourceSessionKey,
|
|
164
|
-
readOnly: session.readOnly,
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
217
|
+
readOnly: session.readOnly ?? providerDefaults.readOnly,
|
|
218
|
+
capabilities: session.capabilities ?? providerDefaults.capabilities,
|
|
219
|
+
provider: session.provider ?? providerDefaults.provider,
|
|
220
|
+
providerRawId: session.providerRawId ?? session.rawSessionId,
|
|
221
|
+
children: rollupChildren.map((c) => {
|
|
222
|
+
const childStatus = c.realTimeStatus || 'idle';
|
|
223
|
+
const childWaitingForUser = shouldMarkChildWaitingForUser(session, c);
|
|
224
|
+
|
|
225
|
+
return {
|
|
226
|
+
id: c.id,
|
|
227
|
+
title: c.title,
|
|
228
|
+
realTimeStatus: childStatus,
|
|
229
|
+
waitingForUser: childWaitingForUser,
|
|
230
|
+
debugReason: deriveChildDebugReason(session, c, now),
|
|
231
|
+
createdAt: c.time?.created || 0,
|
|
232
|
+
updatedAt: c.time?.updated || 0,
|
|
233
|
+
};
|
|
234
|
+
}),
|
|
235
|
+
};
|
|
177
236
|
}
|
|
178
237
|
|
|
179
238
|
function extractAgents(slug?: string): string[] {
|
|
@@ -9,8 +9,17 @@ export type SessionDebugReason =
|
|
|
9
9
|
| 'unknown_fallback'
|
|
10
10
|
| 'waiting_for_user';
|
|
11
11
|
|
|
12
|
+
export type SessionProvider = 'opencode' | 'claude-code';
|
|
13
|
+
|
|
14
|
+
export interface SessionCapabilities {
|
|
15
|
+
openProject: boolean;
|
|
16
|
+
openEditor: boolean;
|
|
17
|
+
archive: boolean;
|
|
18
|
+
delete: boolean;
|
|
19
|
+
}
|
|
20
|
+
|
|
12
21
|
export interface KanbanCard {
|
|
13
|
-
id: string;
|
|
22
|
+
id: string;
|
|
14
23
|
sessionSlug: string;
|
|
15
24
|
title: string;
|
|
16
25
|
directory: string;
|
|
@@ -28,14 +37,16 @@ export interface KanbanCard {
|
|
|
28
37
|
updatedAt: number;
|
|
29
38
|
archivedAt?: number;
|
|
30
39
|
sortOrder: number;
|
|
31
|
-
// Host-aware fields (direct, not nested)
|
|
32
40
|
hostId?: string;
|
|
33
41
|
hostLabel?: string;
|
|
34
42
|
hostKind?: HostSourceKind;
|
|
35
43
|
hostBaseUrl?: string;
|
|
36
|
-
rawSessionId?: string;
|
|
37
|
-
sourceSessionKey?: string;
|
|
44
|
+
rawSessionId?: string;
|
|
45
|
+
sourceSessionKey?: string;
|
|
38
46
|
readOnly?: boolean;
|
|
47
|
+
capabilities?: SessionCapabilities;
|
|
48
|
+
provider?: SessionProvider;
|
|
49
|
+
providerRawId?: string;
|
|
39
50
|
children?: {
|
|
40
51
|
id: string;
|
|
41
52
|
title?: string;
|
|
@@ -47,15 +58,14 @@ export interface KanbanCard {
|
|
|
47
58
|
}[];
|
|
48
59
|
}
|
|
49
60
|
|
|
50
|
-
// OpenCode event types
|
|
51
61
|
export interface OpencodeSession {
|
|
52
|
-
id: string;
|
|
62
|
+
id: string;
|
|
53
63
|
slug: string;
|
|
54
64
|
title?: string;
|
|
55
65
|
directory: string;
|
|
56
66
|
projectName?: string;
|
|
57
67
|
branch?: string;
|
|
58
|
-
parentID?: string;
|
|
68
|
+
parentID?: string;
|
|
59
69
|
time: {
|
|
60
70
|
created: number;
|
|
61
71
|
updated: number;
|
|
@@ -64,18 +74,20 @@ export interface OpencodeSession {
|
|
|
64
74
|
messageCount?: number;
|
|
65
75
|
hasTodos?: boolean;
|
|
66
76
|
hasTranscript?: boolean;
|
|
67
|
-
realTimeStatus?: 'idle' | 'busy' | 'retry';
|
|
77
|
+
realTimeStatus?: 'idle' | 'busy' | 'retry';
|
|
68
78
|
waitingForUser?: boolean;
|
|
69
79
|
debugReason?: SessionDebugReason;
|
|
70
80
|
children?: OpencodeSession[];
|
|
71
|
-
// Host-aware fields (direct, not nested)
|
|
72
81
|
hostId?: string;
|
|
73
82
|
hostLabel?: string;
|
|
74
83
|
hostKind?: HostSourceKind;
|
|
75
84
|
hostBaseUrl?: string;
|
|
76
|
-
rawSessionId?: string;
|
|
77
|
-
sourceSessionKey?: string;
|
|
85
|
+
rawSessionId?: string;
|
|
86
|
+
sourceSessionKey?: string;
|
|
78
87
|
readOnly?: boolean;
|
|
88
|
+
capabilities?: SessionCapabilities;
|
|
89
|
+
provider?: SessionProvider;
|
|
90
|
+
providerRawId?: string;
|
|
79
91
|
}
|
|
80
92
|
|
|
81
93
|
export type OpencodeEventType =
|
|
@@ -105,10 +117,8 @@ export interface OpencodeEvent {
|
|
|
105
117
|
timestamp: number;
|
|
106
118
|
}
|
|
107
119
|
|
|
108
|
-
// Status mapping
|
|
109
120
|
export type OpencodeStatus = 'idle' | 'busy' | 'retry';
|
|
110
121
|
|
|
111
|
-
// Host source types
|
|
112
122
|
export type HostSourceKind = 'local' | 'remote';
|
|
113
123
|
|
|
114
124
|
export interface BuiltInHostSource {
|
|
@@ -139,10 +149,6 @@ export interface HostStatus {
|
|
|
139
149
|
baseUrl?: string;
|
|
140
150
|
}
|
|
141
151
|
|
|
142
|
-
// Host-aware fields that appear directly on sessions/cards
|
|
143
|
-
// (not nested in a wrapper object)
|
|
144
|
-
|
|
145
|
-
// Type guards
|
|
146
152
|
export function isKanbanColumn(value: string): value is KanbanColumn {
|
|
147
153
|
return ['idle', 'busy', 'review', 'done'].includes(value);
|
|
148
154
|
}
|