@krischoichoi/channel-harness 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (202) hide show
  1. package/README.md +110 -0
  2. package/lib/access/controller.d.ts +37 -0
  3. package/lib/access/controller.d.ts.map +1 -0
  4. package/lib/access/controller.js +51 -0
  5. package/lib/access/controller.js.map +1 -0
  6. package/lib/access/decision.d.ts +18 -0
  7. package/lib/access/decision.d.ts.map +1 -0
  8. package/lib/access/decision.js +2 -0
  9. package/lib/access/decision.js.map +1 -0
  10. package/lib/access/resolver.d.ts +41 -0
  11. package/lib/access/resolver.d.ts.map +1 -0
  12. package/lib/access/resolver.js +31 -0
  13. package/lib/access/resolver.js.map +1 -0
  14. package/lib/agent-manager.d.ts +314 -0
  15. package/lib/agent-manager.d.ts.map +1 -0
  16. package/lib/agent-manager.js +603 -0
  17. package/lib/agent-manager.js.map +1 -0
  18. package/lib/agent-router.d.ts +37 -0
  19. package/lib/agent-router.d.ts.map +1 -0
  20. package/lib/agent-router.js +33 -0
  21. package/lib/agent-router.js.map +1 -0
  22. package/lib/bind-support.d.ts +23 -0
  23. package/lib/bind-support.d.ts.map +1 -0
  24. package/lib/bind-support.js +63 -0
  25. package/lib/bind-support.js.map +1 -0
  26. package/lib/binding-store.d.ts +104 -0
  27. package/lib/binding-store.d.ts.map +1 -0
  28. package/lib/binding-store.js +354 -0
  29. package/lib/binding-store.js.map +1 -0
  30. package/lib/bridge.d.ts +248 -0
  31. package/lib/bridge.d.ts.map +1 -0
  32. package/lib/bridge.js +961 -0
  33. package/lib/bridge.js.map +1 -0
  34. package/lib/channel-label.d.ts +46 -0
  35. package/lib/channel-label.d.ts.map +1 -0
  36. package/lib/channel-label.js +89 -0
  37. package/lib/channel-label.js.map +1 -0
  38. package/lib/channel-session-factory.d.ts +76 -0
  39. package/lib/channel-session-factory.d.ts.map +1 -0
  40. package/lib/channel-session-factory.js +187 -0
  41. package/lib/channel-session-factory.js.map +1 -0
  42. package/lib/commands/bind.d.ts +21 -0
  43. package/lib/commands/bind.d.ts.map +1 -0
  44. package/lib/commands/bind.js +91 -0
  45. package/lib/commands/bind.js.map +1 -0
  46. package/lib/commands/help.d.ts +15 -0
  47. package/lib/commands/help.d.ts.map +1 -0
  48. package/lib/commands/help.js +89 -0
  49. package/lib/commands/help.js.map +1 -0
  50. package/lib/commands/index.d.ts +122 -0
  51. package/lib/commands/index.d.ts.map +1 -0
  52. package/lib/commands/index.js +63 -0
  53. package/lib/commands/index.js.map +1 -0
  54. package/lib/commands/locale.d.ts +9 -0
  55. package/lib/commands/locale.d.ts.map +1 -0
  56. package/lib/commands/locale.js +27 -0
  57. package/lib/commands/locale.js.map +1 -0
  58. package/lib/commands/mirror.d.ts +14 -0
  59. package/lib/commands/mirror.d.ts.map +1 -0
  60. package/lib/commands/mirror.js +44 -0
  61. package/lib/commands/mirror.js.map +1 -0
  62. package/lib/commands/model.d.ts +20 -0
  63. package/lib/commands/model.d.ts.map +1 -0
  64. package/lib/commands/model.js +106 -0
  65. package/lib/commands/model.js.map +1 -0
  66. package/lib/commands/models.d.ts +14 -0
  67. package/lib/commands/models.d.ts.map +1 -0
  68. package/lib/commands/models.js +67 -0
  69. package/lib/commands/models.js.map +1 -0
  70. package/lib/commands/new.d.ts +14 -0
  71. package/lib/commands/new.d.ts.map +1 -0
  72. package/lib/commands/new.js +37 -0
  73. package/lib/commands/new.js.map +1 -0
  74. package/lib/commands/status.d.ts +12 -0
  75. package/lib/commands/status.d.ts.map +1 -0
  76. package/lib/commands/status.js +30 -0
  77. package/lib/commands/status.js.map +1 -0
  78. package/lib/commands/stop.d.ts +16 -0
  79. package/lib/commands/stop.d.ts.map +1 -0
  80. package/lib/commands/stop.js +27 -0
  81. package/lib/commands/stop.js.map +1 -0
  82. package/lib/commands/version.d.ts +25 -0
  83. package/lib/commands/version.d.ts.map +1 -0
  84. package/lib/commands/version.js +57 -0
  85. package/lib/commands/version.js.map +1 -0
  86. package/lib/config.d.ts +119 -0
  87. package/lib/config.d.ts.map +1 -0
  88. package/lib/config.js +60 -0
  89. package/lib/config.js.map +1 -0
  90. package/lib/debug-logger.d.ts +8 -0
  91. package/lib/debug-logger.d.ts.map +1 -0
  92. package/lib/debug-logger.js +32 -0
  93. package/lib/debug-logger.js.map +1 -0
  94. package/lib/dsh-home.d.ts +12 -0
  95. package/lib/dsh-home.d.ts.map +1 -0
  96. package/lib/dsh-home.js +31 -0
  97. package/lib/dsh-home.js.map +1 -0
  98. package/lib/failure-display.d.ts +10 -0
  99. package/lib/failure-display.d.ts.map +1 -0
  100. package/lib/failure-display.js +42 -0
  101. package/lib/failure-display.js.map +1 -0
  102. package/lib/file-provider.d.ts +96 -0
  103. package/lib/file-provider.d.ts.map +1 -0
  104. package/lib/file-provider.js +44 -0
  105. package/lib/file-provider.js.map +1 -0
  106. package/lib/index.d.ts +31 -0
  107. package/lib/index.d.ts.map +1 -0
  108. package/lib/index.js +31 -0
  109. package/lib/index.js.map +1 -0
  110. package/lib/interactions/index.d.ts +13 -0
  111. package/lib/interactions/index.d.ts.map +1 -0
  112. package/lib/interactions/index.js +13 -0
  113. package/lib/interactions/index.js.map +1 -0
  114. package/lib/interactions/question-backend.d.ts +133 -0
  115. package/lib/interactions/question-backend.d.ts.map +1 -0
  116. package/lib/interactions/question-backend.js +37 -0
  117. package/lib/interactions/question-backend.js.map +1 -0
  118. package/lib/interactions/question-presenter.d.ts +68 -0
  119. package/lib/interactions/question-presenter.d.ts.map +1 -0
  120. package/lib/interactions/question-presenter.js +425 -0
  121. package/lib/interactions/question-presenter.js.map +1 -0
  122. package/lib/interactions/question-renderer.d.ts +37 -0
  123. package/lib/interactions/question-renderer.d.ts.map +1 -0
  124. package/lib/interactions/question-renderer.js +79 -0
  125. package/lib/interactions/question-renderer.js.map +1 -0
  126. package/lib/interactions/question-state.d.ts +106 -0
  127. package/lib/interactions/question-state.d.ts.map +1 -0
  128. package/lib/interactions/question-state.js +99 -0
  129. package/lib/interactions/question-state.js.map +1 -0
  130. package/lib/interactions/question-text-answer.d.ts +37 -0
  131. package/lib/interactions/question-text-answer.d.ts.map +1 -0
  132. package/lib/interactions/question-text-answer.js +70 -0
  133. package/lib/interactions/question-text-answer.js.map +1 -0
  134. package/lib/interactions/question-waterfall-backend.d.ts +42 -0
  135. package/lib/interactions/question-waterfall-backend.d.ts.map +1 -0
  136. package/lib/interactions/question-waterfall-backend.js +162 -0
  137. package/lib/interactions/question-waterfall-backend.js.map +1 -0
  138. package/lib/lifecycle.d.ts +36 -0
  139. package/lib/lifecycle.d.ts.map +1 -0
  140. package/lib/lifecycle.js +303 -0
  141. package/lib/lifecycle.js.map +1 -0
  142. package/lib/loggable-error.d.ts +10 -0
  143. package/lib/loggable-error.d.ts.map +1 -0
  144. package/lib/loggable-error.js +32 -0
  145. package/lib/loggable-error.js.map +1 -0
  146. package/lib/message-converter.d.ts +64 -0
  147. package/lib/message-converter.d.ts.map +1 -0
  148. package/lib/message-converter.js +191 -0
  149. package/lib/message-converter.js.map +1 -0
  150. package/lib/model-selection.d.ts +54 -0
  151. package/lib/model-selection.d.ts.map +1 -0
  152. package/lib/model-selection.js +116 -0
  153. package/lib/model-selection.js.map +1 -0
  154. package/lib/outbox/binding-resolver.d.ts +23 -0
  155. package/lib/outbox/binding-resolver.d.ts.map +1 -0
  156. package/lib/outbox/binding-resolver.js +38 -0
  157. package/lib/outbox/binding-resolver.js.map +1 -0
  158. package/lib/outbox/capabilities.d.ts +48 -0
  159. package/lib/outbox/capabilities.d.ts.map +1 -0
  160. package/lib/outbox/capabilities.js +35 -0
  161. package/lib/outbox/capabilities.js.map +1 -0
  162. package/lib/outbox/index.d.ts +14 -0
  163. package/lib/outbox/index.d.ts.map +1 -0
  164. package/lib/outbox/index.js +14 -0
  165. package/lib/outbox/index.js.map +1 -0
  166. package/lib/outbox/service.d.ts +48 -0
  167. package/lib/outbox/service.d.ts.map +1 -0
  168. package/lib/outbox/service.js +74 -0
  169. package/lib/outbox/service.js.map +1 -0
  170. package/lib/outbox/target.d.ts +17 -0
  171. package/lib/outbox/target.d.ts.map +1 -0
  172. package/lib/outbox/target.js +15 -0
  173. package/lib/outbox/target.js.map +1 -0
  174. package/lib/outbox/tool-send.d.ts +19 -0
  175. package/lib/outbox/tool-send.d.ts.map +1 -0
  176. package/lib/outbox/tool-send.js +77 -0
  177. package/lib/outbox/tool-send.js.map +1 -0
  178. package/lib/outbox/types.d.ts +42 -0
  179. package/lib/outbox/types.d.ts.map +1 -0
  180. package/lib/outbox/types.js +30 -0
  181. package/lib/outbox/types.js.map +1 -0
  182. package/lib/plugin.d.ts +27 -0
  183. package/lib/plugin.d.ts.map +1 -0
  184. package/lib/plugin.js +47 -0
  185. package/lib/plugin.js.map +1 -0
  186. package/lib/reply-context-store.d.ts +69 -0
  187. package/lib/reply-context-store.d.ts.map +1 -0
  188. package/lib/reply-context-store.js +75 -0
  189. package/lib/reply-context-store.js.map +1 -0
  190. package/lib/reply-router.d.ts +138 -0
  191. package/lib/reply-router.d.ts.map +1 -0
  192. package/lib/reply-router.js +674 -0
  193. package/lib/reply-router.js.map +1 -0
  194. package/lib/session-router.d.ts +49 -0
  195. package/lib/session-router.d.ts.map +1 -0
  196. package/lib/session-router.js +45 -0
  197. package/lib/session-router.js.map +1 -0
  198. package/lib/workspace-resolver.d.ts +67 -0
  199. package/lib/workspace-resolver.d.ts.map +1 -0
  200. package/lib/workspace-resolver.js +102 -0
  201. package/lib/workspace-resolver.js.map +1 -0
  202. package/package.json +103 -0
