@synap-core/cli 1.8.0 → 1.10.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 +1523 -0
- package/dist/commands/capability.js.map +1 -0
- package/dist/commands/centrality.d.ts +20 -0
- package/dist/commands/centrality.js +94 -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 +4 -6
- package/dist/commands/context.js.map +1 -1
- package/dist/commands/data-extra.d.ts +1 -0
- package/dist/commands/data-extra.js +34 -10
- package/dist/commands/data-extra.js.map +1 -1
- package/dist/commands/data.d.ts +4 -4
- package/dist/commands/data.js +241 -184
- package/dist/commands/data.js.map +1 -1
- package/dist/commands/diagnose.d.ts +20 -0
- package/dist/commands/diagnose.js +143 -0
- package/dist/commands/diagnose.js.map +1 -0
- package/dist/commands/digest.d.ts +17 -0
- package/dist/commands/digest.js +121 -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/events.js +2 -1
- 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 +2 -1
- package/dist/commands/graph.js.map +1 -1
- package/dist/commands/import.d.ts +38 -0
- package/dist/commands/import.js +440 -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 +2 -0
- package/dist/commands/knowledge.js +61 -9
- 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.d.ts +209 -0
- package/dist/commands/market.js +1368 -0
- package/dist/commands/market.js.map +1 -0
- package/dist/commands/mcp.d.ts +42 -0
- package/dist/commands/mcp.js +184 -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 +1 -0
- package/dist/commands/pods.js +77 -15
- package/dist/commands/pods.js.map +1 -1
- package/dist/commands/proposals-actions.js +40 -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 +45 -21
- 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 +4 -3
- 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/tools.d.ts +30 -0
- package/dist/commands/tools.js +315 -0
- package/dist/commands/tools.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 +776 -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 +71 -14
- package/dist/lib/capture-lane.js.map +1 -1
- package/dist/lib/cp-packages.d.ts +121 -0
- package/dist/lib/cp-packages.js +218 -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 +78 -1
- package/dist/lib/hub-client.js +474 -22
- package/dist/lib/hub-client.js.map +1 -1
- 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 +91 -19
- package/dist/lib/pod.js +222 -56
- 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/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/package.json +9 -4
- package/skills/agent-os/SKILL.md +212 -0
- package/skills/manifest.json +5 -0
- package/skills/onboard/SKILL.md +186 -0
- package/skills/synap/SKILL.md +1182 -37
- 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 +10 -0
- package/skills/synap/cli-operations.md +107 -0
- package/skills/synap/common-mistakes.md +12 -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 +38 -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 +10 -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 +53 -0
- package/skills/synap/workspace-design.md +45 -0
- package/skills/synap/workspace-edges.md +49 -0
- package/skills/synap/writes.md +156 -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
- package/node_modules/@synap/hub-rest-client/dist/index.cjs +0 -881
- package/node_modules/@synap/hub-rest-client/dist/index.d.cts +0 -907
- package/node_modules/@synap/hub-rest-client/dist/index.d.ts +0 -907
- package/node_modules/@synap/hub-rest-client/dist/index.js +0 -851
- package/node_modules/@synap/hub-rest-client/package.json +0 -45
- package/node_modules/@synap/hub-rest-client/src/client.ts +0 -1143
- package/node_modules/@synap/hub-rest-client/src/errors.ts +0 -30
- package/node_modules/@synap/hub-rest-client/src/index.ts +0 -111
- package/node_modules/@synap/hub-rest-client/src/setup.ts +0 -77
- package/node_modules/@synap/hub-rest-client/src/types.ts +0 -639
package/dist/commands/data.d.ts
CHANGED
|
@@ -2,6 +2,7 @@ export interface BaseOpts {
|
|
|
2
2
|
json?: boolean;
|
|
3
3
|
podUrl?: string;
|
|
4
4
|
apiKey?: string;
|
|
5
|
+
details?: boolean;
|
|
5
6
|
}
|
|
6
7
|
export declare const parseLimit: (s: string | undefined, def: number) => number;
|
|
7
8
|
export declare function formatHit(hit: Record<string, unknown>): {
|
|
@@ -16,18 +17,17 @@ export declare function listEntities(opts: BaseOpts & {
|
|
|
16
17
|
workspace?: string;
|
|
17
18
|
profile?: string;
|
|
18
19
|
limit?: string;
|
|
20
|
+
role?: string;
|
|
19
21
|
}): Promise<void>;
|
|
20
22
|
export declare function getEntity(id: string, opts: BaseOpts & {
|
|
21
23
|
workspace?: string;
|
|
22
24
|
}): Promise<void>;
|
|
23
|
-
export declare function noteData(text: string, opts: BaseOpts & {
|
|
24
|
-
context?: string;
|
|
25
|
-
json?: boolean;
|
|
26
|
-
}): Promise<void>;
|
|
27
25
|
export declare function askKnowledge(query: string, opts: BaseOpts & {
|
|
28
26
|
workspace?: string;
|
|
29
27
|
limit?: string;
|
|
30
28
|
json?: boolean;
|
|
29
|
+
session?: boolean;
|
|
30
|
+
compare?: boolean;
|
|
31
31
|
}): Promise<void>;
|
|
32
32
|
export declare function createEntity(opts: BaseOpts & {
|
|
33
33
|
profile: string;
|
package/dist/commands/data.js
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import chalk from "chalk";
|
|
2
2
|
import { log } from "../utils/logger.js";
|
|
3
|
-
import { resolveHubConfig, resolveUserId, hubGet, hubPost, hubPatch } from "../lib/hub-client.js";
|
|
4
|
-
import {
|
|
3
|
+
import { resolveHubConfig, resolveUserId, hubGet, hubPost, hubPatch, readActiveSessionId, renderHubError } from "../lib/hub-client.js";
|
|
4
|
+
import { unwrapList } from "../lib/unwrapList.js";
|
|
5
|
+
import { reportWrite } from "../lib/capture-lane.js";
|
|
6
|
+
import { renderNextSteps, FLOW } from "../lib/next-steps.js";
|
|
5
7
|
export const parseLimit = (s, def) => s ? parseInt(s, 10) : def;
|
|
6
8
|
export function formatHit(hit) {
|
|
7
9
|
const doc = (hit.document ?? hit);
|
|
@@ -13,112 +15,114 @@ export function formatHit(hit) {
|
|
|
13
15
|
id: String(doc.id ?? hit.id ?? "").slice(0, 8),
|
|
14
16
|
};
|
|
15
17
|
}
|
|
16
|
-
// ─── orient ───────────────────────────────────────────────────────────────────
|
|
17
18
|
export async function orient(opts) {
|
|
18
19
|
try {
|
|
19
20
|
const cfg = await resolveHubConfig(opts);
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
const
|
|
26
|
-
const userId = String(me
|
|
27
|
-
const
|
|
28
|
-
|
|
29
|
-
// Newer pods return `entityCount` directly on GET /workspaces; for older
|
|
30
|
-
// pods fall back to counting a real page of entities (GET /entities
|
|
31
|
-
// returns a bare array — there is no `total` field on the wire).
|
|
32
|
-
const FALLBACK_PAGE = 100;
|
|
33
|
-
const wsDetails = await Promise.all(wsList.map(async (ws) => {
|
|
34
|
-
const wsId = String(ws.id ?? "");
|
|
35
|
-
const declaredCount = typeof ws.entityCount === "number" ? ws.entityCount : undefined;
|
|
36
|
-
const [profilesRes, entitiesRes] = await Promise.allSettled([
|
|
37
|
-
hubGet("/profiles", { userId, workspaceId: wsId }, cfg),
|
|
38
|
-
declaredCount === undefined
|
|
39
|
-
? hubGet("/entities", { userId, workspaceId: wsId, limit: FALLBACK_PAGE }, cfg)
|
|
40
|
-
: Promise.resolve(null),
|
|
41
|
-
]);
|
|
42
|
-
const profiles = profilesRes.status === "fulfilled"
|
|
43
|
-
? (profilesRes.value.profiles ?? profilesRes.value)
|
|
44
|
-
: [];
|
|
45
|
-
const profileList = Array.isArray(profiles) ? profiles : [];
|
|
46
|
-
let entityTotal = declaredCount ?? 0;
|
|
47
|
-
let countIsLowerBound = false;
|
|
48
|
-
if (declaredCount === undefined && entitiesRes.status === "fulfilled" && entitiesRes.value) {
|
|
49
|
-
const v = entitiesRes.value;
|
|
50
|
-
const arr = Array.isArray(v) ? v : (v.entities ?? []);
|
|
51
|
-
entityTotal = Array.isArray(arr) ? arr.length : 0;
|
|
52
|
-
countIsLowerBound = entityTotal === FALLBACK_PAGE;
|
|
53
|
-
}
|
|
54
|
-
return { ws, profileList, entityTotal, countIsLowerBound };
|
|
55
|
-
}));
|
|
21
|
+
// ONE canonical shape: the backend `discover()` service (via GET /orient)
|
|
22
|
+
// assembles the lens map — workspaces + projects + profile sample +
|
|
23
|
+
// disclosure (onboarding→goal, entity counts, per-ws profiles under full).
|
|
24
|
+
// The CLI only RENDERS it; `--details` maps to detail:'full'. No client-side
|
|
25
|
+
// assembly, no N+1 fanout — the server does the shaping.
|
|
26
|
+
const res = (await hubGet("/orient", opts.details ? { detail: "full" } : {}, cfg));
|
|
27
|
+
const userId = String(res.me?.userId ?? cfg.userId);
|
|
28
|
+
const projList = res.projects ?? [];
|
|
29
|
+
const wsList = res.workspaces ?? [];
|
|
56
30
|
if (opts.json) {
|
|
57
|
-
|
|
58
|
-
"synap graph --entity <id> --depth 2",
|
|
59
|
-
"synap events --entity <id>",
|
|
60
|
-
"synap subscribe --event entity.*",
|
|
61
|
-
"synap context",
|
|
62
|
-
"synap automation list",
|
|
63
|
-
"synap list views --type whiteboard",
|
|
64
|
-
"synap view create --type kanban --profile task",
|
|
65
|
-
"synap proposals list",
|
|
66
|
-
"synap explain",
|
|
67
|
-
];
|
|
68
|
-
console.log(JSON.stringify({ userId, podUrl: cfg.podUrl, workspaceId: cfg.workspaceId, workspaces: wsDetails, me, capabilities }, null, 2));
|
|
31
|
+
console.log(JSON.stringify({ ...res, podUrl: cfg.podUrl, workspaceId: cfg.workspaceId, nextSteps: FLOW.afterOrient() }, null, 2));
|
|
69
32
|
return;
|
|
70
33
|
}
|
|
34
|
+
// Render content rows with console.log (default terminal fg) rather than
|
|
35
|
+
// log.info — log.info wraps every line in chalk.blue, and that blue fg
|
|
36
|
+
// persists through inner bold/dim (they reset weight, not color), flattening
|
|
37
|
+
// the hierarchy. We keep only targeted accents: bold=name, dim=metadata,
|
|
38
|
+
// green ▶ = active.
|
|
71
39
|
log.heading("Pod Orientation");
|
|
72
|
-
log
|
|
73
|
-
log
|
|
74
|
-
|
|
75
|
-
|
|
40
|
+
console.log(` User : ${userId}`);
|
|
41
|
+
console.log(` Pod URL : ${cfg.podUrl}`);
|
|
42
|
+
// The per-Claude-session lens (project + workspace + session) — "where am I".
|
|
43
|
+
// Full ids so they can be pasted into 'synap project use' / 'synap use'.
|
|
44
|
+
const { getClaudeSessionId, resolveActiveLens } = await import("../lib/session-lens.js");
|
|
45
|
+
let activeProjectId;
|
|
46
|
+
if (getClaudeSessionId()) {
|
|
47
|
+
const lens = resolveActiveLens();
|
|
48
|
+
activeProjectId = lens?.projectId ?? undefined;
|
|
49
|
+
const proj = lens?.projectId ?? chalk.dim("none");
|
|
50
|
+
const ws = lens?.workspaceId ?? cfg.workspaceId ?? chalk.dim("pod-wide");
|
|
51
|
+
const sess = lens?.focusSessionId ?? chalk.dim("none");
|
|
52
|
+
console.log(` Lens : ${chalk.dim("project")} ${proj} · ${chalk.dim("ws")} ${ws} · ${chalk.dim("session")} ${sess}`);
|
|
53
|
+
}
|
|
54
|
+
else if (cfg.workspaceId) {
|
|
55
|
+
console.log(` Workspace: ${cfg.workspaceId} ${chalk.dim("(active — use 'synap use <id>' to change)")}`);
|
|
56
|
+
}
|
|
57
|
+
// ── Projects (companies / initiatives) — the primary lens ───────────────
|
|
58
|
+
log.blank();
|
|
59
|
+
log.heading("Projects");
|
|
60
|
+
if (projList.length === 0) {
|
|
61
|
+
log.dim("No projects yet — a project is a company/initiative that ties workspaces together.");
|
|
62
|
+
}
|
|
63
|
+
else {
|
|
64
|
+
for (const p of projList) {
|
|
65
|
+
const isActive = p.id === activeProjectId;
|
|
66
|
+
const marker = isActive ? chalk.green("▶ ") : " ";
|
|
67
|
+
const name = chalk.bold(String(p.name ?? p.id));
|
|
68
|
+
const id = chalk.dim(String(p.id ?? ""));
|
|
69
|
+
const status = p.status ? chalk.dim(String(p.status)) : "";
|
|
70
|
+
const homePart = p.homeWorkspace ? chalk.dim(`· ${p.homeWorkspace}`) : "";
|
|
71
|
+
console.log(` ${marker}${name} ${id} ${status}${homePart ? " " + homePart : ""}`);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
// ── Workspaces (operational domains) ────────────────────────────────────
|
|
76
75
|
log.blank();
|
|
77
76
|
log.heading("Workspaces");
|
|
78
|
-
if (
|
|
77
|
+
if (wsList.length === 0) {
|
|
79
78
|
log.dim("No workspaces found.");
|
|
80
79
|
}
|
|
81
|
-
else {
|
|
82
|
-
for (const
|
|
80
|
+
else if (opts.details) {
|
|
81
|
+
for (const ws of wsList) {
|
|
83
82
|
const isActive = ws.id === cfg.workspaceId;
|
|
84
83
|
const marker = isActive ? chalk.green("▶ ") : " ";
|
|
85
84
|
const name = chalk.bold(String(ws.name ?? ws.id));
|
|
86
|
-
const id = chalk.dim(String(ws.id ?? "")
|
|
87
|
-
const count =
|
|
88
|
-
? chalk.dim(`${
|
|
85
|
+
const id = chalk.dim(String(ws.id ?? ""));
|
|
86
|
+
const count = ws.entityCount > 0
|
|
87
|
+
? chalk.dim(`${ws.entityCount} entities`)
|
|
89
88
|
: chalk.dim("empty");
|
|
90
|
-
log
|
|
89
|
+
console.log(` ${marker}${name} ${id} ${count}`);
|
|
91
90
|
if (ws.description)
|
|
92
91
|
log.dim(` ${String(ws.description)}`);
|
|
93
|
-
if (
|
|
94
|
-
|
|
95
|
-
|
|
92
|
+
if (ws.onboarding?.goal && ws.entityCount === 0) {
|
|
93
|
+
log.dim(` ${chalk.cyan("→ onboard:")} ${String(ws.onboarding.goal)}`);
|
|
94
|
+
}
|
|
95
|
+
const profiles = ws.profiles ?? [];
|
|
96
|
+
if (profiles.length > 0) {
|
|
97
|
+
const slugs = profiles
|
|
98
|
+
.map((p) => p.slug)
|
|
96
99
|
.filter(Boolean)
|
|
97
100
|
.slice(0, 8)
|
|
98
101
|
.join(chalk.dim(", "));
|
|
99
|
-
log.dim(` profiles: ${slugs}${
|
|
102
|
+
log.dim(` profiles: ${slugs}${profiles.length > 8 ? chalk.dim(" …") : ""}`);
|
|
100
103
|
}
|
|
101
104
|
}
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
+
}
|
|
106
|
+
else {
|
|
107
|
+
// Light: name + id + domain (operational-domain label = workspaceSubtype
|
|
108
|
+
// falling back to workspaceType, resolved server-side).
|
|
109
|
+
for (const ws of wsList) {
|
|
110
|
+
const isActive = ws.id === cfg.workspaceId;
|
|
111
|
+
const marker = isActive ? chalk.green("▶ ") : " ";
|
|
112
|
+
const name = chalk.bold(String(ws.name ?? ws.id));
|
|
113
|
+
const id = chalk.dim(String(ws.id ?? ""));
|
|
114
|
+
const domain = ws.domain ? chalk.dim(String(ws.domain)) : "";
|
|
115
|
+
console.log(` ${marker}${name} ${id} ${domain}`);
|
|
105
116
|
}
|
|
117
|
+
log.blank();
|
|
118
|
+
log.dim("Workspaces are operational domains; run 'synap orient --details' for profiles + entity counts.");
|
|
106
119
|
}
|
|
107
|
-
// ── Capabilities block ─────────────────────────────────────────────────
|
|
108
|
-
log.blank();
|
|
109
|
-
log.heading("Capabilities");
|
|
110
|
-
console.log(` ${chalk.cyan("Graph traversal")} synap graph --entity <id> --depth 2`);
|
|
111
|
-
console.log(` ${chalk.cyan("Event chain")} synap events --entity <id>`);
|
|
112
|
-
console.log(` ${chalk.cyan("Subscribe")} synap subscribe --event entity.*`);
|
|
113
|
-
console.log(` ${chalk.cyan("Session context")} synap context`);
|
|
114
|
-
console.log(` ${chalk.cyan("Automations")} synap automation list`);
|
|
115
|
-
console.log(` ${chalk.cyan("Views")} synap list views --type whiteboard · synap view create --type kanban --profile task`);
|
|
116
|
-
console.log(` ${chalk.cyan("Governance")} synap proposals list`);
|
|
117
120
|
log.blank();
|
|
118
|
-
log.dim("
|
|
121
|
+
log.dim("Lenses compose — a project spans workspaces; a workspace spans projects. Omit them to stay pod-wide.");
|
|
122
|
+
renderNextSteps(FLOW.afterOrient());
|
|
119
123
|
}
|
|
120
124
|
catch (e) {
|
|
121
|
-
|
|
125
|
+
renderHubError(e);
|
|
122
126
|
process.exit(1);
|
|
123
127
|
}
|
|
124
128
|
}
|
|
@@ -129,8 +133,7 @@ export async function useWorkspace(workspaceId, opts) {
|
|
|
129
133
|
const userId = await resolveUserId(cfg);
|
|
130
134
|
// Verify the workspace exists and is accessible
|
|
131
135
|
const res = await hubGet("/workspaces", {}, cfg);
|
|
132
|
-
const
|
|
133
|
-
const list = Array.isArray(workspaces) ? workspaces : [];
|
|
136
|
+
const list = unwrapList(res, ["workspaces"]);
|
|
134
137
|
const match = list.find((w) => w.id === workspaceId || String(w.name).toLowerCase() === workspaceId.toLowerCase());
|
|
135
138
|
if (!match) {
|
|
136
139
|
const names = list.map((w) => `${String(w.name ?? w.id)}`).join(", ");
|
|
@@ -139,16 +142,26 @@ export async function useWorkspace(workspaceId, opts) {
|
|
|
139
142
|
log.dim(`Available: ${names}`);
|
|
140
143
|
process.exit(1);
|
|
141
144
|
}
|
|
142
|
-
|
|
143
|
-
|
|
145
|
+
// In a Claude Code session, scope to THIS session's lens (so concurrent
|
|
146
|
+
// sessions can be on different workspaces). Otherwise set the global default.
|
|
147
|
+
const { getClaudeSessionId, writeLens } = await import("../lib/session-lens.js");
|
|
148
|
+
const claudeSession = getClaudeSessionId();
|
|
149
|
+
if (claudeSession) {
|
|
150
|
+
writeLens(claudeSession, { workspaceId: String(match.id) });
|
|
151
|
+
}
|
|
152
|
+
else {
|
|
153
|
+
const { setActiveWorkspaceId } = await import("../lib/pod.js");
|
|
154
|
+
setActiveWorkspaceId(String(match.id));
|
|
155
|
+
}
|
|
144
156
|
if (opts.json) {
|
|
145
|
-
console.log(JSON.stringify({ workspaceId: match.id, name: match.name }, null, 2));
|
|
157
|
+
console.log(JSON.stringify({ workspaceId: match.id, name: match.name, scope: claudeSession ? "session" : "global" }, null, 2));
|
|
146
158
|
return;
|
|
147
159
|
}
|
|
148
|
-
|
|
160
|
+
const scopeNote = claudeSession ? chalk.dim(" (this session)") : "";
|
|
161
|
+
log.success(`Now in workspace: ${chalk.bold(String(match.name ?? match.id))} ${chalk.dim(String(match.id ?? ""))}${scopeNote}`);
|
|
149
162
|
}
|
|
150
163
|
catch (e) {
|
|
151
|
-
|
|
164
|
+
renderHubError(e);
|
|
152
165
|
process.exit(1);
|
|
153
166
|
}
|
|
154
167
|
}
|
|
@@ -157,8 +170,7 @@ export async function listWorkspaces(opts) {
|
|
|
157
170
|
try {
|
|
158
171
|
const cfg = await resolveHubConfig(opts);
|
|
159
172
|
const res = await hubGet("/workspaces", {}, cfg);
|
|
160
|
-
const
|
|
161
|
-
const list = Array.isArray(workspaces) ? workspaces : [];
|
|
173
|
+
const list = unwrapList(res, ["workspaces"]);
|
|
162
174
|
if (opts.json) {
|
|
163
175
|
console.log(JSON.stringify({ workspaces: list }, null, 2));
|
|
164
176
|
return;
|
|
@@ -173,7 +185,7 @@ export async function listWorkspaces(opts) {
|
|
|
173
185
|
}
|
|
174
186
|
}
|
|
175
187
|
catch (e) {
|
|
176
|
-
|
|
188
|
+
renderHubError(e);
|
|
177
189
|
process.exit(1);
|
|
178
190
|
}
|
|
179
191
|
}
|
|
@@ -183,14 +195,23 @@ export async function listEntities(opts) {
|
|
|
183
195
|
const cfg = await resolveHubConfig(opts);
|
|
184
196
|
const userId = await resolveUserId(cfg);
|
|
185
197
|
const limit = parseLimit(opts.limit, 20);
|
|
198
|
+
const workspaceId = opts.workspace ?? cfg.workspaceId;
|
|
199
|
+
// --role needs a workspace to resolve facet scope (see browseEntities);
|
|
200
|
+
// without one the filter is silently dropped and "no entities" would lie.
|
|
201
|
+
if (opts.role && !workspaceId) {
|
|
202
|
+
throw new Error("--role needs an active workspace to resolve the role. Run 'synap use <workspace>' or pass --workspace <id>.");
|
|
203
|
+
}
|
|
186
204
|
const res = await hubGet("/entities", {
|
|
187
205
|
userId,
|
|
188
|
-
workspaceId
|
|
206
|
+
workspaceId,
|
|
189
207
|
profileSlug: opts.profile,
|
|
208
|
+
// Browse-by-role: the list route resolves facet scope from the
|
|
209
|
+
// `workspaceId` QUERY PARAM (already threaded above), not the
|
|
210
|
+
// X-Workspace-Id header — verified against the live pod.
|
|
211
|
+
facetSlug: opts.role,
|
|
190
212
|
limit,
|
|
191
213
|
}, cfg);
|
|
192
|
-
const
|
|
193
|
-
const list = Array.isArray(entities) ? entities : [];
|
|
214
|
+
const list = unwrapList(res, ["entities"]);
|
|
194
215
|
if (opts.json) {
|
|
195
216
|
console.log(JSON.stringify({ entities: list, count: list.length, limit, truncated: list.length === limit }, null, 2));
|
|
196
217
|
return;
|
|
@@ -206,8 +227,7 @@ export async function listEntities(opts) {
|
|
|
206
227
|
workspaceId: opts.workspace ?? cfg.workspaceId,
|
|
207
228
|
type: opts.profile,
|
|
208
229
|
}, cfg);
|
|
209
|
-
const views = viewsRes
|
|
210
|
-
?? (Array.isArray(viewsRes) ? viewsRes : []);
|
|
230
|
+
const views = unwrapList(viewsRes, ["views"]);
|
|
211
231
|
if (views.length > 0) {
|
|
212
232
|
log.blank();
|
|
213
233
|
log.info(`'${opts.profile}' is a ${chalk.bold("view type")}, not an entity profile — found ${views.length} view${views.length !== 1 ? "s" : ""}.`);
|
|
@@ -235,7 +255,7 @@ export async function listEntities(opts) {
|
|
|
235
255
|
}
|
|
236
256
|
}
|
|
237
257
|
catch (e) {
|
|
238
|
-
|
|
258
|
+
renderHubError(e);
|
|
239
259
|
process.exit(1);
|
|
240
260
|
}
|
|
241
261
|
}
|
|
@@ -263,64 +283,7 @@ export async function getEntity(id, opts) {
|
|
|
263
283
|
}
|
|
264
284
|
}
|
|
265
285
|
catch (e) {
|
|
266
|
-
|
|
267
|
-
process.exit(1);
|
|
268
|
-
}
|
|
269
|
-
}
|
|
270
|
-
// ─── noteData ─────────────────────────────────────────────────────────────────
|
|
271
|
-
export async function noteData(text, opts) {
|
|
272
|
-
try {
|
|
273
|
-
const cfg = await resolveHubConfig(opts);
|
|
274
|
-
const userId = await resolveUserId(cfg);
|
|
275
|
-
// A `note` is the human raw-inbox primitive ("dump now, structure later") —
|
|
276
|
-
// it lands in the active workspace, NOT a private agent-memory ws (that lane
|
|
277
|
-
// was removed). The AI should never write a note: structuring is its job, so
|
|
278
|
-
// it uses `synap capture` (structured) instead.
|
|
279
|
-
const workspaceId = cfg.workspaceId;
|
|
280
|
-
if (!workspaceId) {
|
|
281
|
-
console.error(chalk.red("No workspace set. Run: synap use <workspace-id>"));
|
|
282
|
-
process.exit(1);
|
|
283
|
-
}
|
|
284
|
-
const res = await hubPost("/entities", {
|
|
285
|
-
userId,
|
|
286
|
-
profileSlug: "note",
|
|
287
|
-
title: text.slice(0, 200),
|
|
288
|
-
workspaceId,
|
|
289
|
-
// The `note` profile requires a `content` property — carry the full text
|
|
290
|
-
// (title is truncated). Without this the hub rejects the write (HTTP 500).
|
|
291
|
-
properties: {
|
|
292
|
-
content: text,
|
|
293
|
-
...(opts.context ? { sourceEntityId: opts.context } : {}),
|
|
294
|
-
},
|
|
295
|
-
}, cfg);
|
|
296
|
-
const isProposed = res.status === "proposed" || Boolean(res.proposalId);
|
|
297
|
-
const report = {
|
|
298
|
-
lane: "work",
|
|
299
|
-
workspaceId,
|
|
300
|
-
workspaceName: await resolveWorkspaceName(workspaceId, cfg),
|
|
301
|
-
governance: isProposed ? "proposed" : "auto",
|
|
302
|
-
};
|
|
303
|
-
if (opts.json) {
|
|
304
|
-
if (isProposed) {
|
|
305
|
-
console.log(JSON.stringify({ proposed: true, proposalId: res.proposalId ?? res.id, ...laneJsonFields(report) }, null, 2));
|
|
306
|
-
}
|
|
307
|
-
else {
|
|
308
|
-
console.log(JSON.stringify({ id: res.id, stored: true, ...laneJsonFields(report) }, null, 2));
|
|
309
|
-
}
|
|
310
|
-
return;
|
|
311
|
-
}
|
|
312
|
-
if (isProposed) {
|
|
313
|
-
log.warn(`Queued for approval (proposal: ${String(res.proposalId ?? "")})`);
|
|
314
|
-
if (res.reviewUrl)
|
|
315
|
-
log.dim(` Review: ${String(res.reviewUrl)}`);
|
|
316
|
-
}
|
|
317
|
-
else {
|
|
318
|
-
log.success(`Note saved: "${text.slice(0, 80)}" ${chalk.dim(String(res.id ?? "").slice(0, 8))}`);
|
|
319
|
-
}
|
|
320
|
-
console.log(" " + formatLaneLine(report));
|
|
321
|
-
}
|
|
322
|
-
catch (e) {
|
|
323
|
-
console.error(chalk.red("Error: " + e.message));
|
|
286
|
+
renderHubError(e);
|
|
324
287
|
process.exit(1);
|
|
325
288
|
}
|
|
326
289
|
}
|
|
@@ -358,16 +321,71 @@ function formatAskItem(substrate, item) {
|
|
|
358
321
|
: "";
|
|
359
322
|
return `${title} ${chalk.dim(`[${type}]`)} ${chalk.dim(id)}${snippet}`;
|
|
360
323
|
}
|
|
324
|
+
/**
|
|
325
|
+
* Render the A/B ranker diagnostic: baseline vs Horizon top-N side-by-side,
|
|
326
|
+
* then the diff. Comparison is by RANK POSITION (not score magnitude) — the two
|
|
327
|
+
* strategies score on different scales, so only the ordering is comparable.
|
|
328
|
+
*/
|
|
329
|
+
function renderComparison(query, comparison) {
|
|
330
|
+
if (!comparison) {
|
|
331
|
+
log.dim(`"${query}" → no ranker comparison returned (semantic pool empty?).`);
|
|
332
|
+
return;
|
|
333
|
+
}
|
|
334
|
+
const { baseline, horizon, diff } = comparison;
|
|
335
|
+
const n = Math.max(baseline.length, horizon.length);
|
|
336
|
+
log.dim(`"${query}" → A/B ranker comparison (by RANK, not score magnitude)`);
|
|
337
|
+
log.blank();
|
|
338
|
+
// Side-by-side: rank · title for each column.
|
|
339
|
+
const trunc = (s, w) => (s.length > w ? s.slice(0, w - 1) + "…" : s).padEnd(w, " ");
|
|
340
|
+
const COL = 38;
|
|
341
|
+
log.info(" " + chalk.bold("BASELINE".padEnd(COL + 5)) + chalk.bold("HORIZON"));
|
|
342
|
+
for (let i = 0; i < n; i++) {
|
|
343
|
+
const b = baseline[i];
|
|
344
|
+
const h = horizon[i];
|
|
345
|
+
const bCell = b ? `${chalk.dim(`#${b.rank}`)} ${trunc(b.title, COL)}` : "".padEnd(COL + 4);
|
|
346
|
+
const hCell = h ? `${chalk.dim(`#${h.rank}`)} ${trunc(h.title, COL)}` : "";
|
|
347
|
+
log.info(" " + bCell + " " + hCell);
|
|
348
|
+
}
|
|
349
|
+
log.blank();
|
|
350
|
+
// Diff — overlap@N + items that moved rank between the two strategies.
|
|
351
|
+
const topN = Math.max(baseline.length, horizon.length);
|
|
352
|
+
log.info(chalk.bold("DIFF") +
|
|
353
|
+
chalk.dim(` · overlap@${topN}: ${diff.overlapAtN}/${topN} shared ids`));
|
|
354
|
+
if (diff.moved.length === 0) {
|
|
355
|
+
log.dim(" No shared item changed rank between the two rankers.");
|
|
356
|
+
}
|
|
357
|
+
else {
|
|
358
|
+
for (const m of diff.moved) {
|
|
359
|
+
const dir = m.horizonRank < m.baselineRank ? chalk.green("↑") : chalk.red("↓");
|
|
360
|
+
log.info(` ${dir} ${m.title} ${chalk.dim(`(baseline #${m.baselineRank} → horizon #${m.horizonRank})`)}`);
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
log.blank();
|
|
364
|
+
}
|
|
361
365
|
export async function askKnowledge(query, opts) {
|
|
362
366
|
try {
|
|
363
367
|
const cfg = await resolveHubConfig(opts);
|
|
364
368
|
const limit = parseLimit(opts.limit, 10);
|
|
365
369
|
const workspaceId = opts.workspace ?? cfg.workspaceId;
|
|
366
|
-
const
|
|
370
|
+
const sessionId = opts.session ? readActiveSessionId() : undefined;
|
|
371
|
+
const res = (await hubPost("/knowledge/ask", {
|
|
372
|
+
query,
|
|
373
|
+
...(workspaceId ? { workspaceId } : {}),
|
|
374
|
+
...(sessionId ? { sessionId } : {}),
|
|
375
|
+
limit,
|
|
376
|
+
...(opts.compare ? { compare: true } : {}),
|
|
377
|
+
}, cfg));
|
|
367
378
|
if (opts.json) {
|
|
368
379
|
console.log(JSON.stringify(res, null, 2));
|
|
369
380
|
return;
|
|
370
381
|
}
|
|
382
|
+
// A/B ranker diagnostic — render the comparison and STOP. This is a
|
|
383
|
+
// ranking diff (baseline vs Horizon on the same candidate pool), not the
|
|
384
|
+
// normal answer, so it replaces the substrate listing when requested.
|
|
385
|
+
if (opts.compare) {
|
|
386
|
+
renderComparison(query, res.comparison);
|
|
387
|
+
return;
|
|
388
|
+
}
|
|
371
389
|
const routed = (res.routedTo ?? []).join(", ");
|
|
372
390
|
const verdict = res.verdict ? chalk.dim(` · ${res.verdict}`) : "";
|
|
373
391
|
// Honest routing: if the query's cue suggested one substrate but another
|
|
@@ -405,12 +423,40 @@ export async function askKnowledge(query, opts) {
|
|
|
405
423
|
}
|
|
406
424
|
log.blank();
|
|
407
425
|
}
|
|
426
|
+
// res.degraded was only ever checked as a boolean (anyErrored) above —
|
|
427
|
+
// surface which substrate(s) actually degraded, verbatim, so the answer's
|
|
428
|
+
// incompleteness is visible rather than just its existence.
|
|
429
|
+
if (res.degraded && res.degraded.length > 0) {
|
|
430
|
+
log.dim(`Degraded: ${res.degraded.join(", ")}`);
|
|
431
|
+
}
|
|
408
432
|
}
|
|
409
433
|
catch (e) {
|
|
410
|
-
|
|
434
|
+
renderHubError(e);
|
|
411
435
|
process.exit(1);
|
|
412
436
|
}
|
|
413
437
|
}
|
|
438
|
+
const refLabel = (r) => `${String(r.name ?? r.id ?? "?")}${r.profileSlug ? ` [${r.profileSlug}]` : ""}`;
|
|
439
|
+
/** Print 1-3 dim graph-impact lines for a create response. No-op if absent. */
|
|
440
|
+
function reportResolution(res) {
|
|
441
|
+
const resolution = res.resolution;
|
|
442
|
+
if (!resolution)
|
|
443
|
+
return;
|
|
444
|
+
const existing = resolution.existingSameProfile;
|
|
445
|
+
if (existing) {
|
|
446
|
+
log.dim(`⚠ an entity named "${String(existing.name ?? "?")}" already exists as profile ${String(existing.profileSlug ?? "?")} (${String(existing.id ?? "?").slice(0, 8)}) — consider updating it instead of duplicating`);
|
|
447
|
+
}
|
|
448
|
+
const autoConnected = resolution.autoConnected ?? [];
|
|
449
|
+
if (autoConnected.length > 0) {
|
|
450
|
+
const names = autoConnected.map(refLabel).join(", ");
|
|
451
|
+
log.dim(`→ auto-linked to ${autoConnected.length} existing same-name entit${autoConnected.length === 1 ? "y" : "ies"}: ${names}`);
|
|
452
|
+
}
|
|
453
|
+
// suggestions beyond what was already auto-connected
|
|
454
|
+
const autoIds = new Set(autoConnected.map((r) => r.id).filter(Boolean));
|
|
455
|
+
const suggestions = (resolution.suggestions ?? []).filter((s) => !autoIds.has(s.id));
|
|
456
|
+
if (suggestions.length > 0) {
|
|
457
|
+
log.dim(`· you may want to link: ${suggestions.map(refLabel).join(", ")}`);
|
|
458
|
+
}
|
|
459
|
+
}
|
|
414
460
|
// ─── createEntity ─────────────────────────────────────────────────────────────
|
|
415
461
|
export async function createEntity(opts) {
|
|
416
462
|
try {
|
|
@@ -425,24 +471,20 @@ export async function createEntity(opts) {
|
|
|
425
471
|
properties,
|
|
426
472
|
}, cfg);
|
|
427
473
|
const entity = res;
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
}
|
|
440
|
-
else {
|
|
441
|
-
log.success(`Created: ${opts.name} ${chalk.dim(String(entity.id ?? "").slice(0, 8))}`);
|
|
442
|
-
}
|
|
474
|
+
await reportWrite(entity, {
|
|
475
|
+
label: `Created: ${opts.name}`,
|
|
476
|
+
lane: "work",
|
|
477
|
+
workspaceId: opts.workspace ?? cfg.workspaceId,
|
|
478
|
+
cfg,
|
|
479
|
+
json: opts.json,
|
|
480
|
+
});
|
|
481
|
+
// Graph-impact feedback — human output only (the `--json` path already
|
|
482
|
+
// passed the raw response, including `resolution`, through reportWrite).
|
|
483
|
+
if (!opts.json)
|
|
484
|
+
reportResolution(entity);
|
|
443
485
|
}
|
|
444
486
|
catch (e) {
|
|
445
|
-
|
|
487
|
+
renderHubError(e);
|
|
446
488
|
process.exit(1);
|
|
447
489
|
}
|
|
448
490
|
}
|
|
@@ -456,8 +498,8 @@ export async function listProfiles(opts) {
|
|
|
456
498
|
console.error(chalk.red("No workspace set. Run: synap use <workspace-id>"));
|
|
457
499
|
process.exit(1);
|
|
458
500
|
}
|
|
459
|
-
const res = await hubGet("/profiles", { userId, workspaceId }, cfg);
|
|
460
|
-
const profiles = (res
|
|
501
|
+
const res = await hubGet("/profiles", { userId, workspaceId, ...(opts.json ? { detail: "full" } : {}) }, cfg);
|
|
502
|
+
const profiles = unwrapList(res, ["profiles"]);
|
|
461
503
|
if (opts.json) {
|
|
462
504
|
console.log(JSON.stringify(profiles, null, 2));
|
|
463
505
|
return;
|
|
@@ -470,11 +512,18 @@ export async function listProfiles(opts) {
|
|
|
470
512
|
for (const p of profiles) {
|
|
471
513
|
const scope = String(p.entityScope ?? "workspace");
|
|
472
514
|
const desc = p.description ? chalk.dim(` — ${String(p.description).slice(0, 60)}`) : "";
|
|
473
|
-
|
|
515
|
+
// A role-profile (client, partner, …) is a hat an existing entity wears
|
|
516
|
+
// via `synap facet attach` — never created as its own entity. Label it
|
|
517
|
+
// distinctly so it's never confused with a primary kind.
|
|
518
|
+
const applicableKinds = p.applicableKinds;
|
|
519
|
+
const kindLabel = p.profileKind === "role"
|
|
520
|
+
? chalk.magenta(`[Role${applicableKinds?.length ? ` of ${applicableKinds.join("/")}` : ""}]`)
|
|
521
|
+
: chalk.green("[Kind]");
|
|
522
|
+
log.info(`${chalk.bold(String(p.slug ?? ""))} ${kindLabel} ${chalk.dim(scope)}${desc}`);
|
|
474
523
|
}
|
|
475
524
|
}
|
|
476
525
|
catch (e) {
|
|
477
|
-
|
|
526
|
+
renderHubError(e);
|
|
478
527
|
process.exit(1);
|
|
479
528
|
}
|
|
480
529
|
}
|
|
@@ -491,14 +540,16 @@ export async function createRelation(opts) {
|
|
|
491
540
|
type: opts.type,
|
|
492
541
|
}, cfg);
|
|
493
542
|
const relation = res;
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
543
|
+
await reportWrite(relation, {
|
|
544
|
+
label: `Relation: ${opts.type} (${opts.source} → ${opts.target})`,
|
|
545
|
+
lane: "work",
|
|
546
|
+
workspaceId: opts.workspace ?? cfg.workspaceId,
|
|
547
|
+
cfg,
|
|
548
|
+
json: opts.json,
|
|
549
|
+
});
|
|
499
550
|
}
|
|
500
551
|
catch (e) {
|
|
501
|
-
|
|
552
|
+
renderHubError(e);
|
|
502
553
|
process.exit(1);
|
|
503
554
|
}
|
|
504
555
|
}
|
|
@@ -521,9 +572,15 @@ export async function updateEntity(id, opts) {
|
|
|
521
572
|
return;
|
|
522
573
|
}
|
|
523
574
|
log.success(`Updated: ${id}`);
|
|
575
|
+
// Graph-impact feedback — shallow immediate neighbors the edit may touch.
|
|
576
|
+
// Additive + graceful: absent on older backends, so output is unchanged.
|
|
577
|
+
const impact = entity.impact;
|
|
578
|
+
if (Array.isArray(impact) && impact.length > 0) {
|
|
579
|
+
log.dim(`→ ${impact.length} connected entit${impact.length === 1 ? "y" : "ies"} may be affected: ${impact.map(refLabel).join(", ")}`);
|
|
580
|
+
}
|
|
524
581
|
}
|
|
525
582
|
catch (e) {
|
|
526
|
-
|
|
583
|
+
renderHubError(e);
|
|
527
584
|
process.exit(1);
|
|
528
585
|
}
|
|
529
586
|
}
|