@deepseek-harness-tui/dsh-tui 0.8.1 → 0.8.2

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 (240) hide show
  1. package/README.md +22 -13
  2. package/dsh-ecosystem-spec/protocols/profile-definitions.d.ts +13 -0
  3. package/dsh-ecosystem-spec/protocols/profile-definitions.js +59 -0
  4. package/dsh-ecosystem-spec/protocols/tui-channel-http.d.ts +15 -0
  5. package/dsh-ecosystem-spec/protocols/tui-channel-http.js +32 -0
  6. package/dsh-ecosystem-spec/protocols/tui-channel.d.ts +59 -0
  7. package/dsh-ecosystem-spec/protocols/tui-channel.js +166 -0
  8. package/dsh-ecosystem-spec/protocols/tui-contributions.d.ts +42 -0
  9. package/dsh-ecosystem-spec/protocols/tui-contributions.js +143 -0
  10. package/dsh-ecosystem-spec/registry/README.md +14 -0
  11. package/dsh-ecosystem-spec/registry/contracts/scene-v1alpha1.json +13 -0
  12. package/dsh-ecosystem-spec/registry/contracts/settings-section-v1alpha1.json +13 -0
  13. package/dsh-ecosystem-spec/registry/contracts/tui-channel-v1alpha1.json +30 -0
  14. package/dsh-ecosystem-spec/registry/contracts/workspace-provider-v1alpha1.json +6 -0
  15. package/{ecosystem-spec → dsh-ecosystem-spec}/registry/permissions-0.1.json +1 -1
  16. package/dsh-ecosystem-spec/registry/registry-0.15.json +149 -0
  17. package/lib/types/command-trees.d.ts +2 -1
  18. package/lib/types/command-trees.d.ts.map +1 -1
  19. package/lib/types/command-trees.js +1 -1
  20. package/lib/types/components/LoadedContextPanel.d.ts +10 -5
  21. package/lib/types/components/LoadedContextPanel.d.ts.map +1 -1
  22. package/lib/types/components/LoadedContextPanel.js +18 -7
  23. package/lib/types/components/LogoV2.d.ts.map +1 -1
  24. package/lib/types/components/LogoV2.js +16 -7
  25. package/lib/types/components/Markdown.d.ts +13 -1
  26. package/lib/types/components/Markdown.d.ts.map +1 -1
  27. package/lib/types/components/Markdown.js +15 -1
  28. package/lib/types/components/MessageList.d.ts +3 -1
  29. package/lib/types/components/MessageList.d.ts.map +1 -1
  30. package/lib/types/components/MessageList.js +90 -9
  31. package/lib/types/components/PromptInput.d.ts.map +1 -1
  32. package/lib/types/components/PromptInput.js +26 -12
  33. package/lib/types/components/StreamingMarkdown.d.ts +2 -8
  34. package/lib/types/components/StreamingMarkdown.d.ts.map +1 -1
  35. package/lib/types/components/StreamingMarkdown.js +51 -9
  36. package/lib/types/components/activityFrames.d.ts +1 -1
  37. package/lib/types/components/activityFrames.d.ts.map +1 -1
  38. package/lib/types/components/activityFrames.js +4 -1
  39. package/lib/types/components/messages/AssistantThinkingMessage.d.ts +5 -1
  40. package/lib/types/components/messages/AssistantThinkingMessage.d.ts.map +1 -1
  41. package/lib/types/components/messages/AssistantThinkingMessage.js +26 -3
  42. package/lib/types/components/messages/AssistantToolUseMessage.d.ts.map +1 -1
  43. package/lib/types/components/messages/AssistantToolUseMessage.js +12 -1
  44. package/lib/types/dsh-adapter/channel.d.ts +31 -4
  45. package/lib/types/dsh-adapter/channel.d.ts.map +1 -1
  46. package/lib/types/dsh-adapter/channel.js +267 -102
  47. package/lib/types/dsh-adapter/childStderr.d.ts.map +1 -1
  48. package/lib/types/dsh-adapter/childStderr.js +10 -0
  49. package/lib/types/dsh-adapter/command-attribution.d.ts.map +1 -1
  50. package/lib/types/dsh-adapter/command-attribution.js +2 -2
  51. package/lib/types/dsh-adapter/command-trees.d.ts +7 -1
  52. package/lib/types/dsh-adapter/command-trees.d.ts.map +1 -1
  53. package/lib/types/dsh-adapter/command-trees.js +70 -20
  54. package/lib/types/dsh-adapter/component-identity.d.ts +5 -0
  55. package/lib/types/dsh-adapter/component-identity.d.ts.map +1 -1
  56. package/lib/types/dsh-adapter/component-identity.js +14 -14
  57. package/lib/types/dsh-adapter/decision-guard.d.ts.map +1 -1
  58. package/lib/types/dsh-adapter/decision-guard.js +10 -16
  59. package/lib/types/dsh-adapter/dialogs.d.ts +2 -3
  60. package/lib/types/dsh-adapter/dialogs.d.ts.map +1 -1
  61. package/lib/types/dsh-adapter/dialogs.js +114 -60
  62. package/lib/types/dsh-adapter/effect-ledger.d.ts +0 -8
  63. package/lib/types/dsh-adapter/effect-ledger.d.ts.map +1 -1
  64. package/lib/types/dsh-adapter/effect-ledger.js +73 -53
  65. package/lib/types/dsh-adapter/extension-events.d.ts.map +1 -1
  66. package/lib/types/dsh-adapter/extension-events.js +39 -1
  67. package/lib/types/dsh-adapter/grants.d.ts.map +1 -1
  68. package/lib/types/dsh-adapter/grants.js +43 -14
  69. package/lib/types/dsh-adapter/host-access.d.ts +37 -0
  70. package/lib/types/dsh-adapter/host-access.d.ts.map +1 -0
  71. package/lib/types/dsh-adapter/host-access.js +652 -0
  72. package/lib/types/dsh-adapter/host-descriptor.d.ts +2 -2
  73. package/lib/types/dsh-adapter/host-descriptor.d.ts.map +1 -1
  74. package/lib/types/dsh-adapter/host-descriptor.js +31 -8
  75. package/lib/types/dsh-adapter/index.d.ts +4 -0
  76. package/lib/types/dsh-adapter/index.d.ts.map +1 -1
  77. package/lib/types/dsh-adapter/index.js +1 -0
  78. package/lib/types/dsh-adapter/message-observer.d.ts +10 -15
  79. package/lib/types/dsh-adapter/message-observer.d.ts.map +1 -1
  80. package/lib/types/dsh-adapter/message-observer.js +114 -70
  81. package/lib/types/dsh-adapter/plugin-host.d.ts +39 -6
  82. package/lib/types/dsh-adapter/plugin-host.d.ts.map +1 -1
  83. package/lib/types/dsh-adapter/plugin-host.js +139 -44
  84. package/lib/types/dsh-adapter/plugin-storage.d.ts +0 -5
  85. package/lib/types/dsh-adapter/plugin-storage.d.ts.map +1 -1
  86. package/lib/types/dsh-adapter/plugin-storage.js +48 -36
  87. package/lib/types/dsh-adapter/plugin.d.ts.map +1 -1
  88. package/lib/types/dsh-adapter/plugin.js +80 -16
  89. package/lib/types/dsh-adapter/promptDebug.d.ts +0 -6
  90. package/lib/types/dsh-adapter/promptDebug.d.ts.map +1 -1
  91. package/lib/types/dsh-adapter/promptDebug.js +13 -4
  92. package/lib/types/dsh-adapter/renderers.d.ts +6 -14
  93. package/lib/types/dsh-adapter/renderers.d.ts.map +1 -1
  94. package/lib/types/dsh-adapter/renderers.js +81 -46
  95. package/lib/types/dsh-adapter/scenes.d.ts +8 -4
  96. package/lib/types/dsh-adapter/scenes.d.ts.map +1 -1
  97. package/lib/types/dsh-adapter/scenes.js +136 -37
  98. package/lib/types/dsh-adapter/settings-sections.d.ts +7 -3
  99. package/lib/types/dsh-adapter/settings-sections.d.ts.map +1 -1
  100. package/lib/types/dsh-adapter/settings-sections.js +106 -26
  101. package/lib/types/dsh-adapter/shortcuts.d.ts +8 -10
  102. package/lib/types/dsh-adapter/shortcuts.d.ts.map +1 -1
  103. package/lib/types/dsh-adapter/shortcuts.js +108 -36
  104. package/lib/types/dsh-adapter/status.d.ts +6 -7
  105. package/lib/types/dsh-adapter/status.d.ts.map +1 -1
  106. package/lib/types/dsh-adapter/status.js +88 -22
  107. package/lib/types/dsh-adapter/workspaces.d.ts +16 -5
  108. package/lib/types/dsh-adapter/workspaces.d.ts.map +1 -1
  109. package/lib/types/dsh-adapter/workspaces.js +287 -170
  110. package/lib/types/extensions.d.ts +10 -5
  111. package/lib/types/extensions.d.ts.map +1 -1
  112. package/lib/types/extensions.js +11 -5
  113. package/lib/types/force-production-react.d.ts +1 -0
  114. package/lib/types/force-production-react.d.ts.map +1 -0
  115. package/lib/types/force-production-react.js +12 -0
  116. package/lib/types/i18n.d.ts +14 -6
  117. package/lib/types/i18n.d.ts.map +1 -1
  118. package/lib/types/i18n.js +4 -2
  119. package/lib/types/index.d.ts +1 -0
  120. package/lib/types/index.d.ts.map +1 -1
  121. package/lib/types/index.js +1 -0
  122. package/lib/types/ink/components/App.d.ts +2 -0
  123. package/lib/types/ink/components/App.d.ts.map +1 -1
  124. package/lib/types/ink/components/App.js +4 -0
  125. package/lib/types/ink/ink.d.ts +20 -3
  126. package/lib/types/ink/ink.d.ts.map +1 -1
  127. package/lib/types/ink/ink.js +57 -5
  128. package/lib/types/ink/log-update.d.ts.map +1 -1
  129. package/lib/types/ink/log-update.js +128 -9
  130. package/lib/types/ink/output.d.ts +28 -2
  131. package/lib/types/ink/output.d.ts.map +1 -1
  132. package/lib/types/ink/output.js +158 -12
  133. package/lib/types/ink/screen.d.ts +39 -0
  134. package/lib/types/ink/screen.d.ts.map +1 -1
  135. package/lib/types/ink/screen.js +117 -0
  136. package/lib/types/ink/terminal.d.ts.map +1 -1
  137. package/lib/types/ink/terminal.js +10 -2
  138. package/lib/types/ink/wrapAnsi.d.ts +1 -1
  139. package/lib/types/ink/wrapAnsi.d.ts.map +1 -1
  140. package/lib/types/ink/wrapAnsi.js +29 -2
  141. package/lib/types/plugin-host.d.ts +13 -11
  142. package/lib/types/plugin-host.d.ts.map +1 -1
  143. package/lib/types/plugin-host.js +16 -16
  144. package/lib/types/plugin-spec/registry.d.ts +2 -2
  145. package/lib/types/plugin-spec/registry.d.ts.map +1 -1
  146. package/lib/types/plugin-spec/registry.js +113 -18
  147. package/lib/types/plugin-spec/tui-extension.d.ts.map +1 -1
  148. package/lib/types/plugin-spec/tui-extension.js +2 -0
  149. package/lib/types/plugin-spec/validate.d.ts.map +1 -1
  150. package/lib/types/plugin-spec/validate.js +20 -1
  151. package/lib/types/scenes.d.ts +2 -1
  152. package/lib/types/scenes.d.ts.map +1 -1
  153. package/lib/types/scenes.js +1 -1
  154. package/lib/types/screens/Chat.d.ts +3 -3
  155. package/lib/types/screens/Chat.d.ts.map +1 -1
  156. package/lib/types/screens/Chat.js +38 -17
  157. package/lib/types/screens/SessionBrowser.d.ts.map +1 -1
  158. package/lib/types/screens/SessionBrowser.js +10 -3
  159. package/lib/types/sessions/view.d.ts +3 -2
  160. package/lib/types/sessions/view.d.ts.map +1 -1
  161. package/lib/types/sessions/view.js +18 -0
  162. package/lib/types/settings-sections.d.ts +2 -1
  163. package/lib/types/settings-sections.d.ts.map +1 -1
  164. package/lib/types/settings-sections.js +1 -1
  165. package/lib/types/utils/execFileNoThrow.d.ts.map +1 -1
  166. package/lib/types/utils/execFileNoThrow.js +3 -0
  167. package/lib/types/workspaces.d.ts +2 -1
  168. package/lib/types/workspaces.d.ts.map +1 -1
  169. package/lib/types/workspaces.js +1 -1
  170. package/node_modules/@dsh-std/command/CHANGELOG.md +8 -0
  171. package/node_modules/@dsh-std/command/package.json +1 -1
  172. package/node_modules/@dsh-std/connection/CHANGELOG.md +8 -0
  173. package/node_modules/@dsh-std/connection/lib/memory.d.ts +1 -1
  174. package/node_modules/@dsh-std/connection/lib/memory.d.ts.map +1 -1
  175. package/node_modules/@dsh-std/connection/lib/memory.js +1 -0
  176. package/node_modules/@dsh-std/connection/lib/memory.js.map +1 -1
  177. package/node_modules/@dsh-std/connection/package.json +1 -1
  178. package/node_modules/@dsh-std/core/CHANGELOG.md +8 -0
  179. package/node_modules/@dsh-std/core/package.json +1 -1
  180. package/node_modules/@dsh-std/manifest/CHANGELOG.md +9 -0
  181. package/node_modules/@dsh-std/manifest/package.json +1 -1
  182. package/node_modules/@dsh-std/messages/CHANGELOG.md +8 -0
  183. package/node_modules/@dsh-std/messages/package.json +1 -1
  184. package/node_modules/@dsh-std/presentation/CHANGELOG.md +9 -0
  185. package/node_modules/@dsh-std/presentation/README.md +2 -1
  186. package/node_modules/@dsh-std/presentation/README.zh.md +2 -1
  187. package/node_modules/@dsh-std/presentation/lib/callback.d.ts +2 -0
  188. package/node_modules/@dsh-std/presentation/lib/callback.js +179 -0
  189. package/node_modules/@dsh-std/presentation/lib/callback.js.map +1 -0
  190. package/node_modules/@dsh-std/presentation/lib/index.d.ts +44 -1
  191. package/node_modules/@dsh-std/presentation/lib/index.d.ts.map +1 -1
  192. package/node_modules/@dsh-std/presentation/lib/index.js +6 -3
  193. package/node_modules/@dsh-std/presentation/lib/index.js.map +1 -1
  194. package/node_modules/@dsh-std/presentation/package.json +7 -3
  195. package/node_modules/@dsh-std/storage/CHANGELOG.md +8 -0
  196. package/node_modules/@dsh-std/storage/package.json +1 -1
  197. package/package.json +10 -5
  198. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/connection/CHANGELOG.md +8 -0
  199. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/connection/lib/memory.d.ts +1 -1
  200. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/connection/lib/memory.d.ts.map +1 -1
  201. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/connection/lib/memory.js +1 -0
  202. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/connection/lib/memory.js.map +1 -1
  203. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/connection/package.json +1 -1
  204. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/core/CHANGELOG.md +8 -0
  205. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/core/package.json +1 -1
  206. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/manifest/CHANGELOG.md +9 -0
  207. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/manifest/package.json +1 -1
  208. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/presentation/CHANGELOG.md +9 -0
  209. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/presentation/README.md +2 -1
  210. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/presentation/README.zh.md +2 -1
  211. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/presentation/lib/callback.d.ts +2 -0
  212. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/presentation/lib/callback.js +179 -0
  213. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/presentation/lib/callback.js.map +1 -0
  214. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/presentation/lib/index.d.ts +44 -1
  215. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/presentation/lib/index.d.ts.map +1 -1
  216. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/presentation/lib/index.js +6 -3
  217. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/presentation/lib/index.js.map +1 -1
  218. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/presentation/package.json +7 -3
  219. package/vendor/dsh-std/packages/connection/node_modules/@dsh-std/core/CHANGELOG.md +8 -0
  220. package/vendor/dsh-std/packages/connection/node_modules/@dsh-std/core/package.json +1 -1
  221. package/vendor/dsh-std/packages/manifest/node_modules/@dsh-std/core/CHANGELOG.md +8 -0
  222. package/vendor/dsh-std/packages/manifest/node_modules/@dsh-std/core/package.json +1 -1
  223. package/vendor/dsh-std/packages/messages/node_modules/@dsh-std/core/CHANGELOG.md +8 -0
  224. package/vendor/dsh-std/packages/messages/node_modules/@dsh-std/core/package.json +1 -1
  225. package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/connection/CHANGELOG.md +8 -0
  226. package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/connection/lib/memory.d.ts +1 -1
  227. package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/connection/lib/memory.d.ts.map +1 -1
  228. package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/connection/lib/memory.js +1 -0
  229. package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/connection/lib/memory.js.map +1 -1
  230. package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/connection/package.json +1 -1
  231. package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/core/CHANGELOG.md +8 -0
  232. package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/core/package.json +1 -1
  233. package/vendor/dsh-std/packages/storage/node_modules/@dsh-std/core/CHANGELOG.md +8 -0
  234. package/vendor/dsh-std/packages/storage/node_modules/@dsh-std/core/package.json +1 -1
  235. package/ecosystem-spec/registry/registry-0.15.json +0 -57
  236. /package/{ecosystem-spec → dsh-ecosystem-spec}/registry/contracts/decision-events-v1alpha1.json +0 -0
  237. /package/{ecosystem-spec → dsh-ecosystem-spec}/registry/host-descriptor.tui.example.json +0 -0
  238. /package/{ecosystem-spec → dsh-ecosystem-spec}/schemas/conformance-claim.schema.json +0 -0
  239. /package/{ecosystem-spec → dsh-ecosystem-spec}/schemas/effect-ledger-record.schema.json +0 -0
  240. /package/{ecosystem-spec → dsh-ecosystem-spec}/schemas/host-descriptor.schema.json +0 -0
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../src/index.ts"],"sourcesContent":["import type {\n ProtocolCatalog,\n ProtocolDefinition,\n ProtocolIssue,\n ProtocolNegotiationInput,\n ProtocolRequirement,\n ProtocolSupport,\n} from '@dsh-std/core'\nimport type {\n CapabilityClient,\n CapabilityHandlerContext,\n CapabilityImplementation,\n ConnectionNegotiationPolicy,\n} from '@dsh-std/connection'\nimport { defineCapabilityProtocol } from '@dsh-std/connection'\n\nexport const API_VERSION = 'presentation.dsh/v1alpha1'\nexport const OPEN_EXTERNAL_KIND = 'OpenExternal'\nexport const COPY_TEXT_KIND = 'CopyText'\nexport const NOTIFICATION_KIND = 'Notification'\nexport const USER_INTERACTION_KIND = 'UserInteraction'\n\nexport interface PresentationDescriptor {\n /** Endpoint identity selected and authenticated by the Host for this invocation. */\n readonly clientId: string\n /** Active Presentation agreements projected into this invocation. */\n readonly contracts: readonly ProtocolSupport[]\n}\n\nexport interface PresentationRequestContext {\n readonly requestId: string\n readonly invocationId: string\n readonly origin: string\n readonly deadline?: string\n}\n\n/** Invocation authority supplied by the Host when it creates scoped clients. */\nexport interface PresentationInvocationScope {\n readonly invocationId: string\n readonly origin: string\n readonly deadline?: string\n nextRequestId(): string\n}\n\nexport type PresentationResult<T> =\n | { readonly status: 'submitted'; readonly value: T }\n | { readonly status: 'cancelled' }\n | { readonly status: 'expired' }\n | { readonly status: 'unavailable'; readonly reason?: string }\n\nexport interface OpenExternalRequest extends PresentationRequestContext {\n readonly uri: string\n}\n\nexport type OpenExternalInput = Omit<OpenExternalRequest, keyof PresentationRequestContext>\n\nexport interface OpenExternalReceipt { readonly accepted: true }\n\nexport interface CopyTextRequest extends PresentationRequestContext {\n readonly text: string\n readonly sensitivity?: 'public' | 'private'\n}\n\nexport type CopyTextInput = Omit<CopyTextRequest, keyof PresentationRequestContext>\n\nexport interface CopyTextReceipt { readonly accepted: true }\n\nexport interface NotificationRequest extends PresentationRequestContext {\n readonly text: string\n readonly level?: 'info' | 'warning' | 'error'\n readonly deduplicationKey?: string\n}\n\nexport type NotificationInput = Omit<NotificationRequest, keyof PresentationRequestContext>\n\nexport interface NotificationReceipt { readonly accepted: true }\n\nexport type UserInteractionOperation = 'question' | 'approval' | 'secret-input'\n\nexport interface UserInteractionRequirementSpec {\n readonly operations: readonly UserInteractionOperation[]\n readonly optionalOperations?: readonly UserInteractionOperation[]\n}\n\nexport interface UserInteractionLimits {\n readonly maxConcurrentRequests?: number\n readonly maxFields?: number\n readonly maxOptionsPerField?: number\n readonly maxTextLength?: number\n}\n\nexport interface UserInteractionSupportSpec {\n readonly operations: readonly UserInteractionOperation[]\n readonly limits?: UserInteractionLimits\n}\n\nexport interface QuestionOption {\n readonly id: string\n readonly label: string\n readonly description?: string\n}\n\ninterface QuestionFieldBase {\n readonly id: string\n readonly label: string\n readonly description?: string\n readonly required?: boolean\n}\n\nexport interface TextQuestionField extends QuestionFieldBase {\n readonly kind: 'text'\n readonly multiline?: boolean\n readonly minLength?: number\n readonly maxLength?: number\n}\n\nexport interface SelectQuestionField extends QuestionFieldBase {\n readonly kind: 'select'\n readonly multiple?: boolean\n readonly options: readonly QuestionOption[]\n}\n\nexport interface ConfirmQuestionField extends QuestionFieldBase {\n readonly kind: 'confirm'\n}\n\nexport type QuestionField = TextQuestionField | SelectQuestionField | ConfirmQuestionField\n\nexport interface QuestionRequest extends PresentationRequestContext {\n readonly kind: 'question'\n readonly title?: string\n readonly description?: string\n readonly fields: readonly QuestionField[]\n}\n\nexport interface QuestionAnswers {\n readonly answers: Readonly<Record<string, string | boolean | readonly string[]>>\n}\n\nexport interface ApprovalDetail {\n readonly label: string\n readonly value: string\n readonly sensitivity?: 'public' | 'private'\n}\n\nexport interface ApprovalRequest extends PresentationRequestContext {\n readonly kind: 'approval'\n readonly action: string\n readonly summary: string\n readonly details?: readonly ApprovalDetail[]\n readonly risk?: 'low' | 'medium' | 'high'\n}\n\nexport interface ApprovalValue { readonly decision: 'approved' | 'denied' }\n\nexport interface SecretInputRequest extends PresentationRequestContext {\n readonly kind: 'secret-input'\n readonly label: string\n readonly description?: string\n readonly minLength?: number\n readonly maxLength?: number\n}\n\nexport interface SecretInputValue { readonly secret: string }\n\nexport type UserInteractionRequest = QuestionRequest | ApprovalRequest | SecretInputRequest\nexport type UserInteractionValue = QuestionAnswers | ApprovalValue | SecretInputValue\nexport type QuestionInput = Omit<QuestionRequest, keyof PresentationRequestContext>\nexport type ApprovalInput = Omit<ApprovalRequest, keyof PresentationRequestContext>\nexport type SecretInput = Omit<SecretInputRequest, keyof PresentationRequestContext>\n\nexport interface OpenExternalClient {\n openExternal(input: OpenExternalInput, options?: { readonly signal?: AbortSignal }): Promise<PresentationResult<OpenExternalReceipt>>\n}\n\nexport interface CopyTextClient {\n copyText(input: CopyTextInput, options?: { readonly signal?: AbortSignal }): Promise<PresentationResult<CopyTextReceipt>>\n}\n\nexport interface NotificationClient {\n notify(input: NotificationInput, options?: { readonly signal?: AbortSignal }): Promise<PresentationResult<NotificationReceipt>>\n}\n\nexport interface UserInteractionClient {\n interact(input: QuestionInput, options?: { readonly signal?: AbortSignal }): Promise<PresentationResult<QuestionAnswers>>\n interact(input: ApprovalInput, options?: { readonly signal?: AbortSignal }): Promise<PresentationResult<ApprovalValue>>\n interact(input: SecretInput, options?: { readonly signal?: AbortSignal }): Promise<PresentationResult<SecretInputValue>>\n}\n\n/** Typed Presentation capabilities available to one domain invocation. */\nexport interface PresentationClients {\n readonly descriptor: PresentationDescriptor\n readonly openExternal?: OpenExternalClient\n readonly copyText?: CopyTextClient\n readonly notification?: NotificationClient\n readonly interaction?: UserInteractionClient\n}\n\nexport interface OpenExternalHandler {\n openExternal(request: OpenExternalRequest, context: CapabilityHandlerContext): PresentationResult<OpenExternalReceipt> | Promise<PresentationResult<OpenExternalReceipt>>\n}\n\nexport interface CopyTextHandler {\n copyText(request: CopyTextRequest, context: CapabilityHandlerContext): PresentationResult<CopyTextReceipt> | Promise<PresentationResult<CopyTextReceipt>>\n}\n\nexport interface NotificationHandler {\n notify(request: NotificationRequest, context: CapabilityHandlerContext): PresentationResult<NotificationReceipt> | Promise<PresentationResult<NotificationReceipt>>\n}\n\nexport interface UserInteractionHandler {\n interact(request: QuestionRequest, context: CapabilityHandlerContext): PresentationResult<QuestionAnswers> | Promise<PresentationResult<QuestionAnswers>>\n interact(request: ApprovalRequest, context: CapabilityHandlerContext): PresentationResult<ApprovalValue> | Promise<PresentationResult<ApprovalValue>>\n interact(request: SecretInputRequest, context: CapabilityHandlerContext): PresentationResult<SecretInputValue> | Promise<PresentationResult<SecretInputValue>>\n}\n\nconst emptySpec = (value: unknown): undefined => {\n if (value !== undefined) throw new TypeError('Presentation operation does not accept spec in v1alpha1')\n return undefined\n}\n\nexport const openExternalProtocol = defineCapabilityProtocol({\n apiVersion: API_VERSION, kind: OPEN_EXTERNAL_KIND, validateRequirement: emptySpec, validateSupport: emptySpec,\n})\nexport const copyTextProtocol = defineCapabilityProtocol({\n apiVersion: API_VERSION, kind: COPY_TEXT_KIND, validateRequirement: emptySpec, validateSupport: emptySpec,\n})\nexport const notificationProtocol = defineCapabilityProtocol({\n apiVersion: API_VERSION, kind: NOTIFICATION_KIND, validateRequirement: emptySpec, validateSupport: emptySpec,\n})\n\nexport const openExternalSupport: ProtocolSupport = Object.freeze({ apiVersion: API_VERSION, kind: OPEN_EXTERNAL_KIND })\nexport const copyTextSupport: ProtocolSupport = Object.freeze({ apiVersion: API_VERSION, kind: COPY_TEXT_KIND })\nexport const notificationSupport: ProtocolSupport = Object.freeze({ apiVersion: API_VERSION, kind: NOTIFICATION_KIND })\nexport const userInteractionSupport = (spec: UserInteractionSupportSpec): ProtocolSupport<UserInteractionSupportSpec> =>\n Object.freeze({ apiVersion: API_VERSION, kind: USER_INTERACTION_KIND, spec: validateUserInteractionSupport(spec) })\n\nexport const userInteractionProtocol: ProtocolDefinition<\n UserInteractionRequirementSpec,\n UserInteractionSupportSpec\n> = Object.freeze({\n apiVersion: API_VERSION,\n kind: USER_INTERACTION_KIND,\n validateRequirement: validateUserInteractionRequirement,\n validateSupport: validateUserInteractionSupport,\n negotiate: negotiateUserInteraction,\n})\n\nexport const protocols: readonly ProtocolDefinition[] = Object.freeze([\n openExternalProtocol,\n copyTextProtocol,\n notificationProtocol,\n userInteractionProtocol,\n])\n\nexport function register(catalog: ProtocolCatalog): () => void {\n const disposers = protocols.map(protocol => catalog.register(protocol))\n return () => { for (const dispose of disposers.reverse()) dispose() }\n}\n\nexport function openExternalClient(client: CapabilityClient, scope: PresentationInvocationScope): OpenExternalClient {\n const request = requestFactory(scope)\n return Object.freeze({\n async openExternal(input: OpenExternalInput, options?: { readonly signal?: AbortSignal }) {\n const value = request(input)\n validateOpenExternalRequest(value)\n const result = await client.invoke<OpenExternalRequest, PresentationResult<OpenExternalReceipt>>(\n openExternalSupport, 'openExternal', value, options,\n ).result\n return validatePresentationResult(result, validateAcceptedReceipt, 'OpenExternal result')\n },\n })\n}\n\nexport function copyTextClient(client: CapabilityClient, scope: PresentationInvocationScope): CopyTextClient {\n const request = requestFactory(scope)\n return Object.freeze({\n async copyText(input: CopyTextInput, options?: { readonly signal?: AbortSignal }) {\n const value = request(input)\n validateCopyTextRequest(value)\n const result = await client.invoke<CopyTextRequest, PresentationResult<CopyTextReceipt>>(\n copyTextSupport, 'copyText', value, options,\n ).result\n return validatePresentationResult(result, validateAcceptedReceipt, 'CopyText result')\n },\n })\n}\n\nexport function notificationClient(client: CapabilityClient, scope: PresentationInvocationScope): NotificationClient {\n const request = requestFactory(scope)\n return Object.freeze({\n async notify(input: NotificationInput, options?: { readonly signal?: AbortSignal }) {\n const value = request(input)\n validateNotificationRequest(value)\n const result = await client.invoke<NotificationRequest, PresentationResult<NotificationReceipt>>(\n notificationSupport, 'notify', value, options,\n ).result\n return validatePresentationResult(result, validateAcceptedReceipt, 'Notification result')\n },\n })\n}\n\nexport function userInteractionClient(client: CapabilityClient, scope: PresentationInvocationScope): UserInteractionClient {\n const request = requestFactory(scope)\n return Object.freeze({\n async interact(input: QuestionInput | ApprovalInput | SecretInput, options?: { readonly signal?: AbortSignal }): Promise<PresentationResult<UserInteractionValue>> {\n const value = request(input) as UserInteractionRequest\n validateUserInteractionRequest(value)\n const result = await client.invoke<UserInteractionRequest, PresentationResult<UserInteractionValue>>(\n { apiVersion: API_VERSION, kind: USER_INTERACTION_KIND }, 'interact', value, options,\n ).result\n return validateInteractionResult(value, result)\n },\n }) as UserInteractionClient\n}\n\nexport function presentationClients(\n descriptor: PresentationDescriptor,\n client: CapabilityClient,\n scope: PresentationInvocationScope,\n): PresentationClients {\n validatePresentationDescriptor(descriptor)\n validateInvocationScope(scope)\n const has = (kind: string) => descriptor.contracts.some(contract =>\n contract.apiVersion === API_VERSION && contract.kind === kind && client.binding(contract) !== undefined)\n return Object.freeze({\n descriptor: freezeClone(descriptor),\n ...(has(OPEN_EXTERNAL_KIND) ? { openExternal: openExternalClient(client, scope) } : {}),\n ...(has(COPY_TEXT_KIND) ? { copyText: copyTextClient(client, scope) } : {}),\n ...(has(NOTIFICATION_KIND) ? { notification: notificationClient(client, scope) } : {}),\n ...(has(USER_INTERACTION_KIND) ? { interaction: userInteractionClient(client, scope) } : {}),\n })\n}\n\nexport function openExternalImplementation(participantId: string, handler: OpenExternalHandler): CapabilityImplementation {\n return implementation(participantId, openExternalSupport, 'openExternal', validateOpenExternalRequest, handler.openExternal.bind(handler),\n result => validatePresentationResult(result, validateAcceptedReceipt, 'OpenExternal result'))\n}\n\nexport function copyTextImplementation(participantId: string, handler: CopyTextHandler): CapabilityImplementation {\n return implementation(participantId, copyTextSupport, 'copyText', validateCopyTextRequest, handler.copyText.bind(handler),\n result => validatePresentationResult(result, validateAcceptedReceipt, 'CopyText result'))\n}\n\nexport function notificationImplementation(participantId: string, handler: NotificationHandler): CapabilityImplementation {\n return implementation(participantId, notificationSupport, 'notify', validateNotificationRequest, handler.notify.bind(handler),\n result => validatePresentationResult(result, validateAcceptedReceipt, 'Notification result'))\n}\n\nexport function userInteractionImplementation(\n participantId: string,\n spec: UserInteractionSupportSpec,\n handler: UserInteractionHandler,\n): CapabilityImplementation {\n const protocol = userInteractionSupport(spec)\n return Object.freeze({\n participantId,\n protocol,\n async handle(operationName: string, input: unknown, context: CapabilityHandlerContext) {\n if (operationName !== 'interact') throw new TypeError(`unsupported UserInteraction operation ${JSON.stringify(operationName)}`)\n validateUserInteractionRequest(input)\n if (!spec.operations.includes(input.kind)) throw new TypeError(`UserInteraction provider does not support ${JSON.stringify(input.kind)}`)\n const result = await handler.interact(input as never, context)\n return validateInteractionResult(input, result)\n },\n })\n}\n\nexport function validatePresentationDescriptor(value: unknown): asserts value is PresentationDescriptor {\n const descriptor = exactRecord(value, ['clientId', 'contracts'], ['clientId', 'contracts'], 'Presentation descriptor')\n nonEmpty(descriptor.clientId, 'Presentation descriptor.clientId')\n if (!Array.isArray(descriptor.contracts)) throw new TypeError('Presentation descriptor.contracts must be an array')\n const seen = new Set<string>()\n for (const [index, contractValue] of descriptor.contracts.entries()) {\n const contract = exactRecord(contractValue, ['apiVersion', 'kind', 'spec'], ['apiVersion', 'kind'], `Presentation descriptor.contracts[${index}]`)\n nonEmpty(contract.apiVersion, `Presentation descriptor.contracts[${index}].apiVersion`)\n nonEmpty(contract.kind, `Presentation descriptor.contracts[${index}].kind`)\n const key = `${String(contract.apiVersion)}\\0${String(contract.kind)}`\n if (seen.has(key)) throw new TypeError(`Presentation descriptor contains duplicate contract ${JSON.stringify(key)}`)\n seen.add(key)\n }\n}\n\nexport function validateOpenExternalRequest(value: unknown): asserts value is OpenExternalRequest {\n const request = requestRecord(value, ['uri'], 'OpenExternal request')\n nonEmpty(request.uri, 'OpenExternal request.uri')\n const uri = new URL(request.uri as string)\n if (uri.protocol !== 'https:' && uri.protocol !== 'http:') throw new TypeError('OpenExternal only accepts HTTP(S) URIs')\n}\n\nexport function validateCopyTextRequest(value: unknown): asserts value is CopyTextRequest {\n const request = requestRecord(value, ['text', 'sensitivity'], 'CopyText request')\n nonEmpty(request.text, 'CopyText request.text')\n if (request.sensitivity !== undefined && request.sensitivity !== 'public' && request.sensitivity !== 'private') {\n throw new TypeError('CopyText request.sensitivity is invalid')\n }\n}\n\nexport function validateNotificationRequest(value: unknown): asserts value is NotificationRequest {\n const request = requestRecord(value, ['text', 'level', 'deduplicationKey'], 'Notification request')\n nonEmpty(request.text, 'Notification request.text')\n if (request.level !== undefined && request.level !== 'info' && request.level !== 'warning' && request.level !== 'error') {\n throw new TypeError('Notification request.level is invalid')\n }\n if (request.deduplicationKey !== undefined) nonEmpty(request.deduplicationKey, 'Notification request.deduplicationKey')\n}\n\nexport function validateUserInteractionRequest(value: unknown): asserts value is UserInteractionRequest {\n if (!record(value)) throw new TypeError('UserInteraction request must be an object')\n if (value.kind === 'question') return validateQuestionRequest(value)\n if (value.kind === 'approval') return validateApprovalRequest(value)\n if (value.kind === 'secret-input') return validateSecretInputRequest(value)\n throw new TypeError('UserInteraction request.kind is invalid')\n}\n\nexport function validateUserInteractionRequirement(value: unknown): UserInteractionRequirementSpec {\n const spec = exactRecord(value, ['operations', 'optionalOperations'], ['operations'], 'UserInteraction requirement spec')\n const operations = operationList(spec.operations, 'UserInteraction requirement spec.operations')\n const optionalOperations = spec.optionalOperations === undefined\n ? undefined\n : operationList(spec.optionalOperations, 'UserInteraction requirement spec.optionalOperations')\n if (optionalOperations?.some(operation => operations.includes(operation)) === true) {\n throw new TypeError('UserInteraction optionalOperations must not duplicate required operations')\n }\n return deepFreeze({ operations, ...(optionalOperations === undefined ? {} : { optionalOperations }) })\n}\n\nexport function validateUserInteractionSupport(value: unknown): UserInteractionSupportSpec {\n const spec = exactRecord(value, ['operations', 'limits'], ['operations'], 'UserInteraction support spec')\n const operations = operationList(spec.operations, 'UserInteraction support spec.operations')\n const limits = spec.limits === undefined ? undefined : validateLimits(spec.limits)\n return deepFreeze({ operations, ...(limits === undefined ? {} : { limits }) })\n}\n\nfunction negotiateUserInteraction(\n input: ProtocolNegotiationInput<UserInteractionRequirementSpec, UserInteractionSupportSpec>,\n) {\n const issues: ProtocolIssue[] = []\n const bindings: Array<{\n readonly consumer: string\n readonly provider: string\n readonly requirement: ProtocolRequirement<UserInteractionRequirementSpec>\n readonly support: ProtocolSupport<UserInteractionSupportSpec>\n }> = []\n const connectionPolicy = connectionNegotiationPolicy(input.policy)\n for (const row of input.requirements) {\n const consumerEndpoint = connectionPolicy?.endpointByParticipant[row.participant]\n const candidates = input.supports.filter(candidate => {\n if (candidate.participant === row.participant) return false\n if (consumerEndpoint !== undefined && connectionPolicy?.endpointByParticipant[candidate.participant] === consumerEndpoint) return false\n return row.requirement.spec!.operations.every(operation => candidate.support.spec!.operations.includes(operation))\n })\n if (candidates.length === 0) {\n issues.push(Object.freeze({\n code: row.requirement.optional === true ? 'optional-support-missing' : 'required-support-missing',\n severity: row.requirement.optional === true ? 'warning' : 'error',\n participant: row.participant,\n message: `no participant supports the required ${USER_INTERACTION_KIND} operations`,\n }))\n continue\n }\n if (candidates.length > 1) {\n issues.push(Object.freeze({\n code: 'support-ambiguous', severity: 'error', participant: row.participant,\n message: `multiple participants support ${API_VERSION} ${USER_INTERACTION_KIND}`,\n }))\n continue\n }\n const provider = candidates[0]!\n bindings.push(Object.freeze({\n consumer: row.participant,\n provider: provider.participant,\n requirement: row.requirement,\n support: provider.support,\n }))\n for (const operation of row.requirement.spec!.optionalOperations ?? []) {\n if (provider.support.spec!.operations.includes(operation)) continue\n issues.push(Object.freeze({\n code: 'optional-operation-missing', severity: 'warning', participant: row.participant,\n message: `${USER_INTERACTION_KIND} provider does not support optional operation ${JSON.stringify(operation)}`,\n }))\n }\n }\n return {\n agreement: Object.freeze({ kind: 'CapabilityBindings' as const, bindings: Object.freeze(bindings) }),\n issues: Object.freeze(issues),\n }\n}\n\nfunction connectionNegotiationPolicy(value: unknown): ConnectionNegotiationPolicy | undefined {\n return record(value) && record(value.endpointByParticipant)\n ? value as unknown as ConnectionNegotiationPolicy\n : undefined\n}\n\nfunction implementation<TInput, TOutput>(\n participantId: string,\n protocol: ProtocolSupport,\n operationName: string,\n validateInput: (value: unknown) => asserts value is TInput,\n handler: (input: TInput, context: CapabilityHandlerContext) => TOutput | Promise<TOutput>,\n validateOutput: (value: unknown) => TOutput,\n): CapabilityImplementation {\n return Object.freeze({\n participantId,\n protocol,\n async handle(operation: string, input: unknown, context: CapabilityHandlerContext) {\n if (operation !== operationName) throw new TypeError(`unsupported ${protocol.kind} operation ${JSON.stringify(operation)}`)\n validateInput(input)\n return validateOutput(await handler(input, context))\n },\n })\n}\n\nfunction validateQuestionRequest(value: unknown): asserts value is QuestionRequest {\n const request = requestRecord(value, ['kind', 'title', 'description', 'fields'], 'Question request')\n if (request.kind !== 'question') throw new TypeError('Question request.kind must be \"question\"')\n optionalText(request.title, 'Question request.title')\n optionalText(request.description, 'Question request.description')\n if (!Array.isArray(request.fields) || request.fields.length === 0) throw new TypeError('Question request.fields must be a non-empty array')\n const ids = new Set<string>()\n for (const [index, fieldValue] of request.fields.entries()) {\n const label = `Question request.fields[${index}]`\n if (!record(fieldValue)) throw new TypeError(`${label} must be an object`)\n const common = ['id', 'kind', 'label', 'description', 'required']\n const allowed = fieldValue.kind === 'text' ? [...common, 'multiline', 'minLength', 'maxLength']\n : fieldValue.kind === 'select' ? [...common, 'multiple', 'options'] : common\n const field = exactRecord(fieldValue, allowed, ['id', 'kind', 'label'], label)\n localId(field.id, `${label}.id`)\n if (ids.has(field.id as string)) throw new TypeError('Question request contains duplicate field id')\n ids.add(field.id as string)\n nonEmpty(field.label, `${label}.label`)\n optionalText(field.description, `${label}.description`)\n optionalBoolean(field.required, `${label}.required`)\n if (field.kind === 'text') {\n optionalBoolean(field.multiline, `${label}.multiline`)\n lengthBounds(field.minLength, field.maxLength, label)\n } else if (field.kind === 'select') {\n optionalBoolean(field.multiple, `${label}.multiple`)\n if (!Array.isArray(field.options) || field.options.length === 0) throw new TypeError(`${label}.options must be a non-empty array`)\n const options = new Set<string>()\n for (const [optionIndex, optionValue] of field.options.entries()) {\n const optionLabel = `${label}.options[${optionIndex}]`\n const option = exactRecord(optionValue, ['id', 'label', 'description'], ['id', 'label'], optionLabel)\n localId(option.id, `${optionLabel}.id`)\n if (options.has(option.id as string)) throw new TypeError(`${label} contains duplicate option id`)\n options.add(option.id as string)\n nonEmpty(option.label, `${optionLabel}.label`)\n optionalText(option.description, `${optionLabel}.description`)\n }\n } else if (field.kind !== 'confirm') {\n throw new TypeError(`${label}.kind is invalid`)\n }\n }\n}\n\nfunction validateApprovalRequest(value: unknown): asserts value is ApprovalRequest {\n const request = requestRecord(value, ['kind', 'action', 'summary', 'details', 'risk'], 'Approval request')\n if (request.kind !== 'approval') throw new TypeError('Approval request.kind must be \"approval\"')\n nonEmpty(request.action, 'Approval request.action')\n nonEmpty(request.summary, 'Approval request.summary')\n if (request.risk !== undefined && request.risk !== 'low' && request.risk !== 'medium' && request.risk !== 'high') {\n throw new TypeError('Approval request.risk is invalid')\n }\n if (request.details !== undefined) {\n if (!Array.isArray(request.details)) throw new TypeError('Approval request.details must be an array')\n for (const [index, detailValue] of request.details.entries()) {\n const label = `Approval request.details[${index}]`\n const detail = exactRecord(detailValue, ['label', 'value', 'sensitivity'], ['label', 'value'], label)\n nonEmpty(detail.label, `${label}.label`)\n nonEmpty(detail.value, `${label}.value`)\n if (detail.sensitivity !== undefined && detail.sensitivity !== 'public' && detail.sensitivity !== 'private') {\n throw new TypeError(`${label}.sensitivity is invalid`)\n }\n }\n }\n}\n\nfunction validateSecretInputRequest(value: unknown): asserts value is SecretInputRequest {\n const request = requestRecord(value, ['kind', 'label', 'description', 'minLength', 'maxLength'], 'SecretInput request')\n if (request.kind !== 'secret-input') throw new TypeError('SecretInput request.kind must be \"secret-input\"')\n nonEmpty(request.label, 'SecretInput request.label')\n optionalText(request.description, 'SecretInput request.description')\n lengthBounds(request.minLength, request.maxLength, 'SecretInput request')\n}\n\nfunction validateInteractionResult(\n request: UserInteractionRequest,\n value: unknown,\n): PresentationResult<UserInteractionValue> {\n if (request.kind === 'question') return validatePresentationResult(value, result => validateQuestionAnswers(request, result), 'Question result')\n if (request.kind === 'approval') return validatePresentationResult(value, validateApprovalValue, 'Approval result')\n return validatePresentationResult(value, result => validateSecretInputValue(request, result), 'SecretInput result')\n}\n\nfunction validateQuestionAnswers(request: QuestionRequest, value: unknown): QuestionAnswers {\n const result = exactRecord(value, ['answers'], ['answers'], 'Question answers')\n if (!record(result.answers)) throw new TypeError('Question answers.answers must be an object')\n const fields = new Map(request.fields.map(field => [field.id, field]))\n for (const field of request.fields) {\n if (field.required === true && !Object.hasOwn(result.answers, field.id)) throw new TypeError(`Question answers is missing required field ${JSON.stringify(field.id)}`)\n }\n for (const [id, answer] of Object.entries(result.answers)) {\n const field = fields.get(id)\n if (field === undefined) throw new TypeError(`Question answers contains unknown field ${JSON.stringify(id)}`)\n if (field.kind === 'text') {\n if (typeof answer !== 'string') throw new TypeError(`Question answer ${JSON.stringify(id)} must be a string`)\n if (field.minLength !== undefined && answer.length < field.minLength) throw new TypeError(`Question answer ${JSON.stringify(id)} is too short`)\n if (field.maxLength !== undefined && answer.length > field.maxLength) throw new TypeError(`Question answer ${JSON.stringify(id)} is too long`)\n } else if (field.kind === 'confirm') {\n if (typeof answer !== 'boolean') throw new TypeError(`Question answer ${JSON.stringify(id)} must be boolean`)\n } else {\n const allowed = new Set(field.options.map(option => option.id))\n const selected = field.multiple === true ? answer : [answer]\n if (!Array.isArray(selected) || selected.some(option => typeof option !== 'string' || !allowed.has(option))) {\n throw new TypeError(`Question answer ${JSON.stringify(id)} contains an invalid option`)\n }\n }\n }\n return freezeClone(value as QuestionAnswers)\n}\n\nfunction validateApprovalValue(value: unknown): ApprovalValue {\n const result = exactRecord(value, ['decision'], ['decision'], 'Approval value')\n if (result.decision !== 'approved' && result.decision !== 'denied') throw new TypeError('Approval value.decision is invalid')\n return freezeClone(value as ApprovalValue)\n}\n\nfunction validateSecretInputValue(request: SecretInputRequest, value: unknown): SecretInputValue {\n const result = exactRecord(value, ['secret'], ['secret'], 'SecretInput value')\n if (typeof result.secret !== 'string') throw new TypeError('SecretInput value.secret must be a string')\n if (request.minLength !== undefined && result.secret.length < request.minLength) throw new TypeError('SecretInput value.secret is too short')\n if (request.maxLength !== undefined && result.secret.length > request.maxLength) throw new TypeError('SecretInput value.secret is too long')\n return freezeClone(value as SecretInputValue)\n}\n\nfunction validatePresentationResult<T>(\n value: unknown,\n validateSubmitted: (submitted: unknown) => T,\n label: string,\n): PresentationResult<T> {\n if (!record(value)) throw new TypeError(`${label} must be an object`)\n if (value.status === 'submitted') {\n const result = exactRecord(value, ['status', 'value'], ['status', 'value'], label)\n return deepFreeze({ status: 'submitted' as const, value: validateSubmitted(result.value) })\n }\n if (value.status === 'unavailable') {\n const result = exactRecord(value, ['status', 'reason'], ['status'], label)\n optionalText(result.reason, `${label}.reason`)\n return freezeClone(value as PresentationResult<T>)\n }\n if (value.status === 'cancelled' || value.status === 'expired') {\n exactRecord(value, ['status'], ['status'], label)\n return freezeClone(value as PresentationResult<T>)\n }\n throw new TypeError(`${label}.status is invalid`)\n}\n\nfunction validateAcceptedReceipt(value: unknown): { readonly accepted: true } {\n const receipt = exactRecord(value, ['accepted'], ['accepted'], 'Presentation receipt')\n if (receipt.accepted !== true) throw new TypeError('Presentation receipt.accepted must be true')\n return Object.freeze({ accepted: true })\n}\n\nfunction requestRecord(value: unknown, fields: readonly string[], label: string): Record<string, unknown> {\n const required = ['requestId', 'invocationId', 'origin', ...fields.filter(field => !['title', 'description', 'details', 'risk', 'level', 'deduplicationKey', 'sensitivity', 'minLength', 'maxLength'].includes(field))]\n const request = exactRecord(value, ['requestId', 'invocationId', 'origin', 'deadline', ...fields], required, label)\n nonEmpty(request.requestId, `${label}.requestId`)\n nonEmpty(request.invocationId, `${label}.invocationId`)\n nonEmpty(request.origin, `${label}.origin`)\n if (request.deadline !== undefined && (typeof request.deadline !== 'string' || Number.isNaN(Date.parse(request.deadline)))) {\n throw new TypeError(`${label}.deadline must be an RFC 3339 date-time`)\n }\n return request\n}\n\nfunction validateLimits(value: unknown): UserInteractionLimits {\n const limits = exactRecord(\n value,\n ['maxConcurrentRequests', 'maxFields', 'maxOptionsPerField', 'maxTextLength'],\n [],\n 'UserInteraction limits',\n )\n for (const [name, limit] of Object.entries(limits)) positiveInteger(limit, `UserInteraction limits.${name}`)\n return freezeClone(value as UserInteractionLimits)\n}\n\nfunction operationList(value: unknown, label: string): readonly UserInteractionOperation[] {\n if (!Array.isArray(value) || value.length === 0) throw new TypeError(`${label} must be a non-empty array`)\n const operations = value.map(operation => {\n if (operation !== 'question' && operation !== 'approval' && operation !== 'secret-input') throw new TypeError(`${label} contains an invalid operation`)\n return operation\n })\n if (new Set(operations).size !== operations.length) throw new TypeError(`${label} contains a duplicate operation`)\n return Object.freeze(operations)\n}\n\nfunction lengthBounds(minimum: unknown, maximum: unknown, label: string): void {\n if (minimum !== undefined) nonNegativeInteger(minimum, `${label}.minLength`)\n if (maximum !== undefined) nonNegativeInteger(maximum, `${label}.maxLength`)\n if (typeof minimum === 'number' && typeof maximum === 'number' && minimum > maximum) {\n throw new TypeError(`${label}.minLength must not exceed maxLength`)\n }\n}\n\nfunction exactRecord(value: unknown, allowed: readonly string[], required: readonly string[], label: string): Record<string, unknown> {\n if (!record(value)) throw new TypeError(`${label} must be an object`)\n const unknown = Object.keys(value).filter(key => !allowed.includes(key))\n if (unknown.length > 0) throw new TypeError(`${label} contains unknown field ${JSON.stringify(unknown[0])}`)\n for (const key of required) if (!Object.hasOwn(value, key)) throw new TypeError(`${label}.${key} is required`)\n return value\n}\n\nfunction record(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value)\n}\n\nfunction nonEmpty(value: unknown, label: string): asserts value is string {\n if (typeof value !== 'string' || value.trim() === '') throw new TypeError(`${label} must be a non-empty string`)\n}\n\nfunction validateInvocationScope(scope: PresentationInvocationScope): void {\n if (!record(scope)) throw new TypeError('Presentation invocation scope must be an object')\n nonEmpty(scope.invocationId, 'Presentation invocation scope.invocationId')\n nonEmpty(scope.origin, 'Presentation invocation scope.origin')\n if (scope.deadline !== undefined && (typeof scope.deadline !== 'string' || Number.isNaN(Date.parse(scope.deadline)))) {\n throw new TypeError('Presentation invocation scope.deadline must be an RFC 3339 date-time')\n }\n if (typeof scope.nextRequestId !== 'function') throw new TypeError('Presentation invocation scope.nextRequestId must be a function')\n}\n\nfunction requestFactory(scope: PresentationInvocationScope) {\n validateInvocationScope(scope)\n return <T extends object>(input: T): Readonly<T & PresentationRequestContext> => {\n if (!record(input)) throw new TypeError('Presentation input must be an object')\n const requestId = scope.nextRequestId()\n nonEmpty(requestId, 'Presentation requestId')\n return freezeClone({\n ...input,\n requestId,\n invocationId: scope.invocationId,\n origin: scope.origin,\n ...(scope.deadline === undefined ? {} : { deadline: scope.deadline }),\n })\n }\n}\n\nfunction optionalText(value: unknown, label: string): void {\n if (value !== undefined) nonEmpty(value, label)\n}\n\nfunction optionalBoolean(value: unknown, label: string): void {\n if (value !== undefined && typeof value !== 'boolean') throw new TypeError(`${label} must be boolean`)\n}\n\nfunction localId(value: unknown, label: string): asserts value is string {\n if (typeof value !== 'string' || !/^[A-Za-z][A-Za-z0-9._-]*$/u.test(value)) throw new TypeError(`${label} is invalid`)\n}\n\nfunction positiveInteger(value: unknown, label: string): void {\n if (!Number.isSafeInteger(value) || (value as number) < 1) throw new TypeError(`${label} must be a positive safe integer`)\n}\n\nfunction nonNegativeInteger(value: unknown, label: string): void {\n if (!Number.isSafeInteger(value) || (value as number) < 0) throw new TypeError(`${label} must be a non-negative safe integer`)\n}\n\nfunction freezeClone<T>(value: T): T { return deepFreeze(structuredClone(value)) }\n\nfunction deepFreeze<T>(value: T): T {\n if (typeof value !== 'object' || value === null || Object.isFrozen(value)) return value\n Object.freeze(value)\n for (const child of Object.values(value)) deepFreeze(child)\n return value\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../src/index.ts"],"sourcesContent":["import type {\n ProtocolCatalog,\n ProtocolDefinition,\n ProtocolIssue,\n ProtocolNegotiationInput,\n ProtocolRequirement,\n ProtocolSupport,\n} from '@dsh-std/core'\nimport type {\n CapabilityClient,\n CapabilityHandlerContext,\n CapabilityImplementation,\n ConnectionNegotiationPolicy,\n} from '@dsh-std/connection'\nimport { defineCapabilityProtocol } from '@dsh-std/connection'\nimport { EXTERNAL_REDIRECT_KIND, externalRedirectClient, externalRedirectProtocol } from './callback.js'\nimport type { ExternalRedirectClient } from './callback.js'\n\nexport * from './callback.js'\n\nexport const API_VERSION = 'presentation.dsh/v1alpha1'\nexport const OPEN_EXTERNAL_KIND = 'OpenExternal'\nexport const COPY_TEXT_KIND = 'CopyText'\nexport const NOTIFICATION_KIND = 'Notification'\nexport const USER_INTERACTION_KIND = 'UserInteraction'\n\nexport interface PresentationDescriptor {\n /** Endpoint identity selected and authenticated by the Host for this invocation. */\n readonly clientId: string\n /** Active Presentation agreements projected into this invocation. */\n readonly contracts: readonly ProtocolSupport[]\n}\n\nexport interface PresentationRequestContext {\n readonly requestId: string\n readonly invocationId: string\n readonly origin: string\n readonly deadline?: string\n}\n\n/** Invocation authority supplied by the Host when it creates scoped clients. */\nexport interface PresentationInvocationScope {\n readonly invocationId: string\n readonly origin: string\n readonly deadline?: string\n nextRequestId(): string\n}\n\nexport type PresentationResult<T> =\n | { readonly status: 'submitted'; readonly value: T }\n | { readonly status: 'cancelled' }\n | { readonly status: 'expired' }\n | { readonly status: 'unavailable'; readonly reason?: string }\n\nexport interface OpenExternalRequest extends PresentationRequestContext {\n readonly uri: string\n}\n\nexport type OpenExternalInput = Omit<OpenExternalRequest, keyof PresentationRequestContext>\n\nexport interface OpenExternalReceipt { readonly accepted: true }\n\nexport interface CopyTextRequest extends PresentationRequestContext {\n readonly text: string\n readonly sensitivity?: 'public' | 'private'\n}\n\nexport type CopyTextInput = Omit<CopyTextRequest, keyof PresentationRequestContext>\n\nexport interface CopyTextReceipt { readonly accepted: true }\n\nexport interface NotificationRequest extends PresentationRequestContext {\n readonly text: string\n readonly level?: 'info' | 'warning' | 'error'\n readonly deduplicationKey?: string\n}\n\nexport type NotificationInput = Omit<NotificationRequest, keyof PresentationRequestContext>\n\nexport interface NotificationReceipt { readonly accepted: true }\n\nexport type UserInteractionOperation = 'question' | 'approval' | 'secret-input'\n\nexport interface UserInteractionRequirementSpec {\n readonly operations: readonly UserInteractionOperation[]\n readonly optionalOperations?: readonly UserInteractionOperation[]\n}\n\nexport interface UserInteractionLimits {\n readonly maxConcurrentRequests?: number\n readonly maxFields?: number\n readonly maxOptionsPerField?: number\n readonly maxTextLength?: number\n}\n\nexport interface UserInteractionSupportSpec {\n readonly operations: readonly UserInteractionOperation[]\n readonly limits?: UserInteractionLimits\n}\n\nexport interface QuestionOption {\n readonly id: string\n readonly label: string\n readonly description?: string\n}\n\ninterface QuestionFieldBase {\n readonly id: string\n readonly label: string\n readonly description?: string\n readonly required?: boolean\n}\n\nexport interface TextQuestionField extends QuestionFieldBase {\n readonly kind: 'text'\n readonly multiline?: boolean\n readonly minLength?: number\n readonly maxLength?: number\n}\n\nexport interface SelectQuestionField extends QuestionFieldBase {\n readonly kind: 'select'\n readonly multiple?: boolean\n readonly options: readonly QuestionOption[]\n}\n\nexport interface ConfirmQuestionField extends QuestionFieldBase {\n readonly kind: 'confirm'\n}\n\nexport type QuestionField = TextQuestionField | SelectQuestionField | ConfirmQuestionField\n\nexport interface QuestionRequest extends PresentationRequestContext {\n readonly kind: 'question'\n readonly title?: string\n readonly description?: string\n readonly fields: readonly QuestionField[]\n}\n\nexport interface QuestionAnswers {\n readonly answers: Readonly<Record<string, string | boolean | readonly string[]>>\n}\n\nexport interface ApprovalDetail {\n readonly label: string\n readonly value: string\n readonly sensitivity?: 'public' | 'private'\n}\n\nexport interface ApprovalRequest extends PresentationRequestContext {\n readonly kind: 'approval'\n readonly action: string\n readonly summary: string\n readonly details?: readonly ApprovalDetail[]\n readonly risk?: 'low' | 'medium' | 'high'\n}\n\nexport interface ApprovalValue { readonly decision: 'approved' | 'denied' }\n\nexport interface SecretInputRequest extends PresentationRequestContext {\n readonly kind: 'secret-input'\n readonly label: string\n readonly description?: string\n readonly minLength?: number\n readonly maxLength?: number\n}\n\nexport interface SecretInputValue { readonly secret: string }\n\nexport type UserInteractionRequest = QuestionRequest | ApprovalRequest | SecretInputRequest\nexport type UserInteractionValue = QuestionAnswers | ApprovalValue | SecretInputValue\nexport type QuestionInput = Omit<QuestionRequest, keyof PresentationRequestContext>\nexport type ApprovalInput = Omit<ApprovalRequest, keyof PresentationRequestContext>\nexport type SecretInput = Omit<SecretInputRequest, keyof PresentationRequestContext>\n\nexport interface OpenExternalClient {\n openExternal(input: OpenExternalInput, options?: { readonly signal?: AbortSignal }): Promise<PresentationResult<OpenExternalReceipt>>\n}\n\nexport interface CopyTextClient {\n copyText(input: CopyTextInput, options?: { readonly signal?: AbortSignal }): Promise<PresentationResult<CopyTextReceipt>>\n}\n\nexport interface NotificationClient {\n notify(input: NotificationInput, options?: { readonly signal?: AbortSignal }): Promise<PresentationResult<NotificationReceipt>>\n}\n\nexport interface UserInteractionClient {\n interact(input: QuestionInput, options?: { readonly signal?: AbortSignal }): Promise<PresentationResult<QuestionAnswers>>\n interact(input: ApprovalInput, options?: { readonly signal?: AbortSignal }): Promise<PresentationResult<ApprovalValue>>\n interact(input: SecretInput, options?: { readonly signal?: AbortSignal }): Promise<PresentationResult<SecretInputValue>>\n}\n\n/** Typed Presentation capabilities available to one domain invocation. */\nexport interface PresentationClients {\n readonly descriptor: PresentationDescriptor\n readonly openExternal?: OpenExternalClient\n readonly copyText?: CopyTextClient\n readonly notification?: NotificationClient\n readonly interaction?: UserInteractionClient\n readonly externalRedirect?: ExternalRedirectClient\n}\n\nexport interface OpenExternalHandler {\n openExternal(request: OpenExternalRequest, context: CapabilityHandlerContext): PresentationResult<OpenExternalReceipt> | Promise<PresentationResult<OpenExternalReceipt>>\n}\n\nexport interface CopyTextHandler {\n copyText(request: CopyTextRequest, context: CapabilityHandlerContext): PresentationResult<CopyTextReceipt> | Promise<PresentationResult<CopyTextReceipt>>\n}\n\nexport interface NotificationHandler {\n notify(request: NotificationRequest, context: CapabilityHandlerContext): PresentationResult<NotificationReceipt> | Promise<PresentationResult<NotificationReceipt>>\n}\n\nexport interface UserInteractionHandler {\n interact(request: QuestionRequest, context: CapabilityHandlerContext): PresentationResult<QuestionAnswers> | Promise<PresentationResult<QuestionAnswers>>\n interact(request: ApprovalRequest, context: CapabilityHandlerContext): PresentationResult<ApprovalValue> | Promise<PresentationResult<ApprovalValue>>\n interact(request: SecretInputRequest, context: CapabilityHandlerContext): PresentationResult<SecretInputValue> | Promise<PresentationResult<SecretInputValue>>\n}\n\nconst emptySpec = (value: unknown): undefined => {\n if (value !== undefined) throw new TypeError('Presentation operation does not accept spec in v1alpha1')\n return undefined\n}\n\nexport const openExternalProtocol = defineCapabilityProtocol({\n apiVersion: API_VERSION, kind: OPEN_EXTERNAL_KIND, validateRequirement: emptySpec, validateSupport: emptySpec,\n})\nexport const copyTextProtocol = defineCapabilityProtocol({\n apiVersion: API_VERSION, kind: COPY_TEXT_KIND, validateRequirement: emptySpec, validateSupport: emptySpec,\n})\nexport const notificationProtocol = defineCapabilityProtocol({\n apiVersion: API_VERSION, kind: NOTIFICATION_KIND, validateRequirement: emptySpec, validateSupport: emptySpec,\n})\n\nexport const openExternalSupport: ProtocolSupport = Object.freeze({ apiVersion: API_VERSION, kind: OPEN_EXTERNAL_KIND })\nexport const copyTextSupport: ProtocolSupport = Object.freeze({ apiVersion: API_VERSION, kind: COPY_TEXT_KIND })\nexport const notificationSupport: ProtocolSupport = Object.freeze({ apiVersion: API_VERSION, kind: NOTIFICATION_KIND })\nexport const userInteractionSupport = (spec: UserInteractionSupportSpec): ProtocolSupport<UserInteractionSupportSpec> =>\n Object.freeze({ apiVersion: API_VERSION, kind: USER_INTERACTION_KIND, spec: validateUserInteractionSupport(spec) })\n\nexport const userInteractionProtocol: ProtocolDefinition<\n UserInteractionRequirementSpec,\n UserInteractionSupportSpec\n> = Object.freeze({\n apiVersion: API_VERSION,\n kind: USER_INTERACTION_KIND,\n validateRequirement: validateUserInteractionRequirement,\n validateSupport: validateUserInteractionSupport,\n negotiate: negotiateUserInteraction,\n})\n\nexport const protocols: readonly ProtocolDefinition[] = Object.freeze([\n openExternalProtocol,\n copyTextProtocol,\n notificationProtocol,\n userInteractionProtocol,\n externalRedirectProtocol,\n])\n\nexport function register(catalog: ProtocolCatalog): () => void {\n const disposers = protocols.map(protocol => catalog.register(protocol))\n return () => { for (const dispose of disposers.reverse()) dispose() }\n}\n\nexport function openExternalClient(client: CapabilityClient, scope: PresentationInvocationScope): OpenExternalClient {\n const request = requestFactory(scope)\n return Object.freeze({\n async openExternal(input: OpenExternalInput, options?: { readonly signal?: AbortSignal }) {\n const value = request(input)\n validateOpenExternalRequest(value)\n const result = await client.invoke<OpenExternalRequest, PresentationResult<OpenExternalReceipt>>(\n openExternalSupport, 'openExternal', value, options,\n ).result\n return validatePresentationResult(result, validateAcceptedReceipt, 'OpenExternal result')\n },\n })\n}\n\nexport function copyTextClient(client: CapabilityClient, scope: PresentationInvocationScope): CopyTextClient {\n const request = requestFactory(scope)\n return Object.freeze({\n async copyText(input: CopyTextInput, options?: { readonly signal?: AbortSignal }) {\n const value = request(input)\n validateCopyTextRequest(value)\n const result = await client.invoke<CopyTextRequest, PresentationResult<CopyTextReceipt>>(\n copyTextSupport, 'copyText', value, options,\n ).result\n return validatePresentationResult(result, validateAcceptedReceipt, 'CopyText result')\n },\n })\n}\n\nexport function notificationClient(client: CapabilityClient, scope: PresentationInvocationScope): NotificationClient {\n const request = requestFactory(scope)\n return Object.freeze({\n async notify(input: NotificationInput, options?: { readonly signal?: AbortSignal }) {\n const value = request(input)\n validateNotificationRequest(value)\n const result = await client.invoke<NotificationRequest, PresentationResult<NotificationReceipt>>(\n notificationSupport, 'notify', value, options,\n ).result\n return validatePresentationResult(result, validateAcceptedReceipt, 'Notification result')\n },\n })\n}\n\nexport function userInteractionClient(client: CapabilityClient, scope: PresentationInvocationScope): UserInteractionClient {\n const request = requestFactory(scope)\n return Object.freeze({\n async interact(input: QuestionInput | ApprovalInput | SecretInput, options?: { readonly signal?: AbortSignal }): Promise<PresentationResult<UserInteractionValue>> {\n const value = request(input) as UserInteractionRequest\n validateUserInteractionRequest(value)\n const result = await client.invoke<UserInteractionRequest, PresentationResult<UserInteractionValue>>(\n { apiVersion: API_VERSION, kind: USER_INTERACTION_KIND }, 'interact', value, options,\n ).result\n return validateInteractionResult(value, result)\n },\n }) as UserInteractionClient\n}\n\nexport function presentationClients(\n descriptor: PresentationDescriptor,\n client: CapabilityClient,\n scope: PresentationInvocationScope,\n): PresentationClients {\n validatePresentationDescriptor(descriptor)\n validateInvocationScope(scope)\n const has = (kind: string) => descriptor.contracts.some(contract =>\n contract.apiVersion === API_VERSION && contract.kind === kind && client.binding(contract) !== undefined)\n return Object.freeze({\n descriptor: freezeClone(descriptor),\n ...(has(OPEN_EXTERNAL_KIND) ? { openExternal: openExternalClient(client, scope) } : {}),\n ...(has(COPY_TEXT_KIND) ? { copyText: copyTextClient(client, scope) } : {}),\n ...(has(NOTIFICATION_KIND) ? { notification: notificationClient(client, scope) } : {}),\n ...(has(USER_INTERACTION_KIND) ? { interaction: userInteractionClient(client, scope) } : {}),\n ...(has(EXTERNAL_REDIRECT_KIND) ? { externalRedirect: externalRedirectClient(client, scope) } : {}),\n })\n}\n\nexport function openExternalImplementation(participantId: string, handler: OpenExternalHandler): CapabilityImplementation {\n return implementation(participantId, openExternalSupport, 'openExternal', validateOpenExternalRequest, handler.openExternal.bind(handler),\n result => validatePresentationResult(result, validateAcceptedReceipt, 'OpenExternal result'))\n}\n\nexport function copyTextImplementation(participantId: string, handler: CopyTextHandler): CapabilityImplementation {\n return implementation(participantId, copyTextSupport, 'copyText', validateCopyTextRequest, handler.copyText.bind(handler),\n result => validatePresentationResult(result, validateAcceptedReceipt, 'CopyText result'))\n}\n\nexport function notificationImplementation(participantId: string, handler: NotificationHandler): CapabilityImplementation {\n return implementation(participantId, notificationSupport, 'notify', validateNotificationRequest, handler.notify.bind(handler),\n result => validatePresentationResult(result, validateAcceptedReceipt, 'Notification result'))\n}\n\nexport function userInteractionImplementation(\n participantId: string,\n spec: UserInteractionSupportSpec,\n handler: UserInteractionHandler,\n): CapabilityImplementation {\n const protocol = userInteractionSupport(spec)\n return Object.freeze({\n participantId,\n protocol,\n async handle(operationName: string, input: unknown, context: CapabilityHandlerContext) {\n if (operationName !== 'interact') throw new TypeError(`unsupported UserInteraction operation ${JSON.stringify(operationName)}`)\n validateUserInteractionRequest(input)\n if (!spec.operations.includes(input.kind)) throw new TypeError(`UserInteraction provider does not support ${JSON.stringify(input.kind)}`)\n const result = await handler.interact(input as never, context)\n return validateInteractionResult(input, result)\n },\n })\n}\n\nexport function validatePresentationDescriptor(value: unknown): asserts value is PresentationDescriptor {\n const descriptor = exactRecord(value, ['clientId', 'contracts'], ['clientId', 'contracts'], 'Presentation descriptor')\n nonEmpty(descriptor.clientId, 'Presentation descriptor.clientId')\n if (!Array.isArray(descriptor.contracts)) throw new TypeError('Presentation descriptor.contracts must be an array')\n const seen = new Set<string>()\n for (const [index, contractValue] of descriptor.contracts.entries()) {\n const contract = exactRecord(contractValue, ['apiVersion', 'kind', 'spec'], ['apiVersion', 'kind'], `Presentation descriptor.contracts[${index}]`)\n nonEmpty(contract.apiVersion, `Presentation descriptor.contracts[${index}].apiVersion`)\n nonEmpty(contract.kind, `Presentation descriptor.contracts[${index}].kind`)\n const key = `${String(contract.apiVersion)}\\0${String(contract.kind)}`\n if (seen.has(key)) throw new TypeError(`Presentation descriptor contains duplicate contract ${JSON.stringify(key)}`)\n seen.add(key)\n }\n}\n\nexport function validateOpenExternalRequest(value: unknown): asserts value is OpenExternalRequest {\n const request = requestRecord(value, ['uri'], 'OpenExternal request')\n nonEmpty(request.uri, 'OpenExternal request.uri')\n const uri = new URL(request.uri as string)\n if (uri.protocol !== 'https:' && uri.protocol !== 'http:') throw new TypeError('OpenExternal only accepts HTTP(S) URIs')\n}\n\nexport function validateCopyTextRequest(value: unknown): asserts value is CopyTextRequest {\n const request = requestRecord(value, ['text', 'sensitivity'], 'CopyText request')\n nonEmpty(request.text, 'CopyText request.text')\n if (request.sensitivity !== undefined && request.sensitivity !== 'public' && request.sensitivity !== 'private') {\n throw new TypeError('CopyText request.sensitivity is invalid')\n }\n}\n\nexport function validateNotificationRequest(value: unknown): asserts value is NotificationRequest {\n const request = requestRecord(value, ['text', 'level', 'deduplicationKey'], 'Notification request')\n nonEmpty(request.text, 'Notification request.text')\n if (request.level !== undefined && request.level !== 'info' && request.level !== 'warning' && request.level !== 'error') {\n throw new TypeError('Notification request.level is invalid')\n }\n if (request.deduplicationKey !== undefined) nonEmpty(request.deduplicationKey, 'Notification request.deduplicationKey')\n}\n\nexport function validateUserInteractionRequest(value: unknown): asserts value is UserInteractionRequest {\n if (!record(value)) throw new TypeError('UserInteraction request must be an object')\n if (value.kind === 'question') return validateQuestionRequest(value)\n if (value.kind === 'approval') return validateApprovalRequest(value)\n if (value.kind === 'secret-input') return validateSecretInputRequest(value)\n throw new TypeError('UserInteraction request.kind is invalid')\n}\n\nexport function validateUserInteractionRequirement(value: unknown): UserInteractionRequirementSpec {\n const spec = exactRecord(value, ['operations', 'optionalOperations'], ['operations'], 'UserInteraction requirement spec')\n const operations = operationList(spec.operations, 'UserInteraction requirement spec.operations')\n const optionalOperations = spec.optionalOperations === undefined\n ? undefined\n : operationList(spec.optionalOperations, 'UserInteraction requirement spec.optionalOperations')\n if (optionalOperations?.some(operation => operations.includes(operation)) === true) {\n throw new TypeError('UserInteraction optionalOperations must not duplicate required operations')\n }\n return deepFreeze({ operations, ...(optionalOperations === undefined ? {} : { optionalOperations }) })\n}\n\nexport function validateUserInteractionSupport(value: unknown): UserInteractionSupportSpec {\n const spec = exactRecord(value, ['operations', 'limits'], ['operations'], 'UserInteraction support spec')\n const operations = operationList(spec.operations, 'UserInteraction support spec.operations')\n const limits = spec.limits === undefined ? undefined : validateLimits(spec.limits)\n return deepFreeze({ operations, ...(limits === undefined ? {} : { limits }) })\n}\n\nfunction negotiateUserInteraction(\n input: ProtocolNegotiationInput<UserInteractionRequirementSpec, UserInteractionSupportSpec>,\n) {\n const issues: ProtocolIssue[] = []\n const bindings: Array<{\n readonly consumer: string\n readonly provider: string\n readonly requirement: ProtocolRequirement<UserInteractionRequirementSpec>\n readonly support: ProtocolSupport<UserInteractionSupportSpec>\n }> = []\n const connectionPolicy = connectionNegotiationPolicy(input.policy)\n for (const row of input.requirements) {\n const consumerEndpoint = connectionPolicy?.endpointByParticipant[row.participant]\n const candidates = input.supports.filter(candidate => {\n if (candidate.participant === row.participant) return false\n if (consumerEndpoint !== undefined && connectionPolicy?.endpointByParticipant[candidate.participant] === consumerEndpoint) return false\n return row.requirement.spec!.operations.every(operation => candidate.support.spec!.operations.includes(operation))\n })\n if (candidates.length === 0) {\n issues.push(Object.freeze({\n code: row.requirement.optional === true ? 'optional-support-missing' : 'required-support-missing',\n severity: row.requirement.optional === true ? 'warning' : 'error',\n participant: row.participant,\n message: `no participant supports the required ${USER_INTERACTION_KIND} operations`,\n }))\n continue\n }\n if (candidates.length > 1) {\n issues.push(Object.freeze({\n code: 'support-ambiguous', severity: 'error', participant: row.participant,\n message: `multiple participants support ${API_VERSION} ${USER_INTERACTION_KIND}`,\n }))\n continue\n }\n const provider = candidates[0]!\n bindings.push(Object.freeze({\n consumer: row.participant,\n provider: provider.participant,\n requirement: row.requirement,\n support: provider.support,\n }))\n for (const operation of row.requirement.spec!.optionalOperations ?? []) {\n if (provider.support.spec!.operations.includes(operation)) continue\n issues.push(Object.freeze({\n code: 'optional-operation-missing', severity: 'warning', participant: row.participant,\n message: `${USER_INTERACTION_KIND} provider does not support optional operation ${JSON.stringify(operation)}`,\n }))\n }\n }\n return {\n agreement: Object.freeze({ kind: 'CapabilityBindings' as const, bindings: Object.freeze(bindings) }),\n issues: Object.freeze(issues),\n }\n}\n\nfunction connectionNegotiationPolicy(value: unknown): ConnectionNegotiationPolicy | undefined {\n return record(value) && record(value.endpointByParticipant)\n ? value as unknown as ConnectionNegotiationPolicy\n : undefined\n}\n\nfunction implementation<TInput, TOutput>(\n participantId: string,\n protocol: ProtocolSupport,\n operationName: string,\n validateInput: (value: unknown) => asserts value is TInput,\n handler: (input: TInput, context: CapabilityHandlerContext) => TOutput | Promise<TOutput>,\n validateOutput: (value: unknown) => TOutput,\n): CapabilityImplementation {\n return Object.freeze({\n participantId,\n protocol,\n async handle(operation: string, input: unknown, context: CapabilityHandlerContext) {\n if (operation !== operationName) throw new TypeError(`unsupported ${protocol.kind} operation ${JSON.stringify(operation)}`)\n validateInput(input)\n return validateOutput(await handler(input, context))\n },\n })\n}\n\nfunction validateQuestionRequest(value: unknown): asserts value is QuestionRequest {\n const request = requestRecord(value, ['kind', 'title', 'description', 'fields'], 'Question request')\n if (request.kind !== 'question') throw new TypeError('Question request.kind must be \"question\"')\n optionalText(request.title, 'Question request.title')\n optionalText(request.description, 'Question request.description')\n if (!Array.isArray(request.fields) || request.fields.length === 0) throw new TypeError('Question request.fields must be a non-empty array')\n const ids = new Set<string>()\n for (const [index, fieldValue] of request.fields.entries()) {\n const label = `Question request.fields[${index}]`\n if (!record(fieldValue)) throw new TypeError(`${label} must be an object`)\n const common = ['id', 'kind', 'label', 'description', 'required']\n const allowed = fieldValue.kind === 'text' ? [...common, 'multiline', 'minLength', 'maxLength']\n : fieldValue.kind === 'select' ? [...common, 'multiple', 'options'] : common\n const field = exactRecord(fieldValue, allowed, ['id', 'kind', 'label'], label)\n localId(field.id, `${label}.id`)\n if (ids.has(field.id as string)) throw new TypeError('Question request contains duplicate field id')\n ids.add(field.id as string)\n nonEmpty(field.label, `${label}.label`)\n optionalText(field.description, `${label}.description`)\n optionalBoolean(field.required, `${label}.required`)\n if (field.kind === 'text') {\n optionalBoolean(field.multiline, `${label}.multiline`)\n lengthBounds(field.minLength, field.maxLength, label)\n } else if (field.kind === 'select') {\n optionalBoolean(field.multiple, `${label}.multiple`)\n if (!Array.isArray(field.options) || field.options.length === 0) throw new TypeError(`${label}.options must be a non-empty array`)\n const options = new Set<string>()\n for (const [optionIndex, optionValue] of field.options.entries()) {\n const optionLabel = `${label}.options[${optionIndex}]`\n const option = exactRecord(optionValue, ['id', 'label', 'description'], ['id', 'label'], optionLabel)\n localId(option.id, `${optionLabel}.id`)\n if (options.has(option.id as string)) throw new TypeError(`${label} contains duplicate option id`)\n options.add(option.id as string)\n nonEmpty(option.label, `${optionLabel}.label`)\n optionalText(option.description, `${optionLabel}.description`)\n }\n } else if (field.kind !== 'confirm') {\n throw new TypeError(`${label}.kind is invalid`)\n }\n }\n}\n\nfunction validateApprovalRequest(value: unknown): asserts value is ApprovalRequest {\n const request = requestRecord(value, ['kind', 'action', 'summary', 'details', 'risk'], 'Approval request')\n if (request.kind !== 'approval') throw new TypeError('Approval request.kind must be \"approval\"')\n nonEmpty(request.action, 'Approval request.action')\n nonEmpty(request.summary, 'Approval request.summary')\n if (request.risk !== undefined && request.risk !== 'low' && request.risk !== 'medium' && request.risk !== 'high') {\n throw new TypeError('Approval request.risk is invalid')\n }\n if (request.details !== undefined) {\n if (!Array.isArray(request.details)) throw new TypeError('Approval request.details must be an array')\n for (const [index, detailValue] of request.details.entries()) {\n const label = `Approval request.details[${index}]`\n const detail = exactRecord(detailValue, ['label', 'value', 'sensitivity'], ['label', 'value'], label)\n nonEmpty(detail.label, `${label}.label`)\n nonEmpty(detail.value, `${label}.value`)\n if (detail.sensitivity !== undefined && detail.sensitivity !== 'public' && detail.sensitivity !== 'private') {\n throw new TypeError(`${label}.sensitivity is invalid`)\n }\n }\n }\n}\n\nfunction validateSecretInputRequest(value: unknown): asserts value is SecretInputRequest {\n const request = requestRecord(value, ['kind', 'label', 'description', 'minLength', 'maxLength'], 'SecretInput request')\n if (request.kind !== 'secret-input') throw new TypeError('SecretInput request.kind must be \"secret-input\"')\n nonEmpty(request.label, 'SecretInput request.label')\n optionalText(request.description, 'SecretInput request.description')\n lengthBounds(request.minLength, request.maxLength, 'SecretInput request')\n}\n\nfunction validateInteractionResult(\n request: UserInteractionRequest,\n value: unknown,\n): PresentationResult<UserInteractionValue> {\n if (request.kind === 'question') return validatePresentationResult(value, result => validateQuestionAnswers(request, result), 'Question result')\n if (request.kind === 'approval') return validatePresentationResult(value, validateApprovalValue, 'Approval result')\n return validatePresentationResult(value, result => validateSecretInputValue(request, result), 'SecretInput result')\n}\n\nfunction validateQuestionAnswers(request: QuestionRequest, value: unknown): QuestionAnswers {\n const result = exactRecord(value, ['answers'], ['answers'], 'Question answers')\n if (!record(result.answers)) throw new TypeError('Question answers.answers must be an object')\n const fields = new Map(request.fields.map(field => [field.id, field]))\n for (const field of request.fields) {\n if (field.required === true && !Object.hasOwn(result.answers, field.id)) throw new TypeError(`Question answers is missing required field ${JSON.stringify(field.id)}`)\n }\n for (const [id, answer] of Object.entries(result.answers)) {\n const field = fields.get(id)\n if (field === undefined) throw new TypeError(`Question answers contains unknown field ${JSON.stringify(id)}`)\n if (field.kind === 'text') {\n if (typeof answer !== 'string') throw new TypeError(`Question answer ${JSON.stringify(id)} must be a string`)\n if (field.minLength !== undefined && answer.length < field.minLength) throw new TypeError(`Question answer ${JSON.stringify(id)} is too short`)\n if (field.maxLength !== undefined && answer.length > field.maxLength) throw new TypeError(`Question answer ${JSON.stringify(id)} is too long`)\n } else if (field.kind === 'confirm') {\n if (typeof answer !== 'boolean') throw new TypeError(`Question answer ${JSON.stringify(id)} must be boolean`)\n } else {\n const allowed = new Set(field.options.map(option => option.id))\n const selected = field.multiple === true ? answer : [answer]\n if (!Array.isArray(selected) || selected.some(option => typeof option !== 'string' || !allowed.has(option))) {\n throw new TypeError(`Question answer ${JSON.stringify(id)} contains an invalid option`)\n }\n }\n }\n return freezeClone(value as QuestionAnswers)\n}\n\nfunction validateApprovalValue(value: unknown): ApprovalValue {\n const result = exactRecord(value, ['decision'], ['decision'], 'Approval value')\n if (result.decision !== 'approved' && result.decision !== 'denied') throw new TypeError('Approval value.decision is invalid')\n return freezeClone(value as ApprovalValue)\n}\n\nfunction validateSecretInputValue(request: SecretInputRequest, value: unknown): SecretInputValue {\n const result = exactRecord(value, ['secret'], ['secret'], 'SecretInput value')\n if (typeof result.secret !== 'string') throw new TypeError('SecretInput value.secret must be a string')\n if (request.minLength !== undefined && result.secret.length < request.minLength) throw new TypeError('SecretInput value.secret is too short')\n if (request.maxLength !== undefined && result.secret.length > request.maxLength) throw new TypeError('SecretInput value.secret is too long')\n return freezeClone(value as SecretInputValue)\n}\n\nfunction validatePresentationResult<T>(\n value: unknown,\n validateSubmitted: (submitted: unknown) => T,\n label: string,\n): PresentationResult<T> {\n if (!record(value)) throw new TypeError(`${label} must be an object`)\n if (value.status === 'submitted') {\n const result = exactRecord(value, ['status', 'value'], ['status', 'value'], label)\n return deepFreeze({ status: 'submitted' as const, value: validateSubmitted(result.value) })\n }\n if (value.status === 'unavailable') {\n const result = exactRecord(value, ['status', 'reason'], ['status'], label)\n optionalText(result.reason, `${label}.reason`)\n return freezeClone(value as PresentationResult<T>)\n }\n if (value.status === 'cancelled' || value.status === 'expired') {\n exactRecord(value, ['status'], ['status'], label)\n return freezeClone(value as PresentationResult<T>)\n }\n throw new TypeError(`${label}.status is invalid`)\n}\n\nfunction validateAcceptedReceipt(value: unknown): { readonly accepted: true } {\n const receipt = exactRecord(value, ['accepted'], ['accepted'], 'Presentation receipt')\n if (receipt.accepted !== true) throw new TypeError('Presentation receipt.accepted must be true')\n return Object.freeze({ accepted: true })\n}\n\nfunction requestRecord(value: unknown, fields: readonly string[], label: string): Record<string, unknown> {\n const required = ['requestId', 'invocationId', 'origin', ...fields.filter(field => !['title', 'description', 'details', 'risk', 'level', 'deduplicationKey', 'sensitivity', 'minLength', 'maxLength'].includes(field))]\n const request = exactRecord(value, ['requestId', 'invocationId', 'origin', 'deadline', ...fields], required, label)\n nonEmpty(request.requestId, `${label}.requestId`)\n nonEmpty(request.invocationId, `${label}.invocationId`)\n nonEmpty(request.origin, `${label}.origin`)\n if (request.deadline !== undefined && (typeof request.deadline !== 'string' || Number.isNaN(Date.parse(request.deadline)))) {\n throw new TypeError(`${label}.deadline must be an RFC 3339 date-time`)\n }\n return request\n}\n\nfunction validateLimits(value: unknown): UserInteractionLimits {\n const limits = exactRecord(\n value,\n ['maxConcurrentRequests', 'maxFields', 'maxOptionsPerField', 'maxTextLength'],\n [],\n 'UserInteraction limits',\n )\n for (const [name, limit] of Object.entries(limits)) positiveInteger(limit, `UserInteraction limits.${name}`)\n return freezeClone(value as UserInteractionLimits)\n}\n\nfunction operationList(value: unknown, label: string): readonly UserInteractionOperation[] {\n if (!Array.isArray(value) || value.length === 0) throw new TypeError(`${label} must be a non-empty array`)\n const operations = value.map(operation => {\n if (operation !== 'question' && operation !== 'approval' && operation !== 'secret-input') throw new TypeError(`${label} contains an invalid operation`)\n return operation\n })\n if (new Set(operations).size !== operations.length) throw new TypeError(`${label} contains a duplicate operation`)\n return Object.freeze(operations)\n}\n\nfunction lengthBounds(minimum: unknown, maximum: unknown, label: string): void {\n if (minimum !== undefined) nonNegativeInteger(minimum, `${label}.minLength`)\n if (maximum !== undefined) nonNegativeInteger(maximum, `${label}.maxLength`)\n if (typeof minimum === 'number' && typeof maximum === 'number' && minimum > maximum) {\n throw new TypeError(`${label}.minLength must not exceed maxLength`)\n }\n}\n\nfunction exactRecord(value: unknown, allowed: readonly string[], required: readonly string[], label: string): Record<string, unknown> {\n if (!record(value)) throw new TypeError(`${label} must be an object`)\n const unknown = Object.keys(value).filter(key => !allowed.includes(key))\n if (unknown.length > 0) throw new TypeError(`${label} contains unknown field ${JSON.stringify(unknown[0])}`)\n for (const key of required) if (!Object.hasOwn(value, key)) throw new TypeError(`${label}.${key} is required`)\n return value\n}\n\nfunction record(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value)\n}\n\nfunction nonEmpty(value: unknown, label: string): asserts value is string {\n if (typeof value !== 'string' || value.trim() === '') throw new TypeError(`${label} must be a non-empty string`)\n}\n\nfunction validateInvocationScope(scope: PresentationInvocationScope): void {\n if (!record(scope)) throw new TypeError('Presentation invocation scope must be an object')\n nonEmpty(scope.invocationId, 'Presentation invocation scope.invocationId')\n nonEmpty(scope.origin, 'Presentation invocation scope.origin')\n if (scope.deadline !== undefined && (typeof scope.deadline !== 'string' || Number.isNaN(Date.parse(scope.deadline)))) {\n throw new TypeError('Presentation invocation scope.deadline must be an RFC 3339 date-time')\n }\n if (typeof scope.nextRequestId !== 'function') throw new TypeError('Presentation invocation scope.nextRequestId must be a function')\n}\n\nfunction requestFactory(scope: PresentationInvocationScope) {\n validateInvocationScope(scope)\n return <T extends object>(input: T): Readonly<T & PresentationRequestContext> => {\n if (!record(input)) throw new TypeError('Presentation input must be an object')\n const requestId = scope.nextRequestId()\n nonEmpty(requestId, 'Presentation requestId')\n return freezeClone({\n ...input,\n requestId,\n invocationId: scope.invocationId,\n origin: scope.origin,\n ...(scope.deadline === undefined ? {} : { deadline: scope.deadline }),\n })\n }\n}\n\nfunction optionalText(value: unknown, label: string): void {\n if (value !== undefined) nonEmpty(value, label)\n}\n\nfunction optionalBoolean(value: unknown, label: string): void {\n if (value !== undefined && typeof value !== 'boolean') throw new TypeError(`${label} must be boolean`)\n}\n\nfunction localId(value: unknown, label: string): asserts value is string {\n if (typeof value !== 'string' || !/^[A-Za-z][A-Za-z0-9._-]*$/u.test(value)) throw new TypeError(`${label} is invalid`)\n}\n\nfunction positiveInteger(value: unknown, label: string): void {\n if (!Number.isSafeInteger(value) || (value as number) < 1) throw new TypeError(`${label} must be a positive safe integer`)\n}\n\nfunction nonNegativeInteger(value: unknown, label: string): void {\n if (!Number.isSafeInteger(value) || (value as number) < 0) throw new TypeError(`${label} must be a non-negative safe integer`)\n}\n\nfunction freezeClone<T>(value: T): T { return deepFreeze(structuredClone(value)) }\n\nfunction deepFreeze<T>(value: T): T {\n if (typeof value !== 'object' || value === null || Object.isFrozen(value)) return value\n Object.freeze(value)\n for (const child of Object.values(value)) deepFreeze(child)\n return value\n}\n"],"mappings":"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"}
@@ -8,14 +8,18 @@
8
8
  "exports": {
9
9
  ".": { "types": "./lib/index.d.ts", "default": "./lib/index.js" },
10
10
  "./operations": { "types": "./lib/operations.d.ts", "default": "./lib/operations.js" },
11
- "./interaction": { "types": "./lib/interaction.d.ts", "default": "./lib/interaction.js" }
11
+ "./interaction": { "types": "./lib/interaction.d.ts", "default": "./lib/interaction.js" },
12
+ "./callback": { "types": "./lib/callback.d.ts", "default": "./lib/callback.js" }
12
13
  },
