@khorsheed/dsh-capability-catalog 0.1.98 → 0.1.99

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.
Files changed (46) hide show
  1. package/CHANGELOG.md +13 -0
  2. package/README.en.md +31 -7
  3. package/README.i18n.yaml +2 -2
  4. package/README.md +31 -7
  5. package/cordis.patch.yml +1 -1
  6. package/lib/client.js +14792 -904
  7. package/lib/index.js +748 -263
  8. package/lib/typert.host.js +614 -295
  9. package/lib/typert.remote-client.d.ts +27 -4
  10. package/lib/typert.remote-client.js +599 -288
  11. package/lib/types/client/CapabilityCatalogCard.js +20 -5
  12. package/lib/types/client/SkillDetailModal.d.ts +13 -5
  13. package/lib/types/client/SkillDetailModal.js +9 -3
  14. package/lib/types/client/locales.d.ts +0 -4
  15. package/lib/types/client/locales.js +4 -8
  16. package/lib/types/envHint.d.ts +7 -1
  17. package/lib/types/envHint.js +52 -18
  18. package/lib/types/evidence.d.ts +142 -0
  19. package/lib/types/evidence.js +179 -0
  20. package/lib/types/frontmatter.d.ts +78 -0
  21. package/lib/types/frontmatter.js +186 -0
  22. package/lib/types/import.js +10 -19
  23. package/lib/types/index.d.ts +8 -3
  24. package/lib/types/index.js +21 -50
  25. package/lib/types/mcpStore.d.ts +6 -8
  26. package/lib/types/mcpStore.js +18 -43
  27. package/lib/types/mcps.d.ts +1 -6
  28. package/lib/types/mcps.js +0 -9
  29. package/lib/types/namespace.d.ts +2 -3
  30. package/lib/types/namespace.js +2 -3
  31. package/lib/types/remote.d.ts +11 -2
  32. package/lib/types/remote.js +4 -1
  33. package/lib/types/scoped-delivery.d.ts +36 -24
  34. package/lib/types/scoped-delivery.js +136 -100
  35. package/lib/types/scoped-edits.js +2 -1
  36. package/lib/types/shellEnv.d.ts +8 -1
  37. package/lib/types/shellEnv.js +37 -16
  38. package/lib/types/skills.d.ts +41 -0
  39. package/lib/types/skills.js +51 -9
  40. package/lib/types/tool-face.d.ts +68 -0
  41. package/lib/types/tool-face.js +82 -0
  42. package/lib/types/types.d.ts +40 -19
  43. package/package.json +20 -18
  44. package/lib/invariant.js +0 -25
  45. package/lib/types/invariant.d.ts +0 -16
  46. package/lib/types/invariant.js +0 -23
