@yadsh/dsh-qa-surface 0.8.0 → 0.9.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.
Files changed (157) hide show
  1. package/README.md +113 -3
  2. package/compatibility.json +5 -0
  3. package/lib/access/capability-catalog.js +32 -3
  4. package/lib/access/capability-catalog.js.map +1 -1
  5. package/lib/access/service.js +45 -17
  6. package/lib/access/service.js.map +1 -1
  7. package/lib/accounts/errors.js.map +1 -1
  8. package/lib/accounts/store.js +14 -0
  9. package/lib/accounts/store.js.map +1 -1
  10. package/lib/admin/permissions.js +4 -0
  11. package/lib/admin/permissions.js.map +1 -1
  12. package/lib/admin/quality-store.js +71 -0
  13. package/lib/admin/quality-store.js.map +1 -1
  14. package/lib/admin/service.js +106 -1
  15. package/lib/admin/service.js.map +1 -1
  16. package/lib/admin/session-log.js +66 -5
  17. package/lib/admin/session-log.js.map +1 -1
  18. package/lib/client/QaSessionController.js +359 -37
  19. package/lib/client/QaSessionController.js.map +1 -1
  20. package/lib/client/QaSurface.js +26 -4
  21. package/lib/client/QaSurface.js.map +1 -1
  22. package/lib/client/QaTranscriptAdapter.js +36 -0
  23. package/lib/client/QaTranscriptAdapter.js.map +1 -1
  24. package/lib/client/admin/QaAdmin.js +9 -1
  25. package/lib/client/admin/QaAdmin.js.map +1 -1
  26. package/lib/client/admin/pages/Conversations.js +33 -7
  27. package/lib/client/admin/pages/Conversations.js.map +1 -1
  28. package/lib/client/admin/shared.js +9 -0
  29. package/lib/client/admin/shared.js.map +1 -1
  30. package/lib/client/admin/styles.js +2 -0
  31. package/lib/client/admin/styles.js.map +1 -1
  32. package/lib/client/audit/QaAuditDialog.js +74 -0
  33. package/lib/client/audit/QaAuditDialog.js.map +1 -0
  34. package/lib/client/audit/QaAuditRowBadge.js +17 -0
  35. package/lib/client/audit/QaAuditRowBadge.js.map +1 -0
  36. package/lib/client/audit/controller.js +39 -0
  37. package/lib/client/audit/controller.js.map +1 -0
  38. package/lib/client/audit/types.js +36 -0
  39. package/lib/client/audit/types.js.map +1 -0
  40. package/lib/client/audit/use-chat-audits.js +139 -0
  41. package/lib/client/audit/use-chat-audits.js.map +1 -0
  42. package/lib/client/components/QaChangelog.js +43 -0
  43. package/lib/client/components/QaChangelog.js.map +1 -1
  44. package/lib/client/components/QaComposer.js +63 -3
  45. package/lib/client/components/QaComposer.js.map +1 -1
  46. package/lib/client/components/QaMessage.js +16 -0
  47. package/lib/client/components/QaMessage.js.map +1 -1
  48. package/lib/client/components/QaQuestions.js +1 -1
  49. package/lib/client/components/QaQuestions.js.map +1 -1
  50. package/lib/client/components/QaSidebar.js +12 -1
  51. package/lib/client/components/QaSidebar.js.map +1 -1
  52. package/lib/client/index.js +22 -2
  53. package/lib/client/index.js.map +1 -1
  54. package/lib/client/project-session-state.js +15 -2
  55. package/lib/client/project-session-state.js.map +1 -1
  56. package/lib/client/prompt-content.js +26 -0
  57. package/lib/client/prompt-content.js.map +1 -1
  58. package/lib/client/settings/card.js +2 -2
  59. package/lib/client/settings/card.js.map +1 -1
  60. package/lib/client/settings/sections/lockdown.js +1 -6
  61. package/lib/client/settings/sections/lockdown.js.map +1 -1
  62. package/lib/client/settings/sections/slash.js +57 -0
  63. package/lib/client/settings/sections/slash.js.map +1 -0
  64. package/lib/client/settings/sections/status.js +9 -1
  65. package/lib/client/settings/sections/status.js.map +1 -1
  66. package/lib/client/settings/sections.js +1 -0
  67. package/lib/client/settings/sections.js.map +1 -1
  68. package/lib/client/slash/SlashPalette.js +48 -0
  69. package/lib/client/slash/SlashPalette.js.map +1 -0
  70. package/lib/client/slash/copy.js +54 -0
  71. package/lib/client/slash/copy.js.map +1 -0
  72. package/lib/client/slash/slash-router.js +49 -0
  73. package/lib/client/slash/slash-router.js.map +1 -0
  74. package/lib/client/slash/useSlashNavigation.js +95 -0
  75. package/lib/client/slash/useSlashNavigation.js.map +1 -0
  76. package/lib/client/styles.js +51 -1
  77. package/lib/client/styles.js.map +1 -1
  78. package/lib/client/types.js +11 -0
  79. package/lib/client/types.js.map +1 -1
  80. package/lib/client.js +4231 -551
  81. package/lib/client.js.map +1 -1
  82. package/lib/config-resolvers/basics.js +11 -2
  83. package/lib/config-resolvers/basics.js.map +1 -1
  84. package/lib/config-resolvers/defaults.js +22 -0
  85. package/lib/config-resolvers/defaults.js.map +1 -1
  86. package/lib/config-resolvers/lockdown.js +8 -2
  87. package/lib/config-resolvers/lockdown.js.map +1 -1
  88. package/lib/config-resolvers/slash-commands.js +60 -0
  89. package/lib/config-resolvers/slash-commands.js.map +1 -0
  90. package/lib/config.js +61 -2
  91. package/lib/config.js.map +1 -1
  92. package/lib/index.js +158 -1
  93. package/lib/index.js.map +1 -1
  94. package/lib/personal-skills/service.js +16 -3
  95. package/lib/personal-skills/service.js.map +1 -1
  96. package/lib/provenance/host-store.js +18 -1
  97. package/lib/provenance/host-store.js.map +1 -1
  98. package/lib/questions.js +90 -43
  99. package/lib/questions.js.map +1 -1
  100. package/lib/resolve-config.js +5 -0
  101. package/lib/resolve-config.js.map +1 -1
  102. package/lib/secure-session.js +24 -0
  103. package/lib/secure-session.js.map +1 -1
  104. package/lib/slash/catalog.js +77 -0
  105. package/lib/slash/catalog.js.map +1 -0
  106. package/lib/slash/matcher.js +100 -0
  107. package/lib/slash/matcher.js.map +1 -0
  108. package/lib/slash/parser.js +79 -0
  109. package/lib/slash/parser.js.map +1 -0
  110. package/lib/slash/policy.js +72 -0
  111. package/lib/slash/policy.js.map +1 -0
  112. package/lib/slash/remotes.js +272 -0
  113. package/lib/slash/remotes.js.map +1 -0
  114. package/lib/typert.host.js +318 -53
  115. package/lib/typert.remote-client.d.ts +7 -1
  116. package/lib/typert.remote-client.js +247 -51
  117. package/lib/types/access/capability-catalog.d.ts +28 -1
  118. package/lib/types/access/service.d.ts +33 -4
  119. package/lib/types/accounts/errors.d.ts +7 -1
  120. package/lib/types/accounts/store.d.ts +12 -0
  121. package/lib/types/admin/quality-store.d.ts +18 -0
  122. package/lib/types/admin/service.d.ts +34 -2
  123. package/lib/types/admin/session-log.d.ts +65 -1
  124. package/lib/types/client/QaSessionController.d.ts +84 -2
  125. package/lib/types/client/QaSurface.d.ts +14 -1
  126. package/lib/types/client/admin/pages/Conversations.d.ts +4 -0
  127. package/lib/types/client/audit/QaAuditDialog.d.ts +21 -0
  128. package/lib/types/client/audit/QaAuditRowBadge.d.ts +18 -0
  129. package/lib/types/client/audit/controller.d.ts +27 -0
  130. package/lib/types/client/audit/types.d.ts +72 -0
  131. package/lib/types/client/audit/use-chat-audits.d.ts +20 -0
  132. package/lib/types/client/components/QaComposer.d.ts +12 -2
  133. package/lib/types/client/components/QaQuestions.d.ts +7 -0
  134. package/lib/types/client/components/QaSidebar.d.ts +8 -0
  135. package/lib/types/client/project-session-state.d.ts +3 -1
  136. package/lib/types/client/prompt-content.d.ts +9 -1
  137. package/lib/types/client/settings/sections/slash.d.ts +16 -0
  138. package/lib/types/client/settings/sections.d.ts +1 -0
  139. package/lib/types/client/slash/SlashPalette.d.ts +24 -0
  140. package/lib/types/client/slash/copy.d.ts +30 -0
  141. package/lib/types/client/slash/slash-router.d.ts +67 -0
  142. package/lib/types/client/slash/useSlashNavigation.d.ts +47 -0
  143. package/lib/types/client/styles.d.ts +9 -0
  144. package/lib/types/client/types.d.ts +16 -1
  145. package/lib/types/config-resolvers/slash-commands.d.ts +20 -0
  146. package/lib/types/index.d.ts +78 -1
  147. package/lib/types/personal-skills/service.d.ts +5 -0
  148. package/lib/types/provenance/host-store.d.ts +13 -0
  149. package/lib/types/questions.d.ts +8 -0
  150. package/lib/types/slash/catalog.d.ts +56 -0
  151. package/lib/types/slash/matcher.d.ts +51 -0
  152. package/lib/types/slash/parser.d.ts +46 -0
  153. package/lib/types/slash/policy.d.ts +40 -0
  154. package/lib/types/slash/remotes.d.ts +35 -0
  155. package/lib/types/types.d.ts +200 -5
  156. package/package.json +7 -3
  157. package/scripts/attach-workspace-sessions.mjs +472 -0