13
- "files": ["lib"],
14
+ "files": ["lib", "CHANGELOG.md"],
14
15
  "scripts": {
15
16
  "build": "pnpm run typecheck && tsdown",
16
17
  "typecheck": "tsc -p tsconfig.json --noEmit",
17
18
  "test": "vitest run --passWithNoTests"
18
19
  },
19
- "dependencies": { "@dsh-std/core": "workspace:*", "@dsh-std/connection": "workspace:*" },
20
+ "dependencies": {
21
+ "@dsh-std/core": "workspace:*",
22
+ "@dsh-std/connection": "workspace:*"
23
+ },
20
24
  "engines": { "node": "^22.19 || >=24" }
21
25
  }
@@ -0,0 +1,8 @@
1
+ # Changelog
2
+
3
+ Changes to `@dsh-std/storage` are recorded here.
4
+
5
+ ## 0.1.0 (draft)
6
+
7
+ - Defined scoped local JSON storage get, set, and delete operations.
8
+ - Added permission names, schemas, validators, and deterministic provider negotiation.
@@ -9,7 +9,7 @@
9
9
  ".": { "types": "./lib/index.d.ts", "default": "./lib/index.js" },
10
10
  "./schema/local-storage-0.15.json": "./schema/local-storage-0.15.schema.json"