@@ -0,0 +1,68 @@
1
+ /**
2
+ * Reading the tools side of the capability face: the visible schemas in a
3
+ * scope, the author-declared origin tags behind them, and the MCP server
4
+ * names the `mcp__` prefixes imply.
5
+ *
6
+ * Extracted from the service so the Remote verbs and the pure-data evidence
7
+ * producer (`evidence.ts`) read the tools registry through ONE
8
+ * implementation — the digest parity between them is by construction, not by
9
+ * two copies agreeing today. Nothing here catches a `schemas()` failure:
10
+ * whether a failed read rejects the call (the Remote verbs' choice) or is
11
+ * recorded as an unavailable section (the evidence producer's choice) is the
12
+ * caller's policy.
13
+ * @module @khorsheed/dsh-capability-catalog/tool-face
14
+ */
15
+ import { type ToolOrigin } from './tool-origin.ts';
16
+ import type { CatalogJsonValue } from './types.ts';
17
+ /** The slice of the tools registry the catalog reads (optional). */
18
+ export interface CatalogToolsSlice {
19
+ schemas: (scope?: unknown) => readonly ToolSchemaLike[];
20
+ get?: (name: string, scope?: unknown) => object | undefined;
21
+ }
22
+ /** Minimal ToolSchema shape (model-facing name/description/parameters). */
23
+ export interface ToolSchemaLike {
24
+ readonly name: string;
25
+ readonly description?: string;
26
+ readonly parameters?: CatalogJsonValue;
27
+ }
28
+ /** The tools side of one reading position, collected once. */
29
+ export interface ToolFaceCollection {
30
+ /** The visible tool schemas in the scope (the set the model sees). */
31
+ readonly schemas: readonly ToolSchemaLike[];
32
+ /** tool name → author-declared origin, where the tag could be read and validated. */
33
+ readonly origins: ReadonlyMap<string, ToolOrigin>;
34
+ /** MCP server names derived from the `mcp__`-prefixed visible tools. */
35
+ readonly mcpServerNames: readonly string[];
36
+ /**
37
+ * Visible tools whose origin tag could not be read (`get` absent from the
38
+ * slice, returned undefined, or carried an invalid tag) and which therefore
39
+ * fall back to heuristic channel attribution. Tool NAMES only — never error
40
+ * text, which may carry paths.
41
+ */
42
+ readonly untaggedOrigins: readonly string[];
43
+ }
44
+ /**
45
+ * The visible tool schemas in a scope, or the global layer when no scope is
46
+ * given; an empty list when the registry is absent.
47
+ */
48
+ export declare function toolSchemasFacing(tools: CatalogToolsSlice | undefined, scope: unknown): readonly ToolSchemaLike[];
49
+ /**
50
+ * The origin tags behind the given schemas, read via `tools.get(name)` so the
51
+ * `Symbol.for('dsh.tool.origin')` tag on the retained definition survives
52
+ * (the system-prompt assembly strips it, but `get()` returns the full
53
+ * definition). A schema the registry cannot hand back contributes no tag —
54
+ * the tool falls back to heuristics and is named in `untaggedOrigins`.
55
+ */
56
+ export declare function toolOriginsFacing(tools: CatalogToolsSlice | undefined, schemas: readonly ToolSchemaLike[], scope: unknown, warn: (message: string) => void): {
57
+ readonly origins: ReadonlyMap<string, ToolOrigin>;
58
+ readonly untaggedOrigins: readonly string[];
59
+ };
60
+ /** MCP server names from live `mcp__`-prefixed tools (prefix-derived baseline). */
61
+ export declare function mcpServerNamesFacing(schemas: readonly ToolSchemaLike[]): readonly string[];
62
+ /**
63
+ * Collect the whole tools side of one reading position with ONE `schemas()`
64
+ * call, so the rows, the origin tags and the MCP names cannot disagree about
65
+ * which registry state they read.
66
+ */
67
+ export declare function collectToolFace(tools: CatalogToolsSlice | undefined, scope: unknown, warn: (message: string) => void): ToolFaceCollection;
68
+ //# sourceMappingURL=tool-face.d.ts.map
@@ -0,0 +1,82 @@
1
+ /**
2
+ * Reading the tools side of the capability face: the visible schemas in a
3
+ * scope, the author-declared origin tags behind them, and the MCP server
4
+ * names the `mcp__` prefixes imply.
5
+ *
6
+ * Extracted from the service so the Remote verbs and the pure-data evidence
7
+ * producer (`evidence.ts`) read the tools registry through ONE
8
+ * implementation — the digest parity between them is by construction, not by
9
+ * two copies agreeing today. Nothing here catches a `schemas()` failure:
10
+ * whether a failed read rejects the call (the Remote verbs' choice) or is
11
+ * recorded as an unavailable section (the evidence producer's choice) is the
12
+ * caller's policy.
13
+ * @module @khorsheed/dsh-capability-catalog/tool-face
14
+ */
15
+ import { MCP_TOOL_PREFIX } from './channels.js';
16
+ import { toolOrigin, isValidOrigin } from './tool-origin.js';
17
+ /**
18
+ * The visible tool schemas in a scope, or the global layer when no scope is
19
+ * given; an empty list when the registry is absent.
20
+ */
21
+ export function toolSchemasFacing(tools, scope) {
22
+ if (tools?.schemas === undefined)
23
+ return [];
24
+ return scope === undefined ? tools.schemas() : tools.schemas(scope);
25
+ }
26
+ /**
27
+ * The origin tags behind the given schemas, read via `tools.get(name)` so the
28
+ * `Symbol.for('dsh.tool.origin')` tag on the retained definition survives
29
+ * (the system-prompt assembly strips it, but `get()` returns the full
30
+ * definition). A schema the registry cannot hand back contributes no tag —
31
+ * the tool falls back to heuristics and is named in `untaggedOrigins`.
32
+ */
33
+ export function toolOriginsFacing(tools, schemas, scope, warn) {
34
+ const out = new Map();
35
+ const untagged = [];
36
+ if (tools?.get === undefined)
37
+ return { origins: out, untaggedOrigins: untagged };
38
+ for (const schema of schemas) {
39
+ const def = scope === undefined ? tools.get(schema.name) : tools.get(schema.name, scope);
40
+ if (def === undefined) {
41
+ // `schemas()` and `get()` disagree for this scope — the author's origin
42
+ // tag (if any) cannot be read, so the tool falls back to heuristics.
43
+ warn(`capability-catalog: tool "${schema.name}" is visible but ctx.tools.get() is undefined in this scope — its origin tag cannot be read; it will be classified by heuristics`);
44
+ untagged.push(schema.name);
45
+ continue;
46
+ }
47
+ const origin = toolOrigin(def);
48
+ if (origin !== undefined) {
49
+ if (!isValidOrigin(origin)) {
50
+ warn(`capability-catalog: tool "${schema.name}" origin channel "${String(origin.channel)}" is not a known channel (plugin/builtin/mcp) — ignoring the tag, falling back to heuristics`);
51
+ untagged.push(schema.name);
52
+ continue;
53
+ }
54
+ out.set(schema.name, origin);
55
+ }
56
+ }
57
+ return { origins: out, untaggedOrigins: untagged };
58
+ }
59
+ /** MCP server names from live `mcp__`-prefixed tools (prefix-derived baseline). */
60
+ export function mcpServerNamesFacing(schemas) {
61
+ const names = [];
62
+ for (const schema of schemas) {
63
+ if (!schema.name.startsWith(MCP_TOOL_PREFIX))
64
+ continue;
65
+ const rest = schema.name.slice(MCP_TOOL_PREFIX.length);
66
+ const sep = rest.indexOf('__');
67
+ const server = sep > 0 ? rest.slice(0, sep) : rest;
68
+ if (server.length > 0 && !names.includes(server))
69
+ names.push(server);
70
+ }
71
+ return names;
72
+ }
73
+ /**
74
+ * Collect the whole tools side of one reading position with ONE `schemas()`
75
+ * call, so the rows, the origin tags and the MCP names cannot disagree about
76
+ * which registry state they read.
77
+ */
78
+ export function collectToolFace(tools, scope, warn) {
79
+ const schemas = toolSchemasFacing(tools, scope);
80
+ const { origins, untaggedOrigins } = toolOriginsFacing(tools, schemas, scope, warn);
81
+ return { schemas, origins, mcpServerNames: mcpServerNamesFacing(schemas), untaggedOrigins };
82
+ }
@@ -120,6 +120,36 @@ export interface CatalogChannelSummary {
120
120
  readonly channel: string;
121
121
  readonly count: number;
122
122
  }