@@ -0,0 +1,100 @@
1
+ /**
2
+ * One matcher for both halves of the slash catalog.
3
+ *
4
+ * Upstream matches skills with `startsWith` and commands fuzzily, so the same
5
+ * query behaves differently depending on which registry answers it. QA always
6
+ * ranks with the ladder below, in this order:
7
+ *
8
+ * exact → prefix → name-token boundary → substring → ordered subsequence
9
+ *
10
+ * so `/tkp` finds `generate-tkp` through the token boundary and `/contract`
11
+ * finds both `contract-analysis` (prefix) and `review-contract` (token).
12
+ *
13
+ * Dependency-free on purpose: inlined into the browser bundle.
14
+ */
15
+ /** How a name matched; lower is a stronger claim on the top of the list. */
16
+ export const SLASH_MATCH_EXACT = 0;
17
+ export const SLASH_MATCH_PREFIX = 1;
18
+ export const SLASH_MATCH_TOKEN = 2;
19
+ export const SLASH_MATCH_SUBSTRING = 3;
20
+ export const SLASH_MATCH_SUBSEQUENCE = 4;
21
+ /** Word separators the name grammars use, for the token-boundary rung. */
22
+ const TOKEN_BREAK = /[-_]/u;
23
+ function tokenIndexOf(name, query) {
24
+ let start = 0;
25
+ for (const token of name.split(TOKEN_BREAK)) {
26
+ if (token.startsWith(query))
27
+ return start;
28
+ start += token.length + 1;
29
+ }
30
+ return undefined;
31
+ }
32
+ /** Greedy ordered-subsequence scan; the index is where the run starts. */
33
+ function subsequenceIndexOf(name, query) {
34
+ let cursor = 0;
35
+ let first = -1;
36
+ for (const character of query) {
37
+ const found = name.indexOf(character, cursor);
38
+ if (found === -1)
39
+ return undefined;
40
+ if (first === -1)
41
+ first = found;
42
+ cursor = found + 1;
43
+ }
44
+ return first === -1 ? undefined : first;
45
+ }
46
+ /**
47
+ * Rank one name against a palette query. An empty query matches everything at
48
+ * the prefix rung, which keeps the unfiltered catalog in catalog order.
49
+ */
50
+ export function matchSlashName(name, query, options = {}) {
51
+ const target = name.toLowerCase();
52
+ const needle = query.toLowerCase();
53
+ if (needle === "")
54
+ return { rank: SLASH_MATCH_PREFIX, index: 0 };
55
+ if (target === needle)
56
+ return { rank: SLASH_MATCH_EXACT, index: 0 };
57
+ if (target.startsWith(needle))
58
+ return { rank: SLASH_MATCH_PREFIX, index: 0 };
59
+ const token = tokenIndexOf(target, needle);
60
+ if (token !== undefined)
61
+ return { rank: SLASH_MATCH_TOKEN, index: token };
62
+ if (options.fuzzy === false)
63
+ return undefined;
64
+ const substring = target.indexOf(needle);
65
+ if (substring !== -1) {
66
+ return { rank: SLASH_MATCH_SUBSTRING, index: substring };
67
+ }
68
+ const subsequence = subsequenceIndexOf(target, needle);
69
+ if (subsequence !== undefined) {
70
+ return { rank: SLASH_MATCH_SUBSEQUENCE, index: subsequence };
71
+ }
72
+ return undefined;
73
+ }
74
+ /**
75
+ * Order two ranked names; the caller has already ruled out `undefined`. Ties
76
+ * fall back to the name, so equal-rank rows keep catalog order and the list
77
+ * never reshuffles between two renders of the same query.
78
+ */
79
+ export function compareSlashMatches(leftName, left, rightName, right) {
80
+ if (left.rank !== right.rank)
81
+ return left.rank - right.rank;
82
+ if (left.index !== right.index)
83
+ return left.index - right.index;
84
+ return leftName.localeCompare(rightName);
85
+ }
86
+ /**
87
+ * The matching entries in rank order. Identity of the input entries is
88
+ * preserved, so a caller can render them without a lookup.
89
+ */
90
+ export function rankSlashEntries(entries, query, options = {}) {
91
+ const ranked = [];
92
+ for (const entry of entries) {
93
+ const match = matchSlashName(entry.name, query, options);
94
+ if (match !== undefined)
95
+ ranked.push({ entry, match });
96
+ }
97
+ ranked.sort((left, right) => compareSlashMatches(left.entry.name, left.match, right.entry.name, right.match));
98
+ return Object.freeze(ranked.map(({ entry }) => entry));
99
+ }
100
+ //# sourceMappingURL=matcher.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"matcher.js","sourceRoot":"","sources":["../../src/slash/matcher.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,79 @@
1
+ /**
2
+ * Composer input classification for the slash interface.
3
+ *
4
+ * The grammars are mirrors, not inventions: a command line is what the native
5
+ * command runtime parses (`/name` at byte zero, name then end-of-input or
6
+ * whitespace, everything after kept verbatim as `rawInput`), and a skill
7
+ * gesture is what `dsh-tool-skill` recognises (any whitespace-bounded `/name`
8
+ * token with the public skill-name grammar). A line that matches neither is
9
+ * ordinary prose and must keep behaving exactly as it did before this feature.
10
+ *
11
+ * Deliberately dependency-free: this module is inlined into the browser
12
+ * bundle, where the Host's config surface must not follow it.
13
+ */
14
+ /** `/name` at byte zero — the shape the native command runtime parses. */
15
+ const COMMAND_LINE = /^\/([a-z][a-z0-9_-]*)(?=$|[\t\n\r ])/u;
16
+ /** Mirror of the native `SKILL_GESTURE`: whitespace-bounded kebab-case. */
17
+ const SKILL_GESTURE = /(^|\s)\/([a-z0-9]+(?:-[a-z0-9]+)*)(?=\s|$)/gu;
18
+ /**
19
+ * A name still being typed in the composer: no whitespace yet, so the token
20
+ * is the palette's filter rather than an invocation. Bare `/` is the empty
21
+ * query that opens the palette on its own.
22
+ */
23
+ const PALETTE_QUERY = /^[a-z0-9][a-z0-9_-]*$/u;
24
+ /**
25
+ * Parse a command-shaped line. `undefined` means the line is not one — either
26
+ * it is not slash-led at all, or the token after the slash is not a command
27
+ * name (`/usr/bin/env` stays a path, not a call).
28
+ */
29
+ export function parseSlashLine(input) {
30
+ const match = COMMAND_LINE.exec(input);
31
+ if (match === null)
32
+ return undefined;
33
+ return Object.freeze({
34
+ name: match[1] ?? "",
35
+ args: input.slice(match[0].length),
36
+ });
37
+ }
38
+ /** The palette filter of a draft, or `undefined` when the palette is closed. */
39
+ export function slashPaletteQuery(input) {
40
+ if (!input.startsWith("/"))
41
+ return undefined;
42
+ const rest = input.slice(1);
43
+ if (rest === "")
44
+ return "";
45
+ return PALETTE_QUERY.test(rest) ? rest : undefined;
46
+ }
47
+ /**
48
+ * Every whitespace-bounded `/name` gesture in the text, first-seen order and
49
+ * deduplicated. The Host owns invocation; this list exists only so the QA
50
+ * surface can warn about a gesture its own policy withholds before the turn
51
+ * is submitted.
52
+ */
53
+ export function skillGestures(input) {
54
+ const names = [];
55
+ const seen = new Set();
56
+ for (const match of input.matchAll(SKILL_GESTURE)) {
57
+ const name = match[2];
58
+ if (name === undefined || seen.has(name))
59
+ continue;
60
+ seen.add(name);
61
+ names.push(name);
62
+ }
63
+ return Object.freeze(names);
64
+ }
65
+ /**
66
+ * The invocation a draft names, independent of the catalog. Used for the
67
+ * routing decision and for the "unknown command" refusal, both of which must
68
+ * work while the catalog itself is unavailable.
69
+ */
70
+ export function slashInvocation(input) {
71
+ const line = parseSlashLine(input);
72
+ if (line === undefined)
73
+ return undefined;
74
+ return Object.freeze({
75
+ name: line.name,
76
+ args: line.args.replace(/^[\t\n\r ]+/u, ""),
77
+ });
78
+ }
79
+ //# sourceMappingURL=parser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parser.js","sourceRoot":"","sources":["../../src/slash/parser.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,0EAA0E;AAC1E,MAAM,YAAY,GAAG,uCAAuC,CAAC;AAE7D,2EAA2E;AAC3E,MAAM,aAAa,GAAG,8CAA8C,CAAC;AAErE;;;;GAIG;AACH,MAAM,aAAa,GAAG,wBAAwB,CAAC;AAQ/C;;;;GAIG;AACH,MAAM,UAAU,cAAc,CAAC,KAAa;IAC1C,MAAM,KAAK,GAAG,YAAY,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACvC,IAAI,KAAK,KAAK,IAAI;QAAE,OAAO,SAAS,CAAC;IACrC,OAAO,MAAM,CAAC,MAAM,CAAC;QACnB,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC,IAAI,EAAE;QACpB,IAAI,EAAE,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC;KACnC,CAAC,CAAC;AACL,CAAC;AAED,gFAAgF;AAChF,MAAM,UAAU,iBAAiB,CAAC,KAAa;IAC7C,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC;QAAE,OAAO,SAAS,CAAC;IAC7C,MAAM,IAAI,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IAC5B,IAAI,IAAI,KAAK,EAAE;QAAE,OAAO,EAAE,CAAC;IAC3B,OAAO,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC;AACrD,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,aAAa,CAAC,KAAa;IACzC,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;IAC/B,KAAK,MAAM,KAAK,IAAI,KAAK,CAAC,QAAQ,CAAC,aAAa,CAAC,EAAE,CAAC;QAClD,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;QACtB,IAAI,IAAI,KAAK,SAAS,IAAI,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC;YAAE,SAAS;QACnD,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QACf,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACnB,CAAC;IACD,OAAO,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AAC9B,CAAC;AASD;;;;GAIG;AACH,MAAM,UAAU,eAAe,CAAC,KAAa;IAC3C,MAAM,IAAI,GAAG,cAAc,CAAC,KAAK,CAAC,CAAC;IACnC,IAAI,IAAI,KAAK,SAAS;QAAE,OAAO,SAAS,CAAC;IACzC,OAAO,MAAM,CAAC,MAAM,CAAC;QACnB,IAAI,EAAE,IAAI,CAAC,IAAI;QACf,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,cAAc,EAAE,EAAE,CAAC;KAC5C,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,72 @@
1
+ /**
2
+ * Admission policy for one half of the slash catalog.
3
+ *
4
+ * The policy is name-based because the persisted config is: an operator writes
5
+ * `generate-tkp`, never an internal id, and the same name means the same thing
6
+ * on every Host restart. Names that cannot be a native skill or command name
7
+ * are refused at config resolution rather than silently ignored at admission,
8
+ * so a typo surfaces while the deployment is being configured.
9
+ */
10
+ /** Every accepted policy mode, in the order the settings card lists them. */
11
+ export const QA_SLASH_MODES = Object.freeze([
12
+ "deny-all",
13
+ "allow-list",
14
+ "all",
15
+ ]);
16
+ /**
17
+ * Union of the two native name grammars: the command registry allows `_` and
18
+ * a leading digit-bearing word, skills are kebab-case. A name outside this
19
+ * shape can never be resolved by either registry.
20
+ */
21
+ const SLASH_NAME = /^[a-z0-9][a-z0-9_-]*$/u;
22
+ /** Longest name either registry accepts in practice; keeps host echoes bounded. */
23
+ export const QA_SLASH_NAME_MAX = 200;
24
+ export function isQaSlashPolicyMode(value) {
25
+ return value === "deny-all" || value === "allow-list" || value === "all";
26
+ }
27
+ /**
28
+ * Normalize one allow-list: trimmed, deduplicated, order-preserving. Refuses
29
+ * a name that neither registry could ever carry, and refuses `all` alongside a
30
+ * non-empty list, which would be two answers to one question.
31
+ */
32
+ export function normalizeSlashAllow(values, label) {
33
+ const names = [...new Set(values.map((value) => value.trim()))].filter((value) => value !== "");
34
+ for (const name of names) {
35
+ if (name.length > QA_SLASH_NAME_MAX) {
36
+ throw new TypeError(`dsh-qa-surface: ${label} names must be at most ${String(QA_SLASH_NAME_MAX)} characters`);
37
+ }
38
+ if (!SLASH_NAME.test(name)) {
39
+ throw new TypeError(`dsh-qa-surface: ${label} admits only lowercase native names (got "${name}")`);
40
+ }
41
+ }
42
+ return Object.freeze(names);
43
+ }
44
+ /** Whether the policy admits this native name. */
45
+ export function allowsSlashName(policy, name) {
46
+ if (policy.mode === "deny-all")
47
+ return false;
48
+ if (policy.mode === "all")
49
+ return true;
50
+ return policy.allow.includes(name);
51
+ }
52
+ /** The admitted subset, in the order the native registry returned it. */
53
+ export function filterBySlashPolicy(entries, policy) {
54
+ if (policy.mode === "deny-all")
55
+ return Object.freeze([]);
56
+ if (policy.mode === "all")
57
+ return entries;
58
+ const allowed = new Set(policy.allow);
59
+ return Object.freeze(entries.filter((entry) => allowed.has(entry.name)));
60
+ }
61
+ /**
62
+ * Intersect an already-admitted list with a second name set (the session's
63
+ * role grant). An empty set means "no second opinion" — the role system keeps
64
+ * its own switch, and a deployment that never enabled it grants nothing here.
65
+ */
66
+ export function intersectSlashNames(entries, names) {
67
+ if (names === undefined)
68
+ return entries;
69
+ const granted = new Set(names);
70
+ return Object.freeze(entries.filter((entry) => granted.has(entry.name)));
71
+ }
72
+ //# sourceMappingURL=policy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"policy.js","sourceRoot":"","sources":["../../src/slash/policy.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAIH,6EAA6E;AAC7E,MAAM,CAAC,MAAM,cAAc,GAAiC,MAAM,CAAC,MAAM,CAAC;IACxE,UAAU;IACV,YAAY;IACZ,KAAK;CACN,CAAC,CAAC;AAEH;;;;GAIG;AACH,MAAM,UAAU,GAAG,wBAAwB,CAAC;AAE5C,mFAAmF;AACnF,MAAM,CAAC,MAAM,iBAAiB,GAAG,GAAG,CAAC;AAOrC,MAAM,UAAU,mBAAmB,CACjC,KAAc;IAEd,OAAO,KAAK,KAAK,UAAU,IAAI,KAAK,KAAK,YAAY,IAAI,KAAK,KAAK,KAAK,CAAC;AAC3E,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,mBAAmB,CACjC,MAAyB,EACzB,KAAa;IAEb,MAAM,KAAK,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,MAAM,CACpE,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,KAAK,EAAE,CACxB,CAAC;IACF,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,IAAI,IAAI,CAAC,MAAM,GAAG,iBAAiB,EAAE,CAAC;YACpC,MAAM,IAAI,SAAS,CACjB,mBAAmB,KAAK,0BAA0B,MAAM,CAAC,iBAAiB,CAAC,aAAa,CACzF,CAAC;QACJ,CAAC;QACD,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;YAC3B,MAAM,IAAI,SAAS,CACjB,mBAAmB,KAAK,6CAA6C,IAAI,IAAI,CAC9E,CAAC;QACJ,CAAC;IACH,CAAC;IACD,OAAO,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AAC9B,CAAC;AAED,kDAAkD;AAClD,MAAM,UAAU,eAAe,CAAC,MAAqB,EAAE,IAAY;IACjE,IAAI,MAAM,CAAC,IAAI,KAAK,UAAU;QAAE,OAAO,KAAK,CAAC;IAC7C,IAAI,MAAM,CAAC,IAAI,KAAK,KAAK;QAAE,OAAO,IAAI,CAAC;IACvC,OAAO,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;AACrC,CAAC;AAED,yEAAyE;AACzE,MAAM,UAAU,mBAAmB,CACjC,OAAqB,EACrB,MAAqB;IAErB,IAAI,MAAM,CAAC,IAAI,KAAK,UAAU;QAAE,OAAO,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;IACzD,IAAI,MAAM,CAAC,IAAI,KAAK,KAAK;QAAE,OAAO,OAAO,CAAC;IAC1C,MAAM,OAAO,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IACtC,OAAO,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAC3E,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,mBAAmB,CACjC,OAAqB,EACrB,KAAoC;IAEpC,IAAI,KAAK,KAAK,SAAS;QAAE,OAAO,OAAO,CAAC;IACxC,MAAM,OAAO,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,CAAC;IAC/B,OAAO,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAC3E,CAAC"}
@@ -0,0 +1,272 @@
1
+ import { SessionId } from "@deepseek-ai/dsh-session/types";
2
+ import { isUserInvocable } from "@deepseek-ai/dsh-skill";
3
+ import { buildSlashCatalog, } from "./catalog.js";
4
+ import { parseSlashLine } from "./parser.js";
5
+ import { allowsSlashName } from "./policy.js";
6
+ /**
7
+ * The reads below are bounded by the Remote transport and by the caller's own
8
+ * patience; an internal deadline would only cut off a slow filesystem scan.
9
+ */
10
+ const NO_CANCELLATION = new AbortController().signal;
11
+ const REFUSAL_COPY = Object.freeze({
12
+ "slash-disabled": "Slash actions are disabled on this deployment.",
13
+ "unknown-command": "No such command.",
14
+ "not-allowed": "This command is not allowed on this deployment.",
15
+ "attachments-unsupported": "This command does not accept attachments.",
16
+ "inactive-session": "The command surface needs a live chat.",
17
+ });
18
+ function refusal(reason, detail) {
19
+ return Object.freeze({
20
+ kind: "refused",
21
+ reason,
22
+ message: detail ?? REFUSAL_COPY[reason],
23
+ });
24
+ }
25
+ function policyOf(mode, allow) {
26
+ return { mode, allow };
27
+ }
28
+ /**
29
+ * User-invocable skills of this chat that no row of the palette represents.
30
+ * The list exists so the browser can say "this `/name` will not load" about a
31
+ * gesture typed inside a sentence, which it can only do if it can tell a real
32
+ * but withheld skill from a path that merely looks like one.
33
+ */
34
+ function withheldSkills(skills, entries) {
35
+ if (skills === undefined)
36
+ return Object.freeze([]);
37
+ const shown = new Set(entries
38
+ .filter((entry) => entry.kind === "skill")
39
+ .map((entry) => entry.name));
40
+ return Object.freeze(skills.map((skill) => skill.name).filter((name) => !shown.has(name)));
41
+ }
42
+ export function createQaSlashRemotes(options) {
43
+ const { ctx, getConfig, logger, sessionGrant } = options;
44
+ let skillCatalog;
45
+ let nativeCommands;
46
+ // Both surfaces are optional capabilities. The session-addressed catalog is
47
+ // preferred because it answers for a cold chat too; the registry below is
48
+ // the fallback for a composition that has skills but no session controller.
49
+ ctx.inject(["sessionSkillCatalog"], (catalogCtx) => {
50
+ skillCatalog =
51
+ catalogCtx.sessionSkillCatalog;
52
+ catalogCtx.effect(() => () => {
53
+ skillCatalog = undefined;
54
+ }, "dsh-qa-surface.slash-skill-catalog");
55
+ });
56
+ ctx.inject(["commands"], (commandsCtx) => {
57
+ nativeCommands = commandsCtx
58
+ .commands;
59
+ commandsCtx.effect(() => () => {
60
+ nativeCommands = undefined;
61
+ }, "dsh-qa-surface.slash-commands");
62
+ });
63
+ function agentOf(sessionId) {
64
+ return ctx.agents.get(SessionId(sessionId));
65
+ }
66
+ /** User-invocable skills of the session; `undefined` when unreadable. */
67
+ async function readSkills(sessionId, agent) {
68
+ if (skillCatalog !== undefined) {
69
+ try {
70
+ const value = await skillCatalog.list({ sessionId: SessionId(sessionId) }, NO_CANCELLATION);
71
+ return value.skills.map((skill) => ({
72
+ name: skill.name,
73
+ description: skill.description,
74
+ modelInvocable: skill.modelInvocable,
75
+ ...(skill.whenToUse === undefined
76
+ ? {}
77
+ : { whenToUse: skill.whenToUse }),
78
+ }));
79
+ }
80
+ catch (error) {
81
+ logger.warn("slash.catalog.skills-failed", {
82
+ sessionId,
83
+ message: error instanceof Error ? error.message : String(error),
84
+ });
85
+ return undefined;
86
+ }
87
+ }
88
+ if (agent === undefined)
89
+ return undefined;
90
+ try {
91
+ // Same view the session-addressed catalog builds: the agent is the
92
+ // scope, and its cwd decides which project layer contributes.
93
+ const live = agent;
94
+ const cwd = live.session.header.cwd;
95
+ const listed = await live.ctx.skills.list({
96
+ scope: agent,
97
+ ...(cwd === undefined ? {} : { cwd }),
98
+ });
99
+ return listed.filter(isUserInvocable).map((skill) => ({
100
+ name: skill.name,
101
+ description: skill.description,
102
+ modelInvocable: skill.invocation.modelInvocable,
103
+ ...(skill.whenToUse === undefined
104
+ ? {}
105
+ : { whenToUse: skill.whenToUse }),
106
+ }));
107
+ }
108
+ catch (error) {
109
+ logger.warn("slash.catalog.skills-failed", {
110
+ sessionId,
111
+ message: error instanceof Error ? error.message : String(error),
112
+ });
113
+ return undefined;
114
+ }
115
+ }
116
+ function readCommands(agent) {
117
+ if (nativeCommands === undefined || agent === undefined)
118
+ return undefined;
119
+ try {
120
+ return nativeCommands.list(agent).map((command) => ({
121
+ name: command.name,
122
+ description: command.description,
123
+ ...(command.input === undefined
124
+ ? {}
125
+ : { inputHint: command.input.hint }),
126
+ ...(command.input?.attachments === undefined
127
+ ? {}
128
+ : { acceptsAttachments: command.input.attachments }),
129
+ }));
130
+ }
131
+ catch (error) {
132
+ logger.warn("slash.catalog.commands-failed", {
133
+ message: error instanceof Error ? error.message : String(error),
134
+ });
135
+ return undefined;
136
+ }
137
+ }
138
+ function commandSurfaceOf(agent, commands) {
139
+ if (nativeCommands === undefined)
140
+ return "unavailable";
141
+ if (agent === undefined)
142
+ return "inactive";
143
+ return commands === undefined ? "unavailable" : "ready";
144
+ }
145
+ return {
146
+ async catalog(token, sessionId) {
147
+ const config = getConfig();
148
+ if (!config.slashCommands.enabled) {
149
+ return Object.freeze({
150
+ enabled: false,
151
+ entries: Object.freeze([]),
152
+ commandSurface: "unavailable",
153
+ deniedSkills: Object.freeze([]),
154
+ });
155
+ }
156
+ const agent = agentOf(sessionId);
157
+ // Ownership is checked before anything is read: the catalog names the
158
+ // session's skills and its operator's commands, which is exactly the
159
+ // kind of fact a foreign browser must not be able to enumerate.
160
+ const granted = await sessionGrant(token, sessionId, agent);
161
+ const [skills, commands] = [
162
+ await readSkills(sessionId, agent),
163
+ readCommands(agent),
164
+ ];
165
+ const commandSurface = commandSurfaceOf(agent, commands);
166
+ const entries = buildSlashCatalog({
167
+ skills: skills ?? [],
168
+ commands: commands ?? [],
169
+ skillPolicy: policyOf(config.slashCommands.skills.mode, config.slashCommands.skills.allow),
170
+ commandPolicy: policyOf(config.slashCommands.commands.mode, config.slashCommands.commands.allow),
171
+ grantedSkills: granted,
172
+ commandSurface,
173
+ });
174
+ const deniedSkills = withheldSkills(skills, entries);
175
+ logger.info("slash.catalog.load", {
176
+ sessionId,
177
+ skills: skills?.length ?? 0,
178
+ commands: commands?.length ?? 0,
179
+ entries: entries.length,
180
+ commandSurface,
181
+ });
182
+ return Object.freeze({
183
+ enabled: true,
184
+ entries,
185
+ commandSurface,
186
+ deniedSkills,
187
+ });
188
+ },
189
+ async execute(token, sessionId, line, attachments) {
190
+ const config = getConfig();
191
+ if (!config.slashCommands.enabled)
192
+ return refusal("slash-disabled");
193
+ const parsed = parseSlashLine(line);
194
+ if (parsed === undefined)
195
+ return refusal("unknown-command");
196
+ const name = parsed.name;
197
+ // Admission re-derives everything from the line. The browser's catalog is
198
+ // a presentation cache and never an authorization: a name the policy does
199
+ // not admit is refused here even though the palette never showed it.
200
+ if (!allowsSlashName(policyOf(config.slashCommands.commands.mode, config.slashCommands.commands.allow), name)) {
201
+ logger.warn("slash.denied", { sessionId, kind: "command", name });
202
+ return refusal("not-allowed");
203
+ }
204
+ // Ownership before execution, exactly as the catalog read does: a
205
+ // command mutates the chat it runs in, so a foreign browser must not be
206
+ // able to reach the native runtime through this surface at all.
207
+ const agent = agentOf(sessionId);
208
+ await sessionGrant(token, sessionId, agent);
209
+ if (nativeCommands === undefined || agent === undefined) {
210
+ return refusal("inactive-session");
211
+ }
212
+ const descriptor = nativeCommands
213
+ .list(agent)
214
+ .find((command) => command.name === name);
215
+ if (descriptor === undefined) {
216
+ logger.warn("slash.unknown", { sessionId, kind: "command", name });
217
+ return refusal("unknown-command");
218
+ }
219
+ if (attachments.length > 0 && descriptor.input?.attachments !== true) {
220
+ // Refused before the handler ran, so the composer keeps its draft and
221
+ // its attachments; the native runtime re-checks this as the authority.
222
+ return refusal("attachments-unsupported");
223
+ }
224
+ logger.info("slash.command.execute", {
225
+ sessionId,
226
+ name,
227
+ attachments: attachments.length,
228
+ });
229
+ let execution;
230
+ try {
231
+ execution = await nativeCommands.execute(agent, line, attachments, NO_CANCELLATION);
232
+ }
233
+ catch (error) {
234
+ // The handler threw: the runtime already wrote command/done with the
235
+ // failure into the session log, so the transcript row carries the
236
+ // outcome and this only tells the caller the submission was consumed.
237
+ const message = error instanceof Error ? error.message : String(error);
238
+ logger.warn("slash.command.error", { sessionId, name, message });
239
+ const failed = { kind: "error", text: message };
240
+ return Object.freeze({
241
+ kind: "executed",
242
+ commandId: "",
243
+ outcome: Object.freeze(failed),
244
+ });
245
+ }
246
+ if (execution === undefined) {
247
+ logger.warn("slash.unknown", { sessionId, kind: "command", name });
248
+ return refusal("unknown-command");
249
+ }
250
+ const outcome = execution.result.kind === "success"
251
+ ? {
252
+ kind: "success",
253
+ ...(execution.result.text === undefined
254
+ ? {}
255
+ : { text: execution.result.text }),
256
+ ...(execution.result.sourceEventSeq === undefined
257
+ ? {}
258
+ : { sourceEventSeq: execution.result.sourceEventSeq }),
259
+ }
260
+ : { kind: "error", text: execution.result.text };
261
+ logger.info(outcome.kind === "success"
262
+ ? "slash.command.success"
263
+ : "slash.command.error", { sessionId, name, commandId: execution.commandId });
264
+ return Object.freeze({
265
+ kind: "executed",
266
+ commandId: execution.commandId,
267
+ outcome: Object.freeze(outcome),
268
+ });
269
+ },
270
+ };
271
+ }
272
+ //# sourceMappingURL=remotes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"remotes.js","sourceRoot":"","sources":["../../src/slash/remotes.ts"],"names":[],"mappings":"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"}