@agimon-ai/doompi-web-contracts 0.0.1-alpha.3 → 0.0.1-alpha.30

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 (69) hide show
  1. package/dist/index.cjs +1 -1
  2. package/dist/index.d.cts +7 -3
  3. package/dist/index.d.mts +7 -3
  4. package/dist/index.mjs +1 -1
  5. package/dist/services/define.d.cts +3 -4
  6. package/dist/services/define.d.cts.map +1 -1
  7. package/dist/services/define.d.mts +3 -4
  8. package/dist/services/define.d.mts.map +1 -1
  9. package/dist/services/globalStore.cjs +2 -0
  10. package/dist/services/globalStore.cjs.map +1 -0
  11. package/dist/services/globalStore.d.cts +6 -0
  12. package/dist/services/globalStore.d.cts.map +1 -0
  13. package/dist/services/globalStore.d.mts +6 -0
  14. package/dist/services/globalStore.d.mts.map +1 -0
  15. package/dist/services/globalStore.mjs +2 -0
  16. package/dist/services/globalStore.mjs.map +1 -0
  17. package/dist/services/sessionRegistry.cjs +2 -0
  18. package/dist/services/sessionRegistry.cjs.map +1 -0
  19. package/dist/services/sessionRegistry.d.cts +42 -0
  20. package/dist/services/sessionRegistry.d.cts.map +1 -0
  21. package/dist/services/sessionRegistry.d.mts +42 -0
  22. package/dist/services/sessionRegistry.d.mts.map +1 -0
  23. package/dist/services/sessionRegistry.mjs +2 -0
  24. package/dist/services/sessionRegistry.mjs.map +1 -0
  25. package/dist/services/sessionStore.d.cts +1 -2
  26. package/dist/services/sessionStore.d.cts.map +1 -1
  27. package/dist/services/sessionStore.d.mts +1 -2
  28. package/dist/services/sessionStore.d.mts.map +1 -1
  29. package/dist/services/testing/channels.cjs +1 -1
  30. package/dist/services/testing/channels.cjs.map +1 -1
  31. package/dist/services/testing/channels.d.cts +5 -6
  32. package/dist/services/testing/channels.d.cts.map +1 -1
  33. package/dist/services/testing/channels.d.mts +5 -6
  34. package/dist/services/testing/channels.d.mts.map +1 -1
  35. package/dist/services/testing/channels.mjs +1 -1
  36. package/dist/services/testing/channels.mjs.map +1 -1
  37. package/dist/services/testing/render.d.cts +2 -3
  38. package/dist/services/testing/render.d.cts.map +1 -1
  39. package/dist/services/testing/render.d.mts +2 -3
  40. package/dist/services/testing/render.d.mts.map +1 -1
  41. package/dist/services/testing/slotProps.cjs +1 -1
  42. package/dist/services/testing/slotProps.cjs.map +1 -1
  43. package/dist/services/testing/slotProps.d.cts +22 -12
  44. package/dist/services/testing/slotProps.d.cts.map +1 -1
  45. package/dist/services/testing/slotProps.d.mts +22 -12
  46. package/dist/services/testing/slotProps.d.mts.map +1 -1
  47. package/dist/services/testing/slotProps.mjs +1 -1
  48. package/dist/services/testing/slotProps.mjs.map +1 -1
  49. package/dist/services/toolResult.d.cts +2 -3
  50. package/dist/services/toolResult.d.cts.map +1 -1
  51. package/dist/services/toolResult.d.mts +2 -3
  52. package/dist/services/toolResult.d.mts.map +1 -1
  53. package/dist/types/modelContext.d.cts +43 -0
  54. package/dist/types/modelContext.d.cts.map +1 -0
  55. package/dist/types/modelContext.d.mts +43 -0
  56. package/dist/types/modelContext.d.mts.map +1 -0
  57. package/dist/types/sessionRegistry.d.cts +59 -0
  58. package/dist/types/sessionRegistry.d.cts.map +1 -0
  59. package/dist/types/sessionRegistry.d.mts +59 -0
  60. package/dist/types/sessionRegistry.d.mts.map +1 -0
  61. package/dist/types/webHub.d.cts +46 -6
  62. package/dist/types/webHub.d.cts.map +1 -1
  63. package/dist/types/webHub.d.mts +46 -6
  64. package/dist/types/webHub.d.mts.map +1 -1
  65. package/dist/types/webPlugin.d.cts +364 -47
  66. package/dist/types/webPlugin.d.cts.map +1 -1
  67. package/dist/types/webPlugin.d.mts +364 -47
  68. package/dist/types/webPlugin.d.mts.map +1 -1
  69. package/package.json +7 -7
package/dist/index.cjs CHANGED
@@ -1 +1 @@
1
- Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./services/define.cjs"),t=require("./services/sessionStore.cjs"),n=require("./services/toolResult.cjs");exports.defineSessionChannel=e.defineSessionChannel,exports.defineSessionStore=t.defineSessionStore,exports.defineSlot=e.defineSlot,exports.defineWebPlugin=e.defineWebPlugin,exports.toolResultText=n.toolResultText,exports.toolResultTextLines=n.toolResultTextLines;
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./services/define.cjs"),t=require("./services/globalStore.cjs"),n=require("./services/sessionStore.cjs"),r=require("./services/sessionRegistry.cjs"),i=require("./services/toolResult.cjs");exports.HUB_ADVERTISEMENT_VERSION=r.HUB_ADVERTISEMENT_VERSION,exports.REGISTRY_DIR_ENV=r.REGISTRY_DIR_ENV,exports.SESSION_LINEAGE_RECORD_VERSION=r.SESSION_LINEAGE_RECORD_VERSION,exports.defineGlobalStore=t.defineGlobalStore,exports.defineSessionChannel=e.defineSessionChannel,exports.defineSessionStore=n.defineSessionStore,exports.defineSlot=e.defineSlot,exports.defineWebPlugin=e.defineWebPlugin,exports.hubAdvertisementPath=r.hubAdvertisementPath,exports.parseHubAdvertisement=r.parseHubAdvertisement,exports.parseSessionLineage=r.parseSessionLineage,exports.resolveRegistryDir=r.resolveRegistryDir,exports.sessionLineagePath=r.sessionLineagePath,exports.toolResultText=i.toolResultText,exports.toolResultTextLines=i.toolResultTextLines;
package/dist/index.d.cts CHANGED
@@ -1,6 +1,10 @@
1
- import { ActivityGroupContribution, LeaderBindingContribution, LeaderKeyContribution, MinorModeContribution, PaletteCommandContext, PaletteCommandContribution, SelectionAxisContribution, SessionChannelContribution, SessionFrameSender, SessionRecords, SessionStore, SessionStoreChannel, SettingsFieldContribution, SettingsFieldOption, SettingsSectionContribution, SlotDataFill, SlotDeclaration, SlotFillContribution, SurfaceContribution, TabContribution, ToolMessageRenderProps, ToolPromptContribution, ToolPromptDialog, ToolPromptRenderProps, ToolRendererContribution, ToolResultView, TransientTab, WebPluginDefinition, WebPluginRuntime, WebPluginSlotProps } from "./types/webPlugin.cjs";
1
+ import { ModelContext, ModelContextAbortSignal, ModelContextBinding, ModelContextExecutionOptions, ModelContextRegistrationOptions, ModelContextTool, ModelContextToolChangeEvent, ModelContextToolChangeListener, ModelContextToolDescriptor } from "./types/modelContext.cjs";
2
+ import { ActivityGroupContribution, CaptureStatusEvent, ComposerCapture, ComposerSubmission, ContextAction, ContextActionContribution, ContextActionRunContext, DockFaceContribution, FileLinkSource, GlobalStore, LeaderBindingContribution, LeaderKeyContribution, MinorModeContribution, PaletteCommandContext, PaletteCommandContribution, RepositorySettingsPanelContribution, RepositorySettingsPanelProps, RepositorySettingsRepository, SelectionAxisContribution, SessionChannelContribution, SessionFrameSender, SessionRecords, SessionStore, SessionStoreChannel, SettingsFieldContribution, SettingsFieldOption, SettingsPanelContribution, SettingsPanelProps, SettingsSectionContribution, SlotDataFill, SlotDeclaration, SlotFillContribution, SurfaceContribution, TabContribution, ThreadViewOptions, ToolMessageRenderProps, ToolPromptContribution, ToolPromptDialog, ToolPromptRenderProps, ToolRendererContribution, ToolResultView, TransientTab, UserMessageActionContribution, UserMessageActionRunContext, WebPluginContextInventoryItem, WebPluginContextItem, WebPluginDefinition, WebPluginRuntime, WebPluginSlotProps } from "./types/webPlugin.cjs";
2
3
  import { defineSessionChannel, defineSlot, defineWebPlugin } from "./services/define.cjs";
4
+ import { defineGlobalStore } from "./services/globalStore.cjs";
3
5
  import { defineSessionStore } from "./services/sessionStore.cjs";
6
+ import { HubAdvertisement, RegistryDirInput, SessionLineageRecord } from "./types/sessionRegistry.cjs";
7
+ import { HUB_ADVERTISEMENT_VERSION, REGISTRY_DIR_ENV, SESSION_LINEAGE_RECORD_VERSION, hubAdvertisementPath, parseHubAdvertisement, parseSessionLineage, resolveRegistryDir, sessionLineagePath } from "./services/sessionRegistry.cjs";
4
8
  import { toolResultText, toolResultTextLines } from "./services/toolResult.cjs";
5
- import { ChannelFrame, HubChannelHost, HubChannelSource, HubSessionScope, WebHubChannel } from "./types/webHub.cjs";
6
- export { type ActivityGroupContribution, type ChannelFrame, type HubChannelHost, type HubChannelSource, type HubSessionScope, type LeaderBindingContribution, type LeaderKeyContribution, type MinorModeContribution, type PaletteCommandContext, type PaletteCommandContribution, type SelectionAxisContribution, type SessionChannelContribution, type SessionFrameSender, type SessionRecords, type SessionStore, type SessionStoreChannel, type SettingsFieldContribution, type SettingsFieldOption, type SettingsSectionContribution, type SlotDataFill, type SlotDeclaration, type SlotFillContribution, type SurfaceContribution, type TabContribution, type ToolMessageRenderProps, type ToolPromptContribution, type ToolPromptDialog, type ToolPromptRenderProps, type ToolRendererContribution, type ToolResultView, type TransientTab, type WebHubChannel, type WebPluginDefinition, type WebPluginRuntime, type WebPluginSlotProps, defineSessionChannel, defineSessionStore, defineSlot, defineWebPlugin, toolResultText, toolResultTextLines };
9
+ import { ChannelFrame, ComputerUseHostBinding, ComputerUseHostOperation, ComputerUseHostRequest, HubChannelConnection, HubChannelHost, HubChannelLifecycle, HubChannelSource, HubSessionApiRequest, HubSessionScope, WebHubChannel } from "./types/webHub.cjs";
10
+ export { type ActivityGroupContribution, type CaptureStatusEvent, type ChannelFrame, type ComposerCapture, type ComposerSubmission, type ComputerUseHostBinding, type ComputerUseHostOperation, type ComputerUseHostRequest, type ContextAction, type ContextActionContribution, type ContextActionRunContext, type DockFaceContribution, type FileLinkSource, type GlobalStore, HUB_ADVERTISEMENT_VERSION, type HubAdvertisement, type HubChannelConnection, type HubChannelHost, type HubChannelLifecycle, type HubChannelSource, type HubSessionApiRequest, type HubSessionScope, type LeaderBindingContribution, type LeaderKeyContribution, type MinorModeContribution, type ModelContext, type ModelContextAbortSignal, type ModelContextBinding, type ModelContextExecutionOptions, type ModelContextRegistrationOptions, type ModelContextTool, type ModelContextToolChangeEvent, type ModelContextToolChangeListener, type ModelContextToolDescriptor, type PaletteCommandContext, type PaletteCommandContribution, REGISTRY_DIR_ENV, type RegistryDirInput, type RepositorySettingsPanelContribution, type RepositorySettingsPanelProps, type RepositorySettingsRepository, SESSION_LINEAGE_RECORD_VERSION, type SelectionAxisContribution, type SessionChannelContribution, type SessionFrameSender, type SessionLineageRecord, type SessionRecords, type SessionStore, type SessionStoreChannel, type SettingsFieldContribution, type SettingsFieldOption, type SettingsPanelContribution, type SettingsPanelProps, type SettingsSectionContribution, type SlotDataFill, type SlotDeclaration, type SlotFillContribution, type SurfaceContribution, type TabContribution, type ThreadViewOptions, type ToolMessageRenderProps, type ToolPromptContribution, type ToolPromptDialog, type ToolPromptRenderProps, type ToolRendererContribution, type ToolResultView, type TransientTab, type UserMessageActionContribution, type UserMessageActionRunContext, type WebHubChannel, type WebPluginContextInventoryItem, type WebPluginContextItem, type WebPluginDefinition, type WebPluginRuntime, type WebPluginSlotProps, defineGlobalStore, defineSessionChannel, defineSessionStore, defineSlot, defineWebPlugin, hubAdvertisementPath, parseHubAdvertisement, parseSessionLineage, resolveRegistryDir, sessionLineagePath, toolResultText, toolResultTextLines };
package/dist/index.d.mts CHANGED
@@ -1,6 +1,10 @@
1
- import { ActivityGroupContribution, LeaderBindingContribution, LeaderKeyContribution, MinorModeContribution, PaletteCommandContext, PaletteCommandContribution, SelectionAxisContribution, SessionChannelContribution, SessionFrameSender, SessionRecords, SessionStore, SessionStoreChannel, SettingsFieldContribution, SettingsFieldOption, SettingsSectionContribution, SlotDataFill, SlotDeclaration, SlotFillContribution, SurfaceContribution, TabContribution, ToolMessageRenderProps, ToolPromptContribution, ToolPromptDialog, ToolPromptRenderProps, ToolRendererContribution, ToolResultView, TransientTab, WebPluginDefinition, WebPluginRuntime, WebPluginSlotProps } from "./types/webPlugin.mjs";
1
+ import { ModelContext, ModelContextAbortSignal, ModelContextBinding, ModelContextExecutionOptions, ModelContextRegistrationOptions, ModelContextTool, ModelContextToolChangeEvent, ModelContextToolChangeListener, ModelContextToolDescriptor } from "./types/modelContext.mjs";
2
+ import { ActivityGroupContribution, CaptureStatusEvent, ComposerCapture, ComposerSubmission, ContextAction, ContextActionContribution, ContextActionRunContext, DockFaceContribution, FileLinkSource, GlobalStore, LeaderBindingContribution, LeaderKeyContribution, MinorModeContribution, PaletteCommandContext, PaletteCommandContribution, RepositorySettingsPanelContribution, RepositorySettingsPanelProps, RepositorySettingsRepository, SelectionAxisContribution, SessionChannelContribution, SessionFrameSender, SessionRecords, SessionStore, SessionStoreChannel, SettingsFieldContribution, SettingsFieldOption, SettingsPanelContribution, SettingsPanelProps, SettingsSectionContribution, SlotDataFill, SlotDeclaration, SlotFillContribution, SurfaceContribution, TabContribution, ThreadViewOptions, ToolMessageRenderProps, ToolPromptContribution, ToolPromptDialog, ToolPromptRenderProps, ToolRendererContribution, ToolResultView, TransientTab, UserMessageActionContribution, UserMessageActionRunContext, WebPluginContextInventoryItem, WebPluginContextItem, WebPluginDefinition, WebPluginRuntime, WebPluginSlotProps } from "./types/webPlugin.mjs";
2
3
  import { defineSessionChannel, defineSlot, defineWebPlugin } from "./services/define.mjs";