123
+ /**
124
+ * Evidence-grade completeness of ONE snapshot section's measurement.
125
+ *
126
+ * The three states are a contract about what the rows may be read as:
127
+ *
128
+ * - `complete` — the section was measured and everything found is included.
129
+ * Zero rows is complete-with-zero (scanned, nothing there), which is
130
+ * distinguishable from a failure.
131
+ * - `partial` — some sources failed, so the rows are a SUBSET. `reason`
132
+ * names the failed source class (never secret content, never raw error
133
+ * text, which may carry paths).
134
+ * - `unavailable` — the section could not be measured at all (the service
135
+ * is not installed, or the read failed, or permission was denied). The
136
+ * rows carry no meaning.
137
+ *
138
+ * A consumer MUST treat `partial` and `unavailable` as "not verified" —
139
+ * never as complete, and never as "the section is empty".
140
+ */
141
+ export interface CatalogSectionCompleteness {
142
+ readonly state: 'complete' | 'partial' | 'unavailable';
143
+ /** Why the section is not complete; absent when it is. */
144
+ readonly reason?: string;
145
+ }
146
+ /** Per-section completeness of a snapshot, keyed by the section names the snapshot carries. */
147
+ export interface CatalogSnapshotCompleteness {
148
+ readonly skills?: CatalogSectionCompleteness;
149
+ readonly tools?: CatalogSectionCompleteness;
150
+ readonly mcpServers?: CatalogSectionCompleteness;
151
+ readonly channels?: CatalogSectionCompleteness;
152
+ }
123
153
  /** Full catalog snapshot. */