@@ -0,0 +1,96 @@
1
+ import type { Context } from '@deepseek-ai/cordis';
2
+ import type { StoredBinaryPart } from './message-converter.js';
3
+ export interface ChannelAttachmentContext {
4
+ sessionId: string;
5
+ channelId: string;
6
+ accountId: string;
7
+ conversationId: string;
8
+ conversationType?: 'dm' | 'group';
9
+ threadId?: string;
10
+ messageId: string;
11
+ }
12
+ export interface ChannelAttachmentDescriptor {
13
+ attachmentId: string;
14
+ name: string;
15
+ mimeType?: string;
16
+ bytes: number;
17
+ durable: boolean;
18
+ readable: boolean;
19
+ }
20
+ export type ResolvedChannelAttachmentKind = 'image' | 'file' | 'audio' | 'video';
21
+ export interface ResolvedChannelAttachment {
22
+ kind: ResolvedChannelAttachmentKind;
23
+ data: Uint8Array;
24
+ name: string;
25
+ mimeType?: string;
26
+ }
27
+ /** Input for mirroring one inbound image into the private asset store. */
28
+ export interface ChannelImageStoreInput {
29
+ /**
30
+ * The HARNESS attachment id (the model-visible `sha256:…` ref id) — the
31
+ * mirror MUST be stored under exactly this id so the outbox can resolve
32
+ * the image for outbound sends (issue #7).
33
+ */
34
+ attachmentId: string;
35
+ data: Uint8Array;
36
+ mimeType?: string;
37
+ name?: string;
38
+ }
39
+ /**
40
+ * Optional generic-attachment capability supplied by an extension package.
41
+ * Core responsibility: `store` / `resolveAttachment` / session ACL.
42
+ * Tool registration (`read_channel_attachment`) is NOT part of the core
43
+ * contract — `installCompatibilityTools` is optional and keeps the tool
44
+ * registered while it is the compatibility path; once Harness
45
+ * ships a native generic-attachment surface this method can be dropped.
46
+ */
47
+ export interface ChannelAttachmentProvider {
48
+ store(context: ChannelAttachmentContext, part: StoredBinaryPart): Promise<ChannelAttachmentDescriptor | undefined>;
49
+ resolveAttachment(attachmentId: string, sessionId: string): Promise<ResolvedChannelAttachment>;
50
+ /**
51
+ * Optional image mirror (issue #7): store the inbound image bytes under
52
+ * the harness attachment id so `send_channel_message` can re-send them.
53
+ * Best-effort by contract — absent or failing implementations leave the
54
+ * harness image seam authoritative; the outbound resolution then simply
55
+ * misses for images.
56
+ */
57
+ storeImage?(context: ChannelAttachmentContext, image: ChannelImageStoreInput): Promise<ChannelAttachmentDescriptor | undefined>;
58
+ installCompatibilityTools?(agentContext: Context): Promise<void>;
59
+ /**
60
+ * @deprecated implement {@link installCompatibilityTools} instead. Retained
61
+ * for one compatibility cycle so providers built against the former
62
+ * ChannelFileProvider contract keep registering their agent-scoped tools.
63
+ */
64
+ installTools?(agentContext: Context): Promise<void>;
65
+ }
66
+ /** @internal Install at most one provider tool hook, preferring the new name. */
67
+ export declare function installAttachmentCompatibilityTools(provider: ChannelAttachmentProvider, agentContext: Context): Promise<void>;
68
+ /**
69
+ * Live view over the OPTIONAL attachment-provider seam.
70
+ *
71
+ * The provider is resolved through `resolve()` on EVERY call instead of being
72
+ * captured once at bridge startup. The bundle's `channels-files` row starts
73
+ * CONCURRENTLY with `channels-harness` (the Cordis entry group creates every
74
+ * row through `Promise.allSettled`), so a startup snapshot is a race: the
75
+ * harness fiber can apply first and permanently wire itself to “no provider”
76
+ * while `channelFiles` mounts a moment later — which silently disables the
77
+ * outbound attachment resolver (issue #7) and the inbound image mirror.
78
+ *
79
+ * Resolving live also keeps the documented contract of the extension honest:
80
+ * deleting the `channels-files` row stays a supported configuration (absent
81
+ * stays absent, nothing becomes a hard dependency).
82
+ */
83
+ export declare function liveAttachmentProvider(resolve: () => ChannelAttachmentProvider | undefined): ChannelAttachmentProvider;
84
+ /**
85
+ * @deprecated use {@link ChannelAttachmentProvider}
86
+ */
87
+ export type ChannelFileProvider = ChannelAttachmentProvider;
88
+ /**
89
+ * @deprecated use {@link ChannelAttachmentContext}
90
+ */
91
+ export type ChannelFileContext = ChannelAttachmentContext;
92
+ /**
93
+ * @deprecated use {@link ChannelAttachmentDescriptor}
94
+ */
95
+ export type ChannelFileDescriptor = ChannelAttachmentDescriptor;
96
+ //# sourceMappingURL=file-provider.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"file-provider.d.ts","sourceRoot":"","sources":["../src/file-provider.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAE/D,MAAM,WAAW,wBAAwB;IACvC,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,cAAc,EAAE,MAAM,CAAC;IACvB,gBAAgB,CAAC,EAAE,IAAI,GAAG,OAAO,CAAC;IAClC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,2BAA2B;IAC1C,YAAY,EAAE,MAAM,CAAC;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,OAAO,CAAC;IACjB,QAAQ,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,MAAM,6BAA6B,GAAG,OAAO,GAAG,MAAM,GAAG,OAAO,GAAG,OAAO,CAAC;AAEjF,MAAM,WAAW,yBAAyB;IACxC,IAAI,EAAE,6BAA6B,CAAC;IACpC,IAAI,EAAE,UAAU,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,0EAA0E;AAC1E,MAAM,WAAW,sBAAsB;IACrC;;;;OAIG;IACH,YAAY,EAAE,MAAM,CAAC;IACrB,IAAI,EAAE,UAAU,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,yBAAyB;IACxC,KAAK,CACH,OAAO,EAAE,wBAAwB,EACjC,IAAI,EAAE,gBAAgB,GACrB,OAAO,CAAC,2BAA2B,GAAG,SAAS,CAAC,CAAC;IACpD,iBAAiB,CACf,YAAY,EAAE,MAAM,EACpB,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,yBAAyB,CAAC,CAAC;IACtC;;;;;;OAMG;IACH,UAAU,CAAC,CACT,OAAO,EAAE,wBAAwB,EACjC,KAAK,EAAE,sBAAsB,GAC5B,OAAO,CAAC,2BAA2B,GAAG,SAAS,CAAC,CAAC;IACpD,yBAAyB,CAAC,CAAC,YAAY,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACjE;;;;OAIG;IACH,YAAY,CAAC,CAAC,YAAY,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACrD;AAED,iFAAiF;AACjF,wBAAsB,mCAAmC,CACvD,QAAQ,EAAE,yBAAyB,EACnC,YAAY,EAAE,OAAO,GACpB,OAAO,CAAC,IAAI,CAAC,CAGf;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,sBAAsB,CACpC,OAAO,EAAE,MAAM,yBAAyB,GAAG,SAAS,GACnD,yBAAyB,CAuB3B;AAED;;GAEG;AACH,MAAM,MAAM,mBAAmB,GAAG,yBAAyB,CAAC;AAE5D;;GAEG;AACH,MAAM,MAAM,kBAAkB,GAAG,wBAAwB,CAAC;AAE1D;;GAEG;AACH,MAAM,MAAM,qBAAqB,GAAG,2BAA2B,CAAC"}
@@ -0,0 +1,44 @@
1
+ /** @internal Install at most one provider tool hook, preferring the new name. */
2
+ export async function installAttachmentCompatibilityTools(provider, agentContext) {
3
+ const install = provider.installCompatibilityTools ?? provider.installTools;
4
+ await install?.call(provider, agentContext);
5
+ }
6
+ /**
7
+ * Live view over the OPTIONAL attachment-provider seam.
8
+ *
9
+ * The provider is resolved through `resolve()` on EVERY call instead of being
10
+ * captured once at bridge startup. The bundle's `channels-files` row starts
11
+ * CONCURRENTLY with `channels-harness` (the Cordis entry group creates every
12
+ * row through `Promise.allSettled`), so a startup snapshot is a race: the
13
+ * harness fiber can apply first and permanently wire itself to “no provider”
14
+ * while `channelFiles` mounts a moment later — which silently disables the
15
+ * outbound attachment resolver (issue #7) and the inbound image mirror.
16
+ *
17
+ * Resolving live also keeps the documented contract of the extension honest:
18
+ * deleting the `channels-files` row stays a supported configuration (absent
19
+ * stays absent, nothing becomes a hard dependency).
20
+ */
21
+ export function liveAttachmentProvider(resolve) {
22
+ return {
23
+ async store(context, part) {
24
+ return resolve()?.store(context, part);
25
+ },
26
+ async resolveAttachment(attachmentId, sessionId) {
27
+ const provider = resolve();
28
+ if (!provider) {
29
+ throw new Error('no channel attachment provider is mounted (the channelFiles service is unavailable)');
30
+ }
31
+ return provider.resolveAttachment(attachmentId, sessionId);
32
+ },
33
+ async storeImage(context, image) {
34
+ return resolve()?.storeImage?.(context, image);
35
+ },
36
+ async installCompatibilityTools(agentContext) {
37
+ const provider = resolve();
38
+ if (!provider)
39
+ return;
40
+ await installAttachmentCompatibilityTools(provider, agentContext);
41
+ },
42
+ };
43
+ }
44
+ //# sourceMappingURL=file-provider.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"file-provider.js","sourceRoot":"","sources":["../src/file-provider.ts"],"names":[],"mappings":"AAiFA,iFAAiF;AACjF,MAAM,CAAC,KAAK,UAAU,mCAAmC,CACvD,QAAmC,EACnC,YAAqB;IAErB,MAAM,OAAO,GAAG,QAAQ,CAAC,yBAAyB,IAAI,QAAQ,CAAC,YAAY,CAAC;IAC5E,MAAM,OAAO,EAAE,IAAI,CAAC,QAAQ,EAAE,YAAY,CAAC,CAAC;AAC9C,CAAC;AAED;;;;;;;;;;;;;;GAcG;AACH,MAAM,UAAU,sBAAsB,CACpC,OAAoD;IAEpD,OAAO;QACL,KAAK,CAAC,KAAK,CAAC,OAAO,EAAE,IAAI;YACvB,OAAO,OAAO,EAAE,EAAE,KAAK,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;QACzC,CAAC;QACD,KAAK,CAAC,iBAAiB,CAAC,YAAY,EAAE,SAAS;YAC7C,MAAM,QAAQ,GAAG,OAAO,EAAE,CAAC;YAC3B,IAAI,CAAC,QAAQ,EAAE,CAAC;gBACd,MAAM,IAAI,KAAK,CACb,qFAAqF,CACtF,CAAC;YACJ,CAAC;YACD,OAAO,QAAQ,CAAC,iBAAiB,CAAC,YAAY,EAAE,SAAS,CAAC,CAAC;QAC7D,CAAC;QACD,KAAK,CAAC,UAAU,CAAC,OAAO,EAAE,KAAK;YAC7B,OAAO,OAAO,EAAE,EAAE,UAAU,EAAE,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;QACjD,CAAC;QACD,KAAK,CAAC,yBAAyB,CAAC,YAAY;YAC1C,MAAM,QAAQ,GAAG,OAAO,EAAE,CAAC;YAC3B,IAAI,CAAC,QAAQ;gBAAE,OAAO;YACtB,MAAM,mCAAmC,CAAC,QAAQ,EAAE,YAAY,CAAC,CAAC;QACpE,CAAC;KACF,CAAC;AACJ,CAAC"}
package/lib/index.d.ts ADDED
@@ -0,0 +1,31 @@
1
+ /**
2
+ * @krischoichoi/channel-harness — the only package that imports Harness public APIs.
3
+ *
4
+ * Bridges ChannelEvents (from `@krischoichoi/channel-core` adapters) to Harness
5
+ * sessions: inbound messages resolve to a SessionBinding, resolve/create an
6
+ * agent via `ctx.agents`, and call `agent.followup`; outbound assistant
7
+ * output flows back through the official `session/event` feed to the channel
8
+ * adapter's reply pipeline.
9
+ *
10
+ * This package never imports platform SDKs and never depends on concrete
11
+ * channel packages.
12
+ */
13
+ export * from './config.js';
14
+ export * from './channel-label.js';
15
+ export * from './dsh-home.js';
16
+ export * from './file-provider.js';
17
+ export * from './outbox/index.js';
18
+ export * from './session-router.js';
19
+ export * from './binding-store.js';
20
+ export * from './agent-router.js';
21
+ export * from './agent-manager.js';
22
+ export * from './message-converter.js';
23
+ export * from './model-selection.js';
24
+ export * from './reply-router.js';
25
+ export * from './reply-context-store.js';
26
+ export * from './interactions/index.js';
27
+ export * from './bridge.js';
28
+ export * from './lifecycle.js';
29
+ export * from './workspace-resolver.js';
30
+ export { name, inject, apply } from './plugin.js';
31
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,cAAc,aAAa,CAAC;AAC5B,cAAc,oBAAoB,CAAC;AACnC,cAAc,eAAe,CAAC;AAC9B,cAAc,oBAAoB,CAAC;AACnC,cAAc,mBAAmB,CAAC;AAClC,cAAc,qBAAqB,CAAC;AACpC,cAAc,oBAAoB,CAAC;AACnC,cAAc,mBAAmB,CAAC;AAClC,cAAc,oBAAoB,CAAC;AACnC,cAAc,wBAAwB,CAAC;AACvC,cAAc,sBAAsB,CAAC;AACrC,cAAc,mBAAmB,CAAC;AAClC,cAAc,0BAA0B,CAAC;AACzC,cAAc,yBAAyB,CAAC;AACxC,cAAc,aAAa,CAAC;AAC5B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,yBAAyB,CAAC;AACxC,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC"}
package/lib/index.js ADDED
@@ -0,0 +1,31 @@
1
+ /**
2
+ * @krischoichoi/channel-harness — the only package that imports Harness public APIs.
3
+ *
4
+ * Bridges ChannelEvents (from `@krischoichoi/channel-core` adapters) to Harness
5
+ * sessions: inbound messages resolve to a SessionBinding, resolve/create an
6
+ * agent via `ctx.agents`, and call `agent.followup`; outbound assistant
7
+ * output flows back through the official `session/event` feed to the channel
8
+ * adapter's reply pipeline.
9
+ *
10
+ * This package never imports platform SDKs and never depends on concrete
11
+ * channel packages.
12
+ */
13
+ export * from './config.js';
14
+ export * from './channel-label.js';
15
+ export * from './dsh-home.js';
16
+ export * from './file-provider.js';
17
+ export * from './outbox/index.js';
18
+ export * from './session-router.js';
19
+ export * from './binding-store.js';
20
+ export * from './agent-router.js';
21
+ export * from './agent-manager.js';
22
+ export * from './message-converter.js';
23
+ export * from './model-selection.js';
24
+ export * from './reply-router.js';
25
+ export * from './reply-context-store.js';
26
+ export * from './interactions/index.js';
27
+ export * from './bridge.js';
28
+ export * from './lifecycle.js';
29
+ export * from './workspace-resolver.js';
30
+ export { name, inject, apply } from './plugin.js';
31
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,cAAc,aAAa,CAAC;AAC5B,cAAc,oBAAoB,CAAC;AACnC,cAAc,eAAe,CAAC;AAC9B,cAAc,oBAAoB,CAAC;AACnC,cAAc,mBAAmB,CAAC;AAClC,cAAc,qBAAqB,CAAC;AACpC,cAAc,oBAAoB,CAAC;AACnC,cAAc,mBAAmB,CAAC;AAClC,cAAc,oBAAoB,CAAC;AACnC,cAAc,wBAAwB,CAAC;AACvC,cAAc,sBAAsB,CAAC;AACrC,cAAc,mBAAmB,CAAC;AAClC,cAAc,0BAA0B,CAAC;AACzC,cAAc,yBAAyB,CAAC;AACxC,cAAc,aAAa,CAAC;AAC5B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,yBAAyB,CAAC;AACxC,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC"}
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Channel-side human interactions.
3
+ *
4
+ * `QuestionInteraction*` today; the directory and interface naming leave
5
+ * room for an `ApprovalInteraction` sibling (future) without sharing
6
+ * interfaces prematurely — the official question/approval domains compose
7
+ * answerers on the same Cordis waterfall mechanism.
8
+ */
9
+ export * from './question-backend.js';
10
+ export * from './question-presenter.js';
11
+ export * from './question-state.js';
12
+ export * from './question-waterfall-backend.js';
13
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/interactions/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,cAAc,uBAAuB,CAAC;AACtC,cAAc,yBAAyB,CAAC;AACxC,cAAc,qBAAqB,CAAC;AACpC,cAAc,iCAAiC,CAAC"}
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Channel-side human interactions.
3
+ *
4
+ * `QuestionInteraction*` today; the directory and interface naming leave
5
+ * room for an `ApprovalInteraction` sibling (future) without sharing
6
+ * interfaces prematurely — the official question/approval domains compose
7
+ * answerers on the same Cordis waterfall mechanism.
8
+ */
9
+ export * from './question-backend.js';
10
+ export * from './question-presenter.js';
11
+ export * from './question-state.js';
12
+ export * from './question-waterfall-backend.js';
13
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/interactions/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,cAAc,uBAAuB,CAAC;AACtC,cAAc,yBAAyB,CAAC;AACxC,cAAc,qBAAqB,CAAC;AACpC,cAAc,iCAAiC,CAAC"}
@@ -0,0 +1,133 @@
1
+ /**
2
+ * Question interaction backend contract + answerer assembly.
3
+ *
4
+ * The official question domain (`ask_user_question` -> `ctx.userQuestions`)
5
+ * dispatches the `user-questions/request` Cordis waterfall; answerers claim a
6
+ * request by returning an answer or delegate with `next()`. The channel
7
+ * composes ONE waterfall answerer that serves every profile:
8
+ *
9
+ * - **Headless**: the channel is typically the only answerer, so a declined
10
+ * presentation fails the ask (`NO_PROVIDER` from the official service).
11
+ * - **Web profile**: the official Remote/Web answerer is composed on the same
12
+ * waterfall and claims first unless the channel answerer is PREPENDED (see
13
+ * `question-waterfall-backend.ts`); a channel decline still delegates to it.
14
+ *
15
+ * There is no version branching here: the waterfall is the only transport,
16
+ * and the `userQuestions` probe is diagnostic (never an admission gate).
17
+ *
18
+ * Naming leaves room for the upcoming approval interaction:
19
+ * everything here is `QuestionInteraction*` under `interactions/`,
20
+ * and the official domain already carries approval requests a future
21
+ * `ApprovalInteraction` can compose the same way.
22
+ */
23
+ import type { Context } from '@deepseek-ai/cordis';
24
+ import type { AskUserQuestionAnswer, AskUserQuestionItem } from '@deepseek-ai/dsh-user-questions/types';
25
+ import type { ChannelAdapter, ChannelLogger } from '@krischoichoi/channel-core';
26
+ import type { AgentManager } from '../agent-manager.js';
27
+ import type { ReplyContextStore } from '../reply-context-store.js';
28
+ import { type ChannelUserQuestionService } from './question-waterfall-backend.js';
29
+ import { ChannelQuestionPresenter } from './question-presenter.js';
30
+ /** One question batch arriving from the Harness question domain. */
31
+ export interface QuestionInteractionRequest {
32
+ /** Correlation key the backend minted (the waterfall ask key). */
33
+ key: string;
34
+ sessionId: string;
35
+ /** Official question items; every field (incl. `intent`) is carried verbatim. */
36
+ questions: AskUserQuestionItem[];
37
+ }
38
+ /**
39
+ * The channel presentation side, as seen by a backend. Backends push
40
+ * harness-origin question traffic through this sink; the presenter resolves
41
+ * answers back through {@link QuestionInteractionBackend}.
42
+ */
43
+ export interface QuestionInteractionSink {
44
+ /**
45
+ * Present a question batch on its bound channel conversation.
46
+ *
47
+ * @returns true when the channel took ownership (it will later resolve or
48
+ * cancel through the backend); false when the channel declined (no bound
49
+ * conversation, adapter absent / text unsupported, or a question already
50
+ * pending there) and the backend must delegate the ask to the next
51
+ * answerer.
52
+ */
53
+ questionRequested(request: QuestionInteractionRequest): Promise<boolean>;
54
+ /**
55
+ * The question settled WITHOUT the channel — the owning tool call aborted.
56
+ * Removes stale channel controls.
57
+ */
58
+ questionSettledExternally(key: string, state?: 'aborted' | 'externally-settled'): Promise<void>;
59
+ }
60
+ /** A channel-collected answer batch submitted to the Harness question domain. */
61
+ export interface QuestionInteractionResolution {
62
+ key: string;
63
+ sessionId: string;
64
+ answer: AskUserQuestionAnswer;
65
+ }
66
+ /** The channel could not / will not answer a question it had taken. */
67
+ export interface QuestionInteractionCancellation {
68
+ key: string;
69
+ /** Human-readable reason; also the code-carrying message headless. */
70
+ reason: string;
71
+ }
72
+ /** Which official transport a backend speaks. */
73
+ export type QuestionBackendKind = 'waterfall';
74
+ /**
75
+ * Transport-neutral question domain port consumed by the presenter.
76
+ * `QuestionInteraction*` naming keeps room for a future approval sibling
77
+ * without sharing this interface prematurely.
78
+ */
79
+ export interface QuestionInteractionBackend {
80
+ readonly kind: QuestionBackendKind;
81
+ /** Connect the presenter sink and begin consuming the question domain. */
82
+ start(sink: QuestionInteractionSink): void;
83
+ /** Tear the transport down and settle every still-open question. */
84
+ stop(): Promise<void>;
85
+ /** Submit a complete answer batch (one entry per question, in order). */
86
+ resolve(submission: QuestionInteractionResolution): Promise<void>;
87
+ /** Cancel an open question with a human-readable reason. */
88
+ cancel(cancellation: QuestionInteractionCancellation): Promise<void>;
89
+ }
90
+ /**
91
+ * Live service probes. The waterfall answerer registers on `ctx` and never
92
+ * calls the service, so `getUserQuestions()` is a DIAGNOSTIC probe: it only
93
+ * decides whether the startup miss is logged.
94
+ */
95
+ export interface QuestionBackendProbe {
96
+ /** The official `ctx.userQuestions` service, when the host spine provides it. */
97
+ getUserQuestions(): ChannelUserQuestionService | undefined;
98
+ /** Root Cordis context the waterfall listener registers on. */
99
+ ctx: Context;
100
+ }
101
+ /** Channel presentation dependencies shared by every backend mode. */
102
+ export interface QuestionInteractionDeps {
103
+ agentManager: AgentManager;
104
+ replyContexts: ReplyContextStore;
105
+ getAdapter(channelId: string): ChannelAdapter | undefined;
106
+ logger: ChannelLogger;
107
+ timeoutMs: number;
108
+ }
109
+ export interface QuestionInteractionOptions extends QuestionInteractionDeps, Omit<QuestionBackendProbe, 'ctx'> {
110
+ ctx: Context;
111
+ }
112
+ /**
113
+ * Backend selection: the waterfall answerer always exists, because it needs
114
+ * only the ROOT context — `ctx.userQuestions` dispatches the event, and this
115
+ * backend never calls the service. The probe is therefore DIAGNOSTIC ONLY.
116
+ *
117
+ * Treating a missing service as fatal (the pre-waterfall behavior) made a
118
+ * transient startup state permanent: profile rows are composed concurrently
119
+ * and `cordis.patch.yml` layers hot-reload, so a `userQuestions` service that
120
+ * mounts after the bridge used to leave channel question presentation
121
+ * disabled for the whole process — every channel-bound ask silently answered
122
+ * by the Web UI instead. A registered listener with no service is inert, so
123
+ * the answerer is composed unconditionally and the miss is only logged.
124
+ */
125
+ export declare function selectQuestionBackend(probe: Omit<QuestionBackendProbe, 'ctx'> & {
126
+ ctx: Context;
127
+ }, deps: Pick<QuestionInteractionDeps, 'logger'>): QuestionInteractionBackend;
128
+ /**
129
+ * Assemble the whole question interaction stack: probe the service (diagnostic
130
+ * only), build the waterfall backend, and wire the channel presenter on top.
131
+ */
132
+ export declare function createQuestionInteraction(options: QuestionInteractionOptions): ChannelQuestionPresenter;
133
+ //# sourceMappingURL=question-backend.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"question-backend.d.ts","sourceRoot":"","sources":["../../src/interactions/question-backend.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,37 @@
1
+ import { WaterfallQuestionBackend } from './question-waterfall-backend.js';
2
+ import { ChannelQuestionPresenter } from './question-presenter.js';
3
+ /**
4
+ * Backend selection: the waterfall answerer always exists, because it needs
5
+ * only the ROOT context — `ctx.userQuestions` dispatches the event, and this
6
+ * backend never calls the service. The probe is therefore DIAGNOSTIC ONLY.
7
+ *
8
+ * Treating a missing service as fatal (the pre-waterfall behavior) made a
9
+ * transient startup state permanent: profile rows are composed concurrently
10
+ * and `cordis.patch.yml` layers hot-reload, so a `userQuestions` service that
11
+ * mounts after the bridge used to leave channel question presentation
12
+ * disabled for the whole process — every channel-bound ask silently answered
13
+ * by the Web UI instead. A registered listener with no service is inert, so
14
+ * the answerer is composed unconditionally and the miss is only logged.
15
+ */
16
+ export function selectQuestionBackend(probe, deps) {
17
+ if (!probe.getUserQuestions()) {
18
+ deps.logger.warn('[channel-harness] the userQuestions service is not mounted yet; the channel question answerer is registered anyway and claims asks as soon as the service appears');
19
+ }
20
+ return new WaterfallQuestionBackend({ ctx: probe.ctx, logger: deps.logger });
21
+ }
22
+ /**
23
+ * Assemble the whole question interaction stack: probe the service (diagnostic
24
+ * only), build the waterfall backend, and wire the channel presenter on top.
25
+ */
26
+ export function createQuestionInteraction(options) {
27
+ const backend = selectQuestionBackend(options, options);
28
+ return new ChannelQuestionPresenter({
29
+ backend,
30
+ agentManager: options.agentManager,
31
+ replyContexts: options.replyContexts,
32
+ getAdapter: options.getAdapter,
33
+ logger: options.logger,
34
+ timeoutMs: options.timeoutMs,
35
+ });
36
+ }
37
+ //# sourceMappingURL=question-backend.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"question-backend.js","sourceRoot":"","sources":["../../src/interactions/question-backend.ts"],"names":[],"mappings":"AA8BA,OAAO,EAAE,wBAAwB,EAAmC,MAAM,iCAAiC,CAAC;AAC5G,OAAO,EAAE,wBAAwB,EAAE,MAAM,yBAAyB,CAAC;AAgGnE;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,qBAAqB,CACnC,KAA2D,EAC3D,IAA6C;IAE7C,IAAI,CAAC,KAAK,CAAC,gBAAgB,EAAE,EAAE,CAAC;QAC9B,IAAI,CAAC,MAAM,CAAC,IAAI,CACd,mKAAmK,CACpK,CAAC;IACJ,CAAC;IACD,OAAO,IAAI,wBAAwB,CAAC,EAAE,GAAG,EAAE,KAAK,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC;AAC/E,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,yBAAyB,CACvC,OAAmC;IAEnC,MAAM,OAAO,GAAG,qBAAqB,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;IACxD,OAAO,IAAI,wBAAwB,CAAC;QAClC,OAAO;QACP,YAAY,EAAE,OAAO,CAAC,YAAY;QAClC,aAAa,EAAE,OAAO,CAAC,aAAa;QACpC,UAAU,EAAE,OAAO,CAAC,UAAU;QAC9B,MAAM,EAAE,OAAO,CAAC,MAAM;QACtB,SAAS,EAAE,OAAO,CAAC,SAAS;KAC7B,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,68 @@
1
+ import type { ChannelAdapter, ChannelEvent, ChannelLogger } from '@krischoichoi/channel-core';
2
+ import type { AgentManager } from '../agent-manager.js';
3
+ import type { ReplyContextStore } from '../reply-context-store.js';
4
+ import type { QuestionInteractionBackend, QuestionInteractionRequest, QuestionInteractionSink } from './question-backend.js';
5
+ export interface ChannelQuestionPresenterOptions {
6
+ backend: QuestionInteractionBackend;
7
+ agentManager: AgentManager;
8
+ replyContexts: ReplyContextStore;
9
+ getAdapter(channelId: string): ChannelAdapter | undefined;
10
+ logger: ChannelLogger;
11
+ timeoutMs: number;
12
+ }
13
+ /**
14
+ * Presents Harness-origin questions (the official `user-questions/request`
15
+ * waterfall) through generic channel actions.
16
+ */
17
+ export declare class ChannelQuestionPresenter implements QuestionInteractionSink {
18
+ private readonly options;
19
+ private readonly state;
20
+ constructor(options: ChannelQuestionPresenterOptions);
21
+ /** Connect the sink and open the backend transport. */
22
+ start(): void;
23
+ /** Cancel every open question, then tear the backend transport down. */
24
+ stop(): Promise<void>;
25
+ /**
26
+ * Present one question batch on the channel conversation bound to the
27
+ * asking session. Returns false when the channel cannot take ownership
28
+ * (no active reply context, no binding, adapter absent / text unsupported,
29
+ * or another question already pending on that conversation) — the backend
30
+ * decides what a decline means per transport.
31
+ *
32
+ * `interactiveActions` decides only presentation quality, never admission:
33
+ * any `text: true` adapter can answer via numbered plain text; a
34
+ * `interactiveActions: true` adapter upgrades to native buttons.
35
+ */
36
+ questionRequested(request: QuestionInteractionRequest): Promise<boolean>;
37
+ /** Another client answered, or the owning tool call aborted: drop controls. */
38
+ questionSettledExternally(key: string, state?: 'aborted' | 'externally-settled'): Promise<void>;
39
+ /** Consume an already-authorized channel answer before it reaches the Agent inbox. */
40
+ handleChannelEvent(event: ChannelEvent): Promise<boolean>;
41
+ private present;
42
+ private handleInteraction;
43
+ /**
44
+ * Route one authorized text message into the question flow. DM answers parse
45
+ * directly; group/thread answers must correlate via the platform `replyTo`
46
+ * mapping or the per-question `replyToken` (stripped before parsing).
47
+ * Returns true when the message was consumed by a pending question (never
48
+ * falls through to Agent routing); false otherwise.
49
+ */
50
+ private handleMessage;
51
+ /**
52
+ * Resolve the answerable text of an inbound message against a pending
53
+ * question. Returns:
54
+ * - the message body for DMs (parse directly), or
55
+ * - the token-stripped body when the platform `replyTo` maps to the prompt,
56
+ * or
57
+ * - the token-stripped body when the reply carries `pending.replyToken`
58
+ * anywhere (`Q-XXXX 2`, `Q-XXXX: 2`, `@bot Q-XXXX 2`), or
59
+ * - `undefined` when nothing correlates (leave for ordinary routing).
60
+ */
61
+ private correlateMessageBody;
62
+ private advance;
63
+ private submit;
64
+ private cancel;
65
+ private removeButtons;
66
+ private cleanup;
67
+ }
68
+ //# sourceMappingURL=question-presenter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"question-presenter.d.ts","sourceRoot":"","sources":["../../src/interactions/question-presenter.ts"],"names":[],"mappings":"AAuCA,OAAO,KAAK,EACV,cAAc,EACd,YAAY,EACZ,aAAa,EAKd,MAAM,4BAA4B,CAAC;AACpC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AACnE,OAAO,KAAK,EACV,0BAA0B,EAC1B,0BAA0B,EAC1B,uBAAuB,EACxB,MAAM,uBAAuB,CAAC;AAU/B,MAAM,WAAW,+BAA+B;IAC9C,OAAO,EAAE,0BAA0B,CAAC;IACpC,YAAY,EAAE,YAAY,CAAC;IAC3B,aAAa,EAAE,iBAAiB,CAAC;IACjC,UAAU,CAAC,SAAS,EAAE,MAAM,GAAG,cAAc,GAAG,SAAS,CAAC;IAC1D,MAAM,EAAE,aAAa,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;CACnB;AAkBD;;;GAGG;AACH,qBAAa,wBAAyB,YAAW,uBAAuB;IAG1D,OAAO,CAAC,QAAQ,CAAC,OAAO;IAFpC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAA4B;gBAErB,OAAO,EAAE,+BAA+B;IAErE,uDAAuD;IACvD,KAAK,IAAI,IAAI;IAIb,wEAAwE;IAClE,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAW3B;;;;;;;;;;OAUG;IACG,iBAAiB,CAAC,OAAO,EAAE,0BAA0B,GAAG,OAAO,CAAC,OAAO,CAAC;IAuE9E,+EAA+E;IACzE,yBAAyB,CAC7B,GAAG,EAAE,MAAM,EACX,KAAK,GAAE,SAAS,GAAG,oBAA2C,GAC7D,OAAO,CAAC,IAAI,CAAC;IAahB,sFAAsF;IAChF,kBAAkB,CAAC,KAAK,EAAE,YAAY,GAAG,OAAO,CAAC,OAAO,CAAC;YAMjD,OAAO;YAmDP,iBAAiB;IA+C/B;;;;;;OAMG;YACW,aAAa;IAwD3B;;;;;;;;;OASG;IACH,OAAO,CAAC,oBAAoB;YA0Bd,OAAO;YAiBP,MAAM;YAqBN,MAAM;YAeN,aAAa;YAUb,OAAO;CAItB"}