@deepseek-harness-tui/dsh-tui 0.9.2 → 0.9.3

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 (214) hide show
  1. package/README.md +4 -4
  2. package/bin/dsh-tui.js +26 -4
  3. package/dsh-ecosystem-spec/protocols/profile-definitions.d.ts +13 -13
  4. package/dsh-ecosystem-spec/protocols/profile-definitions.js +59 -59
  5. package/dsh-ecosystem-spec/protocols/tui-channel-http.d.ts +15 -15
  6. package/dsh-ecosystem-spec/protocols/tui-channel-http.js +32 -32
  7. package/dsh-ecosystem-spec/protocols/tui-channel.d.ts +59 -59
  8. package/dsh-ecosystem-spec/protocols/tui-channel.js +166 -166
  9. package/dsh-ecosystem-spec/protocols/tui-contributions.d.ts +42 -42
  10. package/dsh-ecosystem-spec/protocols/tui-contributions.js +143 -143
  11. package/dsh-ecosystem-spec/registry/README.md +14 -14
  12. package/dsh-ecosystem-spec/registry/host-descriptor.tui.example.json +56 -56
  13. package/dsh-ecosystem-spec/registry/permissions-0.1.json +13 -13
  14. package/dsh-ecosystem-spec/registry/registry-0.15.json +149 -149
  15. package/lib/types/commands.d.ts.map +1 -1
  16. package/lib/types/commands.js +7 -8
  17. package/lib/types/components/BalanceReportRow.d.ts +24 -0
  18. package/lib/types/components/BalanceReportRow.d.ts.map +1 -0
  19. package/lib/types/components/BalanceReportRow.js +87 -0
  20. package/lib/types/components/HistorySearchDialog.js +1 -1
  21. package/lib/types/components/MessageList.d.ts +3 -1
  22. package/lib/types/components/MessageList.d.ts.map +1 -1
  23. package/lib/types/components/MessageList.js +11 -7
  24. package/lib/types/components/PluginSceneBoundary.d.ts +1 -1
  25. package/lib/types/components/PluginSceneBoundary.js +1 -1
  26. package/lib/types/components/PromptInput.d.ts.map +1 -1
  27. package/lib/types/components/PromptInput.js +16 -0
  28. package/lib/types/components/Whale.d.ts +15 -4
  29. package/lib/types/components/Whale.d.ts.map +1 -1
  30. package/lib/types/components/Whale.js +9 -8
  31. package/lib/types/components/messages/AssistantToolUseMessage.d.ts +7 -1
  32. package/lib/types/components/messages/AssistantToolUseMessage.d.ts.map +1 -1
  33. package/lib/types/components/messages/AssistantToolUseMessage.js +34 -4
  34. package/lib/types/deepseekBalance.d.ts +53 -0
  35. package/lib/types/deepseekBalance.d.ts.map +1 -0
  36. package/lib/types/deepseekBalance.js +86 -0
  37. package/lib/types/deepseekPricing.d.ts +82 -0
  38. package/lib/types/deepseekPricing.d.ts.map +1 -0
  39. package/lib/types/deepseekPricing.js +133 -0
  40. package/lib/types/dsh-adapter/channel.d.ts +46 -1
  41. package/lib/types/dsh-adapter/channel.d.ts.map +1 -1
  42. package/lib/types/dsh-adapter/channel.js +84 -10
  43. package/lib/types/dsh-adapter/index.d.ts +5 -0
  44. package/lib/types/dsh-adapter/index.d.ts.map +1 -1
  45. package/lib/types/dsh-adapter/index.js +1 -0
  46. package/lib/types/dsh-adapter/packaged-skills.d.ts +9 -0
  47. package/lib/types/dsh-adapter/packaged-skills.d.ts.map +1 -1
  48. package/lib/types/dsh-adapter/packaged-skills.js +19 -4
  49. package/lib/types/dsh-adapter/plugin.d.ts +6 -0
  50. package/lib/types/dsh-adapter/plugin.d.ts.map +1 -1
  51. package/lib/types/dsh-adapter/plugin.js +122 -18
  52. package/lib/types/dsh-adapter/settings-sections.d.ts +1 -0
  53. package/lib/types/dsh-adapter/settings-sections.d.ts.map +1 -1
  54. package/lib/types/dsh-adapter/settings-sections.js +35 -2
  55. package/lib/types/history.d.ts +4 -3
  56. package/lib/types/history.d.ts.map +1 -1
  57. package/lib/types/history.js +66 -18
  58. package/lib/types/i18n.d.ts +122 -55
  59. package/lib/types/i18n.d.ts.map +1 -1
  60. package/lib/types/i18n.js +39 -18
  61. package/lib/types/ink/ink.d.ts.map +1 -1
  62. package/lib/types/ink/ink.js +67 -17
  63. package/lib/types/ink/root.d.ts +16 -0
  64. package/lib/types/ink/root.d.ts.map +1 -1
  65. package/lib/types/ink/root.js +2 -0
  66. package/lib/types/ink/terminal-querier.d.ts +8 -0
  67. package/lib/types/ink/terminal-querier.d.ts.map +1 -1
  68. package/lib/types/ink/terminal-querier.js +13 -0
  69. package/lib/types/ink/terminal.d.ts +42 -0
  70. package/lib/types/ink/terminal.d.ts.map +1 -1
  71. package/lib/types/ink/terminal.js +52 -2
  72. package/lib/types/plugin-spec/registry.d.ts +1 -1
  73. package/lib/types/plugin-spec/registry.js +1 -1
  74. package/lib/types/screens/Chat.d.ts.map +1 -1
  75. package/lib/types/screens/Chat.js +72 -37
  76. package/lib/types/screens/SessionBrowser.d.ts.map +1 -1
  77. package/lib/types/screens/SessionBrowser.js +28 -13
  78. package/lib/types/screens/SessionTree.d.ts.map +1 -1
  79. package/lib/types/screens/SessionTree.js +33 -9
  80. package/lib/types/screens/Settings.d.ts +7 -5
  81. package/lib/types/screens/Settings.d.ts.map +1 -1
  82. package/lib/types/screens/Settings.js +206 -99
  83. package/lib/types/screens/StatusLine.d.ts.map +1 -1
  84. package/lib/types/screens/StatusLine.js +32 -1
  85. package/lib/types/sessionHistory.d.ts +11 -0
  86. package/lib/types/sessionHistory.d.ts.map +1 -1
  87. package/lib/types/sessionHistory.js +29 -0
  88. package/lib/types/sessions/format.d.ts.map +1 -1
  89. package/lib/types/sessions/format.js +14 -4
  90. package/lib/types/tips.js +2 -2
  91. package/lib/types/tuiDisplayPrefs.d.ts +3 -0
  92. package/lib/types/tuiDisplayPrefs.d.ts.map +1 -1
  93. package/lib/types/tuiDisplayPrefs.js +1 -0
  94. package/lib/types/update.d.ts +46 -0
  95. package/lib/types/update.d.ts.map +1 -1
  96. package/lib/types/update.js +232 -3
  97. package/node_modules/@deepseek-harness-tui/dsh-auth/LICENSE +21 -21
  98. package/node_modules/@deepseek-harness-tui/dsh-auth/dsh-plugin.json +44 -44
  99. package/node_modules/@dsh-std/command/CHANGELOG.md +8 -8
  100. package/node_modules/@dsh-std/command/LICENSE +21 -21
  101. package/node_modules/@dsh-std/command/README.md +26 -26
  102. package/node_modules/@dsh-std/command/README.zh.md +28 -28
  103. package/node_modules/@dsh-std/command/lib/index.js.map +1 -1
  104. package/node_modules/@dsh-std/command/package.json +22 -22
  105. package/node_modules/@dsh-std/connection/CHANGELOG.md +8 -8
  106. package/node_modules/@dsh-std/connection/LICENSE +21 -21
  107. package/node_modules/@dsh-std/connection/README.md +42 -42
  108. package/node_modules/@dsh-std/connection/README.zh.md +42 -42
  109. package/node_modules/@dsh-std/connection/lib/index.js.map +1 -1
  110. package/node_modules/@dsh-std/connection/lib/memory.js.map +1 -1
  111. package/node_modules/@dsh-std/connection/lib/resolve-3X6ausgz.js.map +1 -1
  112. package/node_modules/@dsh-std/connection/package.json +20 -20
  113. package/node_modules/@dsh-std/core/CHANGELOG.md +8 -8
  114. package/node_modules/@dsh-std/core/LICENSE +21 -21
  115. package/node_modules/@dsh-std/core/README.md +13 -13
  116. package/node_modules/@dsh-std/core/README.zh.md +13 -13
  117. package/node_modules/@dsh-std/core/lib/index.js.map +1 -1
  118. package/node_modules/@dsh-std/core/package.json +21 -21
  119. package/node_modules/@dsh-std/manifest/CHANGELOG.md +9 -9
  120. package/node_modules/@dsh-std/manifest/LICENSE +21 -21
  121. package/node_modules/@dsh-std/manifest/README.md +5 -5
  122. package/node_modules/@dsh-std/manifest/README.zh.md +5 -5
  123. package/node_modules/@dsh-std/manifest/lib/index.js.map +1 -1
  124. package/node_modules/@dsh-std/manifest/package.json +20 -20
  125. package/node_modules/@dsh-std/manifest/schema/dsh-plugin-0.15.schema.json +144 -144
  126. package/node_modules/@dsh-std/messages/CHANGELOG.md +8 -8
  127. package/node_modules/@dsh-std/messages/LICENSE +21 -21
  128. package/node_modules/@dsh-std/messages/README.md +5 -5
  129. package/node_modules/@dsh-std/messages/README.zh.md +7 -7
  130. package/node_modules/@dsh-std/messages/lib/index.js.map +1 -1
  131. package/node_modules/@dsh-std/messages/package.json +20 -20
  132. package/node_modules/@dsh-std/messages/schema/message-observer-envelope-0.15.schema.json +54 -54
  133. package/node_modules/@dsh-std/presentation/CHANGELOG.md +9 -9
  134. package/node_modules/@dsh-std/presentation/LICENSE +21 -21
  135. package/node_modules/@dsh-std/presentation/README.md +27 -27
  136. package/node_modules/@dsh-std/presentation/README.zh.md +29 -29
  137. package/node_modules/@dsh-std/presentation/lib/callback.js.map +1 -1
  138. package/node_modules/@dsh-std/presentation/lib/index.js.map +1 -1
  139. package/node_modules/@dsh-std/presentation/package.json +25 -25
  140. package/node_modules/@dsh-std/storage/CHANGELOG.md +8 -8
  141. package/node_modules/@dsh-std/storage/LICENSE +21 -21
  142. package/node_modules/@dsh-std/storage/README.md +5 -5
  143. package/node_modules/@dsh-std/storage/README.zh.md +7 -7
  144. package/node_modules/@dsh-std/storage/lib/index.js.map +1 -1
  145. package/node_modules/@dsh-std/storage/package.json +20 -20
  146. package/node_modules/@dsh-std/storage/schema/local-storage-0.15.schema.json +56 -56
  147. package/package.json +95 -5
  148. package/skills/pr-comments/SKILL.md +1 -1
  149. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/connection/CHANGELOG.md +8 -8
  150. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/connection/LICENSE +21 -21
  151. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/connection/README.md +42 -42
  152. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/connection/README.zh.md +42 -42
  153. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/connection/lib/index.js.map +1 -1
  154. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/connection/lib/memory.js.map +1 -1
  155. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/connection/lib/resolve-3X6ausgz.js.map +1 -1
  156. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/connection/package.json +20 -20
  157. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/core/CHANGELOG.md +8 -8
  158. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/core/LICENSE +21 -21
  159. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/core/README.md +13 -13
  160. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/core/README.zh.md +13 -13
  161. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/core/lib/index.js.map +1 -1
  162. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/core/package.json +21 -21
  163. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/manifest/CHANGELOG.md +9 -9
  164. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/manifest/LICENSE +21 -21
  165. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/manifest/README.md +5 -5
  166. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/manifest/README.zh.md +5 -5
  167. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/manifest/lib/index.js.map +1 -1
  168. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/manifest/package.json +20 -20
  169. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/manifest/schema/dsh-plugin-0.15.schema.json +144 -144
  170. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/presentation/CHANGELOG.md +9 -9
  171. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/presentation/LICENSE +21 -21
  172. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/presentation/README.md +27 -27
  173. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/presentation/README.zh.md +29 -29
  174. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/presentation/lib/callback.js.map +1 -1
  175. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/presentation/lib/index.js.map +1 -1
  176. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/presentation/package.json +25 -25
  177. package/vendor/dsh-std/packages/connection/node_modules/@dsh-std/core/CHANGELOG.md +8 -8
  178. package/vendor/dsh-std/packages/connection/node_modules/@dsh-std/core/LICENSE +21 -21
  179. package/vendor/dsh-std/packages/connection/node_modules/@dsh-std/core/README.md +13 -13
  180. package/vendor/dsh-std/packages/connection/node_modules/@dsh-std/core/README.zh.md +13 -13
  181. package/vendor/dsh-std/packages/connection/node_modules/@dsh-std/core/lib/index.js.map +1 -1
  182. package/vendor/dsh-std/packages/connection/node_modules/@dsh-std/core/package.json +21 -21
  183. package/vendor/dsh-std/packages/manifest/node_modules/@dsh-std/core/CHANGELOG.md +8 -8
  184. package/vendor/dsh-std/packages/manifest/node_modules/@dsh-std/core/LICENSE +21 -21
  185. package/vendor/dsh-std/packages/manifest/node_modules/@dsh-std/core/README.md +13 -13
  186. package/vendor/dsh-std/packages/manifest/node_modules/@dsh-std/core/README.zh.md +13 -13
  187. package/vendor/dsh-std/packages/manifest/node_modules/@dsh-std/core/lib/index.js.map +1 -1
  188. package/vendor/dsh-std/packages/manifest/node_modules/@dsh-std/core/package.json +21 -21
  189. package/vendor/dsh-std/packages/messages/node_modules/@dsh-std/core/CHANGELOG.md +8 -8
  190. package/vendor/dsh-std/packages/messages/node_modules/@dsh-std/core/LICENSE +21 -21
  191. package/vendor/dsh-std/packages/messages/node_modules/@dsh-std/core/README.md +13 -13
  192. package/vendor/dsh-std/packages/messages/node_modules/@dsh-std/core/README.zh.md +13 -13
  193. package/vendor/dsh-std/packages/messages/node_modules/@dsh-std/core/lib/index.js.map +1 -1
  194. package/vendor/dsh-std/packages/messages/node_modules/@dsh-std/core/package.json +21 -21
  195. package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/connection/CHANGELOG.md +8 -8
  196. package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/connection/LICENSE +21 -21
  197. package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/connection/README.md +42 -42
  198. package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/connection/README.zh.md +42 -42
  199. package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/connection/lib/index.js.map +1 -1
  200. package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/connection/lib/memory.js.map +1 -1
  201. package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/connection/lib/resolve-3X6ausgz.js.map +1 -1
  202. package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/connection/package.json +20 -20
  203. package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/core/CHANGELOG.md +8 -8
  204. package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/core/LICENSE +21 -21
  205. package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/core/README.md +13 -13
  206. package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/core/README.zh.md +13 -13
  207. package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/core/lib/index.js.map +1 -1
  208. package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/core/package.json +21 -21
  209. package/vendor/dsh-std/packages/storage/node_modules/@dsh-std/core/CHANGELOG.md +8 -8
  210. package/vendor/dsh-std/packages/storage/node_modules/@dsh-std/core/LICENSE +21 -21
  211. package/vendor/dsh-std/packages/storage/node_modules/@dsh-std/core/README.md +13 -13
  212. package/vendor/dsh-std/packages/storage/node_modules/@dsh-std/core/README.zh.md +13 -13
  213. package/vendor/dsh-std/packages/storage/node_modules/@dsh-std/core/lib/index.js.map +1 -1
  214. package/vendor/dsh-std/packages/storage/node_modules/@dsh-std/core/package.json +21 -21