4
+ import { defineGlobalStore } from "./services/globalStore.mjs";
3
5
  import { defineSessionStore } from "./services/sessionStore.mjs";
6
+ import { HubAdvertisement, RegistryDirInput, SessionLineageRecord } from "./types/sessionRegistry.mjs";
7
+ import { HUB_ADVERTISEMENT_VERSION, REGISTRY_DIR_ENV, SESSION_LINEAGE_RECORD_VERSION, hubAdvertisementPath, parseHubAdvertisement, parseSessionLineage, resolveRegistryDir, sessionLineagePath } from "./services/sessionRegistry.mjs";
4
8
  import { toolResultText, toolResultTextLines } from "./services/toolResult.mjs";
5
- import { ChannelFrame, HubChannelHost, HubChannelSource, HubSessionScope, WebHubChannel } from "./types/webHub.mjs";
6
- export { type ActivityGroupContribution, type ChannelFrame, type HubChannelHost, type HubChannelSource, type HubSessionScope, type LeaderBindingContribution, type LeaderKeyContribution, type MinorModeContribution, type PaletteCommandContext, type PaletteCommandContribution, type SelectionAxisContribution, type SessionChannelContribution, type SessionFrameSender, type SessionRecords, type SessionStore, type SessionStoreChannel, type SettingsFieldContribution, type SettingsFieldOption, type SettingsSectionContribution, type SlotDataFill, type SlotDeclaration, type SlotFillContribution, type SurfaceContribution, type TabContribution, type ToolMessageRenderProps, type ToolPromptContribution, type ToolPromptDialog, type ToolPromptRenderProps, type ToolRendererContribution, type ToolResultView, type TransientTab, type WebHubChannel, type WebPluginDefinition, type WebPluginRuntime, type WebPluginSlotProps, defineSessionChannel, defineSessionStore, defineSlot, defineWebPlugin, toolResultText, toolResultTextLines };
9
+ import { ChannelFrame, ComputerUseHostBinding, ComputerUseHostOperation, ComputerUseHostRequest, HubChannelConnection, HubChannelHost, HubChannelLifecycle, HubChannelSource, HubSessionApiRequest, HubSessionScope, WebHubChannel } from "./types/webHub.mjs";
10
+ export { type ActivityGroupContribution, type CaptureStatusEvent, type ChannelFrame, type ComposerCapture, type ComposerSubmission, type ComputerUseHostBinding, type ComputerUseHostOperation, type ComputerUseHostRequest, type ContextAction, type ContextActionContribution, type ContextActionRunContext, type DockFaceContribution, type FileLinkSource, type GlobalStore, HUB_ADVERTISEMENT_VERSION, type HubAdvertisement, type HubChannelConnection, type HubChannelHost, type HubChannelLifecycle, type HubChannelSource, type HubSessionApiRequest, type HubSessionScope, type LeaderBindingContribution, type LeaderKeyContribution, type MinorModeContribution, type ModelContext, type ModelContextAbortSignal, type ModelContextBinding, type ModelContextExecutionOptions, type ModelContextRegistrationOptions, type ModelContextTool, type ModelContextToolChangeEvent, type ModelContextToolChangeListener, type ModelContextToolDescriptor, type PaletteCommandContext, type PaletteCommandContribution, REGISTRY_DIR_ENV, type RegistryDirInput, type RepositorySettingsPanelContribution, type RepositorySettingsPanelProps, type RepositorySettingsRepository, SESSION_LINEAGE_RECORD_VERSION, type SelectionAxisContribution, type SessionChannelContribution, type SessionFrameSender, type SessionLineageRecord, type SessionRecords, type SessionStore, type SessionStoreChannel, type SettingsFieldContribution, type SettingsFieldOption, type SettingsPanelContribution, type SettingsPanelProps, type SettingsSectionContribution, type SlotDataFill, type SlotDeclaration, type SlotFillContribution, type SurfaceContribution, type TabContribution, type ThreadViewOptions, type ToolMessageRenderProps, type ToolPromptContribution, type ToolPromptDialog, type ToolPromptRenderProps, type ToolRendererContribution, type ToolResultView, type TransientTab, type UserMessageActionContribution, type UserMessageActionRunContext, type WebHubChannel, type WebPluginContextInventoryItem, type WebPluginContextItem, type WebPluginDefinition, type WebPluginRuntime, type WebPluginSlotProps, defineGlobalStore, defineSessionChannel, defineSessionStore, defineSlot, defineWebPlugin, hubAdvertisementPath, parseHubAdvertisement, parseSessionLineage, resolveRegistryDir, sessionLineagePath, toolResultText, toolResultTextLines };
package/dist/index.mjs CHANGED
@@ -1 +1 @@
1
- import{defineSessionChannel as e,defineSlot as t,defineWebPlugin as n}from"./services/define.mjs";import{defineSessionStore as r}from"./services/sessionStore.mjs";import{toolResultText as i,toolResultTextLines as a}from"./services/toolResult.mjs";export{e as defineSessionChannel,r as defineSessionStore,t as defineSlot,n as defineWebPlugin,i as toolResultText,a as toolResultTextLines};
1
+ import{defineSessionChannel as e,defineSlot as t,defineWebPlugin as n}from"./services/define.mjs";import{defineGlobalStore as r}from"./services/globalStore.mjs";import{defineSessionStore as i}from"./services/sessionStore.mjs";import{HUB_ADVERTISEMENT_VERSION as a,REGISTRY_DIR_ENV as o,SESSION_LINEAGE_RECORD_VERSION as s,hubAdvertisementPath as c,parseHubAdvertisement as l,parseSessionLineage as u,resolveRegistryDir as d,sessionLineagePath as f}from"./services/sessionRegistry.mjs";import{toolResultText as p,toolResultTextLines as m}from"./services/toolResult.mjs";export{a as HUB_ADVERTISEMENT_VERSION,o as REGISTRY_DIR_ENV,s as SESSION_LINEAGE_RECORD_VERSION,r as defineGlobalStore,e as defineSessionChannel,i as defineSessionStore,t as defineSlot,n as defineWebPlugin,c as hubAdvertisementPath,l as parseHubAdvertisement,u as parseSessionLineage,d as resolveRegistryDir,f as sessionLineagePath,p as toolResultText,m as toolResultTextLines};
@@ -1,20 +1,19 @@
1
1
  import { SessionChannelContribution, SlotDeclaration, WebPluginDefinition } from "../types/webPlugin.cjs";
2
2
  //#region src/services/define.d.ts
3
3
  /** Identity helper so plugin modules get checked literals without a type annotation. */
4
- declare function defineWebPlugin(plugin: WebPluginDefinition): WebPluginDefinition;
4
+ export declare function defineWebPlugin(plugin: WebPluginDefinition): WebPluginDefinition;
5
5
  /**
6
6
  * The one audited erasure from Payload to unknown. Channels are stored
7
7
  * untyped in the host registry; the payload type lives entirely inside the
8
8
  * plugin, behind its own parse gate.
9
9
  */
10
- declare function defineSessionChannel<Payload>(channel: SessionChannelContribution<Payload>): SessionChannelContribution;
10
+ export declare function defineSessionChannel<Payload>(channel: SessionChannelContribution<Payload>): SessionChannelContribution;
11
11
  /**
12
12
  * Identity helper for a typed slot handle: the owner keeps the
13
13
  * SlotDeclaration<Data> to read its fills back through slotData, and the
14
14
  * plugin's `slots` array holds it erased. No cast is needed because Data only
15
15
  * appears in the parse gate's return position.
16
16
  */
17
- declare function defineSlot<Data>(slot: SlotDeclaration<Data>): SlotDeclaration<Data>;
17
+ export declare function defineSlot<Data>(slot: SlotDeclaration<Data>): SlotDeclaration<Data>;
18
18
  //#endregion
19
- export { defineSessionChannel, defineSlot, defineWebPlugin };
20
19
  //# sourceMappingURL=define.d.cts.map
@@ -1 +1 @@
1
- {"version":3,"file":"define.d.cts","names":[],"sources":["../../src/services/define.ts"],"mappings":";;;iBAGgB,gBAAgB,QAAQ,sBAAsB;;;;;;iBAS9C,qBAAqB,SACnC,SAAS,2BAA2B,WACnC;;;;;;;iBAUa,WAAW,MAAM,MAAM,gBAAgB,QAAQ,gBAAgB"}
1
+ {"version":3,"file":"define.d.cts","names":[],"sources":["../../src/services/define.ts"],"mappings":";;;wBAGgB,gBAAgB,QAAQ,sBAAsB;;;;;;wBAS9C,qBAAqB,SACnC,SAAS,2BAA2B,WACnC;;;;;;;wBAUa,WAAW,MAAM,MAAM,gBAAgB,QAAQ,gBAAgB"}
@@ -1,20 +1,19 @@
1
1
  import { SessionChannelContribution, SlotDeclaration, WebPluginDefinition } from "../types/webPlugin.mjs";
2
2
  //#region src/services/define.d.ts
3
3
  /** Identity helper so plugin modules get checked literals without a type annotation. */
4
- declare function defineWebPlugin(plugin: WebPluginDefinition): WebPluginDefinition;
4
+ export declare function defineWebPlugin(plugin: WebPluginDefinition): WebPluginDefinition;
5
5
  /**
6
6
  * The one audited erasure from Payload to unknown. Channels are stored
7
7
  * untyped in the host registry; the payload type lives entirely inside the
8
8
  * plugin, behind its own parse gate.
9
9
  */
10
- declare function defineSessionChannel<Payload>(channel: SessionChannelContribution<Payload>): SessionChannelContribution;
10
+ export declare function defineSessionChannel<Payload>(channel: SessionChannelContribution<Payload>): SessionChannelContribution;
11
11
  /**
12
12
  * Identity helper for a typed slot handle: the owner keeps the
13
13
  * SlotDeclaration<Data> to read its fills back through slotData, and the
14
14
  * plugin's `slots` array holds it erased. No cast is needed because Data only
15
15
  * appears in the parse gate's return position.
16
16
  */
17
- declare function defineSlot<Data>(slot: SlotDeclaration<Data>): SlotDeclaration<Data>;
17
+ export declare function defineSlot<Data>(slot: SlotDeclaration<Data>): SlotDeclaration<Data>;
18
18
  //#endregion
19
- export { defineSessionChannel, defineSlot, defineWebPlugin };
20
19
  //# sourceMappingURL=define.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"define.d.mts","names":[],"sources":["../../src/services/define.ts"],"mappings":";;;iBAGgB,gBAAgB,QAAQ,sBAAsB;;;;;;iBAS9C,qBAAqB,SACnC,SAAS,2BAA2B,WACnC;;;;;;;iBAUa,WAAW,MAAM,MAAM,gBAAgB,QAAQ,gBAAgB"}
