@synap-core/cli 1.10.0 → 1.12.2
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/README.md +23 -198
- package/dist/build-info.json +6 -0
- package/dist/commands/agent-run.js +3 -2
- package/dist/commands/agent-run.js.map +1 -1
- package/dist/commands/agents.d.ts +33 -17
- package/dist/commands/agents.js +203 -237
- package/dist/commands/agents.js.map +1 -1
- package/dist/commands/app.d.ts +143 -0
- package/dist/commands/app.js +523 -0
- package/dist/commands/app.js.map +1 -0
- package/dist/commands/automate.d.ts +21 -0
- package/dist/commands/automate.js +42 -0
- package/dist/commands/automate.js.map +1 -0
- package/dist/commands/automation-schema.test.d.ts +16 -0
- package/dist/commands/automation-schema.test.js +77 -0
- package/dist/commands/automation-schema.test.js.map +1 -0
- package/dist/commands/automation.d.ts +12 -0
- package/dist/commands/automation.js +80 -35
- package/dist/commands/automation.js.map +1 -1
- package/dist/commands/bridge-setup.d.ts +14 -1
- package/dist/commands/bridge-setup.js +392 -128
- package/dist/commands/bridge-setup.js.map +1 -1
- package/dist/commands/cap-connections.d.ts +4 -4
- package/dist/commands/cap-connections.js +14 -14
- package/dist/commands/cap-connections.js.map +1 -1
- package/dist/commands/capability.d.ts +2 -0
- package/dist/commands/capability.js +297 -176
- package/dist/commands/capability.js.map +1 -1
- package/dist/commands/catalog.d.ts +275 -0
- package/dist/commands/catalog.js +481 -0
- package/dist/commands/catalog.js.map +1 -0
- package/dist/commands/cell.d.ts +155 -8
- package/dist/commands/cell.js +416 -40
- package/dist/commands/cell.js.map +1 -1
- package/dist/commands/centrality.js +3 -14
- package/dist/commands/centrality.js.map +1 -1
- package/dist/commands/connect.d.ts +38 -13
- package/dist/commands/connect.js +68 -167
- package/dist/commands/connect.js.map +1 -1
- package/dist/commands/connections.d.ts +3 -2
- package/dist/commands/connections.js +95 -25
- package/dist/commands/connections.js.map +1 -1
- package/dist/commands/context.js +9 -2
- package/dist/commands/context.js.map +1 -1
- package/dist/commands/data-extra.d.ts +34 -0
- package/dist/commands/data-extra.js +198 -25
- package/dist/commands/data-extra.js.map +1 -1
- package/dist/commands/data.d.ts +120 -2
- package/dist/commands/data.js +307 -24
- package/dist/commands/data.js.map +1 -1
- package/dist/commands/diagnose.d.ts +66 -4
- package/dist/commands/diagnose.js +329 -29
- package/dist/commands/diagnose.js.map +1 -1
- package/dist/commands/digest.js +2 -1
- package/dist/commands/digest.js.map +1 -1
- package/dist/commands/doc.d.ts +25 -4
- package/dist/commands/doc.js +100 -18
- package/dist/commands/doc.js.map +1 -1
- package/dist/commands/doctor.d.ts +130 -0
- package/dist/commands/doctor.js +814 -0
- package/dist/commands/doctor.js.map +1 -0
- package/dist/commands/events.js +3 -1
- package/dist/commands/events.js.map +1 -1
- package/dist/commands/explain.js +5 -5
- package/dist/commands/explain.js.map +1 -1
- package/dist/commands/graph.js +5 -3
- package/dist/commands/graph.js.map +1 -1
- package/dist/commands/import.d.ts +368 -13
- package/dist/commands/import.js +1096 -55
- package/dist/commands/import.js.map +1 -1
- package/dist/commands/init.d.ts +20 -9
- package/dist/commands/init.js +433 -973
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/keys.d.ts +1 -0
- package/dist/commands/keys.js +15 -2
- package/dist/commands/keys.js.map +1 -1
- package/dist/commands/knowledge.d.ts +28 -6
- package/dist/commands/knowledge.js +358 -73
- package/dist/commands/knowledge.js.map +1 -1
- package/dist/commands/launch.js +2 -2
- package/dist/commands/launch.js.map +1 -1
- package/dist/commands/lens.d.ts +37 -1
- package/dist/commands/lens.js +193 -72
- package/dist/commands/lens.js.map +1 -1
- package/dist/commands/market-authoring.d.ts +72 -0
- package/dist/commands/market-authoring.js +566 -0
- package/dist/commands/market-authoring.js.map +1 -0
- package/dist/commands/market-official.d.ts +58 -0
- package/dist/commands/market-official.js +84 -0
- package/dist/commands/market-official.js.map +1 -0
- package/dist/commands/market.d.ts +419 -20
- package/dist/commands/market.js +2124 -193
- package/dist/commands/market.js.map +1 -1
- package/dist/commands/mcp.d.ts +70 -13
- package/dist/commands/mcp.js +308 -40
- package/dist/commands/mcp.js.map +1 -1
- package/dist/commands/open.d.ts +39 -9
- package/dist/commands/open.js +80 -25
- package/dist/commands/open.js.map +1 -1
- package/dist/commands/playbook.d.ts +42 -0
- package/dist/commands/playbook.js +162 -0
- package/dist/commands/playbook.js.map +1 -0
- package/dist/commands/pod.js +1 -1
- package/dist/commands/pod.js.map +1 -1
- package/dist/commands/pods.d.ts +19 -0
- package/dist/commands/pods.js +220 -85
- package/dist/commands/pods.js.map +1 -1
- package/dist/commands/proposals-actions.d.ts +62 -0
- package/dist/commands/proposals-actions.js +146 -8
- package/dist/commands/proposals-actions.js.map +1 -1
- package/dist/commands/proposals-await.d.ts +68 -0
- package/dist/commands/proposals-await.js +248 -0
- package/dist/commands/proposals-await.js.map +1 -0
- package/dist/commands/proton-setup.d.ts +73 -0
- package/dist/commands/proton-setup.js +577 -0
- package/dist/commands/proton-setup.js.map +1 -0
- package/dist/commands/providers.d.ts +23 -0
- package/dist/commands/providers.js +126 -1
- package/dist/commands/providers.js.map +1 -1
- package/dist/commands/raycast.js +6 -2
- package/dist/commands/raycast.js.map +1 -1
- package/dist/commands/rule.d.ts +150 -0
- package/dist/commands/rule.js +447 -0
- package/dist/commands/rule.js.map +1 -0
- package/dist/commands/session-wait.d.ts +111 -0
- package/dist/commands/session-wait.js +209 -0
- package/dist/commands/session-wait.js.map +1 -0
- package/dist/commands/sessions.d.ts +52 -0
- package/dist/commands/sessions.js +479 -58
- package/dist/commands/sessions.js.map +1 -1
- package/dist/commands/skill-manage.d.ts +21 -0
- package/dist/commands/skill-manage.js +136 -19
- package/dist/commands/skill-manage.js.map +1 -1
- package/dist/commands/skills.js +19 -1
- package/dist/commands/skills.js.map +1 -1
- package/dist/commands/status.d.ts +1 -4
- package/dist/commands/status.js +5 -34
- package/dist/commands/status.js.map +1 -1
- package/dist/commands/statusline.backoff.test.d.ts +13 -0
- package/dist/commands/statusline.backoff.test.js +100 -0
- package/dist/commands/statusline.backoff.test.js.map +1 -0
- package/dist/commands/statusline.js +16 -9
- package/dist/commands/statusline.js.map +1 -1
- package/dist/commands/sync-status.d.ts +12 -0
- package/dist/commands/sync-status.js +125 -0
- package/dist/commands/sync-status.js.map +1 -0
- package/dist/commands/templates-retire.d.ts +34 -0
- package/dist/commands/templates-retire.js +192 -0
- package/dist/commands/templates-retire.js.map +1 -0
- package/dist/commands/tools.js +6 -21
- package/dist/commands/tools.js.map +1 -1
- package/dist/commands/tracks.d.ts +51 -0
- package/dist/commands/tracks.js +291 -0
- package/dist/commands/tracks.js.map +1 -0
- package/dist/commands/update.d.ts +3 -11
- package/dist/commands/update.js +5 -134
- package/dist/commands/update.js.map +1 -1
- package/dist/commands/upload.d.ts +68 -0
- package/dist/commands/upload.js +257 -0
- package/dist/commands/upload.js.map +1 -0
- package/dist/commands/vendor.d.ts +28 -0
- package/dist/commands/vendor.js +110 -0
- package/dist/commands/vendor.js.map +1 -0
- package/dist/commands/versions.js +6 -0
- package/dist/commands/versions.js.map +1 -1
- package/dist/commands/view.js +10 -5
- package/dist/commands/view.js.map +1 -1
- package/dist/commands/whoami.d.ts +23 -3
- package/dist/commands/whoami.js +169 -23
- package/dist/commands/whoami.js.map +1 -1
- package/dist/commands/worker.d.ts +122 -0
- package/dist/commands/worker.js +435 -0
- package/dist/commands/worker.js.map +1 -0
- package/dist/commands/worker.test.d.ts +1 -0
- package/dist/commands/worker.test.js +116 -0
- package/dist/commands/worker.test.js.map +1 -0
- package/dist/commands/workspace-ops.d.ts +35 -0
- package/dist/commands/workspace-ops.js +153 -0
- package/dist/commands/workspace-ops.js.map +1 -0
- package/dist/index.d.ts +6 -6
- package/dist/index.js +1009 -171
- package/dist/index.js.map +1 -1
- package/dist/lib/agent-connections.d.ts +31 -0
- package/dist/lib/agent-connections.js +33 -0
- package/dist/lib/agent-connections.js.map +1 -0
- package/dist/lib/agent-detect.d.ts +27 -0
- package/dist/lib/agent-detect.js +71 -0
- package/dist/lib/agent-detect.js.map +1 -0
- package/dist/lib/agent-door.d.ts +138 -0
- package/dist/lib/agent-door.js +426 -0
- package/dist/lib/agent-door.js.map +1 -0
- package/dist/lib/agents-config.d.ts +2 -0
- package/dist/lib/agents-config.js +4 -9
- package/dist/lib/agents-config.js.map +1 -1
- package/dist/lib/approval-poll.d.ts +31 -2
- package/dist/lib/approval-poll.js +20 -7
- package/dist/lib/approval-poll.js.map +1 -1
- package/dist/lib/atomic-file.d.ts +48 -0
- package/dist/lib/atomic-file.js +129 -0
- package/dist/lib/atomic-file.js.map +1 -0
- package/dist/lib/auth.d.ts +14 -9
- package/dist/lib/auth.js +44 -61
- package/dist/lib/auth.js.map +1 -1
- package/dist/lib/batch-approval.d.ts +85 -0
- package/dist/lib/batch-approval.js +170 -0
- package/dist/lib/batch-approval.js.map +1 -0
- package/dist/lib/capture-lane.d.ts +6 -5
- package/dist/lib/capture-lane.js +11 -8
- package/dist/lib/capture-lane.js.map +1 -1
- package/dist/lib/capture-structure.d.ts +342 -0
- package/dist/lib/capture-structure.js +295 -0
- package/dist/lib/capture-structure.js.map +1 -0
- package/dist/lib/catalog-templates.d.ts +59 -0
- package/dist/lib/catalog-templates.js +126 -0
- package/dist/lib/catalog-templates.js.map +1 -0
- package/dist/lib/cli-build.d.ts +19 -0
- package/dist/lib/cli-build.js +37 -0
- package/dist/lib/cli-build.js.map +1 -0
- package/dist/lib/conversation-headers.d.ts +18 -0
- package/dist/lib/conversation-headers.js +32 -0
- package/dist/lib/conversation-headers.js.map +1 -0
- package/dist/lib/cp-packages.d.ts +216 -4
- package/dist/lib/cp-packages.js +414 -11
- package/dist/lib/cp-packages.js.map +1 -1
- package/dist/lib/credential-class.d.ts +117 -0
- package/dist/lib/credential-class.js +116 -0
- package/dist/lib/credential-class.js.map +1 -0
- package/dist/lib/describe-lens.d.ts +35 -0
- package/dist/lib/describe-lens.js +40 -0
- package/dist/lib/describe-lens.js.map +1 -1
- package/dist/lib/device-connect.d.ts +125 -0
- package/dist/lib/device-connect.js +256 -0
- package/dist/lib/device-connect.js.map +1 -0
- package/dist/lib/directory-lens.d.ts +99 -0
- package/dist/lib/directory-lens.js +187 -0
- package/dist/lib/directory-lens.js.map +1 -0
- package/dist/lib/exporter-coverage.d.ts +71 -0
- package/dist/lib/exporter-coverage.js +97 -0
- package/dist/lib/exporter-coverage.js.map +1 -0
- package/dist/lib/hub-client.d.ts +43 -9
- package/dist/lib/hub-client.js +429 -65
- package/dist/lib/hub-client.js.map +1 -1
- package/dist/lib/id.d.ts +23 -0
- package/dist/lib/id.js +35 -0
- package/dist/lib/id.js.map +1 -0
- package/dist/lib/init-connect.d.ts +41 -0
- package/dist/lib/init-connect.js +75 -0
- package/dist/lib/init-connect.js.map +1 -0
- package/dist/lib/init-exit.d.ts +24 -0
- package/dist/lib/init-exit.js +41 -0
- package/dist/lib/init-exit.js.map +1 -0
- package/dist/lib/init-flow.d.ts +25 -0
- package/dist/lib/init-flow.js +40 -0
- package/dist/lib/init-flow.js.map +1 -0
- package/dist/lib/init-handoff.d.ts +16 -0
- package/dist/lib/init-handoff.js +19 -0
- package/dist/lib/init-handoff.js.map +1 -0
- package/dist/lib/init-output.d.ts +18 -0
- package/dist/lib/init-output.js +43 -0
- package/dist/lib/init-output.js.map +1 -0
- package/dist/lib/init-pod.d.ts +45 -0
- package/dist/lib/init-pod.js +36 -0
- package/dist/lib/init-pod.js.map +1 -0
- package/dist/lib/installed.d.ts +210 -11
- package/dist/lib/installed.js +234 -36
- package/dist/lib/installed.js.map +1 -1
- package/dist/lib/key-approval.d.ts +57 -0
- package/dist/lib/key-approval.js +117 -0
- package/dist/lib/key-approval.js.map +1 -0
- package/dist/lib/key-diagnosis.d.ts +56 -0
- package/dist/lib/key-diagnosis.js +227 -0
- package/dist/lib/key-diagnosis.js.map +1 -0
- package/dist/lib/key-doctor.d.ts +136 -0
- package/dist/lib/key-doctor.js +286 -0
- package/dist/lib/key-doctor.js.map +1 -0
- package/dist/lib/key-locations.d.ts +120 -0
- package/dist/lib/key-locations.js +326 -0
- package/dist/lib/key-locations.js.map +1 -0
- package/dist/lib/key-source.d.ts +66 -0
- package/dist/lib/key-source.js +106 -0
- package/dist/lib/key-source.js.map +1 -0
- package/dist/lib/key-state.d.ts +70 -0
- package/dist/lib/key-state.js +115 -0
- package/dist/lib/key-state.js.map +1 -0
- package/dist/lib/kind-package.d.ts +181 -0
- package/dist/lib/kind-package.js +679 -0
- package/dist/lib/kind-package.js.map +1 -0
- package/dist/lib/knowledge-title.d.ts +24 -0
- package/dist/lib/knowledge-title.js +46 -0
- package/dist/lib/knowledge-title.js.map +1 -0
- package/dist/lib/knowledge-title.test.d.ts +1 -0
- package/dist/lib/knowledge-title.test.js +34 -0
- package/dist/lib/knowledge-title.test.js.map +1 -0
- package/dist/lib/machine-instance.d.ts +64 -0
- package/dist/lib/machine-instance.js +142 -0
- package/dist/lib/machine-instance.js.map +1 -0
- package/dist/lib/mcp-bridge.d.ts +42 -0
- package/dist/lib/mcp-bridge.js +147 -0
- package/dist/lib/mcp-bridge.js.map +1 -0
- package/dist/lib/mcp-bridge.test.d.ts +1 -0
- package/dist/lib/mcp-bridge.test.js +90 -0
- package/dist/lib/mcp-bridge.test.js.map +1 -0
- package/dist/lib/mcp-call.d.ts +30 -0
- package/dist/lib/mcp-call.js +107 -0
- package/dist/lib/mcp-call.js.map +1 -0
- package/dist/lib/mcp-snippets.d.ts +53 -0
- package/dist/lib/mcp-snippets.js +82 -0
- package/dist/lib/mcp-snippets.js.map +1 -0
- package/dist/lib/next-steps.d.ts +8 -0
- package/dist/lib/next-steps.js +31 -1
- package/dist/lib/next-steps.js.map +1 -1
- package/dist/lib/package-wire.d.ts +179 -0
- package/dist/lib/package-wire.js +68 -0
- package/dist/lib/package-wire.js.map +1 -0
- package/dist/lib/pair-link.d.ts +38 -0
- package/dist/lib/pair-link.js +68 -0
- package/dist/lib/pair-link.js.map +1 -0
- package/dist/lib/pod-wide.d.ts +40 -0
- package/dist/lib/pod-wide.js +46 -0
- package/dist/lib/pod-wide.js.map +1 -0
- package/dist/lib/pod.d.ts +119 -115
- package/dist/lib/pod.js +206 -412
- package/dist/lib/pod.js.map +1 -1
- package/dist/lib/project-ref.d.ts +9 -3
- package/dist/lib/project-ref.js +10 -4
- package/dist/lib/project-ref.js.map +1 -1
- package/dist/lib/review-credential.d.ts +119 -0
- package/dist/lib/review-credential.js +147 -0
- package/dist/lib/review-credential.js.map +1 -0
- package/dist/lib/safe-open.d.ts +49 -0
- package/dist/lib/safe-open.js +119 -0
- package/dist/lib/safe-open.js.map +1 -0
- package/dist/lib/session-lens.d.ts +40 -1
- package/dist/lib/session-lens.js +54 -4
- package/dist/lib/session-lens.js.map +1 -1
- package/dist/lib/superwhisper-import.d.ts +8 -0
- package/dist/lib/superwhisper-import.js +14 -7
- package/dist/lib/superwhisper-import.js.map +1 -1
- package/dist/lib/superwhisper-title.test.d.ts +1 -0
- package/dist/lib/superwhisper-title.test.js +18 -0
- package/dist/lib/superwhisper-title.test.js.map +1 -0
- package/dist/lib/targets.d.ts +134 -10
- package/dist/lib/targets.js +962 -258
- package/dist/lib/targets.js.map +1 -1
- package/dist/lib/template-file.d.ts +78 -0
- package/dist/lib/template-file.js +140 -0
- package/dist/lib/template-file.js.map +1 -0
- package/dist/lib/template-lifecycle.d.ts +217 -0
- package/dist/lib/template-lifecycle.js +433 -0
- package/dist/lib/template-lifecycle.js.map +1 -0
- package/dist/lib/template-steps.d.ts +88 -0
- package/dist/lib/template-steps.js +118 -0
- package/dist/lib/template-steps.js.map +1 -0
- package/dist/lib/time-ago.d.ts +2 -0
- package/dist/lib/time-ago.js +15 -0
- package/dist/lib/time-ago.js.map +1 -0
- package/dist/utils/logger.js +5 -2
- package/dist/utils/logger.js.map +1 -1
- package/package.json +25 -18
- package/skills/README.md +12 -10
- package/skills/agent-os/SKILL.md +220 -99
- package/skills/manifest.json +2 -2
- package/skills/onboard/SKILL.md +61 -25
- package/skills/synap/README.md +5 -8
- package/skills/synap/SKILL.md +1185 -301
- package/skills/synap/_order.txt +7 -0
- package/skills/synap/_skill.yaml +1 -1
- package/skills/synap/automations.md +15 -0
- package/skills/synap/capture.md +54 -151
- package/skills/synap/cli-operations.md +24 -18
- package/skills/synap/common-mistakes.md +1 -0
- package/skills/synap/concepts.md +28 -0
- package/skills/synap/content-os.md +92 -0
- package/skills/synap/creative-loop.md +15 -10
- package/skills/synap/crm.md +21 -52
- package/skills/synap/digesting-a-channel.md +25 -0
- package/skills/synap/document-embeds.md +141 -47
- package/skills/synap/escalation-ladder.md +20 -10
- package/skills/synap/focus-sessions.md +47 -21
- package/skills/synap/from-intent.md +142 -0
- package/skills/synap/governance-rules.md +4 -4
- package/skills/synap/governance.md +10 -7
- package/skills/synap/hand-off.md +33 -0
- package/skills/synap/inline-patterns.md +15 -7
- package/skills/synap/lenses.md +33 -15
- package/skills/synap/linking.md +41 -40
- package/skills/synap/mcp-remote-servers.md +64 -0
- package/skills/synap/mental-model.md +24 -22
- package/skills/synap/multi-entity-capture.md +6 -4
- package/skills/synap/operating-mode-rules.md +1 -1
- package/skills/synap/processes.md +118 -0
- package/skills/synap/quick-reference.md +5 -1
- package/skills/synap/reading.md +3 -1
- package/skills/synap/reflexes.md +12 -42
- package/skills/synap/viewframe-cells.md +38 -5
- package/skills/synap/work-flow.md +1 -1
- package/skills/synap/work-model.md +96 -0
- package/skills/synap/worked-examples.md +21 -1
- package/skills/synap/workspace-design.md +14 -10
- package/skills/synap/writes.md +165 -35
- package/skills/synap/writing-titles.md +63 -0
- package/skills/synap-app/SKILL.md +319 -0
- package/skills/synap-app/_order.txt +5 -0
- package/skills/synap-app/_skill.yaml +20 -0
- package/skills/synap-app/creating-the-base-app.md +64 -0
- package/skills/synap-app/governance.md +42 -0
- package/skills/synap-app/install-commands.md +55 -0
- package/skills/synap-app/overview.md +50 -0
- package/skills/synap-app/using-the-sdk.md +73 -0
- package/skills/synap-design/SKILL.md +474 -0
- package/skills/synap-design/_order.txt +4 -0
- package/skills/synap-design/_skill.yaml +21 -0
- package/skills/synap-design/loop.md +134 -0
- package/skills/synap-design/overview.md +44 -0
- package/skills/synap-design/principles.md +130 -0
- package/skills/synap-design/system.md +133 -0
- package/skills/synap-market/SKILL.md +625 -0
- package/skills/synap-market/_order.txt +5 -0
- package/skills/synap-market/_skill.yaml +24 -0
- package/skills/synap-market/author-and-publish.md +212 -0
- package/skills/synap-market/discover-and-fetch.md +59 -0
- package/skills/synap-market/governance-and-catalog.md +63 -0
- package/skills/synap-market/install.md +133 -0
- package/skills/synap-market/overview.md +119 -0
- package/skills/synap-schema/SKILL.md +172 -10
- package/skills/synap-schema/_order.txt +2 -0
- package/skills/synap-schema/_skill.yaml +4 -2
- package/skills/synap-schema/common-mistakes.md +4 -2
- package/skills/synap-schema/discover-profiles.md +1 -1
- package/skills/synap-schema/entity-scope.md +15 -3
- package/skills/synap-schema/extend-first.md +29 -0
- package/skills/synap-schema/extend-vs-create.md +1 -1
- package/skills/synap-schema/intent-vocabulary-ssot.md +111 -0
- package/skills/synap-schema/property-types.md +1 -1
- package/skills/synap-schema/relations.md +1 -1
- package/skills/synap-ui/SKILL.md +19 -12
- package/skills/synap-ui/_skill.yaml +1 -1
- package/skills/synap-ui/ai-companion.md +1 -1
- package/skills/synap-ui/arranging-bento.md +2 -0
- package/skills/synap-ui/bento-layouts.md +10 -10
- package/skills/synap-ui/bento-recipes.md +313 -543
- package/skills/synap-ui/four-builds.md +5 -0
- package/skills/synap-ui/view-types.md +2 -2
- package/skills/synap-ui/widget-catalog.md +22 -278
- package/templates/automations/bookmark-enrichment.automation.json +290 -13
- package/templates/automations/url-bookmark-capture.automation.json +73 -11
- package/templates/skills/authoring-playbooks/SKILL.md +6 -3
- package/templates/skills/authoring-playbooks/reference/stages-contract.md +15 -0
- package/templates/skills/authoring-playbooks/reference/worked-example.md +3 -0
- package/dist/commands/infra.d.ts +0 -21
- package/dist/commands/infra.js +0 -262
- package/dist/commands/infra.js.map +0 -1
- package/dist/lib/browser-auth.d.ts +0 -35
- package/dist/lib/browser-auth.js +0 -170
- package/dist/lib/browser-auth.js.map +0 -1
- package/dist/lib/openclaw.d.ts +0 -32
- package/dist/lib/openclaw.js +0 -164
- package/dist/lib/openclaw.js.map +0 -1
- package/dist/lib/seed.d.ts +0 -13
- package/dist/lib/seed.js +0 -135
- package/dist/lib/seed.js.map +0 -1
|
@@ -1,13 +1,129 @@
|
|
|
1
1
|
import chalk from "chalk";
|
|
2
2
|
import { log } from "../utils/logger.js";
|
|
3
|
-
import { resolveHubConfig, hubGet, hubPatch, hubPost,
|
|
3
|
+
import { resolveHubConfig, hubGet, hubPatch, hubPost, attachActiveSessionId, detachActiveSessionId, resolveActiveSessionId, renderHubError, HubError, } from "../lib/hub-client.js";
|
|
4
|
+
import { readFileSync, existsSync } from "fs";
|
|
5
|
+
import { resolve } from "path";
|
|
6
|
+
/**
|
|
7
|
+
* The three session-population lenses ("kind"), and their human labels.
|
|
8
|
+
*
|
|
9
|
+
* `@synap-core/types/vocabulary` (`resolveStatusLabel`) is the SSOT for this —
|
|
10
|
+
* `work`/`run`/`receipt` are pinned there verbatim (`.claude/rules/
|
|
11
|
+
* vocabulary.md` forbids a local `charAt(0).toUpperCase()` guess). But this
|
|
12
|
+
* package cannot import it: the CLI links only `@synap-core/workspace-
|
|
13
|
+
* templates` (a real npm dep already), and `@synap-core/types` pulls in
|
|
14
|
+
* drizzle-orm/drizzle-zod/yjs as transitive deps for a globally-installed
|
|
15
|
+
* binary — an install-topology change, not a labelling fix. Same shape as
|
|
16
|
+
* `KIND_HEADINGS` in `market.ts`: a local table, pinned by a source-scan
|
|
17
|
+
* parity test (`test/session-kind-vocabulary-parity.test.ts`) against the
|
|
18
|
+
* registry across the repo boundary, so it cannot silently drift.
|
|
19
|
+
*/
|
|
20
|
+
const SESSION_KIND_LABELS = {
|
|
21
|
+
work: "Work",
|
|
22
|
+
run: "Run",
|
|
23
|
+
receipt: "Receipt",
|
|
24
|
+
};
|
|
25
|
+
export function sessionKindLabel(kind) {
|
|
26
|
+
return SESSION_KIND_LABELS[kind] ?? kind;
|
|
27
|
+
}
|
|
28
|
+
const SESSION_KIND_FILTERS = ["work", "run", "receipt", "all"];
|
|
29
|
+
/**
|
|
30
|
+
* The name to show for a session: mirrors `resolveSessionTitle` in
|
|
31
|
+
* `synap-backend/packages/types/src/focus-sessions/title.ts` — the
|
|
32
|
+
* platform's ONE resolver (title when set, else the goal's first line,
|
|
33
|
+
* clipped at a word boundary). This package cannot import that file (see the
|
|
34
|
+
* doc comment on `SESSION_KIND_LABELS` above for why), so only the DISPLAY
|
|
35
|
+
* half of the rule is mirrored: the row's `title` already arrives
|
|
36
|
+
* server-normalized (HTML-entity decoded, one line), so the write-path
|
|
37
|
+
* decode step has nothing to do here. Pinned by
|
|
38
|
+
* `test/session-title-resolver-parity.test.ts`, which runs the registry's
|
|
39
|
+
* OWN fixtures (from `title.test.ts`) through this copy.
|
|
40
|
+
*/
|
|
41
|
+
const SESSION_TITLE_FALLBACK_MAX = 80;
|
|
42
|
+
function oneLine(value) {
|
|
43
|
+
return value.replace(/\s+/g, " ").trim();
|
|
44
|
+
}
|
|
45
|
+
function clipAtWordBoundary(line, max) {
|
|
46
|
+
if (line.length <= max)
|
|
47
|
+
return line;
|
|
48
|
+
let cut = line.slice(0, Math.max(1, max - 1));
|
|
49
|
+
const lastSpace = cut.lastIndexOf(" ");
|
|
50
|
+
// Only back off to a word boundary when it keeps most of the budget; a
|
|
51
|
+
// single very long first word is cut mid-word rather than reduced to
|
|
52
|
+
// nothing.
|
|
53
|
+
if (lastSpace >= Math.floor(max / 2))
|
|
54
|
+
cut = cut.slice(0, lastSpace);
|
|
55
|
+
return `${cut.replace(/[\s,;:.\-–—]+$/, "")}…`;
|
|
56
|
+
}
|
|
57
|
+
export function resolveSessionTitle(session, opts = {}) {
|
|
58
|
+
const title = typeof session.title === "string" ? oneLine(session.title) : "";
|
|
59
|
+
if (title)
|
|
60
|
+
return title;
|
|
61
|
+
const goal = typeof session.goal === "string" ? session.goal : "";
|
|
62
|
+
const firstLine = goal
|
|
63
|
+
.split(/\r?\n/)
|
|
64
|
+
.map(oneLine)
|
|
65
|
+
.find((l) => l.length > 0) ?? "";
|
|
66
|
+
return clipAtWordBoundary(firstLine, opts.maxLength ?? SESSION_TITLE_FALLBACK_MAX);
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Session-evaluation verdicts (`session_evaluations.verdict`). SSOT is
|
|
70
|
+
* `@synap-core/types/vocabulary`'s `STATUS_LABELS` (`pass`/`fail`/
|
|
71
|
+
* `unmeasured`) — same cross-boundary constraint as `SESSION_KIND_LABELS`
|
|
72
|
+
* above, mirrored here and pinned by
|
|
73
|
+
* `test/verdict-label-vocabulary-parity.test.ts`.
|
|
74
|
+
*/
|
|
75
|
+
const VERDICT_LABELS = {
|
|
76
|
+
pass: "Passed",
|
|
77
|
+
fail: "Failed",
|
|
78
|
+
unmeasured: "Not checked",
|
|
79
|
+
};
|
|
80
|
+
function verdictLabel(verdict) {
|
|
81
|
+
return VERDICT_LABELS[verdict] ?? verdict;
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* One-glance verdict summary for a list/detail row: "1 unmet" when a
|
|
85
|
+
* required criterion is failing or unmeasured (the thing worth flagging),
|
|
86
|
+
* else "2/3 ✓". `null` when the session carries no criteria at all — most
|
|
87
|
+
* sessions don't, and a bare session shouldn't grow a verdict column.
|
|
88
|
+
*/
|
|
89
|
+
function verdictSummary(v) {
|
|
90
|
+
const verdict = v;
|
|
91
|
+
if (!verdict || typeof verdict.total !== "number" || verdict.total === 0) {
|
|
92
|
+
return null;
|
|
93
|
+
}
|
|
94
|
+
if (verdict.requiredUnmet && verdict.requiredUnmet > 0) {
|
|
95
|
+
return `${verdict.requiredUnmet} unmet`;
|
|
96
|
+
}
|
|
97
|
+
return `${verdict.passed ?? 0}/${verdict.total} ✓`;
|
|
98
|
+
}
|
|
99
|
+
/** Human phrasing for where an attach landed — so scope is never a mystery. */
|
|
100
|
+
function describeAttachTarget(target) {
|
|
101
|
+
return target === "session-lens"
|
|
102
|
+
? "in this Claude Code session (~/.synap/lenses)"
|
|
103
|
+
: "in this working tree (.synap/lens.json)";
|
|
104
|
+
}
|
|
4
105
|
// ─── startSession ─────────────────────────────────────────────────────────────
|
|
5
106
|
export async function startSession(opts) {
|
|
6
107
|
try {
|
|
7
108
|
const cfg = await resolveHubConfig(opts);
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
109
|
+
// LENS PARITY. `resolveHubConfig` already resolves the active project
|
|
110
|
+
// ("write paths should consume resolveHubConfig().projectId" —
|
|
111
|
+
// lib/hub-client.ts), and `synap lens` / `synap capture` both honour it.
|
|
112
|
+
// This door read `cfg.workspaceId` and dropped `cfg.projectId` on the
|
|
113
|
+
// floor, so the same terminal answered differently depending on which
|
|
114
|
+
// command you used: capture filed into the project, `session start` wrote
|
|
115
|
+
// projectId: null. The value was one field away the whole time.
|
|
116
|
+
// A track names its own project (the pod refuses a different projectId):
|
|
117
|
+
// with `--track`, only an EXPLICIT --workspace / --project is sent, never
|
|
118
|
+
// the ambient lens, which may point at another project.
|
|
119
|
+
const workspaceId = opts.track ? opts.workspace : opts.workspace || cfg.workspaceId;
|
|
120
|
+
const projectId = opts.track ? opts.project : opts.project || cfg.projectId;
|
|
121
|
+
// The POD accepts workspaceId OR projectId ("Provide a workspaceId or a
|
|
122
|
+
// projectId" — rest/focus-sessions.ts). Requiring a workspace here was a
|
|
123
|
+
// CLI-only rule, stricter than the contract, and it made a project-scoped
|
|
124
|
+
// session unreachable from the terminal.
|
|
125
|
+
if (!workspaceId && !projectId && !opts.track) {
|
|
126
|
+
console.error(chalk.red("Error: no workspace or project in scope — pass --workspace <id> or --project <id>, or set one with 'synap use' / 'synap project use'"));
|
|
11
127
|
process.exit(1);
|
|
12
128
|
}
|
|
13
129
|
// Resolve caller userId from the hub key
|
|
@@ -17,33 +133,93 @@ export async function startSession(opts) {
|
|
|
17
133
|
console.error(chalk.red("Error: could not resolve userId from /users/me"));
|
|
18
134
|
process.exit(1);
|
|
19
135
|
}
|
|
20
|
-
const body = {
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
136
|
+
const body = { userId, goal: opts.goal };
|
|
137
|
+
// Send only what is in scope: the pod's refine accepts either, and sending
|
|
138
|
+
// an undefined workspaceId would fail the "min(1)" on the wire.
|
|
139
|
+
if (workspaceId)
|
|
140
|
+
body.workspaceId = workspaceId;
|
|
141
|
+
if (projectId)
|
|
142
|
+
body.projectId = projectId;
|
|
143
|
+
if (opts.track)
|
|
144
|
+
body.trackId = opts.track;
|
|
25
145
|
if (opts.taskId)
|
|
26
146
|
body.correlationId = `task:${opts.taskId}`;
|
|
147
|
+
// `--no-template` → opts.template === false → send an explicit `null`,
|
|
148
|
+
// which SKIPS matching (`TEMPLATE_OPT_OUT` in match-session-template.ts).
|
|
149
|
+
// `--template <id>` → send that id, the one way a playbook binds. Neither
|
|
150
|
+
// → omit, so the start comes back with the pod's playbooks to choose from
|
|
151
|
+
// (suggestions; nothing is applied).
|
|
152
|
+
if (opts.template === false)
|
|
153
|
+
body.templateId = null;
|
|
154
|
+
else if (opts.template)
|
|
155
|
+
body.templateId = opts.template;
|
|
156
|
+
// Detour push: the pod records `session --spawned_from--> session` and (with
|
|
157
|
+
// --suspended-intent) writes the "what were you about to do" line onto the
|
|
158
|
+
// PARENT and a `parent --blocked_by--> this session` edge. The parent is
|
|
159
|
+
// NOT closed or paused — it waits, and popping back is `synap session attach <parent>`.
|
|
160
|
+
if (opts.parent)
|
|
161
|
+
body.parentSessionId = opts.parent;
|
|
162
|
+
if (opts.suspendedIntent)
|
|
163
|
+
body.suspendedIntent = opts.suspendedIntent;
|
|
164
|
+
if (opts.criteria) {
|
|
165
|
+
const path = resolve(process.cwd(), opts.criteria);
|
|
166
|
+
if (!existsSync(path)) {
|
|
167
|
+
console.error(chalk.red(`Error: --criteria file not found: ${path}`));
|
|
168
|
+
process.exit(1);
|
|
169
|
+
return;
|
|
170
|
+
}
|
|
171
|
+
try {
|
|
172
|
+
body.criteria = JSON.parse(readFileSync(path, "utf-8"));
|
|
173
|
+
}
|
|
174
|
+
catch (parseErr) {
|
|
175
|
+
console.error(chalk.red(`Error: --criteria file is not valid JSON — ${parseErr.message}`));
|
|
176
|
+
process.exit(1);
|
|
177
|
+
return;
|
|
178
|
+
}
|
|
179
|
+
}
|
|
27
180
|
const session = (await hubPost("/focus-sessions", body, cfg));
|
|
28
181
|
if (opts.json) {
|
|
29
182
|
console.log(JSON.stringify(session, null, 2));
|
|
30
183
|
return;
|
|
31
184
|
}
|
|
185
|
+
// A governed start comes back as a PROPOSAL, not a session: say so, and
|
|
186
|
+
// attach nothing — there is no session id to attach yet.
|
|
187
|
+
if (session.status === "proposed" && typeof session.proposalId === "string") {
|
|
188
|
+
log.warn("Starting this session is queued for your review — not started yet.");
|
|
189
|
+
if (typeof session.reviewUrl === "string")
|
|
190
|
+
log.hint(`Review: ${session.reviewUrl}`);
|
|
191
|
+
else
|
|
192
|
+
log.hint(`Proposal ${session.proposalId} — see: synap proposals list`);
|
|
193
|
+
return;
|
|
194
|
+
}
|
|
32
195
|
const id = String(session.id ?? "");
|
|
33
|
-
// Auto-attach: make this session active
|
|
34
|
-
//
|
|
35
|
-
//
|
|
36
|
-
|
|
37
|
-
const { getClaudeSessionId, writeLens } = await import("../lib/session-lens.js");
|
|
38
|
-
const cs = getClaudeSessionId();
|
|
39
|
-
if (cs)
|
|
40
|
-
writeLens(cs, { focusSessionId: id });
|
|
196
|
+
// Auto-attach: make this session active so the statusline and every scoped
|
|
197
|
+
// call reflect it. Lands on the Claude-session lens inside Claude Code,
|
|
198
|
+
// otherwise on this working tree's directory lens.
|
|
199
|
+
const target = attachActiveSessionId(id);
|
|
41
200
|
log.success(`Session started and attached`);
|
|
42
201
|
console.log(` ID: ${chalk.bold(id)}`);
|
|
202
|
+
console.log(` Name: ${chalk.white(resolveSessionTitle(session))}`);
|
|
43
203
|
console.log(` Goal: ${chalk.white(opts.goal)}`);
|
|
44
204
|
if (opts.taskId)
|
|
45
205
|
console.log(` Task: ${chalk.dim(opts.taskId)}`);
|
|
46
|
-
|
|
206
|
+
if (opts.parent)
|
|
207
|
+
console.log(` Forked from: ${chalk.dim(opts.parent)}`);
|
|
208
|
+
if (session.adopted === true) {
|
|
209
|
+
log.dim(` Continued your auto-opened session`);
|
|
210
|
+
}
|
|
211
|
+
// `playbooks` (SessionPlaybookCandidates) is present iff matching ran —
|
|
212
|
+
// see match-session-template.ts. SUGGESTIONS ONLY: nothing was applied, so
|
|
213
|
+
// say what fits and how to bind one, never that one is in force.
|
|
214
|
+
const playbooks = session.playbooks;
|
|
215
|
+
if (playbooks?.candidates?.length) {
|
|
216
|
+
log.dim(` Playbooks that fit this goal (none applied):`);
|
|
217
|
+
for (const c of playbooks.candidates) {
|
|
218
|
+
log.dim(` - ${c.name} (${c.reason})`);
|
|
219
|
+
log.dim(` ${chalk.dim(`--template ${c.id}`)}`);
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
log.dim(` Active ${describeAttachTarget(target)}`);
|
|
47
223
|
console.log();
|
|
48
224
|
// Print the ID alone on a final line so scripts can grab it easily
|
|
49
225
|
console.log(id);
|
|
@@ -56,18 +232,37 @@ export async function startSession(opts) {
|
|
|
56
232
|
// ─── listSessions ─────────────────────────────────────────────────────────────
|
|
57
233
|
export async function listSessions(opts) {
|
|
58
234
|
try {
|
|
235
|
+
// Validate at the edge, same reasoning as `--progress` above: a typo should
|
|
236
|
+
// fail here with the legal values, not reach the pod and bounce as a raw
|
|
237
|
+
// zod echo.
|
|
238
|
+
if (opts.kind !== undefined &&
|
|
239
|
+
!SESSION_KIND_FILTERS.includes(opts.kind)) {
|
|
240
|
+
console.error(chalk.red(`Error: --kind must be one of ${SESSION_KIND_FILTERS.join(" | ")} (got ${JSON.stringify(opts.kind)}).`));
|
|
241
|
+
process.exit(1);
|
|
242
|
+
}
|
|
59
243
|
const cfg = await resolveHubConfig(opts);
|
|
60
244
|
const params = {};
|
|
61
245
|
// Fall back to the active workspace (config/env) like `start` does — the
|
|
62
246
|
// focus-sessions REST requires workspaceId, and an operator with an active
|
|
63
247
|
// workspace shouldn't have to repeat --workspace on every session command.
|
|
64
|
-
|
|
248
|
+
// `--project` is a scope of its own (the pod accepts projectId alone,
|
|
249
|
+
// project-member floor): a project's sessions span spaces, so with it only
|
|
250
|
+
// an EXPLICIT --workspace narrows — never the ambient one, which would hide
|
|
251
|
+
// every session the project runs in another space.
|
|
252
|
+
const wsId = opts.project ? opts.workspace : opts.workspace || cfg.workspaceId;
|
|
65
253
|
if (wsId)
|
|
66
254
|
params.workspaceId = wsId;
|
|
255
|
+
if (opts.project)
|
|
256
|
+
params.projectId = opts.project;
|
|
67
257
|
if (opts.status)
|
|
68
258
|
params.status = opts.status;
|
|
69
259
|
if (opts.limit)
|
|
70
260
|
params.limit = parseInt(opts.limit, 10);
|
|
261
|
+
// Population lens (`services/focus-sessions/session-kind.ts` on the pod).
|
|
262
|
+
// The Hub REST door defaults to "all" itself, so omit rather than send a
|
|
263
|
+
// redundant param when the flag isn't given.
|
|
264
|
+
if (opts.kind && opts.kind !== "all")
|
|
265
|
+
params.kind = opts.kind;
|
|
71
266
|
// The Hub REST GET /focus-sessions returns a bare array of sessions.
|
|
72
267
|
// (Tolerate a { sessions: [...] } envelope too, for forward-compat.)
|
|
73
268
|
const res = await hubGet("/focus-sessions", params, cfg);
|
|
@@ -90,7 +285,17 @@ export async function listSessions(opts) {
|
|
|
90
285
|
? chalk.yellow(status)
|
|
91
286
|
: chalk.dim(status);
|
|
92
287
|
const progress = typeof s.progress === "number" ? ` ${chalk.dim(`[${s.progress}%]`)}` : "";
|
|
93
|
-
|
|
288
|
+
// `kind` is projected on every row by the Hub REST door regardless of the
|
|
289
|
+
// `--kind` filter — an older pod without the kind wave simply omits it.
|
|
290
|
+
const kindLabel = typeof s.kind === "string" ? sessionKindLabel(s.kind) : null;
|
|
291
|
+
const kindCol = kindLabel ? ` ${chalk.dim(`[${kindLabel}]`)}` : "";
|
|
292
|
+
// Present only when the door lifts `verdict` onto the row (today: the
|
|
293
|
+
// single-session GET, not this list) — `verdictSummary` returns null on
|
|
294
|
+
// an absent field, so an older/list door just omits the marker.
|
|
295
|
+
const verdict = verdictSummary(s.verdict);
|
|
296
|
+
const verdictCol = verdict ? ` ${chalk.dim(`(${verdict})`)}` : "";
|
|
297
|
+
// Full id — feeds straight into `synap session get/update/attach <id>`.
|
|
298
|
+
console.log(` ${chalk.bold(String(s.id ?? ""))} ${statusColor}${kindCol}${progress} ${chalk.white(resolveSessionTitle(s))}${verdictCol}`);
|
|
94
299
|
}
|
|
95
300
|
}
|
|
96
301
|
catch (e) {
|
|
@@ -99,22 +304,62 @@ export async function listSessions(opts) {
|
|
|
99
304
|
}
|
|
100
305
|
}
|
|
101
306
|
// ─── getSession ───────────────────────────────────────────────────────────────
|
|
307
|
+
/**
|
|
308
|
+
* Fetch a focus session by id.
|
|
309
|
+
*
|
|
310
|
+
* Prefer GET without workspaceId so project-scoped sessions (workspaceId null)
|
|
311
|
+
* resolve. Older pods still require the query param — if the bare GET fails
|
|
312
|
+
* with 400 and we have a workspace, retry with it.
|
|
313
|
+
*/
|
|
314
|
+
async function fetchSessionById(id, cfg, workspaceHint) {
|
|
315
|
+
try {
|
|
316
|
+
return (await hubGet(`/focus-sessions/${id}`, {}, cfg));
|
|
317
|
+
}
|
|
318
|
+
catch (e) {
|
|
319
|
+
const wsId = workspaceHint || cfg.workspaceId;
|
|
320
|
+
if (e instanceof HubError && e.status === 400 && wsId) {
|
|
321
|
+
return (await hubGet(`/focus-sessions/${id}`, { workspaceId: wsId }, cfg));
|
|
322
|
+
}
|
|
323
|
+
throw e;
|
|
324
|
+
}
|
|
325
|
+
}
|
|
102
326
|
export async function getSession(id, opts) {
|
|
103
327
|
try {
|
|
104
328
|
const cfg = await resolveHubConfig(opts);
|
|
105
|
-
const
|
|
106
|
-
const wsId = opts.workspace || cfg.workspaceId;
|
|
107
|
-
if (wsId)
|
|
108
|
-
params.workspaceId = wsId;
|
|
109
|
-
const res = await hubGet(`/focus-sessions/${id}`, params, cfg);
|
|
329
|
+
const res = await fetchSessionById(id, cfg, opts.workspace);
|
|
110
330
|
if (opts.json) {
|
|
111
331
|
console.log(JSON.stringify(res, null, 2));
|
|
112
332
|
return;
|
|
113
333
|
}
|
|
114
334
|
const s = res;
|
|
115
335
|
log.info(`Session ${chalk.bold(String(s.id ?? ""))}`);
|
|
336
|
+
console.log(` Name: ${chalk.white(resolveSessionTitle(s))}`);
|
|
116
337
|
console.log(` Goal: ${chalk.white(String(s.goal ?? ""))}`);
|
|
117
338
|
console.log(` Status: ${chalk.cyan(String(s.status ?? ""))}`);
|
|
339
|
+
if (typeof s.kind === "string")
|
|
340
|
+
console.log(` Kind: ${chalk.dim(sessionKindLabel(s.kind))}`);
|
|
341
|
+
// `verdict` (SessionVerdict) is present iff the session carries criteria —
|
|
342
|
+
// see `test/verdict-label-vocabulary-parity.test.ts` for the label SSOT.
|
|
343
|
+
const verdict = s.verdict;
|
|
344
|
+
if (verdict && typeof verdict.total === "number" && verdict.total > 0) {
|
|
345
|
+
const summary = verdictSummary(verdict);
|
|
346
|
+
console.log(` Criteria: ${chalk.white(`${verdict.passed ?? 0}/${verdict.total}`)}` +
|
|
347
|
+
(summary && verdict.requiredUnmet
|
|
348
|
+
? ` ${chalk.yellow(summary)}`
|
|
349
|
+
: ""));
|
|
350
|
+
}
|
|
351
|
+
// Project-scoped sessions have workspaceId null — show scope honestly.
|
|
352
|
+
if (s.workspaceId != null && s.workspaceId !== "") {
|
|
353
|
+
console.log(` Workspace: ${chalk.dim(String(s.workspaceId))}`);
|
|
354
|
+
}
|
|
355
|
+
else if (s.projectId) {
|
|
356
|
+
console.log(` Project: ${chalk.dim(String(s.projectId))} ${chalk.dim("(no workspace)")}`);
|
|
357
|
+
}
|
|
358
|
+
else {
|
|
359
|
+
console.log(` Scope: ${chalk.dim("project/unscoped (workspace null)")}`);
|
|
360
|
+
}
|
|
361
|
+
if (s.projectId && s.workspaceId)
|
|
362
|
+
console.log(` Project: ${chalk.dim(String(s.projectId))}`);
|
|
118
363
|
if (typeof s.progress === "number")
|
|
119
364
|
console.log(` Progress: ${s.progress}%`);
|
|
120
365
|
if (s.templateId)
|
|
@@ -135,16 +380,31 @@ export async function getSession(id, opts) {
|
|
|
135
380
|
export async function updateSession(id, opts) {
|
|
136
381
|
try {
|
|
137
382
|
const cfg = await resolveHubConfig(opts);
|
|
383
|
+
// The session is identified by `id` in the URL and `workspaceId` is
|
|
384
|
+
// `.optional()` on the pod's UpdateBodySchema — so demanding one here was a
|
|
385
|
+
// CLI-only rule that made an already-attached (or project-scoped) session
|
|
386
|
+
// un-updatable without re-stating a lens the terminal already holds.
|
|
138
387
|
const wsId = opts.workspace || cfg.workspaceId;
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
388
|
+
const body = {};
|
|
389
|
+
if (wsId)
|
|
390
|
+
body.workspaceId = wsId;
|
|
391
|
+
// `progress` is `z.number().int().min(0).max(100)` on the pod. `parseInt`
|
|
392
|
+
// on prose yields NaN, which serialized to the wire and came back as a raw
|
|
393
|
+
// zod echo — an unreadable error for a mistake the CLI could name here.
|
|
394
|
+
// Validate at the edge and say what the flag actually takes.
|
|
395
|
+
if (opts.progress !== undefined) {
|
|
396
|
+
const pct = Number(opts.progress);
|
|
397
|
+
if (!Number.isInteger(pct) || pct < 0 || pct > 100) {
|
|
398
|
+
console.error(chalk.red(`Error: --progress takes a whole number 0-100 (got ${JSON.stringify(opts.progress)}).`));
|
|
399
|
+
log.hint("For a free-text note, use --goal to restate the goal, or capture the note: synap capture --type lesson --claim \"...\"");
|
|
400
|
+
process.exit(1);
|
|
401
|
+
}
|
|
402
|
+
body.progress = pct;
|
|
142
403
|
}
|
|
143
|
-
const body = { workspaceId: wsId };
|
|
144
|
-
if (opts.progress !== undefined)
|
|
145
|
-
body.progress = parseInt(opts.progress, 10);
|
|
146
404
|
if (opts.status)
|
|
147
405
|
body.status = opts.status;
|
|
406
|
+
if (opts.stage)
|
|
407
|
+
body.currentStage = opts.stage;
|
|
148
408
|
if (opts.goal)
|
|
149
409
|
body.goal = opts.goal;
|
|
150
410
|
const res = await hubPatch(`/focus-sessions/${id}`, body, cfg);
|
|
@@ -157,6 +417,8 @@ export async function updateSession(id, opts) {
|
|
|
157
417
|
log.dim(` progress → ${opts.progress}%`);
|
|
158
418
|
if (opts.status)
|
|
159
419
|
log.dim(` status → ${opts.status}`);
|
|
420
|
+
if (opts.stage)
|
|
421
|
+
log.dim(` stage → ${opts.stage}`);
|
|
160
422
|
}
|
|
161
423
|
catch (e) {
|
|
162
424
|
renderHubError(e);
|
|
@@ -165,34 +427,27 @@ export async function updateSession(id, opts) {
|
|
|
165
427
|
}
|
|
166
428
|
// ─── attachSession ────────────────────────────────────────────────────────────
|
|
167
429
|
export async function attachSession(id, opts) {
|
|
168
|
-
// Validate the session exists before attaching
|
|
430
|
+
// Validate the session exists before attaching (project-scoped OK — no workspace required)
|
|
169
431
|
try {
|
|
170
432
|
const cfg = await resolveHubConfig(opts);
|
|
171
|
-
|
|
172
|
-
if (cfg.workspaceId)
|
|
173
|
-
params.workspaceId = cfg.workspaceId;
|
|
174
|
-
await hubGet(`/focus-sessions/${id}`, params, cfg);
|
|
433
|
+
await fetchSessionById(id, cfg, opts.workspace);
|
|
175
434
|
}
|
|
176
435
|
catch (e) {
|
|
177
436
|
console.error(chalk.red("Error: session not found — " + e.message));
|
|
178
437
|
process.exit(1);
|
|
179
438
|
}
|
|
180
|
-
|
|
181
|
-
const { getClaudeSessionId, writeLens } = await import("../lib/session-lens.js");
|
|
182
|
-
const cs = getClaudeSessionId();
|
|
183
|
-
if (cs)
|
|
184
|
-
writeLens(cs, { focusSessionId: id });
|
|
439
|
+
const target = attachActiveSessionId(id);
|
|
185
440
|
if (opts.json) {
|
|
186
|
-
console.log(JSON.stringify({ ok: true, sessionId: id }));
|
|
441
|
+
console.log(JSON.stringify({ ok: true, sessionId: id, scope: target }));
|
|
187
442
|
return;
|
|
188
443
|
}
|
|
189
444
|
log.success(`Session attached ${chalk.dim(id.slice(0, 8))}`);
|
|
445
|
+
log.dim(` Active ${describeAttachTarget(target)}`);
|
|
190
446
|
log.dim(` All hub calls in this terminal will tag X-Session-Id: ${id.slice(0, 8)}…`);
|
|
191
447
|
}
|
|
192
448
|
// ─── detachSession ────────────────────────────────────────────────────────────
|
|
193
449
|
export function detachSession(opts) {
|
|
194
|
-
const current =
|
|
195
|
-
clearActiveSessionId();
|
|
450
|
+
const current = detachActiveSessionId();
|
|
196
451
|
if (opts.json) {
|
|
197
452
|
console.log(JSON.stringify({ ok: true }));
|
|
198
453
|
return;
|
|
@@ -206,39 +461,205 @@ export function detachSession(opts) {
|
|
|
206
461
|
}
|
|
207
462
|
// ─── sessionStatus ────────────────────────────────────────────────────────────
|
|
208
463
|
export function sessionStatus(opts) {
|
|
209
|
-
const id =
|
|
464
|
+
const id = resolveActiveSessionId();
|
|
210
465
|
if (opts.json) {
|
|
211
466
|
console.log(JSON.stringify({ sessionId: id ?? null }));
|
|
212
467
|
return;
|
|
213
468
|
}
|
|
214
469
|
if (id) {
|
|
215
|
-
log.info(`Active session: ${chalk.bold(id.slice(0, 8))}… ${chalk.dim("(
|
|
470
|
+
log.info(`Active session: ${chalk.bold(id.slice(0, 8))}… ${chalk.dim("(SYNAP_SESSION_ID, session lens, or .synap/lens.json)")}`);
|
|
216
471
|
}
|
|
217
472
|
else {
|
|
218
473
|
log.dim("No active session — run `synap session start` or `synap session attach <id>`");
|
|
219
474
|
}
|
|
220
475
|
}
|
|
221
|
-
|
|
476
|
+
/**
|
|
477
|
+
* Close a focus session via Hub complete (proposal pack).
|
|
478
|
+
*
|
|
479
|
+
* Prefer POST /focus-sessions/:id/complete with `{ summary }` from `--recap`.
|
|
480
|
+
* On 404 (older pods without the route) fall back to PATCH status=closed and
|
|
481
|
+
* write verificationReport.summary — graceful degrade, pack unavailable.
|
|
482
|
+
*
|
|
483
|
+
* --workspace is optional: complete loads the row by id; PATCH also scopes
|
|
484
|
+
* from the row (workspaceId body is back-compat only).
|
|
485
|
+
*/
|
|
222
486
|
export async function closeSession(id, opts) {
|
|
223
487
|
try {
|
|
224
488
|
const cfg = await resolveHubConfig(opts);
|
|
225
489
|
const wsId = opts.workspace || cfg.workspaceId;
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
490
|
+
let pack = null;
|
|
491
|
+
let usedPack = false;
|
|
492
|
+
try {
|
|
493
|
+
// Canonical close: completeFocusSession — returns proposal pack.
|
|
494
|
+
// Map CLI --recap → body.summary (server field; there is no `recap` key).
|
|
495
|
+
const body = {};
|
|
496
|
+
if (opts.recap)
|
|
497
|
+
body.summary = opts.recap;
|
|
498
|
+
// How the session ended. Validated at the edge (see index.ts) so a typo
|
|
499
|
+
// fails here with the three legal values, rather than reaching the pod
|
|
500
|
+
// and being rejected by a zod enum the user cannot see.
|
|
501
|
+
if (opts.as)
|
|
502
|
+
body.terminalStatus = opts.as;
|
|
503
|
+
pack = (await hubPost(`/focus-sessions/${id}/complete`, body, cfg));
|
|
504
|
+
usedPack = true;
|
|
505
|
+
}
|
|
506
|
+
catch (e) {
|
|
507
|
+
if (!(e instanceof HubError) || e.status !== 404)
|
|
508
|
+
throw e;
|
|
509
|
+
// Older pod: no complete route — close via PATCH and warn that pack is
|
|
510
|
+
// unavailable. verificationReport.summary is the field the complete path
|
|
511
|
+
// writes (complete-session.ts); UpdateBodySchema accepts it as z.unknown().
|
|
512
|
+
log.dim("Pack unavailable on this pod (POST …/complete → 404); falling back to status close.");
|
|
513
|
+
const patchBody = {
|
|
514
|
+
status: opts.as ?? "closed",
|
|
515
|
+
};
|
|
516
|
+
if (wsId)
|
|
517
|
+
patchBody.workspaceId = wsId;
|
|
518
|
+
if (opts.recap)
|
|
519
|
+
patchBody.verificationReport = { summary: opts.recap };
|
|
520
|
+
await hubPatch(`/focus-sessions/${id}`, patchBody, cfg);
|
|
229
521
|
}
|
|
230
|
-
// Close via PATCH — the /focus-sessions/:id endpoint sets closedAt automatically
|
|
231
|
-
// when status transitions to "closed"
|
|
232
|
-
const body = { workspaceId: wsId, status: "closed" };
|
|
233
|
-
await hubPatch(`/focus-sessions/${id}`, body, cfg);
|
|
234
522
|
// Detach if this was the active terminal session
|
|
235
|
-
if (
|
|
236
|
-
|
|
523
|
+
if (resolveActiveSessionId(cfg.podUrl) === id)
|
|
524
|
+
detachActiveSessionId(cfg.podUrl);
|
|
525
|
+
if (opts.json) {
|
|
526
|
+
if (usedPack && pack) {
|
|
527
|
+
console.log(JSON.stringify(pack, null, 2));
|
|
528
|
+
}
|
|
529
|
+
else {
|
|
530
|
+
console.log(JSON.stringify({
|
|
531
|
+
ok: true,
|
|
532
|
+
status: "closed",
|
|
533
|
+
pack: false,
|
|
534
|
+
summary: opts.recap ?? null,
|
|
535
|
+
}, null, 2));
|
|
536
|
+
}
|
|
537
|
+
return;
|
|
538
|
+
}
|
|
539
|
+
const sessionStatus = (pack?.session && String(pack.session.status ?? "")) ||
|
|
540
|
+
pack?.status ||
|
|
541
|
+
"closed";
|
|
542
|
+
// Close never blocks on criteria — a required-but-unmet criterion is a
|
|
543
|
+
// flag on the closed session, never a refusal.
|
|
544
|
+
const closeVerdict = pack?.verdict && pack.verdict.requiredUnmet
|
|
545
|
+
? ` · ${pack.verdict.requiredUnmet} criteri${pack.verdict.requiredUnmet === 1 ? "on" : "a"} not met`
|
|
546
|
+
: "";
|
|
547
|
+
log.success(`Session closed ${chalk.dim(id.slice(0, 8))} ${chalk.cyan(sessionStatus)}${chalk.yellow(closeVerdict)}`);
|
|
548
|
+
if (opts.recap)
|
|
549
|
+
log.dim(` recap: ${opts.recap}`);
|
|
550
|
+
if (usedPack && pack) {
|
|
551
|
+
const pending = pack.counts?.pending ??
|
|
552
|
+
(Array.isArray(pack.pendingProposals) ? pack.pendingProposals.length : 0);
|
|
553
|
+
const unfinished = pack.counts?.unfinishedOutputs ?? 0;
|
|
554
|
+
console.log(` Pack: ${chalk.white(String(pending))} pending proposal(s)` +
|
|
555
|
+
(unfinished > 0
|
|
556
|
+
? ` ${chalk.yellow(`${unfinished} unfinished output(s)`)}`
|
|
557
|
+
: ""));
|
|
558
|
+
if (Array.isArray(pack.warnings)) {
|
|
559
|
+
for (const w of pack.warnings) {
|
|
560
|
+
log.warn(String(w));
|
|
561
|
+
}
|
|
562
|
+
}
|
|
563
|
+
if (pack.note)
|
|
564
|
+
log.dim(` ${pack.note}`);
|
|
565
|
+
if (pending > 0) {
|
|
566
|
+
log.dim(` Review: synap proposals list --session ${id}`);
|
|
567
|
+
}
|
|
568
|
+
}
|
|
569
|
+
}
|
|
570
|
+
catch (e) {
|
|
571
|
+
renderHubError(e);
|
|
572
|
+
process.exit(1);
|
|
573
|
+
}
|
|
574
|
+
}
|
|
575
|
+
// ─── evidenceSession / evaluateSession ─────────────────────────────────────────
|
|
576
|
+
/** Resolve the target session: `--session <id>`, else this terminal's active one. */
|
|
577
|
+
function resolveTargetSessionId(opts, cfg) {
|
|
578
|
+
const id = opts.session || resolveActiveSessionId(cfg.podUrl);
|
|
579
|
+
if (!id) {
|
|
580
|
+
console.error(chalk.red("Error: no session in scope — pass --session <id> or attach one with 'synap session attach <id>'"));
|
|
581
|
+
process.exit(1);
|
|
582
|
+
}
|
|
583
|
+
return id;
|
|
584
|
+
}
|
|
585
|
+
function printEvaluateResult(result) {
|
|
586
|
+
if (result.status === "not_found") {
|
|
587
|
+
log.warn("Session not found");
|
|
588
|
+
return;
|
|
589
|
+
}
|
|
590
|
+
for (const r of result.results ?? []) {
|
|
591
|
+
if (r.status === "recorded" && r.verdict) {
|
|
592
|
+
const label = verdictLabel(r.verdict);
|
|
593
|
+
const colored = r.verdict === "pass"
|
|
594
|
+
? chalk.green(label)
|
|
595
|
+
: r.verdict === "fail"
|
|
596
|
+
? chalk.red(label)
|
|
597
|
+
: chalk.dim(label);
|
|
598
|
+
console.log(` ${chalk.bold(r.key)}: ${colored}${r.escalated ? chalk.yellow(" (escalated)") : ""}`);
|
|
599
|
+
}
|
|
600
|
+
else {
|
|
601
|
+
console.log(` ${chalk.bold(r.key)}: ${chalk.dim(`skipped — ${r.reason ?? "not applicable"}`)}`);
|
|
602
|
+
}
|
|
603
|
+
}
|
|
604
|
+
const summary = verdictSummary(result.verdict);
|
|
605
|
+
if (summary)
|
|
606
|
+
log.dim(` Verdict: ${summary}`);
|
|
607
|
+
if (result.resumed)
|
|
608
|
+
log.dim(` Resumed a paused check-gate`);
|
|
609
|
+
}
|
|
610
|
+
/**
|
|
611
|
+
* `synap session evidence <key> --passed|--failed [--detail "…"]`
|
|
612
|
+
*
|
|
613
|
+
* POST /focus-sessions/:id/evidence — the agent's own deterministic report
|
|
614
|
+
* for an `evidence`-checked criterion. Grades ONLY evidence-checked
|
|
615
|
+
* criteria; never spends a judge call or runs a capability
|
|
616
|
+
* (`rest/focus-sessions.ts`, the `onlyEvidence` branch).
|
|
617
|
+
*/
|
|
618
|
+
export async function evidenceSession(key, opts) {
|
|
619
|
+
try {
|
|
620
|
+
const cfg = await resolveHubConfig(opts);
|
|
621
|
+
const id = resolveTargetSessionId(opts, cfg);
|
|
622
|
+
if (opts.passed === opts.failed) {
|
|
623
|
+
// Both or neither given — commander gives us two independent booleans,
|
|
624
|
+
// not an enum, so this is the edge check for "exactly one".
|
|
625
|
+
console.error(chalk.red("Error: pass exactly one of --passed or --failed"));
|
|
626
|
+
process.exit(1);
|
|
627
|
+
return;
|
|
628
|
+
}
|
|
629
|
+
const evidence = {
|
|
630
|
+
[key]: { passed: !!opts.passed, ...(opts.detail ? { detail: opts.detail } : {}) },
|
|
631
|
+
};
|
|
632
|
+
const result = (await hubPost(`/focus-sessions/${id}/evidence`, { evidence }, cfg));
|
|
633
|
+
if (opts.json) {
|
|
634
|
+
console.log(JSON.stringify(result, null, 2));
|
|
635
|
+
return;
|
|
636
|
+
}
|
|
637
|
+
log.success(`Evidence recorded ${chalk.dim(id.slice(0, 8))}`);
|
|
638
|
+
printEvaluateResult(result);
|
|
639
|
+
}
|
|
640
|
+
catch (e) {
|
|
641
|
+
renderHubError(e);
|
|
642
|
+
process.exit(1);
|
|
643
|
+
}
|
|
644
|
+
}
|
|
645
|
+
/**
|
|
646
|
+
* `synap session evaluate [--session <id>]`
|
|
647
|
+
*
|
|
648
|
+
* POST /focus-sessions/:id/evaluations — runs every PENDING criterion check
|
|
649
|
+
* (evidence already posted, then capability, then judge) and prints the
|
|
650
|
+
* per-criterion verdicts.
|
|
651
|
+
*/
|
|
652
|
+
export async function evaluateSession(opts) {
|
|
653
|
+
try {
|
|
654
|
+
const cfg = await resolveHubConfig(opts);
|
|
655
|
+
const id = resolveTargetSessionId(opts, cfg);
|
|
656
|
+
const result = (await hubPost(`/focus-sessions/${id}/evaluations`, {}, cfg));
|
|
237
657
|
if (opts.json) {
|
|
238
|
-
console.log(JSON.stringify(
|
|
658
|
+
console.log(JSON.stringify(result, null, 2));
|
|
239
659
|
return;
|
|
240
660
|
}
|
|
241
|
-
log.success(`Session
|
|
661
|
+
log.success(`Session evaluated ${chalk.dim(id.slice(0, 8))}`);
|
|
662
|
+
printEvaluateResult(result);
|
|
242
663
|
}
|
|
243
664
|
catch (e) {
|
|
244
665
|
renderHubError(e);
|