11
11
  },
12
- "files": ["lib", "schema"],
12
+ "files": ["lib", "schema", "CHANGELOG.md"],
13
13
  "scripts": {
14
14
  "build": "pnpm run typecheck && tsdown",
15
15
  "typecheck": "tsc -p tsconfig.json --noEmit",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@deepseek-harness-tui/dsh-tui",
3
- "version": "0.8.1",
3
+ "version": "0.8.2",
4
4
  "description": "Claude Code style interactive TUI front door for DeepSeek Harness agents, built on the ported Ink core.",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -15,6 +15,9 @@
15
15
  "access": "public"
16
16
  },
17
17
  "type": "module",
18
+ "imports": {
19
+ "#dsh-ecosystem-spec/tui-channel": "./dsh-ecosystem-spec/protocols/tui-channel.js"
20
+ },
18
21
  "bin": {
19
22
  "dsh-tui": "./bin/dsh-tui.js"
20
23
  },
@@ -69,8 +72,9 @@
69
72
  "lib",
70
73
  "cordis.patch.yml",
71
74
  "cordis.yml",
72
- "ecosystem-spec/registry",
73
- "ecosystem-spec/schemas",
75
+ "dsh-ecosystem-spec/registry",
76
+ "dsh-ecosystem-spec/protocols",
77
+ "dsh-ecosystem-spec/schemas",
74
78
  "presets",