1
+ {"version":3,"file":"define.d.mts","names":[],"sources":["../../src/services/define.ts"],"mappings":";;;wBAGgB,gBAAgB,QAAQ,sBAAsB;;;;;;wBAS9C,qBAAqB,SACnC,SAAS,2BAA2B,WACnC;;;;;;;wBAUa,WAAW,MAAM,MAAM,gBAAgB,QAAQ,gBAAgB"}
@@ -0,0 +1,2 @@
1
+ let e=require("@tanstack/store");function t(t){let n=new e.Store(t);return{store:n,update:e=>{let t=n.state,r=e(t);r!==t&&n.setState(()=>r)},reset:()=>{n.setState(e=>e===t?e:t)}}}exports.defineGlobalStore=t;
2
+ //# sourceMappingURL=globalStore.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"globalStore.cjs","names":["Store"],"sources":["../../src/services/globalStore.ts"],"sourcesContent":["import { Store } from '@tanstack/store';\nimport type { GlobalStore } from '../types/webPlugin.ts';\n\n/** Page-wide plugin state shared by every contribution from the plugin. */\nexport function defineGlobalStore<T>(initial: T): GlobalStore<T> {\n const store = new Store<T>(initial);\n\n const update = (updater: (current: T) => T): void => {\n const current = store.state;\n const next = updater(current);\n if (next !== current) store.setState(() => next);\n };\n\n const reset = (): void => {\n store.setState((current) => (current === initial ? current : initial));\n };\n\n return { store, update, reset };\n}\n"],"mappings":"iCAIA,SAAgB,EAAqB,EAA4B,CAC/D,IAAM,EAAQ,IAAIA,EAAAA,MAAS,CAAO,EAYlC,MAAO,CAAE,QAAO,OAVA,GAAqC,CACnD,IAAM,EAAU,EAAM,MAChB,EAAO,EAAQ,CAAO,EACxB,IAAS,GAAS,EAAM,aAAe,CAAI,CACjD,EAMwB,UAJE,CACxB,EAAM,SAAU,GAAa,IAAY,EAAU,EAAU,CAAQ,CACvE,CAE8B,CAChC"}
@@ -0,0 +1,6 @@
1
+ import { GlobalStore } from "../types/webPlugin.cjs";
2
+ //#region src/services/globalStore.d.ts
3
+ /** Page-wide plugin state shared by every contribution from the plugin. */
4
+ export declare function defineGlobalStore<T>(initial: T): GlobalStore<T>;
5
+ //#endregion
6
+ //# sourceMappingURL=globalStore.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"globalStore.d.cts","names":[],"sources":["../../src/services/globalStore.ts"],"mappings":";;;wBAIgB,kBAAkB,GAAG,SAAS,IAAI,YAAY"}
@@ -0,0 +1,6 @@
1
+ import { GlobalStore } from "../types/webPlugin.mjs";
2
+ //#region src/services/globalStore.d.ts
3
+ /** Page-wide plugin state shared by every contribution from the plugin. */
4
+ export declare function defineGlobalStore<T>(initial: T): GlobalStore<T>;
5
+ //#endregion
6
+ //# sourceMappingURL=globalStore.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"globalStore.d.mts","names":[],"sources":["../../src/services/globalStore.ts"],"mappings":";;;wBAIgB,kBAAkB,GAAG,SAAS,IAAI,YAAY"}
@@ -0,0 +1,2 @@
1
+ import{Store as e}from"@tanstack/store";function t(t){let n=new e(t);return{store:n,update:e=>{let t=n.state,r=e(t);r!==t&&n.setState(()=>r)},reset:()=>{n.setState(e=>e===t?e:t)}}}export{t as defineGlobalStore};
2
+ //# sourceMappingURL=globalStore.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"globalStore.mjs","names":[],"sources":["../../src/services/globalStore.ts"],"sourcesContent":["import { Store } from '@tanstack/store';\nimport type { GlobalStore } from '../types/webPlugin.ts';\n\n/** Page-wide plugin state shared by every contribution from the plugin. */\nexport function defineGlobalStore<T>(initial: T): GlobalStore<T> {\n const store = new Store<T>(initial);\n\n const update = (updater: (current: T) => T): void => {\n const current = store.state;\n const next = updater(current);\n if (next !== current) store.setState(() => next);\n };\n\n const reset = (): void => {\n store.setState((current) => (current === initial ? current : initial));\n };\n\n return { store, update, reset };\n}\n"],"mappings":"wCAIA,SAAgB,EAAqB,EAA4B,CAC/D,IAAM,EAAQ,IAAI,EAAS,CAAO,EAYlC,MAAO,CAAE,QAAO,OAVA,GAAqC,CACnD,IAAM,EAAU,EAAM,MAChB,EAAO,EAAQ,CAAO,EACxB,IAAS,GAAS,EAAM,aAAe,CAAI,CACjD,EAMwB,UAJE,CACxB,EAAM,SAAU,GAAa,IAAY,EAAU,EAAU,CAAQ,CACvE,CAE8B,CAChC"}
@@ -0,0 +1,2 @@
1
+ function e(e){return e.flagValue?e.flagValue:e.envValue?e.envValue:`${e.homeDir}/.doompi/run`}function t(e,t){return`${e}/sessions/${t}.lineage.json`}function n(e){let t;try{t=JSON.parse(e)}catch{return}if(typeof t!=`object`||!t)return;let n=t;if(n.version!==1||typeof n.parentSessionId!=`string`||n.parentSessionId===``)return;let r=typeof n.provenance==`string`?n.provenance:``;return{version:1,parentSessionId:n.parentSessionId,provenance:r}}function r(e){return`${e}/hub.json`}function i(e){let t;try{t=JSON.parse(e)}catch{return}if(typeof t!=`object`||!t)return;let n=t;if(n.version===1&&typeof n.url==`string`&&a(n.url)&&!(typeof n.pid!=`number`||!Number.isInteger(n.pid)||n.pid<=0))return{version:1,url:n.url,pid:n.pid}}function a(e){let t;try{t=new URL(e)}catch{return!1}return t.protocol===`http:`?t.hostname===`127.0.0.1`||t.hostname===`localhost`||t.hostname===`[::1]`||t.hostname===`::1`:!1}exports.HUB_ADVERTISEMENT_VERSION=1,exports.REGISTRY_DIR_ENV=`DOOMPI_RUNTIME_DIR`,exports.SESSION_LINEAGE_RECORD_VERSION=1,exports.hubAdvertisementPath=r,exports.parseHubAdvertisement=i,exports.parseSessionLineage=n,exports.resolveRegistryDir=e,exports.sessionLineagePath=t;
2
+ //# sourceMappingURL=sessionRegistry.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sessionRegistry.cjs","names":[],"sources":["../../src/services/sessionRegistry.ts"],"sourcesContent":["import type { HubAdvertisement, RegistryDirInput, SessionLineageRecord } from '../types/sessionRegistry.ts';\n\n/** Overrides the runtime directory the hub and its session servers share. */\nexport const REGISTRY_DIR_ENV = 'DOOMPI_RUNTIME_DIR';\n\n/** The version a lineage sidecar must carry to be read at all. */\nexport const SESSION_LINEAGE_RECORD_VERSION = 1;\n\n/** The version a hub advertisement must carry to be read at all. */\nexport const HUB_ADVERTISEMENT_VERSION = 1;\n\nconst DEFAULT_RUN_DIR_SEGMENT = '.doompi/run';\nconst SESSIONS_SEGMENT = 'sessions';\nconst LINEAGE_EXTENSION = '.lineage.json';\nconst HUB_ADVERTISEMENT_FILE = 'hub.json';\n\n/**\n * The single definition of where the session registry lives.\n *\n * The hub, the session server, and any package that spawns a session must land\n * on the same directory or a spawned session never appears in the rail. This\n * used to be copied into each of them; it lives here so there is one answer.\n */\nexport function resolveRegistryDir(input: RegistryDirInput): string {\n if (input.flagValue) return input.flagValue;\n if (input.envValue) return input.envValue;\n return `${input.homeDir}/${DEFAULT_RUN_DIR_SEGMENT}`;\n}\n\n/** The lineage sidecar's path, beside the session's own record file. */\nexport function sessionLineagePath(registryDir: string, sessionId: string): string {\n return `${registryDir}/${SESSIONS_SEGMENT}/${sessionId}${LINEAGE_EXTENSION}`;\n}\n\n/**\n * Reads a lineage sidecar's contents.\n *\n * Every failure means the same thing to a caller: this session has no known\n * parent. A torn write, a version this build predates, or a file that is not\n * JSON at all are all normal, because the sidecar is written by a separate\n * process that may be mid-write or newer than the reader.\n */\nexport function parseSessionLineage(raw: string): SessionLineageRecord | undefined {\n let parsed: unknown;\n try {\n parsed = JSON.parse(raw);\n } catch {\n return undefined;\n }\n if (typeof parsed !== 'object' || parsed === null) return undefined;\n const record = parsed as Partial<SessionLineageRecord>;\n if (record.version !== SESSION_LINEAGE_RECORD_VERSION) return undefined;\n if (typeof record.parentSessionId !== 'string' || record.parentSessionId === '') return undefined;\n const provenance = typeof record.provenance === 'string' ? record.provenance : '';\n return { version: SESSION_LINEAGE_RECORD_VERSION, parentSessionId: record.parentSessionId, provenance };\n}\n\n/** Where the hub publishes its local address, at the registry root. */\nexport function hubAdvertisementPath(registryDir: string): string {\n return `${registryDir}/${HUB_ADVERTISEMENT_FILE}`;\n}\n\n/**\n * Reads a hub advertisement's contents.\n *\n * Like the lineage sidecar, every failure collapses to \"no hub advertised\",\n * because a caller can do nothing different with a torn write than with a\n * missing file. The url is required to be a loopback http origin: this file is\n * a discovery hint for local processes, and honouring an arbitrary address out\n * of it would let anything that can write the registry directory redirect a\n * session-create call to a host of its choosing.\n */\nexport function parseHubAdvertisement(raw: string): HubAdvertisement | undefined {\n let parsed: unknown;\n try {\n parsed = JSON.parse(raw);\n } catch {\n return undefined;\n }\n if (typeof parsed !== 'object' || parsed === null) return undefined;\n const record = parsed as Partial<HubAdvertisement>;\n if (record.version !== HUB_ADVERTISEMENT_VERSION) return undefined;\n if (typeof record.url !== 'string' || !isLoopbackHttpUrl(record.url)) return undefined;\n if (typeof record.pid !== 'number' || !Number.isInteger(record.pid) || record.pid <= 0) return undefined;\n return { version: HUB_ADVERTISEMENT_VERSION, url: record.url, pid: record.pid };\n}\n\n/** Whether a url is plain http to this machine, which is all this file may name. */\nfunction isLoopbackHttpUrl(value: string): boolean {\n let url: URL;\n try {\n url = new URL(value);\n } catch {\n return false;\n }\n if (url.protocol !== 'http:') return false;\n return (\n url.hostname === '127.0.0.1' || url.hostname === 'localhost' || url.hostname === '[::1]' || url.hostname === '::1'\n );\n}\n"],"mappings":"AAuBA,SAAgB,EAAmB,EAAiC,CAGlE,OAFI,EAAM,UAAkB,EAAM,UAC9B,EAAM,SAAiB,EAAM,SAC1B,GAAG,EAAM,QAAQ,aAC1B,CAGA,SAAgB,EAAmB,EAAqB,EAA2B,CACjF,MAAO,GAAG,EAAY,YAAuB,gBAC/C,CAUA,SAAgB,EAAoB,EAA+C,CACjF,IAAI,EACJ,GAAI,CACF,EAAS,KAAK,MAAM,CAAG,CACzB,MAAQ,CACN,MACF,CACA,GAAI,OAAO,GAAW,WAAY,EAAiB,OACnD,IAAM,EAAS,EAEf,GADI,EAAO,UAAA,GACP,OAAO,EAAO,iBAAoB,UAAY,EAAO,kBAAoB,GAAI,OACjF,IAAM,EAAa,OAAO,EAAO,YAAe,SAAW,EAAO,WAAa,GAC/E,MAAO,CAAE,QAAA,EAAyC,gBAAiB,EAAO,gBAAiB,YAAW,CACxG,CAGA,SAAgB,EAAqB,EAA6B,CAChE,MAAO,GAAG,EAAY,UACxB,CAYA,SAAgB,EAAsB,EAA2C,CAC/E,IAAI,EACJ,GAAI,CACF,EAAS,KAAK,MAAM,CAAG,CACzB,MAAQ,CACN,MACF,CACA,GAAI,OAAO,GAAW,WAAY,EAAiB,OACnD,IAAM,EAAS,EACX,KAAO,UAAA,GACP,OAAO,EAAO,KAAQ,UAAa,EAAkB,EAAO,GAAG,GAC/D,SAAO,EAAO,KAAQ,UAAY,CAAC,OAAO,UAAU,EAAO,GAAG,GAAK,EAAO,KAAO,GACrF,MAAO,CAAE,QAAA,EAAoC,IAAK,EAAO,IAAK,IAAK,EAAO,GAAI,CAChF,CAGA,SAAS,EAAkB,EAAwB,CACjD,IAAI,EACJ,GAAI,CACF,EAAM,IAAI,IAAI,CAAK,CACrB,MAAQ,CACN,MAAO,EACT,CAEA,OADI,EAAI,WAAa,QAEnB,EAAI,WAAa,aAAe,EAAI,WAAa,aAAe,EAAI,WAAa,SAAW,EAAI,WAAa,MAF1E,EAIvC"}
@@ -0,0 +1,42 @@
1
+ import { HubAdvertisement, RegistryDirInput, SessionLineageRecord } from "../types/sessionRegistry.cjs";
2
+ //#region src/services/sessionRegistry.d.ts
3
+ /** Overrides the runtime directory the hub and its session servers share. */
4
+ export declare const REGISTRY_DIR_ENV = "DOOMPI_RUNTIME_DIR";
5
+ /** The version a lineage sidecar must carry to be read at all. */
6
+ export declare const SESSION_LINEAGE_RECORD_VERSION = 1;
7
+ /** The version a hub advertisement must carry to be read at all. */
8
+ export declare const HUB_ADVERTISEMENT_VERSION = 1;
9
+ /**
10
+ * The single definition of where the session registry lives.
11
+ *
12
+ * The hub, the session server, and any package that spawns a session must land
13
+ * on the same directory or a spawned session never appears in the rail. This
14
+ * used to be copied into each of them; it lives here so there is one answer.
15
+ */
16
+ export declare function resolveRegistryDir(input: RegistryDirInput): string;
17
+ /** The lineage sidecar's path, beside the session's own record file. */
18
+ export declare function sessionLineagePath(registryDir: string, sessionId: string): string;
19
+ /**
20
+ * Reads a lineage sidecar's contents.
21
+ *
22
+ * Every failure means the same thing to a caller: this session has no known
23
+ * parent. A torn write, a version this build predates, or a file that is not
24
+ * JSON at all are all normal, because the sidecar is written by a separate
25
+ * process that may be mid-write or newer than the reader.
26
+ */
27
+ export declare function parseSessionLineage(raw: string): SessionLineageRecord | undefined;
28
+ /** Where the hub publishes its local address, at the registry root. */
29
+ export declare function hubAdvertisementPath(registryDir: string): string;
30
+ /**
31
+ * Reads a hub advertisement's contents.
32
+ *
33
+ * Like the lineage sidecar, every failure collapses to "no hub advertised",
34
+ * because a caller can do nothing different with a torn write than with a
35
+ * missing file. The url is required to be a loopback http origin: this file is
36
+ * a discovery hint for local processes, and honouring an arbitrary address out
37
+ * of it would let anything that can write the registry directory redirect a
38
+ * session-create call to a host of its choosing.
39
+ */
40
+ export declare function parseHubAdvertisement(raw: string): HubAdvertisement | undefined;
41
+ //#endregion
42
+ //# sourceMappingURL=sessionRegistry.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sessionRegistry.d.cts","names":[],"sources":["../../src/services/sessionRegistry.ts"],"mappings":";;;qBAGa;;qBAGA;;qBAGA;;;;;;;;wBAcG,mBAAmB,OAAO;;wBAO1B,mBAAmB,qBAAqB;;;;;;;;;wBAYxC,oBAAoB,cAAc;;wBAgBlC,qBAAqB;;;;;;;;;;;wBAcrB,sBAAsB,cAAc"}
@@ -0,0 +1,42 @@
1
+ import { HubAdvertisement, RegistryDirInput, SessionLineageRecord } from "../types/sessionRegistry.mjs";
2
+ //#region src/services/sessionRegistry.d.ts
3
+ /** Overrides the runtime directory the hub and its session servers share. */
4
+ export declare const REGISTRY_DIR_ENV = "DOOMPI_RUNTIME_DIR";
5
+ /** The version a lineage sidecar must carry to be read at all. */
6
+ export declare const SESSION_LINEAGE_RECORD_VERSION = 1;
7
+ /** The version a hub advertisement must carry to be read at all. */
8
+ export declare const HUB_ADVERTISEMENT_VERSION = 1;
9
+ /**
10
+ * The single definition of where the session registry lives.
11
+ *
12
+ * The hub, the session server, and any package that spawns a session must land
13
+ * on the same directory or a spawned session never appears in the rail. This
14
+ * used to be copied into each of them; it lives here so there is one answer.
15
+ */
16
+ export declare function resolveRegistryDir(input: RegistryDirInput): string;
17
+ /** The lineage sidecar's path, beside the session's own record file. */
18
+ export declare function sessionLineagePath(registryDir: string, sessionId: string): string;
19
+ /**
20
+ * Reads a lineage sidecar's contents.
21
+ *
22
+ * Every failure means the same thing to a caller: this session has no known
23
+ * parent. A torn write, a version this build predates, or a file that is not
24
+ * JSON at all are all normal, because the sidecar is written by a separate
25
+ * process that may be mid-write or newer than the reader.
26
+ */
27
+ export declare function parseSessionLineage(raw: string): SessionLineageRecord | undefined;
28
+ /** Where the hub publishes its local address, at the registry root. */
29
+ export declare function hubAdvertisementPath(registryDir: string): string;
30
+ /**
31
+ * Reads a hub advertisement's contents.
32
+ *
33
+ * Like the lineage sidecar, every failure collapses to "no hub advertised",
34
+ * because a caller can do nothing different with a torn write than with a
35
+ * missing file. The url is required to be a loopback http origin: this file is
36
+ * a discovery hint for local processes, and honouring an arbitrary address out
37
+ * of it would let anything that can write the registry directory redirect a
38
+ * session-create call to a host of its choosing.
39
+ */
40
+ export declare function parseHubAdvertisement(raw: string): HubAdvertisement | undefined;
41
+ //#endregion
42
+ //# sourceMappingURL=sessionRegistry.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sessionRegistry.d.mts","names":[],"sources":["../../src/services/sessionRegistry.ts"],"mappings":";;;qBAGa;;qBAGA;;qBAGA;;;;;;;;wBAcG,mBAAmB,OAAO;;wBAO1B,mBAAmB,qBAAqB;;;;;;;;;wBAYxC,oBAAoB,cAAc;;wBAgBlC,qBAAqB;;;;;;;;;;;wBAcrB,sBAAsB,cAAc"}
@@ -0,0 +1,2 @@
1
+ const e=`DOOMPI_RUNTIME_DIR`,t=1,n=1;function r(e){return e.flagValue?e.flagValue:e.envValue?e.envValue:`${e.homeDir}/.doompi/run`}function i(e,t){return`${e}/sessions/${t}.lineage.json`}function a(e){let t;try{t=JSON.parse(e)}catch{return}if(typeof t!=`object`||!t)return;let n=t;if(n.version!==1||typeof n.parentSessionId!=`string`||n.parentSessionId===``)return;let r=typeof n.provenance==`string`?n.provenance:``;return{version:1,parentSessionId:n.parentSessionId,provenance:r}}function o(e){return`${e}/hub.json`}function s(e){let t;try{t=JSON.parse(e)}catch{return}if(typeof t!=`object`||!t)return;let n=t;if(n.version===1&&typeof n.url==`string`&&c(n.url)&&!(typeof n.pid!=`number`||!Number.isInteger(n.pid)||n.pid<=0))return{version:1,url:n.url,pid:n.pid}}function c(e){let t;try{t=new URL(e)}catch{return!1}return t.protocol===`http:`?t.hostname===`127.0.0.1`||t.hostname===`localhost`||t.hostname===`[::1]`||t.hostname===`::1`:!1}export{n as HUB_ADVERTISEMENT_VERSION,e as REGISTRY_DIR_ENV,t as SESSION_LINEAGE_RECORD_VERSION,o as hubAdvertisementPath,s as parseHubAdvertisement,a as parseSessionLineage,r as resolveRegistryDir,i as sessionLineagePath};
2
+ //# sourceMappingURL=sessionRegistry.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sessionRegistry.mjs","names":[],"sources":["../../src/services/sessionRegistry.ts"],"sourcesContent":["import type { HubAdvertisement, RegistryDirInput, SessionLineageRecord } from '../types/sessionRegistry.ts';\n\n/** Overrides the runtime directory the hub and its session servers share. */\nexport const REGISTRY_DIR_ENV = 'DOOMPI_RUNTIME_DIR';\n\n/** The version a lineage sidecar must carry to be read at all. */\nexport const SESSION_LINEAGE_RECORD_VERSION = 1;\n\n/** The version a hub advertisement must carry to be read at all. */\nexport const HUB_ADVERTISEMENT_VERSION = 1;\n\nconst DEFAULT_RUN_DIR_SEGMENT = '.doompi/run';\nconst SESSIONS_SEGMENT = 'sessions';\nconst LINEAGE_EXTENSION = '.lineage.json';\nconst HUB_ADVERTISEMENT_FILE = 'hub.json';\n\n/**\n * The single definition of where the session registry lives.\n *\n * The hub, the session server, and any package that spawns a session must land\n * on the same directory or a spawned session never appears in the rail. This\n * used to be copied into each of them; it lives here so there is one answer.\n */\nexport function resolveRegistryDir(input: RegistryDirInput): string {\n if (input.flagValue) return input.flagValue;\n if (input.envValue) return input.envValue;\n return `${input.homeDir}/${DEFAULT_RUN_DIR_SEGMENT}`;\n}\n\n/** The lineage sidecar's path, beside the session's own record file. */\nexport function sessionLineagePath(registryDir: string, sessionId: string): string {\n return `${registryDir}/${SESSIONS_SEGMENT}/${sessionId}${LINEAGE_EXTENSION}`;\n}\n\n/**\n * Reads a lineage sidecar's contents.\n *\n * Every failure means the same thing to a caller: this session has no known\n * parent. A torn write, a version this build predates, or a file that is not\n * JSON at all are all normal, because the sidecar is written by a separate\n * process that may be mid-write or newer than the reader.\n */\nexport function parseSessionLineage(raw: string): SessionLineageRecord | undefined {\n let parsed: unknown;\n try {\n parsed = JSON.parse(raw);\n } catch {\n return undefined;\n }\n if (typeof parsed !== 'object' || parsed === null) return undefined;\n const record = parsed as Partial<SessionLineageRecord>;\n if (record.version !== SESSION_LINEAGE_RECORD_VERSION) return undefined;\n if (typeof record.parentSessionId !== 'string' || record.parentSessionId === '') return undefined;\n const provenance = typeof record.provenance === 'string' ? record.provenance : '';\n return { version: SESSION_LINEAGE_RECORD_VERSION, parentSessionId: record.parentSessionId, provenance };\n}\n\n/** Where the hub publishes its local address, at the registry root. */\nexport function hubAdvertisementPath(registryDir: string): string {\n return `${registryDir}/${HUB_ADVERTISEMENT_FILE}`;\n}\n\n/**\n * Reads a hub advertisement's contents.\n *\n * Like the lineage sidecar, every failure collapses to \"no hub advertised\",\n * because a caller can do nothing different with a torn write than with a\n * missing file. The url is required to be a loopback http origin: this file is\n * a discovery hint for local processes, and honouring an arbitrary address out\n * of it would let anything that can write the registry directory redirect a\n * session-create call to a host of its choosing.\n */\nexport function parseHubAdvertisement(raw: string): HubAdvertisement | undefined {\n let parsed: unknown;\n try {\n parsed = JSON.parse(raw);\n } catch {\n return undefined;\n }\n if (typeof parsed !== 'object' || parsed === null) return undefined;\n const record = parsed as Partial<HubAdvertisement>;\n if (record.version !== HUB_ADVERTISEMENT_VERSION) return undefined;\n if (typeof record.url !== 'string' || !isLoopbackHttpUrl(record.url)) return undefined;\n if (typeof record.pid !== 'number' || !Number.isInteger(record.pid) || record.pid <= 0) return undefined;\n return { version: HUB_ADVERTISEMENT_VERSION, url: record.url, pid: record.pid };\n}\n\n/** Whether a url is plain http to this machine, which is all this file may name. */\nfunction isLoopbackHttpUrl(value: string): boolean {\n let url: URL;\n try {\n url = new URL(value);\n } catch {\n return false;\n }\n if (url.protocol !== 'http:') return false;\n return (\n url.hostname === '127.0.0.1' || url.hostname === 'localhost' || url.hostname === '[::1]' || url.hostname === '::1'\n );\n}\n"],"mappings":"AAGA,MAAa,EAAmB,qBAGnB,EAAiC,EAGjC,EAA4B,EAczC,SAAgB,EAAmB,EAAiC,CAGlE,OAFI,EAAM,UAAkB,EAAM,UAC9B,EAAM,SAAiB,EAAM,SAC1B,GAAG,EAAM,QAAQ,aAC1B,CAGA,SAAgB,EAAmB,EAAqB,EAA2B,CACjF,MAAO,GAAG,EAAY,YAAuB,gBAC/C,CAUA,SAAgB,EAAoB,EAA+C,CACjF,IAAI,EACJ,GAAI,CACF,EAAS,KAAK,MAAM,CAAG,CACzB,MAAQ,CACN,MACF,CACA,GAAI,OAAO,GAAW,WAAY,EAAiB,OACnD,IAAM,EAAS,EAEf,GADI,EAAO,UAAA,GACP,OAAO,EAAO,iBAAoB,UAAY,EAAO,kBAAoB,GAAI,OACjF,IAAM,EAAa,OAAO,EAAO,YAAe,SAAW,EAAO,WAAa,GAC/E,MAAO,CAAE,QAAA,EAAyC,gBAAiB,EAAO,gBAAiB,YAAW,CACxG,CAGA,SAAgB,EAAqB,EAA6B,CAChE,MAAO,GAAG,EAAY,UACxB,CAYA,SAAgB,EAAsB,EAA2C,CAC/E,IAAI,EACJ,GAAI,CACF,EAAS,KAAK,MAAM,CAAG,CACzB,MAAQ,CACN,MACF,CACA,GAAI,OAAO,GAAW,WAAY,EAAiB,OACnD,IAAM,EAAS,EACX,KAAO,UAAA,GACP,OAAO,EAAO,KAAQ,UAAa,EAAkB,EAAO,GAAG,GAC/D,SAAO,EAAO,KAAQ,UAAY,CAAC,OAAO,UAAU,EAAO,GAAG,GAAK,EAAO,KAAO,GACrF,MAAO,CAAE,QAAA,EAAoC,IAAK,EAAO,IAAK,IAAK,EAAO,GAAI,CAChF,CAGA,SAAS,EAAkB,EAAwB,CACjD,IAAI,EACJ,GAAI,CACF,EAAM,IAAI,IAAI,CAAK,CACrB,MAAQ,CACN,MAAO,EACT,CAEA,OADI,EAAI,WAAa,QAEnB,EAAI,WAAa,aAAe,EAAI,WAAa,aAAe,EAAI,WAAa,SAAW,EAAI,WAAa,MAF1E,EAIvC"}
@@ -9,7 +9,6 @@ import { SessionStore } from "../types/webPlugin.cjs";
9
9
  * per read would re-render forever. Records are therefore immutable values,
