@agimon-ai/doompi-minor-mode 0.0.1-alpha.100

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 (103) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +3 -0
  3. package/dist/apiContracts.cjs +17 -0
  4. package/dist/apiContracts.cjs.map +1 -0
  5. package/dist/apiContracts.d.mts +53 -0
  6. package/dist/apiContracts.d.mts.map +1 -0
  7. package/dist/apiContracts.mjs +13 -0
  8. package/dist/apiContracts.mjs.map +1 -0
  9. package/dist/catalog-8apySKXB.mjs +222 -0
  10. package/dist/catalog-8apySKXB.mjs.map +1 -0
  11. package/dist/catalog-jTd7UXiI.cjs +227 -0
  12. package/dist/catalog-jTd7UXiI.cjs.map +1 -0
  13. package/dist/catalog.cjs +3 -0
  14. package/dist/catalog.d.mts +14 -0
  15. package/dist/catalog.d.mts.map +1 -0
  16. package/dist/catalog.mjs +2 -0
  17. package/dist/command-B5HZmmyU.cjs +11 -0
  18. package/dist/command-B5HZmmyU.cjs.map +1 -0
  19. package/dist/command-BvYpwiin.mjs +6 -0
  20. package/dist/command-BvYpwiin.mjs.map +1 -0
  21. package/dist/command-C4u3oOPT.mjs +128 -0
  22. package/dist/command-C4u3oOPT.mjs.map +1 -0
  23. package/dist/command-D9hQfJb_.cjs +151 -0
  24. package/dist/command-D9hQfJb_.cjs.map +1 -0
  25. package/dist/command.cjs +8 -0
  26. package/dist/command.d.mts +6 -0
  27. package/dist/command.d.mts.map +1 -0
  28. package/dist/command.mjs +3 -0
  29. package/dist/extensions/pi.cjs +181 -0
  30. package/dist/extensions/pi.cjs.map +1 -0
  31. package/dist/extensions/pi.d.mts +5 -0
  32. package/dist/extensions/pi.d.mts.map +1 -0
  33. package/dist/extensions/pi.mjs +176 -0
  34. package/dist/extensions/pi.mjs.map +1 -0
  35. package/dist/extensions/server.cjs +134 -0
  36. package/dist/extensions/server.cjs.map +1 -0
  37. package/dist/extensions/server.d.mts +5 -0
  38. package/dist/extensions/server.d.mts.map +1 -0
  39. package/dist/extensions/server.mjs +129 -0
  40. package/dist/extensions/server.mjs.map +1 -0
  41. package/dist/headlessCommand-BJhocUje.mjs +53 -0
  42. package/dist/headlessCommand-BJhocUje.mjs.map +1 -0
  43. package/dist/headlessCommand-CaFFcvJA.cjs +58 -0
  44. package/dist/headlessCommand-CaFFcvJA.cjs.map +1 -0
  45. package/dist/index-COS4uLcb.d.mts +24 -0
  46. package/dist/index-COS4uLcb.d.mts.map +1 -0
  47. package/dist/index-DEjyk6tg.d.mts +8 -0
  48. package/dist/index-DEjyk6tg.d.mts.map +1 -0
  49. package/dist/index-DSKnT657.d.mts +31 -0
  50. package/dist/index-DSKnT657.d.mts.map +1 -0
  51. package/dist/index.cjs +180 -0
  52. package/dist/index.cjs.map +1 -0
  53. package/dist/index.d.mts +53 -0
  54. package/dist/index.d.mts.map +1 -0
  55. package/dist/index.mjs +136 -0
  56. package/dist/index.mjs.map +1 -0
  57. package/dist/minorModeCommand.cjs +5 -0
  58. package/dist/minorModeCommand.d.mts +2 -0
  59. package/dist/minorModeCommand.mjs +2 -0
  60. package/dist/mode-BwRkDqO4.mjs +241 -0
  61. package/dist/mode-BwRkDqO4.mjs.map +1 -0
  62. package/dist/mode-Dft08ke8.cjs +444 -0
  63. package/dist/mode-Dft08ke8.cjs.map +1 -0
  64. package/dist/mode-EZWqhrYy.d.mts +492 -0
  65. package/dist/mode-EZWqhrYy.d.mts.map +1 -0
  66. package/dist/mode.cjs +36 -0
  67. package/dist/mode.d.mts +2 -0
  68. package/dist/mode.mjs +2 -0
  69. package/dist/modeDefinition-BcqEwTzh.mjs +46 -0
  70. package/dist/modeDefinition-BcqEwTzh.mjs.map +1 -0
  71. package/dist/modeDefinition-BtgwqXMo.cjs +51 -0
  72. package/dist/modeDefinition-BtgwqXMo.cjs.map +1 -0
  73. package/dist/modeDefinition.cjs +3 -0
  74. package/dist/modeDefinition.d.mts +2 -0
  75. package/dist/modeDefinition.mjs +2 -0
  76. package/dist/owner-BbCQufLu.cjs +14 -0
  77. package/dist/owner-BbCQufLu.cjs.map +1 -0
  78. package/dist/owner-Bs55c_qE.mjs +9 -0
  79. package/dist/owner-Bs55c_qE.mjs.map +1 -0
  80. package/dist/owner.cjs +3 -0
  81. package/dist/owner.d.mts +2 -0
  82. package/dist/owner.mjs +2 -0
  83. package/dist/projection-Cy1LWVIe.mjs +47 -0
  84. package/dist/projection-Cy1LWVIe.mjs.map +1 -0
  85. package/dist/projection-DYOm9Kev.cjs +58 -0
  86. package/dist/projection-DYOm9Kev.cjs.map +1 -0
  87. package/dist/projection.cjs +4 -0
  88. package/dist/projection.d.mts +12 -0
  89. package/dist/projection.d.mts.map +1 -0
  90. package/dist/projection.mjs +2 -0
  91. package/dist/reloadHandoff-C-GaCf0F.cjs +71 -0
  92. package/dist/reloadHandoff-C-GaCf0F.cjs.map +1 -0
  93. package/dist/reloadHandoff-D1QsS9qd.mjs +54 -0
  94. package/dist/reloadHandoff-D1QsS9qd.mjs.map +1 -0
  95. package/dist/reloadHandoff.cjs +5 -0
  96. package/dist/reloadHandoff.d.mts +11 -0
  97. package/dist/reloadHandoff.d.mts.map +1 -0
  98. package/dist/reloadHandoff.mjs +2 -0
  99. package/dist/validation-BuQc8UrL.mjs +81 -0
  100. package/dist/validation-BuQc8UrL.mjs.map +1 -0
  101. package/dist/validation-DRV8Dtoc.cjs +104 -0
  102. package/dist/validation-DRV8Dtoc.cjs.map +1 -0
  103. package/package.json +157 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pi.cjs","names":["MINOR_MODE_COMMAND","MINOR_MODE_COMMAND_DESCRIPTION","executeMinorModeCommand","readDoomNotificationService","DOOM_CORDIS_SESSION_SERVICE","DOOM_TRANSITION_SERVICE","requireDoomTransitionCoordinator","consumeMinorModeReloadHandoff","createMinorModeCatalogHost","DOOM_MINOR_MODE_CATALOG_SERVICE","projectMinorModes","DOOM_MINOR_MODE_ENTRY_TYPE","defineRoot","definePiExtension","rootSession","composeRootHooks"],"sources":["../../src/extensions/workspaces/sessions/(backend)/_lib/minorModeCommand.ts","../../src/extensions/workspaces/sessions/(backend)/_lib/catalogRuntime.ts","../../src/extensions/workspaces/sessions/(backend)/root.cli.ts","../../generated/pi.ts"],"sourcesContent":["import type { ExtensionAPI, ExtensionContext } from '@earendil-works/pi-coding-agent';\n\nimport type { MinorModeCatalogService, MinorModeSessionKind } from '../../../../../schemas/mode';\nimport {\n executeMinorModeCommand,\n MINOR_MODE_COMMAND,\n MINOR_MODE_COMMAND_DESCRIPTION,\n} from '../../../../../services/command';\n\nfunction sessionKindOf(ctx: ExtensionContext): MinorModeSessionKind {\n return ctx.hasUI && ctx.mode === 'tui' ? 'tui' : 'headless';\n}\n\n/** Register the Pi prompt adapter for the shared minor-mode command behavior. */\nexport function registerMinorModeCommand(\n pi: ExtensionAPI,\n currentCatalog: () => MinorModeCatalogService | undefined,\n): void {\n pi.registerCommand(MINOR_MODE_COMMAND, {\n description: MINOR_MODE_COMMAND_DESCRIPTION,\n getArgumentCompletions: (prefix) => {\n const query = prefix.trim().toLowerCase();\n const records = currentCatalog()?.list() ?? [];\n return records\n .map((record) => record.descriptor.label.toLowerCase())\n .filter((label) => label.startsWith(query))\n .map((label) => ({ value: label, label }));\n },\n handler: (args, ctx) =>\n executeMinorModeCommand(args, {\n catalog: currentCatalog(),\n kind: sessionKindOf(ctx),\n ui: {\n select: (title, options) => ctx.ui.select(title, [...options]),\n input: (title, message) => ctx.ui.input(title, message),\n confirm: (title, message) => ctx.ui.confirm(title, message),\n notify: (message, level) => ctx.ui.notify(message, level),\n },\n }),\n });\n}\n","import { DOOM_CORDIS_SESSION_SERVICE, type DoomCordisSessionService } from '@agimon-ai/doompi-core/cordisHost';\nimport { type DoomNotificationLevel, readDoomNotificationService } from '@agimon-ai/doompi-core/notification';\nimport type { PiPluginContributions } from '@agimon-ai/doompi-core/piExtension';\nimport {\n DOOM_TRANSITION_SERVICE,\n requireDoomTransitionCoordinator,\n type TransitionSource,\n} from '@agimon-ai/doompi-core/transition';\nimport type { Context } from '@deepseek-ai/cordis';\nimport type { ExtensionAPI, ExtensionContext } from '@earendil-works/pi-coding-agent';\n\nimport {\n DOOM_MINOR_MODE_CATALOG_SERVICE,\n DOOM_MINOR_MODE_ENTRY_TYPE,\n type MinorModeActionResponse,\n type MinorModeCatalogService,\n} from '../../../../../schemas/mode';\nimport { createMinorModeCatalogHost } from '../../../../../services/catalog';\nimport { projectMinorModes } from '../../../../../services/projection';\nimport { consumeMinorModeReloadHandoff, discardMinorModeReloadHandoff } from '../../../../../services/reloadHandoff';\nimport { registerMinorModeCommand } from './minorModeCommand';\n\n/** Registrations and state flips arrive in bursts; one entry covers a burst. */\nconst PROJECTION_SETTLE_MS = 50;\n/**\n * Pi's rpc mode subscribes to session events only after bindExtensions()\n * returns, which is after session_start has run, so an entry journaled during\n * startup never reaches a client. A publish deferred past that point does.\n */\nconst BOOT_PUBLISH_DELAY_MS = 500;\n\ninterface CatalogBinding {\n current: MinorModeCatalogService | undefined;\n /** Journals the projection even if unchanged; set while a session is bound. */\n republish?: () => void;\n /**\n * The bound session, which the detail store is keyed by.\n *\n * The server launches the agent with `--session-id`, so this is the same id\n * the cockpit and the session API know the session by, and a browser asking\n * for a row's detail looks under the file this session wrote.\n */\n sessionId?: string;\n}\n\nfunction notify(cordis: Context, context: ExtensionContext, body: string, level: DoomNotificationLevel): void {\n const service = readDoomNotificationService(cordis);\n if (service) {\n try {\n void Promise.resolve(service.request({ body, level })).catch(() => undefined);\n } catch {\n // Notification delivery is best effort and does not fall back after routing.\n }\n return;\n }\n context.ui.notify(body, level);\n}\n\nfunction transitionSource(requesterSource: string): TransitionSource {\n if (requesterSource.includes('voice')) return 'voice';\n if (requesterSource.includes('leader')) return 'leader';\n if (requesterSource.includes('ui')) return 'ui';\n return 'system';\n}\n\n/**\n * The minor modes that are actually on, for the composition panel.\n *\n * Read from the bound catalog at publish time rather than passed in, because a\n * mode switching on is one of the reasons a publish happens at all, and a\n * remembered list would describe the composition before the switch.\n */\nexport function createMinorModePiRuntime(pi: ExtensionAPI): PiPluginContributions {\n // The command outlives any one session: it is registered once and reads the\n // catalog binding the session-scoped inject below sets and clears.\n const activeCatalog: CatalogBinding = { current: undefined };\n registerMinorModeCommand(pi, () => activeCatalog.current);\n // The composition is only complete once every extension has registered, so\n // the inventory is read on the same deferred tick the catalog republishes on.\n pi.on('session_start', () => {\n setTimeout(() => {\n activeCatalog.republish?.();\n }, BOOT_PUBLISH_DELAY_MS);\n });\n return { services: [(cordis: Context) => modeCatalogPlugin(cordis, pi, activeCatalog)] };\n}\n\nfunction modeCatalogPlugin(\n cordis: Context,\n pi: Pick<ExtensionAPI, 'appendEntry'>,\n activeCatalog: CatalogBinding,\n): void {\n cordis.inject([DOOM_CORDIS_SESSION_SERVICE, DOOM_TRANSITION_SERVICE], (sessionContext) => {\n const session = sessionContext.get(DOOM_CORDIS_SESSION_SERVICE) as DoomCordisSessionService;\n const context = session.context;\n const coordinator = requireDoomTransitionCoordinator(sessionContext);\n const reloadSession = session.reason === 'reload';\n const sessionId = session.sessionId;\n const restoreSnapshot = reloadSession ? consumeMinorModeReloadHandoff(sessionId) : undefined;\n if (!reloadSession) discardMinorModeReloadHandoff(sessionId);\n const sessionKind = context.hasUI && context.mode === 'tui' ? 'tui' : 'headless';\n const catalog: MinorModeCatalogService = createMinorModeCatalogHost({\n sessionKind,\n context,\n restoreSnapshot,\n onRestorationError(error) {\n notify(\n sessionContext,\n context,\n `Could not restore a minor mode after reload: ${error instanceof Error ? error.message : String(error)}`,\n 'warning',\n );\n },\n async routeInvocation(request, requesterSource, invoke) {\n let response: MinorModeActionResponse | undefined;\n const result = await coordinator.execute(\n {\n sessionId: context.sessionManager.getSessionId(),\n hostGeneration: coordinator.hostGeneration,\n operationId: request.operationId,\n source: transitionSource(requesterSource),\n target: { axis: 'live', capability: 'minor-mode' },\n },\n async () => {\n response = await invoke();\n return 'applied';\n },\n );\n if (result.outcome !== 'applied' || !response) {\n throw new Error(`Minor-mode transition was ${result.outcome}: ${result.diagnostics.join(', ')}`);\n }\n return response;\n },\n });\n sessionContext.plugin((providerContext) => {\n providerContext.provide(DOOM_MINOR_MODE_CATALOG_SERVICE, catalog);\n });\n activeCatalog.current = catalog;\n activeCatalog.sessionId = sessionId;\n\n // Journal the projection so RPC clients see catalog state live and on\n // replay; identical projections are skipped so detail churn stays cheap.\n let published: string | undefined;\n let settle: NodeJS.Timeout | undefined;\n const publish = (): void => {\n settle = undefined;\n const projection = projectMinorModes(catalog.getSnapshot(), sessionKind);\n const serialized = JSON.stringify(projection);\n if (serialized === published) return;\n published = serialized;\n pi.appendEntry(DOOM_MINOR_MODE_ENTRY_TYPE, projection);\n // A mode changing is the usual reason the toolbox changed too.\n };\n const unsubscribe = catalog.subscribe(() => {\n settle ??= setTimeout(publish, PROJECTION_SETTLE_MS);\n });\n activeCatalog.republish = () => {\n published = undefined;\n publish();\n };\n\n return () => {\n if (settle) clearTimeout(settle);\n unsubscribe();\n activeCatalog.republish = undefined;\n activeCatalog.current = undefined;\n activeCatalog.sessionId = undefined;\n catalog.dispose();\n };\n });\n}\n","import { defineRoot } from '@agimon-ai/doompi-core/extensionFile';\nimport type { PiPluginContext } from '@agimon-ai/doompi-core/piExtension';\n\nimport { createMinorModePiRuntime } from './_lib/catalogRuntime';\nexport default defineRoot(({ pi }: PiPluginContext) => {\n const runtime = createMinorModePiRuntime(pi);\n return { value: runtime, services: runtime.services, onStop: runtime.onStop, onDispose: runtime.onDispose };\n});\n","// Generated by @agimon-ai/doompi-build. Do not edit by hand.\nimport { definePiExtension, type PiPluginContext } from '@agimon-ai/doompi-core/piExtension';\nimport { composeRootHooks } from '@agimon-ai/doompi-core/extensionFile';\n\nimport rootSession from '../src/extensions/workspaces/sessions/(backend)/root.cli';\n\ntype OptionsOf<T> = T extends (context: PiPluginContext<infer Options>) => unknown ? Options : never;\ntype InferredOptions = Exclude<OptionsOf<typeof rootSession>, undefined>;\ntype Intersect<Union> =\n (Union extends unknown ? (value: Union) => void : never) extends (value: infer Value) => void ? Value : never;\ntype ExtensionOptions = [InferredOptions] extends [never] ? undefined : Intersect<InferredOptions>;\n\nexport const extension = definePiExtension<ExtensionOptions>('@agimon-ai/doompi-minor-mode', async (context) => {\n const scopeSession = await rootSession(context);\n return {\n ...composeRootHooks(scopeSession),\n services: [...(scopeSession.services ?? [])],\n };\n});\n\nexport default extension;\n"],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ //#region generated/pi.d.ts
2
+ export declare const extension: import("@agimon-ai/doompi-core/runtimePiExtension").DefinedPiExtension<undefined>;
3
+ //#endregion
4
+ export { extension as default };
5
+ //# sourceMappingURL=pi.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pi.d.mts","names":[],"sources":["../../generated/pi.ts"],"mappings":";qBAYa,+DAAS"}
@@ -0,0 +1,176 @@
1
+ import { n as DOOM_MINOR_MODE_ENTRY_TYPE, t as DOOM_MINOR_MODE_CATALOG_SERVICE } from "../mode-BwRkDqO4.mjs";
2
+ import { t as createMinorModeCatalogHost } from "../catalog-8apySKXB.mjs";
3
+ import { t as MINOR_MODE_COMMAND_DESCRIPTION } from "../command-BvYpwiin.mjs";
4
+ import { r as executeMinorModeCommand, t as MINOR_MODE_COMMAND } from "../command-C4u3oOPT.mjs";
5
+ import { t as projectMinorModes } from "../projection-Cy1LWVIe.mjs";
6
+ import { n as discardMinorModeReloadHandoff, t as consumeMinorModeReloadHandoff } from "../reloadHandoff-D1QsS9qd.mjs";
7
+ import { definePiExtension } from "@agimon-ai/doompi-core/piExtension";
8
+ import { composeRootHooks, defineRoot } from "@agimon-ai/doompi-core/extensionFile";
9
+ import { DOOM_CORDIS_SESSION_SERVICE } from "@agimon-ai/doompi-core/cordisHost";
10
+ import { readDoomNotificationService } from "@agimon-ai/doompi-core/notification";
11
+ import { DOOM_TRANSITION_SERVICE, requireDoomTransitionCoordinator } from "@agimon-ai/doompi-core/transition";
12
+ //#region src/extensions/workspaces/sessions/(backend)/_lib/minorModeCommand.ts
13
+ function sessionKindOf(ctx) {
14
+ return ctx.hasUI && ctx.mode === "tui" ? "tui" : "headless";
15
+ }
16
+ /** Register the Pi prompt adapter for the shared minor-mode command behavior. */
17
+ function registerMinorModeCommand(pi, currentCatalog) {
18
+ pi.registerCommand(MINOR_MODE_COMMAND, {
19
+ description: MINOR_MODE_COMMAND_DESCRIPTION,
20
+ getArgumentCompletions: (prefix) => {
21
+ const query = prefix.trim().toLowerCase();
22
+ return (currentCatalog()?.list() ?? []).map((record) => record.descriptor.label.toLowerCase()).filter((label) => label.startsWith(query)).map((label) => ({
23
+ value: label,
24
+ label
25
+ }));
26
+ },
27
+ handler: (args, ctx) => executeMinorModeCommand(args, {
28
+ catalog: currentCatalog(),
29
+ kind: sessionKindOf(ctx),
30
+ ui: {
31
+ select: (title, options) => ctx.ui.select(title, [...options]),
32
+ input: (title, message) => ctx.ui.input(title, message),
33
+ confirm: (title, message) => ctx.ui.confirm(title, message),
34
+ notify: (message, level) => ctx.ui.notify(message, level)
35
+ }
36
+ })
37
+ });
38
+ }
39
+ //#endregion
40
+ //#region src/extensions/workspaces/sessions/(backend)/_lib/catalogRuntime.ts
41
+ /** Registrations and state flips arrive in bursts; one entry covers a burst. */
42
+ const PROJECTION_SETTLE_MS = 50;
43
+ /**
44
+ * Pi's rpc mode subscribes to session events only after bindExtensions()
45
+ * returns, which is after session_start has run, so an entry journaled during
46
+ * startup never reaches a client. A publish deferred past that point does.
47
+ */
48
+ const BOOT_PUBLISH_DELAY_MS = 500;
49
+ function notify(cordis, context, body, level) {
50
+ const service = readDoomNotificationService(cordis);
51
+ if (service) {
52
+ try {
53
+ Promise.resolve(service.request({
54
+ body,
55
+ level
56
+ })).catch(() => void 0);
57
+ } catch {}
58
+ return;
59
+ }
60
+ context.ui.notify(body, level);
61
+ }
62
+ function transitionSource(requesterSource) {
63
+ if (requesterSource.includes("voice")) return "voice";
64
+ if (requesterSource.includes("leader")) return "leader";
65
+ if (requesterSource.includes("ui")) return "ui";
66
+ return "system";
67
+ }
68
+ /**
69
+ * The minor modes that are actually on, for the composition panel.
70
+ *
71
+ * Read from the bound catalog at publish time rather than passed in, because a
72
+ * mode switching on is one of the reasons a publish happens at all, and a
73
+ * remembered list would describe the composition before the switch.
74
+ */
75
+ function createMinorModePiRuntime(pi) {
76
+ const activeCatalog = { current: void 0 };
77
+ registerMinorModeCommand(pi, () => activeCatalog.current);
78
+ pi.on("session_start", () => {
79
+ setTimeout(() => {
80
+ activeCatalog.republish?.();
81
+ }, BOOT_PUBLISH_DELAY_MS);
82
+ });
83
+ return { services: [(cordis) => modeCatalogPlugin(cordis, pi, activeCatalog)] };
84
+ }
85
+ function modeCatalogPlugin(cordis, pi, activeCatalog) {
86
+ cordis.inject([DOOM_CORDIS_SESSION_SERVICE, DOOM_TRANSITION_SERVICE], (sessionContext) => {
87
+ const session = sessionContext.get(DOOM_CORDIS_SESSION_SERVICE);
88
+ const context = session.context;
89
+ const coordinator = requireDoomTransitionCoordinator(sessionContext);
90
+ const reloadSession = session.reason === "reload";
91
+ const sessionId = session.sessionId;
92
+ const restoreSnapshot = reloadSession ? consumeMinorModeReloadHandoff(sessionId) : void 0;
93
+ if (!reloadSession) discardMinorModeReloadHandoff(sessionId);
94
+ const sessionKind = context.hasUI && context.mode === "tui" ? "tui" : "headless";
95
+ const catalog = createMinorModeCatalogHost({
96
+ sessionKind,
97
+ context,
98
+ restoreSnapshot,
99
+ onRestorationError(error) {
100
+ notify(sessionContext, context, `Could not restore a minor mode after reload: ${error instanceof Error ? error.message : String(error)}`, "warning");
101
+ },
102
+ async routeInvocation(request, requesterSource, invoke) {
103
+ let response;
104
+ const result = await coordinator.execute({
105
+ sessionId: context.sessionManager.getSessionId(),
106
+ hostGeneration: coordinator.hostGeneration,
107
+ operationId: request.operationId,
108
+ source: transitionSource(requesterSource),
109
+ target: {
110
+ axis: "live",
111
+ capability: "minor-mode"
112
+ }
113
+ }, async () => {
114
+ response = await invoke();
115
+ return "applied";
116
+ });
117
+ if (result.outcome !== "applied" || !response) throw new Error(`Minor-mode transition was ${result.outcome}: ${result.diagnostics.join(", ")}`);
118
+ return response;
119
+ }
120
+ });
121
+ sessionContext.plugin((providerContext) => {
122
+ providerContext.provide(DOOM_MINOR_MODE_CATALOG_SERVICE, catalog);
123
+ });
124
+ activeCatalog.current = catalog;
125
+ activeCatalog.sessionId = sessionId;
126
+ let published;
127
+ let settle;
128
+ const publish = () => {
129
+ settle = void 0;
130
+ const projection = projectMinorModes(catalog.getSnapshot(), sessionKind);
131
+ const serialized = JSON.stringify(projection);
132
+ if (serialized === published) return;
133
+ published = serialized;
134
+ pi.appendEntry(DOOM_MINOR_MODE_ENTRY_TYPE, projection);
135
+ };
136
+ const unsubscribe = catalog.subscribe(() => {
137
+ settle ??= setTimeout(publish, PROJECTION_SETTLE_MS);
138
+ });
139
+ activeCatalog.republish = () => {
140
+ published = void 0;
141
+ publish();
142
+ };
143
+ return () => {
144
+ if (settle) clearTimeout(settle);
145
+ unsubscribe();
146
+ activeCatalog.republish = void 0;
147
+ activeCatalog.current = void 0;
148
+ activeCatalog.sessionId = void 0;
149
+ catalog.dispose();
150
+ };
151
+ });
152
+ }
153
+ //#endregion
154
+ //#region src/extensions/workspaces/sessions/(backend)/root.cli.ts
155
+ var root_cli_default = defineRoot(({ pi }) => {
156
+ const runtime = createMinorModePiRuntime(pi);
157
+ return {
158
+ value: runtime,
159
+ services: runtime.services,
160
+ onStop: runtime.onStop,
161
+ onDispose: runtime.onDispose
162
+ };
163
+ });
164
+ //#endregion
165
+ //#region generated/pi.ts
166
+ const extension = definePiExtension("@agimon-ai/doompi-minor-mode", async (context) => {
167
+ const scopeSession = await root_cli_default(context);
168
+ return {
169
+ ...composeRootHooks(scopeSession),
170
+ services: [...scopeSession.services ?? []]
171
+ };
172
+ });
173
+ //#endregion
174
+ export { extension as default, extension };
175
+
176
+ //# sourceMappingURL=pi.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pi.mjs","names":["rootSession"],"sources":["../../src/extensions/workspaces/sessions/(backend)/_lib/minorModeCommand.ts","../../src/extensions/workspaces/sessions/(backend)/_lib/catalogRuntime.ts","../../src/extensions/workspaces/sessions/(backend)/root.cli.ts","../../generated/pi.ts"],"sourcesContent":["import type { ExtensionAPI, ExtensionContext } from '@earendil-works/pi-coding-agent';\n\nimport type { MinorModeCatalogService, MinorModeSessionKind } from '../../../../../schemas/mode';\nimport {\n executeMinorModeCommand,\n MINOR_MODE_COMMAND,\n MINOR_MODE_COMMAND_DESCRIPTION,\n} from '../../../../../services/command';\n\nfunction sessionKindOf(ctx: ExtensionContext): MinorModeSessionKind {\n return ctx.hasUI && ctx.mode === 'tui' ? 'tui' : 'headless';\n}\n\n/** Register the Pi prompt adapter for the shared minor-mode command behavior. */\nexport function registerMinorModeCommand(\n pi: ExtensionAPI,\n currentCatalog: () => MinorModeCatalogService | undefined,\n): void {\n pi.registerCommand(MINOR_MODE_COMMAND, {\n description: MINOR_MODE_COMMAND_DESCRIPTION,\n getArgumentCompletions: (prefix) => {\n const query = prefix.trim().toLowerCase();\n const records = currentCatalog()?.list() ?? [];\n return records\n .map((record) => record.descriptor.label.toLowerCase())\n .filter((label) => label.startsWith(query))\n .map((label) => ({ value: label, label }));\n },\n handler: (args, ctx) =>\n executeMinorModeCommand(args, {\n catalog: currentCatalog(),\n kind: sessionKindOf(ctx),\n ui: {\n select: (title, options) => ctx.ui.select(title, [...options]),\n input: (title, message) => ctx.ui.input(title, message),\n confirm: (title, message) => ctx.ui.confirm(title, message),\n notify: (message, level) => ctx.ui.notify(message, level),\n },\n }),\n });\n}\n","import { DOOM_CORDIS_SESSION_SERVICE, type DoomCordisSessionService } from '@agimon-ai/doompi-core/cordisHost';\nimport { type DoomNotificationLevel, readDoomNotificationService } from '@agimon-ai/doompi-core/notification';\nimport type { PiPluginContributions } from '@agimon-ai/doompi-core/piExtension';\nimport {\n DOOM_TRANSITION_SERVICE,\n requireDoomTransitionCoordinator,\n type TransitionSource,\n} from '@agimon-ai/doompi-core/transition';\nimport type { Context } from '@deepseek-ai/cordis';\nimport type { ExtensionAPI, ExtensionContext } from '@earendil-works/pi-coding-agent';\n\nimport {\n DOOM_MINOR_MODE_CATALOG_SERVICE,\n DOOM_MINOR_MODE_ENTRY_TYPE,\n type MinorModeActionResponse,\n type MinorModeCatalogService,\n} from '../../../../../schemas/mode';\nimport { createMinorModeCatalogHost } from '../../../../../services/catalog';\nimport { projectMinorModes } from '../../../../../services/projection';\nimport { consumeMinorModeReloadHandoff, discardMinorModeReloadHandoff } from '../../../../../services/reloadHandoff';\nimport { registerMinorModeCommand } from './minorModeCommand';\n\n/** Registrations and state flips arrive in bursts; one entry covers a burst. */\nconst PROJECTION_SETTLE_MS = 50;\n/**\n * Pi's rpc mode subscribes to session events only after bindExtensions()\n * returns, which is after session_start has run, so an entry journaled during\n * startup never reaches a client. A publish deferred past that point does.\n */\nconst BOOT_PUBLISH_DELAY_MS = 500;\n\ninterface CatalogBinding {\n current: MinorModeCatalogService | undefined;\n /** Journals the projection even if unchanged; set while a session is bound. */\n republish?: () => void;\n /**\n * The bound session, which the detail store is keyed by.\n *\n * The server launches the agent with `--session-id`, so this is the same id\n * the cockpit and the session API know the session by, and a browser asking\n * for a row's detail looks under the file this session wrote.\n */\n sessionId?: string;\n}\n\nfunction notify(cordis: Context, context: ExtensionContext, body: string, level: DoomNotificationLevel): void {\n const service = readDoomNotificationService(cordis);\n if (service) {\n try {\n void Promise.resolve(service.request({ body, level })).catch(() => undefined);\n } catch {\n // Notification delivery is best effort and does not fall back after routing.\n }\n return;\n }\n context.ui.notify(body, level);\n}\n\nfunction transitionSource(requesterSource: string): TransitionSource {\n if (requesterSource.includes('voice')) return 'voice';\n if (requesterSource.includes('leader')) return 'leader';\n if (requesterSource.includes('ui')) return 'ui';\n return 'system';\n}\n\n/**\n * The minor modes that are actually on, for the composition panel.\n *\n * Read from the bound catalog at publish time rather than passed in, because a\n * mode switching on is one of the reasons a publish happens at all, and a\n * remembered list would describe the composition before the switch.\n */\nexport function createMinorModePiRuntime(pi: ExtensionAPI): PiPluginContributions {\n // The command outlives any one session: it is registered once and reads the\n // catalog binding the session-scoped inject below sets and clears.\n const activeCatalog: CatalogBinding = { current: undefined };\n registerMinorModeCommand(pi, () => activeCatalog.current);\n // The composition is only complete once every extension has registered, so\n // the inventory is read on the same deferred tick the catalog republishes on.\n pi.on('session_start', () => {\n setTimeout(() => {\n activeCatalog.republish?.();\n }, BOOT_PUBLISH_DELAY_MS);\n });\n return { services: [(cordis: Context) => modeCatalogPlugin(cordis, pi, activeCatalog)] };\n}\n\nfunction modeCatalogPlugin(\n cordis: Context,\n pi: Pick<ExtensionAPI, 'appendEntry'>,\n activeCatalog: CatalogBinding,\n): void {\n cordis.inject([DOOM_CORDIS_SESSION_SERVICE, DOOM_TRANSITION_SERVICE], (sessionContext) => {\n const session = sessionContext.get(DOOM_CORDIS_SESSION_SERVICE) as DoomCordisSessionService;\n const context = session.context;\n const coordinator = requireDoomTransitionCoordinator(sessionContext);\n const reloadSession = session.reason === 'reload';\n const sessionId = session.sessionId;\n const restoreSnapshot = reloadSession ? consumeMinorModeReloadHandoff(sessionId) : undefined;\n if (!reloadSession) discardMinorModeReloadHandoff(sessionId);\n const sessionKind = context.hasUI && context.mode === 'tui' ? 'tui' : 'headless';\n const catalog: MinorModeCatalogService = createMinorModeCatalogHost({\n sessionKind,\n context,\n restoreSnapshot,\n onRestorationError(error) {\n notify(\n sessionContext,\n context,\n `Could not restore a minor mode after reload: ${error instanceof Error ? error.message : String(error)}`,\n 'warning',\n );\n },\n async routeInvocation(request, requesterSource, invoke) {\n let response: MinorModeActionResponse | undefined;\n const result = await coordinator.execute(\n {\n sessionId: context.sessionManager.getSessionId(),\n hostGeneration: coordinator.hostGeneration,\n operationId: request.operationId,\n source: transitionSource(requesterSource),\n target: { axis: 'live', capability: 'minor-mode' },\n },\n async () => {\n response = await invoke();\n return 'applied';\n },\n );\n if (result.outcome !== 'applied' || !response) {\n throw new Error(`Minor-mode transition was ${result.outcome}: ${result.diagnostics.join(', ')}`);\n }\n return response;\n },\n });\n sessionContext.plugin((providerContext) => {\n providerContext.provide(DOOM_MINOR_MODE_CATALOG_SERVICE, catalog);\n });\n activeCatalog.current = catalog;\n activeCatalog.sessionId = sessionId;\n\n // Journal the projection so RPC clients see catalog state live and on\n // replay; identical projections are skipped so detail churn stays cheap.\n let published: string | undefined;\n let settle: NodeJS.Timeout | undefined;\n const publish = (): void => {\n settle = undefined;\n const projection = projectMinorModes(catalog.getSnapshot(), sessionKind);\n const serialized = JSON.stringify(projection);\n if (serialized === published) return;\n published = serialized;\n pi.appendEntry(DOOM_MINOR_MODE_ENTRY_TYPE, projection);\n // A mode changing is the usual reason the toolbox changed too.\n };\n const unsubscribe = catalog.subscribe(() => {\n settle ??= setTimeout(publish, PROJECTION_SETTLE_MS);\n });\n activeCatalog.republish = () => {\n published = undefined;\n publish();\n };\n\n return () => {\n if (settle) clearTimeout(settle);\n unsubscribe();\n activeCatalog.republish = undefined;\n activeCatalog.current = undefined;\n activeCatalog.sessionId = undefined;\n catalog.dispose();\n };\n });\n}\n","import { defineRoot } from '@agimon-ai/doompi-core/extensionFile';\nimport type { PiPluginContext } from '@agimon-ai/doompi-core/piExtension';\n\nimport { createMinorModePiRuntime } from './_lib/catalogRuntime';\nexport default defineRoot(({ pi }: PiPluginContext) => {\n const runtime = createMinorModePiRuntime(pi);\n return { value: runtime, services: runtime.services, onStop: runtime.onStop, onDispose: runtime.onDispose };\n});\n","// Generated by @agimon-ai/doompi-build. Do not edit by hand.\nimport { definePiExtension, type PiPluginContext } from '@agimon-ai/doompi-core/piExtension';\nimport { composeRootHooks } from '@agimon-ai/doompi-core/extensionFile';\n\nimport rootSession from '../src/extensions/workspaces/sessions/(backend)/root.cli';\n\ntype OptionsOf<T> = T extends (context: PiPluginContext<infer Options>) => unknown ? Options : never;\ntype InferredOptions = Exclude<OptionsOf<typeof rootSession>, undefined>;\ntype Intersect<Union> =\n (Union extends unknown ? (value: Union) => void : never) extends (value: infer Value) => void ? Value : never;\ntype ExtensionOptions = [InferredOptions] extends [never] ? undefined : Intersect<InferredOptions>;\n\nexport const extension = definePiExtension<ExtensionOptions>('@agimon-ai/doompi-minor-mode', async (context) => {\n const scopeSession = await rootSession(context);\n return {\n ...composeRootHooks(scopeSession),\n services: [...(scopeSession.services ?? [])],\n };\n});\n\nexport default extension;\n"],"mappings":"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"}
@@ -0,0 +1,134 @@
1
+ Object.defineProperties(exports, {
2
+ __esModule: { value: true },
3
+ [Symbol.toStringTag]: { value: "Module" }
4
+ });
5
+ const require_mode = require("../mode-Dft08ke8.cjs");
6
+ const require_catalog = require("../catalog-jTd7UXiI.cjs");
7
+ const require_headlessCommand = require("../headlessCommand-CaFFcvJA.cjs");
8
+ const require_projection = require("../projection-DYOm9Kev.cjs");
9
+ let _agimon_ai_doompi_core_extensionFile = require("@agimon-ai/doompi-core/extensionFile");
10
+ let _agimon_ai_doompi_core_serverFacet = require("@agimon-ai/doompi-core/serverFacet");
11
+ //#region src/extensions/workspaces/sessions/(backend)/root.server.ts
12
+ var root_server_default = (0, _agimon_ai_doompi_core_extensionFile.defineRoot)(({ agent }) => {
13
+ if (!agent) throw new Error("Minor modes require a session host");
14
+ let started = false;
15
+ let stopped = false;
16
+ let pending = Promise.resolve();
17
+ let published;
18
+ const publish = () => {
19
+ const operation = pending.then(async () => {
20
+ if (!started || stopped) return;
21
+ const projection = require_projection.projectMinorModes(catalog.getSnapshot(), "headless");
22
+ const key = JSON.stringify(projection);
23
+ if (key === published) return;
24
+ await agent.context.session.appendCustomEntry(require_mode.DOOM_MINOR_MODE_ENTRY_TYPE, projection);
25
+ published = key;
26
+ });
27
+ pending = operation.catch(() => void 0);
28
+ return operation;
29
+ };
30
+ const catalog = require_catalog.createMinorModeCatalogHost({
31
+ sessionKind: "headless",
32
+ context: { sessionManager: { getSessionId: () => agent.context.sessionId } },
33
+ async routeInvocation(_request, _source, invoke) {
34
+ agent.assertActive();
35
+ const response = await invoke();
36
+ await publish();
37
+ return response;
38
+ }
39
+ });
40
+ const contributions = {
41
+ commands: [require_headlessCommand.headlessMinorModeCommand(catalog)],
42
+ services: [(context) => {
43
+ context.plugin((providerContext) => {
44
+ providerContext.provide(require_mode.DOOM_MINOR_MODE_CATALOG_SERVICE, catalog);
45
+ });
46
+ context.effect(() => catalog.subscribe(() => {
47
+ publish().catch(async (error) => {
48
+ if (stopped) return;
49
+ await agent.context.client.notify({
50
+ body: `Minor-mode projection failed: ${String(error)}`,
51
+ level: "error"
52
+ });
53
+ });
54
+ }));
55
+ context.effect(() => agent.subscribeSelection(publish));
56
+ }],
57
+ hooks: [{
58
+ event: "session_shutdown",
59
+ async handle() {
60
+ stopped = true;
61
+ await pending;
62
+ }
63
+ }, {
64
+ event: "session_start",
65
+ async handle() {
66
+ const entries = await agent.context.session.entries({
67
+ type: "custom",
68
+ customType: require_mode.DOOM_MINOR_MODE_ENTRY_TYPE
69
+ });
70
+ const values = require_projection.restoreMinorModeSelection(entries);
71
+ if (values) await agent.changeSelection({
72
+ axis: "state",
73
+ key: "minor-mode",
74
+ values
75
+ });
76
+ started = true;
77
+ await publish();
78
+ }
79
+ }]
80
+ };
81
+ return {
82
+ value: contributions,
83
+ services: contributions.services,
84
+ async onDispose() {
85
+ stopped = true;
86
+ catalog.dispose();
87
+ await pending;
88
+ }
89
+ };
90
+ });
91
+ //#endregion
92
+ //#region src/extensions/workspaces/sessions/(backend)/command/minor-modes.server.ts
93
+ var minor_modes_server_default = (0, _agimon_ai_doompi_core_extensionFile.defineServerCommand)((context) => context.root.commands[0]);
94
+ //#endregion
95
+ //#region src/extensions/workspaces/sessions/(backend)/hook/session-shutdown.server.ts
96
+ var session_shutdown_server_default = (0, _agimon_ai_doompi_core_extensionFile.defineHook)((context) => context.root.hooks.find((hook) => hook.event === "session_shutdown"));
97
+ //#endregion
98
+ //#region src/extensions/workspaces/sessions/(backend)/hook/session-start.server.ts
99
+ var session_start_server_default = (0, _agimon_ai_doompi_core_extensionFile.defineHook)((context) => context.root.hooks.find((hook) => hook.event === "session_start"));
100
+ //#endregion
101
+ //#region generated/server.ts
102
+ const at = (value, context) => typeof value === "function" ? value(context) : value;
103
+ const via = (identity, value) => value === void 0 ? void 0 : {
104
+ ...identity,
105
+ ...value
106
+ };
107
+ const facet = (0, _agimon_ai_doompi_core_serverFacet.defineServerPlugin)({
108
+ name: "@agimon-ai/doompi-minor-mode",
109
+ session: async (context) => {
110
+ const scopeSession = await root_server_default(context);
111
+ const contextSession = {
112
+ ...context,
113
+ root: scopeSession.value
114
+ };
115
+ return {
116
+ ...(0, _agimon_ai_doompi_core_extensionFile.composeRootHooks)(scopeSession),
117
+ get commands() {
118
+ return [via({ name: "minor-modes" }, at(minor_modes_server_default, contextSession))];
119
+ },
120
+ get hooks() {
121
+ return [via({ event: "session_shutdown" }, at(session_shutdown_server_default, contextSession)), via({ event: "session_start" }, at(session_start_server_default, contextSession))];
122
+ },
123
+ services: [...scopeSession.services ?? []],
124
+ get activities() {
125
+ return [...scopeSession.activities ?? []];
126
+ }
127
+ };
128
+ }
129
+ });
130
+ //#endregion
131
+ exports.default = facet;
132
+ exports.facet = facet;
133
+
134
+ //# sourceMappingURL=server.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.cjs","names":["defineRoot","projectMinorModes","DOOM_MINOR_MODE_ENTRY_TYPE","createMinorModeCatalogHost","headlessMinorModeCommand","DOOM_MINOR_MODE_CATALOG_SERVICE","restoreMinorModeSelection","defineServerCommand","defineHook","defineHook","defineServerPlugin","rootSession","composeRootHooks","commandMinorModes","hookSessionShutdown","hookSessionStart"],"sources":["../../src/extensions/workspaces/sessions/(backend)/root.server.ts","../../src/extensions/workspaces/sessions/(backend)/command/minor-modes.server.ts","../../src/extensions/workspaces/sessions/(backend)/hook/session-shutdown.server.ts","../../src/extensions/workspaces/sessions/(backend)/hook/session-start.server.ts","../../generated/server.ts"],"sourcesContent":["import { defineRoot } from '@agimon-ai/doompi-core/extensionFile';\nimport type { DoomServerPluginContext } from '@agimon-ai/doompi-core/serverFacet';\n\nimport { DOOM_MINOR_MODE_CATALOG_SERVICE, DOOM_MINOR_MODE_ENTRY_TYPE } from '../../../../schemas/mode';\nimport { createMinorModeCatalogHost } from '../../../../services/catalog';\nimport { headlessMinorModeCommand } from '../../../../services/headlessCommand';\nimport { projectMinorModes, restoreMinorModeSelection } from '../../../../services/projection';\nimport type { MinorModeServerScope } from './_lib/serverScope';\n\nexport default defineRoot(({ agent }: DoomServerPluginContext) => {\n if (!agent) throw new Error('Minor modes require a session host');\n let started = false;\n let stopped = false;\n let pending = Promise.resolve();\n let published: string | undefined;\n const publish = (): Promise<void> => {\n const operation = pending.then(async () => {\n if (!started || stopped) return;\n const projection = projectMinorModes(catalog.getSnapshot(), 'headless');\n const key = JSON.stringify(projection);\n if (key === published) return;\n await agent.context.session.appendCustomEntry(DOOM_MINOR_MODE_ENTRY_TYPE, projection);\n published = key;\n });\n pending = operation.catch(() => undefined);\n return operation;\n };\n const catalog = createMinorModeCatalogHost({\n sessionKind: 'headless',\n context: { sessionManager: { getSessionId: () => agent.context.sessionId } },\n async routeInvocation(_request, _source, invoke) {\n agent.assertActive();\n const response = await invoke();\n await publish();\n return response;\n },\n });\n const contributions: MinorModeServerScope = {\n commands: [headlessMinorModeCommand(catalog)],\n services: [\n (context: DoomServerPluginContext['context']) => {\n context.plugin((providerContext) => {\n providerContext.provide(DOOM_MINOR_MODE_CATALOG_SERVICE, catalog);\n });\n context.effect(() =>\n catalog.subscribe(() => {\n void publish().catch(async (error) => {\n if (stopped) return;\n await agent.context.client.notify({\n body: `Minor-mode projection failed: ${String(error)}`,\n level: 'error',\n });\n });\n }),\n );\n context.effect(() => agent.subscribeSelection(publish));\n },\n ],\n hooks: [\n {\n event: 'session_shutdown' as const,\n async handle() {\n stopped = true;\n await pending;\n },\n },\n {\n event: 'session_start' as const,\n async handle() {\n const entries = await agent.context.session.entries({\n type: 'custom',\n customType: DOOM_MINOR_MODE_ENTRY_TYPE,\n });\n const values = restoreMinorModeSelection(entries);\n if (values) await agent.changeSelection({ axis: 'state', key: 'minor-mode', values });\n started = true;\n await publish();\n },\n },\n ],\n };\n return {\n value: contributions,\n services: contributions.services,\n async onDispose() {\n stopped = true;\n catalog.dispose();\n await pending;\n },\n };\n});\n","import { defineServerCommand } from '@agimon-ai/doompi-core/extensionFile';\nimport type { WithRoot } from '@agimon-ai/doompi-core/extensionFile';\nimport type { DoomServerPluginContext } from '@agimon-ai/doompi-core/serverFacet';\n\nimport type { MinorModeServerScope } from '../_lib/serverScope';\nexport default defineServerCommand(\n (context: WithRoot<DoomServerPluginContext, MinorModeServerScope>) => context.root.commands[0]!,\n);\n","import { defineHook } from '@agimon-ai/doompi-core/extensionFile';\nimport type { WithRoot } from '@agimon-ai/doompi-core/extensionFile';\nimport type { DoomServerPluginContext } from '@agimon-ai/doompi-core/serverFacet';\n\nimport type { MinorModeServerScope } from '../_lib/serverScope';\nexport default defineHook((context: WithRoot<DoomServerPluginContext, MinorModeServerScope>) =>\n context.root.hooks.find((hook) => hook.event === 'session_shutdown')!,\n);\n","import { defineHook } from '@agimon-ai/doompi-core/extensionFile';\nimport type { WithRoot } from '@agimon-ai/doompi-core/extensionFile';\nimport type { DoomServerPluginContext } from '@agimon-ai/doompi-core/serverFacet';\n\nimport type { MinorModeServerScope } from '../_lib/serverScope';\nexport default defineHook((context: WithRoot<DoomServerPluginContext, MinorModeServerScope>) =>\n context.root.hooks.find((hook) => hook.event === 'session_start')!,\n);\n","// Generated by @agimon-ai/doompi-build. Do not edit by hand.\nimport { defineServerPlugin, type DoomServerSessionPlugin } from '@agimon-ai/doompi-core/serverFacet';\nimport { composeRootHooks } from '@agimon-ai/doompi-core/extensionFile';\n\nimport rootSession from '../src/extensions/workspaces/sessions/(backend)/root.server';\nimport commandMinorModes from '../src/extensions/workspaces/sessions/(backend)/command/minor-modes.server';\nimport hookSessionShutdown from '../src/extensions/workspaces/sessions/(backend)/hook/session-shutdown.server';\nimport hookSessionStart from '../src/extensions/workspaces/sessions/(backend)/hook/session-start.server';\n\ntype Factory<T, C> = (context: C) => T;\nconst at = <T, C>(value: T | Factory<T, C>, context: C): T =>\n typeof value === 'function' ? (value as Factory<T, C>)(context) : value;\nconst via = <T>(identity: Record<string, unknown>, value: unknown): T =>\n (value === undefined ? undefined : { ...identity, ...(value as object) }) as T;\n\nexport const facet = defineServerPlugin({\n name: '@agimon-ai/doompi-minor-mode',\n session: async (context) => {\n const scopeSession = await rootSession(context);\n const contextSession = { ...context, root: scopeSession.value };\n return {\n ...composeRootHooks(scopeSession),\n get commands(): DoomServerSessionPlugin['commands'] { return [via({ name: 'minor-modes' }, at(commandMinorModes, contextSession))]; },\n get hooks(): DoomServerSessionPlugin['hooks'] { return [via({ event: 'session_shutdown' }, at(hookSessionShutdown, contextSession)), via({ event: 'session_start' }, at(hookSessionStart, contextSession))]; },\n services: [...(scopeSession.services ?? [])],\n get activities(): DoomServerSessionPlugin['activities'] { return [...(scopeSession.activities ?? [])]; },\n };\n },\n});\n\nexport default facet;\n"],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ //#region generated/server.d.ts
2
+ export declare const facet: import("@agimon-ai/doompi-core/serverFacet").DoomServerFacet;
3
+ //#endregion
4
+ export { facet as default };
5
+ //# sourceMappingURL=server.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.d.mts","names":[],"sources":["../../generated/server.ts"],"mappings":";qBAea,oDAAK"}
@@ -0,0 +1,129 @@
1
+ import { n as DOOM_MINOR_MODE_ENTRY_TYPE, t as DOOM_MINOR_MODE_CATALOG_SERVICE } from "../mode-BwRkDqO4.mjs";
2
+ import { t as createMinorModeCatalogHost } from "../catalog-8apySKXB.mjs";
3
+ import { t as headlessMinorModeCommand } from "../headlessCommand-BJhocUje.mjs";
4
+ import { n as restoreMinorModeSelection, t as projectMinorModes } from "../projection-Cy1LWVIe.mjs";
5
+ import { composeRootHooks, defineHook, defineRoot, defineServerCommand } from "@agimon-ai/doompi-core/extensionFile";
6
+ import { defineServerPlugin } from "@agimon-ai/doompi-core/serverFacet";
7
+ //#region src/extensions/workspaces/sessions/(backend)/root.server.ts
8
+ var root_server_default = defineRoot(({ agent }) => {
9
+ if (!agent) throw new Error("Minor modes require a session host");
10
+ let started = false;
11
+ let stopped = false;
12
+ let pending = Promise.resolve();
13
+ let published;
14
+ const publish = () => {
15
+ const operation = pending.then(async () => {
16
+ if (!started || stopped) return;
17
+ const projection = projectMinorModes(catalog.getSnapshot(), "headless");
18
+ const key = JSON.stringify(projection);
19
+ if (key === published) return;
20
+ await agent.context.session.appendCustomEntry(DOOM_MINOR_MODE_ENTRY_TYPE, projection);
21
+ published = key;
22
+ });
23
+ pending = operation.catch(() => void 0);
24
+ return operation;
25
+ };
26
+ const catalog = createMinorModeCatalogHost({
27
+ sessionKind: "headless",
28
+ context: { sessionManager: { getSessionId: () => agent.context.sessionId } },
29
+ async routeInvocation(_request, _source, invoke) {
30
+ agent.assertActive();
31
+ const response = await invoke();
32
+ await publish();
33
+ return response;
34
+ }
35
+ });
36
+ const contributions = {
37
+ commands: [headlessMinorModeCommand(catalog)],
38
+ services: [(context) => {
39
+ context.plugin((providerContext) => {
40
+ providerContext.provide(DOOM_MINOR_MODE_CATALOG_SERVICE, catalog);
41
+ });
42
+ context.effect(() => catalog.subscribe(() => {
43
+ publish().catch(async (error) => {
44
+ if (stopped) return;
45
+ await agent.context.client.notify({
46
+ body: `Minor-mode projection failed: ${String(error)}`,
47
+ level: "error"
48
+ });
49
+ });
50
+ }));
51
+ context.effect(() => agent.subscribeSelection(publish));
52
+ }],
53
+ hooks: [{
54
+ event: "session_shutdown",
55
+ async handle() {
56
+ stopped = true;
57
+ await pending;
58
+ }
59
+ }, {
60
+ event: "session_start",
61
+ async handle() {
62
+ const entries = await agent.context.session.entries({
63
+ type: "custom",
64
+ customType: DOOM_MINOR_MODE_ENTRY_TYPE
65
+ });
66
+ const values = restoreMinorModeSelection(entries);
67
+ if (values) await agent.changeSelection({
68
+ axis: "state",
69
+ key: "minor-mode",
70
+ values
71
+ });
72
+ started = true;
73
+ await publish();
74
+ }
75
+ }]
76
+ };
77
+ return {
78
+ value: contributions,
79
+ services: contributions.services,
80
+ async onDispose() {
81
+ stopped = true;
82
+ catalog.dispose();
83
+ await pending;
84
+ }
85
+ };
86
+ });
87
+ //#endregion
88
+ //#region src/extensions/workspaces/sessions/(backend)/command/minor-modes.server.ts
89
+ var minor_modes_server_default = defineServerCommand((context) => context.root.commands[0]);
90
+ //#endregion
91
+ //#region src/extensions/workspaces/sessions/(backend)/hook/session-shutdown.server.ts
92
+ var session_shutdown_server_default = defineHook((context) => context.root.hooks.find((hook) => hook.event === "session_shutdown"));
93
+ //#endregion
94
+ //#region src/extensions/workspaces/sessions/(backend)/hook/session-start.server.ts
95
+ var session_start_server_default = defineHook((context) => context.root.hooks.find((hook) => hook.event === "session_start"));
96
+ //#endregion
97
+ //#region generated/server.ts
98
+ const at = (value, context) => typeof value === "function" ? value(context) : value;
99
+ const via = (identity, value) => value === void 0 ? void 0 : {
100
+ ...identity,
101
+ ...value
102
+ };
103
+ const facet = defineServerPlugin({
104
+ name: "@agimon-ai/doompi-minor-mode",
105
+ session: async (context) => {
106
+ const scopeSession = await root_server_default(context);
107
+ const contextSession = {
108
+ ...context,
109
+ root: scopeSession.value
110
+ };
111
+ return {
112
+ ...composeRootHooks(scopeSession),
113
+ get commands() {
114
+ return [via({ name: "minor-modes" }, at(minor_modes_server_default, contextSession))];
115
+ },
116
+ get hooks() {
117
+ return [via({ event: "session_shutdown" }, at(session_shutdown_server_default, contextSession)), via({ event: "session_start" }, at(session_start_server_default, contextSession))];
118
+ },
119
+ services: [...scopeSession.services ?? []],
120
+ get activities() {
121
+ return [...scopeSession.activities ?? []];
122
+ }
123
+ };
124
+ }
125
+ });
126
+ //#endregion
127
+ export { facet as default, facet };
128
+
129
+ //# sourceMappingURL=server.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.mjs","names":["rootSession","commandMinorModes","hookSessionShutdown","hookSessionStart"],"sources":["../../src/extensions/workspaces/sessions/(backend)/root.server.ts","../../src/extensions/workspaces/sessions/(backend)/command/minor-modes.server.ts","../../src/extensions/workspaces/sessions/(backend)/hook/session-shutdown.server.ts","../../src/extensions/workspaces/sessions/(backend)/hook/session-start.server.ts","../../generated/server.ts"],"sourcesContent":["import { defineRoot } from '@agimon-ai/doompi-core/extensionFile';\nimport type { DoomServerPluginContext } from '@agimon-ai/doompi-core/serverFacet';\n\nimport { DOOM_MINOR_MODE_CATALOG_SERVICE, DOOM_MINOR_MODE_ENTRY_TYPE } from '../../../../schemas/mode';\nimport { createMinorModeCatalogHost } from '../../../../services/catalog';\nimport { headlessMinorModeCommand } from '../../../../services/headlessCommand';\nimport { projectMinorModes, restoreMinorModeSelection } from '../../../../services/projection';\nimport type { MinorModeServerScope } from './_lib/serverScope';\n\nexport default defineRoot(({ agent }: DoomServerPluginContext) => {\n if (!agent) throw new Error('Minor modes require a session host');\n let started = false;\n let stopped = false;\n let pending = Promise.resolve();\n let published: string | undefined;\n const publish = (): Promise<void> => {\n const operation = pending.then(async () => {\n if (!started || stopped) return;\n const projection = projectMinorModes(catalog.getSnapshot(), 'headless');\n const key = JSON.stringify(projection);\n if (key === published) return;\n await agent.context.session.appendCustomEntry(DOOM_MINOR_MODE_ENTRY_TYPE, projection);\n published = key;\n });\n pending = operation.catch(() => undefined);\n return operation;\n };\n const catalog = createMinorModeCatalogHost({\n sessionKind: 'headless',\n context: { sessionManager: { getSessionId: () => agent.context.sessionId } },\n async routeInvocation(_request, _source, invoke) {\n agent.assertActive();\n const response = await invoke();\n await publish();\n return response;\n },\n });\n const contributions: MinorModeServerScope = {\n commands: [headlessMinorModeCommand(catalog)],\n services: [\n (context: DoomServerPluginContext['context']) => {\n context.plugin((providerContext) => {\n providerContext.provide(DOOM_MINOR_MODE_CATALOG_SERVICE, catalog);\n });\n context.effect(() =>\n catalog.subscribe(() => {\n void publish().catch(async (error) => {\n if (stopped) return;\n await agent.context.client.notify({\n body: `Minor-mode projection failed: ${String(error)}`,\n level: 'error',\n });\n });\n }),\n );\n context.effect(() => agent.subscribeSelection(publish));\n },\n ],\n hooks: [\n {\n event: 'session_shutdown' as const,\n async handle() {\n stopped = true;\n await pending;\n },\n },\n {\n event: 'session_start' as const,\n async handle() {\n const entries = await agent.context.session.entries({\n type: 'custom',\n customType: DOOM_MINOR_MODE_ENTRY_TYPE,\n });\n const values = restoreMinorModeSelection(entries);\n if (values) await agent.changeSelection({ axis: 'state', key: 'minor-mode', values });\n started = true;\n await publish();\n },\n },\n ],\n };\n return {\n value: contributions,\n services: contributions.services,\n async onDispose() {\n stopped = true;\n catalog.dispose();\n await pending;\n },\n };\n});\n","import { defineServerCommand } from '@agimon-ai/doompi-core/extensionFile';\nimport type { WithRoot } from '@agimon-ai/doompi-core/extensionFile';\nimport type { DoomServerPluginContext } from '@agimon-ai/doompi-core/serverFacet';\n\nimport type { MinorModeServerScope } from '../_lib/serverScope';\nexport default defineServerCommand(\n (context: WithRoot<DoomServerPluginContext, MinorModeServerScope>) => context.root.commands[0]!,\n);\n","import { defineHook } from '@agimon-ai/doompi-core/extensionFile';\nimport type { WithRoot } from '@agimon-ai/doompi-core/extensionFile';\nimport type { DoomServerPluginContext } from '@agimon-ai/doompi-core/serverFacet';\n\nimport type { MinorModeServerScope } from '../_lib/serverScope';\nexport default defineHook((context: WithRoot<DoomServerPluginContext, MinorModeServerScope>) =>\n context.root.hooks.find((hook) => hook.event === 'session_shutdown')!,\n);\n","import { defineHook } from '@agimon-ai/doompi-core/extensionFile';\nimport type { WithRoot } from '@agimon-ai/doompi-core/extensionFile';\nimport type { DoomServerPluginContext } from '@agimon-ai/doompi-core/serverFacet';\n\nimport type { MinorModeServerScope } from '../_lib/serverScope';\nexport default defineHook((context: WithRoot<DoomServerPluginContext, MinorModeServerScope>) =>\n context.root.hooks.find((hook) => hook.event === 'session_start')!,\n);\n","// Generated by @agimon-ai/doompi-build. Do not edit by hand.\nimport { defineServerPlugin, type DoomServerSessionPlugin } from '@agimon-ai/doompi-core/serverFacet';\nimport { composeRootHooks } from '@agimon-ai/doompi-core/extensionFile';\n\nimport rootSession from '../src/extensions/workspaces/sessions/(backend)/root.server';\nimport commandMinorModes from '../src/extensions/workspaces/sessions/(backend)/command/minor-modes.server';\nimport hookSessionShutdown from '../src/extensions/workspaces/sessions/(backend)/hook/session-shutdown.server';\nimport hookSessionStart from '../src/extensions/workspaces/sessions/(backend)/hook/session-start.server';\n\ntype Factory<T, C> = (context: C) => T;\nconst at = <T, C>(value: T | Factory<T, C>, context: C): T =>\n typeof value === 'function' ? (value as Factory<T, C>)(context) : value;\nconst via = <T>(identity: Record<string, unknown>, value: unknown): T =>\n (value === undefined ? undefined : { ...identity, ...(value as object) }) as T;\n\nexport const facet = defineServerPlugin({\n name: '@agimon-ai/doompi-minor-mode',\n session: async (context) => {\n const scopeSession = await rootSession(context);\n const contextSession = { ...context, root: scopeSession.value };\n return {\n ...composeRootHooks(scopeSession),\n get commands(): DoomServerSessionPlugin['commands'] { return [via({ name: 'minor-modes' }, at(commandMinorModes, contextSession))]; },\n get hooks(): DoomServerSessionPlugin['hooks'] { return [via({ event: 'session_shutdown' }, at(hookSessionShutdown, contextSession)), via({ event: 'session_start' }, at(hookSessionStart, contextSession))]; },\n services: [...(scopeSession.services ?? [])],\n get activities(): DoomServerSessionPlugin['activities'] { return [...(scopeSession.activities ?? [])]; },\n };\n },\n});\n\nexport default facet;\n"],"mappings":";;;;;;;AASA,IAAA,sBAAe,YAAY,EAAE,YAAqC;CAChE,IAAI,CAAC,OAAO,MAAM,IAAI,MAAM,oCAAoC;CAChE,IAAI,UAAU;CACd,IAAI,UAAU;CACd,IAAI,UAAU,QAAQ,QAAQ;CAC9B,IAAI;CACJ,MAAM,gBAA+B;EACnC,MAAM,YAAY,QAAQ,KAAK,YAAY;GACzC,IAAI,CAAC,WAAW,SAAS;GACzB,MAAM,aAAa,kBAAkB,QAAQ,YAAY,GAAG,UAAU;GACtE,MAAM,MAAM,KAAK,UAAU,UAAU;GACrC,IAAI,QAAQ,WAAW;GACvB,MAAM,MAAM,QAAQ,QAAQ,kBAAkB,4BAA4B,UAAU;GACpF,YAAY;EACd,CAAC;EACD,UAAU,UAAU,YAAY,KAAA,CAAS;EACzC,OAAO;CACT;CACA,MAAM,UAAU,2BAA2B;EACzC,aAAa;EACb,SAAS,EAAE,gBAAgB,EAAE,oBAAoB,MAAM,QAAQ,UAAU,EAAE;EAC3E,MAAM,gBAAgB,UAAU,SAAS,QAAQ;GAC/C,MAAM,aAAa;GACnB,MAAM,WAAW,MAAM,OAAO;GAC9B,MAAM,QAAQ;GACd,OAAO;EACT;CACF,CAAC;CACD,MAAM,gBAAsC;EAC1C,UAAU,CAAC,yBAAyB,OAAO,CAAC;EAC5C,UAAU,EACP,YAAgD;GAC/C,QAAQ,QAAQ,oBAAoB;IAClC,gBAAgB,QAAQ,iCAAiC,OAAO;GAClE,CAAC;GACD,QAAQ,aACN,QAAQ,gBAAgB;IACtB,QAAa,CAAC,CAAC,MAAM,OAAO,UAAU;KACpC,IAAI,SAAS;KACb,MAAM,MAAM,QAAQ,OAAO,OAAO;MAChC,MAAM,iCAAiC,OAAO,KAAK;MACnD,OAAO;KACT,CAAC;IACH,CAAC;GACH,CAAC,CACH;GACA,QAAQ,aAAa,MAAM,mBAAmB,OAAO,CAAC;EACxD,CACF;EACA,OAAO,CACL;GACE,OAAO;GACP,MAAM,SAAS;IACb,UAAU;IACV,MAAM;GACR;EACF,GACA;GACE,OAAO;GACP,MAAM,SAAS;IACb,MAAM,UAAU,MAAM,MAAM,QAAQ,QAAQ,QAAQ;KAClD,MAAM;KACN,YAAY;IACd,CAAC;IACD,MAAM,SAAS,0BAA0B,OAAO;IAChD,IAAI,QAAQ,MAAM,MAAM,gBAAgB;KAAE,MAAM;KAAS,KAAK;KAAc;IAAO,CAAC;IACpF,UAAU;IACV,MAAM,QAAQ;GAChB;EACF,CACF;CACF;CACA,OAAO;EACL,OAAO;EACP,UAAU,cAAc;EACxB,MAAM,YAAY;GAChB,UAAU;GACV,QAAQ,QAAQ;GAChB,MAAM;EACR;CACF;AACF,CAAC;;;ACrFD,IAAA,6BAAe,qBACZ,YAAqE,QAAQ,KAAK,SAAS,EAC9F;;;ACFA,IAAA,kCAAe,YAAY,YACzB,QAAQ,KAAK,MAAM,MAAM,SAAS,KAAK,UAAU,kBAAkB,CACrE;;;ACFA,IAAA,+BAAe,YAAY,YACzB,QAAQ,KAAK,MAAM,MAAM,SAAS,KAAK,UAAU,eAAe,CAClE;;;ACGA,MAAM,MAAY,OAA0B,YAC1C,OAAO,UAAU,aAAc,MAAwB,OAAO,IAAI;AACpE,MAAM,OAAU,UAAmC,UAChD,UAAU,KAAA,IAAY,KAAA,IAAY;CAAE,GAAG;CAAU,GAAI;AAAiB;AAEzE,MAAa,QAAQ,mBAAmB;CACtC,MAAM;CACN,SAAS,OAAO,YAAY;EAC1B,MAAM,eAAe,MAAMA,oBAAY,OAAO;EAC9C,MAAM,iBAAiB;GAAE,GAAG;GAAS,MAAM,aAAa;EAAM;EAC9D,OAAO;GACL,GAAG,iBAAiB,YAAY;GAChC,IAAI,WAAgD;IAAE,OAAO,CAAC,IAAI,EAAE,MAAM,cAAc,GAAG,GAAGC,4BAAmB,cAAc,CAAC,CAAC;GAAG;GACpI,IAAI,QAA0C;IAAE,OAAO,CAAC,IAAI,EAAE,OAAO,mBAAmB,GAAG,GAAGC,iCAAqB,cAAc,CAAC,GAAG,IAAI,EAAE,OAAO,gBAAgB,GAAG,GAAGC,8BAAkB,cAAc,CAAC,CAAC;GAAG;GAC7M,UAAU,CAAC,GAAI,aAAa,YAAY,CAAC,CAAE;GAC3C,IAAI,aAAoD;IAAE,OAAO,CAAC,GAAI,aAAa,cAAc,CAAC,CAAE;GAAG;EACzG;CACF;AACF,CAAC"}
@@ -0,0 +1,53 @@
1
+ import { t as MINOR_MODE_COMMAND_DESCRIPTION } from "./command-BvYpwiin.mjs";
2
+ import { r as executeMinorModeCommand, t as MINOR_MODE_COMMAND } from "./command-C4u3oOPT.mjs";
3
+ //#region src/services/headlessCommand/index.ts
4
+ function headlessMinorModeCommand(catalog) {
5
+ return {
6
+ name: MINOR_MODE_COMMAND,
7
+ description: MINOR_MODE_COMMAND_DESCRIPTION,
8
+ async execute(args, execution) {
9
+ const executionClient = execution.client;
10
+ await executeMinorModeCommand(args, {
11
+ catalog,
12
+ kind: "headless",
13
+ ui: {
14
+ async select(title, options) {
15
+ const selected = await executionClient.request({
16
+ kind: "select",
17
+ title,
18
+ options: options.map((label) => ({
19
+ label,
20
+ value: label
21
+ }))
22
+ });
23
+ return typeof selected === "string" ? selected : void 0;
24
+ },
25
+ async input(title, message) {
26
+ const entered = await executionClient.request({
27
+ kind: "input",
28
+ title,
29
+ message
30
+ });
31
+ return typeof entered === "string" ? entered : void 0;
32
+ },
33
+ async confirm(title, message) {
34
+ const confirmed = await executionClient.request({
35
+ kind: "confirm",
36
+ title,
37
+ message
38
+ });
39
+ return typeof confirmed === "boolean" ? confirmed : void 0;
40
+ },
41
+ notify: (message, level) => executionClient.notify({
42
+ body: message,
43
+ level
44
+ })
45
+ }
46
+ });
47
+ }
48
+ };
49
+ }
50
+ //#endregion
51
+ export { headlessMinorModeCommand as t };
52
+
53
+ //# sourceMappingURL=headlessCommand-BJhocUje.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"headlessCommand-BJhocUje.mjs","names":[],"sources":["../src/services/headlessCommand/index.ts"],"sourcesContent":["import type { DoomHeadlessCommand } from '@agimon-ai/doompi-core/headless';\n\nimport type { MinorModeCatalogService } from '../../schemas/mode';\nimport { executeMinorModeCommand, MINOR_MODE_COMMAND, MINOR_MODE_COMMAND_DESCRIPTION } from '../command';\nexport function headlessMinorModeCommand(catalog: MinorModeCatalogService): DoomHeadlessCommand {\n return {\n name: MINOR_MODE_COMMAND,\n description: MINOR_MODE_COMMAND_DESCRIPTION,\n async execute(args, execution) {\n const executionClient = execution.client;\n await executeMinorModeCommand(args, {\n catalog,\n kind: 'headless',\n ui: {\n async select(title, options) {\n const selected = await executionClient.request({\n kind: 'select',\n title,\n options: options.map((label) => ({ label, value: label })),\n });\n return typeof selected === 'string' ? selected : undefined;\n },\n async input(title, message) {\n const entered = await executionClient.request({ kind: 'input', title, message });\n return typeof entered === 'string' ? entered : undefined;\n },\n async confirm(title, message) {\n const confirmed = await executionClient.request({ kind: 'confirm', title, message });\n return typeof confirmed === 'boolean' ? confirmed : undefined;\n },\n notify: (message, level) => executionClient.notify({ body: message, level }),\n },\n });\n },\n };\n}\n"],"mappings":";;;AAIA,SAAgB,yBAAyB,SAAuD;CAC9F,OAAO;EACL,MAAM;EACN,aAAa;EACb,MAAM,QAAQ,MAAM,WAAW;GAC7B,MAAM,kBAAkB,UAAU;GAClC,MAAM,wBAAwB,MAAM;IAClC;IACA,MAAM;IACN,IAAI;KACF,MAAM,OAAO,OAAO,SAAS;MAC3B,MAAM,WAAW,MAAM,gBAAgB,QAAQ;OAC7C,MAAM;OACN;OACA,SAAS,QAAQ,KAAK,WAAW;QAAE;QAAO,OAAO;OAAM,EAAE;MAC3D,CAAC;MACD,OAAO,OAAO,aAAa,WAAW,WAAW,KAAA;KACnD;KACA,MAAM,MAAM,OAAO,SAAS;MAC1B,MAAM,UAAU,MAAM,gBAAgB,QAAQ;OAAE,MAAM;OAAS;OAAO;MAAQ,CAAC;MAC/E,OAAO,OAAO,YAAY,WAAW,UAAU,KAAA;KACjD;KACA,MAAM,QAAQ,OAAO,SAAS;MAC5B,MAAM,YAAY,MAAM,gBAAgB,QAAQ;OAAE,MAAM;OAAW;OAAO;MAAQ,CAAC;MACnF,OAAO,OAAO,cAAc,YAAY,YAAY,KAAA;KACtD;KACA,SAAS,SAAS,UAAU,gBAAgB,OAAO;MAAE,MAAM;MAAS;KAAM,CAAC;IAC7E;GACF,CAAC;EACH;CACF;AACF"}