@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.
- package/README.md +22 -13
- package/dsh-ecosystem-spec/protocols/profile-definitions.d.ts +13 -0
- package/dsh-ecosystem-spec/protocols/profile-definitions.js +59 -0
- package/dsh-ecosystem-spec/protocols/tui-channel-http.d.ts +15 -0
- package/dsh-ecosystem-spec/protocols/tui-channel-http.js +32 -0
- package/dsh-ecosystem-spec/protocols/tui-channel.d.ts +59 -0
- package/dsh-ecosystem-spec/protocols/tui-channel.js +166 -0
- package/dsh-ecosystem-spec/protocols/tui-contributions.d.ts +42 -0
- package/dsh-ecosystem-spec/protocols/tui-contributions.js +143 -0
- package/dsh-ecosystem-spec/registry/README.md +14 -0
- package/dsh-ecosystem-spec/registry/contracts/scene-v1alpha1.json +13 -0
- package/dsh-ecosystem-spec/registry/contracts/settings-section-v1alpha1.json +13 -0
- package/dsh-ecosystem-spec/registry/contracts/tui-channel-v1alpha1.json +30 -0
- package/dsh-ecosystem-spec/registry/contracts/workspace-provider-v1alpha1.json +6 -0
- package/{ecosystem-spec → dsh-ecosystem-spec}/registry/permissions-0.1.json +1 -1
- package/dsh-ecosystem-spec/registry/registry-0.15.json +149 -0
- package/lib/types/command-trees.d.ts +2 -1
- package/lib/types/command-trees.d.ts.map +1 -1
- package/lib/types/command-trees.js +1 -1
- package/lib/types/components/LoadedContextPanel.d.ts +10 -5
- package/lib/types/components/LoadedContextPanel.d.ts.map +1 -1
- package/lib/types/components/LoadedContextPanel.js +18 -7
- package/lib/types/components/LogoV2.d.ts.map +1 -1
- package/lib/types/components/LogoV2.js +16 -7
- package/lib/types/components/Markdown.d.ts +13 -1
- package/lib/types/components/Markdown.d.ts.map +1 -1
- package/lib/types/components/Markdown.js +15 -1
- package/lib/types/components/MessageList.d.ts +3 -1
- package/lib/types/components/MessageList.d.ts.map +1 -1
- package/lib/types/components/MessageList.js +90 -9
- package/lib/types/components/PromptInput.d.ts.map +1 -1
- package/lib/types/components/PromptInput.js +26 -12
- package/lib/types/components/StreamingMarkdown.d.ts +2 -8
- package/lib/types/components/StreamingMarkdown.d.ts.map +1 -1
- package/lib/types/components/StreamingMarkdown.js +51 -9
- package/lib/types/components/activityFrames.d.ts +1 -1
- package/lib/types/components/activityFrames.d.ts.map +1 -1
- package/lib/types/components/activityFrames.js +4 -1
- package/lib/types/components/messages/AssistantThinkingMessage.d.ts +5 -1
- package/lib/types/components/messages/AssistantThinkingMessage.d.ts.map +1 -1
- package/lib/types/components/messages/AssistantThinkingMessage.js +26 -3
- package/lib/types/components/messages/AssistantToolUseMessage.d.ts.map +1 -1
- package/lib/types/components/messages/AssistantToolUseMessage.js +12 -1
- package/lib/types/dsh-adapter/channel.d.ts +31 -4
- package/lib/types/dsh-adapter/channel.d.ts.map +1 -1
- package/lib/types/dsh-adapter/channel.js +267 -102
- package/lib/types/dsh-adapter/childStderr.d.ts.map +1 -1
- package/lib/types/dsh-adapter/childStderr.js +10 -0
- package/lib/types/dsh-adapter/command-attribution.d.ts.map +1 -1
- package/lib/types/dsh-adapter/command-attribution.js +2 -2
- package/lib/types/dsh-adapter/command-trees.d.ts +7 -1
- package/lib/types/dsh-adapter/command-trees.d.ts.map +1 -1
- package/lib/types/dsh-adapter/command-trees.js +70 -20
- package/lib/types/dsh-adapter/component-identity.d.ts +5 -0
- package/lib/types/dsh-adapter/component-identity.d.ts.map +1 -1
- package/lib/types/dsh-adapter/component-identity.js +14 -14
- package/lib/types/dsh-adapter/decision-guard.d.ts.map +1 -1
- package/lib/types/dsh-adapter/decision-guard.js +10 -16
- package/lib/types/dsh-adapter/dialogs.d.ts +2 -3
- package/lib/types/dsh-adapter/dialogs.d.ts.map +1 -1
- package/lib/types/dsh-adapter/dialogs.js +114 -60
- package/lib/types/dsh-adapter/effect-ledger.d.ts +0 -8
- package/lib/types/dsh-adapter/effect-ledger.d.ts.map +1 -1
- package/lib/types/dsh-adapter/effect-ledger.js +73 -53
- package/lib/types/dsh-adapter/extension-events.d.ts.map +1 -1
- package/lib/types/dsh-adapter/extension-events.js +39 -1
- package/lib/types/dsh-adapter/grants.d.ts.map +1 -1
- package/lib/types/dsh-adapter/grants.js +43 -14
- package/lib/types/dsh-adapter/host-access.d.ts +37 -0
- package/lib/types/dsh-adapter/host-access.d.ts.map +1 -0
- package/lib/types/dsh-adapter/host-access.js +652 -0
- package/lib/types/dsh-adapter/host-descriptor.d.ts +2 -2
- package/lib/types/dsh-adapter/host-descriptor.d.ts.map +1 -1
- package/lib/types/dsh-adapter/host-descriptor.js +31 -8
- package/lib/types/dsh-adapter/index.d.ts +4 -0
- package/lib/types/dsh-adapter/index.d.ts.map +1 -1
- package/lib/types/dsh-adapter/index.js +1 -0
- package/lib/types/dsh-adapter/message-observer.d.ts +10 -15
- package/lib/types/dsh-adapter/message-observer.d.ts.map +1 -1
- package/lib/types/dsh-adapter/message-observer.js +114 -70
- package/lib/types/dsh-adapter/plugin-host.d.ts +39 -6
- package/lib/types/dsh-adapter/plugin-host.d.ts.map +1 -1
- package/lib/types/dsh-adapter/plugin-host.js +139 -44
- package/lib/types/dsh-adapter/plugin-storage.d.ts +0 -5
- package/lib/types/dsh-adapter/plugin-storage.d.ts.map +1 -1
- package/lib/types/dsh-adapter/plugin-storage.js +48 -36
- package/lib/types/dsh-adapter/plugin.d.ts.map +1 -1
- package/lib/types/dsh-adapter/plugin.js +80 -16
- package/lib/types/dsh-adapter/promptDebug.d.ts +0 -6
- package/lib/types/dsh-adapter/promptDebug.d.ts.map +1 -1
- package/lib/types/dsh-adapter/promptDebug.js +13 -4
- package/lib/types/dsh-adapter/renderers.d.ts +6 -14
- package/lib/types/dsh-adapter/renderers.d.ts.map +1 -1
- package/lib/types/dsh-adapter/renderers.js +81 -46
- package/lib/types/dsh-adapter/scenes.d.ts +8 -4
- package/lib/types/dsh-adapter/scenes.d.ts.map +1 -1
- package/lib/types/dsh-adapter/scenes.js +136 -37
- package/lib/types/dsh-adapter/settings-sections.d.ts +7 -3
- package/lib/types/dsh-adapter/settings-sections.d.ts.map +1 -1
- package/lib/types/dsh-adapter/settings-sections.js +106 -26
- package/lib/types/dsh-adapter/shortcuts.d.ts +8 -10
- package/lib/types/dsh-adapter/shortcuts.d.ts.map +1 -1
- package/lib/types/dsh-adapter/shortcuts.js +108 -36
- package/lib/types/dsh-adapter/status.d.ts +6 -7
- package/lib/types/dsh-adapter/status.d.ts.map +1 -1
- package/lib/types/dsh-adapter/status.js +88 -22
- package/lib/types/dsh-adapter/workspaces.d.ts +16 -5
- package/lib/types/dsh-adapter/workspaces.d.ts.map +1 -1
- package/lib/types/dsh-adapter/workspaces.js +287 -170
- package/lib/types/extensions.d.ts +10 -5
- package/lib/types/extensions.d.ts.map +1 -1
- package/lib/types/extensions.js +11 -5
- package/lib/types/force-production-react.d.ts +1 -0
- package/lib/types/force-production-react.d.ts.map +1 -0
- package/lib/types/force-production-react.js +12 -0
- package/lib/types/i18n.d.ts +14 -6
- package/lib/types/i18n.d.ts.map +1 -1
- package/lib/types/i18n.js +4 -2
- package/lib/types/index.d.ts +1 -0
- package/lib/types/index.d.ts.map +1 -1
- package/lib/types/index.js +1 -0
- package/lib/types/ink/components/App.d.ts +2 -0
- package/lib/types/ink/components/App.d.ts.map +1 -1
- package/lib/types/ink/components/App.js +4 -0
- package/lib/types/ink/ink.d.ts +20 -3
- package/lib/types/ink/ink.d.ts.map +1 -1
- package/lib/types/ink/ink.js +57 -5
- package/lib/types/ink/log-update.d.ts.map +1 -1
- package/lib/types/ink/log-update.js +128 -9
- package/lib/types/ink/output.d.ts +28 -2
- package/lib/types/ink/output.d.ts.map +1 -1
- package/lib/types/ink/output.js +158 -12
- package/lib/types/ink/screen.d.ts +39 -0
- package/lib/types/ink/screen.d.ts.map +1 -1
- package/lib/types/ink/screen.js +117 -0
- package/lib/types/ink/terminal.d.ts.map +1 -1
- package/lib/types/ink/terminal.js +10 -2
- package/lib/types/ink/wrapAnsi.d.ts +1 -1
- package/lib/types/ink/wrapAnsi.d.ts.map +1 -1
- package/lib/types/ink/wrapAnsi.js +29 -2
- package/lib/types/plugin-host.d.ts +13 -11
- package/lib/types/plugin-host.d.ts.map +1 -1
- package/lib/types/plugin-host.js +16 -16
- package/lib/types/plugin-spec/registry.d.ts +2 -2
- package/lib/types/plugin-spec/registry.d.ts.map +1 -1
- package/lib/types/plugin-spec/registry.js +113 -18
- package/lib/types/plugin-spec/tui-extension.d.ts.map +1 -1
- package/lib/types/plugin-spec/tui-extension.js +2 -0
- package/lib/types/plugin-spec/validate.d.ts.map +1 -1
- package/lib/types/plugin-spec/validate.js +20 -1
- package/lib/types/scenes.d.ts +2 -1
- package/lib/types/scenes.d.ts.map +1 -1
- package/lib/types/scenes.js +1 -1
- package/lib/types/screens/Chat.d.ts +3 -3
- package/lib/types/screens/Chat.d.ts.map +1 -1
- package/lib/types/screens/Chat.js +38 -17
- package/lib/types/screens/SessionBrowser.d.ts.map +1 -1
- package/lib/types/screens/SessionBrowser.js +10 -3
- package/lib/types/sessions/view.d.ts +3 -2
- package/lib/types/sessions/view.d.ts.map +1 -1
- package/lib/types/sessions/view.js +18 -0
- package/lib/types/settings-sections.d.ts +2 -1
- package/lib/types/settings-sections.d.ts.map +1 -1
- package/lib/types/settings-sections.js +1 -1
- package/lib/types/utils/execFileNoThrow.d.ts.map +1 -1
- package/lib/types/utils/execFileNoThrow.js +3 -0
- package/lib/types/workspaces.d.ts +2 -1
- package/lib/types/workspaces.d.ts.map +1 -1
- package/lib/types/workspaces.js +1 -1
- package/node_modules/@dsh-std/command/CHANGELOG.md +8 -0
- package/node_modules/@dsh-std/command/package.json +1 -1
- package/node_modules/@dsh-std/connection/CHANGELOG.md +8 -0
- package/node_modules/@dsh-std/connection/lib/memory.d.ts +1 -1
- package/node_modules/@dsh-std/connection/lib/memory.d.ts.map +1 -1
- package/node_modules/@dsh-std/connection/lib/memory.js +1 -0
- package/node_modules/@dsh-std/connection/lib/memory.js.map +1 -1
- package/node_modules/@dsh-std/connection/package.json +1 -1
- package/node_modules/@dsh-std/core/CHANGELOG.md +8 -0
- package/node_modules/@dsh-std/core/package.json +1 -1
- package/node_modules/@dsh-std/manifest/CHANGELOG.md +9 -0
- package/node_modules/@dsh-std/manifest/package.json +1 -1
- package/node_modules/@dsh-std/messages/CHANGELOG.md +8 -0
- package/node_modules/@dsh-std/messages/package.json +1 -1
- package/node_modules/@dsh-std/presentation/CHANGELOG.md +9 -0
- package/node_modules/@dsh-std/presentation/README.md +2 -1
- package/node_modules/@dsh-std/presentation/README.zh.md +2 -1
- package/node_modules/@dsh-std/presentation/lib/callback.d.ts +2 -0
- package/node_modules/@dsh-std/presentation/lib/callback.js +179 -0
- package/node_modules/@dsh-std/presentation/lib/callback.js.map +1 -0
- package/node_modules/@dsh-std/presentation/lib/index.d.ts +44 -1
- package/node_modules/@dsh-std/presentation/lib/index.d.ts.map +1 -1
- package/node_modules/@dsh-std/presentation/lib/index.js +6 -3
- package/node_modules/@dsh-std/presentation/lib/index.js.map +1 -1
- package/node_modules/@dsh-std/presentation/package.json +7 -3
- package/node_modules/@dsh-std/storage/CHANGELOG.md +8 -0
- package/node_modules/@dsh-std/storage/package.json +1 -1
- package/package.json +10 -5
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/connection/CHANGELOG.md +8 -0
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/connection/lib/memory.d.ts +1 -1
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/connection/lib/memory.d.ts.map +1 -1
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/connection/lib/memory.js +1 -0
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/connection/lib/memory.js.map +1 -1
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/connection/package.json +1 -1
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/core/CHANGELOG.md +8 -0
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/core/package.json +1 -1
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/manifest/CHANGELOG.md +9 -0
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/manifest/package.json +1 -1
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/presentation/CHANGELOG.md +9 -0
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/presentation/README.md +2 -1
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/presentation/README.zh.md +2 -1
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/presentation/lib/callback.d.ts +2 -0
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/presentation/lib/callback.js +179 -0
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/presentation/lib/callback.js.map +1 -0
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/presentation/lib/index.d.ts +44 -1
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/presentation/lib/index.d.ts.map +1 -1
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/presentation/lib/index.js +6 -3
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/presentation/lib/index.js.map +1 -1
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/presentation/package.json +7 -3
- package/vendor/dsh-std/packages/connection/node_modules/@dsh-std/core/CHANGELOG.md +8 -0
- package/vendor/dsh-std/packages/connection/node_modules/@dsh-std/core/package.json +1 -1
- package/vendor/dsh-std/packages/manifest/node_modules/@dsh-std/core/CHANGELOG.md +8 -0
- package/vendor/dsh-std/packages/manifest/node_modules/@dsh-std/core/package.json +1 -1
- package/vendor/dsh-std/packages/messages/node_modules/@dsh-std/core/CHANGELOG.md +8 -0
- package/vendor/dsh-std/packages/messages/node_modules/@dsh-std/core/package.json +1 -1
- package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/connection/CHANGELOG.md +8 -0
- package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/connection/lib/memory.d.ts +1 -1
- package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/connection/lib/memory.d.ts.map +1 -1
- package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/connection/lib/memory.js +1 -0
- package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/connection/lib/memory.js.map +1 -1
- package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/connection/package.json +1 -1
- package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/core/CHANGELOG.md +8 -0
- package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/core/package.json +1 -1
- package/vendor/dsh-std/packages/storage/node_modules/@dsh-std/core/CHANGELOG.md +8 -0
- package/vendor/dsh-std/packages/storage/node_modules/@dsh-std/core/package.json +1 -1
- package/ecosystem-spec/registry/registry-0.15.json +0 -57
- /package/{ecosystem-spec → dsh-ecosystem-spec}/registry/contracts/decision-events-v1alpha1.json +0 -0
- /package/{ecosystem-spec → dsh-ecosystem-spec}/registry/host-descriptor.tui.example.json +0 -0
- /package/{ecosystem-spec → dsh-ecosystem-spec}/schemas/conformance-claim.schema.json +0 -0
- /package/{ecosystem-spec → dsh-ecosystem-spec}/schemas/effect-ledger-record.schema.json +0 -0
- /package/{ecosystem-spec → dsh-ecosystem-spec}/schemas/host-descriptor.schema.json +0 -0
|
@@ -1,3 +1,4 @@
|
|
|
1
|
-
export
|
|
1
|
+
export { name, WORKSPACE_PROVIDER_TIMEOUT_MS, TuiWorkspaceRuntime, createLocalWorkspaceRuntime, localWorkspaceUri, parseLocalWorkspaceReference, } from './dsh-adapter/workspaces.js';
|
|
2
|
+
export type { TuiWorkspaceKind, TuiWorkspaceTarget, TuiWorkspaceChoice, TuiWorkspaceCommandResult, TuiWorkspaceCommand, TuiCommandShell, TuiWorkspaceProvider, } from './dsh-adapter/workspaces.js';
|
|
2
3
|
export { default } from './dsh-adapter/workspaces.js';
|
|
3
4
|
//# sourceMappingURL=workspaces.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"workspaces.d.ts","sourceRoot":"","sources":["../../src/workspaces.ts"],"names":[],"mappings":"AAEA,
|
|
1
|
+
{"version":3,"file":"workspaces.d.ts","sourceRoot":"","sources":["../../src/workspaces.ts"],"names":[],"mappings":"AAEA,OAAO,EACL,IAAI,EACJ,6BAA6B,EAC7B,mBAAmB,EACnB,2BAA2B,EAC3B,iBAAiB,EACjB,4BAA4B,GAC7B,MAAM,6BAA6B,CAAA;AACpC,YAAY,EACV,gBAAgB,EAChB,kBAAkB,EAClB,kBAAkB,EAClB,yBAAyB,EACzB,mBAAmB,EACnB,eAAe,EACf,oBAAoB,GACrB,MAAM,6BAA6B,CAAA;AACpC,OAAO,EAAE,OAAO,EAAE,MAAM,6BAA6B,CAAA"}
|
package/lib/types/workspaces.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
// Re-export shim: the Cordis-backed implementation lives behind the adapter
|
|
2
2
|
// boundary so UI consumers never import official @deepseek-ai/* packages.
|
|
3
|
-
export
|
|
3
|
+
export { name, WORKSPACE_PROVIDER_TIMEOUT_MS, TuiWorkspaceRuntime, createLocalWorkspaceRuntime, localWorkspaceUri, parseLocalWorkspaceReference, } from './dsh-adapter/workspaces.js';
|
|
4
4
|
export { default } from './dsh-adapter/workspaces.js';
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
"main": "lib/index.js",
|
|
7
7
|
"types": "lib/index.d.ts",
|
|
8
8
|
"exports": { ".": { "types": "./lib/index.d.ts", "default": "./lib/index.js" } },
|
|
9
|
-
"files": ["lib"],
|
|
9
|
+
"files": ["lib", "CHANGELOG.md"],
|
|
10
10
|
"scripts": {
|
|
11
11
|
"build": "pnpm run typecheck && tsdown",
|
|
12
12
|
"typecheck": "tsc -p tsconfig.json --noEmit",
|
|
@@ -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:
|
|
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,
|
|
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.
|
|
@@ -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",
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
".": { "types": "./lib/index.d.ts", "default": "./lib/index.js" },
|
|
10
10
|
"./schema/message-observer-envelope-0.15.json": "./schema/message-observer-envelope-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
|
|
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 };
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
import { defineCapabilityProtocol } from "@dsh-std/connection";
|
|
2
|
+
//#region src/callback.ts
|
|
3
|
+
const EXTERNAL_REDIRECT_KIND = "ExternalRedirect";
|
|
4
|
+
const emptySpec = (value) => {
|
|
5
|
+
if (value !== void 0) throw new TypeError("ExternalRedirect does not accept spec in v1alpha1");
|
|
6
|
+
};
|
|
7
|
+
const externalRedirectProtocol = defineCapabilityProtocol({
|
|
8
|
+
apiVersion: "presentation.dsh/v1alpha1",
|
|
9
|
+
kind: EXTERNAL_REDIRECT_KIND,
|
|
10
|
+
validateRequirement: emptySpec,
|
|
11
|
+
validateSupport: emptySpec
|
|
12
|
+
});
|
|
13
|
+
const externalRedirectSupport = Object.freeze({
|
|
14
|
+
apiVersion: "presentation.dsh/v1alpha1",
|
|
15
|
+
kind: EXTERNAL_REDIRECT_KIND
|
|
16
|
+
});
|
|
17
|
+
function externalRedirectClient(client, scope) {
|
|
18
|
+
validateScope(scope);
|
|
19
|
+
return Object.freeze({ receive(input = {}, options) {
|
|
20
|
+
const request = Object.freeze({
|
|
21
|
+
...input,
|
|
22
|
+
mode: input.mode ?? "http-get",
|
|
23
|
+
requestId: nextRequestId(scope),
|
|
24
|
+
invocationId: scope.invocationId,
|
|
25
|
+
origin: scope.origin,
|
|
26
|
+
...scope.deadline === void 0 ? {} : { deadline: scope.deadline }
|
|
27
|
+
});
|
|
28
|
+
validateExternalRedirectRequest(request);
|
|
29
|
+
const call = client.invoke(externalRedirectSupport, "receive", request, options);
|
|
30
|
+
return Object.freeze({
|
|
31
|
+
invocationId: call.invocationId,
|
|
32
|
+
ready: firstReady(call.progress),
|
|
33
|
+
result: call.result.then(validateExternalRedirectResult),
|
|
34
|
+
cancel: (reason) => call.cancel(reason)
|
|
35
|
+
});
|
|
36
|
+
} });
|
|
37
|
+
}
|
|
38
|
+
function externalRedirectImplementation(participantId, handler) {
|
|
39
|
+
return Object.freeze({
|
|
40
|
+
participantId,
|
|
41
|
+
protocol: externalRedirectSupport,
|
|
42
|
+
async handle(operation, input, context) {
|
|
43
|
+
if (operation !== "receive") throw new TypeError(`unsupported ExternalRedirect operation ${JSON.stringify(operation)}`);
|
|
44
|
+
validateExternalRedirectRequest(input);
|
|
45
|
+
let announced = false;
|
|
46
|
+
const guardedContext = Object.freeze({
|
|
47
|
+
...context,
|
|
48
|
+
progress(value) {
|
|
49
|
+
if (announced) throw new TypeError("ExternalRedirect provider emitted more than one ready event");
|
|
50
|
+
validateExternalRedirectReady(value);
|
|
51
|
+
if (input.exactRedirectUri !== void 0 && value.redirectUri !== input.exactRedirectUri) throw new TypeError("ExternalRedirect provider did not announce the exact requested redirect URI");
|
|
52
|
+
announced = true;
|
|
53
|
+
context.progress(value);
|
|
54
|
+
}
|
|
55
|
+
});
|
|
56
|
+
const result = validateExternalRedirectResult(await handler.receive(input, guardedContext));
|
|
57
|
+
if (result.status === "submitted" && !announced) throw new TypeError("ExternalRedirect provider submitted a result before announcing redirectUri");
|
|
58
|
+
return result;
|
|
59
|
+
}
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
function validateExternalRedirectRequest(value) {
|
|
63
|
+
const request = exactRecord(value, [
|
|
64
|
+
"requestId",
|
|
65
|
+
"invocationId",
|
|
66
|
+
"origin",
|
|
67
|
+
"deadline",
|
|
68
|
+
"mode",
|
|
69
|
+
"exactRedirectUri"
|
|
70
|
+
], [
|
|
71
|
+
"requestId",
|
|
72
|
+
"invocationId",
|
|
73
|
+
"origin",
|
|
74
|
+
"mode"
|
|
75
|
+
], "ExternalRedirect request");
|
|
76
|
+
nonEmpty(request.requestId, "ExternalRedirect request.requestId");
|
|
77
|
+
nonEmpty(request.invocationId, "ExternalRedirect request.invocationId");
|
|
78
|
+
nonEmpty(request.origin, "ExternalRedirect request.origin");
|
|
79
|
+
if (request.mode !== "http-get") throw new TypeError("ExternalRedirect request.mode must be \"http-get\"");
|
|
80
|
+
if (request.exactRedirectUri !== void 0) validateLoopbackUri(request.exactRedirectUri, "ExternalRedirect request.exactRedirectUri", true);
|
|
81
|
+
dateTime(request.deadline, "ExternalRedirect request.deadline");
|
|
82
|
+
}
|
|
83
|
+
function validateExternalRedirectReady(value) {
|
|
84
|
+
const ready = exactRecord(value, [
|
|
85
|
+
"type",
|
|
86
|
+
"redirectUri",
|
|
87
|
+
"expiresAt"
|
|
88
|
+
], ["type", "redirectUri"], "ExternalRedirect ready");
|
|
89
|
+
if (ready.type !== "ready") throw new TypeError("ExternalRedirect ready.type must be \"ready\"");
|
|
90
|
+
validateLoopbackUri(ready.redirectUri, "ExternalRedirect ready.redirectUri", false);
|
|
91
|
+
dateTime(ready.expiresAt, "ExternalRedirect ready.expiresAt");
|
|
92
|
+
}
|
|
93
|
+
function validateExternalRedirectResult(value) {
|
|
94
|
+
if (!record(value)) throw new TypeError("ExternalRedirect result must be an object");
|
|
95
|
+
if (value.status === "submitted") {
|
|
96
|
+
const submitted = exactRecord(exactRecord(value, ["status", "value"], ["status", "value"], "ExternalRedirect result").value, ["query"], ["query"], "ExternalRedirect value");
|
|
97
|
+
if (!record(submitted.query)) throw new TypeError("ExternalRedirect value.query must be an object");
|
|
98
|
+
const query = {};
|
|
99
|
+
for (const [name, entries] of Object.entries(submitted.query)) {
|
|
100
|
+
if (name === "" || !Array.isArray(entries) || entries.some((entry) => typeof entry !== "string")) throw new TypeError("ExternalRedirect value.query must map non-empty names to string arrays");
|
|
101
|
+
query[name] = Object.freeze([...entries]);
|
|
102
|
+
}
|
|
103
|
+
return Object.freeze({
|
|
104
|
+
status: "submitted",
|
|
105
|
+
value: Object.freeze({ query: Object.freeze(query) })
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
if (value.status === "unavailable") {
|
|
109
|
+
const result = exactRecord(value, ["status", "reason"], ["status"], "ExternalRedirect result");
|
|
110
|
+
if (result.reason !== void 0) nonEmpty(result.reason, "ExternalRedirect result.reason");
|
|
111
|
+
return Object.freeze({
|
|
112
|
+
status: "unavailable",
|
|
113
|
+
...result.reason === void 0 ? {} : { reason: result.reason }
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
if (value.status === "cancelled" || value.status === "expired") {
|
|
117
|
+
exactRecord(value, ["status"], ["status"], "ExternalRedirect result");
|
|
118
|
+
return Object.freeze({ status: value.status });
|
|
119
|
+
}
|
|
120
|
+
throw new TypeError("ExternalRedirect result.status is invalid");
|
|
121
|
+
}
|
|
122
|
+
async function firstReady(progress) {
|
|
123
|
+
for await (const value of progress) {
|
|
124
|
+
validateExternalRedirectReady(value);
|
|
125
|
+
return Object.freeze({ ...value });
|
|
126
|
+
}
|
|
127
|
+
throw new TypeError("ExternalRedirect provider completed without announcing redirectUri");
|
|
128
|
+
}
|
|
129
|
+
function validateScope(scope) {
|
|
130
|
+
if (!record(scope)) throw new TypeError("Presentation invocation scope must be an object");
|
|
131
|
+
nonEmpty(scope.invocationId, "Presentation invocation scope.invocationId");
|
|
132
|
+
nonEmpty(scope.origin, "Presentation invocation scope.origin");
|
|
133
|
+
dateTime(scope.deadline, "Presentation invocation scope.deadline");
|
|
134
|
+
if (typeof scope.nextRequestId !== "function") throw new TypeError("Presentation invocation scope.nextRequestId must be a function");
|
|
135
|
+
}
|
|
136
|
+
function nextRequestId(scope) {
|
|
137
|
+
const value = scope.nextRequestId();
|
|
138
|
+
nonEmpty(value, "Presentation requestId");
|
|
139
|
+
return value;
|
|
140
|
+
}
|
|
141
|
+
function exactRecord(value, allowed, required, label) {
|
|
142
|
+
if (!record(value)) throw new TypeError(`${label} must be an object`);
|
|
143
|
+
const unknown = Object.keys(value).filter((key) => !allowed.includes(key));
|
|
144
|
+
if (unknown.length > 0) throw new TypeError(`${label} contains unknown field ${JSON.stringify(unknown[0])}`);
|
|
145
|
+
for (const key of required) if (!Object.hasOwn(value, key)) throw new TypeError(`${label}.${key} is required`);
|
|
146
|
+
return value;
|
|
147
|
+
}
|
|
148
|
+
function record(value) {
|
|
149
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
150
|
+
}
|
|
151
|
+
function nonEmpty(value, label) {
|
|
152
|
+
if (typeof value !== "string" || value.trim() === "") throw new TypeError(`${label} must be a non-empty string`);
|
|
153
|
+
}
|
|
154
|
+
function dateTime(value, label) {
|
|
155
|
+
if (value !== void 0 && (typeof value !== "string" || Number.isNaN(Date.parse(value)))) throw new TypeError(`${label} must be an RFC 3339 date-time`);
|
|
156
|
+
}
|
|
157
|
+
function validateLoopbackUri(value, label, requireExplicitPort) {
|
|
158
|
+
nonEmpty(value, label);
|
|
159
|
+
let uri;
|
|
160
|
+
try {
|
|
161
|
+
uri = new URL(value);
|
|
162
|
+
} catch {
|
|
163
|
+
throw new TypeError(`${label} must be an absolute URI`);
|
|
164
|
+
}
|
|
165
|
+
if (uri.protocol !== "http:") throw new TypeError(`${label} must use HTTP`);
|
|
166
|
+
if (uri.hostname !== "127.0.0.1" && uri.hostname !== "[::1]" && uri.hostname !== "localhost") throw new TypeError(`${label} must target a loopback host`);
|
|
167
|
+
if (uri.username !== "" || uri.password !== "") throw new TypeError(`${label} must not contain user information`);
|
|
168
|
+
if (uri.hash !== "") throw new TypeError(`${label} must not contain a fragment`);
|
|
169
|
+
if (requireExplicitPort) {
|
|
170
|
+
const authority = value.slice(value.indexOf("//") + 2).split(/[/?#]/u, 1)[0];
|
|
171
|
+
const match = /^(?:127\.0\.0\.1|localhost):(\d+)$|^\[::1\]:(\d+)$/iu.exec(authority);
|
|
172
|
+
const port = Number(match?.[1] ?? match?.[2]);
|
|
173
|
+
if (!Number.isSafeInteger(port) || port < 1 || port > 65535) throw new TypeError(`${label} must include an explicit TCP port`);
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
//#endregion
|
|
177
|
+
export { EXTERNAL_REDIRECT_KIND, externalRedirectClient, externalRedirectImplementation, externalRedirectProtocol, externalRedirectSupport, validateExternalRedirectReady, validateExternalRedirectRequest, validateExternalRedirectResult };
|
|
178
|
+
|
|
179
|
+
//# sourceMappingURL=callback.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"callback.js","names":[],"sources":["../src/callback.ts"],"sourcesContent":["import type {\n CapabilityClient,\n CapabilityHandlerContext,\n CapabilityImplementation,\n} from '@dsh-std/connection'\nimport { defineCapabilityProtocol } from '@dsh-std/connection'\nimport type { ProtocolSupport } from '@dsh-std/core'\nimport type { PresentationInvocationScope, PresentationRequestContext, PresentationResult } from './index.js'\n\nexport const EXTERNAL_REDIRECT_KIND = 'ExternalRedirect'\n\nexport interface ExternalRedirectRequest extends PresentationRequestContext {\n readonly mode: 'http-get'\n /** Exact loopback URI required by the external provider, including an explicit port. */\n readonly exactRedirectUri?: string\n}\nexport interface ExternalRedirectInput {\n readonly mode?: 'http-get'\n /** The provider must bind and announce this exact URI or report the request unavailable. */\n readonly exactRedirectUri?: string\n}\n\nexport interface ExternalRedirectReady {\n readonly type: 'ready'\n readonly redirectUri: string\n readonly expiresAt?: string\n}\n\nexport interface ExternalRedirectValue {\n readonly query: Readonly<Record<string, readonly string[]>>\n}\n\nexport interface ExternalRedirectCall {\n readonly invocationId: string\n readonly ready: Promise<ExternalRedirectReady>\n readonly result: Promise<PresentationResult<ExternalRedirectValue>>\n cancel(reason?: string): void\n}\n\nexport interface ExternalRedirectClient {\n receive(input?: ExternalRedirectInput, options?: { readonly signal?: AbortSignal }): ExternalRedirectCall\n}\n\nexport interface ExternalRedirectHandler {\n receive(\n request: ExternalRedirectRequest,\n context: CapabilityHandlerContext<ExternalRedirectReady>,\n ): PresentationResult<ExternalRedirectValue> | Promise<PresentationResult<ExternalRedirectValue>>\n}\n\nconst emptySpec = (value: unknown): undefined => {\n if (value !== undefined) throw new TypeError('ExternalRedirect does not accept spec in v1alpha1')\n return undefined\n}\n\nexport const externalRedirectProtocol = defineCapabilityProtocol({\n apiVersion: 'presentation.dsh/v1alpha1', kind: EXTERNAL_REDIRECT_KIND,\n validateRequirement: emptySpec, validateSupport: emptySpec,\n})\nexport const externalRedirectSupport: ProtocolSupport = Object.freeze({\n apiVersion: 'presentation.dsh/v1alpha1', kind: EXTERNAL_REDIRECT_KIND,\n})\n\nexport function externalRedirectClient(client: CapabilityClient, scope: PresentationInvocationScope): ExternalRedirectClient {\n validateScope(scope)\n return Object.freeze({\n receive(input: ExternalRedirectInput = {}, options?: { readonly signal?: AbortSignal }) {\n const request = Object.freeze({\n ...input,\n mode: input.mode ?? 'http-get',\n requestId: nextRequestId(scope), invocationId: scope.invocationId, origin: scope.origin,\n ...(scope.deadline === undefined ? {} : { deadline: scope.deadline }),\n })\n validateExternalRedirectRequest(request)\n const call = client.invoke<ExternalRedirectRequest, PresentationResult<ExternalRedirectValue>, ExternalRedirectReady>(\n externalRedirectSupport, 'receive', request, options,\n )\n return Object.freeze({\n invocationId: call.invocationId,\n ready: firstReady(call.progress),\n result: call.result.then(validateExternalRedirectResult),\n cancel: (reason?: string) => call.cancel(reason),\n })\n },\n })\n}\n\nexport function externalRedirectImplementation(\n participantId: string,\n handler: ExternalRedirectHandler,\n): CapabilityImplementation<ExternalRedirectRequest, PresentationResult<ExternalRedirectValue>, ExternalRedirectReady> {\n return Object.freeze({\n participantId, protocol: externalRedirectSupport,\n async handle(operation: string, input: ExternalRedirectRequest, context: CapabilityHandlerContext<ExternalRedirectReady>) {\n if (operation !== 'receive') throw new TypeError(`unsupported ExternalRedirect operation ${JSON.stringify(operation)}`)\n validateExternalRedirectRequest(input)\n let announced = false\n const guardedContext: CapabilityHandlerContext<ExternalRedirectReady> = Object.freeze({\n ...context,\n progress(value: ExternalRedirectReady) {\n if (announced) throw new TypeError('ExternalRedirect provider emitted more than one ready event')\n validateExternalRedirectReady(value)\n if (input.exactRedirectUri !== undefined && value.redirectUri !== input.exactRedirectUri) {\n throw new TypeError('ExternalRedirect provider did not announce the exact requested redirect URI')\n }\n announced = true\n context.progress(value)\n },\n })\n const result = validateExternalRedirectResult(await handler.receive(input, guardedContext))\n if (result.status === 'submitted' && !announced) {\n throw new TypeError('ExternalRedirect provider submitted a result before announcing redirectUri')\n }\n return result\n },\n })\n}\n\nexport function validateExternalRedirectRequest(value: unknown): asserts value is ExternalRedirectRequest {\n const request = exactRecord(value, ['requestId', 'invocationId', 'origin', 'deadline', 'mode', 'exactRedirectUri'], ['requestId', 'invocationId', 'origin', 'mode'], 'ExternalRedirect request')\n nonEmpty(request.requestId, 'ExternalRedirect request.requestId')\n nonEmpty(request.invocationId, 'ExternalRedirect request.invocationId')\n nonEmpty(request.origin, 'ExternalRedirect request.origin')\n if (request.mode !== 'http-get') throw new TypeError('ExternalRedirect request.mode must be \"http-get\"')\n if (request.exactRedirectUri !== undefined) validateLoopbackUri(request.exactRedirectUri, 'ExternalRedirect request.exactRedirectUri', true)\n dateTime(request.deadline, 'ExternalRedirect request.deadline')\n}\n\nexport function validateExternalRedirectReady(value: unknown): asserts value is ExternalRedirectReady {\n const ready = exactRecord(value, ['type', 'redirectUri', 'expiresAt'], ['type', 'redirectUri'], 'ExternalRedirect ready')\n if (ready.type !== 'ready') throw new TypeError('ExternalRedirect ready.type must be \"ready\"')\n validateLoopbackUri(ready.redirectUri, 'ExternalRedirect ready.redirectUri', false)\n dateTime(ready.expiresAt, 'ExternalRedirect ready.expiresAt')\n}\n\nexport function validateExternalRedirectResult(value: unknown): PresentationResult<ExternalRedirectValue> {\n if (!record(value)) throw new TypeError('ExternalRedirect result must be an object')\n if (value.status === 'submitted') {\n const result = exactRecord(value, ['status', 'value'], ['status', 'value'], 'ExternalRedirect result')\n const submitted = exactRecord(result.value, ['query'], ['query'], 'ExternalRedirect value')\n if (!record(submitted.query)) throw new TypeError('ExternalRedirect value.query must be an object')\n const query: Record<string, readonly string[]> = {}\n for (const [name, entries] of Object.entries(submitted.query)) {\n if (name === '' || !Array.isArray(entries) || entries.some(entry => typeof entry !== 'string')) {\n throw new TypeError('ExternalRedirect value.query must map non-empty names to string arrays')\n }\n query[name] = Object.freeze([...entries])\n }\n return Object.freeze({ status: 'submitted', value: Object.freeze({ query: Object.freeze(query) }) })\n }\n if (value.status === 'unavailable') {\n const result = exactRecord(value, ['status', 'reason'], ['status'], 'ExternalRedirect result')\n if (result.reason !== undefined) nonEmpty(result.reason, 'ExternalRedirect result.reason')\n return Object.freeze({ status: 'unavailable', ...(result.reason === undefined ? {} : { reason: result.reason as string }) })\n }\n if (value.status === 'cancelled' || value.status === 'expired') {\n exactRecord(value, ['status'], ['status'], 'ExternalRedirect result')\n return Object.freeze({ status: value.status })\n }\n throw new TypeError('ExternalRedirect result.status is invalid')\n}\n\nasync function firstReady(progress: AsyncIterable<ExternalRedirectReady>): Promise<ExternalRedirectReady> {\n for await (const value of progress) {\n validateExternalRedirectReady(value)\n return Object.freeze({ ...value })\n }\n throw new TypeError('ExternalRedirect provider completed without announcing redirectUri')\n}\n\nfunction validateScope(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 dateTime(scope.deadline, 'Presentation invocation scope.deadline')\n if (typeof scope.nextRequestId !== 'function') throw new TypeError('Presentation invocation scope.nextRequestId must be a function')\n}\n\nfunction nextRequestId(scope: PresentationInvocationScope): string {\n const value = scope.nextRequestId()\n nonEmpty(value, 'Presentation requestId')\n return value\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}\nfunction record(value: unknown): value is Record<string, unknown> { return typeof value === 'object' && value !== null && !Array.isArray(value) }\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}\nfunction dateTime(value: unknown, label: string): void {\n if (value !== undefined && (typeof value !== 'string' || Number.isNaN(Date.parse(value)))) throw new TypeError(`${label} must be an RFC 3339 date-time`)\n}\n\nfunction validateLoopbackUri(value: unknown, label: string, requireExplicitPort: boolean): asserts value is string {\n nonEmpty(value, label)\n let uri: URL\n try {\n uri = new URL(value)\n } catch {\n throw new TypeError(`${label} must be an absolute URI`)\n }\n if (uri.protocol !== 'http:') throw new TypeError(`${label} must use HTTP`)\n if (uri.hostname !== '127.0.0.1' && uri.hostname !== '[::1]' && uri.hostname !== 'localhost') {\n throw new TypeError(`${label} must target a loopback host`)\n }\n if (uri.username !== '' || uri.password !== '') throw new TypeError(`${label} must not contain user information`)\n if (uri.hash !== '') throw new TypeError(`${label} must not contain a fragment`)\n if (requireExplicitPort) {\n const authority = value.slice(value.indexOf('//') + 2).split(/[/?#]/u, 1)[0]!\n const match = /^(?:127\\.0\\.0\\.1|localhost):(\\d+)$|^\\[::1\\]:(\\d+)$/iu.exec(authority)\n const port = Number(match?.[1] ?? match?.[2])\n if (!Number.isSafeInteger(port) || port < 1 || port > 65_535) {\n throw new TypeError(`${label} must include an explicit TCP port`)\n }\n }\n}\n"],"mappings":"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"}
|
|
@@ -173,6 +173,7 @@ interface PresentationClients {
|
|
|
173
173
|
readonly copyText?: CopyTextClient;
|
|
174
174
|
readonly notification?: NotificationClient;
|
|
175
175
|
readonly interaction?: UserInteractionClient;
|
|
176
|
+
readonly externalRedirect?: ExternalRedirectClient;
|
|
176
177
|
}
|
|
177
178
|
interface OpenExternalHandler {
|
|
178
179
|
openExternal(request: OpenExternalRequest, context: CapabilityHandlerContext): PresentationResult<OpenExternalReceipt> | Promise<PresentationResult<OpenExternalReceipt>>;
|
|
@@ -215,5 +216,47 @@ declare function validateUserInteractionRequest(value: unknown): asserts value i
|
|
|
215
216
|
declare function validateUserInteractionRequirement(value: unknown): UserInteractionRequirementSpec;
|
|
216
217
|
declare function validateUserInteractionSupport(value: unknown): UserInteractionSupportSpec;
|
|
217
218
|
//#endregion
|
|
218
|
-
|
|
219
|
+
//#region src/callback.d.ts
|
|
220
|
+
declare const EXTERNAL_REDIRECT_KIND = "ExternalRedirect";
|
|
221
|
+
interface ExternalRedirectRequest extends PresentationRequestContext {
|
|
222
|
+
readonly mode: 'http-get';
|
|
223
|
+
/** Exact loopback URI required by the external provider, including an explicit port. */
|
|
224
|
+
readonly exactRedirectUri?: string;
|
|
225
|
+
}
|
|
226
|
+
interface ExternalRedirectInput {
|
|
227
|
+
readonly mode?: 'http-get';
|
|
228
|
+
/** The provider must bind and announce this exact URI or report the request unavailable. */
|
|
229
|
+
readonly exactRedirectUri?: string;
|
|
230
|
+
}
|
|
231
|
+
interface ExternalRedirectReady {
|
|
232
|
+
readonly type: 'ready';
|
|
233
|
+
readonly redirectUri: string;
|
|
234
|
+
readonly expiresAt?: string;
|
|
235
|
+
}
|
|
236
|
+
interface ExternalRedirectValue {
|
|
237
|
+
readonly query: Readonly<Record<string, readonly string[]>>;
|
|
238
|
+
}
|
|
239
|
+
interface ExternalRedirectCall {
|
|
240
|
+
readonly invocationId: string;
|
|
241
|
+
readonly ready: Promise<ExternalRedirectReady>;
|
|
242
|
+
readonly result: Promise<PresentationResult<ExternalRedirectValue>>;
|
|
243
|
+
cancel(reason?: string): void;
|
|
244
|
+
}
|
|
245
|
+
interface ExternalRedirectClient {
|
|
246
|
+
receive(input?: ExternalRedirectInput, options?: {
|
|
247
|
+
readonly signal?: AbortSignal;
|
|
248
|
+
}): ExternalRedirectCall;
|
|
249
|
+
}
|
|
250
|
+
interface ExternalRedirectHandler {
|
|
251
|
+
receive(request: ExternalRedirectRequest, context: CapabilityHandlerContext<ExternalRedirectReady>): PresentationResult<ExternalRedirectValue> | Promise<PresentationResult<ExternalRedirectValue>>;
|
|
252
|
+
}
|
|
253
|
+
declare const externalRedirectProtocol: import("@dsh-std/core").ProtocolDefinition<unknown, unknown, unknown, unknown>;
|
|
254
|
+
declare const externalRedirectSupport: ProtocolSupport;
|
|
255
|
+
declare function externalRedirectClient(client: CapabilityClient, scope: PresentationInvocationScope): ExternalRedirectClient;
|
|
256
|
+
declare function externalRedirectImplementation(participantId: string, handler: ExternalRedirectHandler): CapabilityImplementation<ExternalRedirectRequest, PresentationResult<ExternalRedirectValue>, ExternalRedirectReady>;
|
|
257
|
+
declare function validateExternalRedirectRequest(value: unknown): asserts value is ExternalRedirectRequest;
|
|
258
|
+
declare function validateExternalRedirectReady(value: unknown): asserts value is ExternalRedirectReady;
|
|
259
|
+
declare function validateExternalRedirectResult(value: unknown): PresentationResult<ExternalRedirectValue>;
|
|
260
|
+
//#endregion
|
|
261
|
+
export { API_VERSION, ApprovalDetail, ApprovalInput, ApprovalRequest, ApprovalValue, COPY_TEXT_KIND, ConfirmQuestionField, CopyTextClient, CopyTextHandler, CopyTextInput, CopyTextReceipt, CopyTextRequest, EXTERNAL_REDIRECT_KIND, ExternalRedirectCall, ExternalRedirectClient, ExternalRedirectHandler, ExternalRedirectInput, ExternalRedirectReady, ExternalRedirectRequest, ExternalRedirectValue, NOTIFICATION_KIND, NotificationClient, NotificationHandler, NotificationInput, NotificationReceipt, NotificationRequest, OPEN_EXTERNAL_KIND, OpenExternalClient, OpenExternalHandler, OpenExternalInput, OpenExternalReceipt, OpenExternalRequest, PresentationClients, PresentationDescriptor, PresentationInvocationScope, PresentationRequestContext, PresentationResult, QuestionAnswers, QuestionField, QuestionInput, QuestionOption, QuestionRequest, SecretInput, SecretInputRequest, SecretInputValue, SelectQuestionField, TextQuestionField, USER_INTERACTION_KIND, UserInteractionClient, UserInteractionHandler, UserInteractionLimits, UserInteractionOperation, UserInteractionRequest, UserInteractionRequirementSpec, UserInteractionSupportSpec, UserInteractionValue, copyTextClient, copyTextImplementation, copyTextProtocol, copyTextSupport, externalRedirectClient, externalRedirectImplementation, externalRedirectProtocol, externalRedirectSupport, notificationClient, notificationImplementation, notificationProtocol, notificationSupport, openExternalClient, openExternalImplementation, openExternalProtocol, openExternalSupport, presentationClients, protocols, register, userInteractionClient, userInteractionImplementation, userInteractionProtocol, userInteractionSupport, validateCopyTextRequest, validateExternalRedirectReady, validateExternalRedirectRequest, validateExternalRedirectResult, validateNotificationRequest, validateOpenExternalRequest, validatePresentationDescriptor, validateUserInteractionRequest, validateUserInteractionRequirement, validateUserInteractionSupport };
|
|
219
262
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","names":[],"sources":["../src/index.ts"],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"index.d.ts","names":[],"sources":["../src/index.ts","../src/callback.ts"],"mappings":"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"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { EXTERNAL_REDIRECT_KIND, externalRedirectClient, externalRedirectImplementation, externalRedirectProtocol, externalRedirectSupport, validateExternalRedirectReady, validateExternalRedirectRequest, validateExternalRedirectResult } from "./callback.js";
|
|
1
2
|
import { defineCapabilityProtocol } from "@dsh-std/connection";
|
|
2
3
|
//#region src/index.ts
|
|
3
4
|
const API_VERSION = "presentation.dsh/v1alpha1";
|
|
@@ -54,7 +55,8 @@ const protocols = Object.freeze([
|
|
|
54
55
|
openExternalProtocol,
|
|
55
56
|
copyTextProtocol,
|
|
56
57
|
notificationProtocol,
|
|
57
|
-
userInteractionProtocol
|
|
58
|
+
userInteractionProtocol,
|
|
59
|
+
externalRedirectProtocol
|
|
58
60
|
]);
|
|
59
61
|
function register(catalog) {
|
|
60
62
|
const disposers = protocols.map((protocol) => catalog.register(protocol));
|
|
@@ -106,7 +108,8 @@ function presentationClients(descriptor, client, scope) {
|
|
|
106
108
|
...has("OpenExternal") ? { openExternal: openExternalClient(client, scope) } : {},
|
|
107
109
|
...has("CopyText") ? { copyText: copyTextClient(client, scope) } : {},
|
|
108
110
|
...has("Notification") ? { notification: notificationClient(client, scope) } : {},
|
|
109
|
-
...has("UserInteraction") ? { interaction: userInteractionClient(client, scope) } : {}
|
|
111
|
+
...has("UserInteraction") ? { interaction: userInteractionClient(client, scope) } : {},
|
|
112
|
+
...has("ExternalRedirect") ? { externalRedirect: externalRedirectClient(client, scope) } : {}
|
|
110
113
|
});
|
|
111
114
|
}
|
|
112
115
|
function openExternalImplementation(participantId, handler) {
|
|
@@ -542,6 +545,6 @@ function deepFreeze(value) {
|
|
|
542
545
|
return value;
|
|
543
546
|
}
|
|
544
547
|
//#endregion
|
|
545
|
-
export { API_VERSION, COPY_TEXT_KIND, NOTIFICATION_KIND, OPEN_EXTERNAL_KIND, USER_INTERACTION_KIND, copyTextClient, copyTextImplementation, copyTextProtocol, copyTextSupport, notificationClient, notificationImplementation, notificationProtocol, notificationSupport, openExternalClient, openExternalImplementation, openExternalProtocol, openExternalSupport, presentationClients, protocols, register, userInteractionClient, userInteractionImplementation, userInteractionProtocol, userInteractionSupport, validateCopyTextRequest, validateNotificationRequest, validateOpenExternalRequest, validatePresentationDescriptor, validateUserInteractionRequest, validateUserInteractionRequirement, validateUserInteractionSupport };
|
|
548
|
+
export { API_VERSION, COPY_TEXT_KIND, EXTERNAL_REDIRECT_KIND, NOTIFICATION_KIND, OPEN_EXTERNAL_KIND, USER_INTERACTION_KIND, copyTextClient, copyTextImplementation, copyTextProtocol, copyTextSupport, externalRedirectClient, externalRedirectImplementation, externalRedirectProtocol, externalRedirectSupport, notificationClient, notificationImplementation, notificationProtocol, notificationSupport, openExternalClient, openExternalImplementation, openExternalProtocol, openExternalSupport, presentationClients, protocols, register, userInteractionClient, userInteractionImplementation, userInteractionProtocol, userInteractionSupport, validateCopyTextRequest, validateExternalRedirectReady, validateExternalRedirectRequest, validateExternalRedirectResult, validateNotificationRequest, validateOpenExternalRequest, validatePresentationDescriptor, validateUserInteractionRequest, validateUserInteractionRequirement, validateUserInteractionSupport };
|
|
546
549
|
|
|
547
550
|
//# sourceMappingURL=index.js.map
|