10
10
  * and updaters and reducers return new ones.
11
11
  */
12
- declare function defineSessionStore<T>(empty: T): SessionStore<T>;
12
+ export declare function defineSessionStore<T>(empty: T): SessionStore<T>;
13
13
  //#endregion
14
- export { defineSessionStore };
15
14
  //# sourceMappingURL=sessionStore.d.cts.map
@@ -1 +1 @@
1
- {"version":3,"file":"sessionStore.d.cts","names":[],"sources":["../../src/services/sessionStore.ts"],"mappings":";;;;;;;;;;;iBAkBgB,mBAAmB,GAAG,OAAO,IAAI,aAAa"}
1
+ {"version":3,"file":"sessionStore.d.cts","names":[],"sources":["../../src/services/sessionStore.ts"],"mappings":";;;;;;;;;;;wBAkBgB,mBAAmB,GAAG,OAAO,IAAI,aAAa"}
@@ -9,7 +9,6 @@ import { SessionStore } from "../types/webPlugin.mjs";
9
9
  * per read would re-render forever. Records are therefore immutable values,
10
10
  * and updaters and reducers return new ones.
11
11
  */
12
- declare function defineSessionStore<T>(empty: T): SessionStore<T>;
12
+ export declare function defineSessionStore<T>(empty: T): SessionStore<T>;
13
13
  //#endregion
14
- export { defineSessionStore };
15
14
  //# sourceMappingURL=sessionStore.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"sessionStore.d.mts","names":[],"sources":["../../src/services/sessionStore.ts"],"mappings":";;;;;;;;;;;iBAkBgB,mBAAmB,GAAG,OAAO,IAAI,aAAa"}