75
79
  "skills"
76
80
  ],
@@ -89,7 +93,7 @@
89
93
  "prompt:debug": "node scripts/read-prompt-debug.mjs",
90
94
  "tui": "node --import tsx/esm scripts/run.ts",
91
95
  "smoke": "node --import tsx/esm scripts/smoke.tsx",
92
- "verify:build": "npm run verify:boundary && npm run verify:contract && npm run verify:manifest-deps && npm run verify:patch-surface && npm run verify:plugin-spec && npm run verify:plugin-grants && npm run verify:plugin-storage && npm run verify:plugin-messages && npm run verify:plugin-ledger && npm run verify:plugin-commands && npm run verify:plugin-negotiation && npm run verify:packaged-presets && npm run verify:minimal-preset-tools && npm run verify:liangshen-bootstrap",
96
+ "verify:build": "npm run verify:boundary && npm run verify:contract && npm run verify:manifest-deps && npm run verify:patch-surface && npm run verify:plugin-spec && npm run verify:plugin-grants && npm run verify:plugin-storage && npm run verify:plugin-messages && npm run verify:plugin-ledger && npm run verify:plugin-commands && npm run verify:plugin-negotiation && npm run verify:plugin-lifecycle && npm run verify:packaged-presets && npm run verify:minimal-preset-tools && npm run verify:liangshen-bootstrap",
93
97
  "verify:boundary": "node --import tsx/esm scripts/verify-adapter-boundary.ts",