124
154
  export interface CapabilityCatalogSnapshot {
125
155
  readonly skills: readonly CatalogSkillRow[];
@@ -134,6 +164,13 @@ export interface CapabilityCatalogSnapshot {
134
164
  readonly sha?: string;
135
165
  /** The agent preset this snapshot was taken under; absent when none resolved. */
136
166
  readonly preset?: string;
167
+ /**
168
+ * Evidence-grade per-section completeness, attached only by evidence
169
+ * production (the Remote listing/fingerprint verbs never set it, so their
170
+ * wire form is unchanged). Like `sha`, it is NOT part of the canonical
171
+ * form `hashOf` digests.
172
+ */
173
+ readonly completeness?: CatalogSnapshotCompleteness;
137
174
  }
138
175
  /** Fresh detail of one skill (body + metadata), loaded on demand. */
139
176
  export interface CatalogSkillDetail {
@@ -152,7 +189,9 @@ export interface CatalogSkillDetail {
152
189
  /** Declared credentials + their configured state (metadata.credentials only). */
153
190
  readonly credentials?: readonly CatalogCredentialState[];
154
191
  /** Env-var references detected in the skill body (read-only, informational —
155
- * typically provided by the runtime/caller, NOT user-configurable here). */
192
+ * typically provided by the runtime/caller, NOT user-configurable here). A key
193
+ * already declared in metadata.credentials is excluded — it renders in the
194
+ * credential form instead. */
156
195
  readonly environmentRefs?: readonly string[];
157
196
  /** Bundle-relative file paths (SKILL.md + scripts/assets/references) for a directory side. */
158
197
  readonly files?: readonly string[];
@@ -294,22 +333,4 @@ export interface CatalogCredentialSetRequest {
294
333
  readonly key: string;
295
334
  readonly value: string;
296
335
  }
297
- /** Remote surface the browser card binds through. */
298
- export interface CapabilityCatalogRemote {
299
- readonly snapshot: (workdir?: string) => Promise<CapabilityCatalogSnapshot>;
300
- /** The capability face of one preset, with its `sha` (see the host half). */
301
- readonly snapshotFor: (presetId?: string, workdir?: string) => Promise<CapabilityCatalogSnapshot>;
302
- /** The capability face of one mode as a LISTING (no fingerprint work). */
303
- readonly snapshotAt: (presetId?: string, workdir?: string) => Promise<CapabilityCatalogSnapshot>;
304
- /** Every mode's face in one call, for the cross-mode comparison view. */
305
- readonly modeFaces: (workdir?: string) => Promise<readonly CatalogModeFace[]>;
306
- /** Read one capability at a mode's scope, or the default mode when omitted. */
307
- readonly detail: (name: string, workdir?: string, presetId?: string) => Promise<CatalogSkillDetail | undefined>;
308
- readonly readSkillFile: (name: string, filePath: string, workdir?: string, presetId?: string) => Promise<CatalogSkillFileRead | undefined>;
309
- readonly listDirSkills: (dirPath: string) => Promise<readonly CatalogDirSkillInfo[]>;
310
- readonly setCredential: (request: CatalogCredentialSetRequest) => Promise<boolean>;
311
- readonly addSkill: (request: CatalogAddSkillRequest) => Promise<CatalogAddSkillResult>;
312
- readonly deleteSkill: (name: string, workdir?: string, presetId?: string) => Promise<CatalogDeleteSkillResult>;
313
- readonly pickDirectory: () => Promise<string | null>;
314
- }
315
336
  //# sourceMappingURL=types.d.ts.map
package/package.json CHANGED
@@ -9,7 +9,7 @@
9
9
  "catalog",
10
10
  "skills"
11
11
  ],
12
- "version": "0.1.98",
12
+ "version": "0.1.99",
13
13
  "type": "module",
14
14
  "main": "lib/index.js",
15
15
  "types": "lib/types/index.d.ts",
@@ -18,10 +18,6 @@
18
18
  "types": "./lib/types/index.d.ts",
19
19
  "default": "./lib/index.js"
20
20
  },