1
+ {"version":3,"file":"sessionStore.d.mts","names":[],"sources":["../../src/services/sessionStore.ts"],"mappings":";;;;;;;;;;;wBAkBgB,mBAAmB,GAAG,OAAO,IAAI,aAAa"}
@@ -1,2 +1,2 @@
1
- function e(e,t,n){let r=e.parse(n);return r===null?{accepted:!1}:(e.apply(t,r),{accepted:!0})}const t={sessionId:`s1`,cwd:`/repo`};function n(e,n={}){let r=[...n.sessions??[t]],i=[],a=[],o=e.start({sessions:()=>r,publish:(t,n)=>{i.push({type:e.frameType,sessionId:t,payload:n})},onNotice:e=>a.push(e)});return{source:o,published:i,notices:a,snapshot(e){let n=r.find(t=>t.sessionId===e)??r[0]??t;return o.payloadFor(n)},addSession(e){r.push(e),o.sessionAdded?.(e)},removeSession(e){let t=r.findIndex(t=>t.sessionId===e);t>=0&&r.splice(t,1),o.sessionRemoved?.(e)},close:()=>o.close()}}exports.driveChannel=e,exports.hubChannelHarness=n;
1
+ function e(e,t,n){let r=e.parse(n);return r===null?{accepted:!1}:(e.apply(t,r),{accepted:!0})}const t={sessionId:`s1`,cwd:`/repo`};function n(e,n={}){let r=[...n.sessions??[t]],i=[],a=[],o=e.start({sessions:()=>r,publish:(t,n)=>{i.push({type:e.frameType,sessionId:t,payload:n})},requestSessionApi:()=>Promise.resolve(Response.json({error:`No session API in the channel harness.`},{status:501})),onNotice:e=>a.push(e)});return{source:o,published:i,notices:a,snapshot(e){let n=r.find(t=>t.sessionId===e)??r[0]??t;return o.payloadFor(n)},addSession(e){r.push(e),o.sessionAdded?.(e)},removeSession(e){let t=r.findIndex(t=>t.sessionId===e);t>=0&&r.splice(t,1),o.sessionRemoved?.(e)},close:()=>o.close()}}exports.driveChannel=e,exports.hubChannelHarness=n;
2
2
  //# sourceMappingURL=channels.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"channels.cjs","names":[],"sources":["../../../src/services/testing/channels.ts"],"sourcesContent":["import type {\n ChannelFrame,\n HubChannelHost,\n HubChannelSource,\n HubSessionScope,\n WebHubChannel,\n} from '../../types/webHub.ts';\nimport type { SessionChannelContribution } from '../../types/webPlugin.ts';\n\n/**\n * The two halves of a plugin's data channel, driven the way the hub drives them.\n *\n * A channel is the one place a plugin parses input it did not produce, so its\n * parse gate is the boundary that matters, and a test that calls `apply`\n * directly steps straight over it. `driveChannel` sends a wire payload the way\n * the page does: through `parse` first, and nothing applied when it is\n * rejected.\n */\n\nexport interface ChannelDelivery {\n /** Whether the parse gate accepted the payload. */\n accepted: boolean;\n}\n\n/**\n * Sends one wire payload to a session channel.\n *\n * Returns whether the gate accepted it, so a test can assert a rejection\n * without knowing what the plugin's parsed shape looks like.\n */\nexport function driveChannel(\n channel: SessionChannelContribution,\n sessionId: string,\n payload: unknown,\n): ChannelDelivery {\n const parsed: unknown = channel.parse(payload);\n if (parsed === null) return { accepted: false };\n channel.apply(sessionId, parsed);\n return { accepted: true };\n}\n\nexport interface HubChannelHarness {\n /** The running source, as the hub holds it. */\n source: HubChannelSource;\n /** Everything the source pushed, in order. */\n readonly published: readonly ChannelFrame[];\n /** What the source told the hub. */\n readonly notices: readonly string[];\n /** The subscribe-time snapshot one session would receive; undefined means no frame. */\n snapshot(sessionId?: string): unknown;\n /** Registers a session with the source, as the hub does when one appears. */\n addSession(scope: HubSessionScope): void;\n removeSession(sessionId: string): void;\n close(): void;\n}\n\nexport interface HubChannelHarnessOptions {\n /** Sessions the hub already manages when the channel starts. */\n sessions?: readonly HubSessionScope[];\n}\n\nconst DEFAULT_SESSION: HubSessionScope = { sessionId: 's1', cwd: '/repo' };\n\n/**\n * A plugin's hub channel, started against a real host.\n *\n * The hub calls `payloadFor` once per subscriber and pushes through `publish`\n * afterwards, and a channel that only answers one of those looks correct in a\n * test that exercises the other.\n */\nexport function hubChannelHarness(channel: WebHubChannel, options: HubChannelHarnessOptions = {}): HubChannelHarness {\n const sessions = [...(options.sessions ?? [DEFAULT_SESSION])];\n const published: ChannelFrame[] = [];\n const notices: string[] = [];\n const host: HubChannelHost = {\n sessions: () => sessions,\n publish: (sessionId, payload) => {\n published.push({ type: channel.frameType, sessionId, payload });\n },\n onNotice: (message) => notices.push(message),\n };\n const source = channel.start(host);\n\n return {\n source,\n published,\n notices,\n snapshot(sessionId) {\n const scope = sessions.find((candidate) => candidate.sessionId === sessionId) ?? sessions[0] ?? DEFAULT_SESSION;\n return source.payloadFor(scope);\n },\n addSession(scope) {\n sessions.push(scope);\n source.sessionAdded?.(scope);\n },\n removeSession(sessionId) {\n const index = sessions.findIndex((candidate) => candidate.sessionId === sessionId);\n if (index >= 0) sessions.splice(index, 1);\n source.sessionRemoved?.(sessionId);\n },\n close: () => source.close(),\n };\n}\n"],"mappings":"AA8BA,SAAgB,EACd,EACA,EACA,EACiB,CACjB,IAAM,EAAkB,EAAQ,MAAM,CAAO,EAG7C,OAFI,IAAW,KAAa,CAAE,SAAU,EAAM,GAC9C,EAAQ,MAAM,EAAW,CAAM,EACxB,CAAE,SAAU,EAAK,EAC1B,CAsBA,MAAM,EAAmC,CAAE,UAAW,KAAM,IAAK,OAAQ,EASzE,SAAgB,EAAkB,EAAwB,EAAoC,CAAC,EAAsB,CACnH,IAAM,EAAW,CAAC,GAAI,EAAQ,UAAY,CAAC,CAAe,CAAE,EACtD,EAA4B,CAAC,EAC7B,EAAoB,CAAC,EAQrB,EAAS,EAAQ,MAAM,CAN3B,aAAgB,EAChB,SAAU,EAAW,IAAY,CAC/B,EAAU,KAAK,CAAE,KAAM,EAAQ,UAAW,YAAW,SAAQ,CAAC,CAChE,EACA,SAAW,GAAY,EAAQ,KAAK,CAAO,CAEb,CAAC,EAEjC,MAAO,CACL,SACA,YACA,UACA,SAAS,EAAW,CAClB,IAAM,EAAQ,EAAS,KAAM,GAAc,EAAU,YAAc,CAAS,GAAK,EAAS,IAAM,EAChG,OAAO,EAAO,WAAW,CAAK,CAChC,EACA,WAAW,EAAO,CAChB,EAAS,KAAK,CAAK,EACnB,EAAO,eAAe,CAAK,CAC7B,EACA,cAAc,EAAW,CACvB,IAAM,EAAQ,EAAS,UAAW,GAAc,EAAU,YAAc,CAAS,EAC7E,GAAS,GAAG,EAAS,OAAO,EAAO,CAAC,EACxC,EAAO,iBAAiB,CAAS,CACnC,EACA,UAAa,EAAO,MAAM,CAC5B,CACF"}
1
+ {"version":3,"file":"channels.cjs","names":[],"sources":["../../../src/services/testing/channels.ts"],"sourcesContent":["import type {\n ChannelFrame,\n HubChannelHost,\n HubChannelSource,\n HubSessionScope,\n WebHubChannel,\n} from '../../types/webHub.ts';\nimport type { SessionChannelContribution } from '../../types/webPlugin.ts';\n\n/**\n * The two halves of a plugin's data channel, driven the way the hub drives them.\n *\n * A channel is the one place a plugin parses input it did not produce, so its\n * parse gate is the boundary that matters, and a test that calls `apply`\n * directly steps straight over it. `driveChannel` sends a wire payload the way\n * the page does: through `parse` first, and nothing applied when it is\n * rejected.\n */\n\nexport interface ChannelDelivery {\n /** Whether the parse gate accepted the payload. */\n accepted: boolean;\n}\n\n/**\n * Sends one wire payload to a session channel.\n *\n * Returns whether the gate accepted it, so a test can assert a rejection\n * without knowing what the plugin's parsed shape looks like.\n */\nexport function driveChannel(\n channel: SessionChannelContribution,\n sessionId: string,\n payload: unknown,\n): ChannelDelivery {\n const parsed: unknown = channel.parse(payload);\n if (parsed === null) return { accepted: false };\n channel.apply(sessionId, parsed);\n return { accepted: true };\n}\n\nexport interface HubChannelHarness {\n /** The running source, as the hub holds it. */\n source: HubChannelSource;\n /** Everything the source pushed, in order. */\n readonly published: readonly ChannelFrame[];\n /** What the source told the hub. */\n readonly notices: readonly string[];\n /** The subscribe-time snapshot one session would receive; undefined means no frame. */\n snapshot(sessionId?: string): unknown;\n /** Registers a session with the source, as the hub does when one appears. */\n addSession(scope: HubSessionScope): void;\n removeSession(sessionId: string): void;\n close(): void;\n}\n\nexport interface HubChannelHarnessOptions {\n /** Sessions the hub already manages when the channel starts. */\n sessions?: readonly HubSessionScope[];\n}\n\nconst DEFAULT_SESSION: HubSessionScope = { sessionId: 's1', cwd: '/repo' };\n\n/**\n * A plugin's hub channel, started against a real host.\n *\n * The hub calls `payloadFor` once per subscriber and pushes through `publish`\n * afterwards, and a channel that only answers one of those looks correct in a\n * test that exercises the other.\n */\nexport function hubChannelHarness(channel: WebHubChannel, options: HubChannelHarnessOptions = {}): HubChannelHarness {\n const sessions = [...(options.sessions ?? [DEFAULT_SESSION])];\n const published: ChannelFrame[] = [];\n const notices: string[] = [];\n const host: HubChannelHost = {\n sessions: () => sessions,\n publish: (sessionId, payload) => {\n published.push({ type: channel.frameType, sessionId, payload });\n },\n requestSessionApi: () =>\n Promise.resolve(Response.json({ error: 'No session API in the channel harness.' }, { status: 501 })),\n onNotice: (message) => notices.push(message),\n };\n const source = channel.start(host);\n\n return {\n source,\n published,\n notices,\n snapshot(sessionId) {\n const scope = sessions.find((candidate) => candidate.sessionId === sessionId) ?? sessions[0] ?? DEFAULT_SESSION;\n return source.payloadFor(scope);\n },\n addSession(scope) {\n sessions.push(scope);\n source.sessionAdded?.(scope);\n },\n removeSession(sessionId) {\n const index = sessions.findIndex((candidate) => candidate.sessionId === sessionId);\n if (index >= 0) sessions.splice(index, 1);\n source.sessionRemoved?.(sessionId);\n },\n close: () => source.close(),\n };\n}\n"],"mappings":"AA8BA,SAAgB,EACd,EACA,EACA,EACiB,CACjB,IAAM,EAAkB,EAAQ,MAAM,CAAO,EAG7C,OAFI,IAAW,KAAa,CAAE,SAAU,EAAM,GAC9C,EAAQ,MAAM,EAAW,CAAM,EACxB,CAAE,SAAU,EAAK,EAC1B,CAsBA,MAAM,EAAmC,CAAE,UAAW,KAAM,IAAK,OAAQ,EASzE,SAAgB,EAAkB,EAAwB,EAAoC,CAAC,EAAsB,CACnH,IAAM,EAAW,CAAC,GAAI,EAAQ,UAAY,CAAC,CAAe,CAAE,EACtD,EAA4B,CAAC,EAC7B,EAAoB,CAAC,EAUrB,EAAS,EAAQ,MAAM,CAR3B,aAAgB,EAChB,SAAU,EAAW,IAAY,CAC/B,EAAU,KAAK,CAAE,KAAM,EAAQ,UAAW,YAAW,SAAQ,CAAC,CAChE,EACA,sBACE,QAAQ,QAAQ,SAAS,KAAK,CAAE,MAAO,wCAAyC,EAAG,CAAE,OAAQ,GAAI,CAAC,CAAC,EACrG,SAAW,GAAY,EAAQ,KAAK,CAAO,CAEb,CAAC,EAEjC,MAAO,CACL,SACA,YACA,UACA,SAAS,EAAW,CAClB,IAAM,EAAQ,EAAS,KAAM,GAAc,EAAU,YAAc,CAAS,GAAK,EAAS,IAAM,EAChG,OAAO,EAAO,WAAW,CAAK,CAChC,EACA,WAAW,EAAO,CAChB,EAAS,KAAK,CAAK,EACnB,EAAO,eAAe,CAAK,CAC7B,EACA,cAAc,EAAW,CACvB,IAAM,EAAQ,EAAS,UAAW,GAAc,EAAU,YAAc,CAAS,EAC7E,GAAS,GAAG,EAAS,OAAO,EAAO,CAAC,EACxC,EAAO,iBAAiB,CAAS,CACnC,EACA,UAAa,EAAO,MAAM,CAC5B,CACF"}
@@ -10,7 +10,7 @@ import { ChannelFrame, HubChannelSource, HubSessionScope, WebHubChannel } from "
10
10
  * the page does: through `parse` first, and nothing applied when it is
11
11
  * rejected.
12
12
  */