94
98
  "verify:contract": "node --import tsx/esm scripts/verify-upstream-contract.ts",
95
99
  "verify:manifest-deps": "node --import tsx/esm scripts/verify-manifest-deps.ts",
@@ -106,7 +110,8 @@
106
110
  "verify:clipboard-image": "node --import tsx/esm scripts/verify-clipboard-image.ts",
107
111
  "verify:plugin-ledger": "node --import tsx/esm scripts/verify-plugin-ledger.ts",
108
112
  "verify:plugin-commands": "node --import tsx/esm scripts/verify-plugin-commands.ts",
109
- "verify:plugin-negotiation": "node --import tsx/esm scripts/verify-plugin-negotiation.ts"
113
+ "verify:plugin-negotiation": "node --import tsx/esm scripts/verify-plugin-negotiation.ts",
114
+ "verify:plugin-lifecycle": "node --import tsx/esm scripts/verify-plugin-lifecycle.ts"
110
115
  },
111
116
  "peerDependencies": {
112
117
  "@deepseek-ai/cordis": "^4.0.1",
@@ -0,0 +1,8 @@
1
+ # Changelog
2
+
3
+ Changes to `@dsh-std/connection` are recorded here.
4
+
5
+ ## 0.1.0 (draft)
6
+
7
+ - Defined connection services, endpoint views, participant publication, capability bindings, and attachments.
8
+ - Added an in-memory transport for protocol conformance and host integration tests.
@@ -18,7 +18,7 @@ interface MemoryConnectionPair {
18
18
  renegotiate(options: ResolveConnectionOptions): ConnectionPlan;
19
19
  close(reason?: string): void;
20
20
  }
21
- declare function createMemoryConnectionPair(left: MemoryConnectionEndpoint, right: MemoryConnectionEndpoint, options: ResolveConnectionOptions): MemoryConnectionPair;
21
+ declare function createMemoryConnectionPair(left: ConnectionEndpoint, right: ConnectionEndpoint, options: ResolveConnectionOptions): MemoryConnectionPair;
22
22
  //#endregion
23
23
  export { MemoryConnectionEndpoint, MemoryConnectionPair, createMemoryConnectionPair };
24
24
  //# sourceMappingURL=memory.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"memory.d.ts","names":[],"sources":["../src/memory.ts"],"mappings":";;cAmBa,oCAAoC;UACvC;mBACS;mBACA;EAEL,YAAA,OAAO;MAKf,SAAS;EAEb,aAAa,OAAO;EAQpB,SAAS,gBAAgB;EAgBnB,SAAS,kBAAkB,mBAAmB,qBAAqB,YAAY,mBAAmB,QAAQ,aAAa,QAAQ;EAerI,cAAc,WAAW,OAAO;;UAMjB;WACN,MAAM;WACN,OAAO;WACP,MAAM;EACf,YAAY,SAAS,2BAA2B;EAChD,MAAM;;iBAGQ,2BACd,MAAM,0BAA0B,OAAO,0BAA0B,SAAS,2BACzE"}
1
+ {"version":3,"file":"memory.d.ts","names":[],"sources":["../src/memory.ts"],"mappings":";;cAmBa,oCAAoC;UACvC;mBACS;mBACA;EAEL,YAAA,OAAO;MAKf,SAAS;EAEb,aAAa,OAAO;EAQpB,SAAS,gBAAgB;EAgBnB,SAAS,kBAAkB,mBAAmB,qBAAqB,YAAY,mBAAmB,QAAQ,aAAa,QAAQ;EAerI,cAAc,WAAW,OAAO;;UAMjB;WACN,MAAM;WACN,OAAO;WACP,MAAM;EACf,YAAY,SAAS,2BAA2B;EAChD,MAAM;;iBAGQ,2BACd,MAAM,oBAAoB,OAAO,oBAAoB,SAAS,2BAC7D"}
@@ -89,6 +89,7 @@ var MemoryPair = class {
89
89
  };
90
90
  }