@@ -1,143 +1,143 @@
1
- /** dsh-TUI private, lifecycle-owned manifest contribution definitions. */
2
-
3
- export const API_VERSION = 'tui.dsh/v1alpha1'
4
-
5
- export const SETTINGS_SECTION = Object.freeze({
6
- apiVersion: API_VERSION,
7
- kind: 'SettingsSection',
8
- })
9
-
10
- export const SCENE = Object.freeze({
11
- apiVersion: API_VERSION,
12
- kind: 'Scene',
13
- })
14
-
15
- export const settingsSectionExtensionDefinition = Object.freeze({
16
- ...SETTINGS_SECTION,
17
- validateMetadata(metadata) {
18
- contributionName(metadata?.name, 'SettingsSection metadata.name')
19
- },
20
- validateSpec: validateSettingsSectionSpec,
21
- })
22
-
23
- export function validateSettingsSectionSpec(value) {
24
- const spec = exactRecord(value, ['namespace', 'title', 'titles', 'fields'], 'SettingsSection content')
25
- contributionName(spec.namespace, 'SettingsSection content.namespace')
26
- nonEmpty(spec.title, 'SettingsSection content.title')
27
- localized(spec.titles, 'SettingsSection content.titles')
28
- if (!Array.isArray(spec.fields)) throw new TypeError('SettingsSection content.fields must be an array')
29
- return Object.freeze({
30
- namespace: spec.namespace,
31
- title: spec.title,
32
- ...(spec.titles === undefined ? {} : { titles: freezeRecord(spec.titles) }),
33
- fields: Object.freeze(spec.fields.map((field, index) => validateSettingsField(field, index))),
34
- })
35
- }
36
-
37
- export const sceneExtensionDefinition = Object.freeze({
38
- ...SCENE,
39
- validateMetadata(metadata) {
40
- contributionName(metadata?.name, 'Scene metadata.name')
41
- },
42
- validateSpec: validateSceneSpec,
43
- })
44
-
45
- export function validateSceneSpec(value) {
46
- const spec = exactRecord(value, ['title', 'titles'], 'Scene content')
47
- if (spec.title !== undefined) nonEmpty(spec.title, 'Scene content.title')
48
- localized(spec.titles, 'Scene content.titles')
49
- return Object.freeze({
50
- ...(spec.title === undefined ? {} : { title: spec.title }),
51
- ...(spec.titles === undefined ? {} : { titles: freezeRecord(spec.titles) }),
52
- })
53
- }
54
-
55
- export const contributionExtensionDefinitions = Object.freeze([
56
- settingsSectionExtensionDefinition,
57
- sceneExtensionDefinition,
58
- ])
59
-
60
- export function registerTuiContributionExtensions(catalog) {
61
- const disposers = contributionExtensionDefinitions.map(definition => catalog.registerExtension(definition))
62
- return () => { for (const dispose of disposers.reverse()) dispose() }
63
- }
64
-
65
- export function assertSettingsSectionHandler(value) {
66
- runtimeObject(value, 'SettingsSection handler')
67
- }
68
-
69
- export function assertSceneHandler(value) {
70
- const handler = runtimeObject(value, 'Scene handler')
71
- if (typeof handler.component !== 'function') throw new TypeError('Scene handler.component must be a function')
72
- }
73
-
74
- function validateSettingsField(value, index) {
75
- const label = `SettingsSection spec.fields[${index}]`
76
- const field = exactRecord(value, [
77
- 'path', 'label', 'titles', 'hint', 'hintTitles', 'kind', 'options', 'placeholder', 'secretRef',
78
- ], label)
79
- if (!Array.isArray(field.path) || field.path.length === 0
80
- || field.path.some(segment => typeof segment !== 'string' || segment.length === 0)) {
81
- throw new TypeError(`${label}.path must be a non-empty string array`)
82
- }
83
- nonEmpty(field.label, `${label}.label`)
84
- localized(field.titles, `${label}.titles`)
85
- if (field.hint !== undefined) nonEmpty(field.hint, `${label}.hint`)
86
- localized(field.hintTitles, `${label}.hintTitles`)
87
- if (!['text', 'number', 'boolean', 'select'].includes(field.kind)) {
88
- throw new TypeError(`${label}.kind is invalid`)
89
- }
90
- if (field.placeholder !== undefined && typeof field.placeholder !== 'string') {
91
- throw new TypeError(`${label}.placeholder must be a string`)
92
- }
93
- if (field.secretRef !== undefined) nonEmpty(field.secretRef, `${label}.secretRef`)
94
- if (field.options !== undefined) {
95
- if (!Array.isArray(field.options)) throw new TypeError(`${label}.options must be an array`)
96
- for (const [optionIndex, valueOption] of field.options.entries()) {
97
- const option = exactRecord(valueOption, ['value', 'label', 'titles'], `${label}.options[${optionIndex}]`)
98
- nonEmpty(option.value, `${label}.options[${optionIndex}].value`)
99
- nonEmpty(option.label, `${label}.options[${optionIndex}].label`)
100
- localized(option.titles, `${label}.options[${optionIndex}].titles`)
101
- }
102
- }
103
- return Object.freeze(structuredClone(field))
104
- }
105
-
106
- function exactRecord(value, allowed, label) {
107
- if (typeof value !== 'object' || value === null || Array.isArray(value)) {
108
- throw new TypeError(`${label} must be an object`)
109
- }
110
- const unknown = Object.keys(value).filter(key => !allowed.includes(key) && !key.startsWith('x-'))
111
- if (unknown.length > 0) throw new TypeError(`${label} contains unknown field ${JSON.stringify(unknown[0])}`)
112
- return value
113
- }
114
-
115
- function runtimeObject(value, label) {
116
- if ((typeof value !== 'object' && typeof value !== 'function') || value === null || Array.isArray(value)) {
117
- throw new TypeError(`${label} must be an object`)
118
- }
119
- return value
120
- }
121
-
122
- function contributionName(value, label) {
123
- if (typeof value !== 'string' || !/^[a-z][a-z0-9_-]*$/u.test(value)) {
124
- throw new TypeError(`${label} is invalid`)
125
- }
126
- }
127
-
128
- function nonEmpty(value, label) {
129
- if (typeof value !== 'string' || value.trim() === '') throw new TypeError(`${label} must be a non-empty string`)
130
- }
131
-
132
- function localized(value, label) {
133
- if (value === undefined) return
134
- const record = exactRecord(value, Object.keys(value), label)
135
- for (const [locale, text] of Object.entries(record)) {
136
- if (locale.trim() === '') throw new TypeError(`${label} contains an empty locale`)
137
- nonEmpty(text, `${label}.${locale}`)
138
- }
139
- }
140
-
141
- function freezeRecord(value) {
142
- return Object.freeze({ ...value })
143
- }
1
+ /** dsh-TUI private, lifecycle-owned manifest contribution definitions. */
2
+
3
+ export const API_VERSION = 'tui.dsh/v1alpha1'
4
+
5
+ export const SETTINGS_SECTION = Object.freeze({
6
+ apiVersion: API_VERSION,
7
+ kind: 'SettingsSection',
8
+ })
9
+
10
+ export const SCENE = Object.freeze({
11
+ apiVersion: API_VERSION,
12
+ kind: 'Scene',
13
+ })
14
+
15
+ export const settingsSectionExtensionDefinition = Object.freeze({
16
+ ...SETTINGS_SECTION,
17
+ validateMetadata(metadata) {
18
+ contributionName(metadata?.name, 'SettingsSection metadata.name')
19
+ },
20
+ validateSpec: validateSettingsSectionSpec,
21
+ })
22
+
23
+ export function validateSettingsSectionSpec(value) {
24
+ const spec = exactRecord(value, ['namespace', 'title', 'titles', 'fields'], 'SettingsSection content')
25
+ contributionName(spec.namespace, 'SettingsSection content.namespace')
26
+ nonEmpty(spec.title, 'SettingsSection content.title')
27
+ localized(spec.titles, 'SettingsSection content.titles')
28
+ if (!Array.isArray(spec.fields)) throw new TypeError('SettingsSection content.fields must be an array')
29
+ return Object.freeze({
30
+ namespace: spec.namespace,
31
+ title: spec.title,
32
+ ...(spec.titles === undefined ? {} : { titles: freezeRecord(spec.titles) }),
33
+ fields: Object.freeze(spec.fields.map((field, index) => validateSettingsField(field, index))),
34
+ })
35
+ }
36
+
37
+ export const sceneExtensionDefinition = Object.freeze({
38
+ ...SCENE,
39
+ validateMetadata(metadata) {
40
+ contributionName(metadata?.name, 'Scene metadata.name')
41
+ },
42
+ validateSpec: validateSceneSpec,
43
+ })
44
+
45
+ export function validateSceneSpec(value) {
46
+ const spec = exactRecord(value, ['title', 'titles'], 'Scene content')
47
+ if (spec.title !== undefined) nonEmpty(spec.title, 'Scene content.title')
48
+ localized(spec.titles, 'Scene content.titles')
49
+ return Object.freeze({
50
+ ...(spec.title === undefined ? {} : { title: spec.title }),
51
+ ...(spec.titles === undefined ? {} : { titles: freezeRecord(spec.titles) }),
52
+ })
53
+ }
54
+
55
+ export const contributionExtensionDefinitions = Object.freeze([
56
+ settingsSectionExtensionDefinition,
57
+ sceneExtensionDefinition,
58
+ ])
59
+
60
+ export function registerTuiContributionExtensions(catalog) {
61
+ const disposers = contributionExtensionDefinitions.map(definition => catalog.registerExtension(definition))
62
+ return () => { for (const dispose of disposers.reverse()) dispose() }
63
+ }
64
+
65
+ export function assertSettingsSectionHandler(value) {
66
+ runtimeObject(value, 'SettingsSection handler')
67
+ }
68
+
69
+ export function assertSceneHandler(value) {
70
+ const handler = runtimeObject(value, 'Scene handler')
71
+ if (typeof handler.component !== 'function') throw new TypeError('Scene handler.component must be a function')
72
+ }
73
+
74
+ function validateSettingsField(value, index) {
75
+ const label = `SettingsSection spec.fields[${index}]`
76
+ const field = exactRecord(value, [
77
+ 'path', 'label', 'titles', 'hint', 'hintTitles', 'kind', 'options', 'placeholder', 'secretRef',
78
+ ], label)
79
+ if (!Array.isArray(field.path) || field.path.length === 0
80
+ || field.path.some(segment => typeof segment !== 'string' || segment.length === 0)) {
81
+ throw new TypeError(`${label}.path must be a non-empty string array`)
82
+ }
83
+ nonEmpty(field.label, `${label}.label`)
84
+ localized(field.titles, `${label}.titles`)
85
+ if (field.hint !== undefined) nonEmpty(field.hint, `${label}.hint`)
86
+ localized(field.hintTitles, `${label}.hintTitles`)
87
+ if (!['text', 'number', 'boolean', 'select'].includes(field.kind)) {
88
+ throw new TypeError(`${label}.kind is invalid`)
89
+ }
90
+ if (field.placeholder !== undefined && typeof field.placeholder !== 'string') {
91
+ throw new TypeError(`${label}.placeholder must be a string`)
92
+ }
93
+ if (field.secretRef !== undefined) nonEmpty(field.secretRef, `${label}.secretRef`)
94
+ if (field.options !== undefined) {
95
+ if (!Array.isArray(field.options)) throw new TypeError(`${label}.options must be an array`)
96
+ for (const [optionIndex, valueOption] of field.options.entries()) {
97
+ const option = exactRecord(valueOption, ['value', 'label', 'titles'], `${label}.options[${optionIndex}]`)
98
+ nonEmpty(option.value, `${label}.options[${optionIndex}].value`)
99
+ nonEmpty(option.label, `${label}.options[${optionIndex}].label`)
100
+ localized(option.titles, `${label}.options[${optionIndex}].titles`)
101
+ }
102
+ }
103
+ return Object.freeze(structuredClone(field))
104
+ }
105
+
106
+ function exactRecord(value, allowed, label) {
107
+ if (typeof value !== 'object' || value === null || Array.isArray(value)) {
108
+ throw new TypeError(`${label} must be an object`)
109
+ }
110
+ const unknown = Object.keys(value).filter(key => !allowed.includes(key) && !key.startsWith('x-'))
111
+ if (unknown.length > 0) throw new TypeError(`${label} contains unknown field ${JSON.stringify(unknown[0])}`)
112
+ return value
113
+ }
114
+
115
+ function runtimeObject(value, label) {
116
+ if ((typeof value !== 'object' && typeof value !== 'function') || value === null || Array.isArray(value)) {
117
+ throw new TypeError(`${label} must be an object`)
118
+ }
119
+ return value
120
+ }
121
+
122
+ function contributionName(value, label) {
123
+ if (typeof value !== 'string' || !/^[a-z][a-z0-9_-]*$/u.test(value)) {
124
+ throw new TypeError(`${label} is invalid`)
125
+ }
126
+ }
127
+
128
+ function nonEmpty(value, label) {
129
+ if (typeof value !== 'string' || value.trim() === '') throw new TypeError(`${label} must be a non-empty string`)
130
+ }
131
+
132
+ function localized(value, label) {
133
+ if (value === undefined) return
134
+ const record = exactRecord(value, Object.keys(value), label)
135
+ for (const [locale, text] of Object.entries(record)) {
136
+ if (locale.trim() === '') throw new TypeError(`${label} contains an empty locale`)
137
+ nonEmpty(text, `${label}.${locale}`)
138
+ }
139
+ }
140
+
141
+ function freezeRecord(value) {
142
+ return Object.freeze({ ...value })
143
+ }
@@ -1,14 +1,14 @@
1
- # dsh-TUI Admission Protocol Profile
2
-
3
- [`registry-0.15.json`](registry-0.15.json) 不是全局协议注册表。它描述本 TUI admission profile 使用的 definition 集合:
4
-
5
- - `imports` 引用固定 dsh-std revision 已提供的 definitions;
6
- - `definitions` 只收录 dsh-TUI 私有 definitions。
7
-
8
- 导入条目不复制 dsh-std 的 schema 或 contract 正文。Community v0.15 的 `Command`、`LocalStorage`、`MessageObserver`、Presentation 与 Workspace 定义分别由 `@dsh-std/command`、`@dsh-std/storage`、`@dsh-std/messages`、`@dsh-std/presentation` 与 `@dsh-std/workspace` 注册。
9
-
10
- 本地 definition 的 contract profile 使用 SHA-256 固定。修改 profile 内容必须更新 digest,并按兼容性决定保留坐标或发布新 `apiVersion`。digest 只证明字节一致,不证明发布者身份。
11
-
12
- `tui.dsh/*` 是 dsh-TUI 私有 namespace。私有 definition 与公共 definition 一样注册到 dsh-std `ProtocolCatalog`;目录收录本身不产生 live support。
13
-
14
- 权限目录仍是 TUI authorization policy 的输入。permission grant 与 protocol support 分开判断,安装 definition 不自动授权操作。
1
+ # dsh-TUI Admission Protocol Profile
2
+
3
+ [`registry-0.15.json`](registry-0.15.json) 不是全局协议注册表。它描述本 TUI admission profile 使用的 definition 集合:
4
+
5
+ - `imports` 引用固定 dsh-std revision 已提供的 definitions;
6
+ - `definitions` 只收录 dsh-TUI 私有 definitions。
7
+
8
+ 导入条目不复制 dsh-std 的 schema 或 contract 正文。Community v0.15 的 `Command`、`LocalStorage`、`MessageObserver`、Presentation 与 Workspace 定义分别由 `@dsh-std/command`、`@dsh-std/storage`、`@dsh-std/messages`、`@dsh-std/presentation` 与 `@dsh-std/workspace` 注册。
9
+
10
+ 本地 definition 的 contract profile 使用 SHA-256 固定。修改 profile 内容必须更新 digest,并按兼容性决定保留坐标或发布新 `apiVersion`。digest 只证明字节一致,不证明发布者身份。
11
+
12
+ `tui.dsh/*` 是 dsh-TUI 私有 namespace。私有 definition 与公共 definition 一样注册到 dsh-std `ProtocolCatalog`;目录收录本身不产生 live support。
13
+
14
+ 权限目录仍是 TUI authorization policy 的输入。permission grant 与 protocol support 分开判断,安装 definition 不自动授权操作。
@@ -1,56 +1,56 @@
1
- {
2
- "$schema": "urn:dsh-tui:host-descriptor:0.15",
3
- "hostId": "dsh-tui",
4
- "hostVersion": "0.1.0-experimental",
5
- "facetApiVersions": [
6
- "v1alpha1"
7
- ],
8
- "contracts": [
9
- {
10
- "apiVersion": "storage.dsh/v1alpha1",
11
- "kind": "LocalStorage",
12
- "definition": {
13
- "source": "dsh-std",
14
- "package": "@dsh-std/storage"
15
- },
16
- "permissions": [
17
- "storage.local.read",
18
- "storage.local.write"
19
- ]
20
- },
21
- {
22
- "apiVersion": "commands.dsh/v1alpha1",
23
- "kind": "Command",
24
- "definition": {
25
- "source": "dsh-std",
26
- "package": "@dsh-std/command"
27
- },
28
- "permissions": [
29
- "commands.invoke"
30
- ]
31
- },
32
- {
33
- "apiVersion": "messages.dsh/v1alpha1",
34
- "kind": "MessageObserver",
35
- "definition": {
36
- "source": "dsh-std",
37
- "package": "@dsh-std/messages"
38
- },
39
- "permissions": [
40
- "messages.observe.read"
41
- ]
42
- }
43
- ],
44
- "runtime": {
45
- "location": "remote",
46
- "generationId": "example-generation-1",
47
- "headless": true,
48
- "remoteAttach": true
49
- },
50
- "trustLevel": "trusted-in-process",
51
- "platform": {
52
- "os": "linux",
53
- "arch": "x64",
54
- "node": ">=22.19"
55
- }
56
- }
1
+ {
2
+ "$schema": "urn:dsh-tui:host-descriptor:0.15",
3
+ "hostId": "dsh-tui",
4
+ "hostVersion": "0.1.0-experimental",
5
+ "facetApiVersions": [
6
+ "v1alpha1"
7
+ ],
8
+ "contracts": [
9
+ {
10
+ "apiVersion": "storage.dsh/v1alpha1",
11
+ "kind": "LocalStorage",
12
+ "definition": {
13
+ "source": "dsh-std",
14
+ "package": "@dsh-std/storage"
15
+ },
16
+ "permissions": [
17
+ "storage.local.read",
18
+ "storage.local.write"
19
+ ]
20
+ },
21
+ {
22
+ "apiVersion": "commands.dsh/v1alpha1",
23
+ "kind": "Command",
24
+ "definition": {
25
+ "source": "dsh-std",
26
+ "package": "@dsh-std/command"
27
+ },
28
+ "permissions": [
29
+ "commands.invoke"
30
+ ]
31
+ },
32
+ {
33
+ "apiVersion": "messages.dsh/v1alpha1",
34
+ "kind": "MessageObserver",
35
+ "definition": {
36
+ "source": "dsh-std",
37
+ "package": "@dsh-std/messages"
38
+ },
39
+ "permissions": [
40
+ "messages.observe.read"
41
+ ]
42
+ }
43
+ ],
44
+ "runtime": {
45
+ "location": "remote",
46
+ "generationId": "example-generation-1",
47
+ "headless": true,
48
+ "remoteAttach": true
49
+ },
50
+ "trustLevel": "trusted-in-process",
51
+ "platform": {
52
+ "os": "linux",
53
+ "arch": "x64",
54
+ "node": ">=22.19"
55
+ }
56
+ }
@@ -1,13 +1,13 @@
1
- {
2
- "registryVersion":"0.1",
3
- "permissions":[
4
- {"name":"storage.local.read","default":"deny","revocable":true,"scope":"plugin namespace"},
5
- {"name":"storage.local.write","default":"deny","revocable":true,"scope":"plugin namespace"},
6
- {"name":"commands.invoke","default":"allow","revocable":true,"scope":"declared command id","rationale":"调用由宿主或用户通过一次 invocation 主动发起,不同于数据访问类权限——插件无法仅凭此权限被动读取任何数据,故默认允许;撤销只关闭该 command ID 的调用入口"},
7
- {"name":"messages.observe.read","default":"deny","revocable":true,"scope":"message observation scope"},
8
- {"name":"session.input.intercept","default":"deny","revocable":true,"scope":"decision event subscription","rationale":"拦截类订阅(RFC 0005 D-7):能否决/改写用户输入,严格强于观察,故默认拒绝;TUI 实验实现见 tui.dsh.decision-events"},
9
- {"name":"session.rewind.intercept","default":"deny","revocable":true,"scope":"decision event subscription","rationale":"同 session.input.intercept——可否决会话回退或注入回退模式"},
10
- {"name":"session.switch.intercept","default":"deny","revocable":true,"scope":"decision event subscription","rationale":"同 session.input.intercept——可否决会话切换"},
11
- {"name":"session.compact.intercept","default":"deny","revocable":true,"scope":"decision event subscription","rationale":"同 session.input.intercept——可否决手动压缩"}
12
- ]
13
- }
1
+ {
2
+ "registryVersion":"0.1",
3
+ "permissions":[
4
+ {"name":"storage.local.read","default":"deny","revocable":true,"scope":"plugin namespace"},
5
+ {"name":"storage.local.write","default":"deny","revocable":true,"scope":"plugin namespace"},
6
+ {"name":"commands.invoke","default":"allow","revocable":true,"scope":"declared command id","rationale":"调用由宿主或用户通过一次 invocation 主动发起,不同于数据访问类权限——插件无法仅凭此权限被动读取任何数据,故默认允许;撤销只关闭该 command ID 的调用入口"},
7
+ {"name":"messages.observe.read","default":"deny","revocable":true,"scope":"message observation scope"},
8
+ {"name":"session.input.intercept","default":"deny","revocable":true,"scope":"decision event subscription","rationale":"拦截类订阅(RFC 0005 D-7):能否决/改写用户输入,严格强于观察,故默认拒绝;TUI 实验实现见 tui.dsh.decision-events"},
9
+ {"name":"session.rewind.intercept","default":"deny","revocable":true,"scope":"decision event subscription","rationale":"同 session.input.intercept——可否决会话回退或注入回退模式"},
10
+ {"name":"session.switch.intercept","default":"deny","revocable":true,"scope":"decision event subscription","rationale":"同 session.input.intercept——可否决会话切换"},
11
+ {"name":"session.compact.intercept","default":"deny","revocable":true,"scope":"decision event subscription","rationale":"同 session.input.intercept——可否决手动压缩"}
12
+ ]
13
+ }