21
- "./invariant": {
22
- "types": "./lib/types/invariant.d.ts",
23
- "default": "./lib/invariant.js"
24
- },
25
21
  "./client": {
26
22
  "types": "./lib/types/client/index.d.ts",
27
23
  "default": "./lib/client.js"
@@ -58,26 +54,32 @@
58
54
  "compat": {
59
55
  "minHost": "0.1.5-rc.1",
60
56
  "notes": "0.1.5-rc.1 full-line boot-verified 2026-09-25 (42 packages including capture) through the three compat layers: preset-registry dual-name probe, dual-shape typert codecs, and typert faces carrying zod@4; 0.1.7-rc.2 is the 3080 production-verified line",
61
- "verifiedHost": "0.1.7-rc.2"
62
- }
57
+ "verifiedHost": "0.2.1-rc.1"
58
+ },
59
+ "runtimeDependencies": [
60
+ "js-yaml"
61
+ ]
63
62
  },
64
63
  "license": "MIT",
64
+ "engines": {
65
+ "dsh": ">=0.1.5-rc.1 <0.3.0-0"
66
+ },
65
67
  "dependencies": {
68
+ "js-yaml": "^4.3.1",
66
69
  "zod": "^4.4.3"
67
70
  },
68
71
  "peerDependencies": {
69
72
  "@deepseek-ai/cordis": "^4.0.1",
70
- "@deepseek-ai/dsh-agent-presets": "^0.1.0-rc.6 || ^0.2.0-rc.1",
71
- "@deepseek-ai/dsh-client-locale": "^0.1.0-rc.6 || ^0.2.0-rc.1",
72
- "@deepseek-ai/dsh-client-ui-primitives": "^0.1.0-rc.6 || ^0.2.0-rc.1",
73
- "@deepseek-ai/dsh-client-ui-settings": "^0.1.0-rc.6 || ^0.2.0-rc.1",
74
- "@deepseek-ai/dsh-client-ui-settings-plugins": "^0.1.0-rc.6 || ^0.2.0-rc.1",
75
- "@deepseek-ai/dsh-client-ui-slots": "^0.1.0-rc.6 || ^0.2.0-rc.1",
76
- "@deepseek-ai/dsh-credentials": "^0.1.0-rc.6 || ^0.2.0-rc.1",
77
- "@deepseek-ai/dsh-invariants": "^0.1.0-rc.6 || ^0.2.0-rc.1",
78
- "@deepseek-ai/dsh-skill": "^0.1.0-rc.6 || ^0.2.0-rc.1",
79
- "@deepseek-ai/dsh-tools": "^0.1.0-rc.6 || ^0.2.0-rc.1",
80
- "@deepseek-ai/dsh-typert-protocol": "^0.1.0-rc.6 || ^0.2.0-rc.1",
73
+ "@deepseek-ai/dsh-agent-presets": "^0.1.0-rc.6 || ^0.2.0-rc.1 || ^0.2.1-rc.1",
74
+ "@deepseek-ai/dsh-client-locale": "^0.1.0-rc.6 || ^0.2.0-rc.1 || ^0.2.1-rc.1",
75
+ "@deepseek-ai/dsh-client-ui-primitives": "^0.1.0-rc.6 || ^0.2.0-rc.1 || ^0.2.1-rc.1",
76
+ "@deepseek-ai/dsh-client-ui-settings": "^0.1.0-rc.6 || ^0.2.0-rc.1 || ^0.2.1-rc.1",
77
+ "@deepseek-ai/dsh-client-ui-settings-plugins": "^0.1.0-rc.6 || ^0.2.0-rc.1 || ^0.2.1-rc.1",
78
+ "@deepseek-ai/dsh-client-ui-slots": "^0.1.0-rc.6 || ^0.2.0-rc.1 || ^0.2.1-rc.1",
79
+ "@deepseek-ai/dsh-credentials": "^0.1.0-rc.6 || ^0.2.0-rc.1 || ^0.2.1-rc.1",
80
+ "@deepseek-ai/dsh-skill": "^0.1.0-rc.6 || ^0.2.0-rc.1 || ^0.2.1-rc.1",
81
+ "@deepseek-ai/dsh-tools": "^0.1.0-rc.6 || ^0.2.0-rc.1 || ^0.2.1-rc.1",
82
+ "@deepseek-ai/dsh-typert-protocol": "^0.1.0-rc.6 || ^0.2.0-rc.1 || ^0.2.1-rc.1",
81
83
  "react": "^18.2.0"
82
84
  },