13
- interface ChannelDelivery {
13
+ export interface ChannelDelivery {
14
14
  /** Whether the parse gate accepted the payload. */
15
15
  accepted: boolean;
16
16
  }
@@ -20,8 +20,8 @@ interface ChannelDelivery {
20
20
  * Returns whether the gate accepted it, so a test can assert a rejection
21
21
  * without knowing what the plugin's parsed shape looks like.
22
22
  */
23
- declare function driveChannel(channel: SessionChannelContribution, sessionId: string, payload: unknown): ChannelDelivery;
24
- interface HubChannelHarness {
23
+ export declare function driveChannel(channel: SessionChannelContribution, sessionId: string, payload: unknown): ChannelDelivery;
24
+ export interface HubChannelHarness {
25
25
  /** The running source, as the hub holds it. */
26
26
  source: HubChannelSource;
27
27
  /** Everything the source pushed, in order. */
@@ -35,7 +35,7 @@ interface HubChannelHarness {
35
35
  removeSession(sessionId: string): void;
36
36
  close(): void;
37
37
  }
38
- interface HubChannelHarnessOptions {
38
+ export interface HubChannelHarnessOptions {
39
39
  /** Sessions the hub already manages when the channel starts. */
40
40
  sessions?: readonly HubSessionScope[];
41
41
  }
@@ -46,7 +46,6 @@ interface HubChannelHarnessOptions {
46
46
  * afterwards, and a channel that only answers one of those looks correct in a
47
47
  * test that exercises the other.
48
48
  */
49
- declare function hubChannelHarness(channel: WebHubChannel, options?: HubChannelHarnessOptions): HubChannelHarness;
49
+ export declare function hubChannelHarness(channel: WebHubChannel, options?: HubChannelHarnessOptions): HubChannelHarness;
50
50
  //#endregion
51
- export { ChannelDelivery, HubChannelHarness, HubChannelHarnessOptions, driveChannel, hubChannelHarness };
52
51
  //# sourceMappingURL=channels.d.cts.map
@@ -1 +1 @@
1
- {"version":3,"file":"channels.d.cts","names":[],"sources":["../../../src/services/testing/channels.ts"],"mappings":";;;;;;;;;;;;UAmBiB;;EAEf;;;;;;;;iBASc,aACd,SAAS,4BACT,mBACA,mBACC;UAOc;;EAEf,QAAQ;;WAEC,oBAAoB;;WAEpB;;EAET,SAAS;;EAET,WAAW,OAAO;EAClB,cAAc;EACd;;UAGe;;EAEf,oBAAoB;;;;;;;;;iBAYN,kBAAkB,SAAS,eAAe,UAAS,2BAAgC"}
1
+ {"version":3,"file":"channels.d.cts","names":[],"sources":["../../../src/services/testing/channels.ts"],"mappings":";;;;;;;;;;;;iBAmBiB;;EAEf;;;;;;;;wBASc,aACd,SAAS,4BACT,mBACA,mBACC;iBAOc;;EAEf,QAAQ;;WAEC,oBAAoB;;WAEpB;;EAET,SAAS;;EAET,WAAW,OAAO;EAClB,cAAc;EACd;;iBAGe;;EAEf,oBAAoB;;;;;;;;;wBAYN,kBAAkB,SAAS,eAAe,UAAS,2BAAgC"}
@@ -10,7 +10,7 @@ import { ChannelFrame, HubChannelSource, HubSessionScope, WebHubChannel } from "
10
10
  * the page does: through `parse` first, and nothing applied when it is
11
11
  * rejected.
12
12
  */
13
- interface ChannelDelivery {
13
+ export interface ChannelDelivery {
14
14
  /** Whether the parse gate accepted the payload. */
15
15
  accepted: boolean;
16
16
  }
@@ -20,8 +20,8 @@ interface ChannelDelivery {
20
20
  * Returns whether the gate accepted it, so a test can assert a rejection
21
21
  * without knowing what the plugin's parsed shape looks like.
22
22
  */
23
- declare function driveChannel(channel: SessionChannelContribution, sessionId: string, payload: unknown): ChannelDelivery;
24
- interface HubChannelHarness {
23
+ export declare function driveChannel(channel: SessionChannelContribution, sessionId: string, payload: unknown): ChannelDelivery;
24
+ export interface HubChannelHarness {
25
25
  /** The running source, as the hub holds it. */
26
26
  source: HubChannelSource;
27
27
  /** Everything the source pushed, in order. */
@@ -35,7 +35,7 @@ interface HubChannelHarness {
35
35
  removeSession(sessionId: string): void;
36
36
  close(): void;
37
37
  }
38
- interface HubChannelHarnessOptions {
38
+ export interface HubChannelHarnessOptions {
39
39
  /** Sessions the hub already manages when the channel starts. */
40
40
  sessions?: readonly HubSessionScope[];
41
41
  }
@@ -46,7 +46,6 @@ interface HubChannelHarnessOptions {
46
46
  * afterwards, and a channel that only answers one of those looks correct in a
47
47
  * test that exercises the other.
48
48
  */
49
- declare function hubChannelHarness(channel: WebHubChannel, options?: HubChannelHarnessOptions): HubChannelHarness;
49
+ export declare function hubChannelHarness(channel: WebHubChannel, options?: HubChannelHarnessOptions): HubChannelHarness;
50
50
  //#endregion
51
- export { ChannelDelivery, HubChannelHarness, HubChannelHarnessOptions, driveChannel, hubChannelHarness };
52
51
  //# sourceMappingURL=channels.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"channels.d.mts","names":[],"sources":["../../../src/services/testing/channels.ts"],"mappings":";;;;;;;;;;;;UAmBiB;;EAEf;;;;;;;;iBASc,aACd,SAAS,4BACT,mBACA,mBACC;UAOc;;EAEf,QAAQ;;WAEC,oBAAoB;;WAEpB;;EAET,SAAS;;EAET,WAAW,OAAO;EAClB,cAAc;EACd;;UAGe;;EAEf,oBAAoB;;;;;;;;;iBAYN,kBAAkB,SAAS,eAAe,UAAS,2BAAgC"}
1
+ {"version":3,"file":"channels.d.mts","names":[],"sources":["../../../src/services/testing/channels.ts"],"mappings":";;;;;;;;;;;;iBAmBiB;;EAEf;;;;;;;;wBASc,aACd,SAAS,4BACT,mBACA,mBACC;iBAOc;;EAEf,QAAQ;;WAEC,oBAAoB;;WAEpB;;EAET,SAAS;;EAET,WAAW,OAAO;EAClB,cAAc;EACd;;iBAGe;;EAEf,oBAAoB;;;;;;;;;wBAYN,kBAAkB,SAAS,eAAe,UAAS,2BAAgC"}
@@ -1,2 +1,2 @@
1
- function e(e,t,n){let r=e.parse(n);return r===null?{accepted:!1}:(e.apply(t,r),{accepted:!0})}const t={sessionId:`s1`,cwd:`/repo`};function n(e,n={}){let r=[...n.sessions??[t]],i=[],a=[],o=e.start({sessions:()=>r,publish:(t,n)=>{i.push({type:e.frameType,sessionId:t,payload:n})},onNotice:e=>a.push(e)});return{source:o,published:i,notices:a,snapshot(e){let n=r.find(t=>t.sessionId===e)??r[0]??t;return o.payloadFor(n)},addSession(e){r.push(e),o.sessionAdded?.(e)},removeSession(e){let t=r.findIndex(t=>t.sessionId===e);t>=0&&r.splice(t,1),o.sessionRemoved?.(e)},close:()=>o.close()}}export{e as driveChannel,n as hubChannelHarness};
1
+ function e(e,t,n){let r=e.parse(n);return r===null?{accepted:!1}:(e.apply(t,r),{accepted:!0})}const t={sessionId:`s1`,cwd:`/repo`};function n(e,n={}){let r=[...n.sessions??[t]],i=[],a=[],o=e.start({sessions:()=>r,publish:(t,n)=>{i.push({type:e.frameType,sessionId:t,payload:n})},requestSessionApi:()=>Promise.resolve(Response.json({error:`No session API in the channel harness.`},{status:501})),onNotice:e=>a.push(e)});return{source:o,published:i,notices:a,snapshot(e){let n=r.find(t=>t.sessionId===e)??r[0]??t;return o.payloadFor(n)},addSession(e){r.push(e),o.sessionAdded?.(e)},removeSession(e){let t=r.findIndex(t=>t.sessionId===e);t>=0&&r.splice(t,1),o.sessionRemoved?.(e)},close:()=>o.close()}}export{e as driveChannel,n as hubChannelHarness};
2
2
  //# sourceMappingURL=channels.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"channels.mjs","names":[],"sources":["../../../src/services/testing/channels.ts"],"sourcesContent":["import type {\n ChannelFrame,\n HubChannelHost,\n HubChannelSource,\n HubSessionScope,\n WebHubChannel,\n} from '../../types/webHub.ts';\nimport type { SessionChannelContribution } from '../../types/webPlugin.ts';\n\n/**\n * The two halves of a plugin's data channel, driven the way the hub drives them.\n *\n * A channel is the one place a plugin parses input it did not produce, so its\n * parse gate is the boundary that matters, and a test that calls `apply`\n * directly steps straight over it. `driveChannel` sends a wire payload the way\n * the page does: through `parse` first, and nothing applied when it is\n * rejected.\n */\n\nexport interface ChannelDelivery {\n /** Whether the parse gate accepted the payload. */\n accepted: boolean;\n}\n\n/**\n * Sends one wire payload to a session channel.\n *\n * Returns whether the gate accepted it, so a test can assert a rejection\n * without knowing what the plugin's parsed shape looks like.\n */\nexport function driveChannel(\n channel: SessionChannelContribution,\n sessionId: string,\n payload: unknown,\n): ChannelDelivery {\n const parsed: unknown = channel.parse(payload);\n if (parsed === null) return { accepted: false };\n channel.apply(sessionId, parsed);\n return { accepted: true };\n}\n\nexport interface HubChannelHarness {\n /** The running source, as the hub holds it. */\n source: HubChannelSource;\n /** Everything the source pushed, in order. */\n readonly published: readonly ChannelFrame[];\n /** What the source told the hub. */\n readonly notices: readonly string[];\n /** The subscribe-time snapshot one session would receive; undefined means no frame. */\n snapshot(sessionId?: string): unknown;\n /** Registers a session with the source, as the hub does when one appears. */\n addSession(scope: HubSessionScope): void;\n removeSession(sessionId: string): void;\n close(): void;\n}\n\nexport interface HubChannelHarnessOptions {\n /** Sessions the hub already manages when the channel starts. */\n sessions?: readonly HubSessionScope[];\n}\n\nconst DEFAULT_SESSION: HubSessionScope = { sessionId: 's1', cwd: '/repo' };\n\n/**\n * A plugin's hub channel, started against a real host.\n *\n * The hub calls `payloadFor` once per subscriber and pushes through `publish`\n * afterwards, and a channel that only answers one of those looks correct in a\n * test that exercises the other.\n */\nexport function hubChannelHarness(channel: WebHubChannel, options: HubChannelHarnessOptions = {}): HubChannelHarness {\n const sessions = [...(options.sessions ?? [DEFAULT_SESSION])];\n const published: ChannelFrame[] = [];\n const notices: string[] = [];\n const host: HubChannelHost = {\n sessions: () => sessions,\n publish: (sessionId, payload) => {\n published.push({ type: channel.frameType, sessionId, payload });\n },\n onNotice: (message) => notices.push(message),\n };\n const source = channel.start(host);\n\n return {\n source,\n published,\n notices,\n snapshot(sessionId) {\n const scope = sessions.find((candidate) => candidate.sessionId === sessionId) ?? sessions[0] ?? DEFAULT_SESSION;\n return source.payloadFor(scope);\n },\n addSession(scope) {\n sessions.push(scope);\n source.sessionAdded?.(scope);\n },\n removeSession(sessionId) {\n const index = sessions.findIndex((candidate) => candidate.sessionId === sessionId);\n if (index >= 0) sessions.splice(index, 1);\n source.sessionRemoved?.(sessionId);\n },\n close: () => source.close(),\n };\n}\n"],"mappings":"AA8BA,SAAgB,EACd,EACA,EACA,EACiB,CACjB,IAAM,EAAkB,EAAQ,MAAM,CAAO,EAG7C,OAFI,IAAW,KAAa,CAAE,SAAU,EAAM,GAC9C,EAAQ,MAAM,EAAW,CAAM,EACxB,CAAE,SAAU,EAAK,EAC1B,CAsBA,MAAM,EAAmC,CAAE,UAAW,KAAM,IAAK,OAAQ,EASzE,SAAgB,EAAkB,EAAwB,EAAoC,CAAC,EAAsB,CACnH,IAAM,EAAW,CAAC,GAAI,EAAQ,UAAY,CAAC,CAAe,CAAE,EACtD,EAA4B,CAAC,EAC7B,EAAoB,CAAC,EAQrB,EAAS,EAAQ,MAAM,CAN3B,aAAgB,EAChB,SAAU,EAAW,IAAY,CAC/B,EAAU,KAAK,CAAE,KAAM,EAAQ,UAAW,YAAW,SAAQ,CAAC,CAChE,EACA,SAAW,GAAY,EAAQ,KAAK,CAAO,CAEb,CAAC,EAEjC,MAAO,CACL,SACA,YACA,UACA,SAAS,EAAW,CAClB,IAAM,EAAQ,EAAS,KAAM,GAAc,EAAU,YAAc,CAAS,GAAK,EAAS,IAAM,EAChG,OAAO,EAAO,WAAW,CAAK,CAChC,EACA,WAAW,EAAO,CAChB,EAAS,KAAK,CAAK,EACnB,EAAO,eAAe,CAAK,CAC7B,EACA,cAAc,EAAW,CACvB,IAAM,EAAQ,EAAS,UAAW,GAAc,EAAU,YAAc,CAAS,EAC7E,GAAS,GAAG,EAAS,OAAO,EAAO,CAAC,EACxC,EAAO,iBAAiB,CAAS,CACnC,EACA,UAAa,EAAO,MAAM,CAC5B,CACF"}
1
+ {"version":3,"file":"channels.mjs","names":[],"sources":["../../../src/services/testing/channels.ts"],"sourcesContent":["import type {\n ChannelFrame,\n HubChannelHost,\n HubChannelSource,\n HubSessionScope,\n WebHubChannel,\n} from '../../types/webHub.ts';\nimport type { SessionChannelContribution } from '../../types/webPlugin.ts';\n\n/**\n * The two halves of a plugin's data channel, driven the way the hub drives them.\n *\n * A channel is the one place a plugin parses input it did not produce, so its\n * parse gate is the boundary that matters, and a test that calls `apply`\n * directly steps straight over it. `driveChannel` sends a wire payload the way\n * the page does: through `parse` first, and nothing applied when it is\n * rejected.\n */\n\nexport interface ChannelDelivery {\n /** Whether the parse gate accepted the payload. */\n accepted: boolean;\n}\n\n/**\n * Sends one wire payload to a session channel.\n *\n * Returns whether the gate accepted it, so a test can assert a rejection\n * without knowing what the plugin's parsed shape looks like.\n */\nexport function driveChannel(\n channel: SessionChannelContribution,\n sessionId: string,\n payload: unknown,\n): ChannelDelivery {\n const parsed: unknown = channel.parse(payload);\n if (parsed === null) return { accepted: false };\n channel.apply(sessionId, parsed);\n return { accepted: true };\n}\n\nexport interface HubChannelHarness {\n /** The running source, as the hub holds it. */\n source: HubChannelSource;\n /** Everything the source pushed, in order. */\n readonly published: readonly ChannelFrame[];\n /** What the source told the hub. */\n readonly notices: readonly string[];\n /** The subscribe-time snapshot one session would receive; undefined means no frame. */\n snapshot(sessionId?: string): unknown;\n /** Registers a session with the source, as the hub does when one appears. */\n addSession(scope: HubSessionScope): void;\n removeSession(sessionId: string): void;\n close(): void;\n}\n\nexport interface HubChannelHarnessOptions {\n /** Sessions the hub already manages when the channel starts. */\n sessions?: readonly HubSessionScope[];\n}\n\nconst DEFAULT_SESSION: HubSessionScope = { sessionId: 's1', cwd: '/repo' };\n\n/**\n * A plugin's hub channel, started against a real host.\n *\n * The hub calls `payloadFor` once per subscriber and pushes through `publish`\n * afterwards, and a channel that only answers one of those looks correct in a\n * test that exercises the other.\n */\nexport function hubChannelHarness(channel: WebHubChannel, options: HubChannelHarnessOptions = {}): HubChannelHarness {\n const sessions = [...(options.sessions ?? [DEFAULT_SESSION])];\n const published: ChannelFrame[] = [];\n const notices: string[] = [];\n const host: HubChannelHost = {\n sessions: () => sessions,\n publish: (sessionId, payload) => {\n published.push({ type: channel.frameType, sessionId, payload });\n },\n requestSessionApi: () =>\n Promise.resolve(Response.json({ error: 'No session API in the channel harness.' }, { status: 501 })),\n onNotice: (message) => notices.push(message),\n };\n const source = channel.start(host);\n\n return {\n source,\n published,\n notices,\n snapshot(sessionId) {\n const scope = sessions.find((candidate) => candidate.sessionId === sessionId) ?? sessions[0] ?? DEFAULT_SESSION;\n return source.payloadFor(scope);\n },\n addSession(scope) {\n sessions.push(scope);\n source.sessionAdded?.(scope);\n },\n removeSession(sessionId) {\n const index = sessions.findIndex((candidate) => candidate.sessionId === sessionId);\n if (index >= 0) sessions.splice(index, 1);\n source.sessionRemoved?.(sessionId);\n },\n close: () => source.close(),\n };\n}\n"],"mappings":"AA8BA,SAAgB,EACd,EACA,EACA,EACiB,CACjB,IAAM,EAAkB,EAAQ,MAAM,CAAO,EAG7C,OAFI,IAAW,KAAa,CAAE,SAAU,EAAM,GAC9C,EAAQ,MAAM,EAAW,CAAM,EACxB,CAAE,SAAU,EAAK,EAC1B,CAsBA,MAAM,EAAmC,CAAE,UAAW,KAAM,IAAK,OAAQ,EASzE,SAAgB,EAAkB,EAAwB,EAAoC,CAAC,EAAsB,CACnH,IAAM,EAAW,CAAC,GAAI,EAAQ,UAAY,CAAC,CAAe,CAAE,EACtD,EAA4B,CAAC,EAC7B,EAAoB,CAAC,EAUrB,EAAS,EAAQ,MAAM,CAR3B,aAAgB,EAChB,SAAU,EAAW,IAAY,CAC/B,EAAU,KAAK,CAAE,KAAM,EAAQ,UAAW,YAAW,SAAQ,CAAC,CAChE,EACA,sBACE,QAAQ,QAAQ,SAAS,KAAK,CAAE,MAAO,wCAAyC,EAAG,CAAE,OAAQ,GAAI,CAAC,CAAC,EACrG,SAAW,GAAY,EAAQ,KAAK,CAAO,CAEb,CAAC,EAEjC,MAAO,CACL,SACA,YACA,UACA,SAAS,EAAW,CAClB,IAAM,EAAQ,EAAS,KAAM,GAAc,EAAU,YAAc,CAAS,GAAK,EAAS,IAAM,EAChG,OAAO,EAAO,WAAW,CAAK,CAChC,EACA,WAAW,EAAO,CAChB,EAAS,KAAK,CAAK,EACnB,EAAO,eAAe,CAAK,CAC7B,EACA,cAAc,EAAW,CACvB,IAAM,EAAQ,EAAS,UAAW,GAAc,EAAU,YAAc,CAAS,EAC7E,GAAS,GAAG,EAAS,OAAO,EAAO,CAAC,EACxC,EAAO,iBAAiB,CAAS,CACnC,EACA,UAAa,EAAO,MAAM,CAC5B,CACF"}
@@ -18,7 +18,7 @@ import { ComponentType } from "react";
18
18
  * Callers pass components as values, never as JSX, so a plugin package needs no
19
19
  * JSX configuration in the project that holds its tests.
20
20
  */
21
- interface RenderedPlugin {
21
+ export interface RenderedPlugin {
22
22
  /** The markup, or an empty string when the component threw. */
23
23
  html: string;
24
24
  /** What the component threw, which the host would have swallowed. */
@@ -26,7 +26,6 @@ interface RenderedPlugin {
26
26
  /** Whether the rendered markup contains this text, ignoring the tags around it. */
27
27
  includes(text: string): boolean;
28
28
  }
29
- declare function renderPlugin<Props extends object>(component: ComponentType<Props>, props: Props): RenderedPlugin;
29
+ export declare function renderPlugin<Props extends object>(component: ComponentType<Props>, props: Props): RenderedPlugin;
30
30
  //#endregion
31
- export { RenderedPlugin, renderPlugin };
32
31
  //# sourceMappingURL=render.d.cts.map
@@ -1 +1 @@
1
- {"version":3,"file":"render.d.cts","names":[],"sources":["../../../src/services/testing/render.ts"],"mappings":";;;;;;;;;;;;;;;;;;;;UAuBiB;;EAEf;;EAEA,OAAO;;EAEP,SAAS;;iBAWK,aAAa,sBAAsB,WAAW,cAAc,QAAQ,OAAO,QAAQ"}
1
+ {"version":3,"file":"render.d.cts","names":[],"sources":["../../../src/services/testing/render.ts"],"mappings":";;;;;;;;;;;;;;;;;;;;iBAuBiB;;EAEf;;EAEA,OAAO;;EAEP,SAAS;;wBAWK,aAAa,sBAAsB,WAAW,cAAc,QAAQ,OAAO,QAAQ"}
@@ -18,7 +18,7 @@ import { ComponentType } from "react";
18
18
  * Callers pass components as values, never as JSX, so a plugin package needs no
19
19
  * JSX configuration in the project that holds its tests.
20
20
  */
21
- interface RenderedPlugin {
21
+ export interface RenderedPlugin {
22
22
  /** The markup, or an empty string when the component threw. */
23
23
  html: string;
24
24
  /** What the component threw, which the host would have swallowed. */
@@ -26,7 +26,6 @@ interface RenderedPlugin {
26
26
  /** Whether the rendered markup contains this text, ignoring the tags around it. */
27
27
  includes(text: string): boolean;
28
28
  }
29
- declare function renderPlugin<Props extends object>(component: ComponentType<Props>, props: Props): RenderedPlugin;
29
+ export declare function renderPlugin<Props extends object>(component: ComponentType<Props>, props: Props): RenderedPlugin;
30
30
  //#endregion
31
- export { RenderedPlugin, renderPlugin };
32
31
  //# sourceMappingURL=render.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"render.d.mts","names":[],"sources":["../../../src/services/testing/render.ts"],"mappings":";;;;;;;;;;;;;;;;;;;;UAuBiB;;EAEf;;EAEA,OAAO;;EAEP,SAAS;;iBAWK,aAAa,sBAAsB,WAAW,cAAc,QAAQ,OAAO,QAAQ"}
1
+ {"version":3,"file":"render.d.mts","names":[],"sources":["../../../src/services/testing/render.ts"],"mappings":";;;;;;;;;;;;;;;;;;;;iBAuBiB;;EAEf;;EAEA,OAAO;;EAEP,SAAS;;wBAWK,aAAa,sBAAsB,WAAW,cAAc,QAAQ,OAAO,QAAQ"}
@@ -1,2 +1,2 @@
1
- function e(e={}){let t=[];return{props:{sessionId:e.sessionId===void 0?`s1`:e.sessionId,statuses:e.statuses??{},openTab:e=>{t.push({action:`openTab`,target:e})},openTransientTab:e=>{t.push({action:`openTransientTab`,target:e.id})},closeTransientTab:e=>{t.push({action:`closeTransientTab`,target:e})},sendSessionFrame:(e,n)=>{t.push({action:`sendSessionFrame`,target:e,frame:n})},renderThread:t=>e.thread?.(t)??null,renderSlot:t=>e.slotContent?.[t]??null,slotData:t=>e.slotData?.[t.slot]??[]},actions:t,frames:()=>t.flatMap(e=>e.frame?[e.frame]:[])}}function t(t){let n=e(t),r=t.result===void 0?null:t.result;return{...n,props:{...n.props,toolCallId:t.toolCallId??`call-1`,toolName:t.toolName,args:t.args??{},result:r,output:t.output??``,running:t.running??!1,isError:t.isError??!1}}}exports.slotPropsFixture=e,exports.toolMessagePropsFixture=t;
1
+ function e(e={}){let t=[],n={sessionId:e.sessionId===void 0?`s1`:e.sessionId,statuses:e.statuses??{},contextInventory:e.contextInventory??[],openTab:e=>{t.push({action:`openTab`,target:e})},openTransientTab:e=>{t.push({action:`openTransientTab`,target:e.id})},closeTransientTab:e=>{t.push({action:`closeTransientTab`,target:e})},fileTabFor:t=>e.fileTab?.(t),appendComposerDraft:e=>{t.push({action:`appendComposerDraft`,target:n.sessionId,text:e})},attachComposerContext:e=>{t.push({action:`attachComposerContext`,target:n.sessionId,context:e})},attachComposerCapture:e=>{t.push({action:`attachComposerCapture`,target:n.sessionId,capture:e})},contextActionsFor:t=>e.contextActions?.(t)??[],sendSessionFrame:(e,n)=>{t.push({action:`sendSessionFrame`,target:e,frame:n})},renderThread:(t,n)=>e.thread?.(t,n)??null,renderSlot:t=>e.slotContent?.[t]??null,slotData:t=>e.slotData?.[t.slot]??[]};return{props:n,actions:t,frames:()=>t.flatMap(e=>e.frame?[e.frame]:[])}}function t(t){let n=e(t),r=t.result===void 0?null:t.result;return{...n,props:{...n.props,toolCallId:t.toolCallId??`call-1`,toolName:t.toolName,args:t.args??{},result:r,output:t.output??``,running:t.running??!1,isError:t.isError??!1}}}exports.slotPropsFixture=e,exports.toolMessagePropsFixture=t;
2
2
  //# sourceMappingURL=slotProps.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"slotProps.cjs","names":[],"sources":["../../../src/services/testing/slotProps.ts"],"sourcesContent":["import type { ReactNode } from 'react';\nimport type {\n SlotDataFill,\n SlotDeclaration,\n ToolMessageRenderProps,\n ToolResultView,\n TransientTab,\n WebPluginSlotProps,\n} from '../../types/webPlugin.ts';\n\n/**\n * The props the cockpit hands a plugin's components, built for a test.\n *\n * A plugin component takes fifteen props and reads three of them. Written out\n * by hand in each test, the other twelve are noise that goes stale the moment\n * the contract grows a member; written as a cast, the component compiles\n * against props the host never sends. This builds all of them, records what the\n * component did with the actions, and lets a test override the two or three it\n * cares about.\n */\n\nexport interface RecordedSlotAction {\n action: 'openTab' | 'openTransientTab' | 'closeTransientTab' | 'sendSessionFrame';\n /** The tab id, the transient tab's id, or the target session of a frame. */\n target: string | null;\n /** The frame a component sent, for `sendSessionFrame`. */\n frame?: Record<string, unknown>;\n}\n\nexport interface SlotPropsFixture {\n props: WebPluginSlotProps;\n /** Everything the component did through its props, in order. */\n readonly actions: readonly RecordedSlotAction[];\n /** Frames the component sent, which is what most assertions want. */\n frames(): readonly Record<string, unknown>[];\n}\n\nexport interface SlotPropsOptions {\n sessionId?: string | null;\n statuses?: Readonly<Record<string, string>>;\n /** Component fills this slot owner should see; keyed by slot name. */\n slotContent?: Readonly<Record<string, ReactNode>>;\n /** Data fills this slot owner should read back, keyed by slot name. */\n slotData?: Readonly<Record<string, readonly SlotDataFill[]>>;\n /** What `renderThread` returns for a plugin that renders one. */\n thread?: (threadId: string) => ReactNode;\n}\n\nconst DEFAULT_SESSION_ID = 's1';\n\nexport function slotPropsFixture(options: SlotPropsOptions = {}): SlotPropsFixture {\n const actions: RecordedSlotAction[] = [];\n const props: WebPluginSlotProps = {\n sessionId: options.sessionId === undefined ? DEFAULT_SESSION_ID : options.sessionId,\n statuses: options.statuses ?? {},\n openTab: (tabId) => {\n actions.push({ action: 'openTab', target: tabId });\n },\n openTransientTab: (tab: TransientTab) => {\n actions.push({ action: 'openTransientTab', target: tab.id });\n },\n closeTransientTab: (tabId: string) => {\n actions.push({ action: 'closeTransientTab', target: tabId });\n },\n sendSessionFrame: (sessionId, frame) => {\n actions.push({ action: 'sendSessionFrame', target: sessionId, frame });\n },\n renderThread: (threadId) => options.thread?.(threadId) ?? null,\n renderSlot: (slot) => options.slotContent?.[slot] ?? null,\n // The host resolves fills by slot name and hands the owner its own typed\n // view, so a test declares them by name too.\n slotData: <Data>(slot: SlotDeclaration<Data>) =>\n (options.slotData?.[slot.slot] ?? []) as readonly SlotDataFill<Data>[],\n };\n\n return {\n props,\n actions,\n frames: () => actions.flatMap((entry) => (entry.frame ? [entry.frame] : [])),\n };\n}\n\nexport interface ToolMessagePropsOptions extends SlotPropsOptions {\n toolCallId?: string;\n toolName: string;\n args?: Record<string, unknown>;\n /** The newest result; null is what the host sends before any output. */\n result?: ToolResultView | null;\n /** The result's text blocks joined, as the host's own fallback item shows them. */\n output?: string;\n running?: boolean;\n isError?: boolean;\n}\n\nexport interface ToolMessagePropsFixture extends Omit<SlotPropsFixture, 'props'> {\n props: ToolMessageRenderProps;\n}\n\nconst DEFAULT_TOOL_CALL_ID = 'call-1';\n\n/** The props a tool's timeline item receives, in any of its four states. */\nexport function toolMessagePropsFixture(options: ToolMessagePropsOptions): ToolMessagePropsFixture {\n const base = slotPropsFixture(options);\n const result = options.result === undefined ? null : options.result;\n return {\n ...base,\n props: {\n ...base.props,\n toolCallId: options.toolCallId ?? DEFAULT_TOOL_CALL_ID,\n toolName: options.toolName,\n args: options.args ?? {},\n result,\n output: options.output ?? '',\n running: options.running ?? false,\n isError: options.isError ?? false,\n },\n };\n}\n"],"mappings":"AAkDA,SAAgB,EAAiB,EAA4B,CAAC,EAAqB,CACjF,IAAM,EAAgC,CAAC,EAwBvC,MAAO,CACL,MAAA,CAvBA,UAAW,EAAQ,YAAc,IAAA,GAAY,KAAqB,EAAQ,UAC1E,SAAU,EAAQ,UAAY,CAAC,EAC/B,QAAU,GAAU,CAClB,EAAQ,KAAK,CAAE,OAAQ,UAAW,OAAQ,CAAM,CAAC,CACnD,EACA,iBAAmB,GAAsB,CACvC,EAAQ,KAAK,CAAE,OAAQ,mBAAoB,OAAQ,EAAI,EAAG,CAAC,CAC7D,EACA,kBAAoB,GAAkB,CACpC,EAAQ,KAAK,CAAE,OAAQ,oBAAqB,OAAQ,CAAM,CAAC,CAC7D,EACA,kBAAmB,EAAW,IAAU,CACtC,EAAQ,KAAK,CAAE,OAAQ,mBAAoB,OAAQ,EAAW,OAAM,CAAC,CACvE,EACA,aAAe,GAAa,EAAQ,SAAS,CAAQ,GAAK,KAC1D,WAAa,GAAS,EAAQ,cAAc,IAAS,KAGrD,SAAiB,GACd,EAAQ,WAAW,EAAK,OAAS,CAAC,CAIjC,EACJ,UACA,WAAc,EAAQ,QAAS,GAAW,EAAM,MAAQ,CAAC,EAAM,KAAK,EAAI,CAAC,CAAE,CAC7E,CACF,CAqBA,SAAgB,EAAwB,EAA2D,CACjG,IAAM,EAAO,EAAiB,CAAO,EAC/B,EAAS,EAAQ,SAAW,IAAA,GAAY,KAAO,EAAQ,OAC7D,MAAO,CACL,GAAG,EACH,MAAO,CACL,GAAG,EAAK,MACR,WAAY,EAAQ,YAAc,SAClC,SAAU,EAAQ,SAClB,KAAM,EAAQ,MAAQ,CAAC,EACvB,SACA,OAAQ,EAAQ,QAAU,GAC1B,QAAS,EAAQ,SAAW,GAC5B,QAAS,EAAQ,SAAW,EAC9B,CACF,CACF"}
1
+ {"version":3,"file":"slotProps.cjs","names":[],"sources":["../../../src/services/testing/slotProps.ts"],"sourcesContent":["import type { ReactNode } from 'react';\nimport type {\n ComposerCapture,\n ContextAction,\n SlotDataFill,\n SlotDeclaration,\n ThreadViewOptions,\n ToolMessageRenderProps,\n ToolResultView,\n TransientTab,\n WebPluginContextItem,\n WebPluginSlotProps,\n} from '../../types/webPlugin.ts';\n\n/**\n * The props the cockpit hands a plugin's components, built for a test.\n *\n * A plugin component takes fifteen props and reads three of them. Written out\n * by hand in each test, the other twelve are noise that goes stale the moment\n * the contract grows a member; written as a cast, the component compiles\n * against props the host never sends. This builds all of them, records what the\n * component did with the actions, and lets a test override the two or three it\n * cares about.\n */\n\nexport interface RecordedSlotAction {\n action:\n | 'appendComposerDraft'\n | 'attachComposerCapture'\n | 'attachComposerContext'\n | 'openTab'\n | 'openTransientTab'\n | 'closeTransientTab'\n | 'sendSessionFrame';\n /** The tab id, the transient tab's id, or the target session of a frame or composer action. */\n target: string | null;\n /** The text passed to `appendComposerDraft`. */\n text?: string;\n /** The structured item passed to `attachComposerContext`. */\n context?: WebPluginContextItem;\n /** The atomic screenshot and context passed to `attachComposerCapture`. */\n capture?: ComposerCapture;\n /** The frame a component sent, for `sendSessionFrame`. */\n frame?: Record<string, unknown>;\n}\n\nexport interface SlotPropsFixture {\n props: WebPluginSlotProps;\n /** Everything the component did through its props, in order. */\n readonly actions: readonly RecordedSlotAction[];\n /** Frames the component sent, which is what most assertions want. */\n frames(): readonly Record<string, unknown>[];\n}\n\nexport interface SlotPropsOptions {\n sessionId?: string | null;\n statuses?: Readonly<Record<string, string>>;\n contextInventory?: WebPluginSlotProps['contextInventory'];\n /** Component fills this slot owner should see; keyed by slot name. */\n slotContent?: Readonly<Record<string, ReactNode>>;\n /** Data fills this slot owner should read back, keyed by slot name. */\n slotData?: Readonly<Record<string, readonly SlotDataFill[]>>;\n /** What `renderThread` returns for a plugin that renders one. */\n thread?: (threadId: string, options?: ThreadViewOptions) => ReactNode;\n /** The tab a path opens; by default no path opens one, as with no file plugin installed. */\n fileTab?: (path: string) => TransientTab | undefined;\n /** Context actions installed plugins should offer for the item under test. */\n contextActions?: (item: WebPluginContextItem) => readonly ContextAction[];\n}\n\nconst DEFAULT_SESSION_ID = 's1';\n\nexport function slotPropsFixture(options: SlotPropsOptions = {}): SlotPropsFixture {\n const actions: RecordedSlotAction[] = [];\n const props: WebPluginSlotProps = {\n sessionId: options.sessionId === undefined ? DEFAULT_SESSION_ID : options.sessionId,\n statuses: options.statuses ?? {},\n contextInventory: options.contextInventory ?? [],\n openTab: (tabId) => {\n actions.push({ action: 'openTab', target: tabId });\n },\n openTransientTab: (tab: TransientTab) => {\n actions.push({ action: 'openTransientTab', target: tab.id });\n },\n closeTransientTab: (tabId: string) => {\n actions.push({ action: 'closeTransientTab', target: tabId });\n },\n fileTabFor: (path: string) => options.fileTab?.(path),\n appendComposerDraft: (text) => {\n actions.push({ action: 'appendComposerDraft', target: props.sessionId, text });\n },\n attachComposerContext: (context) => {\n actions.push({ action: 'attachComposerContext', target: props.sessionId, context });\n },\n attachComposerCapture: (capture) => {\n actions.push({ action: 'attachComposerCapture', target: props.sessionId, capture });\n },\n contextActionsFor: (item) => options.contextActions?.(item) ?? [],\n sendSessionFrame: (sessionId, frame) => {\n actions.push({ action: 'sendSessionFrame', target: sessionId, frame });\n },\n renderThread: (threadId, threadOptions) => options.thread?.(threadId, threadOptions) ?? null,\n renderSlot: (slot) => options.slotContent?.[slot] ?? null,\n // The host resolves fills by slot name and hands the owner its own typed\n // view, so a test declares them by name too.\n slotData: <Data>(slot: SlotDeclaration<Data>) =>\n (options.slotData?.[slot.slot] ?? []) as readonly SlotDataFill<Data>[],\n };\n\n return {\n props,\n actions,\n frames: () => actions.flatMap((entry) => (entry.frame ? [entry.frame] : [])),\n };\n}\n\nexport interface ToolMessagePropsOptions extends SlotPropsOptions {\n toolCallId?: string;\n toolName: string;\n args?: Record<string, unknown>;\n /** The newest result; null is what the host sends before any output. */\n result?: ToolResultView | null;\n /** The result's text blocks joined, as the host's own fallback item shows them. */\n output?: string;\n running?: boolean;\n isError?: boolean;\n}\n\nexport interface ToolMessagePropsFixture extends Omit<SlotPropsFixture, 'props'> {\n props: ToolMessageRenderProps;\n}\n\nconst DEFAULT_TOOL_CALL_ID = 'call-1';\n\n/** The props a tool's timeline item receives, in any of its four states. */\nexport function toolMessagePropsFixture(options: ToolMessagePropsOptions): ToolMessagePropsFixture {\n const base = slotPropsFixture(options);\n const result = options.result === undefined ? null : options.result;\n return {\n ...base,\n props: {\n ...base.props,\n toolCallId: options.toolCallId ?? DEFAULT_TOOL_CALL_ID,\n toolName: options.toolName,\n args: options.args ?? {},\n result,\n output: options.output ?? '',\n running: options.running ?? false,\n isError: options.isError ?? false,\n },\n };\n}\n"],"mappings":"AAwEA,SAAgB,EAAiB,EAA4B,CAAC,EAAqB,CACjF,IAAM,EAAgC,CAAC,EACjC,EAA4B,CAChC,UAAW,EAAQ,YAAc,IAAA,GAAY,KAAqB,EAAQ,UAC1E,SAAU,EAAQ,UAAY,CAAC,EAC/B,iBAAkB,EAAQ,kBAAoB,CAAC,EAC/C,QAAU,GAAU,CAClB,EAAQ,KAAK,CAAE,OAAQ,UAAW,OAAQ,CAAM,CAAC,CACnD,EACA,iBAAmB,GAAsB,CACvC,EAAQ,KAAK,CAAE,OAAQ,mBAAoB,OAAQ,EAAI,EAAG,CAAC,CAC7D,EACA,kBAAoB,GAAkB,CACpC,EAAQ,KAAK,CAAE,OAAQ,oBAAqB,OAAQ,CAAM,CAAC,CAC7D,EACA,WAAa,GAAiB,EAAQ,UAAU,CAAI,EACpD,oBAAsB,GAAS,CAC7B,EAAQ,KAAK,CAAE,OAAQ,sBAAuB,OAAQ,EAAM,UAAW,MAAK,CAAC,CAC/E,EACA,sBAAwB,GAAY,CAClC,EAAQ,KAAK,CAAE,OAAQ,wBAAyB,OAAQ,EAAM,UAAW,SAAQ,CAAC,CACpF,EACA,sBAAwB,GAAY,CAClC,EAAQ,KAAK,CAAE,OAAQ,wBAAyB,OAAQ,EAAM,UAAW,SAAQ,CAAC,CACpF,EACA,kBAAoB,GAAS,EAAQ,iBAAiB,CAAI,GAAK,CAAC,EAChE,kBAAmB,EAAW,IAAU,CACtC,EAAQ,KAAK,CAAE,OAAQ,mBAAoB,OAAQ,EAAW,OAAM,CAAC,CACvE,EACA,cAAe,EAAU,IAAkB,EAAQ,SAAS,EAAU,CAAa,GAAK,KACxF,WAAa,GAAS,EAAQ,cAAc,IAAS,KAGrD,SAAiB,GACd,EAAQ,WAAW,EAAK,OAAS,CAAC,CACvC,EAEA,MAAO,CACL,QACA,UACA,WAAc,EAAQ,QAAS,GAAW,EAAM,MAAQ,CAAC,EAAM,KAAK,EAAI,CAAC,CAAE,CAC7E,CACF,CAqBA,SAAgB,EAAwB,EAA2D,CACjG,IAAM,EAAO,EAAiB,CAAO,EAC/B,EAAS,EAAQ,SAAW,IAAA,GAAY,KAAO,EAAQ,OAC7D,MAAO,CACL,GAAG,EACH,MAAO,CACL,GAAG,EAAK,MACR,WAAY,EAAQ,YAAc,SAClC,SAAU,EAAQ,SAClB,KAAM,EAAQ,MAAQ,CAAC,EACvB,SACA,OAAQ,EAAQ,QAAU,GAC1B,QAAS,EAAQ,SAAW,GAC5B,QAAS,EAAQ,SAAW,EAC9B,CACF,CACF"}