@agimon-ai/doompi-notification 0.0.1-alpha.46 → 0.0.1-alpha.47
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +10 -4
- package/dist/api-contracts.cjs +1 -0
- package/dist/api-contracts.d.cts +2 -0
- package/dist/api-contracts.d.mts +2 -0
- package/dist/api-contracts.mjs +1 -0
- package/dist/controllers/notificationCommand.cjs +2 -0
- package/dist/controllers/notificationCommand.cjs.map +1 -0
- package/dist/controllers/notificationCommand.mjs +2 -0
- package/dist/controllers/notificationCommand.mjs.map +1 -0
- package/dist/controllers/notificationRouter.cjs +2 -0
- package/dist/controllers/notificationRouter.cjs.map +1 -0
- package/dist/controllers/notificationRouter.mjs +2 -0
- package/dist/controllers/notificationRouter.mjs.map +1 -0
- package/dist/controllers/notificationRuntime.cjs +2 -0
- package/dist/controllers/notificationRuntime.cjs.map +1 -0
- package/dist/controllers/notificationRuntime.d.cts +11 -0
- package/dist/controllers/notificationRuntime.d.cts.map +1 -0
- package/dist/controllers/notificationRuntime.d.mts +11 -0
- package/dist/controllers/notificationRuntime.d.mts.map +1 -0
- package/dist/controllers/notificationRuntime.mjs +2 -0
- package/dist/controllers/notificationRuntime.mjs.map +1 -0
- package/dist/controllers/shellTitleController.cjs.map +1 -0
- package/dist/{adapters → controllers}/shellTitleController.d.cts +1 -1
- package/dist/controllers/shellTitleController.d.cts.map +1 -0
- package/dist/{adapters → controllers}/shellTitleController.d.mts +1 -1
- package/dist/controllers/shellTitleController.d.mts.map +1 -0
- package/dist/controllers/shellTitleController.mjs.map +1 -0
- package/dist/controllers/systemNotification.cjs +2 -0
- package/dist/controllers/systemNotification.cjs.map +1 -0
- package/dist/{adapters → controllers}/systemNotification.d.cts +1 -1
- package/dist/controllers/systemNotification.d.cts.map +1 -0
- package/dist/{adapters → controllers}/systemNotification.d.mts +1 -1
- package/dist/controllers/systemNotification.d.mts.map +1 -0
- package/dist/controllers/systemNotification.mjs +2 -0
- package/dist/controllers/systemNotification.mjs.map +1 -0
- package/dist/extensions/pi.cjs +2 -1
- package/dist/extensions/pi.cjs.map +1 -0
- package/dist/extensions/pi.d.cts +8 -2
- package/dist/extensions/pi.d.cts.map +1 -0
- package/dist/extensions/pi.d.mts +8 -2
- package/dist/extensions/pi.d.mts.map +1 -0
- package/dist/extensions/pi.mjs +2 -1
- package/dist/extensions/pi.mjs.map +1 -0
- package/dist/extensions/server.cjs +2 -0
- package/dist/extensions/server.cjs.map +1 -0
- package/dist/extensions/server.d.cts +5 -0
- package/dist/extensions/server.d.cts.map +1 -0
- package/dist/extensions/server.d.mts +5 -0
- package/dist/extensions/server.d.mts.map +1 -0
- package/dist/extensions/server.mjs +2 -0
- package/dist/extensions/server.mjs.map +1 -0
- package/dist/index.cjs +1 -1
- package/dist/index.d.cts +6 -6
- package/dist/index.d.mts +6 -6
- package/dist/index.mjs +1 -1
- package/dist/schemas/apiContracts.cjs +2 -0
- package/dist/schemas/apiContracts.cjs.map +1 -0
- package/dist/schemas/apiContracts.d.cts +53 -0
- package/dist/schemas/apiContracts.d.cts.map +1 -0
- package/dist/schemas/apiContracts.d.mts +53 -0
- package/dist/schemas/apiContracts.d.mts.map +1 -0
- package/dist/schemas/apiContracts.mjs +2 -0
- package/dist/schemas/apiContracts.mjs.map +1 -0
- package/dist/services/{notificationPolicy.cjs → notificationPolicy/index.cjs} +1 -1
- package/dist/services/notificationPolicy/index.cjs.map +1 -0
- package/dist/services/{notificationPolicy.d.mts → notificationPolicy/index.d.cts} +2 -2
- package/dist/services/notificationPolicy/index.d.cts.map +1 -0
- package/dist/services/{notificationPolicy.d.cts → notificationPolicy/index.d.mts} +2 -2
- package/dist/services/notificationPolicy/index.d.mts.map +1 -0
- package/dist/services/{notificationPolicy.mjs → notificationPolicy/index.mjs} +1 -1
- package/dist/services/notificationPolicy/index.mjs.map +1 -0
- package/dist/services/notificationText/index.cjs +2 -0
- package/dist/services/{notificationText.cjs.map → notificationText/index.cjs.map} +1 -1
- package/dist/services/{notificationText.d.cts → notificationText/index.d.cts} +3 -3
- package/dist/services/notificationText/index.d.cts.map +1 -0
- package/dist/services/{notificationText.d.mts → notificationText/index.d.mts} +3 -3
- package/dist/services/notificationText/index.d.mts.map +1 -0
- package/dist/services/{notificationText.mjs → notificationText/index.mjs} +1 -1
- package/dist/services/{notificationText.mjs.map → notificationText/index.mjs.map} +1 -1
- package/package.json +19 -3
- package/dist/adapters/notificationRouter.cjs +0 -2
- package/dist/adapters/notificationRouter.cjs.map +0 -1
- package/dist/adapters/notificationRouter.mjs +0 -2
- package/dist/adapters/notificationRouter.mjs.map +0 -1
- package/dist/adapters/pi/extension.cjs +0 -2
- package/dist/adapters/pi/extension.cjs.map +0 -1
- package/dist/adapters/pi/extension.d.cts +0 -13
- package/dist/adapters/pi/extension.d.cts.map +0 -1
- package/dist/adapters/pi/extension.d.mts +0 -13
- package/dist/adapters/pi/extension.d.mts.map +0 -1
- package/dist/adapters/pi/extension.mjs +0 -2
- package/dist/adapters/pi/extension.mjs.map +0 -1
- package/dist/adapters/shellTitleController.cjs.map +0 -1
- package/dist/adapters/shellTitleController.d.cts.map +0 -1
- package/dist/adapters/shellTitleController.d.mts.map +0 -1
- package/dist/adapters/shellTitleController.mjs.map +0 -1
- package/dist/adapters/systemNotification.cjs +0 -2
- package/dist/adapters/systemNotification.cjs.map +0 -1
- package/dist/adapters/systemNotification.d.cts.map +0 -1
- package/dist/adapters/systemNotification.d.mts.map +0 -1
- package/dist/adapters/systemNotification.mjs +0 -2
- package/dist/adapters/systemNotification.mjs.map +0 -1
- package/dist/services/notificationPolicy.cjs.map +0 -1
- package/dist/services/notificationPolicy.d.cts.map +0 -1
- package/dist/services/notificationPolicy.d.mts.map +0 -1
- package/dist/services/notificationPolicy.mjs.map +0 -1
- package/dist/services/notificationText.cjs +0 -2
- package/dist/services/notificationText.d.cts.map +0 -1
- package/dist/services/notificationText.d.mts.map +0 -1
- /package/dist/{adapters → controllers}/shellTitleController.cjs +0 -0
- /package/dist/{adapters → controllers}/shellTitleController.mjs +0 -0
package/README.md
CHANGED
|
@@ -27,10 +27,7 @@ Callers should discover the optional service through Cordis and request delivery
|
|
|
27
27
|
a particular host:
|
|
28
28
|
|
|
29
29
|
```ts
|
|
30
|
-
import {
|
|
31
|
-
DOOM_NOTIFICATION_SERVICE,
|
|
32
|
-
readDoomNotificationService,
|
|
33
|
-
} from '@agimon-ai/doompi-extension-contracts/notification';
|
|
30
|
+
import { DOOM_NOTIFICATION_SERVICE, readDoomNotificationService } from '@agimon-ai/doompi-core/notification';
|
|
34
31
|
|
|
35
32
|
ctx.inject([DOOM_NOTIFICATION_SERVICE], (notificationContext) => {
|
|
36
33
|
void readDoomNotificationService(notificationContext)?.request({
|
|
@@ -85,6 +82,15 @@ escape sequences never end up in machine-read output.
|
|
|
85
82
|
DoomPi depends on this package and activates it as fixed host core, so a DoomPi install already has
|
|
86
83
|
it. It is not selectable from `.doom/modes.yaml`.
|
|
87
84
|
|
|
85
|
+
The Pi and server loaders use `/extensions/pi` and `/extensions/server`, built directly from
|
|
86
|
+
`src/extensions`. The root export contains reusable notification helpers and types.
|
|
87
|
+
Controllers own delivery and UI integration; policy and text services live in named service folders.
|
|
88
|
+
|
|
89
|
+
The Pi declaration installs its router and optional session binding before handling events.
|
|
90
|
+
`onStop` restores the original UI methods and shell title before service registrations are removed.
|
|
91
|
+
`onDispose` provides the same cleanup after partial startup. Detached children return before
|
|
92
|
+
acquiring a Cordis connection, leaving notification ownership with the parent.
|
|
93
|
+
|
|
88
94
|
## License
|
|
89
95
|
|
|
90
96
|
MIT
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:`Module`}});const e=require("./schemas/apiContracts.cjs");exports.apiContracts=e.apiContracts,exports.default=e.apiContracts;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{apiContracts as e}from"./schemas/apiContracts.mjs";export{e as apiContracts,e as default};
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
const e=(0,require("@agimon-ai/doompi-core/server-facet").defineCommand)({name:`notify`,description:`Send a notification through the active headless client.`,async execute(e,t){let n=e.trim();n&&await t.notify({body:n,level:`info`})}});exports.notificationCommand=e;
|
|
2
|
+
//# sourceMappingURL=notificationCommand.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"notificationCommand.cjs","names":["defineCommand"],"sources":["../../src/controllers/notificationCommand.ts"],"sourcesContent":["import { defineCommand } from '@agimon-ai/doompi-core/server-facet';\n\nexport const notificationCommand = defineCommand({\n name: 'notify',\n description: 'Send a notification through the active headless client.',\n async execute(args, execution) {\n const body = args.trim();\n if (body) await execution.notify({ body, level: 'info' });\n },\n});\n"],"mappings":"AAEA,MAAa,GAAA,+CAAsBA,CAAAA,CAAAA,cAAAA,CAAc,CAC/C,KAAM,SACN,YAAa,0DACb,MAAM,QAAQ,EAAM,EAAW,CAC7B,IAAM,EAAO,EAAK,KAAK,EACnB,GAAM,MAAM,EAAU,OAAO,CAAE,OAAM,MAAO,MAAO,CAAC,CAC1D,CACF,CAAC"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{defineCommand as e}from"@agimon-ai/doompi-core/server-facet";const t=e({name:`notify`,description:`Send a notification through the active headless client.`,async execute(e,t){let n=e.trim();n&&await t.notify({body:n,level:`info`})}});export{t as notificationCommand};
|
|
2
|
+
//# sourceMappingURL=notificationCommand.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"notificationCommand.mjs","names":[],"sources":["../../src/controllers/notificationCommand.ts"],"sourcesContent":["import { defineCommand } from '@agimon-ai/doompi-core/server-facet';\n\nexport const notificationCommand = defineCommand({\n name: 'notify',\n description: 'Send a notification through the active headless client.',\n async execute(args, execution) {\n const body = args.trim();\n if (body) await execution.notify({ body, level: 'info' });\n },\n});\n"],"mappings":"oEAEA,MAAa,EAAsB,EAAc,CAC/C,KAAM,SACN,YAAa,0DACb,MAAM,QAAQ,EAAM,EAAW,CAC7B,IAAM,EAAO,EAAK,KAAK,EACnB,GAAM,MAAM,EAAU,OAAO,CAAE,OAAM,MAAO,MAAO,CAAC,CAC1D,CACF,CAAC"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
const e=require("../_virtual/_rolldown/runtime.cjs"),t=require("./systemNotification.cjs");let n=require("node:path");n=e.__toESM(n,1);let r=require("@agimon-ai/doompi-core/notification");function i({generation:e,pi:i,context:a}){return Object.freeze({generation:e,async request(e){let o=a();if(o)try{let a=(0,r.normalizeDoomNotificationRequest)(e);if(!a)return;let s=(0,r.createDoomNotificationEntryData)({title:a.title??`Pi`,subtitle:a.subtitle??i.getSessionName()??n.default.basename(o.cwd),body:a.body,level:a.level??`info`});if(!s)return;if(o.mode===`rpc`){i.appendEntry(r.DOOM_NOTIFICATION_ENTRY_TYPE,s);return}await t.sendSystemNotification(i,s)}catch{}}})}exports.createDoomNotificationRouter=i;
|
|
2
|
+
//# sourceMappingURL=notificationRouter.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"notificationRouter.cjs","names":["normalizeDoomNotificationRequest","createDoomNotificationEntryData","path","DOOM_NOTIFICATION_ENTRY_TYPE","sendSystemNotification"],"sources":["../../src/controllers/notificationRouter.ts"],"sourcesContent":["import path from 'node:path';\n\nimport {\n createDoomNotificationEntryData,\n DOOM_NOTIFICATION_ENTRY_TYPE,\n type DoomNotificationRequest,\n type DoomNotificationService,\n normalizeDoomNotificationRequest,\n} from '@agimon-ai/doompi-core/notification';\nimport type { ExtensionAPI, ExtensionContext } from '@earendil-works/pi-coding-agent';\n\nimport { sendSystemNotification } from './systemNotification';\n\nconst DEFAULT_TITLE = 'Pi';\n\nexport interface DoomNotificationRouterOptions {\n readonly generation: string;\n readonly pi: ExtensionAPI;\n readonly context: () => ExtensionContext | undefined;\n}\n\n/**\n * Creates the shared notification router for one extension runtime.\n *\n * A missing session, invalid request, or delivery failure is an intentional\n * silent outcome because notification delivery must never fail the active turn.\n * RPC delivery never falls back to a host notifier after an append failure.\n */\nexport function createDoomNotificationRouter({\n generation,\n pi,\n context: readContext,\n}: DoomNotificationRouterOptions): DoomNotificationService {\n return Object.freeze({\n generation,\n async request(request: DoomNotificationRequest): Promise<void> {\n const context = readContext();\n if (!context) return;\n\n try {\n const normalized = normalizeDoomNotificationRequest(request);\n if (!normalized) return;\n const data = createDoomNotificationEntryData({\n title: normalized.title ?? DEFAULT_TITLE,\n subtitle: normalized.subtitle ?? pi.getSessionName() ?? path.basename(context.cwd),\n body: normalized.body,\n level: normalized.level ?? 'info',\n });\n if (!data) return;\n\n if (context.mode === 'rpc') {\n pi.appendEntry(DOOM_NOTIFICATION_ENTRY_TYPE, data);\n return;\n }\n await sendSystemNotification(pi, data);\n } catch (error) {\n // Best-effort delivery deliberately ends here. In particular, an RPC\n // append failure must not leak the notification through the host OS.\n void error;\n }\n },\n });\n}\n"],"mappings":"4LA4BA,SAAgB,EAA6B,CAC3C,aACA,KACA,QAAS,GACgD,CACzD,OAAO,OAAO,OAAO,CACnB,aACA,MAAM,QAAQ,EAAiD,CAC7D,IAAM,EAAU,EAAY,EACvB,KAEL,GAAI,CACF,IAAM,GAAA,EAAaA,EAAAA,iCAAAA,CAAiC,CAAO,EAC3D,GAAI,CAAC,EAAY,OACjB,IAAM,GAAA,EAAOC,EAAAA,gCAAAA,CAAgC,CAC3C,MAAO,EAAW,OAAS,KAC3B,SAAU,EAAW,UAAY,EAAG,eAAe,GAAKC,EAAAA,QAAK,SAAS,EAAQ,GAAG,EACjF,KAAM,EAAW,KACjB,MAAO,EAAW,OAAS,MAC7B,CAAC,EACD,GAAI,CAAC,EAAM,OAEX,GAAI,EAAQ,OAAS,MAAO,CAC1B,EAAG,YAAYC,EAAAA,6BAA8B,CAAI,EACjD,MACF,CACA,MAAMC,EAAAA,uBAAuB,EAAI,CAAI,CACvC,MAAgB,CAIhB,CACF,CACF,CAAC,CACH"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{sendSystemNotification as e}from"./systemNotification.mjs";import t from"node:path";import{DOOM_NOTIFICATION_ENTRY_TYPE as n,createDoomNotificationEntryData as r,normalizeDoomNotificationRequest as i}from"@agimon-ai/doompi-core/notification";function a({generation:a,pi:o,context:s}){return Object.freeze({generation:a,async request(a){let c=s();if(c)try{let s=i(a);if(!s)return;let l=r({title:s.title??`Pi`,subtitle:s.subtitle??o.getSessionName()??t.basename(c.cwd),body:s.body,level:s.level??`info`});if(!l)return;if(c.mode===`rpc`){o.appendEntry(n,l);return}await e(o,l)}catch{}}})}export{a as createDoomNotificationRouter};
|
|
2
|
+
//# sourceMappingURL=notificationRouter.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"notificationRouter.mjs","names":[],"sources":["../../src/controllers/notificationRouter.ts"],"sourcesContent":["import path from 'node:path';\n\nimport {\n createDoomNotificationEntryData,\n DOOM_NOTIFICATION_ENTRY_TYPE,\n type DoomNotificationRequest,\n type DoomNotificationService,\n normalizeDoomNotificationRequest,\n} from '@agimon-ai/doompi-core/notification';\nimport type { ExtensionAPI, ExtensionContext } from '@earendil-works/pi-coding-agent';\n\nimport { sendSystemNotification } from './systemNotification';\n\nconst DEFAULT_TITLE = 'Pi';\n\nexport interface DoomNotificationRouterOptions {\n readonly generation: string;\n readonly pi: ExtensionAPI;\n readonly context: () => ExtensionContext | undefined;\n}\n\n/**\n * Creates the shared notification router for one extension runtime.\n *\n * A missing session, invalid request, or delivery failure is an intentional\n * silent outcome because notification delivery must never fail the active turn.\n * RPC delivery never falls back to a host notifier after an append failure.\n */\nexport function createDoomNotificationRouter({\n generation,\n pi,\n context: readContext,\n}: DoomNotificationRouterOptions): DoomNotificationService {\n return Object.freeze({\n generation,\n async request(request: DoomNotificationRequest): Promise<void> {\n const context = readContext();\n if (!context) return;\n\n try {\n const normalized = normalizeDoomNotificationRequest(request);\n if (!normalized) return;\n const data = createDoomNotificationEntryData({\n title: normalized.title ?? DEFAULT_TITLE,\n subtitle: normalized.subtitle ?? pi.getSessionName() ?? path.basename(context.cwd),\n body: normalized.body,\n level: normalized.level ?? 'info',\n });\n if (!data) return;\n\n if (context.mode === 'rpc') {\n pi.appendEntry(DOOM_NOTIFICATION_ENTRY_TYPE, data);\n return;\n }\n await sendSystemNotification(pi, data);\n } catch (error) {\n // Best-effort delivery deliberately ends here. In particular, an RPC\n // append failure must not leak the notification through the host OS.\n void error;\n }\n },\n });\n}\n"],"mappings":"yPA4BA,SAAgB,EAA6B,CAC3C,aACA,KACA,QAAS,GACgD,CACzD,OAAO,OAAO,OAAO,CACnB,aACA,MAAM,QAAQ,EAAiD,CAC7D,IAAM,EAAU,EAAY,EACvB,KAEL,GAAI,CACF,IAAM,EAAa,EAAiC,CAAO,EAC3D,GAAI,CAAC,EAAY,OACjB,IAAM,EAAO,EAAgC,CAC3C,MAAO,EAAW,OAAS,KAC3B,SAAU,EAAW,UAAY,EAAG,eAAe,GAAK,EAAK,SAAS,EAAQ,GAAG,EACjF,KAAM,EAAW,KACjB,MAAO,EAAW,OAAS,MAC7B,CAAC,EACD,GAAI,CAAC,EAAM,OAEX,GAAI,EAAQ,OAAS,MAAO,CAC1B,EAAG,YAAY,EAA8B,CAAI,EACjD,MACF,CACA,MAAM,EAAuB,EAAI,CAAI,CACvC,MAAgB,CAIhB,CACF,CACF,CAAC,CACH"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
const e=require("./shellTitleController.cjs"),t=require("../services/notificationText/index.cjs"),n=require("../services/notificationPolicy/index.cjs"),r=require("./notificationRouter.cjs");let i=require("@agimon-ai/doompi-core/ask-user"),a=require("@agimon-ai/doompi-core/cordis-host"),o=require("@agimon-ai/doompi-core/notification");const s=Symbol.for(`@agimon-ai/doompi-notification/original-ui-method`);function c(e,t){let n=e[t],r=new Set;for(;typeof n==`function`&&!r.has(n);){r.add(n);let e=Reflect.get(n,s);if(typeof e!=`function`)break;n=e}return n}function l(e,t){Reflect.defineProperty(e,s,{configurable:!1,enumerable:!1,value:t,writable:!1})}function u(e,t,n,r,i){let a=c(e,`confirm`),o=(t,i,o)=>(n()&&r(`${t}: ${i}`),a.call(e,t,i,o));l(o,a),e.confirm=o;let s=c(e,`select`),u=(t,i,a)=>(n()&&r(t),s.call(e,t,i,a));l(u,s),e.select=u;let d=c(e,`input`),f=(t,i,a)=>(n()&&r(t),d.call(e,t,i,a));l(f,d),e.input=f;let p=c(e,`editor`),m=(t,i)=>(n()&&r(t),p.call(e,t,i));l(m,p),e.editor=m;let h=c(e,`notify`),g=(n,r)=>{t()?i(n,r):h.call(e,n,r)};return l(g,h),e.notify=g,()=>{e.confirm===o&&(e.confirm=a),e.select===u&&(e.select=s),e.input===f&&(e.input=d),e.editor===m&&(e.editor=p),e.notify===g&&(e.notify=h)}}function d({generation:s,pi:c,options:l}){let d,f=r.createDoomNotificationRouter({generation:s,pi:c,context:()=>d}),p=l.titleController??e.createWorkerTitleController(),m=new Map,h=!0,g=!1,_=!1,v,y,b=e=>t.shellTabTitle({cwd:e,sessionName:c.getSessionName(),prompt:v}),x=e=>{if(h&&n.supportsShellTitle(e))return y={cwd:e.cwd,write:t=>e.ui.setTitle(t)},y},S=e=>{h&&f.request(t.attentionNotification(e))},C=()=>{h=!1,g=!1,_=!1;for(let e of m.values())e();m.clear(),y&&p.dispose(b(y.cwd),y.write),y=void 0,d=void 0};return{services:[e=>{e.provide(o.DOOM_NOTIFICATION_SERVICE,f),e.inject([a.DOOM_CORDIS_SESSION_SERVICE],e=>{let t=e.get(a.DOOM_CORDIS_SESSION_SERVICE).context;return d=t,()=>{d===t&&(d=void 0)}}),e.effect(()=>e.on(i.DOOM_ASK_USER_PROMPT_EVENT,e=>{S(n.askUserPromptBody(e.questions))})),e.effect(()=>e.on(i.DOOM_ASK_USER_BLOCKED_EVENT,e=>{_=e.active}))}],onStop:C,onDispose:C,events:{input:(e,n)=>{if(!h||v||e.source===`extension`)return;d=n,v=t.promptTitle(e.text);let r=v?x(n):void 0;r&&p.set(b(r.cwd),r.write)},session_start:(e,t)=>{h&&!m.has(t.ui)&&(d=t,m.set(t.ui,u(t.ui,()=>h,()=>h&&n.warrantsAttentionNotification({agentRunning:g,askUserBlocked:_}),S,(e,t)=>void f.request({body:e,...t?{level:t}:{}}))))},agent_start:(e,t)=>{if(!h)return;d=t,g=!0;let n=x(t);n&&p.start(b(n.cwd),n.write)},agent_settled:async(e,r)=>{if(!h)return;d=r,g=!1,_=!1;let i=x(r);i&&p.stop(b(i.cwd),i.write),n.warrantsSettledNotification(r.hasPendingMessages())&&await f.request(t.settledNotification({cwd:r.cwd,sessionName:c.getSessionName()}))}}}}exports.createNotificationRuntime=d;
|
|
2
|
+
//# sourceMappingURL=notificationRuntime.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"notificationRuntime.cjs","names":["createDoomNotificationRouter","createWorkerTitleController","shellTabTitle","supportsShellTitle","attentionNotification","DOOM_NOTIFICATION_SERVICE","DOOM_CORDIS_SESSION_SERVICE","DOOM_ASK_USER_PROMPT_EVENT","askUserPromptBody","DOOM_ASK_USER_BLOCKED_EVENT","promptTitle","warrantsAttentionNotification","warrantsSettledNotification","settledNotification"],"sources":["../../src/controllers/notificationRuntime.ts"],"sourcesContent":["import { DOOM_ASK_USER_BLOCKED_EVENT, DOOM_ASK_USER_PROMPT_EVENT } from '@agimon-ai/doompi-core/ask-user';\nimport { DOOM_CORDIS_SESSION_SERVICE, type DoomCordisSessionService } from '@agimon-ai/doompi-core/cordis-host';\nimport { DOOM_NOTIFICATION_SERVICE, type DoomNotificationLevel } from '@agimon-ai/doompi-core/notification';\nimport type { PiPluginContributions } from '@agimon-ai/doompi-core/pi-extension';\nimport type { Context } from '@deepseek-ai/cordis';\nimport type { ExtensionAPI, ExtensionContext, ExtensionUIContext } from '@earendil-works/pi-coding-agent';\n\nimport {\n askUserPromptBody,\n supportsShellTitle,\n warrantsAttentionNotification,\n warrantsSettledNotification,\n} from '../services/notificationPolicy';\nimport { attentionNotification, promptTitle, settledNotification, shellTabTitle } from '../services/notificationText';\nimport type { ShellTitleController, WriteTitle } from '../types/notifications';\nimport { createDoomNotificationRouter } from './notificationRouter';\nimport { createWorkerTitleController } from './shellTitleController';\n\nconst AGENT_SETTLED_EVENT = 'agent_settled';\nconst AGENT_START_EVENT = 'agent_start';\nconst EXTENSION_INPUT_SOURCE = 'extension';\nconst INPUT_EVENT = 'input';\nconst SESSION_START_EVENT = 'session_start';\n\nexport interface NotificationExtensionOptions {\n /** Replaces the worker-thread animator, which a host without worker threads cannot start. */\n titleController?: ShellTitleController;\n environment?: NodeJS.ProcessEnv;\n}\n\n/** Where the tab title is written, remembered so shutdown can restore it without an event. */\ninterface TitleSurface {\n cwd: string;\n write: WriteTitle;\n}\n\ntype WrappedUiMethod = 'confirm' | 'editor' | 'input' | 'notify' | 'select';\n\nconst ORIGINAL_UI_METHOD = Symbol.for('@agimon-ai/doompi-notification/original-ui-method');\n\n/** Capture the true host method even when another bundle copy currently owns the UI. */\nfunction captureUiMethod<Method extends WrappedUiMethod>(\n ui: ExtensionUIContext,\n method: Method,\n): ExtensionUIContext[Method] {\n let captured: unknown = ui[method];\n const seen = new Set<unknown>();\n while (typeof captured === 'function' && !seen.has(captured)) {\n seen.add(captured);\n const original = Reflect.get(captured, ORIGINAL_UI_METHOD) as unknown;\n if (typeof original !== 'function') break;\n captured = original;\n }\n return captured as ExtensionUIContext[Method];\n}\n\nfunction tagUiWrapper(wrapper: object, original: object): void {\n Reflect.defineProperty(wrapper, ORIGINAL_UI_METHOD, {\n configurable: false,\n enumerable: false,\n value: original,\n writable: false,\n });\n}\n\n/**\n * Routes UI notices and announces dialogs the agent opens on its own initiative.\n * Dialog wrappers preserve the original behavior. The notice wrapper replaces\n * host delivery while this plugin owns the UI and restores its exact identity.\n */\nfunction wrapUiNotifications(\n ui: ExtensionUIContext,\n isActive: () => boolean,\n shouldNotifyAttention: () => boolean,\n notifyAttention: (body: string) => void,\n notify: (body: string, level?: DoomNotificationLevel) => void,\n): () => void {\n const originalConfirm = captureUiMethod(ui, 'confirm');\n const wrappedConfirm: ExtensionUIContext['confirm'] = (title, message, options) => {\n if (shouldNotifyAttention()) notifyAttention(`${title}: ${message}`);\n return originalConfirm.call(ui, title, message, options);\n };\n tagUiWrapper(wrappedConfirm, originalConfirm);\n ui.confirm = wrappedConfirm;\n\n const originalSelect = captureUiMethod(ui, 'select');\n const wrappedSelect: ExtensionUIContext['select'] = (title, options, dialogOptions) => {\n if (shouldNotifyAttention()) notifyAttention(title);\n return originalSelect.call(ui, title, options, dialogOptions);\n };\n tagUiWrapper(wrappedSelect, originalSelect);\n ui.select = wrappedSelect;\n\n const originalInput = captureUiMethod(ui, 'input');\n const wrappedInput: ExtensionUIContext['input'] = (title, placeholder, options) => {\n if (shouldNotifyAttention()) notifyAttention(title);\n return originalInput.call(ui, title, placeholder, options);\n };\n tagUiWrapper(wrappedInput, originalInput);\n ui.input = wrappedInput;\n\n const originalEditor = captureUiMethod(ui, 'editor');\n const wrappedEditor: ExtensionUIContext['editor'] = (title, prefill) => {\n if (shouldNotifyAttention()) notifyAttention(title);\n return originalEditor.call(ui, title, prefill);\n };\n tagUiWrapper(wrappedEditor, originalEditor);\n ui.editor = wrappedEditor;\n\n const originalNotify = captureUiMethod(ui, 'notify');\n const wrappedNotify: ExtensionUIContext['notify'] = (message, level) => {\n if (isActive()) notify(message, level);\n else originalNotify.call(ui, message, level);\n };\n tagUiWrapper(wrappedNotify, originalNotify);\n ui.notify = wrappedNotify;\n\n return () => {\n if (ui.confirm === wrappedConfirm) ui.confirm = originalConfirm;\n if (ui.select === wrappedSelect) ui.select = originalSelect;\n if (ui.input === wrappedInput) ui.input = originalInput;\n if (ui.editor === wrappedEditor) ui.editor = originalEditor;\n if (ui.notify === wrappedNotify) ui.notify = originalNotify;\n };\n}\n\ninterface NotificationPluginConfig {\n readonly generation: string;\n readonly pi: ExtensionAPI;\n readonly options: NotificationExtensionOptions;\n}\n\nexport function createNotificationRuntime({\n generation,\n pi,\n options,\n}: NotificationPluginConfig): PiPluginContributions<NotificationExtensionOptions> {\n let activeContext: ExtensionContext | undefined;\n const router = createDoomNotificationRouter({ generation, pi, context: () => activeContext });\n\n const titles = options.titleController ?? createWorkerTitleController();\n const wrappedUis = new Map<ExtensionUIContext, () => void>();\n let active = true;\n let agentRunning = false;\n let askUserBlocked = false;\n let firstPrompt: string | undefined;\n let surface: TitleSurface | undefined;\n\n const idleTitle = (cwd: string): string =>\n shellTabTitle({ cwd, sessionName: pi.getSessionName(), prompt: firstPrompt });\n const titleSurface = (context: ExtensionContext): TitleSurface | undefined => {\n if (!active || !supportsShellTitle(context)) return undefined;\n surface = { cwd: context.cwd, write: (title) => context.ui.setTitle(title) };\n return surface;\n };\n const notifyAttention = (body: string): void => {\n if (active) void router.request(attentionNotification(body));\n };\n\n const stop = (): void => {\n active = false;\n agentRunning = false;\n askUserBlocked = false;\n for (const restore of wrappedUis.values()) restore();\n wrappedUis.clear();\n if (surface) titles.dispose(idleTitle(surface.cwd), surface.write);\n surface = undefined;\n activeContext = undefined;\n };\n return {\n services: [\n (cordis: Context) => {\n cordis.provide(DOOM_NOTIFICATION_SERVICE, router);\n cordis.inject([DOOM_CORDIS_SESSION_SERVICE], (sessionContext) => {\n const session = sessionContext.get(DOOM_CORDIS_SESSION_SERVICE) as DoomCordisSessionService;\n const context = session.context;\n activeContext = context;\n return () => {\n if (activeContext === context) activeContext = undefined;\n };\n });\n cordis.effect(() =>\n cordis.on(DOOM_ASK_USER_PROMPT_EVENT, (prompt) => {\n notifyAttention(askUserPromptBody(prompt.questions));\n }),\n );\n cordis.effect(() =>\n cordis.on(DOOM_ASK_USER_BLOCKED_EVENT, (payload) => {\n askUserBlocked = payload.active;\n }),\n );\n },\n ],\n onStop: stop,\n onDispose: stop,\n events: {\n [INPUT_EVENT]: (event, context) => {\n if (!active || firstPrompt || event.source === EXTENSION_INPUT_SOURCE) return;\n activeContext = context;\n firstPrompt = promptTitle(event.text);\n const target = firstPrompt ? titleSurface(context) : undefined;\n if (target) titles.set(idleTitle(target.cwd), target.write);\n },\n [SESSION_START_EVENT]: (_event, context) => {\n if (!active || wrappedUis.has(context.ui)) return;\n activeContext = context;\n wrappedUis.set(\n context.ui,\n wrapUiNotifications(\n context.ui,\n () => active,\n () => active && warrantsAttentionNotification({ agentRunning, askUserBlocked }),\n notifyAttention,\n (body, level) => void router.request({ body, ...(level ? { level } : {}) }),\n ),\n );\n },\n [AGENT_START_EVENT]: (_event, context) => {\n if (!active) return;\n activeContext = context;\n agentRunning = true;\n const target = titleSurface(context);\n if (target) titles.start(idleTitle(target.cwd), target.write);\n },\n [AGENT_SETTLED_EVENT]: async (_event, context) => {\n if (!active) return;\n activeContext = context;\n agentRunning = false;\n askUserBlocked = false;\n const target = titleSurface(context);\n if (target) titles.stop(idleTitle(target.cwd), target.write);\n if (!warrantsSettledNotification(context.hasPendingMessages())) return;\n await router.request(settledNotification({ cwd: context.cwd, sessionName: pi.getSessionName() }));\n },\n },\n };\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { ShellTitleController } from "../types/notifications.cjs";
|
|
2
|
+
import "@agimon-ai/doompi-core/pi-extension";
|
|
3
|
+
import { ExtensionAPI } from "@earendil-works/pi-coding-agent";
|
|
4
|
+
//#region src/controllers/notificationRuntime.d.ts
|
|
5
|
+
export interface NotificationExtensionOptions {
|
|
6
|
+
/** Replaces the worker-thread animator, which a host without worker threads cannot start. */
|
|
7
|
+
titleController?: ShellTitleController;
|
|
8
|
+
environment?: NodeJS.ProcessEnv;
|
|
9
|
+
}
|
|
10
|
+
//#endregion
|
|
11
|
+
//# sourceMappingURL=notificationRuntime.d.cts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"notificationRuntime.d.cts","names":[],"sources":["../../src/controllers/notificationRuntime.ts"],"mappings":";;;;iBAwBiB;;EAEf,kBAAkB;EAClB,cAAc,OAAO"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { ShellTitleController } from "../types/notifications.mjs";
|
|
2
|
+
import "@agimon-ai/doompi-core/pi-extension";
|
|
3
|
+
import { ExtensionAPI } from "@earendil-works/pi-coding-agent";
|
|
4
|
+
//#region src/controllers/notificationRuntime.d.ts
|
|
5
|
+
export interface NotificationExtensionOptions {
|
|
6
|
+
/** Replaces the worker-thread animator, which a host without worker threads cannot start. */
|
|
7
|
+
titleController?: ShellTitleController;
|
|
8
|
+
environment?: NodeJS.ProcessEnv;
|
|
9
|
+
}
|
|
10
|
+
//#endregion
|
|
11
|
+
//# sourceMappingURL=notificationRuntime.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"notificationRuntime.d.mts","names":[],"sources":["../../src/controllers/notificationRuntime.ts"],"mappings":";;;;iBAwBiB;;EAEf,kBAAkB;EAClB,cAAc,OAAO"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{createWorkerTitleController as e}from"./shellTitleController.mjs";import{attentionNotification as t,promptTitle as n,settledNotification as r,shellTabTitle as i}from"../services/notificationText/index.mjs";import{askUserPromptBody as a,supportsShellTitle as o,warrantsAttentionNotification as s,warrantsSettledNotification as c}from"../services/notificationPolicy/index.mjs";import{createDoomNotificationRouter as l}from"./notificationRouter.mjs";import{DOOM_ASK_USER_BLOCKED_EVENT as u,DOOM_ASK_USER_PROMPT_EVENT as d}from"@agimon-ai/doompi-core/ask-user";import{DOOM_CORDIS_SESSION_SERVICE as f}from"@agimon-ai/doompi-core/cordis-host";import{DOOM_NOTIFICATION_SERVICE as p}from"@agimon-ai/doompi-core/notification";const m=Symbol.for(`@agimon-ai/doompi-notification/original-ui-method`);function h(e,t){let n=e[t],r=new Set;for(;typeof n==`function`&&!r.has(n);){r.add(n);let e=Reflect.get(n,m);if(typeof e!=`function`)break;n=e}return n}function g(e,t){Reflect.defineProperty(e,m,{configurable:!1,enumerable:!1,value:t,writable:!1})}function _(e,t,n,r,i){let a=h(e,`confirm`),o=(t,i,o)=>(n()&&r(`${t}: ${i}`),a.call(e,t,i,o));g(o,a),e.confirm=o;let s=h(e,`select`),c=(t,i,a)=>(n()&&r(t),s.call(e,t,i,a));g(c,s),e.select=c;let l=h(e,`input`),u=(t,i,a)=>(n()&&r(t),l.call(e,t,i,a));g(u,l),e.input=u;let d=h(e,`editor`),f=(t,i)=>(n()&&r(t),d.call(e,t,i));g(f,d),e.editor=f;let p=h(e,`notify`),m=(n,r)=>{t()?i(n,r):p.call(e,n,r)};return g(m,p),e.notify=m,()=>{e.confirm===o&&(e.confirm=a),e.select===c&&(e.select=s),e.input===u&&(e.input=l),e.editor===f&&(e.editor=d),e.notify===m&&(e.notify=p)}}function v({generation:m,pi:h,options:g}){let v,y=l({generation:m,pi:h,context:()=>v}),b=g.titleController??e(),x=new Map,S=!0,C=!1,w=!1,T,E,D=e=>i({cwd:e,sessionName:h.getSessionName(),prompt:T}),O=e=>{if(S&&o(e))return E={cwd:e.cwd,write:t=>e.ui.setTitle(t)},E},k=e=>{S&&y.request(t(e))},A=()=>{S=!1,C=!1,w=!1;for(let e of x.values())e();x.clear(),E&&b.dispose(D(E.cwd),E.write),E=void 0,v=void 0};return{services:[e=>{e.provide(p,y),e.inject([f],e=>{let t=e.get(f).context;return v=t,()=>{v===t&&(v=void 0)}}),e.effect(()=>e.on(d,e=>{k(a(e.questions))})),e.effect(()=>e.on(u,e=>{w=e.active}))}],onStop:A,onDispose:A,events:{input:(e,t)=>{if(!S||T||e.source===`extension`)return;v=t,T=n(e.text);let r=T?O(t):void 0;r&&b.set(D(r.cwd),r.write)},session_start:(e,t)=>{S&&!x.has(t.ui)&&(v=t,x.set(t.ui,_(t.ui,()=>S,()=>S&&s({agentRunning:C,askUserBlocked:w}),k,(e,t)=>void y.request({body:e,...t?{level:t}:{}}))))},agent_start:(e,t)=>{if(!S)return;v=t,C=!0;let n=O(t);n&&b.start(D(n.cwd),n.write)},agent_settled:async(e,t)=>{if(!S)return;v=t,C=!1,w=!1;let n=O(t);n&&b.stop(D(n.cwd),n.write),c(t.hasPendingMessages())&&await y.request(r({cwd:t.cwd,sessionName:h.getSessionName()}))}}}}export{v as createNotificationRuntime};
|
|
2
|
+
//# sourceMappingURL=notificationRuntime.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"notificationRuntime.mjs","names":[],"sources":["../../src/controllers/notificationRuntime.ts"],"sourcesContent":["import { DOOM_ASK_USER_BLOCKED_EVENT, DOOM_ASK_USER_PROMPT_EVENT } from '@agimon-ai/doompi-core/ask-user';\nimport { DOOM_CORDIS_SESSION_SERVICE, type DoomCordisSessionService } from '@agimon-ai/doompi-core/cordis-host';\nimport { DOOM_NOTIFICATION_SERVICE, type DoomNotificationLevel } from '@agimon-ai/doompi-core/notification';\nimport type { PiPluginContributions } from '@agimon-ai/doompi-core/pi-extension';\nimport type { Context } from '@deepseek-ai/cordis';\nimport type { ExtensionAPI, ExtensionContext, ExtensionUIContext } from '@earendil-works/pi-coding-agent';\n\nimport {\n askUserPromptBody,\n supportsShellTitle,\n warrantsAttentionNotification,\n warrantsSettledNotification,\n} from '../services/notificationPolicy';\nimport { attentionNotification, promptTitle, settledNotification, shellTabTitle } from '../services/notificationText';\nimport type { ShellTitleController, WriteTitle } from '../types/notifications';\nimport { createDoomNotificationRouter } from './notificationRouter';\nimport { createWorkerTitleController } from './shellTitleController';\n\nconst AGENT_SETTLED_EVENT = 'agent_settled';\nconst AGENT_START_EVENT = 'agent_start';\nconst EXTENSION_INPUT_SOURCE = 'extension';\nconst INPUT_EVENT = 'input';\nconst SESSION_START_EVENT = 'session_start';\n\nexport interface NotificationExtensionOptions {\n /** Replaces the worker-thread animator, which a host without worker threads cannot start. */\n titleController?: ShellTitleController;\n environment?: NodeJS.ProcessEnv;\n}\n\n/** Where the tab title is written, remembered so shutdown can restore it without an event. */\ninterface TitleSurface {\n cwd: string;\n write: WriteTitle;\n}\n\ntype WrappedUiMethod = 'confirm' | 'editor' | 'input' | 'notify' | 'select';\n\nconst ORIGINAL_UI_METHOD = Symbol.for('@agimon-ai/doompi-notification/original-ui-method');\n\n/** Capture the true host method even when another bundle copy currently owns the UI. */\nfunction captureUiMethod<Method extends WrappedUiMethod>(\n ui: ExtensionUIContext,\n method: Method,\n): ExtensionUIContext[Method] {\n let captured: unknown = ui[method];\n const seen = new Set<unknown>();\n while (typeof captured === 'function' && !seen.has(captured)) {\n seen.add(captured);\n const original = Reflect.get(captured, ORIGINAL_UI_METHOD) as unknown;\n if (typeof original !== 'function') break;\n captured = original;\n }\n return captured as ExtensionUIContext[Method];\n}\n\nfunction tagUiWrapper(wrapper: object, original: object): void {\n Reflect.defineProperty(wrapper, ORIGINAL_UI_METHOD, {\n configurable: false,\n enumerable: false,\n value: original,\n writable: false,\n });\n}\n\n/**\n * Routes UI notices and announces dialogs the agent opens on its own initiative.\n * Dialog wrappers preserve the original behavior. The notice wrapper replaces\n * host delivery while this plugin owns the UI and restores its exact identity.\n */\nfunction wrapUiNotifications(\n ui: ExtensionUIContext,\n isActive: () => boolean,\n shouldNotifyAttention: () => boolean,\n notifyAttention: (body: string) => void,\n notify: (body: string, level?: DoomNotificationLevel) => void,\n): () => void {\n const originalConfirm = captureUiMethod(ui, 'confirm');\n const wrappedConfirm: ExtensionUIContext['confirm'] = (title, message, options) => {\n if (shouldNotifyAttention()) notifyAttention(`${title}: ${message}`);\n return originalConfirm.call(ui, title, message, options);\n };\n tagUiWrapper(wrappedConfirm, originalConfirm);\n ui.confirm = wrappedConfirm;\n\n const originalSelect = captureUiMethod(ui, 'select');\n const wrappedSelect: ExtensionUIContext['select'] = (title, options, dialogOptions) => {\n if (shouldNotifyAttention()) notifyAttention(title);\n return originalSelect.call(ui, title, options, dialogOptions);\n };\n tagUiWrapper(wrappedSelect, originalSelect);\n ui.select = wrappedSelect;\n\n const originalInput = captureUiMethod(ui, 'input');\n const wrappedInput: ExtensionUIContext['input'] = (title, placeholder, options) => {\n if (shouldNotifyAttention()) notifyAttention(title);\n return originalInput.call(ui, title, placeholder, options);\n };\n tagUiWrapper(wrappedInput, originalInput);\n ui.input = wrappedInput;\n\n const originalEditor = captureUiMethod(ui, 'editor');\n const wrappedEditor: ExtensionUIContext['editor'] = (title, prefill) => {\n if (shouldNotifyAttention()) notifyAttention(title);\n return originalEditor.call(ui, title, prefill);\n };\n tagUiWrapper(wrappedEditor, originalEditor);\n ui.editor = wrappedEditor;\n\n const originalNotify = captureUiMethod(ui, 'notify');\n const wrappedNotify: ExtensionUIContext['notify'] = (message, level) => {\n if (isActive()) notify(message, level);\n else originalNotify.call(ui, message, level);\n };\n tagUiWrapper(wrappedNotify, originalNotify);\n ui.notify = wrappedNotify;\n\n return () => {\n if (ui.confirm === wrappedConfirm) ui.confirm = originalConfirm;\n if (ui.select === wrappedSelect) ui.select = originalSelect;\n if (ui.input === wrappedInput) ui.input = originalInput;\n if (ui.editor === wrappedEditor) ui.editor = originalEditor;\n if (ui.notify === wrappedNotify) ui.notify = originalNotify;\n };\n}\n\ninterface NotificationPluginConfig {\n readonly generation: string;\n readonly pi: ExtensionAPI;\n readonly options: NotificationExtensionOptions;\n}\n\nexport function createNotificationRuntime({\n generation,\n pi,\n options,\n}: NotificationPluginConfig): PiPluginContributions<NotificationExtensionOptions> {\n let activeContext: ExtensionContext | undefined;\n const router = createDoomNotificationRouter({ generation, pi, context: () => activeContext });\n\n const titles = options.titleController ?? createWorkerTitleController();\n const wrappedUis = new Map<ExtensionUIContext, () => void>();\n let active = true;\n let agentRunning = false;\n let askUserBlocked = false;\n let firstPrompt: string | undefined;\n let surface: TitleSurface | undefined;\n\n const idleTitle = (cwd: string): string =>\n shellTabTitle({ cwd, sessionName: pi.getSessionName(), prompt: firstPrompt });\n const titleSurface = (context: ExtensionContext): TitleSurface | undefined => {\n if (!active || !supportsShellTitle(context)) return undefined;\n surface = { cwd: context.cwd, write: (title) => context.ui.setTitle(title) };\n return surface;\n };\n const notifyAttention = (body: string): void => {\n if (active) void router.request(attentionNotification(body));\n };\n\n const stop = (): void => {\n active = false;\n agentRunning = false;\n askUserBlocked = false;\n for (const restore of wrappedUis.values()) restore();\n wrappedUis.clear();\n if (surface) titles.dispose(idleTitle(surface.cwd), surface.write);\n surface = undefined;\n activeContext = undefined;\n };\n return {\n services: [\n (cordis: Context) => {\n cordis.provide(DOOM_NOTIFICATION_SERVICE, router);\n cordis.inject([DOOM_CORDIS_SESSION_SERVICE], (sessionContext) => {\n const session = sessionContext.get(DOOM_CORDIS_SESSION_SERVICE) as DoomCordisSessionService;\n const context = session.context;\n activeContext = context;\n return () => {\n if (activeContext === context) activeContext = undefined;\n };\n });\n cordis.effect(() =>\n cordis.on(DOOM_ASK_USER_PROMPT_EVENT, (prompt) => {\n notifyAttention(askUserPromptBody(prompt.questions));\n }),\n );\n cordis.effect(() =>\n cordis.on(DOOM_ASK_USER_BLOCKED_EVENT, (payload) => {\n askUserBlocked = payload.active;\n }),\n );\n },\n ],\n onStop: stop,\n onDispose: stop,\n events: {\n [INPUT_EVENT]: (event, context) => {\n if (!active || firstPrompt || event.source === EXTENSION_INPUT_SOURCE) return;\n activeContext = context;\n firstPrompt = promptTitle(event.text);\n const target = firstPrompt ? titleSurface(context) : undefined;\n if (target) titles.set(idleTitle(target.cwd), target.write);\n },\n [SESSION_START_EVENT]: (_event, context) => {\n if (!active || wrappedUis.has(context.ui)) return;\n activeContext = context;\n wrappedUis.set(\n context.ui,\n wrapUiNotifications(\n context.ui,\n () => active,\n () => active && warrantsAttentionNotification({ agentRunning, askUserBlocked }),\n notifyAttention,\n (body, level) => void router.request({ body, ...(level ? { level } : {}) }),\n ),\n );\n },\n [AGENT_START_EVENT]: (_event, context) => {\n if (!active) return;\n activeContext = context;\n agentRunning = true;\n const target = titleSurface(context);\n if (target) titles.start(idleTitle(target.cwd), target.write);\n },\n [AGENT_SETTLED_EVENT]: async (_event, context) => {\n if (!active) return;\n activeContext = context;\n agentRunning = false;\n askUserBlocked = false;\n const target = titleSurface(context);\n if (target) titles.stop(idleTitle(target.cwd), target.write);\n if (!warrantsSettledNotification(context.hasPendingMessages())) return;\n await router.request(settledNotification({ cwd: context.cwd, sessionName: pi.getSessionName() }));\n },\n },\n };\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"shellTitleController.cjs","names":["Worker"],"sources":["../../src/controllers/shellTitleController.ts"],"sourcesContent":["import { Worker } from 'node:worker_threads';\n\nimport type { ShellTitleCommand, ShellTitleController, WriteTitle } from '../types/notifications';\n\nconst BRAILLE_FRAMES = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'];\nconst TITLE_FRAME_INTERVAL_MS = 80;\n/**\n * The animator runs off the main thread so a busy agent turn cannot stall the\n * spinner. It is an inline eval source rather than a shipped file because the\n * package is bundled per entry, and a separate worker module would have to be\n * located on disk at runtime.\n */\nconst TITLE_WORKER_SOURCE = `\nconst { writeSync } = require('node:fs');\nconst { parentPort, workerData } = require('node:worker_threads');\nlet frameIndex = 0;\nlet timer;\nconst writeTitle = (title) => writeSync(1, '\\\\u001b]0;' + title + '\\\\u0007');\nconst stop = () => {\n if (timer) clearInterval(timer);\n timer = undefined;\n frameIndex = 0;\n};\nparentPort.on('message', (command) => {\n stop();\n if (command.action === 'start') {\n const render = () => {\n writeTitle(workerData.frames[frameIndex % workerData.frames.length] + ' ' + command.title);\n frameIndex += 1;\n };\n render();\n timer = setInterval(render, workerData.intervalMs);\n return;\n }\n writeTitle(command.title);\n if (command.action === 'dispose') parentPort.close();\n});\n`;\n\n/** Animates on the main thread, for hosts where a worker could not be started. */\nexport function createMainThreadTitleController(): ShellTitleController {\n let frameIndex = 0;\n let timer: ReturnType<typeof setInterval> | undefined;\n const stopAnimation = () => {\n if (timer) clearInterval(timer);\n timer = undefined;\n frameIndex = 0;\n };\n\n return {\n set(title, write) {\n stopAnimation();\n write(title);\n },\n start(title, write) {\n stopAnimation();\n const render = () => {\n write(`${BRAILLE_FRAMES[frameIndex % BRAILLE_FRAMES.length]} ${title}`);\n frameIndex += 1;\n };\n render();\n timer = setInterval(render, TITLE_FRAME_INTERVAL_MS);\n },\n stop(title, write) {\n stopAnimation();\n write(title);\n },\n dispose(title, write) {\n stopAnimation();\n write(title);\n },\n };\n}\n\n/**\n * Animates from a worker thread, replaying the last command on the main thread\n * if the worker never started, failed, or exited under us. The worker is\n * unreferenced so a pending frame never holds the process open.\n */\nexport function createWorkerTitleController(): ShellTitleController {\n const fallback = createMainThreadTitleController();\n let lastCommand: ShellTitleCommand | undefined;\n let lastWrite: WriteTitle | undefined;\n let worker: Worker | undefined;\n\n const fallBack = () => {\n worker = undefined;\n if (!lastCommand || !lastWrite) return;\n fallback[lastCommand.action](lastCommand.title, lastWrite);\n };\n\n try {\n const titleWorker = new Worker(TITLE_WORKER_SOURCE, {\n eval: true,\n workerData: { frames: BRAILLE_FRAMES, intervalMs: TITLE_FRAME_INTERVAL_MS },\n });\n titleWorker.unref();\n titleWorker.once('error', fallBack);\n titleWorker.once('exit', (code) => {\n if (code !== 0 && worker === titleWorker) fallBack();\n });\n worker = titleWorker;\n } catch {\n // Workers are unavailable on this host, which the main-thread animator covers.\n worker = undefined;\n }\n\n const dispatch = (command: ShellTitleCommand, write: WriteTitle) => {\n lastCommand = command;\n lastWrite = write;\n if (!worker) {\n fallback[command.action](command.title, write);\n return;\n }\n try {\n worker.postMessage(command);\n } catch {\n // The worker closed between the last frame and this command.\n fallBack();\n }\n };\n\n return {\n set: (title, write) => dispatch({ action: 'set', title }, write),\n start: (title, write) => dispatch({ action: 'start', title }, write),\n stop: (title, write) => dispatch({ action: 'stop', title }, write),\n dispose: (title, write) => dispatch({ action: 'dispose', title }, write),\n };\n}\n"],"mappings":"qCAIA,MAAM,EAAiB,CAAC,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,GAAG,EAoCxE,SAAgB,GAAwD,CACtE,IAAI,EAAa,EACb,EACE,MAAsB,CACtB,GAAO,cAAc,CAAK,EAC9B,EAAQ,IAAA,GACR,EAAa,CACf,EAEA,MAAO,CACL,IAAI,EAAO,EAAO,CAChB,EAAc,EACd,EAAM,CAAK,CACb,EACA,MAAM,EAAO,EAAO,CAClB,EAAc,EACd,IAAM,MAAe,CACnB,EAAM,GAAG,EAAe,EAAa,EAAe,QAAQ,GAAG,GAAO,EACtE,GAAc,CAChB,EACA,EAAO,EACP,EAAQ,YAAY,EAAQ,EAAuB,CACrD,EACA,KAAK,EAAO,EAAO,CACjB,EAAc,EACd,EAAM,CAAK,CACb,EACA,QAAQ,EAAO,EAAO,CACpB,EAAc,EACd,EAAM,CAAK,CACb,CACF,CACF,CAOA,SAAgB,GAAoD,CAClE,IAAM,EAAW,EAAgC,EAC7C,EACA,EACA,EAEE,MAAiB,CACrB,EAAS,IAAA,GACJ,GAAgB,GACrB,EAAS,EAAY,OAAO,CAAC,EAAY,MAAO,CAAS,CAC3D,EAEA,GAAI,CACF,IAAM,EAAc,IAAIA,EAAAA,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;EAAqB,CAClD,KAAM,GACN,WAAY,CAAE,OAAQ,EAAgB,WAAY,EAAwB,CAC5E,CAAC,EACD,EAAY,MAAM,EAClB,EAAY,KAAK,QAAS,CAAQ,EAClC,EAAY,KAAK,OAAS,GAAS,CAC7B,IAAS,GAAK,IAAW,GAAa,EAAS,CACrD,CAAC,EACD,EAAS,CACX,MAAQ,CAEN,EAAS,IAAA,EACX,CAEA,IAAM,GAAY,EAA4B,IAAsB,CAGlE,GAFA,EAAc,EACd,EAAY,EACR,CAAC,EAAQ,CACX,EAAS,EAAQ,OAAO,CAAC,EAAQ,MAAO,CAAK,EAC7C,MACF,CACA,GAAI,CACF,EAAO,YAAY,CAAO,CAC5B,MAAQ,CAEN,EAAS,CACX,CACF,EAEA,MAAO,CACL,KAAM,EAAO,IAAU,EAAS,CAAE,OAAQ,MAAO,OAAM,EAAG,CAAK,EAC/D,OAAQ,EAAO,IAAU,EAAS,CAAE,OAAQ,QAAS,OAAM,EAAG,CAAK,EACnE,MAAO,EAAO,IAAU,EAAS,CAAE,OAAQ,OAAQ,OAAM,EAAG,CAAK,EACjE,SAAU,EAAO,IAAU,EAAS,CAAE,OAAQ,UAAW,OAAM,EAAG,CAAK,CACzE,CACF"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ShellTitleController } from "../types/notifications.cjs";
|
|
2
|
-
//#region src/
|
|
2
|
+
//#region src/controllers/shellTitleController.d.ts
|
|
3
3
|
/** Animates on the main thread, for hosts where a worker could not be started. */
|
|
4
4
|
export declare function createMainThreadTitleController(): ShellTitleController;
|
|
5
5
|
/**
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"shellTitleController.d.cts","names":[],"sources":["../../src/controllers/shellTitleController.ts"],"mappings":";;;wBAwCgB,mCAAmC;;;;;;wBAuCnC,+BAA+B"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ShellTitleController } from "../types/notifications.mjs";
|
|
2
|
-
//#region src/
|
|
2
|
+
//#region src/controllers/shellTitleController.d.ts
|
|
3
3
|
/** Animates on the main thread, for hosts where a worker could not be started. */
|
|
4
4
|
export declare function createMainThreadTitleController(): ShellTitleController;
|
|
5
5
|
/**
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"shellTitleController.d.mts","names":[],"sources":["../../src/controllers/shellTitleController.ts"],"mappings":";;;wBAwCgB,mCAAmC;;;;;;wBAuCnC,+BAA+B"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"shellTitleController.mjs","names":[],"sources":["../../src/controllers/shellTitleController.ts"],"sourcesContent":["import { Worker } from 'node:worker_threads';\n\nimport type { ShellTitleCommand, ShellTitleController, WriteTitle } from '../types/notifications';\n\nconst BRAILLE_FRAMES = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'];\nconst TITLE_FRAME_INTERVAL_MS = 80;\n/**\n * The animator runs off the main thread so a busy agent turn cannot stall the\n * spinner. It is an inline eval source rather than a shipped file because the\n * package is bundled per entry, and a separate worker module would have to be\n * located on disk at runtime.\n */\nconst TITLE_WORKER_SOURCE = `\nconst { writeSync } = require('node:fs');\nconst { parentPort, workerData } = require('node:worker_threads');\nlet frameIndex = 0;\nlet timer;\nconst writeTitle = (title) => writeSync(1, '\\\\u001b]0;' + title + '\\\\u0007');\nconst stop = () => {\n if (timer) clearInterval(timer);\n timer = undefined;\n frameIndex = 0;\n};\nparentPort.on('message', (command) => {\n stop();\n if (command.action === 'start') {\n const render = () => {\n writeTitle(workerData.frames[frameIndex % workerData.frames.length] + ' ' + command.title);\n frameIndex += 1;\n };\n render();\n timer = setInterval(render, workerData.intervalMs);\n return;\n }\n writeTitle(command.title);\n if (command.action === 'dispose') parentPort.close();\n});\n`;\n\n/** Animates on the main thread, for hosts where a worker could not be started. */\nexport function createMainThreadTitleController(): ShellTitleController {\n let frameIndex = 0;\n let timer: ReturnType<typeof setInterval> | undefined;\n const stopAnimation = () => {\n if (timer) clearInterval(timer);\n timer = undefined;\n frameIndex = 0;\n };\n\n return {\n set(title, write) {\n stopAnimation();\n write(title);\n },\n start(title, write) {\n stopAnimation();\n const render = () => {\n write(`${BRAILLE_FRAMES[frameIndex % BRAILLE_FRAMES.length]} ${title}`);\n frameIndex += 1;\n };\n render();\n timer = setInterval(render, TITLE_FRAME_INTERVAL_MS);\n },\n stop(title, write) {\n stopAnimation();\n write(title);\n },\n dispose(title, write) {\n stopAnimation();\n write(title);\n },\n };\n}\n\n/**\n * Animates from a worker thread, replaying the last command on the main thread\n * if the worker never started, failed, or exited under us. The worker is\n * unreferenced so a pending frame never holds the process open.\n */\nexport function createWorkerTitleController(): ShellTitleController {\n const fallback = createMainThreadTitleController();\n let lastCommand: ShellTitleCommand | undefined;\n let lastWrite: WriteTitle | undefined;\n let worker: Worker | undefined;\n\n const fallBack = () => {\n worker = undefined;\n if (!lastCommand || !lastWrite) return;\n fallback[lastCommand.action](lastCommand.title, lastWrite);\n };\n\n try {\n const titleWorker = new Worker(TITLE_WORKER_SOURCE, {\n eval: true,\n workerData: { frames: BRAILLE_FRAMES, intervalMs: TITLE_FRAME_INTERVAL_MS },\n });\n titleWorker.unref();\n titleWorker.once('error', fallBack);\n titleWorker.once('exit', (code) => {\n if (code !== 0 && worker === titleWorker) fallBack();\n });\n worker = titleWorker;\n } catch {\n // Workers are unavailable on this host, which the main-thread animator covers.\n worker = undefined;\n }\n\n const dispatch = (command: ShellTitleCommand, write: WriteTitle) => {\n lastCommand = command;\n lastWrite = write;\n if (!worker) {\n fallback[command.action](command.title, write);\n return;\n }\n try {\n worker.postMessage(command);\n } catch {\n // The worker closed between the last frame and this command.\n fallBack();\n }\n };\n\n return {\n set: (title, write) => dispatch({ action: 'set', title }, write),\n start: (title, write) => dispatch({ action: 'start', title }, write),\n stop: (title, write) => dispatch({ action: 'stop', title }, write),\n dispose: (title, write) => dispatch({ action: 'dispose', title }, write),\n };\n}\n"],"mappings":"6CAIA,MAAM,EAAiB,CAAC,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,GAAG,EAoCxE,SAAgB,GAAwD,CACtE,IAAI,EAAa,EACb,EACE,MAAsB,CACtB,GAAO,cAAc,CAAK,EAC9B,EAAQ,IAAA,GACR,EAAa,CACf,EAEA,MAAO,CACL,IAAI,EAAO,EAAO,CAChB,EAAc,EACd,EAAM,CAAK,CACb,EACA,MAAM,EAAO,EAAO,CAClB,EAAc,EACd,IAAM,MAAe,CACnB,EAAM,GAAG,EAAe,EAAa,EAAe,QAAQ,GAAG,GAAO,EACtE,GAAc,CAChB,EACA,EAAO,EACP,EAAQ,YAAY,EAAQ,EAAuB,CACrD,EACA,KAAK,EAAO,EAAO,CACjB,EAAc,EACd,EAAM,CAAK,CACb,EACA,QAAQ,EAAO,EAAO,CACpB,EAAc,EACd,EAAM,CAAK,CACb,CACF,CACF,CAOA,SAAgB,GAAoD,CAClE,IAAM,EAAW,EAAgC,EAC7C,EACA,EACA,EAEE,MAAiB,CACrB,EAAS,IAAA,GACJ,GAAgB,GACrB,EAAS,EAAY,OAAO,CAAC,EAAY,MAAO,CAAS,CAC3D,EAEA,GAAI,CACF,IAAM,EAAc,IAAI,EAAO;;;;;;;;;;;;;;;;;;;;;;;;;EAAqB,CAClD,KAAM,GACN,WAAY,CAAE,OAAQ,EAAgB,WAAY,EAAwB,CAC5E,CAAC,EACD,EAAY,MAAM,EAClB,EAAY,KAAK,QAAS,CAAQ,EAClC,EAAY,KAAK,OAAS,GAAS,CAC7B,IAAS,GAAK,IAAW,GAAa,EAAS,CACrD,CAAC,EACD,EAAS,CACX,MAAQ,CAEN,EAAS,IAAA,EACX,CAEA,IAAM,GAAY,EAA4B,IAAsB,CAGlE,GAFA,EAAc,EACd,EAAY,EACR,CAAC,EAAQ,CACX,EAAS,EAAQ,OAAO,CAAC,EAAQ,MAAO,CAAK,EAC7C,MACF,CACA,GAAI,CACF,EAAO,YAAY,CAAO,CAC5B,MAAQ,CAEN,EAAS,CACX,CACF,EAEA,MAAO,CACL,KAAM,EAAO,IAAU,EAAS,CAAE,OAAQ,MAAO,OAAM,EAAG,CAAK,EAC/D,OAAQ,EAAO,IAAU,EAAS,CAAE,OAAQ,QAAS,OAAM,EAAG,CAAK,EACnE,MAAO,EAAO,IAAU,EAAS,CAAE,OAAQ,OAAQ,OAAM,EAAG,CAAK,EACjE,SAAU,EAAO,IAAU,EAAS,CAAE,OAAQ,UAAW,OAAM,EAAG,CAAK,CACzE,CACF"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
const e=require("../services/notificationText/index.cjs");async function t(e,t,n){try{return(await e.exec(t,n,{timeout:3e3})).code===0}catch{return!1}}async function n(n,r,i=process.platform){let a=e.notificationBody(r.body);await t(n,`cmux`,[`notify`,`--title`,r.title,`--subtitle`,r.subtitle,`--body`,a])||i!==`darwin`||await t(n,`osascript`,[`-e`,`on run argv`,`-e`,`display notification (item 3 of argv) with title (item 1 of argv) subtitle (item 2 of argv)`,`-e`,`end run`,r.title,r.subtitle,a])}exports.sendSystemNotification=n;
|
|
2
|
+
//# sourceMappingURL=systemNotification.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"systemNotification.cjs","names":["notificationBody"],"sources":["../../src/controllers/systemNotification.ts"],"sourcesContent":["import type { ExtensionAPI } from '@earendil-works/pi-coding-agent';\n\nimport { notificationBody } from '../services/notificationText';\nimport type { DesktopNotification } from '../types/notifications';\n\nconst CMUX_COMMAND = 'cmux';\nconst COMMAND_TIMEOUT_MS = 3_000;\nconst DARWIN_PLATFORM = 'darwin';\nconst OSASCRIPT_COMMAND = 'osascript';\nconst OSASCRIPT_EXPRESSION_FLAG = '-e';\n\nasync function execute(pi: ExtensionAPI, command: string, args: string[]): Promise<boolean> {\n try {\n const result = await pi.exec(command, args, { timeout: COMMAND_TIMEOUT_MS });\n return result.code === 0;\n } catch {\n // A notifier that is not installed is the ordinary case, not a fault: report\n // \"not delivered\" and let the caller decide whether another one exists.\n return false;\n }\n}\n\n/**\n * Delivers one desktop notification on a best-effort basis.\n *\n * cmux is tried first because it routes the notification to the window the\n * session actually lives in. Only macOS has a second option worth attempting,\n * and a host with neither stays silent rather than failing the turn.\n */\nexport async function sendSystemNotification(\n pi: ExtensionAPI,\n notification: DesktopNotification,\n platform: string = process.platform,\n): Promise<void> {\n const body = notificationBody(notification.body);\n const sentToCmux = await execute(pi, CMUX_COMMAND, [\n 'notify',\n '--title',\n notification.title,\n '--subtitle',\n notification.subtitle,\n '--body',\n body,\n ]);\n if (sentToCmux || platform !== DARWIN_PLATFORM) return;\n\n await execute(pi, OSASCRIPT_COMMAND, [\n OSASCRIPT_EXPRESSION_FLAG,\n 'on run argv',\n OSASCRIPT_EXPRESSION_FLAG,\n 'display notification (item 3 of argv) with title (item 1 of argv) subtitle (item 2 of argv)',\n OSASCRIPT_EXPRESSION_FLAG,\n 'end run',\n notification.title,\n notification.subtitle,\n body,\n ]);\n}\n"],"mappings":"0DAWA,eAAe,EAAQ,EAAkB,EAAiB,EAAkC,CAC1F,GAAI,CAEF,OAAO,MADc,EAAG,KAAK,EAAS,EAAM,CAAE,QAAS,GAAmB,CAAC,EAAA,CAC7D,OAAS,CACzB,MAAQ,CAGN,MAAO,EACT,CACF,CASA,eAAsB,EACpB,EACA,EACA,EAAmB,QAAQ,SACZ,CACf,IAAM,EAAOA,EAAAA,iBAAiB,EAAa,IAAI,EAU3C,MATqB,EAAQ,EAAI,OAAc,CACjD,SACA,UACA,EAAa,MACb,aACA,EAAa,SACb,SACA,CACF,CAAC,GACiB,IAAa,UAE/B,MAAM,EAAQ,EAAI,YAAmB,CACnC,KACA,cACA,KACA,8FACA,KACA,UACA,EAAa,MACb,EAAa,SACb,CACF,CAAC,CACH"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { DesktopNotification } from "../types/notifications.cjs";
|
|
2
2
|
import { ExtensionAPI } from "@earendil-works/pi-coding-agent";
|
|
3
|
-
//#region src/
|
|
3
|
+
//#region src/controllers/systemNotification.d.ts
|
|
4
4
|
/**
|
|
5
5
|
* Delivers one desktop notification on a best-effort basis.
|
|
6
6
|
*
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"systemNotification.d.cts","names":[],"sources":["../../src/controllers/systemNotification.ts"],"mappings":";;;;;;;;;;wBA6BsB,uBACpB,IAAI,cACJ,cAAc,qBACd,oBACC"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { DesktopNotification } from "../types/notifications.mjs";
|
|
2
2
|
import { ExtensionAPI } from "@earendil-works/pi-coding-agent";
|
|
3
|
-
//#region src/
|
|
3
|
+
//#region src/controllers/systemNotification.d.ts
|
|
4
4
|
/**
|
|
5
5
|
* Delivers one desktop notification on a best-effort basis.
|
|
6
6
|
*
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"systemNotification.d.mts","names":[],"sources":["../../src/controllers/systemNotification.ts"],"mappings":";;;;;;;;;;wBA6BsB,uBACpB,IAAI,cACJ,cAAc,qBACd,oBACC"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{notificationBody as e}from"../services/notificationText/index.mjs";async function t(e,t,n){try{return(await e.exec(t,n,{timeout:3e3})).code===0}catch{return!1}}async function n(n,r,i=process.platform){let a=e(r.body);await t(n,`cmux`,[`notify`,`--title`,r.title,`--subtitle`,r.subtitle,`--body`,a])||i!==`darwin`||await t(n,`osascript`,[`-e`,`on run argv`,`-e`,`display notification (item 3 of argv) with title (item 1 of argv) subtitle (item 2 of argv)`,`-e`,`end run`,r.title,r.subtitle,a])}export{n as sendSystemNotification};
|
|
2
|
+
//# sourceMappingURL=systemNotification.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"systemNotification.mjs","names":[],"sources":["../../src/controllers/systemNotification.ts"],"sourcesContent":["import type { ExtensionAPI } from '@earendil-works/pi-coding-agent';\n\nimport { notificationBody } from '../services/notificationText';\nimport type { DesktopNotification } from '../types/notifications';\n\nconst CMUX_COMMAND = 'cmux';\nconst COMMAND_TIMEOUT_MS = 3_000;\nconst DARWIN_PLATFORM = 'darwin';\nconst OSASCRIPT_COMMAND = 'osascript';\nconst OSASCRIPT_EXPRESSION_FLAG = '-e';\n\nasync function execute(pi: ExtensionAPI, command: string, args: string[]): Promise<boolean> {\n try {\n const result = await pi.exec(command, args, { timeout: COMMAND_TIMEOUT_MS });\n return result.code === 0;\n } catch {\n // A notifier that is not installed is the ordinary case, not a fault: report\n // \"not delivered\" and let the caller decide whether another one exists.\n return false;\n }\n}\n\n/**\n * Delivers one desktop notification on a best-effort basis.\n *\n * cmux is tried first because it routes the notification to the window the\n * session actually lives in. Only macOS has a second option worth attempting,\n * and a host with neither stays silent rather than failing the turn.\n */\nexport async function sendSystemNotification(\n pi: ExtensionAPI,\n notification: DesktopNotification,\n platform: string = process.platform,\n): Promise<void> {\n const body = notificationBody(notification.body);\n const sentToCmux = await execute(pi, CMUX_COMMAND, [\n 'notify',\n '--title',\n notification.title,\n '--subtitle',\n notification.subtitle,\n '--body',\n body,\n ]);\n if (sentToCmux || platform !== DARWIN_PLATFORM) return;\n\n await execute(pi, OSASCRIPT_COMMAND, [\n OSASCRIPT_EXPRESSION_FLAG,\n 'on run argv',\n OSASCRIPT_EXPRESSION_FLAG,\n 'display notification (item 3 of argv) with title (item 1 of argv) subtitle (item 2 of argv)',\n OSASCRIPT_EXPRESSION_FLAG,\n 'end run',\n notification.title,\n notification.subtitle,\n body,\n ]);\n}\n"],"mappings":"0EAWA,eAAe,EAAQ,EAAkB,EAAiB,EAAkC,CAC1F,GAAI,CAEF,OAAO,MADc,EAAG,KAAK,EAAS,EAAM,CAAE,QAAS,GAAmB,CAAC,EAAA,CAC7D,OAAS,CACzB,MAAQ,CAGN,MAAO,EACT,CACF,CASA,eAAsB,EACpB,EACA,EACA,EAAmB,QAAQ,SACZ,CACf,IAAM,EAAO,EAAiB,EAAa,IAAI,EAU3C,MATqB,EAAQ,EAAI,OAAc,CACjD,SACA,UACA,EAAa,MACb,aACA,EAAa,SACb,SACA,CACF,CAAC,GACiB,IAAa,UAE/B,MAAM,EAAQ,EAAI,YAAmB,CACnC,KACA,cACA,KACA,8FACA,KACA,UACA,EAAa,MACb,EAAa,SACb,CACF,CAAC,CACH"}
|
package/dist/extensions/pi.cjs
CHANGED
|
@@ -1 +1,2 @@
|
|
|
1
|
-
Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:`Module`}});const e=require("../
|
|
1
|
+
Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:`Module`}});const e=require("../controllers/notificationRuntime.cjs");let t=require("@agimon-ai/doompi-core/child-process");const n=(0,require("@agimon-ai/doompi-core/pi-extension").definePiExtension)(`@agimon-ai/doompi-notification`,({pi:t,options:n,runtime:r})=>{if(!r)throw Error(`This Pi extension requires the Cordis runtime metadata.`);return e.createNotificationRuntime({pi:t,options:n??{},generation:`${r.generation}:notification`})});async function r(e,r={}){(r.environment??process.env)[t.SUBAGENT_CHILD_ENV]||await n(e,r)}exports.default=r,exports.notificationExtension=r;
|
|
2
|
+
//# sourceMappingURL=pi.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pi.cjs","names":["definePiExtension","createNotificationRuntime","SUBAGENT_CHILD_ENV"],"sources":["../../src/extensions/pi.ts"],"sourcesContent":["import { SUBAGENT_CHILD_ENV } from '@agimon-ai/doompi-core/child-process';\nimport { definePiExtension } from '@agimon-ai/doompi-core/pi-extension';\nimport type { ExtensionAPI } from '@earendil-works/pi-coding-agent';\n\nimport { createNotificationRuntime, type NotificationExtensionOptions } from '../controllers/notificationRuntime';\n\nconst notificationPlugin = definePiExtension<NotificationExtensionOptions>(\n '@agimon-ai/doompi-notification',\n ({ pi, options, runtime }) => {\n if (!runtime) throw new Error('This Pi extension requires the Cordis runtime metadata.');\n return createNotificationRuntime({ pi, options: options ?? {}, generation: `${runtime.generation}:notification` });\n },\n);\n\n/** Detached children leave notification ownership with their parent session. */\nexport async function notificationExtension(\n pi: ExtensionAPI,\n options: NotificationExtensionOptions = {},\n): Promise<void> {\n if ((options.environment ?? process.env)[SUBAGENT_CHILD_ENV]) return;\n await notificationPlugin(pi, options);\n}\nexport default notificationExtension;\n"],"mappings":"+MAMA,MAAM,GAAA,+CAAqBA,CAAAA,CAAAA,kBAAAA,CACzB,kCACC,CAAE,KAAI,UAAS,aAAc,CAC5B,GAAI,CAAC,EAAS,MAAU,MAAM,yDAAyD,EACvF,OAAOC,EAAAA,0BAA0B,CAAE,KAAI,QAAS,GAAW,CAAC,EAAG,WAAY,GAAG,EAAQ,WAAW,cAAe,CAAC,CACnH,CACF,EAGA,eAAsB,EACpB,EACA,EAAwC,CAAC,EAC1B,EACV,EAAQ,aAAe,QAAQ,IAAA,CAAKC,EAAAA,qBACzC,MAAM,EAAmB,EAAI,CAAO,CACtC"}
|
package/dist/extensions/pi.d.cts
CHANGED
|
@@ -1,2 +1,8 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
1
|
+
import { NotificationExtensionOptions } from "../controllers/notificationRuntime.cjs";
|
|
2
|
+
import { ExtensionAPI } from "@earendil-works/pi-coding-agent";
|
|
3
|
+
//#region src/extensions/pi.d.ts
|
|
4
|
+
/** Detached children leave notification ownership with their parent session. */
|
|
5
|
+
export declare function notificationExtension(pi: ExtensionAPI, options?: NotificationExtensionOptions): Promise<void>;
|
|
6
|
+
//#endregion
|
|
7
|
+
export { notificationExtension as default };
|
|
8
|
+
//# sourceMappingURL=pi.d.cts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pi.d.cts","names":[],"sources":["../../src/extensions/pi.ts"],"mappings":";;;;wBAesB,sBACpB,IAAI,cACJ,UAAS,+BACR"}
|
package/dist/extensions/pi.d.mts
CHANGED
|
@@ -1,2 +1,8 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
1
|
+
import { NotificationExtensionOptions } from "../controllers/notificationRuntime.mjs";
|
|
2
|
+
import { ExtensionAPI } from "@earendil-works/pi-coding-agent";
|
|
3
|
+
//#region src/extensions/pi.d.ts
|
|
4
|
+
/** Detached children leave notification ownership with their parent session. */
|
|
5
|
+
export declare function notificationExtension(pi: ExtensionAPI, options?: NotificationExtensionOptions): Promise<void>;
|
|
6
|
+
//#endregion
|
|
7
|
+
export { notificationExtension as default };
|
|
8
|
+
//# sourceMappingURL=pi.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pi.d.mts","names":[],"sources":["../../src/extensions/pi.ts"],"mappings":";;;;wBAesB,sBACpB,IAAI,cACJ,UAAS,+BACR"}
|
package/dist/extensions/pi.mjs
CHANGED
|
@@ -1 +1,2 @@
|
|
|
1
|
-
import e
|
|
1
|
+
import{createNotificationRuntime as e}from"../controllers/notificationRuntime.mjs";import{SUBAGENT_CHILD_ENV as t}from"@agimon-ai/doompi-core/child-process";import{definePiExtension as n}from"@agimon-ai/doompi-core/pi-extension";const r=n(`@agimon-ai/doompi-notification`,({pi:t,options:n,runtime:r})=>{if(!r)throw Error(`This Pi extension requires the Cordis runtime metadata.`);return e({pi:t,options:n??{},generation:`${r.generation}:notification`})});async function i(e,n={}){(n.environment??process.env)[t]||await r(e,n)}export{i as default,i as notificationExtension};
|
|
2
|
+
//# sourceMappingURL=pi.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pi.mjs","names":[],"sources":["../../src/extensions/pi.ts"],"sourcesContent":["import { SUBAGENT_CHILD_ENV } from '@agimon-ai/doompi-core/child-process';\nimport { definePiExtension } from '@agimon-ai/doompi-core/pi-extension';\nimport type { ExtensionAPI } from '@earendil-works/pi-coding-agent';\n\nimport { createNotificationRuntime, type NotificationExtensionOptions } from '../controllers/notificationRuntime';\n\nconst notificationPlugin = definePiExtension<NotificationExtensionOptions>(\n '@agimon-ai/doompi-notification',\n ({ pi, options, runtime }) => {\n if (!runtime) throw new Error('This Pi extension requires the Cordis runtime metadata.');\n return createNotificationRuntime({ pi, options: options ?? {}, generation: `${runtime.generation}:notification` });\n },\n);\n\n/** Detached children leave notification ownership with their parent session. */\nexport async function notificationExtension(\n pi: ExtensionAPI,\n options: NotificationExtensionOptions = {},\n): Promise<void> {\n if ((options.environment ?? process.env)[SUBAGENT_CHILD_ENV]) return;\n await notificationPlugin(pi, options);\n}\nexport default notificationExtension;\n"],"mappings":"qOAMA,MAAM,EAAqB,EACzB,kCACC,CAAE,KAAI,UAAS,aAAc,CAC5B,GAAI,CAAC,EAAS,MAAU,MAAM,yDAAyD,EACvF,OAAO,EAA0B,CAAE,KAAI,QAAS,GAAW,CAAC,EAAG,WAAY,GAAG,EAAQ,WAAW,cAAe,CAAC,CACnH,CACF,EAGA,eAAsB,EACpB,EACA,EAAwC,CAAC,EAC1B,EACV,EAAQ,aAAe,QAAQ,IAAA,CAAK,IACzC,MAAM,EAAmB,EAAI,CAAO,CACtC"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:`Module`}});const e=require("../controllers/notificationCommand.cjs"),t=(0,require("@agimon-ai/doompi-core/server-facet").defineServerPlugin)({name:`@agimon-ai/doompi-notification`,session:{commands:[e.notificationCommand]}});exports.default=t,exports.notificationServerFacet=t;
|
|
2
|
+
//# sourceMappingURL=server.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.cjs","names":["defineServerPlugin","notificationCommand"],"sources":["../../src/extensions/server.ts"],"sourcesContent":["import { defineServerPlugin } from '@agimon-ai/doompi-core/server-facet';\n\nimport { notificationCommand } from '../controllers/notificationCommand';\n\nexport const notificationServerFacet = defineServerPlugin({\n name: '@agimon-ai/doompi-notification',\n session: { commands: [notificationCommand] },\n});\nexport default notificationServerFacet;\n"],"mappings":"yJAIa,GAAA,+CAA0BA,CAAAA,CAAAA,mBAAAA,CAAmB,CACxD,KAAM,iCACN,QAAS,CAAE,SAAU,CAACC,EAAAA,mBAAmB,CAAE,CAC7C,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.d.cts","names":[],"sources":["../../src/extensions/server.ts"],"mappings":";qBAIa,uEAAuB"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.d.mts","names":[],"sources":["../../src/extensions/server.ts"],"mappings":";qBAIa,uEAAuB"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{notificationCommand as e}from"../controllers/notificationCommand.mjs";import{defineServerPlugin as t}from"@agimon-ai/doompi-core/server-facet";const n=t({name:`@agimon-ai/doompi-notification`,session:{commands:[e]}});export{n as default,n as notificationServerFacet};
|
|
2
|
+
//# sourceMappingURL=server.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.mjs","names":[],"sources":["../../src/extensions/server.ts"],"sourcesContent":["import { defineServerPlugin } from '@agimon-ai/doompi-core/server-facet';\n\nimport { notificationCommand } from '../controllers/notificationCommand';\n\nexport const notificationServerFacet = defineServerPlugin({\n name: '@agimon-ai/doompi-notification',\n session: { commands: [notificationCommand] },\n});\nexport default notificationServerFacet;\n"],"mappings":"sJAIA,MAAa,EAA0B,EAAmB,CACxD,KAAM,iCACN,QAAS,CAAE,SAAU,CAAC,CAAmB,CAAE,CAC7C,CAAC"}
|
package/dist/index.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./controllers/shellTitleController.cjs"),t=require("./services/notificationText/index.cjs"),n=require("./controllers/systemNotification.cjs"),r=require("./services/notificationPolicy/index.cjs");exports.askUserPromptBody=r.askUserPromptBody,exports.attentionNotification=t.attentionNotification,exports.createMainThreadTitleController=e.createMainThreadTitleController,exports.createWorkerTitleController=e.createWorkerTitleController,exports.notificationBody=t.notificationBody,exports.promptTitle=t.promptTitle,exports.sendSystemNotification=n.sendSystemNotification,exports.settledNotification=t.settledNotification,exports.shellTabTitle=t.shellTabTitle,exports.supportsShellTitle=r.supportsShellTitle,exports.warrantsAttentionNotification=r.warrantsAttentionNotification,exports.warrantsSettledNotification=r.warrantsSettledNotification;
|
package/dist/index.d.cts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { DesktopNotification, ShellTitleAction, ShellTitleCommand, ShellTitleController, WriteTitle } from "./types/notifications.cjs";
|
|
2
|
-
import
|
|
3
|
-
import { createMainThreadTitleController, createWorkerTitleController } from "./
|
|
4
|
-
import { sendSystemNotification } from "./
|
|
5
|
-
import { AttentionState, ShellSurface, askUserPromptBody, supportsShellTitle, warrantsAttentionNotification, warrantsSettledNotification } from "./services/notificationPolicy.cjs";
|
|
6
|
-
import { ShellTabTitleInput, attentionNotification, notificationBody, promptTitle, settledNotification, shellTabTitle } from "./services/notificationText.cjs";
|
|
7
|
-
export { type AttentionState, type DesktopNotification, type NotificationExtensionOptions, type ShellSurface, type ShellTabTitleInput, type ShellTitleAction, type ShellTitleCommand, type ShellTitleController, type WriteTitle, askUserPromptBody, attentionNotification, createMainThreadTitleController, createWorkerTitleController, notificationBody,
|
|
2
|
+
import { NotificationExtensionOptions } from "./controllers/notificationRuntime.cjs";
|
|
3
|
+
import { createMainThreadTitleController, createWorkerTitleController } from "./controllers/shellTitleController.cjs";
|
|
4
|
+
import { sendSystemNotification } from "./controllers/systemNotification.cjs";
|
|
5
|
+
import { AttentionState, ShellSurface, askUserPromptBody, supportsShellTitle, warrantsAttentionNotification, warrantsSettledNotification } from "./services/notificationPolicy/index.cjs";
|
|
6
|
+
import { ShellTabTitleInput, attentionNotification, notificationBody, promptTitle, settledNotification, shellTabTitle } from "./services/notificationText/index.cjs";
|
|
7
|
+
export { type AttentionState, type DesktopNotification, type NotificationExtensionOptions, type ShellSurface, type ShellTabTitleInput, type ShellTitleAction, type ShellTitleCommand, type ShellTitleController, type WriteTitle, askUserPromptBody, attentionNotification, createMainThreadTitleController, createWorkerTitleController, notificationBody, promptTitle, sendSystemNotification, settledNotification, shellTabTitle, supportsShellTitle, warrantsAttentionNotification, warrantsSettledNotification };
|
package/dist/index.d.mts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { DesktopNotification, ShellTitleAction, ShellTitleCommand, ShellTitleController, WriteTitle } from "./types/notifications.mjs";
|
|
2
|
-
import
|
|
3
|
-
import { createMainThreadTitleController, createWorkerTitleController } from "./
|
|
4
|
-
import { sendSystemNotification } from "./
|
|
5
|
-
import { AttentionState, ShellSurface, askUserPromptBody, supportsShellTitle, warrantsAttentionNotification, warrantsSettledNotification } from "./services/notificationPolicy.mjs";
|
|
6
|
-
import { ShellTabTitleInput, attentionNotification, notificationBody, promptTitle, settledNotification, shellTabTitle } from "./services/notificationText.mjs";
|
|
7
|
-
export { type AttentionState, type DesktopNotification, type NotificationExtensionOptions, type ShellSurface, type ShellTabTitleInput, type ShellTitleAction, type ShellTitleCommand, type ShellTitleController, type WriteTitle, askUserPromptBody, attentionNotification, createMainThreadTitleController, createWorkerTitleController, notificationBody,
|
|
2
|
+
import { NotificationExtensionOptions } from "./controllers/notificationRuntime.mjs";
|
|
3
|
+
import { createMainThreadTitleController, createWorkerTitleController } from "./controllers/shellTitleController.mjs";
|
|
4
|
+
import { sendSystemNotification } from "./controllers/systemNotification.mjs";
|
|
5
|
+
import { AttentionState, ShellSurface, askUserPromptBody, supportsShellTitle, warrantsAttentionNotification, warrantsSettledNotification } from "./services/notificationPolicy/index.mjs";
|
|
6
|
+
import { ShellTabTitleInput, attentionNotification, notificationBody, promptTitle, settledNotification, shellTabTitle } from "./services/notificationText/index.mjs";
|
|
7
|
+
export { type AttentionState, type DesktopNotification, type NotificationExtensionOptions, type ShellSurface, type ShellTabTitleInput, type ShellTitleAction, type ShellTitleCommand, type ShellTitleController, type WriteTitle, askUserPromptBody, attentionNotification, createMainThreadTitleController, createWorkerTitleController, notificationBody, promptTitle, sendSystemNotification, settledNotification, shellTabTitle, supportsShellTitle, warrantsAttentionNotification, warrantsSettledNotification };
|
package/dist/index.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{
|
|
1
|
+
import{createMainThreadTitleController as e,createWorkerTitleController as t}from"./controllers/shellTitleController.mjs";import{attentionNotification as n,notificationBody as r,promptTitle as i,settledNotification as a,shellTabTitle as o}from"./services/notificationText/index.mjs";import{sendSystemNotification as s}from"./controllers/systemNotification.mjs";import{askUserPromptBody as c,supportsShellTitle as l,warrantsAttentionNotification as u,warrantsSettledNotification as d}from"./services/notificationPolicy/index.mjs";export{c as askUserPromptBody,n as attentionNotification,e as createMainThreadTitleController,t as createWorkerTitleController,r as notificationBody,i as promptTitle,s as sendSystemNotification,a as settledNotification,o as shellTabTitle,l as supportsShellTitle,u as warrantsAttentionNotification,d as warrantsSettledNotification};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"apiContracts.cjs","names":["defineApiContract"],"sources":["../../src/schemas/apiContracts.ts"],"sourcesContent":["import { defineApiContract } from '@agimon-ai/doompi-core/api-contracts';\n\n/** This facet contributes agent tools, commands or lifecycle only, with no separate HTTP or socket surface. */\nexport const apiContracts = defineApiContract({ version: 1, http: [], sockets: [], dynamic: [] });\nexport default apiContracts;\n"],"mappings":"AAGA,MAAa,GAAA,gDAAeA,CAAAA,CAAAA,kBAAAA,CAAkB,CAAE,QAAS,EAAG,KAAM,CAAC,EAAG,QAAS,CAAC,EAAG,QAAS,CAAC,CAAE,CAAC"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
//#region src/schemas/apiContracts.d.ts
|
|
2
|
+
/** This facet contributes agent tools, commands or lifecycle only, with no separate HTTP or socket surface. */
|
|
3
|
+
export declare const apiContracts: {
|
|
4
|
+
version: 1;
|
|
5
|
+
protocols?: Record<string, string> | undefined;
|
|
6
|
+
schemas?: Record<string, boolean | object> | undefined;
|
|
7
|
+
http: {
|
|
8
|
+
id: string;
|
|
9
|
+
scope: "global" | "session" | "workspace";
|
|
10
|
+
basePath?: string | undefined;
|
|
11
|
+
path: string;
|
|
12
|
+
method: "DELETE" | "GET" | "HEAD" | "OPTIONS" | "PATCH" | "POST" | "PUT";
|
|
13
|
+
description: string;
|
|
14
|
+
availability?: string | undefined;
|
|
15
|
+
authentication: "device" | "none" | "owner";
|
|
16
|
+
parameters?: {
|
|
17
|
+
name: string;
|
|
18
|
+
in: "header" | "path" | "query";
|
|
19
|
+
required: boolean;
|
|
20
|
+
schema: boolean | object;
|
|
21
|
+
}[] | undefined;
|
|
22
|
+
body?: {
|
|
23
|
+
contentType: string;
|
|
24
|
+
contentTypes?: string[] | undefined;
|
|
25
|
+
required: boolean;
|
|
26
|
+
schema: boolean | object;
|
|
27
|
+
} | undefined;
|
|
28
|
+
responses: Record<string, {
|
|
29
|
+
description: string;
|
|
30
|
+
contentType?: string | undefined;
|
|
31
|
+
schema?: boolean | object | undefined;
|
|
32
|
+
events?: Record<string, boolean | object> | undefined;
|
|
33
|
+
}>;
|
|
34
|
+
}[];
|
|
35
|
+
sockets: {
|
|
36
|
+
id: string;
|
|
37
|
+
scope: "global" | "session" | "workspace";
|
|
38
|
+
description: string;
|
|
39
|
+
availability?: string | undefined;
|
|
40
|
+
service: string;
|
|
41
|
+
member: string;
|
|
42
|
+
direction: "client-to-server" | "server-to-client";
|
|
43
|
+
kind: "channel" | "method" | "state";
|
|
44
|
+
input: boolean | object;
|
|
45
|
+
output?: boolean | object | undefined;
|
|
46
|
+
errors?: boolean | object | undefined;
|
|
47
|
+
}[];
|
|
48
|
+
dynamic: string[];
|
|
49
|
+
gaps?: string[] | undefined;
|
|
50
|
+
};
|
|
51
|
+
//#endregion
|
|
52
|
+
export { apiContracts as default };
|
|
53
|
+
//# sourceMappingURL=apiContracts.d.cts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"apiContracts.d.cts","names":[],"sources":["../../src/schemas/apiContracts.ts"],"mappings":";;qBAGa"}
|