91
91
  binding(local, participantId, reference) {
92
+ if (this.closed) return void 0;
92
93
  return this.currentPlan.bindings.find((binding) => binding.consumer.endpoint.instanceId === local.offer.endpoint.instanceId && binding.consumer.participantId === participantId && sameProtocol(binding.requirement, reference));
93
94
  }
94
95
  invoke(local, participantId, reference, operation, input, signal) {
@@ -1 +1 @@
1
- {"version":3,"file":"memory.js","names":[],"sources":["../src/memory.ts"],"sourcesContent":["import { sameProtocol, type ApiReference } from '@dsh-std/core'\nimport {\n ConnectionInvocationError,\n type CapabilityCall,\n type CapabilityClient,\n type CapabilityDispatch,\n type CapabilityImplementation,\n type ConnectionEndpoint,\n type StandardConnection,\n} from './connection.js'\nimport {\n validateEndpointOffer,\n type CapabilityBinding,\n type ConnectionPlan,\n type EndpointOffer,\n type ResolveConnectionOptions,\n} from './model.js'\nimport { resolveConnection } from './resolve.js'\n\nexport class MemoryConnectionEndpoint implements ConnectionEndpoint {\n private currentOffer: EndpointOffer\n private readonly implementations: CapabilityImplementation[] = []\n private readonly offerListeners = new Set<(offer: EndpointOffer) => void>()\n\n constructor(offer: EndpointOffer) {\n validateEndpointOffer(offer)\n this.currentOffer = offer\n }\n\n get offer(): EndpointOffer { return this.currentOffer }\n\n replaceOffer(offer: EndpointOffer): void {\n validateEndpointOffer(offer)\n if (offer.endpoint.instanceId !== this.currentOffer.endpoint.instanceId) throw new TypeError('replacement offer belongs to another endpoint')\n if (offer.revision <= this.currentOffer.revision) throw new TypeError('replacement offer must increase revision')\n this.currentOffer = offer\n for (const listener of this.offerListeners) listener(offer)\n }\n\n register(implementation: CapabilityImplementation): () => void {\n const declaration = this.currentOffer.declarations.find(row => row.participant.id === implementation.participantId)\n if (declaration === undefined || !(declaration.supports ?? []).some(row => sameProtocol(row, implementation.protocol))) {\n throw new TypeError('implementation is not backed by a live endpoint declaration')\n }\n if (this.implementations.some(row => row.participantId === implementation.participantId && sameProtocol(row.protocol, implementation.protocol))) {\n throw new TypeError('capability implementation is already registered')\n }\n const stored = Object.freeze({ ...implementation, protocol: Object.freeze({ ...implementation.protocol }) })\n this.implementations.push(stored)\n return () => {\n const index = this.implementations.indexOf(stored)\n if (index >= 0) this.implementations.splice(index, 1)\n }\n }\n\n async dispatch<TInput = unknown, TOutput = unknown, TProgress = unknown>(invocation: CapabilityDispatch<TInput, TProgress>): Promise<TOutput> {\n const implementation = this.implementations.find(row =>\n row.participantId === invocation.binding.provider.participantId\n && sameProtocol(row.protocol, invocation.binding.support))\n if (implementation === undefined) throw new ConnectionInvocationError('handler-missing', 'binding has no live implementation')\n return await implementation.handle(invocation.operation, invocation.input, Object.freeze({\n connectionId: invocation.connectionId,\n planRevision: invocation.planRevision,\n invocationId: invocation.invocationId,\n binding: invocation.binding,\n signal: invocation.signal,\n progress: invocation.progress,\n })) as TOutput\n }\n\n onOfferChange(listener: (offer: EndpointOffer) => void): () => void {\n this.offerListeners.add(listener)\n return () => { this.offerListeners.delete(listener) }\n }\n}\n\nexport interface MemoryConnectionPair {\n readonly left: StandardConnection\n readonly right: StandardConnection\n readonly plan: ConnectionPlan\n renegotiate(options: ResolveConnectionOptions): ConnectionPlan\n close(reason?: string): void\n}\n\nexport function createMemoryConnectionPair(\n left: MemoryConnectionEndpoint, right: MemoryConnectionEndpoint, options: ResolveConnectionOptions,\n): MemoryConnectionPair {\n return new MemoryPair(left, right, options)\n}\n\nclass MemoryPair implements MemoryConnectionPair {\n private currentPlan: ConnectionPlan\n private closed = false\n private invocationSequence = 0\n private readonly listeners = new Set<(plan: ConnectionPlan) => void>()\n private readonly active = new Map<string, (reason?: string, code?: 'cancelled' | 'connection-closed') => void>()\n readonly left: StandardConnection\n readonly right: StandardConnection\n\n constructor(\n private readonly leftEndpoint: MemoryConnectionEndpoint,\n private readonly rightEndpoint: MemoryConnectionEndpoint,\n options: ResolveConnectionOptions,\n ) {\n this.currentPlan = resolveConnection(leftEndpoint.offer, rightEndpoint.offer, options)\n this.left = new MemoryConnectionView(this, leftEndpoint, rightEndpoint)\n this.right = new MemoryConnectionView(this, rightEndpoint, leftEndpoint)\n }\n\n get plan(): ConnectionPlan { return this.currentPlan }\n\n renegotiate(options: ResolveConnectionOptions): ConnectionPlan {\n this.assertOpen()\n if (options.connectionId !== this.currentPlan.connectionId || options.revision <= this.currentPlan.revision) {\n throw new TypeError('renegotiation must retain connectionId and increase revision')\n }\n this.currentPlan = resolveConnection(this.leftEndpoint.offer, this.rightEndpoint.offer, options)\n for (const listener of this.listeners) listener(this.currentPlan)\n return this.currentPlan\n }\n\n subscribe(listener: (plan: ConnectionPlan) => void): () => void {\n this.listeners.add(listener)\n return () => { this.listeners.delete(listener) }\n }\n\n binding(local: MemoryConnectionEndpoint, participantId: string, reference: ApiReference): CapabilityBinding | undefined {\n return this.currentPlan.bindings.find(binding =>\n binding.consumer.endpoint.instanceId === local.offer.endpoint.instanceId\n && binding.consumer.participantId === participantId\n && sameProtocol(binding.requirement, reference))\n }\n\n invoke<TInput, TOutput, TProgress>(\n local: MemoryConnectionEndpoint,\n participantId: string,\n reference: ApiReference,\n operation: string,\n input: TInput,\n signal?: AbortSignal,\n ): CapabilityCall<TOutput, TProgress> {\n this.assertOpen()\n signal?.throwIfAborted()\n const binding = this.binding(local, participantId, reference)\n if (binding === undefined) throw new ConnectionInvocationError('capability-unbound', `participant ${JSON.stringify(participantId)} has no binding`)\n const target = binding.provider.endpoint.instanceId === this.leftEndpoint.offer.endpoint.instanceId\n ? this.leftEndpoint\n : binding.provider.endpoint.instanceId === this.rightEndpoint.offer.endpoint.instanceId ? this.rightEndpoint : undefined\n if (target === undefined) throw new ConnectionInvocationError('handler-missing', 'binding provider endpoint is unavailable')\n const invocationId = `${local.offer.endpoint.instanceId}:${String(++this.invocationSequence)}`\n const controller = new AbortController()\n const progress = new AsyncProgress<TProgress>()\n let settled = false\n let resolveResult!: (value: TOutput | PromiseLike<TOutput>) => void\n let rejectResult!: (reason?: unknown) => void\n const result = new Promise<TOutput>((resolve, reject) => { resolveResult = resolve; rejectResult = reject })\n const finish = () => { settled = true; this.active.delete(invocationId); progress.close() }\n const cancel = (reason = 'capability invocation cancelled', code: 'cancelled' | 'connection-closed' = 'cancelled') => {\n if (settled) return\n controller.abort(reason)\n finish()\n rejectResult(new ConnectionInvocationError(code, reason))\n }\n this.active.set(invocationId, cancel)\n if (signal !== undefined) signal.addEventListener('abort', () => cancel(abortMessage(signal)), { once: true })\n queueMicrotask(() => {\n if (settled) return\n Promise.resolve(target.dispatch<TInput, TOutput, TProgress>({\n connectionId: this.currentPlan.connectionId,\n planRevision: binding.planRevision,\n invocationId,\n binding,\n operation,\n input,\n signal: controller.signal,\n progress: value => { if (!settled) progress.push(value) },\n })).then(value => { if (!settled) { finish(); resolveResult(value) } }, error => {\n if (!settled) { finish(); rejectResult(error) }\n })\n })\n return Object.freeze({ invocationId, result, progress, cancel })\n }\n\n close(reason = 'connection closed'): void {\n if (this.closed) return\n this.closed = true\n for (const cancel of this.active.values()) cancel(reason, 'connection-closed')\n this.active.clear()\n this.listeners.clear()\n }\n\n private assertOpen(): void {\n if (this.closed) throw new ConnectionInvocationError('connection-closed', 'connection is closed')\n }\n}\n\nclass MemoryConnectionView implements StandardConnection {\n constructor(\n private readonly pair: MemoryPair,\n private readonly localEndpoint: MemoryConnectionEndpoint,\n private readonly remoteEndpoint: MemoryConnectionEndpoint,\n ) {}\n\n get id(): string { return this.pair.plan.connectionId }\n get local() { return this.localEndpoint.offer.endpoint }\n get remote() { return this.remoteEndpoint.offer.endpoint }\n get plan() { return this.pair.plan }\n\n client(participantId: string): CapabilityClient {\n nonEmpty(participantId, 'participantId')\n return Object.freeze({\n participantId,\n binding: (reference: ApiReference) => this.pair.binding(this.localEndpoint, participantId, reference),\n invoke: <TInput, TOutput, TProgress>(\n reference: ApiReference, operation: string, input: TInput, options?: { readonly signal?: AbortSignal },\n ) => this.pair.invoke<TInput, TOutput, TProgress>(this.localEndpoint, participantId, reference, operation, input, options?.signal),\n })\n }\n\n onPlanChange(listener: (plan: ConnectionPlan) => void): () => void { return this.pair.subscribe(listener) }\n close(reason?: string): void { this.pair.close(reason) }\n}\n\nclass AsyncProgress<T> implements AsyncIterableIterator<T> {\n private readonly values: T[] = []\n private readonly waiters: Array<(result: IteratorResult<T>) => void> = []\n private done = false\n push(value: T): void {\n if (this.done) return\n const waiter = this.waiters.shift()\n if (waiter === undefined) this.values.push(value)\n else waiter({ done: false, value })\n }\n close(): void {\n if (this.done) return\n this.done = true\n for (const waiter of this.waiters.splice(0)) waiter({ done: true, value: undefined })\n }\n next(): Promise<IteratorResult<T>> {\n if (this.values.length > 0) return Promise.resolve({ done: false, value: this.values.shift() as T })\n if (this.done) return Promise.resolve({ done: true, value: undefined })\n return new Promise(resolve => { this.waiters.push(resolve) })\n }\n return(): Promise<IteratorResult<T>> { this.close(); return Promise.resolve({ done: true, value: undefined }) }\n [Symbol.asyncIterator](): AsyncIterableIterator<T> { return this }\n}\n\nfunction abortMessage(signal: AbortSignal): string {\n return signal.reason instanceof Error ? signal.reason.message : typeof signal.reason === 'string' ? signal.reason : 'capability invocation cancelled'\n}\n\nfunction nonEmpty(value: string, label: string): void {\n if (typeof value !== 'string' || value.trim() === '') throw new TypeError(`${label} must be non-empty`)\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"memory.js","names":[],"sources":["../src/memory.ts"],"sourcesContent":["import { sameProtocol, type ApiReference } from '@dsh-std/core'\nimport {\n ConnectionInvocationError,\n type CapabilityCall,\n type CapabilityClient,\n type CapabilityDispatch,\n type CapabilityImplementation,\n type ConnectionEndpoint,\n type StandardConnection,\n} from './connection.js'\nimport {\n validateEndpointOffer,\n type CapabilityBinding,\n type ConnectionPlan,\n type EndpointOffer,\n type ResolveConnectionOptions,\n} from './model.js'\nimport { resolveConnection } from './resolve.js'\n\nexport class MemoryConnectionEndpoint implements ConnectionEndpoint {\n private currentOffer: EndpointOffer\n private readonly implementations: CapabilityImplementation[] = []\n private readonly offerListeners = new Set<(offer: EndpointOffer) => void>()\n\n constructor(offer: EndpointOffer) {\n validateEndpointOffer(offer)\n this.currentOffer = offer\n }\n\n get offer(): EndpointOffer { return this.currentOffer }\n\n replaceOffer(offer: EndpointOffer): void {\n validateEndpointOffer(offer)\n if (offer.endpoint.instanceId !== this.currentOffer.endpoint.instanceId) throw new TypeError('replacement offer belongs to another endpoint')\n if (offer.revision <= this.currentOffer.revision) throw new TypeError('replacement offer must increase revision')\n this.currentOffer = offer\n for (const listener of this.offerListeners) listener(offer)\n }\n\n register(implementation: CapabilityImplementation): () => void {\n const declaration = this.currentOffer.declarations.find(row => row.participant.id === implementation.participantId)\n if (declaration === undefined || !(declaration.supports ?? []).some(row => sameProtocol(row, implementation.protocol))) {\n throw new TypeError('implementation is not backed by a live endpoint declaration')\n }\n if (this.implementations.some(row => row.participantId === implementation.participantId && sameProtocol(row.protocol, implementation.protocol))) {\n throw new TypeError('capability implementation is already registered')\n }\n const stored = Object.freeze({ ...implementation, protocol: Object.freeze({ ...implementation.protocol }) })\n this.implementations.push(stored)\n return () => {\n const index = this.implementations.indexOf(stored)\n if (index >= 0) this.implementations.splice(index, 1)\n }\n }\n\n async dispatch<TInput = unknown, TOutput = unknown, TProgress = unknown>(invocation: CapabilityDispatch<TInput, TProgress>): Promise<TOutput> {\n const implementation = this.implementations.find(row =>\n row.participantId === invocation.binding.provider.participantId\n && sameProtocol(row.protocol, invocation.binding.support))\n if (implementation === undefined) throw new ConnectionInvocationError('handler-missing', 'binding has no live implementation')\n return await implementation.handle(invocation.operation, invocation.input, Object.freeze({\n connectionId: invocation.connectionId,\n planRevision: invocation.planRevision,\n invocationId: invocation.invocationId,\n binding: invocation.binding,\n signal: invocation.signal,\n progress: invocation.progress,\n })) as TOutput\n }\n\n onOfferChange(listener: (offer: EndpointOffer) => void): () => void {\n this.offerListeners.add(listener)\n return () => { this.offerListeners.delete(listener) }\n }\n}\n\nexport interface MemoryConnectionPair {\n readonly left: StandardConnection\n readonly right: StandardConnection\n readonly plan: ConnectionPlan\n renegotiate(options: ResolveConnectionOptions): ConnectionPlan\n close(reason?: string): void\n}\n\nexport function createMemoryConnectionPair(\n left: ConnectionEndpoint, right: ConnectionEndpoint, options: ResolveConnectionOptions,\n): MemoryConnectionPair {\n return new MemoryPair(left, right, options)\n}\n\nclass MemoryPair implements MemoryConnectionPair {\n private currentPlan: ConnectionPlan\n private closed = false\n private invocationSequence = 0\n private readonly listeners = new Set<(plan: ConnectionPlan) => void>()\n private readonly active = new Map<string, (reason?: string, code?: 'cancelled' | 'connection-closed') => void>()\n readonly left: StandardConnection\n readonly right: StandardConnection\n\n constructor(\n private readonly leftEndpoint: ConnectionEndpoint,\n private readonly rightEndpoint: ConnectionEndpoint,\n options: ResolveConnectionOptions,\n ) {\n this.currentPlan = resolveConnection(leftEndpoint.offer, rightEndpoint.offer, options)\n this.left = new MemoryConnectionView(this, leftEndpoint, rightEndpoint)\n this.right = new MemoryConnectionView(this, rightEndpoint, leftEndpoint)\n }\n\n get plan(): ConnectionPlan { return this.currentPlan }\n\n renegotiate(options: ResolveConnectionOptions): ConnectionPlan {\n this.assertOpen()\n if (options.connectionId !== this.currentPlan.connectionId || options.revision <= this.currentPlan.revision) {\n throw new TypeError('renegotiation must retain connectionId and increase revision')\n }\n this.currentPlan = resolveConnection(this.leftEndpoint.offer, this.rightEndpoint.offer, options)\n for (const listener of this.listeners) listener(this.currentPlan)\n return this.currentPlan\n }\n\n subscribe(listener: (plan: ConnectionPlan) => void): () => void {\n this.listeners.add(listener)\n return () => { this.listeners.delete(listener) }\n }\n\n binding(local: ConnectionEndpoint, participantId: string, reference: ApiReference): CapabilityBinding | undefined {\n if (this.closed) return undefined\n return this.currentPlan.bindings.find(binding =>\n binding.consumer.endpoint.instanceId === local.offer.endpoint.instanceId\n && binding.consumer.participantId === participantId\n && sameProtocol(binding.requirement, reference))\n }\n\n invoke<TInput, TOutput, TProgress>(\n local: ConnectionEndpoint,\n participantId: string,\n reference: ApiReference,\n operation: string,\n input: TInput,\n signal?: AbortSignal,\n ): CapabilityCall<TOutput, TProgress> {\n this.assertOpen()\n signal?.throwIfAborted()\n const binding = this.binding(local, participantId, reference)\n if (binding === undefined) throw new ConnectionInvocationError('capability-unbound', `participant ${JSON.stringify(participantId)} has no binding`)\n const target = binding.provider.endpoint.instanceId === this.leftEndpoint.offer.endpoint.instanceId\n ? this.leftEndpoint\n : binding.provider.endpoint.instanceId === this.rightEndpoint.offer.endpoint.instanceId ? this.rightEndpoint : undefined\n if (target === undefined) throw new ConnectionInvocationError('handler-missing', 'binding provider endpoint is unavailable')\n const invocationId = `${local.offer.endpoint.instanceId}:${String(++this.invocationSequence)}`\n const controller = new AbortController()\n const progress = new AsyncProgress<TProgress>()\n let settled = false\n let resolveResult!: (value: TOutput | PromiseLike<TOutput>) => void\n let rejectResult!: (reason?: unknown) => void\n const result = new Promise<TOutput>((resolve, reject) => { resolveResult = resolve; rejectResult = reject })\n const finish = () => { settled = true; this.active.delete(invocationId); progress.close() }\n const cancel = (reason = 'capability invocation cancelled', code: 'cancelled' | 'connection-closed' = 'cancelled') => {\n if (settled) return\n controller.abort(reason)\n finish()\n rejectResult(new ConnectionInvocationError(code, reason))\n }\n this.active.set(invocationId, cancel)\n if (signal !== undefined) signal.addEventListener('abort', () => cancel(abortMessage(signal)), { once: true })\n queueMicrotask(() => {\n if (settled) return\n Promise.resolve(target.dispatch<TInput, TOutput, TProgress>({\n connectionId: this.currentPlan.connectionId,\n planRevision: binding.planRevision,\n invocationId,\n binding,\n operation,\n input,\n signal: controller.signal,\n progress: value => { if (!settled) progress.push(value) },\n })).then(value => { if (!settled) { finish(); resolveResult(value) } }, error => {\n if (!settled) { finish(); rejectResult(error) }\n })\n })\n return Object.freeze({ invocationId, result, progress, cancel })\n }\n\n close(reason = 'connection closed'): void {\n if (this.closed) return\n this.closed = true\n for (const cancel of this.active.values()) cancel(reason, 'connection-closed')\n this.active.clear()\n this.listeners.clear()\n }\n\n private assertOpen(): void {\n if (this.closed) throw new ConnectionInvocationError('connection-closed', 'connection is closed')\n }\n\n}\n\nclass MemoryConnectionView implements StandardConnection {\n constructor(\n private readonly pair: MemoryPair,\n private readonly localEndpoint: ConnectionEndpoint,\n private readonly remoteEndpoint: ConnectionEndpoint,\n ) {}\n\n get id(): string { return this.pair.plan.connectionId }\n get local() { return this.localEndpoint.offer.endpoint }\n get remote() { return this.remoteEndpoint.offer.endpoint }\n get plan() { return this.pair.plan }\n\n client(participantId: string): CapabilityClient {\n nonEmpty(participantId, 'participantId')\n return Object.freeze({\n participantId,\n binding: (reference: ApiReference) => this.pair.binding(this.localEndpoint, participantId, reference),\n invoke: <TInput, TOutput, TProgress>(\n reference: ApiReference, operation: string, input: TInput, options?: { readonly signal?: AbortSignal },\n ) => this.pair.invoke<TInput, TOutput, TProgress>(this.localEndpoint, participantId, reference, operation, input, options?.signal),\n })\n }\n\n onPlanChange(listener: (plan: ConnectionPlan) => void): () => void { return this.pair.subscribe(listener) }\n close(reason?: string): void { this.pair.close(reason) }\n}\n\nclass AsyncProgress<T> implements AsyncIterableIterator<T> {\n private readonly values: T[] = []\n private readonly waiters: Array<(result: IteratorResult<T>) => void> = []\n private done = false\n push(value: T): void {\n if (this.done) return\n const waiter = this.waiters.shift()\n if (waiter === undefined) this.values.push(value)\n else waiter({ done: false, value })\n }\n close(): void {\n if (this.done) return\n this.done = true\n for (const waiter of this.waiters.splice(0)) waiter({ done: true, value: undefined })\n }\n next(): Promise<IteratorResult<T>> {\n if (this.values.length > 0) return Promise.resolve({ done: false, value: this.values.shift() as T })\n if (this.done) return Promise.resolve({ done: true, value: undefined })\n return new Promise(resolve => { this.waiters.push(resolve) })\n }\n return(): Promise<IteratorResult<T>> { this.close(); return Promise.resolve({ done: true, value: undefined }) }\n [Symbol.asyncIterator](): AsyncIterableIterator<T> { return this }\n}\n\nfunction abortMessage(signal: AbortSignal): string {\n return signal.reason instanceof Error ? signal.reason.message : typeof signal.reason === 'string' ? signal.reason : 'capability invocation cancelled'\n}\n\nfunction nonEmpty(value: string, label: string): void {\n if (typeof value !== 'string' || value.trim() === '') throw new TypeError(`${label} must be non-empty`)\n}\n"],"mappings":"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"}
@@ -9,7 +9,7 @@
9
9
  ".": { "types": "./lib/index.d.ts", "default": "./lib/index.js" },
10
10
  "./memory": { "types": "./lib/memory.d.ts", "default": "./lib/memory.js" }
11
11
  },
12
- "files": ["lib"],
12
+ "files": ["lib", "CHANGELOG.md"],
13
13
  "scripts": {
14
14
  "build": "pnpm run typecheck && tsdown",
15
15
  "typecheck": "tsc -p tsconfig.json --noEmit",
@@ -0,0 +1,8 @@
1
+ # Changelog
2
+
3
+ Changes to `@dsh-std/core` are recorded here.
4
+
5
+ ## 0.1.0 (draft)
6
+
7
+ - Defined protocol coordinates, participant declarations, definition catalogs, and negotiation reports.
8
+ - Separated evaluator knowledge, requirements, potential support, and live support.
@@ -11,7 +11,7 @@
11
11
  "default": "./lib/index.js"
12
12
  }
13
13
  },
14
- "files": ["lib"],
14
+ "files": ["lib", "CHANGELOG.md"],
15
15
  "scripts": {
16
16
  "build": "pnpm run typecheck && tsdown",
17
17
  "typecheck": "tsc -p tsconfig.json --noEmit",
@@ -0,0 +1,9 @@
1
+ # Changelog
2
+
3
+ Changes to `@dsh-std/manifest` are recorded here.
4
+
5
+ ## 0.1.0 (draft)
6
+
7
+ - Added Community v0.15 manifest parsing and validation.
8
+ - Added definition catalogs for independently installed extension protocols.
9
+ - Kept activation, compatibility, and runtime availability separate from manifest validity.
@@ -9,7 +9,7 @@
9
9
  ".": { "types": "./lib/index.d.ts", "default": "./lib/index.js" },
10
10
  "./schema/dsh-plugin-0.15.schema.json": "./schema/dsh-plugin-0.15.schema.json"
11
11
  },
12
- "files": ["lib", "schema"],
12
+ "files": ["lib", "schema", "CHANGELOG.md"],
13
13
  "scripts": {
14
14
  "build": "pnpm run typecheck && tsdown",
15
15
  "typecheck": "tsc -p tsconfig.json --noEmit",
@@ -0,0 +1,9 @@
1
+ # Changelog
2
+
3
+ Changes to `@dsh-std/presentation` are recorded here.
4
+
5
+ ## 0.1.0 (draft)
6
+
7
+ - Defined invocation-scoped `OpenExternal`, `CopyText`, `Notification`, `UserInteraction`, and `ExternalRedirect` capabilities.
8
+ - Added typed question, approval, secret-input, and one-shot loopback redirect flows.
9
+ - Added optional exact loopback callback URIs with explicit-port validation, no-substitution semantics, and address-in-use failure reporting.
@@ -6,12 +6,13 @@ Small, invocation-scoped operations that a runtime facet may request from a conn
6
6
 
7
7
  ## Contracts
8
8
 
9
- `v1alpha1` defines four independent presentation protocols:
9
+ `v1alpha1` defines five independent presentation protocols:
10
10
 
11
11
  - `OpenExternal` asks the client to open an HTTP or HTTPS URI.
12
12
  - `CopyText` asks the client to copy text to its clipboard.
13
13
  - `Notification` asks the client to display informational, warning, or error text.
14
14
  - `UserInteraction` carries structured questions, one-invocation approvals, and secret input.
15
+ - `ExternalRedirect` receives a one-shot HTTP redirect on the user side and may reserve an exact loopback URI requested by the consumer.
15
16
 
16
17
  A facet declares each required operation in its manifest. A client advertises only the protocols it can perform for the current connection. The runtime admits the command only when all required presentation protocols are available, and it accepts only operations declared by that facet. Operations belong to the active invocation; they are not a global event bus or a persistent client capability.
17
18
 
@@ -8,12 +8,13 @@
8
8
 
9
9
  ## 协议
10
10
 
11
- `v1alpha1` 定义四个彼此独立的表现协议:
11
+ `v1alpha1` 定义五个彼此独立的表现协议:
12
12
 
13
13
  - `OpenExternal` 请求客户端打开 HTTP 或 HTTPS URI;
14
14
  - `CopyText` 请求客户端把文本复制到剪贴板;
15
15
  - `Notification` 请求客户端显示信息、警告或错误文本;
16
16
  - `UserInteraction` 承载结构化 question、单次 approval 和 secret input。
17
+ - `ExternalRedirect` 在用户侧接收一次 HTTP redirect,并可按调用方要求独占精确的 loopback URI。
17
18
 
18
19
  Facet 在清单中声明每项所需操作。客户端只为当前连接声明自己能够执行的协议。仅当全部必需表现协议可用时,运行时才接纳命令;运行时也只接受该 facet 事先声明的操作。操作属于当前调用,不是全局事件总线或持久客户端能力。
19
20
 
@@ -0,0 +1,2 @@
1
+ import { EXTERNAL_REDIRECT_KIND, ExternalRedirectCall, ExternalRedirectClient, ExternalRedirectHandler, ExternalRedirectInput, ExternalRedirectReady, ExternalRedirectRequest, ExternalRedirectValue, externalRedirectClient, externalRedirectImplementation, externalRedirectProtocol, externalRedirectSupport, validateExternalRedirectReady, validateExternalRedirectRequest, validateExternalRedirectResult } from "./index.js";
2
+ export { EXTERNAL_REDIRECT_KIND, ExternalRedirectCall, ExternalRedirectClient, ExternalRedirectHandler, ExternalRedirectInput, ExternalRedirectReady, ExternalRedirectRequest, ExternalRedirectValue, externalRedirectClient, externalRedirectImplementation, externalRedirectProtocol, externalRedirectSupport, validateExternalRedirectReady, validateExternalRedirectRequest, validateExternalRedirectResult };