@synap-core/cli 1.8.0 → 1.11.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/dist/commands/agent-chat.d.ts +47 -0
- package/dist/commands/agent-chat.js +250 -0
- package/dist/commands/agent-chat.js.map +1 -0
- package/dist/commands/agent-run.js +3 -4
- package/dist/commands/agent-run.js.map +1 -1
- package/dist/commands/agents.js +85 -46
- package/dist/commands/agents.js.map +1 -1
- package/dist/commands/automation.js +2 -1
- package/dist/commands/automation.js.map +1 -1
- package/dist/commands/bridge-setup.d.ts +66 -0
- package/dist/commands/bridge-setup.js +1112 -0
- package/dist/commands/bridge-setup.js.map +1 -0
- package/dist/commands/cap-connections.d.ts +28 -0
- package/dist/commands/cap-connections.js +224 -0
- package/dist/commands/cap-connections.js.map +1 -0
- package/dist/commands/capability.d.ts +89 -0
- package/dist/commands/capability.js +1594 -0
- package/dist/commands/capability.js.map +1 -0
- package/dist/commands/centrality.d.ts +20 -0
- package/dist/commands/centrality.js +95 -0
- package/dist/commands/centrality.js.map +1 -0
- package/dist/commands/connect.d.ts +2 -0
- package/dist/commands/connect.js +16 -35
- package/dist/commands/connect.js.map +1 -1
- package/dist/commands/context.js +6 -7
- package/dist/commands/context.js.map +1 -1
- package/dist/commands/data-extra.d.ts +1 -0
- package/dist/commands/data-extra.js +41 -14
- package/dist/commands/data-extra.js.map +1 -1
- package/dist/commands/data.d.ts +4 -4
- package/dist/commands/data.js +254 -187
- package/dist/commands/data.js.map +1 -1
- package/dist/commands/diagnose.d.ts +20 -0
- package/dist/commands/diagnose.js +186 -0
- package/dist/commands/diagnose.js.map +1 -0
- package/dist/commands/digest.d.ts +17 -0
- package/dist/commands/digest.js +122 -0
- package/dist/commands/digest.js.map +1 -0
- package/dist/commands/discover.d.ts +2 -0
- package/dist/commands/discover.js +25 -8
- package/dist/commands/discover.js.map +1 -1
- package/dist/commands/doc.d.ts +14 -0
- package/dist/commands/doc.js +61 -4
- package/dist/commands/doc.js.map +1 -1
- package/dist/commands/doctor.d.ts +21 -0
- package/dist/commands/doctor.js +189 -0
- package/dist/commands/doctor.js.map +1 -0
- package/dist/commands/events.js +5 -2
- package/dist/commands/events.js.map +1 -1
- package/dist/commands/explain.d.ts +1 -1
- package/dist/commands/explain.js +18 -15
- package/dist/commands/explain.js.map +1 -1
- package/dist/commands/facet.d.ts +29 -0
- package/dist/commands/facet.js +113 -0
- package/dist/commands/facet.js.map +1 -0
- package/dist/commands/graph.js +7 -4
- package/dist/commands/graph.js.map +1 -1
- package/dist/commands/import.d.ts +38 -0
- package/dist/commands/import.js +471 -0
- package/dist/commands/import.js.map +1 -0
- package/dist/commands/init.js +35 -16
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/keys.js +3 -4
- package/dist/commands/keys.js.map +1 -1
- package/dist/commands/knowledge.d.ts +8 -0
- package/dist/commands/knowledge.js +308 -33
- package/dist/commands/knowledge.js.map +1 -1
- package/dist/commands/launch.d.ts +50 -0
- package/dist/commands/launch.js +790 -0
- package/dist/commands/launch.js.map +1 -0
- package/dist/commands/lens.d.ts +45 -0
- package/dist/commands/lens.js +386 -0
- package/dist/commands/lens.js.map +1 -0
- package/dist/commands/market-authoring.d.ts +45 -0
- package/dist/commands/market-authoring.js +225 -0
- package/dist/commands/market-authoring.js.map +1 -0
- package/dist/commands/market.d.ts +224 -0
- package/dist/commands/market.js +1643 -0
- package/dist/commands/market.js.map +1 -0
- package/dist/commands/mcp.d.ts +64 -0
- package/dist/commands/mcp.js +265 -0
- package/dist/commands/mcp.js.map +1 -0
- package/dist/commands/observe.js +14 -11
- package/dist/commands/observe.js.map +1 -1
- package/dist/commands/open.d.ts +21 -4
- package/dist/commands/open.js +45 -4
- package/dist/commands/open.js.map +1 -1
- package/dist/commands/pod.d.ts +100 -0
- package/dist/commands/pod.js +359 -0
- package/dist/commands/pod.js.map +1 -0
- package/dist/commands/pods.d.ts +15 -0
- package/dist/commands/pods.js +233 -17
- package/dist/commands/pods.js.map +1 -1
- package/dist/commands/proposals-actions.js +43 -3
- package/dist/commands/proposals-actions.js.map +1 -1
- package/dist/commands/purge.d.ts +23 -0
- package/dist/commands/purge.js +148 -0
- package/dist/commands/purge.js.map +1 -0
- package/dist/commands/raycast.d.ts +15 -0
- package/dist/commands/raycast.js +153 -0
- package/dist/commands/raycast.js.map +1 -0
- package/dist/commands/sessions.js +47 -22
- package/dist/commands/sessions.js.map +1 -1
- package/dist/commands/skill-manage.d.ts +21 -0
- package/dist/commands/skill-manage.js +195 -0
- package/dist/commands/skill-manage.js.map +1 -0
- package/dist/commands/skills-commands.js +2 -1
- package/dist/commands/skills-commands.js.map +1 -1
- package/dist/commands/skills.js +7 -4
- package/dist/commands/skills.js.map +1 -1
- package/dist/commands/status.d.ts +3 -1
- package/dist/commands/status.js +166 -14
- package/dist/commands/status.js.map +1 -1
- package/dist/commands/statusline.d.ts +24 -0
- package/dist/commands/statusline.js +450 -0
- package/dist/commands/statusline.js.map +1 -0
- package/dist/commands/subscribe.js +2 -2
- package/dist/commands/subscribe.js.map +1 -1
- package/dist/commands/template.d.ts +42 -0
- package/dist/commands/template.js +191 -0
- package/dist/commands/template.js.map +1 -0
- package/dist/commands/tools.d.ts +30 -0
- package/dist/commands/tools.js +315 -0
- package/dist/commands/tools.js.map +1 -0
- package/dist/commands/upload.d.ts +30 -0
- package/dist/commands/upload.js +155 -0
- package/dist/commands/upload.js.map +1 -0
- package/dist/commands/versions.d.ts +27 -0
- package/dist/commands/versions.js +277 -0
- package/dist/commands/versions.js.map +1 -0
- package/dist/commands/view.js +3 -2
- package/dist/commands/view.js.map +1 -1
- package/dist/commands/whoami.d.ts +21 -0
- package/dist/commands/whoami.js +129 -0
- package/dist/commands/whoami.js.map +1 -0
- package/dist/index.js +894 -60
- package/dist/index.js.map +1 -1
- package/dist/lib/approval-poll.d.ts +42 -0
- package/dist/lib/approval-poll.js +52 -0
- package/dist/lib/approval-poll.js.map +1 -0
- package/dist/lib/auth.d.ts +29 -6
- package/dist/lib/auth.js +105 -94
- package/dist/lib/auth.js.map +1 -1
- package/dist/lib/bundle-version.d.ts +11 -0
- package/dist/lib/bundle-version.js +33 -0
- package/dist/lib/bundle-version.js.map +1 -0
- package/dist/lib/capture-lane.d.ts +30 -12
- package/dist/lib/capture-lane.js +73 -14
- package/dist/lib/capture-lane.js.map +1 -1
- package/dist/lib/capture-structure.d.ts +123 -0
- package/dist/lib/capture-structure.js +57 -0
- package/dist/lib/capture-structure.js.map +1 -0
- package/dist/lib/cp-packages.d.ts +177 -0
- package/dist/lib/cp-packages.js +389 -0
- package/dist/lib/cp-packages.js.map +1 -0
- package/dist/lib/describe-lens.d.ts +46 -0
- package/dist/lib/describe-lens.js +33 -0
- package/dist/lib/describe-lens.js.map +1 -0
- package/dist/lib/hub-client.d.ts +91 -1
- package/dist/lib/hub-client.js +565 -22
- 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/installed.d.ts +51 -0
- package/dist/lib/installed.js +70 -0
- package/dist/lib/installed.js.map +1 -0
- package/dist/lib/next-steps.d.ts +61 -0
- package/dist/lib/next-steps.js +146 -0
- package/dist/lib/next-steps.js.map +1 -0
- package/dist/lib/pod.d.ts +144 -22
- package/dist/lib/pod.js +302 -64
- package/dist/lib/pod.js.map +1 -1
- package/dist/lib/project-ref.d.ts +95 -0
- package/dist/lib/project-ref.js +144 -0
- package/dist/lib/project-ref.js.map +1 -0
- package/dist/lib/project.d.ts +35 -0
- package/dist/lib/project.js +39 -0
- package/dist/lib/project.js.map +1 -0
- package/dist/lib/session-lens.d.ts +33 -0
- package/dist/lib/session-lens.js +76 -0
- package/dist/lib/session-lens.js.map +1 -0
- package/dist/lib/skill-import.d.ts +40 -0
- package/dist/lib/skill-import.js +203 -0
- package/dist/lib/skill-import.js.map +1 -0
- package/dist/lib/skills-installer.d.ts +17 -6
- package/dist/lib/skills-installer.js +133 -19
- package/dist/lib/skills-installer.js.map +1 -1
- package/dist/lib/suite.d.ts +28 -0
- package/dist/lib/suite.js +29 -0
- package/dist/lib/suite.js.map +1 -0
- package/dist/lib/superwhisper-import.d.ts +40 -0
- package/dist/lib/superwhisper-import.js +389 -0
- package/dist/lib/superwhisper-import.js.map +1 -0
- package/dist/lib/targets.d.ts +49 -1
- package/dist/lib/targets.js +420 -288
- package/dist/lib/targets.js.map +1 -1
- package/dist/lib/template-file.d.ts +74 -0
- package/dist/lib/template-file.js +140 -0
- package/dist/lib/template-file.js.map +1 -0
- package/dist/lib/unwrapList.d.ts +1 -0
- package/dist/lib/unwrapList.js +20 -0
- package/dist/lib/unwrapList.js.map +1 -0
- package/dist/utils/logger.d.ts +2 -0
- package/dist/utils/logger.js +10 -2
- package/dist/utils/logger.js.map +1 -1
- package/node_modules/@synap/hub-rest-client/dist/index.cjs +414 -34
- package/node_modules/@synap/hub-rest-client/dist/index.d.cts +762 -22
- package/node_modules/@synap/hub-rest-client/dist/index.d.ts +762 -22
- package/node_modules/@synap/hub-rest-client/dist/index.js +414 -34
- package/node_modules/@synap/hub-rest-client/package.json +1 -1
- package/node_modules/@synap/hub-rest-client/src/client.ts +525 -37
- package/node_modules/@synap/hub-rest-client/src/index.ts +42 -0
- package/node_modules/@synap/hub-rest-client/src/setup.ts +57 -1
- package/node_modules/@synap/hub-rest-client/src/types.ts +697 -37
- package/package.json +11 -5
- package/skills/agent-os/SKILL.md +218 -0
- package/skills/manifest.json +5 -0
- package/skills/onboard/SKILL.md +193 -0
- package/skills/synap/SKILL.md +1284 -58
- package/skills/synap/_order.txt +37 -0
- package/skills/synap/_skill.yaml +24 -0
- package/skills/synap/authentication.md +10 -0
- package/skills/synap/automations.md +264 -0
- package/skills/synap/capabilities.md +107 -0
- package/skills/synap/capture.md +50 -142
- package/skills/synap/cli-operations.md +107 -0
- package/skills/synap/common-mistakes.md +13 -0
- package/skills/synap/content-os.md +83 -0
- package/skills/synap/creative-loop.md +43 -0
- package/skills/synap/crm.md +117 -0
- package/skills/synap/diagnostics.md +35 -0
- package/skills/synap/digesting-a-channel.md +63 -0
- package/skills/synap/document-embeds.md +123 -0
- package/skills/synap/escalation-ladder.md +71 -0
- package/skills/synap/focus-sessions.md +47 -0
- package/skills/synap/governance-rules.md +64 -0
- package/skills/synap/governance.md +6 -6
- package/skills/synap/graph-gardening.md +21 -0
- package/skills/synap/inline-patterns.md +38 -0
- package/skills/synap/lenses.md +38 -0
- package/skills/synap/linking-principle.md +39 -0
- package/skills/synap/linking.md +1 -0
- package/skills/synap/mental-model.md +45 -0
- package/skills/synap/more.md +7 -0
- package/skills/synap/multi-entity-capture.md +12 -0
- package/skills/synap/next-action.md +37 -0
- package/skills/synap/north-star.md +17 -0
- package/skills/synap/operating-mode-rules.md +45 -0
- package/skills/synap/operating-mode.md +9 -0
- package/skills/synap/quick-reference.md +67 -0
- package/skills/synap/reading.md +43 -0
- package/skills/synap/recap.md +21 -0
- package/skills/synap/reflexes.md +46 -0
- package/skills/synap/response-style.md +21 -0
- package/skills/synap/scope.md +13 -0
- package/skills/synap/showing.md +17 -0
- package/skills/synap/user-model.md +25 -0
- package/skills/synap/viewframe-cells.md +290 -0
- package/skills/synap/work-flow.md +113 -0
- package/skills/synap/worked-examples.md +74 -0
- package/skills/synap/workspace-design.md +45 -0
- package/skills/synap/workspace-edges.md +49 -0
- package/skills/synap/writes.md +213 -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-market/SKILL.md +335 -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 +75 -0
- package/skills/synap-market/discover-and-fetch.md +59 -0
- package/skills/synap-market/governance-and-catalog.md +56 -0
- package/skills/synap-market/install.md +55 -0
- package/skills/synap-market/overview.md +51 -0
- package/skills/synap-schema/SKILL.md +97 -6
- package/skills/synap-schema/_order.txt +13 -0
- package/skills/synap-schema/_skill.yaml +22 -0
- package/skills/synap-schema/before-you-touch.md +14 -0
- package/skills/synap-schema/common-mistakes.md +9 -0
- package/skills/synap-schema/creating-profiles.md +17 -0
- package/skills/synap-schema/discover-profiles.md +24 -0
- package/skills/synap-schema/entity-scope.md +8 -0
- package/skills/synap-schema/extend-vs-create.md +31 -0
- package/skills/synap-schema/more.md +6 -0
- package/skills/synap-schema/overlay-properties.md +22 -0
- package/skills/synap-schema/profiles.md +3 -0
- package/skills/synap-schema/property-defs.md +29 -0
- package/skills/synap-schema/read-before-write.md +50 -0
- package/skills/synap-schema/relations.md +18 -0
- package/skills/synap-schema/worked-example.md +30 -0
- package/skills/synap-ui/SKILL.md +26 -2
- package/skills/synap-ui/_order.txt +13 -0
- package/skills/synap-ui/_skill.yaml +23 -0
- package/skills/synap-ui/ai-companion.md +27 -0
- package/skills/synap-ui/arranging-bento.md +8 -0
- package/skills/synap-ui/before-you-build.md +20 -0
- package/skills/synap-ui/bento-layouts.md +35 -0
- package/skills/synap-ui/common-mistakes.md +10 -0
- package/skills/synap-ui/creating-views.md +26 -0
- package/skills/synap-ui/four-builds.md +24 -0
- package/skills/synap-ui/more.md +7 -0
- package/skills/synap-ui/proposing-vs-extending.md +11 -0
- package/skills/synap-ui/view-list.md +24 -0
- package/skills/synap-ui/views.md +3 -0
- package/skills/synap-ui/worked-example.md +18 -0
- package/skills/synap-ui/workspaces.md +47 -0
- package/templates/automations/bookmark-enrichment.automation.json +44 -0
- package/templates/automations/mail-feed.automation.json +86 -0
- package/templates/automations/url-bookmark-capture.automation.json +70 -0
- package/templates/skills/README.md +21 -0
- package/templates/skills/authoring-automations/SKILL.md +95 -0
- package/templates/skills/authoring-automations/reference/node-matrix.md +49 -0
- package/templates/skills/authoring-capabilities/SKILL.md +93 -0
- package/templates/skills/authoring-capabilities/reference/template-anatomy.md +70 -0
- package/templates/skills/authoring-playbooks/SKILL.md +102 -0
- package/templates/skills/authoring-playbooks/reference/stages-contract.md +35 -0
- package/templates/skills/authoring-playbooks/reference/worked-example.md +64 -0
- package/templates/skills/bookmark-enrichment/SKILL.md +40 -0
- package/templates/skills/coordinating-agents/SKILL.md +32 -0
- package/templates/skills/coordinating-branches/SKILL.md +27 -0
- package/templates/skills/mapping-the-server/SKILL.md +54 -0
- package/templates/skills/reading-client-progress/SKILL.md +65 -0
- package/templates/skills/routing-to-channels/SKILL.md +54 -0
- package/templates/skills/stellar-scf-grants-advisor/ASSOCIATE-CHEATSHEET.md +133 -0
- package/templates/skills/stellar-scf-grants-advisor/ASSOCIATE-ONBOARDING-GUIDE.md +761 -0
- package/templates/skills/stellar-scf-grants-advisor/CLIENT-FAQ.md +181 -0
- package/templates/skills/stellar-scf-grants-advisor/PARTNER-HANDOVER.md +130 -0
- package/templates/skills/stellar-scf-grants-advisor/SKILL.md +102 -0
- package/templates/skills/stellar-scf-grants-advisor/examples/README.md +43 -0
- package/templates/skills/stellar-scf-grants-advisor/examples/chat-summary-templates.md +158 -0
- package/templates/skills/stellar-scf-grants-advisor/examples/corpus-comparable-rows.md +136 -0
- package/templates/skills/stellar-scf-grants-advisor/examples/q10-team-rewrites.md +109 -0
- package/templates/skills/stellar-scf-grants-advisor/examples/q2-description-rewrites.md +88 -0
- package/templates/skills/stellar-scf-grants-advisor/examples/q6-integration-rewrites.md +107 -0
- package/templates/skills/stellar-scf-grants-advisor/examples/tranche-structures.md +176 -0
- package/templates/skills/stellar-scf-grants-advisor/reference/01-methodology.md +96 -0
- package/templates/skills/stellar-scf-grants-advisor/reference/02-scoring-framework.md +199 -0
- package/templates/skills/stellar-scf-grants-advisor/reference/03-rejection-patterns.md +241 -0
- package/templates/skills/stellar-scf-grants-advisor/reference/04-winner-patterns.md +120 -0
- package/templates/skills/stellar-scf-grants-advisor/reference/05-comeback-patterns.md +92 -0
- package/templates/skills/stellar-scf-grants-advisor/reference/06-budget-benchmarks.md +125 -0
- package/templates/skills/stellar-scf-grants-advisor/reference/07-integration-list.md +147 -0
- package/templates/skills/stellar-scf-grants-advisor/reference/08-abstract-fields.md +258 -0
- package/templates/skills/stellar-scf-grants-advisor/reference/09-build-fields.md +259 -0
- package/templates/skills/stellar-scf-grants-advisor/reference/10-corpus-winners.md +135 -0
- package/templates/skills/stellar-scf-grants-advisor/reference/11-corpus-rejects.md +267 -0
- package/templates/skills/stellar-scf-grants-advisor/reference/12-client-communication.md +131 -0
- package/templates/skills/stellar-scf-grants-advisor/reference/13-excel-output-spec.md +199 -0
- package/templates/skills/stellar-scf-grants-advisor/reference/14-worked-examples.md +160 -0
- package/templates/skills/stellar-scf-grants-advisor/templates/abstract-review-builder.py +253 -0
- package/templates/skills/stellar-scf-grants-advisor/templates/build-review-builder.py +213 -0
- package/dist/commands/connectors.d.ts +0 -31
- package/dist/commands/connectors.js +0 -276
- package/dist/commands/connectors.js.map +0 -1
- package/dist/commands/finish.d.ts +0 -25
- package/dist/commands/finish.js +0 -274
- package/dist/commands/finish.js.map +0 -1
- package/dist/commands/openclaw.d.ts +0 -40
- package/dist/commands/openclaw.js +0 -1148
- package/dist/commands/openclaw.js.map +0 -1
- package/dist/commands/security-audit.d.ts +0 -12
- package/dist/commands/security-audit.js +0 -100
- package/dist/commands/security-audit.js.map +0 -1
- package/dist/lib/hardening.d.ts +0 -18
- package/dist/lib/hardening.js +0 -214
- package/dist/lib/hardening.js.map +0 -1
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Control-plane package registry client (read-only).
|
|
3
|
+
* ==================================================
|
|
4
|
+
*
|
|
5
|
+
* The ONE authed HTTP client for the CP package registry (`/api/packages`).
|
|
6
|
+
* Before this file there was NO `/api/packages` client in the CLI — `launch`
|
|
7
|
+
* read the whole catalog from the bundled `@synap-core/workspace-templates`
|
|
8
|
+
* package. The ratified architecture is: PUBLIC templates ship in the bundle,
|
|
9
|
+
* PRIVATE templates live in the CP behind the user's login. This client is the
|
|
10
|
+
* private half.
|
|
11
|
+
*
|
|
12
|
+
* Two list endpoints, one detail endpoint:
|
|
13
|
+
* • GET /api/packages — public browse rows (no auth, `definition` stripped)
|
|
14
|
+
* • GET /api/packages/mine — the caller's own packages (Bearer, incl. private)
|
|
15
|
+
* • GET /api/packages/:slug — full row WITH `definition` (Bearer → private visible to author)
|
|
16
|
+
*
|
|
17
|
+
* The row→`RemoteEntry` mapping is NOT here — it is the canonical
|
|
18
|
+
* `rowToRemoteEntry` in `@synap-core/workspace-templates` (browser + CLI share
|
|
19
|
+
* the ONE copy; the two hand-copies had already drifted). This file owns only
|
|
20
|
+
* TRANSPORT: the Bearer token, the base URL (`auth.ts`'s `getCpUrl()`), and the
|
|
21
|
+
* query params the CP `/api/packages` route supports (`search`/`category`/`tag`/
|
|
22
|
+
* `verified`).
|
|
23
|
+
*/
|
|
24
|
+
import { type CpPackageRow, type RemoteEntry, type RemoteSourceStatus } from "@synap-core/workspace-templates";
|
|
25
|
+
import type { PackageDefinitionLike } from "./template-file.js";
|
|
26
|
+
/**
|
|
27
|
+
* The server-side filters `GET /api/packages` accepts (CP `routes/packages.ts`).
|
|
28
|
+
* `category` is a PACKAGE_TYPES value (`workspace`/`capability`/`skill`/…). The
|
|
29
|
+
* `/mine` route supports none of these — it is the caller's own small set — so
|
|
30
|
+
* they are applied CLIENT-side there.
|
|
31
|
+
*/
|
|
32
|
+
export interface PackageFilters {
|
|
33
|
+
search?: string;
|
|
34
|
+
category?: string;
|
|
35
|
+
tag?: string;
|
|
36
|
+
verified?: boolean;
|
|
37
|
+
}
|
|
38
|
+
/** Tier / pricing signal the browse route carries but `RemoteEntry` drops. */
|
|
39
|
+
export interface TierInfo {
|
|
40
|
+
requiredTier?: string | null;
|
|
41
|
+
pricingModel?: string | null;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* A public browse row — the canonical `CpPackageRow` PLUS the tier/pricing and
|
|
45
|
+
* count fields the browse route (`GET /api/packages`) returns but the shared
|
|
46
|
+
* `RemoteEntry` shape does not carry. Kept local because they are a
|
|
47
|
+
* discovery-surface concern, not part of the merge door's contract.
|
|
48
|
+
*/
|
|
49
|
+
export interface CpBrowseRow extends CpPackageRow {
|
|
50
|
+
version?: string;
|
|
51
|
+
requiredTier?: string | null;
|
|
52
|
+
pricingModel?: string | null;
|
|
53
|
+
isVerified?: boolean;
|
|
54
|
+
installCount?: number;
|
|
55
|
+
}
|
|
56
|
+
/** `/mine` returns `isPublic` (and, like the browse route, `version`) on top of the canonical row shape. */
|
|
57
|
+
export type CpMineRow = CpPackageRow & {
|
|
58
|
+
isPublic?: boolean;
|
|
59
|
+
version?: string;
|
|
60
|
+
};
|
|
61
|
+
/**
|
|
62
|
+
* GET /api/packages — public browse rows, RAW (incl. `requiredTier`/
|
|
63
|
+
* `pricingModel`/`category`). No auth. Throws on non-2xx / network. This is the
|
|
64
|
+
* source both the merged launch catalog and the `market` command read from.
|
|
65
|
+
*/
|
|
66
|
+
export declare function fetchPublicBrowseRows(filters?: PackageFilters): Promise<CpBrowseRow[]>;
|
|
67
|
+
/** GET /api/packages — public workspace templates as `RemoteEntry`. No auth. */
|
|
68
|
+
export declare function fetchPublicPackages(filters?: PackageFilters): Promise<RemoteEntry[]>;
|
|
69
|
+
/**
|
|
70
|
+
* GET /api/packages/mine — the caller's own packages (incl. private). Bearer
|
|
71
|
+
* required. The route has no `search`/`category` params, so those filters are
|
|
72
|
+
* applied client-side over this (small) set; `search` is honored, `category`
|
|
73
|
+
* only when the row actually carries one (the `/mine` select omits it, so a
|
|
74
|
+
* type filter never silently drops the user's own rows).
|
|
75
|
+
*/
|
|
76
|
+
export declare function fetchMyRows(token: string, filters?: PackageFilters): Promise<CpMineRow[]>;
|
|
77
|
+
export declare function fetchMyPackages(token: string, filters?: PackageFilters): Promise<RemoteEntry[]>;
|
|
78
|
+
/**
|
|
79
|
+
* GET /api/packages/available — the slugs THIS account's subscription tier can
|
|
80
|
+
* install (Bearer required; the route reads the user's `subscriptions.tier`).
|
|
81
|
+
* Used to compute the "locked" set: a public package that declares a
|
|
82
|
+
* `requiredTier` but is absent here is ungrantable for this account. Only
|
|
83
|
+
* `category` is a real filter on this route — the others are ignored server-side.
|
|
84
|
+
*/
|
|
85
|
+
export declare function fetchAvailableSlugs(token: string, filters?: PackageFilters): Promise<Set<string>>;
|
|
86
|
+
/**
|
|
87
|
+
* GET /api/packages/:slug — the full row, INCLUDING `definition` (the install
|
|
88
|
+
* payload). Authed when a token is given, which is REQUIRED for a private
|
|
89
|
+
* template (the author-only visibility gate 404s otherwise). Returns `null` if
|
|
90
|
+
* the package is absent / not visible.
|
|
91
|
+
*/
|
|
92
|
+
export declare function fetchPackageDefinition(slug: string, token?: string): Promise<Record<string, unknown> | null>;
|
|
93
|
+
/** The remote half of the catalog, plus the health `mergeCatalog` needs. */
|
|
94
|
+
export interface RemoteCatalog {
|
|
95
|
+
rows: RemoteEntry[];
|
|
96
|
+
status: RemoteSourceStatus;
|
|
97
|
+
loggedIn: boolean;
|
|
98
|
+
email?: string;
|
|
99
|
+
/** How many private rows we actually fetched (meaningful only when status === "ok"). */
|
|
100
|
+
privateCount: number;
|
|
101
|
+
/** Tier/pricing per public slug — the browse route carries it, `RemoteEntry` drops it. */
|
|
102
|
+
tierBySlug: Map<string, TierInfo>;
|
|
103
|
+
/**
|
|
104
|
+
* Slugs that declare a `requiredTier` this account CANNOT install (browse ∖
|
|
105
|
+
* `/available`). Empty when logged out or when `/available` couldn't be read
|
|
106
|
+
* (older pod / failure) — absence means "unknown", never "locked".
|
|
107
|
+
*/
|
|
108
|
+
lockedSlugs: Set<string>;
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Assemble the remote catalog for `launch`, degrading HONESTLY rather than
|
|
112
|
+
* failing open empty:
|
|
113
|
+
*
|
|
114
|
+
* • Logged out → NO network. The bundle already IS the public catalog, and
|
|
115
|
+
* private templates are invisible without auth. Status "unauthenticated"
|
|
116
|
+
* tells the consumer to render the `synap login` path.
|
|
117
|
+
* • Logged in → fetch `/mine` (private + own public) and best-effort `/packages`
|
|
118
|
+
* (official / third-party public); merge, private-carrying rows win a tie.
|
|
119
|
+
* • `/mine` 401/403 → "unauthenticated" (session expired). Network failure →
|
|
120
|
+
* "unreachable". Either way `rows` is empty and the door keeps the bundle.
|
|
121
|
+
*/
|
|
122
|
+
export declare function fetchRemoteCatalog(filters?: PackageFilters): Promise<RemoteCatalog>;
|
|
123
|
+
/**
|
|
124
|
+
* A CP write failure carrying the server's OWN message + status, so the caller
|
|
125
|
+
* can surface `detail` (never swallow it — the `readErrorBody`/`detail` lesson)
|
|
126
|
+
* and special-case a 403 reserved-slug rejection.
|
|
127
|
+
*/
|
|
128
|
+
export declare class CpWriteError extends Error {
|
|
129
|
+
readonly status: number;
|
|
130
|
+
readonly serverMessage: string;
|
|
131
|
+
constructor(status: number, serverMessage: string);
|
|
132
|
+
}
|
|
133
|
+
/** Test seams — inject a fetch + token + base URL instead of touching the network / `~/.synap`. */
|
|
134
|
+
export interface CpWriteDeps {
|
|
135
|
+
fetchImpl?: typeof fetch;
|
|
136
|
+
token?: string;
|
|
137
|
+
cpUrl?: string;
|
|
138
|
+
}
|
|
139
|
+
export interface PublishResult {
|
|
140
|
+
/** `created` (201) · `updated` (200, content changed) · `no-op` (200, identical content). */
|
|
141
|
+
outcome: "created" | "updated" | "no-op";
|
|
142
|
+
slug: string;
|
|
143
|
+
displayName: string;
|
|
144
|
+
/** The `h-<hash>` version the CP derived from the definition. */
|
|
145
|
+
version: string;
|
|
146
|
+
isPublic: boolean;
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* `POST /api/packages` — publish (upsert) a package definition under the caller's
|
|
150
|
+
* account. `isPublic` decides visibility (default private — the command flips it
|
|
151
|
+
* with `--public`). The version is DERIVED server-side from the definition, so
|
|
152
|
+
* identical content re-published is a no-op. Surfaces a 403 reserved-slug
|
|
153
|
+
* rejection (and any other failure) as a `CpWriteError` carrying the server's
|
|
154
|
+
* own message.
|
|
155
|
+
*
|
|
156
|
+
* The definition's identity (`slug`, `displayName`) is read off its `_meta`/
|
|
157
|
+
* `workspaceName`; `_meta.icon`/`.color`/`.domain` are hoisted onto the
|
|
158
|
+
* definition's top level because the CP reads those off `definition.icon`/… for
|
|
159
|
+
* the list DTO (it strips the unknown `_meta` key).
|
|
160
|
+
*/
|
|
161
|
+
export declare function publishPackage(def: PackageDefinitionLike, opts: {
|
|
162
|
+
isPublic: boolean;
|
|
163
|
+
}, deps?: CpWriteDeps): Promise<PublishResult>;
|
|
164
|
+
/**
|
|
165
|
+
* `PATCH /api/packages/:slug` — owner-gated flip of a package to private.
|
|
166
|
+
*
|
|
167
|
+
* ⚠️ TODO(cp): the CP PATCH handler's body validator is
|
|
168
|
+
* `z.object({ podId: z.string().min(1).nullable() })` TODAY — it does NOT accept
|
|
169
|
+
* `isPublic`, so this call currently fails (400) until the CP adds `isPublic` to
|
|
170
|
+
* that PATCH allow-list. This is deliberately the INTENDED endpoint (not a
|
|
171
|
+
* faked flip): it will start working the moment the CP door is widened. The
|
|
172
|
+
* command surfaces the CP's message honestly meanwhile.
|
|
173
|
+
*/
|
|
174
|
+
export declare function unpublishPackage(slug: string, deps?: CpWriteDeps): Promise<{
|
|
175
|
+
slug: string;
|
|
176
|
+
isPublic: boolean;
|
|
177
|
+
}>;
|
|
@@ -0,0 +1,389 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Control-plane package registry client (read-only).
|
|
3
|
+
* ==================================================
|
|
4
|
+
*
|
|
5
|
+
* The ONE authed HTTP client for the CP package registry (`/api/packages`).
|
|
6
|
+
* Before this file there was NO `/api/packages` client in the CLI — `launch`
|
|
7
|
+
* read the whole catalog from the bundled `@synap-core/workspace-templates`
|
|
8
|
+
* package. The ratified architecture is: PUBLIC templates ship in the bundle,
|
|
9
|
+
* PRIVATE templates live in the CP behind the user's login. This client is the
|
|
10
|
+
* private half.
|
|
11
|
+
*
|
|
12
|
+
* Two list endpoints, one detail endpoint:
|
|
13
|
+
* • GET /api/packages — public browse rows (no auth, `definition` stripped)
|
|
14
|
+
* • GET /api/packages/mine — the caller's own packages (Bearer, incl. private)
|
|
15
|
+
* • GET /api/packages/:slug — full row WITH `definition` (Bearer → private visible to author)
|
|
16
|
+
*
|
|
17
|
+
* The row→`RemoteEntry` mapping is NOT here — it is the canonical
|
|
18
|
+
* `rowToRemoteEntry` in `@synap-core/workspace-templates` (browser + CLI share
|
|
19
|
+
* the ONE copy; the two hand-copies had already drifted). This file owns only
|
|
20
|
+
* TRANSPORT: the Bearer token, the base URL (`auth.ts`'s `getCpUrl()`), and the
|
|
21
|
+
* query params the CP `/api/packages` route supports (`search`/`category`/`tag`/
|
|
22
|
+
* `verified`).
|
|
23
|
+
*/
|
|
24
|
+
import { rowToRemoteEntry, } from "@synap-core/workspace-templates";
|
|
25
|
+
import { getCpUrl, getStoredToken, isTokenLocallyExpired } from "./auth.js";
|
|
26
|
+
// Packages mount under `/api/packages` (CP `routes/index.ts`), unlike `/auth`
|
|
27
|
+
// and `/pods` which sit at the root — hence the explicit `/api` segment here.
|
|
28
|
+
const packagesBase = () => `${getCpUrl()}/api/packages`;
|
|
29
|
+
const FETCH_TIMEOUT_MS = 10_000;
|
|
30
|
+
/** Build the `/api/packages` query string from filters + any extra params. */
|
|
31
|
+
function buildQuery(filters, extra) {
|
|
32
|
+
const p = new URLSearchParams(extra);
|
|
33
|
+
if (filters?.search)
|
|
34
|
+
p.set("search", filters.search);
|
|
35
|
+
if (filters?.category)
|
|
36
|
+
p.set("category", filters.category);
|
|
37
|
+
if (filters?.tag)
|
|
38
|
+
p.set("tag", filters.tag);
|
|
39
|
+
if (filters?.verified)
|
|
40
|
+
p.set("verified", "true");
|
|
41
|
+
return p.toString();
|
|
42
|
+
}
|
|
43
|
+
/** An auth failure (401/403) — distinct from an unreachable-network failure. */
|
|
44
|
+
class CpAuthError extends Error {
|
|
45
|
+
authFailed = true;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* GET /api/packages — public browse rows, RAW (incl. `requiredTier`/
|
|
49
|
+
* `pricingModel`/`category`). No auth. Throws on non-2xx / network. This is the
|
|
50
|
+
* source both the merged launch catalog and the `market` command read from.
|
|
51
|
+
*/
|
|
52
|
+
export async function fetchPublicBrowseRows(filters) {
|
|
53
|
+
const qs = buildQuery(filters, { limit: "100" });
|
|
54
|
+
const res = await fetch(`${packagesBase()}?${qs}`, {
|
|
55
|
+
signal: AbortSignal.timeout(FETCH_TIMEOUT_MS),
|
|
56
|
+
});
|
|
57
|
+
if (!res.ok)
|
|
58
|
+
throw new Error(`CP GET /api/packages → HTTP ${res.status}`);
|
|
59
|
+
const data = (await res.json());
|
|
60
|
+
return data.packages ?? [];
|
|
61
|
+
}
|
|
62
|
+
/** GET /api/packages — public workspace templates as `RemoteEntry`. No auth. */
|
|
63
|
+
export async function fetchPublicPackages(filters) {
|
|
64
|
+
const rows = await fetchPublicBrowseRows(filters);
|
|
65
|
+
// Browse rows are all public by construction — pass `isPrivate` undefined.
|
|
66
|
+
return rows.map((r) => rowToRemoteEntry(r, undefined));
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* GET /api/packages/mine — the caller's own packages (incl. private). Bearer
|
|
70
|
+
* required. The route has no `search`/`category` params, so those filters are
|
|
71
|
+
* applied client-side over this (small) set; `search` is honored, `category`
|
|
72
|
+
* only when the row actually carries one (the `/mine` select omits it, so a
|
|
73
|
+
* type filter never silently drops the user's own rows).
|
|
74
|
+
*/
|
|
75
|
+
export async function fetchMyRows(token, filters) {
|
|
76
|
+
const res = await fetch(`${packagesBase()}/mine?limit=100`, {
|
|
77
|
+
headers: { Authorization: `Bearer ${token}` },
|
|
78
|
+
signal: AbortSignal.timeout(FETCH_TIMEOUT_MS),
|
|
79
|
+
});
|
|
80
|
+
if (res.status === 401 || res.status === 403) {
|
|
81
|
+
throw new CpAuthError(`CP GET /api/packages/mine → HTTP ${res.status}`);
|
|
82
|
+
}
|
|
83
|
+
if (!res.ok)
|
|
84
|
+
throw new Error(`CP GET /api/packages/mine → HTTP ${res.status}`);
|
|
85
|
+
const data = (await res.json());
|
|
86
|
+
let rows = data.packages ?? [];
|
|
87
|
+
if (filters?.category) {
|
|
88
|
+
rows = rows.filter((r) => r.category == null || r.category === filters.category);
|
|
89
|
+
}
|
|
90
|
+
if (filters?.search) {
|
|
91
|
+
const q = filters.search.toLowerCase();
|
|
92
|
+
rows = rows.filter((r) => r.slug.toLowerCase().includes(q) ||
|
|
93
|
+
r.displayName.toLowerCase().includes(q) ||
|
|
94
|
+
(r.description ?? "").toLowerCase().includes(q));
|
|
95
|
+
}
|
|
96
|
+
return rows;
|
|
97
|
+
}
|
|
98
|
+
export async function fetchMyPackages(token, filters) {
|
|
99
|
+
const rows = await fetchMyRows(token, filters);
|
|
100
|
+
return rows.map((r) => rowToRemoteEntry(r, r.isPublic === false ? true : undefined));
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* GET /api/packages/available — the slugs THIS account's subscription tier can
|
|
104
|
+
* install (Bearer required; the route reads the user's `subscriptions.tier`).
|
|
105
|
+
* Used to compute the "locked" set: a public package that declares a
|
|
106
|
+
* `requiredTier` but is absent here is ungrantable for this account. Only
|
|
107
|
+
* `category` is a real filter on this route — the others are ignored server-side.
|
|
108
|
+
*/
|
|
109
|
+
export async function fetchAvailableSlugs(token, filters) {
|
|
110
|
+
const qs = buildQuery({ category: filters?.category }, { limit: "100" });
|
|
111
|
+
const res = await fetch(`${packagesBase()}/available?${qs}`, {
|
|
112
|
+
headers: { Authorization: `Bearer ${token}` },
|
|
113
|
+
signal: AbortSignal.timeout(FETCH_TIMEOUT_MS),
|
|
114
|
+
});
|
|
115
|
+
if (!res.ok)
|
|
116
|
+
throw new Error(`CP GET /api/packages/available → HTTP ${res.status}`);
|
|
117
|
+
const data = (await res.json());
|
|
118
|
+
return new Set((data.packages ?? []).map((p) => p.slug));
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* GET /api/packages/:slug — the full row, INCLUDING `definition` (the install
|
|
122
|
+
* payload). Authed when a token is given, which is REQUIRED for a private
|
|
123
|
+
* template (the author-only visibility gate 404s otherwise). Returns `null` if
|
|
124
|
+
* the package is absent / not visible.
|
|
125
|
+
*/
|
|
126
|
+
export async function fetchPackageDefinition(slug, token) {
|
|
127
|
+
const res = await fetch(`${packagesBase()}/${encodeURIComponent(slug)}`, {
|
|
128
|
+
headers: token ? { Authorization: `Bearer ${token}` } : {},
|
|
129
|
+
signal: AbortSignal.timeout(FETCH_TIMEOUT_MS),
|
|
130
|
+
});
|
|
131
|
+
if (!res.ok)
|
|
132
|
+
return null;
|
|
133
|
+
const data = (await res.json());
|
|
134
|
+
return data.package?.definition ?? null;
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Assemble the remote catalog for `launch`, degrading HONESTLY rather than
|
|
138
|
+
* failing open empty:
|
|
139
|
+
*
|
|
140
|
+
* • Logged out → NO network. The bundle already IS the public catalog, and
|
|
141
|
+
* private templates are invisible without auth. Status "unauthenticated"
|
|
142
|
+
* tells the consumer to render the `synap login` path.
|
|
143
|
+
* • Logged in → fetch `/mine` (private + own public) and best-effort `/packages`
|
|
144
|
+
* (official / third-party public); merge, private-carrying rows win a tie.
|
|
145
|
+
* • `/mine` 401/403 → "unauthenticated" (session expired). Network failure →
|
|
146
|
+
* "unreachable". Either way `rows` is empty and the door keeps the bundle.
|
|
147
|
+
*/
|
|
148
|
+
export async function fetchRemoteCatalog(filters) {
|
|
149
|
+
const creds = getStoredToken();
|
|
150
|
+
const loggedIn = !!creds && !isTokenLocallyExpired(creds);
|
|
151
|
+
if (!loggedIn) {
|
|
152
|
+
return {
|
|
153
|
+
rows: [],
|
|
154
|
+
status: "unauthenticated",
|
|
155
|
+
loggedIn: false,
|
|
156
|
+
privateCount: 0,
|
|
157
|
+
tierBySlug: new Map(),
|
|
158
|
+
lockedSlugs: new Set(),
|
|
159
|
+
};
|
|
160
|
+
}
|
|
161
|
+
let publicRows = [];
|
|
162
|
+
let mineRows = [];
|
|
163
|
+
let availableSlugs = null;
|
|
164
|
+
try {
|
|
165
|
+
[publicRows, mineRows, availableSlugs] = await Promise.all([
|
|
166
|
+
// Public is best-effort: a private catalog that resolves is still useful
|
|
167
|
+
// even if the browse route hiccups.
|
|
168
|
+
fetchPublicBrowseRows(filters).catch(() => []),
|
|
169
|
+
fetchMyPackages(creds.token, filters),
|
|
170
|
+
// Tier gate is best-effort: an older pod without `/available` ⇒ null ⇒
|
|
171
|
+
// "unknown", never "locked".
|
|
172
|
+
fetchAvailableSlugs(creds.token, filters).catch(() => null),
|
|
173
|
+
]);
|
|
174
|
+
}
|
|
175
|
+
catch (e) {
|
|
176
|
+
const authFailed = e.authFailed === true;
|
|
177
|
+
return {
|
|
178
|
+
rows: [],
|
|
179
|
+
status: authFailed ? "unauthenticated" : "unreachable",
|
|
180
|
+
loggedIn: true,
|
|
181
|
+
email: creds.email,
|
|
182
|
+
privateCount: 0,
|
|
183
|
+
tierBySlug: new Map(),
|
|
184
|
+
lockedSlugs: new Set(),
|
|
185
|
+
};
|
|
186
|
+
}
|
|
187
|
+
const tierBySlug = new Map();
|
|
188
|
+
const lockedSlugs = new Set();
|
|
189
|
+
for (const r of publicRows) {
|
|
190
|
+
if (r.requiredTier != null || r.pricingModel != null) {
|
|
191
|
+
tierBySlug.set(r.slug, {
|
|
192
|
+
requiredTier: r.requiredTier ?? null,
|
|
193
|
+
pricingModel: r.pricingModel ?? null,
|
|
194
|
+
});
|
|
195
|
+
}
|
|
196
|
+
// Locked = declares a tier this account's `/available` set doesn't include.
|
|
197
|
+
if (availableSlugs && r.requiredTier && !availableSlugs.has(r.slug)) {
|
|
198
|
+
lockedSlugs.add(r.slug);
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
// Dedup by slug; `/mine` rows overwrite public ones so the private flag wins.
|
|
202
|
+
const bySlug = new Map();
|
|
203
|
+
for (const r of publicRows)
|
|
204
|
+
bySlug.set(r.slug, rowToRemoteEntry(r, undefined));
|
|
205
|
+
for (const r of mineRows)
|
|
206
|
+
bySlug.set(r.slug, r);
|
|
207
|
+
const rows = [...bySlug.values()];
|
|
208
|
+
return {
|
|
209
|
+
rows,
|
|
210
|
+
status: "ok",
|
|
211
|
+
loggedIn: true,
|
|
212
|
+
email: creds.email,
|
|
213
|
+
privateCount: rows.filter((r) => r.isPrivate).length,
|
|
214
|
+
tierBySlug,
|
|
215
|
+
lockedSlugs,
|
|
216
|
+
};
|
|
217
|
+
}
|
|
218
|
+
// ─── WRITE half: publish / unpublish ────────────────────────────────────────
|
|
219
|
+
// Everything above is GET-only. These are the CLI's publish-loop write door to
|
|
220
|
+
// `POST /api/packages` (upsert on (slug, authorId), content-hash version) and
|
|
221
|
+
// `PATCH /api/packages/:slug` (owner-gated). All CP HTTP goes through THIS file
|
|
222
|
+
// — the command layer never hand-rolls a `fetch`.
|
|
223
|
+
/**
|
|
224
|
+
* A CP write failure carrying the server's OWN message + status, so the caller
|
|
225
|
+
* can surface `detail` (never swallow it — the `readErrorBody`/`detail` lesson)
|
|
226
|
+
* and special-case a 403 reserved-slug rejection.
|
|
227
|
+
*/
|
|
228
|
+
export class CpWriteError extends Error {
|
|
229
|
+
status;
|
|
230
|
+
serverMessage;
|
|
231
|
+
constructor(status, serverMessage) {
|
|
232
|
+
super(serverMessage);
|
|
233
|
+
this.status = status;
|
|
234
|
+
this.serverMessage = serverMessage;
|
|
235
|
+
this.name = "CpWriteError";
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
/**
|
|
239
|
+
* Extract the human cause from a CP error body, mirroring `hub-client`'s
|
|
240
|
+
* `readErrorBody` precedence (message → error+detail → error → detail) so the
|
|
241
|
+
* SPECIFIC cause in `detail` is never thrown away for the generic `error`.
|
|
242
|
+
*/
|
|
243
|
+
function extractServerMessage(raw, status) {
|
|
244
|
+
const trimmed = raw.trim();
|
|
245
|
+
if (!trimmed)
|
|
246
|
+
return `HTTP ${status}`;
|
|
247
|
+
try {
|
|
248
|
+
const o = JSON.parse(trimmed);
|
|
249
|
+
const str = (v) => typeof v === "string" && v.trim() ? v.trim() : undefined;
|
|
250
|
+
const err = str(o.error);
|
|
251
|
+
const detail = str(o.detail);
|
|
252
|
+
const msg = str(o.message);
|
|
253
|
+
const base = msg ?? (err && detail ? `${err}: ${detail}` : (err ?? detail));
|
|
254
|
+
if (base) {
|
|
255
|
+
if (Array.isArray(o.issues) && o.issues.length) {
|
|
256
|
+
return `${base} (${o.issues.length} validation issue(s))`;
|
|
257
|
+
}
|
|
258
|
+
return base;
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
catch {
|
|
262
|
+
// not JSON — fall through to the plain-text body
|
|
263
|
+
}
|
|
264
|
+
return trimmed.length > 200 ? `${trimmed.slice(0, 200)}…` : trimmed;
|
|
265
|
+
}
|
|
266
|
+
function requireToken(deps) {
|
|
267
|
+
const token = deps.token ?? getStoredToken()?.token;
|
|
268
|
+
if (!token)
|
|
269
|
+
throw new CpWriteError(401, "Not logged in — run: synap login");
|
|
270
|
+
return token;
|
|
271
|
+
}
|
|
272
|
+
/**
|
|
273
|
+
* `POST /api/packages` — publish (upsert) a package definition under the caller's
|
|
274
|
+
* account. `isPublic` decides visibility (default private — the command flips it
|
|
275
|
+
* with `--public`). The version is DERIVED server-side from the definition, so
|
|
276
|
+
* identical content re-published is a no-op. Surfaces a 403 reserved-slug
|
|
277
|
+
* rejection (and any other failure) as a `CpWriteError` carrying the server's
|
|
278
|
+
* own message.
|
|
279
|
+
*
|
|
280
|
+
* The definition's identity (`slug`, `displayName`) is read off its `_meta`/
|
|
281
|
+
* `workspaceName`; `_meta.icon`/`.color`/`.domain` are hoisted onto the
|
|
282
|
+
* definition's top level because the CP reads those off `definition.icon`/… for
|
|
283
|
+
* the list DTO (it strips the unknown `_meta` key).
|
|
284
|
+
*/
|
|
285
|
+
export async function publishPackage(def, opts, deps = {}) {
|
|
286
|
+
const fetchImpl = deps.fetchImpl ?? fetch;
|
|
287
|
+
const token = requireToken(deps);
|
|
288
|
+
const base = deps.cpUrl ?? getCpUrl();
|
|
289
|
+
const slug = def._meta?.slug;
|
|
290
|
+
const displayName = def.workspaceName;
|
|
291
|
+
if (!slug)
|
|
292
|
+
throw new CpWriteError(0, "Template has no slug (meta.slug) — cannot publish");
|
|
293
|
+
if (!displayName)
|
|
294
|
+
throw new CpWriteError(0, "Template has no workspace name — cannot publish");
|
|
295
|
+
// Best-effort pre-read of the caller's OWN row for this slug, so a
|
|
296
|
+
// content-identical no-op is told apart from an in-place update (the CP
|
|
297
|
+
// returns 200 for both). A failure here only loses that precision.
|
|
298
|
+
let priorVersion;
|
|
299
|
+
let existed = false;
|
|
300
|
+
try {
|
|
301
|
+
const pre = await fetchImpl(`${base}/api/packages/mine?limit=100`, {
|
|
302
|
+
headers: { Authorization: `Bearer ${token}` },
|
|
303
|
+
signal: AbortSignal.timeout(FETCH_TIMEOUT_MS),
|
|
304
|
+
});
|
|
305
|
+
if (pre.ok) {
|
|
306
|
+
const data = (await pre.json());
|
|
307
|
+
const row = (data.packages ?? []).find((r) => r.slug === slug);
|
|
308
|
+
if (row) {
|
|
309
|
+
existed = true;
|
|
310
|
+
priorVersion = row.version;
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
catch {
|
|
315
|
+
// best-effort
|
|
316
|
+
}
|
|
317
|
+
const definition = {
|
|
318
|
+
...def,
|
|
319
|
+
icon: def._meta?.icon ?? def.icon,
|
|
320
|
+
color: def._meta?.color ?? def.color,
|
|
321
|
+
domain: def._meta?.domain ?? def.domain,
|
|
322
|
+
};
|
|
323
|
+
const res = await fetchImpl(`${base}/api/packages`, {
|
|
324
|
+
method: "POST",
|
|
325
|
+
headers: {
|
|
326
|
+
Authorization: `Bearer ${token}`,
|
|
327
|
+
"Content-Type": "application/json",
|
|
328
|
+
},
|
|
329
|
+
body: JSON.stringify({
|
|
330
|
+
slug,
|
|
331
|
+
displayName,
|
|
332
|
+
description: def.description,
|
|
333
|
+
isPublic: opts.isPublic,
|
|
334
|
+
tags: def._meta?.tags,
|
|
335
|
+
category: "workspace",
|
|
336
|
+
definition,
|
|
337
|
+
}),
|
|
338
|
+
signal: AbortSignal.timeout(FETCH_TIMEOUT_MS),
|
|
339
|
+
});
|
|
340
|
+
if (!res.ok) {
|
|
341
|
+
const raw = await res.text().catch(() => "");
|
|
342
|
+
throw new CpWriteError(res.status, extractServerMessage(raw, res.status));
|
|
343
|
+
}
|
|
344
|
+
const data = (await res.json());
|
|
345
|
+
const version = data.package?.version ?? "";
|
|
346
|
+
const outcome = res.status === 201
|
|
347
|
+
? "created"
|
|
348
|
+
: existed && priorVersion === version
|
|
349
|
+
? "no-op"
|
|
350
|
+
: "updated";
|
|
351
|
+
return {
|
|
352
|
+
outcome,
|
|
353
|
+
slug,
|
|
354
|
+
displayName,
|
|
355
|
+
version,
|
|
356
|
+
isPublic: data.package?.isPublic ?? opts.isPublic,
|
|
357
|
+
};
|
|
358
|
+
}
|
|
359
|
+
/**
|
|
360
|
+
* `PATCH /api/packages/:slug` — owner-gated flip of a package to private.
|
|
361
|
+
*
|
|
362
|
+
* ⚠️ TODO(cp): the CP PATCH handler's body validator is
|
|
363
|
+
* `z.object({ podId: z.string().min(1).nullable() })` TODAY — it does NOT accept
|
|
364
|
+
* `isPublic`, so this call currently fails (400) until the CP adds `isPublic` to
|
|
365
|
+
* that PATCH allow-list. This is deliberately the INTENDED endpoint (not a
|
|
366
|
+
* faked flip): it will start working the moment the CP door is widened. The
|
|
367
|
+
* command surfaces the CP's message honestly meanwhile.
|
|
368
|
+
*/
|
|
369
|
+
export async function unpublishPackage(slug, deps = {}) {
|
|
370
|
+
const fetchImpl = deps.fetchImpl ?? fetch;
|
|
371
|
+
const token = requireToken(deps);
|
|
372
|
+
const base = deps.cpUrl ?? getCpUrl();
|
|
373
|
+
const res = await fetchImpl(`${base}/api/packages/${encodeURIComponent(slug)}`, {
|
|
374
|
+
method: "PATCH",
|
|
375
|
+
headers: {
|
|
376
|
+
Authorization: `Bearer ${token}`,
|
|
377
|
+
"Content-Type": "application/json",
|
|
378
|
+
},
|
|
379
|
+
body: JSON.stringify({ isPublic: false }),
|
|
380
|
+
signal: AbortSignal.timeout(FETCH_TIMEOUT_MS),
|
|
381
|
+
});
|
|
382
|
+
if (!res.ok) {
|
|
383
|
+
const raw = await res.text().catch(() => "");
|
|
384
|
+
throw new CpWriteError(res.status, extractServerMessage(raw, res.status));
|
|
385
|
+
}
|
|
386
|
+
const data = (await res.json());
|
|
387
|
+
return { slug, isPublic: data.isPublic ?? false };
|
|
388
|
+
}
|
|
389
|
+
//# sourceMappingURL=cp-packages.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cp-packages.js","sourceRoot":"","sources":["../../src/lib/cp-packages.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared lens display formatter.
|
|
3
|
+
*
|
|
4
|
+
* The lens itself — `{ workspaceId, projectId, focusSessionId }` — is resolved
|
|
5
|
+
* by `resolveActiveLens()` in `session-lens.ts`; this module only answers "how
|
|
6
|
+
* do we SHOW it". Before this existed, `commands/lens.ts` and
|
|
7
|
+
* `commands/statusline.ts` each hand-rolled their own "no workspace → pod-wide"
|
|
8
|
+
* / "no project → none" fallback text. One formatter now owns that logic so
|
|
9
|
+
* new surfaces (Raycast, `orient`) can render the same lens consistently.
|
|
10
|
+
*
|
|
11
|
+
* Colors/links are deliberately NOT baked in here — `lens.ts` uses chalk,
|
|
12
|
+
* `statusline.ts` uses raw ANSI + OSC-8 hyperlinks, and a future Raycast
|
|
13
|
+
* consumer will use neither. Callers wrap the plain names/ids this module
|
|
14
|
+
* resolves in whatever presentation their surface needs.
|
|
15
|
+
*/
|
|
16
|
+
export interface LensEntry {
|
|
17
|
+
id: string;
|
|
18
|
+
name?: string;
|
|
19
|
+
}
|
|
20
|
+
export interface ResolvedLens {
|
|
21
|
+
workspace?: LensEntry;
|
|
22
|
+
project?: LensEntry;
|
|
23
|
+
session?: LensEntry;
|
|
24
|
+
}
|
|
25
|
+
export interface DescribedLensField {
|
|
26
|
+
id: string;
|
|
27
|
+
/** Display name, falling back to the raw id when no name was resolved. */
|
|
28
|
+
name: string;
|
|
29
|
+
}
|
|
30
|
+
export interface DescribedLens {
|
|
31
|
+
structured: {
|
|
32
|
+
workspace?: DescribedLensField;
|
|
33
|
+
project?: DescribedLensField;
|
|
34
|
+
session?: DescribedLensField;
|
|
35
|
+
/** True iff neither a workspace nor a project is bound — fully pod-wide. */
|
|
36
|
+
podWide: boolean;
|
|
37
|
+
};
|
|
38
|
+
/** One "Label: value" line per field, in workspace/project/session order — value is the
|
|
39
|
+
* placeholder text when unset, so callers can print it as-is or re-color it. */
|
|
40
|
+
lines: Array<{
|
|
41
|
+
label: "Workspace" | "Project" | "Session";
|
|
42
|
+
value: string;
|
|
43
|
+
bound: boolean;
|
|
44
|
+
}>;
|
|
45
|
+
}
|
|
46
|
+
export declare function describeLens(lens: ResolvedLens): DescribedLens;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared lens display formatter.
|
|
3
|
+
*
|
|
4
|
+
* The lens itself — `{ workspaceId, projectId, focusSessionId }` — is resolved
|
|
5
|
+
* by `resolveActiveLens()` in `session-lens.ts`; this module only answers "how
|
|
6
|
+
* do we SHOW it". Before this existed, `commands/lens.ts` and
|
|
7
|
+
* `commands/statusline.ts` each hand-rolled their own "no workspace → pod-wide"
|
|
8
|
+
* / "no project → none" fallback text. One formatter now owns that logic so
|
|
9
|
+
* new surfaces (Raycast, `orient`) can render the same lens consistently.
|
|
10
|
+
*
|
|
11
|
+
* Colors/links are deliberately NOT baked in here — `lens.ts` uses chalk,
|
|
12
|
+
* `statusline.ts` uses raw ANSI + OSC-8 hyperlinks, and a future Raycast
|
|
13
|
+
* consumer will use neither. Callers wrap the plain names/ids this module
|
|
14
|
+
* resolves in whatever presentation their surface needs.
|
|
15
|
+
*/
|
|
16
|
+
function describeField(entry) {
|
|
17
|
+
if (!entry?.id)
|
|
18
|
+
return undefined;
|
|
19
|
+
return { id: entry.id, name: entry.name?.trim() || entry.id };
|
|
20
|
+
}
|
|
21
|
+
export function describeLens(lens) {
|
|
22
|
+
const workspace = describeField(lens.workspace);
|
|
23
|
+
const project = describeField(lens.project);
|
|
24
|
+
const session = describeField(lens.session);
|
|
25
|
+
const podWide = !workspace && !project;
|
|
26
|
+
const lines = [
|
|
27
|
+
{ label: "Workspace", value: workspace?.name ?? "— (pod-wide)", bound: Boolean(workspace) },
|
|
28
|
+
{ label: "Project", value: project?.name ?? "— none", bound: Boolean(project) },
|
|
29
|
+
{ label: "Session", value: session?.name ?? "— none", bound: Boolean(session) },
|
|
30
|
+
];
|
|
31
|
+
return { structured: { workspace, project, session, podWide }, lines };
|
|
32
|
+
}
|
|
33
|
+
//# sourceMappingURL=describe-lens.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"describe-lens.js","sourceRoot":"","sources":["../../src/lib/describe-lens.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAgCH,SAAS,aAAa,CAAC,KAAiB;IACtC,IAAI,CAAC,KAAK,EAAE,EAAE;QAAE,OAAO,SAAS,CAAC;IACjC,OAAO,EAAE,EAAE,EAAE,KAAK,CAAC,EAAE,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,KAAK,CAAC,EAAE,EAAE,CAAC;AAChE,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,IAAkB;IAC7C,MAAM,SAAS,GAAG,aAAa,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IAChD,MAAM,OAAO,GAAG,aAAa,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IAC5C,MAAM,OAAO,GAAG,aAAa,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IAC5C,MAAM,OAAO,GAAG,CAAC,SAAS,IAAI,CAAC,OAAO,CAAC;IAEvC,MAAM,KAAK,GAA2B;QACpC,EAAE,KAAK,EAAE,WAAW,EAAE,KAAK,EAAE,SAAS,EAAE,IAAI,IAAI,cAAc,EAAE,KAAK,EAAE,OAAO,CAAC,SAAS,CAAC,EAAE;QAC3F,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,IAAI,QAAQ,EAAE,KAAK,EAAE,OAAO,CAAC,OAAO,CAAC,EAAE;QAC/E,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,IAAI,QAAQ,EAAE,KAAK,EAAE,OAAO,CAAC,OAAO,CAAC,EAAE;KAChF,CAAC;IAEF,OAAO,EAAE,UAAU,EAAE,EAAE,SAAS,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,EAAE,KAAK,EAAE,CAAC;AACzE,CAAC"}
|