83
85
  "peerDependenciesMeta": {
package/lib/invariant.js DELETED
@@ -1,25 +0,0 @@
1
- //#region lib/types/invariant.js
2
- /**
3
- * Package-owned invariant companion for `@khorsheed/dsh-capability-catalog`.
4
- * @module @khorsheed/dsh-capability-catalog/invariant
5
- */
6
- const PACKAGE_NAME = "@khorsheed/dsh-capability-catalog";
7
- /** Cordis companion plugin name. */
8
- const name = "capability-catalog-invariant";
9
- /** Service required before the companion can reserve package ownership. */
10
- const inject = ["invariants"];
11
- /**
12
- * No runtime invariant: the catalog is read-only over existing registries
13
- * (ctx.skills / ctx.tools) and the add-skill write path validates its inputs
14
- * before touching disk. The unit tests exercise the channel attribution,
15
- * skill decoding, and the wire projection.
16
- */
17
- const install = () => {};
18
- /**
19
- * Register this package's invariant companion.
20
- * @param ctx - Cordis context carrying the invariant service.
21
- * @returns the installed registration's disposer after setup succeeds.
22
- */
23
- const apply = (ctx) => Promise.resolve(ctx.invariants.register(PACKAGE_NAME, install));
24
- //#endregion
25
- export { apply, inject, name };
@@ -1,16 +0,0 @@
1
- /**
2
- * Package-owned invariant companion for `@khorsheed/dsh-capability-catalog`.
3
- * @module @khorsheed/dsh-capability-catalog/invariant
4
- */
5
- import type { Context } from '@deepseek-ai/cordis';
6
- /** Cordis companion plugin name. */
7
- export declare const name = "capability-catalog-invariant";
8
- /** Service required before the companion can reserve package ownership. */
9
- export declare const inject: string[];
10
- /**
11
- * Register this package's invariant companion.
12
- * @param ctx - Cordis context carrying the invariant service.
13
- * @returns the installed registration's disposer after setup succeeds.
14
- */
15
- export declare const apply: (ctx: Context) => Promise<() => void>;
16
- //# sourceMappingURL=invariant.d.ts.map
@@ -1,23 +0,0 @@
1
- /**
2
- * Package-owned invariant companion for `@khorsheed/dsh-capability-catalog`.
3
- * @module @khorsheed/dsh-capability-catalog/invariant
4
- */
5
- const PACKAGE_NAME = '@khorsheed/dsh-capability-catalog';
6
- /** Cordis companion plugin name. */
7
- export const name = 'capability-catalog-invariant';
8
- /** Service required before the companion can reserve package ownership. */
9
- export const inject = ['invariants'];
10
- /**
11
- * No runtime invariant: the catalog is read-only over existing registries
12
- * (ctx.skills / ctx.tools) and the add-skill write path validates its inputs
13
- * before touching disk. The unit tests exercise the channel attribution,
14
- * skill decoding, and the wire projection.
15
- */
16
- const install = () => { };
17
- /**
18
- * Register this package's invariant companion.
19
- * @param ctx - Cordis context carrying the invariant service.
20
- * @returns the installed registration's disposer after setup succeeds.
21
- */
22
- export const apply = (ctx) => Promise.resolve(ctx.invariants.register(PACKAGE_NAME, install));
23
- /* jscpd:ignore-end */