@agimon-ai/doompi 0.0.1-alpha.57 → 0.0.1-alpha.59
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 -10
- package/dist/src/commands/syncPipeline.cjs +3 -3
- package/dist/src/commands/syncPipeline.cjs.map +1 -1
- package/dist/src/commands/syncPipeline.mjs +3 -3
- package/dist/src/commands/syncPipeline.mjs.map +1 -1
- package/dist/src/extensions/entries/modeCatalog.cjs +1 -1
- package/dist/src/extensions/entries/modeCatalog.cjs.map +1 -1
- package/dist/src/extensions/entries/modeCatalog.d.cts.map +1 -1
- package/dist/src/extensions/entries/modeCatalog.d.mts.map +1 -1
- package/dist/src/extensions/entries/modeCatalog.mjs +1 -1
- package/dist/src/extensions/entries/modeCatalog.mjs.map +1 -1
- package/package.json +13 -13
package/README.md
CHANGED
|
@@ -115,8 +115,8 @@ matter, and profiles choose a point of view.
|
|
|
115
115
|
### Major and minor modes
|
|
116
116
|
|
|
117
117
|
A major mode is the base config. It names the extension layers for development, marketing,
|
|
118
|
-
or whatever else you do. Define as many as you like; only one is active at a time
|
|
119
|
-
can
|
|
118
|
+
or whatever else you do. Define as many as you like; only one is active at a time. Synchronized
|
|
119
|
+
sessions can reload compatible changes; launcher-owned composition changes require a relaunch.
|
|
120
120
|
|
|
121
121
|
Minor modes are batteries-included switches inside that base. They start off, stack freely,
|
|
122
122
|
and keep their model tools and skills out of context until turned on. DoomPi ships six:
|
|
@@ -371,11 +371,11 @@ generated mode gets it. Short commands still return inline; commands that pass t
|
|
|
371
371
|
threshold of 60 seconds by default move into the background with durable logs. Use
|
|
372
372
|
`background: true` for an immediate detached run or `interactive: true` when the command needs
|
|
373
373
|
terminal input. Runner IDs and complete raw logs remain available to the current session through
|
|
374
|
-
Runner Space at `SPC r l` or the `doom-runner` CLI.
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
RTK stdin filter after completion. Compound commands, pipelines, incompatible
|
|
378
|
-
unsupported commands keep bounded raw output. Remove Runner from `default.packages` to keep Pi's
|
|
374
|
+
Runner Space at `SPC r l` or the `doom-runner` CLI. Runner tries bundled RMUX, then `rmux` on PATH,
|
|
375
|
+
then `tmux` on PATH. If no pane backend accepts the run, non-interactive commands use a supervised
|
|
376
|
+
subprocess; interactive commands require RMUX or tmux. Conservatively recognized single commands
|
|
377
|
+
use the matching RTK stdin filter after completion. Compound commands, pipelines, incompatible
|
|
378
|
+
formats, and unsupported commands keep bounded raw output. Remove Runner from `default.packages` to keep Pi's
|
|
379
379
|
`bash`, or add it to a named layer when only selected modes should replace `bash`.
|
|
380
380
|
|
|
381
381
|
#### Auto-compact
|
|
@@ -464,7 +464,7 @@ handoffs rather than one long conversation.
|
|
|
464
464
|
|
|
465
465
|
[`@agimon-ai/doompi-voice`][pkg-doompi-voice] captures PCM audio through the local platform helper
|
|
466
466
|
and can transcribe it locally. Transcript text, session state, and model requests may still cross
|
|
467
|
-
process or provider boundaries according to the configured engines. `SPC v
|
|
467
|
+
process or provider boundaries according to the configured engines. `SPC v m` is one-shot manual
|
|
468
468
|
dictation and never enables Voice tools. `SPC v e` enters autonomous capture and exits it again; only its exact-active
|
|
469
469
|
TUI session receives the two Voice façades plus the standalone `narrate` tool.
|
|
470
470
|
|
|
@@ -706,8 +706,8 @@ its owning package's controls; values supplied by callers are not automatically
|
|
|
706
706
|
|
|
707
707
|
- Run `doompi sync --check` to detect drift or missing configured packages, and `doompi sync`
|
|
708
708
|
to install them and rebuild synchronized state.
|
|
709
|
-
- If RMUX is
|
|
710
|
-
Interactive calls require RMUX. Linux native artifacts require a compatible loader and libc.
|
|
709
|
+
- If neither RMUX nor tmux is available, non-interactive Runner calls report the supervised subprocess
|
|
710
|
+
fallback. Interactive calls require RMUX or tmux. Linux native artifacts require a compatible loader and libc.
|
|
711
711
|
- Leader menus and overlays require Pi's interactive TUI. Commands and tools remain the interface
|
|
712
712
|
for JSON, RPC, and other headless sessions where the owning package supports them.
|
|
713
713
|
- Install a directly loaded Pi subsystem with `pi install npm:@agimon-ai/<package>`. Library consumers
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const e=require("../../_virtual/_rolldown/runtime.cjs"),t=require("../adapters/repository/repository.cjs"),n=require("../adapters/syncLocation.cjs"),r=require("../adapters/layerPackageInstaller.cjs"),i=require("../adapters/syncDrift.cjs"),a=require("./syncPresenter.cjs"),o=require("./syncCommand.cjs"),s=require("./buildCommand.cjs");let c=require("node:path");c=e.__toESM(c,1);let l=require("node:os");l=e.__toESM(l,1);let u=require("@agimon-ai/doompi-config/majorModes");const d=`--check`,f=`--force`,p=`DOOMPI_ROOT`,m=`packages`;function h(e,t){return`${String(e)} ${t}${e===1?``:`s`}`}function g(e){let t=[];return e.updated.length>0&&t.push(`updated ${h(e.updated.length,`package`)}`),e.installed.length>0&&t.push(`installed ${h(e.installed.length,`missing package`)}`),t.length===0&&t.push(`already up to date`),e.unchecked.length>0&&t.push(`${h(e.unchecked.length,`package`)} left unchecked`),t.join(`, `)}var _=class{settingsMode;telemetry;constructor(e={}){this.settingsMode=e.settingsMode??`persisted`,this.telemetry=e.telemetry}async execute(e,r=process.env,u=process.cwd(),m=process.stdout){if(e.includes(d))return new o.SyncCommand({settingsMode:this.settingsMode}).execute(e,r,u,m);let h=r.HOME??l.default.homedir(),g=r[p],_=g?c.default.resolve(g):t.resolveDoomConfigurationRoot(u,h);if(!e.includes(f)&&i.readSyncDrift(
|
|
2
|
-
`),0;let
|
|
3
|
-
`),0;let t=new a.SyncProgress(m);await this.refreshPackages(r,u,t);let n=[],c=t.start(`build`,`compiling the mode extension`),l=await new s.BuildCommand(this.telemetry).execute([`build`,...e.slice(1).filter(e=>e!==d)],r,u,{write:e=>(n.push(String(e)),!0)});return l===0?(c(`mode extension compiled`),await new o.SyncCommand({settingsMode:this.settingsMode,homeDirectory:h,lockHeld:!0}).execute(e,r,u,m)):(c(`failed`),m.write(n.join(``)),l)}finally{await
|
|
1
|
+
const e=require("../../_virtual/_rolldown/runtime.cjs"),t=require("../adapters/repository/repository.cjs"),n=require("../adapters/syncLocation.cjs"),r=require("../adapters/layerPackageInstaller.cjs"),i=require("../adapters/syncDrift.cjs"),a=require("./syncPresenter.cjs"),o=require("./syncCommand.cjs"),s=require("./buildCommand.cjs");let c=require("node:path");c=e.__toESM(c,1);let l=require("node:os");l=e.__toESM(l,1);let u=require("@agimon-ai/doompi-config/majorModes");const d=`--check`,f=`--force`,p=`DOOMPI_ROOT`,m=`packages`;function h(e,t){return`${String(e)} ${t}${e===1?``:`s`}`}function g(e){let t=[];return e.updated.length>0&&t.push(`updated ${h(e.updated.length,`package`)}`),e.installed.length>0&&t.push(`installed ${h(e.installed.length,`missing package`)}`),t.length===0&&t.push(`already up to date`),e.unchecked.length>0&&t.push(`${h(e.unchecked.length,`package`)} left unchecked`),t.join(`, `)}var _=class{settingsMode;telemetry;constructor(e={}){this.settingsMode=e.settingsMode??`persisted`,this.telemetry=e.telemetry}async execute(e,r=process.env,u=process.cwd(),m=process.stdout){if(e.includes(d))return new o.SyncCommand({settingsMode:this.settingsMode}).execute(e,r,u,m);let h=r.HOME??l.default.homedir(),g=r[p],_=g?c.default.resolve(g):t.resolveDoomConfigurationRoot(u,h),v={repoRoot:_,homeDirectory:h,requireWebBundle:!!r.DOOMPI_WEB_PACKAGE_ROOT};if(!e.includes(f)&&i.readSyncDrift(v).fresh)return m.write(`doompi sync is already up to date
|
|
2
|
+
`),0;let y=await n.acquireSyncLocationLock(n.resolveSyncLocation(_,h));try{if(!e.includes(f)&&i.readSyncDrift(v).fresh)return m.write(`doompi sync is already up to date
|
|
3
|
+
`),0;let t=new a.SyncProgress(m);await this.refreshPackages(r,u,t);let n=[],c=t.start(`build`,`compiling the mode extension`),l=await new s.BuildCommand(this.telemetry).execute([`build`,...e.slice(1).filter(e=>e!==d)],r,u,{write:e=>(n.push(String(e)),!0)});return l===0?(c(`mode extension compiled`),await new o.SyncCommand({settingsMode:this.settingsMode,homeDirectory:h,lockHeld:!0}).execute(e,r,u,m)):(c(`failed`),m.write(n.join(``)),l)}finally{await y()}}async refreshPackages(e,n,i){let a=e.HOME??l.default.homedir(),o=e[p],s=o?c.default.resolve(o):t.resolveDoomConfigurationRoot(n,a),d=(0,u.loadMajorModesConfig)(s,a);i.start(m,`checking configured packages for updates`)(g(await r.ensureLayerPackages({repoRoot:s,config:d,layers:Object.keys(d.layers),environment:e,refresh:!0,onProgress:e=>i.line(m,e)})))}};exports.SyncPipeline=_;
|
|
4
4
|
//# sourceMappingURL=syncPipeline.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"syncPipeline.cjs","names":["SyncCommand","os","path","resolveDoomConfigurationRoot","readSyncDrift","acquireSyncLocationLock","resolveSyncLocation","SyncProgress","BuildCommand","loadMajorModesConfig","ensureLayerPackages"],"sources":["../../../src/commands/syncPipeline.ts"],"sourcesContent":["import os from 'node:os';\nimport path from 'node:path';\nimport { loadMajorModesConfig } from '@agimon-ai/doompi-config/majorModes';\nimport { ensureLayerPackages, type LayerPackageResult } from '../adapters/layerPackageInstaller.ts';\nimport { resolveDoomConfigurationRoot } from '../adapters/repository/repository';\nimport type { HarnessTelemetry } from '../adapters/telemetry/logSinkTelemetry.ts';\nimport { acquireSyncLocationLock, resolveSyncLocation } from '../adapters/syncLocation.ts';\nimport { readSyncDrift } from '../adapters/syncDrift.ts';\nimport { BuildCommand } from './buildCommand.ts';\nimport { SyncCommand, type SyncSettingsMode } from './syncCommand.ts';\nimport { SyncProgress, type SyncProgressOutput } from './syncPresenter.ts';\n\nconst CHECK_OPTION = '--check';\n/** Rebuilds and republishes even when nothing drifted. */\nconst FORCE_OPTION = '--force';\nconst HARNESS_ROOT_ENV = 'DOOMPI_ROOT';\nconst BUILD_COMMAND = 'build';\nconst PACKAGES_LABEL = 'packages';\nconst BUILD_LABEL = 'build';\n\nexport interface SyncPipelineOptions {\n settingsMode?: SyncSettingsMode;\n telemetry?: HarnessTelemetry;\n}\n\nfunction pluralize(count: number, noun: string): string {\n return `${String(count)} ${noun}${count === 1 ? '' : 's'}`;\n}\n\nfunction packageSummary(result: LayerPackageResult): string {\n const parts: string[] = [];\n if (result.updated.length > 0) parts.push(`updated ${pluralize(result.updated.length, 'package')}`);\n if (result.installed.length > 0) parts.push(`installed ${pluralize(result.installed.length, 'missing package')}`);\n if (parts.length === 0) parts.push('already up to date');\n if (result.unchecked.length > 0) parts.push(`${pluralize(result.unchecked.length, 'package')} left unchecked`);\n return parts.join(', ');\n}\n\n/** Refreshes packages, runs the private cache build, then commits the synchronized state. */\nexport class SyncPipeline {\n private readonly settingsMode: SyncSettingsMode;\n private readonly telemetry: HarnessTelemetry | undefined;\n\n constructor(options: SyncPipelineOptions = {}) {\n this.settingsMode = options.settingsMode ?? 'persisted';\n this.telemetry = options.telemetry;\n }\n\n async execute(\n args: string[],\n environment: NodeJS.ProcessEnv = process.env,\n currentDirectory = process.cwd(),\n output: SyncProgressOutput = process.stdout,\n ): Promise<number> {\n if (args.includes(CHECK_OPTION)) {\n return new SyncCommand({ settingsMode: this.settingsMode }).execute(args, environment, currentDirectory, output);\n }\n\n const homeDirectory = environment.HOME ?? os.homedir();\n const inheritedRoot = environment[HARNESS_ROOT_ENV];\n const repoRoot = inheritedRoot\n ? path.resolve(inheritedRoot)\n : resolveDoomConfigurationRoot(currentDirectory, homeDirectory);\n\n // Nothing drifted means the packages are current, the mode extension is\n // compiled from these exact bytes, and the published generation already\n // describes them. Refreshing and rebuilding anyway costs seconds per call\n // and, worse, ends in a republished generation that reloads every attached\n // cockpit for no change at all. The cockpit calls this before every session\n // launch, so the cheap answer has to be the common one.\n if (!args.includes(FORCE_OPTION) && readSyncDrift(
|
|
1
|
+
{"version":3,"file":"syncPipeline.cjs","names":["SyncCommand","os","path","resolveDoomConfigurationRoot","readSyncDrift","acquireSyncLocationLock","resolveSyncLocation","SyncProgress","BuildCommand","loadMajorModesConfig","ensureLayerPackages"],"sources":["../../../src/commands/syncPipeline.ts"],"sourcesContent":["import os from 'node:os';\nimport path from 'node:path';\nimport { loadMajorModesConfig } from '@agimon-ai/doompi-config/majorModes';\nimport { ensureLayerPackages, type LayerPackageResult } from '../adapters/layerPackageInstaller.ts';\nimport { resolveDoomConfigurationRoot } from '../adapters/repository/repository';\nimport type { HarnessTelemetry } from '../adapters/telemetry/logSinkTelemetry.ts';\nimport { acquireSyncLocationLock, resolveSyncLocation } from '../adapters/syncLocation.ts';\nimport { readSyncDrift } from '../adapters/syncDrift.ts';\nimport { BuildCommand } from './buildCommand.ts';\nimport { SyncCommand, type SyncSettingsMode } from './syncCommand.ts';\nimport { SyncProgress, type SyncProgressOutput } from './syncPresenter.ts';\n\nconst CHECK_OPTION = '--check';\n/** Rebuilds and republishes even when nothing drifted. */\nconst FORCE_OPTION = '--force';\nconst HARNESS_ROOT_ENV = 'DOOMPI_ROOT';\nconst BUILD_COMMAND = 'build';\nconst PACKAGES_LABEL = 'packages';\nconst BUILD_LABEL = 'build';\n\nexport interface SyncPipelineOptions {\n settingsMode?: SyncSettingsMode;\n telemetry?: HarnessTelemetry;\n}\n\nfunction pluralize(count: number, noun: string): string {\n return `${String(count)} ${noun}${count === 1 ? '' : 's'}`;\n}\n\nfunction packageSummary(result: LayerPackageResult): string {\n const parts: string[] = [];\n if (result.updated.length > 0) parts.push(`updated ${pluralize(result.updated.length, 'package')}`);\n if (result.installed.length > 0) parts.push(`installed ${pluralize(result.installed.length, 'missing package')}`);\n if (parts.length === 0) parts.push('already up to date');\n if (result.unchecked.length > 0) parts.push(`${pluralize(result.unchecked.length, 'package')} left unchecked`);\n return parts.join(', ');\n}\n\n/** Refreshes packages, runs the private cache build, then commits the synchronized state. */\nexport class SyncPipeline {\n private readonly settingsMode: SyncSettingsMode;\n private readonly telemetry: HarnessTelemetry | undefined;\n\n constructor(options: SyncPipelineOptions = {}) {\n this.settingsMode = options.settingsMode ?? 'persisted';\n this.telemetry = options.telemetry;\n }\n\n async execute(\n args: string[],\n environment: NodeJS.ProcessEnv = process.env,\n currentDirectory = process.cwd(),\n output: SyncProgressOutput = process.stdout,\n ): Promise<number> {\n if (args.includes(CHECK_OPTION)) {\n return new SyncCommand({ settingsMode: this.settingsMode }).execute(args, environment, currentDirectory, output);\n }\n\n const homeDirectory = environment.HOME ?? os.homedir();\n const inheritedRoot = environment[HARNESS_ROOT_ENV];\n const repoRoot = inheritedRoot\n ? path.resolve(inheritedRoot)\n : resolveDoomConfigurationRoot(currentDirectory, homeDirectory);\n\n // Nothing drifted means the packages are current, the mode extension is\n // compiled from these exact bytes, and the published generation already\n // describes them. Refreshing and rebuilding anyway costs seconds per call\n // and, worse, ends in a republished generation that reloads every attached\n // cockpit for no change at all. The cockpit calls this before every session\n // launch, so the cheap answer has to be the common one.\n const driftOptions = {\n repoRoot,\n homeDirectory,\n requireWebBundle: Boolean(environment.DOOMPI_WEB_PACKAGE_ROOT),\n };\n if (!args.includes(FORCE_OPTION) && readSyncDrift(driftOptions).fresh) {\n output.write('doompi sync is already up to date\\n');\n return 0;\n }\n\n const releaseLock = await acquireSyncLocationLock(resolveSyncLocation(repoRoot, homeDirectory));\n try {\n // A concurrent publisher may have resolved the drift while this command\n // waited for the lock. Do not rebuild and republish the same generation.\n if (!args.includes(FORCE_OPTION) && readSyncDrift(driftOptions).fresh) {\n output.write('doompi sync is already up to date\\n');\n return 0;\n }\n const progress = new SyncProgress(output);\n await this.refreshPackages(environment, currentDirectory, progress);\n\n const captured: string[] = [];\n const done = progress.start(BUILD_LABEL, 'compiling the mode extension');\n const buildCode = await new BuildCommand(this.telemetry).execute(\n [BUILD_COMMAND, ...args.slice(1).filter((argument) => argument !== CHECK_OPTION)],\n environment,\n currentDirectory,\n {\n write: (chunk: unknown) => {\n captured.push(String(chunk));\n return true;\n },\n },\n );\n if (buildCode !== 0) {\n done('failed');\n output.write(captured.join(''));\n return buildCode;\n }\n done('mode extension compiled');\n\n return await new SyncCommand({\n settingsMode: this.settingsMode,\n homeDirectory,\n lockHeld: true,\n }).execute(args, environment, currentDirectory, output);\n } finally {\n await releaseLock();\n }\n }\n\n /** Moves every package sync owns to its newest published version. */\n private async refreshPackages(\n environment: NodeJS.ProcessEnv,\n currentDirectory: string,\n progress: SyncProgress,\n ): Promise<void> {\n const homeDirectory = environment.HOME ?? os.homedir();\n const inheritedRoot = environment[HARNESS_ROOT_ENV];\n const repoRoot = inheritedRoot\n ? path.resolve(inheritedRoot)\n : resolveDoomConfigurationRoot(currentDirectory, homeDirectory);\n const config = loadMajorModesConfig(repoRoot, homeDirectory);\n const done = progress.start(PACKAGES_LABEL, 'checking configured packages for updates');\n const result = await ensureLayerPackages({\n repoRoot,\n config,\n // Every declared layer, not only the selected one: sync writes the state a\n // later /mode switch reads without reinstalling.\n layers: Object.keys(config.layers),\n environment,\n refresh: true,\n onProgress: (message) => progress.line(PACKAGES_LABEL, message),\n });\n done(packageSummary(result));\n }\n}\n"],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{resolveDoomConfigurationRoot as e}from"../adapters/repository/repository.mjs";import{acquireSyncLocationLock as t,resolveSyncLocation as n}from"../adapters/syncLocation.mjs";import{ensureLayerPackages as r}from"../adapters/layerPackageInstaller.mjs";import{readSyncDrift as i}from"../adapters/syncDrift.mjs";import{SyncProgress as a}from"./syncPresenter.mjs";import{SyncCommand as o}from"./syncCommand.mjs";import{BuildCommand as s}from"./buildCommand.mjs";import c from"node:path";import l from"node:os";import{loadMajorModesConfig as u}from"@agimon-ai/doompi-config/majorModes";const d=`--check`,f=`--force`,p=`DOOMPI_ROOT`,m=`packages`;function h(e,t){return`${String(e)} ${t}${e===1?``:`s`}`}function g(e){let t=[];return e.updated.length>0&&t.push(`updated ${h(e.updated.length,`package`)}`),e.installed.length>0&&t.push(`installed ${h(e.installed.length,`missing package`)}`),t.length===0&&t.push(`already up to date`),e.unchecked.length>0&&t.push(`${h(e.unchecked.length,`package`)} left unchecked`),t.join(`, `)}var _=class{settingsMode;telemetry;constructor(e={}){this.settingsMode=e.settingsMode??`persisted`,this.telemetry=e.telemetry}async execute(r,u=process.env,m=process.cwd(),h=process.stdout){if(r.includes(d))return new o({settingsMode:this.settingsMode}).execute(r,u,m,h);let g=u.HOME??l.homedir(),_=u[p],v=_?c.resolve(_):e(m,g);if(!r.includes(f)&&i(
|
|
2
|
-
`),0;let
|
|
3
|
-
`),0;let e=new a(h);await this.refreshPackages(u,m,e);let t=[],n=e.start(`build`,`compiling the mode extension`),c=await new s(this.telemetry).execute([`build`,...r.slice(1).filter(e=>e!==d)],u,m,{write:e=>(t.push(String(e)),!0)});return c===0?(n(`mode extension compiled`),await new o({settingsMode:this.settingsMode,homeDirectory:g,lockHeld:!0}).execute(r,u,m,h)):(n(`failed`),h.write(t.join(``)),c)}finally{await
|
|
1
|
+
import{resolveDoomConfigurationRoot as e}from"../adapters/repository/repository.mjs";import{acquireSyncLocationLock as t,resolveSyncLocation as n}from"../adapters/syncLocation.mjs";import{ensureLayerPackages as r}from"../adapters/layerPackageInstaller.mjs";import{readSyncDrift as i}from"../adapters/syncDrift.mjs";import{SyncProgress as a}from"./syncPresenter.mjs";import{SyncCommand as o}from"./syncCommand.mjs";import{BuildCommand as s}from"./buildCommand.mjs";import c from"node:path";import l from"node:os";import{loadMajorModesConfig as u}from"@agimon-ai/doompi-config/majorModes";const d=`--check`,f=`--force`,p=`DOOMPI_ROOT`,m=`packages`;function h(e,t){return`${String(e)} ${t}${e===1?``:`s`}`}function g(e){let t=[];return e.updated.length>0&&t.push(`updated ${h(e.updated.length,`package`)}`),e.installed.length>0&&t.push(`installed ${h(e.installed.length,`missing package`)}`),t.length===0&&t.push(`already up to date`),e.unchecked.length>0&&t.push(`${h(e.unchecked.length,`package`)} left unchecked`),t.join(`, `)}var _=class{settingsMode;telemetry;constructor(e={}){this.settingsMode=e.settingsMode??`persisted`,this.telemetry=e.telemetry}async execute(r,u=process.env,m=process.cwd(),h=process.stdout){if(r.includes(d))return new o({settingsMode:this.settingsMode}).execute(r,u,m,h);let g=u.HOME??l.homedir(),_=u[p],v=_?c.resolve(_):e(m,g),y={repoRoot:v,homeDirectory:g,requireWebBundle:!!u.DOOMPI_WEB_PACKAGE_ROOT};if(!r.includes(f)&&i(y).fresh)return h.write(`doompi sync is already up to date
|
|
2
|
+
`),0;let b=await t(n(v,g));try{if(!r.includes(f)&&i(y).fresh)return h.write(`doompi sync is already up to date
|
|
3
|
+
`),0;let e=new a(h);await this.refreshPackages(u,m,e);let t=[],n=e.start(`build`,`compiling the mode extension`),c=await new s(this.telemetry).execute([`build`,...r.slice(1).filter(e=>e!==d)],u,m,{write:e=>(t.push(String(e)),!0)});return c===0?(n(`mode extension compiled`),await new o({settingsMode:this.settingsMode,homeDirectory:g,lockHeld:!0}).execute(r,u,m,h)):(n(`failed`),h.write(t.join(``)),c)}finally{await b()}}async refreshPackages(t,n,i){let a=t.HOME??l.homedir(),o=t[p],s=o?c.resolve(o):e(n,a),d=u(s,a);i.start(m,`checking configured packages for updates`)(g(await r({repoRoot:s,config:d,layers:Object.keys(d.layers),environment:t,refresh:!0,onProgress:e=>i.line(m,e)})))}};export{_ as SyncPipeline};
|
|
4
4
|
//# sourceMappingURL=syncPipeline.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"syncPipeline.mjs","names":[],"sources":["../../../src/commands/syncPipeline.ts"],"sourcesContent":["import os from 'node:os';\nimport path from 'node:path';\nimport { loadMajorModesConfig } from '@agimon-ai/doompi-config/majorModes';\nimport { ensureLayerPackages, type LayerPackageResult } from '../adapters/layerPackageInstaller.ts';\nimport { resolveDoomConfigurationRoot } from '../adapters/repository/repository';\nimport type { HarnessTelemetry } from '../adapters/telemetry/logSinkTelemetry.ts';\nimport { acquireSyncLocationLock, resolveSyncLocation } from '../adapters/syncLocation.ts';\nimport { readSyncDrift } from '../adapters/syncDrift.ts';\nimport { BuildCommand } from './buildCommand.ts';\nimport { SyncCommand, type SyncSettingsMode } from './syncCommand.ts';\nimport { SyncProgress, type SyncProgressOutput } from './syncPresenter.ts';\n\nconst CHECK_OPTION = '--check';\n/** Rebuilds and republishes even when nothing drifted. */\nconst FORCE_OPTION = '--force';\nconst HARNESS_ROOT_ENV = 'DOOMPI_ROOT';\nconst BUILD_COMMAND = 'build';\nconst PACKAGES_LABEL = 'packages';\nconst BUILD_LABEL = 'build';\n\nexport interface SyncPipelineOptions {\n settingsMode?: SyncSettingsMode;\n telemetry?: HarnessTelemetry;\n}\n\nfunction pluralize(count: number, noun: string): string {\n return `${String(count)} ${noun}${count === 1 ? '' : 's'}`;\n}\n\nfunction packageSummary(result: LayerPackageResult): string {\n const parts: string[] = [];\n if (result.updated.length > 0) parts.push(`updated ${pluralize(result.updated.length, 'package')}`);\n if (result.installed.length > 0) parts.push(`installed ${pluralize(result.installed.length, 'missing package')}`);\n if (parts.length === 0) parts.push('already up to date');\n if (result.unchecked.length > 0) parts.push(`${pluralize(result.unchecked.length, 'package')} left unchecked`);\n return parts.join(', ');\n}\n\n/** Refreshes packages, runs the private cache build, then commits the synchronized state. */\nexport class SyncPipeline {\n private readonly settingsMode: SyncSettingsMode;\n private readonly telemetry: HarnessTelemetry | undefined;\n\n constructor(options: SyncPipelineOptions = {}) {\n this.settingsMode = options.settingsMode ?? 'persisted';\n this.telemetry = options.telemetry;\n }\n\n async execute(\n args: string[],\n environment: NodeJS.ProcessEnv = process.env,\n currentDirectory = process.cwd(),\n output: SyncProgressOutput = process.stdout,\n ): Promise<number> {\n if (args.includes(CHECK_OPTION)) {\n return new SyncCommand({ settingsMode: this.settingsMode }).execute(args, environment, currentDirectory, output);\n }\n\n const homeDirectory = environment.HOME ?? os.homedir();\n const inheritedRoot = environment[HARNESS_ROOT_ENV];\n const repoRoot = inheritedRoot\n ? path.resolve(inheritedRoot)\n : resolveDoomConfigurationRoot(currentDirectory, homeDirectory);\n\n // Nothing drifted means the packages are current, the mode extension is\n // compiled from these exact bytes, and the published generation already\n // describes them. Refreshing and rebuilding anyway costs seconds per call\n // and, worse, ends in a republished generation that reloads every attached\n // cockpit for no change at all. The cockpit calls this before every session\n // launch, so the cheap answer has to be the common one.\n if (!args.includes(FORCE_OPTION) && readSyncDrift(
|
|
1
|
+
{"version":3,"file":"syncPipeline.mjs","names":[],"sources":["../../../src/commands/syncPipeline.ts"],"sourcesContent":["import os from 'node:os';\nimport path from 'node:path';\nimport { loadMajorModesConfig } from '@agimon-ai/doompi-config/majorModes';\nimport { ensureLayerPackages, type LayerPackageResult } from '../adapters/layerPackageInstaller.ts';\nimport { resolveDoomConfigurationRoot } from '../adapters/repository/repository';\nimport type { HarnessTelemetry } from '../adapters/telemetry/logSinkTelemetry.ts';\nimport { acquireSyncLocationLock, resolveSyncLocation } from '../adapters/syncLocation.ts';\nimport { readSyncDrift } from '../adapters/syncDrift.ts';\nimport { BuildCommand } from './buildCommand.ts';\nimport { SyncCommand, type SyncSettingsMode } from './syncCommand.ts';\nimport { SyncProgress, type SyncProgressOutput } from './syncPresenter.ts';\n\nconst CHECK_OPTION = '--check';\n/** Rebuilds and republishes even when nothing drifted. */\nconst FORCE_OPTION = '--force';\nconst HARNESS_ROOT_ENV = 'DOOMPI_ROOT';\nconst BUILD_COMMAND = 'build';\nconst PACKAGES_LABEL = 'packages';\nconst BUILD_LABEL = 'build';\n\nexport interface SyncPipelineOptions {\n settingsMode?: SyncSettingsMode;\n telemetry?: HarnessTelemetry;\n}\n\nfunction pluralize(count: number, noun: string): string {\n return `${String(count)} ${noun}${count === 1 ? '' : 's'}`;\n}\n\nfunction packageSummary(result: LayerPackageResult): string {\n const parts: string[] = [];\n if (result.updated.length > 0) parts.push(`updated ${pluralize(result.updated.length, 'package')}`);\n if (result.installed.length > 0) parts.push(`installed ${pluralize(result.installed.length, 'missing package')}`);\n if (parts.length === 0) parts.push('already up to date');\n if (result.unchecked.length > 0) parts.push(`${pluralize(result.unchecked.length, 'package')} left unchecked`);\n return parts.join(', ');\n}\n\n/** Refreshes packages, runs the private cache build, then commits the synchronized state. */\nexport class SyncPipeline {\n private readonly settingsMode: SyncSettingsMode;\n private readonly telemetry: HarnessTelemetry | undefined;\n\n constructor(options: SyncPipelineOptions = {}) {\n this.settingsMode = options.settingsMode ?? 'persisted';\n this.telemetry = options.telemetry;\n }\n\n async execute(\n args: string[],\n environment: NodeJS.ProcessEnv = process.env,\n currentDirectory = process.cwd(),\n output: SyncProgressOutput = process.stdout,\n ): Promise<number> {\n if (args.includes(CHECK_OPTION)) {\n return new SyncCommand({ settingsMode: this.settingsMode }).execute(args, environment, currentDirectory, output);\n }\n\n const homeDirectory = environment.HOME ?? os.homedir();\n const inheritedRoot = environment[HARNESS_ROOT_ENV];\n const repoRoot = inheritedRoot\n ? path.resolve(inheritedRoot)\n : resolveDoomConfigurationRoot(currentDirectory, homeDirectory);\n\n // Nothing drifted means the packages are current, the mode extension is\n // compiled from these exact bytes, and the published generation already\n // describes them. Refreshing and rebuilding anyway costs seconds per call\n // and, worse, ends in a republished generation that reloads every attached\n // cockpit for no change at all. The cockpit calls this before every session\n // launch, so the cheap answer has to be the common one.\n const driftOptions = {\n repoRoot,\n homeDirectory,\n requireWebBundle: Boolean(environment.DOOMPI_WEB_PACKAGE_ROOT),\n };\n if (!args.includes(FORCE_OPTION) && readSyncDrift(driftOptions).fresh) {\n output.write('doompi sync is already up to date\\n');\n return 0;\n }\n\n const releaseLock = await acquireSyncLocationLock(resolveSyncLocation(repoRoot, homeDirectory));\n try {\n // A concurrent publisher may have resolved the drift while this command\n // waited for the lock. Do not rebuild and republish the same generation.\n if (!args.includes(FORCE_OPTION) && readSyncDrift(driftOptions).fresh) {\n output.write('doompi sync is already up to date\\n');\n return 0;\n }\n const progress = new SyncProgress(output);\n await this.refreshPackages(environment, currentDirectory, progress);\n\n const captured: string[] = [];\n const done = progress.start(BUILD_LABEL, 'compiling the mode extension');\n const buildCode = await new BuildCommand(this.telemetry).execute(\n [BUILD_COMMAND, ...args.slice(1).filter((argument) => argument !== CHECK_OPTION)],\n environment,\n currentDirectory,\n {\n write: (chunk: unknown) => {\n captured.push(String(chunk));\n return true;\n },\n },\n );\n if (buildCode !== 0) {\n done('failed');\n output.write(captured.join(''));\n return buildCode;\n }\n done('mode extension compiled');\n\n return await new SyncCommand({\n settingsMode: this.settingsMode,\n homeDirectory,\n lockHeld: true,\n }).execute(args, environment, currentDirectory, output);\n } finally {\n await releaseLock();\n }\n }\n\n /** Moves every package sync owns to its newest published version. */\n private async refreshPackages(\n environment: NodeJS.ProcessEnv,\n currentDirectory: string,\n progress: SyncProgress,\n ): Promise<void> {\n const homeDirectory = environment.HOME ?? os.homedir();\n const inheritedRoot = environment[HARNESS_ROOT_ENV];\n const repoRoot = inheritedRoot\n ? path.resolve(inheritedRoot)\n : resolveDoomConfigurationRoot(currentDirectory, homeDirectory);\n const config = loadMajorModesConfig(repoRoot, homeDirectory);\n const done = progress.start(PACKAGES_LABEL, 'checking configured packages for updates');\n const result = await ensureLayerPackages({\n repoRoot,\n config,\n // Every declared layer, not only the selected one: sync writes the state a\n // later /mode switch reads without reinstalling.\n layers: Object.keys(config.layers),\n environment,\n refresh: true,\n onProgress: (message) => progress.line(PACKAGES_LABEL, message),\n });\n done(packageSummary(result));\n }\n}\n"],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
const e=require("../../services/modeCatalog.cjs"),t=require("../../adapters/contextDetailStore.cjs"),n=require("../../services/contextCatalog.cjs"),r=require("../../services/minorModeProjection.cjs"),i=require("./minorModeCommand.cjs");let a=require("@agimon-ai/doompi-extension-contracts/cordis-host"),o=require("@agimon-ai/doompi-extension-contracts/mode"),s=require("@agimon-ai/doompi-extension-contracts/
|
|
1
|
+
const e=require("../../services/modeCatalog.cjs"),t=require("../../adapters/contextDetailStore.cjs"),n=require("../../services/contextCatalog.cjs"),r=require("../../services/minorModeProjection.cjs"),i=require("./minorModeCommand.cjs");let a=require("@agimon-ai/doompi-extension-contracts/cordis-host"),o=require("@agimon-ai/doompi-extension-contracts/mode"),s=require("@agimon-ai/doompi-extension-contracts/mcp-status"),c=require("@agimon-ai/doompi-extension-contracts/help"),l=require("@agimon-ai/doompi-extension-contracts/notification"),u=require("@agimon-ai/doompi-extension-contracts/transition");function d(e,t,n,r){let i=(0,l.readDoomNotificationService)(e);if(i){try{Promise.resolve(i.request({body:n,level:r})).catch(()=>void 0)}catch{}return}t.ui.notify(n,r)}function f(e){return e.includes(`voice`)?`voice`:e.includes(`leader`)?`leader`:e.includes(`ui`)?`ui`:`system`}function p(e){let t=e.current?.getSnapshot();return t?t.modes.filter(e=>e.state.activation===`active`).map(e=>({id:e.descriptor.id,label:e.descriptor.label})):[]}async function m(e){let r={current:void 0};i.registerMinorModeCommand(e,()=>r.current);let o={};e.on(`session_start`,()=>{setTimeout(()=>{r.republish?.(),o.publisher?.publish()},500)}),e.on(`turn_start`,()=>{o.publisher?.publish()});let c=await(0,a.connectDoomCordisHost)(e,`@agimon-ai/doompi/mode-catalog`),l=c.root.plugin(i=>(o.publisher=n.createContextPublisher(e,i,{readMinorModes:()=>p(r),readSessionId:()=>r.sessionId,writeDetail:(e,n,r)=>void t.writeContextDetail(e,n,r),removeDetail:t.removeContextDetail}),i.inject([s.DOOM_MCP_STATUS_SERVICE],e=>{let t=()=>void o.publisher?.publish(),n=(0,s.readDoomMcpStatus)(e)?.onChange?.(t);return t(),n}),h(i,e,r,()=>void o.publisher?.publish()),()=>{o.publisher?.dispose(),o.publisher=void 0}));try{await l}catch(e){throw await l.dispose(),await c.dispose(),e}let u;e.on(`session_shutdown`,()=>u??=(async()=>{try{await l.dispose()}finally{await c.dispose()}})())}function h(t,n,i,s){t.inject([c.DOOM_HELP_SERVICE],e=>{let t=(0,c.requireDoomHelpService)(e).register({source:`@agimon-ai/doompi`,moduleUrl:require("url").pathToFileURL(__filename).href,skills:[{name:`doompi-author-extension`,description:`Create or update a DoomPi extension package inside the DoomPi monorepo or as an external npm package. Use for package layout, Pi discovery entries, shared Cordis lifecycle, package-owned Help, and extension verification.`}]});return()=>t.dispose()}),t.inject([a.DOOM_CORDIS_SESSION_SERVICE,u.DOOM_TRANSITION_SERVICE],t=>{let c=t.get(a.DOOM_CORDIS_SESSION_SERVICE),l=c.context,p=(0,u.requireDoomTransitionCoordinator)(t),m=c.reason===`reload`,h=c.sessionId,g=m?(0,u.consumeMinorModeReloadHandoff)(h):void 0;m||(0,u.discardMinorModeReloadHandoff)(h);let _=l.hasUI&&l.mode===`tui`?`tui`:`headless`,v=e.createMinorModeCatalogHost({sessionKind:_,context:l,restoreSnapshot:g,onRestorationError(e){d(t,l,`Could not restore a minor mode after reload: ${e instanceof Error?e.message:String(e)}`,`warning`)},async routeInvocation(e,t,n){let r,i=await p.execute({sessionId:l.sessionManager.getSessionId(),hostGeneration:p.hostGeneration,operationId:e.operationId,source:f(t),target:{axis:`minor-mode`,action:e,requesterSource:t}},async()=>(r=await n(),`applied`));if(i.outcome!==`applied`||!r)throw Error(`Minor-mode transition was ${i.outcome}: ${i.diagnostics.join(`, `)}`);return r}});t.provide(o.DOOM_MINOR_MODE_CATALOG_SERVICE,v),i.current=v,i.sessionId=h;let y,b,x=()=>{b=void 0;let e=r.projectMinorModes(v.getSnapshot(),_),t=JSON.stringify(e);t!==y&&(y=t,n.appendEntry(o.DOOM_MINOR_MODE_ENTRY_TYPE,e),s())},S=v.subscribe(()=>{b??=setTimeout(x,50)});return i.republish=()=>{y=void 0,x()},()=>{b&&clearTimeout(b),S(),i.republish=void 0,i.current=void 0,i.sessionId=void 0,v.dispose()}})}exports.default=m,exports.modeCatalogExtension=m;
|
|
2
2
|
//# sourceMappingURL=modeCatalog.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"modeCatalog.cjs","names":["readDoomNotificationService","connectDoomCordisHost","createContextPublisher","writeContextDetail","removeContextDetail","DOOM_HELP_SERVICE","requireDoomHelpService","DOOM_CORDIS_SESSION_SERVICE","DOOM_TRANSITION_SERVICE","requireDoomTransitionCoordinator","consumeMinorModeReloadHandoff","createMinorModeCatalogHost","DOOM_MINOR_MODE_CATALOG_SERVICE","projectMinorModes","DOOM_MINOR_MODE_ENTRY_TYPE"],"sources":["../../../../src/extensions/entries/modeCatalog.ts"],"sourcesContent":["import {\n DOOM_MINOR_MODE_CATALOG_SERVICE,\n DOOM_MINOR_MODE_ENTRY_TYPE,\n type MinorModeActionResponse,\n type MinorModeCatalogService,\n} from '@agimon-ai/doompi-extension-contracts/mode';\nimport {\n connectDoomCordisHost,\n DOOM_CORDIS_SESSION_SERVICE,\n type DoomCordisSessionService,\n} from '@agimon-ai/doompi-extension-contracts/cordis-host';\nimport { DOOM_HELP_SERVICE, requireDoomHelpService } from '@agimon-ai/doompi-extension-contracts/help';\nimport {\n type DoomNotificationLevel,\n readDoomNotificationService,\n} from '@agimon-ai/doompi-extension-contracts/notification';\nimport type { ExtensionAPI, ExtensionContext } from '@earendil-works/pi-coding-agent';\nimport {\n consumeMinorModeReloadHandoff,\n discardMinorModeReloadHandoff,\n type MinorModeCatalogHost,\n DOOM_TRANSITION_SERVICE,\n requireDoomTransitionCoordinator,\n type TransitionSource,\n} from '@agimon-ai/doompi-extension-contracts/transition';\nimport type { Context } from '@deepseek-ai/cordis';\nimport { removeContextDetail, writeContextDetail } from '../../adapters/contextDetailStore.ts';\nimport { type ContextPublisher, createContextPublisher } from '../../services/contextCatalog.ts';\nimport { projectMinorModes } from '../../services/minorModeProjection.ts';\nimport { createMinorModeCatalogHost } from '../../services/modeCatalog.ts';\nimport { registerMinorModeCommand } from './minorModeCommand.ts';\n\nconst PACKAGE_SOURCE = '@agimon-ai/doompi/mode-catalog';\nconst HELP_CONTRIBUTION_SOURCE = '@agimon-ai/doompi';\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 */\nfunction activeMinorModes(binding: CatalogBinding): { id: string; label: string }[] {\n const snapshot = binding.current?.getSnapshot();\n if (!snapshot) return [];\n return snapshot.modes\n .filter((record) => record.state.activation === 'active')\n .map((record) => ({ id: record.descriptor.id, label: record.descriptor.label }));\n}\n\nexport async function modeCatalogExtension(pi: ExtensionAPI): Promise<void> {\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 const contextBinding: { publisher?: ContextPublisher } = {};\n pi.on('session_start', () => {\n setTimeout(() => {\n activeCatalog.republish?.();\n void contextBinding.publisher?.publish();\n }, BOOT_PUBLISH_DELAY_MS);\n });\n // MCP status is pull-only and servers connect long after startup, so the\n // boot read above cannot see them. A turn is the moment the composition is\n // actually sent, which makes it both the freshest and the most meaningful\n // time to price. Identical compositions are skipped, so a quiet session\n // journals nothing extra.\n pi.on('turn_start', () => {\n void contextBinding.publisher?.publish();\n });\n const connection = await connectDoomCordisHost(pi, PACKAGE_SOURCE);\n const fiber = connection.root.plugin((cordis: Context) => {\n contextBinding.publisher = createContextPublisher(pi, cordis, {\n readMinorModes: () => activeMinorModes(activeCatalog),\n readSessionId: () => activeCatalog.sessionId,\n writeDetail: (sessionId, revision, items) => void writeContextDetail(sessionId, revision, items),\n removeDetail: removeContextDetail,\n });\n modeCatalogPlugin(cordis, pi, activeCatalog, () => void contextBinding.publisher?.publish());\n return () => {\n contextBinding.publisher?.dispose();\n contextBinding.publisher = undefined;\n };\n });\n try {\n await fiber;\n } catch (error) {\n await fiber.dispose();\n await connection.dispose();\n throw error;\n }\n let disposal: Promise<void> | undefined;\n pi.on(\n 'session_shutdown',\n () =>\n (disposal ??= (async () => {\n try {\n await fiber.dispose();\n } finally {\n await connection.dispose();\n }\n })()),\n );\n}\n\nfunction modeCatalogPlugin(\n cordis: Context,\n pi: Pick<ExtensionAPI, 'appendEntry'>,\n activeCatalog: CatalogBinding,\n onCatalogChanged: () => void,\n): void {\n cordis.inject([DOOM_HELP_SERVICE], (helpContext) => {\n const contribution = requireDoomHelpService(helpContext).register({\n source: HELP_CONTRIBUTION_SOURCE,\n moduleUrl: import.meta.url,\n skills: [\n {\n name: 'doompi-author-extension',\n description:\n 'Create or update a DoomPi extension package inside the DoomPi monorepo or as an external npm package. Use for package layout, Pi discovery entries, shared Cordis lifecycle, package-owned Help, and extension verification.',\n },\n ],\n });\n return () => contribution.dispose();\n });\n\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: MinorModeCatalogHost = 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: 'minor-mode', action: request, requesterSource },\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.provide(DOOM_MINOR_MODE_CATALOG_SERVICE, catalog);\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 onCatalogChanged();\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\nexport default modeCatalogExtension;\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"modeCatalog.cjs","names":["readDoomNotificationService","connectDoomCordisHost","createContextPublisher","writeContextDetail","removeContextDetail","DOOM_MCP_STATUS_SERVICE","readDoomMcpStatus","DOOM_HELP_SERVICE","requireDoomHelpService","DOOM_CORDIS_SESSION_SERVICE","DOOM_TRANSITION_SERVICE","requireDoomTransitionCoordinator","consumeMinorModeReloadHandoff","createMinorModeCatalogHost","DOOM_MINOR_MODE_CATALOG_SERVICE","projectMinorModes","DOOM_MINOR_MODE_ENTRY_TYPE"],"sources":["../../../../src/extensions/entries/modeCatalog.ts"],"sourcesContent":["import { DOOM_MCP_STATUS_SERVICE, readDoomMcpStatus } from '@agimon-ai/doompi-extension-contracts/mcp-status';\nimport {\n DOOM_MINOR_MODE_CATALOG_SERVICE,\n DOOM_MINOR_MODE_ENTRY_TYPE,\n type MinorModeActionResponse,\n type MinorModeCatalogService,\n} from '@agimon-ai/doompi-extension-contracts/mode';\nimport {\n connectDoomCordisHost,\n DOOM_CORDIS_SESSION_SERVICE,\n type DoomCordisSessionService,\n} from '@agimon-ai/doompi-extension-contracts/cordis-host';\nimport { DOOM_HELP_SERVICE, requireDoomHelpService } from '@agimon-ai/doompi-extension-contracts/help';\nimport {\n type DoomNotificationLevel,\n readDoomNotificationService,\n} from '@agimon-ai/doompi-extension-contracts/notification';\nimport type { ExtensionAPI, ExtensionContext } from '@earendil-works/pi-coding-agent';\nimport {\n consumeMinorModeReloadHandoff,\n discardMinorModeReloadHandoff,\n type MinorModeCatalogHost,\n DOOM_TRANSITION_SERVICE,\n requireDoomTransitionCoordinator,\n type TransitionSource,\n} from '@agimon-ai/doompi-extension-contracts/transition';\nimport type { Context } from '@deepseek-ai/cordis';\nimport { removeContextDetail, writeContextDetail } from '../../adapters/contextDetailStore.ts';\nimport { type ContextPublisher, createContextPublisher } from '../../services/contextCatalog.ts';\nimport { projectMinorModes } from '../../services/minorModeProjection.ts';\nimport { createMinorModeCatalogHost } from '../../services/modeCatalog.ts';\nimport { registerMinorModeCommand } from './minorModeCommand.ts';\n\nconst PACKAGE_SOURCE = '@agimon-ai/doompi/mode-catalog';\nconst HELP_CONTRIBUTION_SOURCE = '@agimon-ai/doompi';\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 */\nfunction activeMinorModes(binding: CatalogBinding): { id: string; label: string }[] {\n const snapshot = binding.current?.getSnapshot();\n if (!snapshot) return [];\n return snapshot.modes\n .filter((record) => record.state.activation === 'active')\n .map((record) => ({ id: record.descriptor.id, label: record.descriptor.label }));\n}\n\nexport async function modeCatalogExtension(pi: ExtensionAPI): Promise<void> {\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 const contextBinding: { publisher?: ContextPublisher } = {};\n pi.on('session_start', () => {\n setTimeout(() => {\n activeCatalog.republish?.();\n void contextBinding.publisher?.publish();\n }, BOOT_PUBLISH_DELAY_MS);\n });\n // Turns still refresh active-tool costs, including for older pull-only MCP providers.\n // Identical compositions are skipped rather than journaled again.\n pi.on('turn_start', () => {\n void contextBinding.publisher?.publish();\n });\n const connection = await connectDoomCordisHost(pi, PACKAGE_SOURCE);\n const fiber = connection.root.plugin((cordis: Context) => {\n contextBinding.publisher = createContextPublisher(pi, cordis, {\n readMinorModes: () => activeMinorModes(activeCatalog),\n readSessionId: () => activeCatalog.sessionId,\n writeDetail: (sessionId, revision, items) => void writeContextDetail(sessionId, revision, items),\n removeDetail: removeContextDetail,\n });\n cordis.inject([DOOM_MCP_STATUS_SERVICE], (mcpContext) => {\n const publish = () => void contextBinding.publisher?.publish();\n const unsubscribe = readDoomMcpStatus(mcpContext)?.onChange?.(publish);\n // Subscribe first, then read: discovery may already have finished before binding.\n publish();\n return unsubscribe;\n });\n modeCatalogPlugin(cordis, pi, activeCatalog, () => void contextBinding.publisher?.publish());\n return () => {\n contextBinding.publisher?.dispose();\n contextBinding.publisher = undefined;\n };\n });\n try {\n await fiber;\n } catch (error) {\n await fiber.dispose();\n await connection.dispose();\n throw error;\n }\n let disposal: Promise<void> | undefined;\n pi.on(\n 'session_shutdown',\n () =>\n (disposal ??= (async () => {\n try {\n await fiber.dispose();\n } finally {\n await connection.dispose();\n }\n })()),\n );\n}\n\nfunction modeCatalogPlugin(\n cordis: Context,\n pi: Pick<ExtensionAPI, 'appendEntry'>,\n activeCatalog: CatalogBinding,\n onCatalogChanged: () => void,\n): void {\n cordis.inject([DOOM_HELP_SERVICE], (helpContext) => {\n const contribution = requireDoomHelpService(helpContext).register({\n source: HELP_CONTRIBUTION_SOURCE,\n moduleUrl: import.meta.url,\n skills: [\n {\n name: 'doompi-author-extension',\n description:\n 'Create or update a DoomPi extension package inside the DoomPi monorepo or as an external npm package. Use for package layout, Pi discovery entries, shared Cordis lifecycle, package-owned Help, and extension verification.',\n },\n ],\n });\n return () => contribution.dispose();\n });\n\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: MinorModeCatalogHost = 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: 'minor-mode', action: request, requesterSource },\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.provide(DOOM_MINOR_MODE_CATALOG_SERVICE, catalog);\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 onCatalogChanged();\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\nexport default modeCatalogExtension;\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"modeCatalog.d.cts","names":[],"sources":["../../../../src/extensions/entries/modeCatalog.ts"],"mappings":";;
|
|
1
|
+
{"version":3,"file":"modeCatalog.d.cts","names":[],"sources":["../../../../src/extensions/entries/modeCatalog.ts"],"mappings":";;iBA6FsB,qBAAqB,IAAI,eAAe"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"modeCatalog.d.mts","names":[],"sources":["../../../../src/extensions/entries/modeCatalog.ts"],"mappings":";;
|
|
1
|
+
{"version":3,"file":"modeCatalog.d.mts","names":[],"sources":["../../../../src/extensions/entries/modeCatalog.ts"],"mappings":";;iBA6FsB,qBAAqB,IAAI,eAAe"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{createMinorModeCatalogHost as e}from"../../services/modeCatalog.mjs";import{removeContextDetail as t,writeContextDetail as n}from"../../adapters/contextDetailStore.mjs";import{createContextPublisher as r}from"../../services/contextCatalog.mjs";import{projectMinorModes as i}from"../../services/minorModeProjection.mjs";import{registerMinorModeCommand as a}from"./minorModeCommand.mjs";import{DOOM_CORDIS_SESSION_SERVICE as o,connectDoomCordisHost as s}from"@agimon-ai/doompi-extension-contracts/cordis-host";import{DOOM_MINOR_MODE_CATALOG_SERVICE as c,DOOM_MINOR_MODE_ENTRY_TYPE as l}from"@agimon-ai/doompi-extension-contracts/mode";import{
|
|
1
|
+
import{createMinorModeCatalogHost as e}from"../../services/modeCatalog.mjs";import{removeContextDetail as t,writeContextDetail as n}from"../../adapters/contextDetailStore.mjs";import{createContextPublisher as r}from"../../services/contextCatalog.mjs";import{projectMinorModes as i}from"../../services/minorModeProjection.mjs";import{registerMinorModeCommand as a}from"./minorModeCommand.mjs";import{DOOM_CORDIS_SESSION_SERVICE as o,connectDoomCordisHost as s}from"@agimon-ai/doompi-extension-contracts/cordis-host";import{DOOM_MINOR_MODE_CATALOG_SERVICE as c,DOOM_MINOR_MODE_ENTRY_TYPE as l}from"@agimon-ai/doompi-extension-contracts/mode";import{DOOM_MCP_STATUS_SERVICE as u,readDoomMcpStatus as d}from"@agimon-ai/doompi-extension-contracts/mcp-status";import{DOOM_HELP_SERVICE as f,requireDoomHelpService as p}from"@agimon-ai/doompi-extension-contracts/help";import{readDoomNotificationService as m}from"@agimon-ai/doompi-extension-contracts/notification";import{DOOM_TRANSITION_SERVICE as h,consumeMinorModeReloadHandoff as g,discardMinorModeReloadHandoff as _,requireDoomTransitionCoordinator as v}from"@agimon-ai/doompi-extension-contracts/transition";function y(e,t,n,r){let i=m(e);if(i){try{Promise.resolve(i.request({body:n,level:r})).catch(()=>void 0)}catch{}return}t.ui.notify(n,r)}function b(e){return e.includes(`voice`)?`voice`:e.includes(`leader`)?`leader`:e.includes(`ui`)?`ui`:`system`}function x(e){let t=e.current?.getSnapshot();return t?t.modes.filter(e=>e.state.activation===`active`).map(e=>({id:e.descriptor.id,label:e.descriptor.label})):[]}async function S(e){let i={current:void 0};a(e,()=>i.current);let o={};e.on(`session_start`,()=>{setTimeout(()=>{i.republish?.(),o.publisher?.publish()},500)}),e.on(`turn_start`,()=>{o.publisher?.publish()});let c=await s(e,`@agimon-ai/doompi/mode-catalog`),l=c.root.plugin(a=>(o.publisher=r(e,a,{readMinorModes:()=>x(i),readSessionId:()=>i.sessionId,writeDetail:(e,t,r)=>void n(e,t,r),removeDetail:t}),a.inject([u],e=>{let t=()=>void o.publisher?.publish(),n=d(e)?.onChange?.(t);return t(),n}),C(a,e,i,()=>void o.publisher?.publish()),()=>{o.publisher?.dispose(),o.publisher=void 0}));try{await l}catch(e){throw await l.dispose(),await c.dispose(),e}let f;e.on(`session_shutdown`,()=>f??=(async()=>{try{await l.dispose()}finally{await c.dispose()}})())}function C(t,n,r,a){t.inject([f],e=>{let t=p(e).register({source:`@agimon-ai/doompi`,moduleUrl:import.meta.url,skills:[{name:`doompi-author-extension`,description:`Create or update a DoomPi extension package inside the DoomPi monorepo or as an external npm package. Use for package layout, Pi discovery entries, shared Cordis lifecycle, package-owned Help, and extension verification.`}]});return()=>t.dispose()}),t.inject([o,h],t=>{let s=t.get(o),u=s.context,d=v(t),f=s.reason===`reload`,p=s.sessionId,m=f?g(p):void 0;f||_(p);let h=u.hasUI&&u.mode===`tui`?`tui`:`headless`,x=e({sessionKind:h,context:u,restoreSnapshot:m,onRestorationError(e){y(t,u,`Could not restore a minor mode after reload: ${e instanceof Error?e.message:String(e)}`,`warning`)},async routeInvocation(e,t,n){let r,i=await d.execute({sessionId:u.sessionManager.getSessionId(),hostGeneration:d.hostGeneration,operationId:e.operationId,source:b(t),target:{axis:`minor-mode`,action:e,requesterSource:t}},async()=>(r=await n(),`applied`));if(i.outcome!==`applied`||!r)throw Error(`Minor-mode transition was ${i.outcome}: ${i.diagnostics.join(`, `)}`);return r}});t.provide(c,x),r.current=x,r.sessionId=p;let S,C,w=()=>{C=void 0;let e=i(x.getSnapshot(),h),t=JSON.stringify(e);t!==S&&(S=t,n.appendEntry(l,e),a())},T=x.subscribe(()=>{C??=setTimeout(w,50)});return r.republish=()=>{S=void 0,w()},()=>{C&&clearTimeout(C),T(),r.republish=void 0,r.current=void 0,r.sessionId=void 0,x.dispose()}})}export{S as default,S as modeCatalogExtension};
|
|
2
2
|
//# sourceMappingURL=modeCatalog.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"modeCatalog.mjs","names":[],"sources":["../../../../src/extensions/entries/modeCatalog.ts"],"sourcesContent":["import {\n DOOM_MINOR_MODE_CATALOG_SERVICE,\n DOOM_MINOR_MODE_ENTRY_TYPE,\n type MinorModeActionResponse,\n type MinorModeCatalogService,\n} from '@agimon-ai/doompi-extension-contracts/mode';\nimport {\n connectDoomCordisHost,\n DOOM_CORDIS_SESSION_SERVICE,\n type DoomCordisSessionService,\n} from '@agimon-ai/doompi-extension-contracts/cordis-host';\nimport { DOOM_HELP_SERVICE, requireDoomHelpService } from '@agimon-ai/doompi-extension-contracts/help';\nimport {\n type DoomNotificationLevel,\n readDoomNotificationService,\n} from '@agimon-ai/doompi-extension-contracts/notification';\nimport type { ExtensionAPI, ExtensionContext } from '@earendil-works/pi-coding-agent';\nimport {\n consumeMinorModeReloadHandoff,\n discardMinorModeReloadHandoff,\n type MinorModeCatalogHost,\n DOOM_TRANSITION_SERVICE,\n requireDoomTransitionCoordinator,\n type TransitionSource,\n} from '@agimon-ai/doompi-extension-contracts/transition';\nimport type { Context } from '@deepseek-ai/cordis';\nimport { removeContextDetail, writeContextDetail } from '../../adapters/contextDetailStore.ts';\nimport { type ContextPublisher, createContextPublisher } from '../../services/contextCatalog.ts';\nimport { projectMinorModes } from '../../services/minorModeProjection.ts';\nimport { createMinorModeCatalogHost } from '../../services/modeCatalog.ts';\nimport { registerMinorModeCommand } from './minorModeCommand.ts';\n\nconst PACKAGE_SOURCE = '@agimon-ai/doompi/mode-catalog';\nconst HELP_CONTRIBUTION_SOURCE = '@agimon-ai/doompi';\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 */\nfunction activeMinorModes(binding: CatalogBinding): { id: string; label: string }[] {\n const snapshot = binding.current?.getSnapshot();\n if (!snapshot) return [];\n return snapshot.modes\n .filter((record) => record.state.activation === 'active')\n .map((record) => ({ id: record.descriptor.id, label: record.descriptor.label }));\n}\n\nexport async function modeCatalogExtension(pi: ExtensionAPI): Promise<void> {\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 const contextBinding: { publisher?: ContextPublisher } = {};\n pi.on('session_start', () => {\n setTimeout(() => {\n activeCatalog.republish?.();\n void contextBinding.publisher?.publish();\n }, BOOT_PUBLISH_DELAY_MS);\n });\n // MCP status is pull-only and servers connect long after startup, so the\n // boot read above cannot see them. A turn is the moment the composition is\n // actually sent, which makes it both the freshest and the most meaningful\n // time to price. Identical compositions are skipped, so a quiet session\n // journals nothing extra.\n pi.on('turn_start', () => {\n void contextBinding.publisher?.publish();\n });\n const connection = await connectDoomCordisHost(pi, PACKAGE_SOURCE);\n const fiber = connection.root.plugin((cordis: Context) => {\n contextBinding.publisher = createContextPublisher(pi, cordis, {\n readMinorModes: () => activeMinorModes(activeCatalog),\n readSessionId: () => activeCatalog.sessionId,\n writeDetail: (sessionId, revision, items) => void writeContextDetail(sessionId, revision, items),\n removeDetail: removeContextDetail,\n });\n modeCatalogPlugin(cordis, pi, activeCatalog, () => void contextBinding.publisher?.publish());\n return () => {\n contextBinding.publisher?.dispose();\n contextBinding.publisher = undefined;\n };\n });\n try {\n await fiber;\n } catch (error) {\n await fiber.dispose();\n await connection.dispose();\n throw error;\n }\n let disposal: Promise<void> | undefined;\n pi.on(\n 'session_shutdown',\n () =>\n (disposal ??= (async () => {\n try {\n await fiber.dispose();\n } finally {\n await connection.dispose();\n }\n })()),\n );\n}\n\nfunction modeCatalogPlugin(\n cordis: Context,\n pi: Pick<ExtensionAPI, 'appendEntry'>,\n activeCatalog: CatalogBinding,\n onCatalogChanged: () => void,\n): void {\n cordis.inject([DOOM_HELP_SERVICE], (helpContext) => {\n const contribution = requireDoomHelpService(helpContext).register({\n source: HELP_CONTRIBUTION_SOURCE,\n moduleUrl: import.meta.url,\n skills: [\n {\n name: 'doompi-author-extension',\n description:\n 'Create or update a DoomPi extension package inside the DoomPi monorepo or as an external npm package. Use for package layout, Pi discovery entries, shared Cordis lifecycle, package-owned Help, and extension verification.',\n },\n ],\n });\n return () => contribution.dispose();\n });\n\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: MinorModeCatalogHost = 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: 'minor-mode', action: request, requesterSource },\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.provide(DOOM_MINOR_MODE_CATALOG_SERVICE, catalog);\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 onCatalogChanged();\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\nexport default modeCatalogExtension;\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"modeCatalog.mjs","names":[],"sources":["../../../../src/extensions/entries/modeCatalog.ts"],"sourcesContent":["import { DOOM_MCP_STATUS_SERVICE, readDoomMcpStatus } from '@agimon-ai/doompi-extension-contracts/mcp-status';\nimport {\n DOOM_MINOR_MODE_CATALOG_SERVICE,\n DOOM_MINOR_MODE_ENTRY_TYPE,\n type MinorModeActionResponse,\n type MinorModeCatalogService,\n} from '@agimon-ai/doompi-extension-contracts/mode';\nimport {\n connectDoomCordisHost,\n DOOM_CORDIS_SESSION_SERVICE,\n type DoomCordisSessionService,\n} from '@agimon-ai/doompi-extension-contracts/cordis-host';\nimport { DOOM_HELP_SERVICE, requireDoomHelpService } from '@agimon-ai/doompi-extension-contracts/help';\nimport {\n type DoomNotificationLevel,\n readDoomNotificationService,\n} from '@agimon-ai/doompi-extension-contracts/notification';\nimport type { ExtensionAPI, ExtensionContext } from '@earendil-works/pi-coding-agent';\nimport {\n consumeMinorModeReloadHandoff,\n discardMinorModeReloadHandoff,\n type MinorModeCatalogHost,\n DOOM_TRANSITION_SERVICE,\n requireDoomTransitionCoordinator,\n type TransitionSource,\n} from '@agimon-ai/doompi-extension-contracts/transition';\nimport type { Context } from '@deepseek-ai/cordis';\nimport { removeContextDetail, writeContextDetail } from '../../adapters/contextDetailStore.ts';\nimport { type ContextPublisher, createContextPublisher } from '../../services/contextCatalog.ts';\nimport { projectMinorModes } from '../../services/minorModeProjection.ts';\nimport { createMinorModeCatalogHost } from '../../services/modeCatalog.ts';\nimport { registerMinorModeCommand } from './minorModeCommand.ts';\n\nconst PACKAGE_SOURCE = '@agimon-ai/doompi/mode-catalog';\nconst HELP_CONTRIBUTION_SOURCE = '@agimon-ai/doompi';\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 */\nfunction activeMinorModes(binding: CatalogBinding): { id: string; label: string }[] {\n const snapshot = binding.current?.getSnapshot();\n if (!snapshot) return [];\n return snapshot.modes\n .filter((record) => record.state.activation === 'active')\n .map((record) => ({ id: record.descriptor.id, label: record.descriptor.label }));\n}\n\nexport async function modeCatalogExtension(pi: ExtensionAPI): Promise<void> {\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 const contextBinding: { publisher?: ContextPublisher } = {};\n pi.on('session_start', () => {\n setTimeout(() => {\n activeCatalog.republish?.();\n void contextBinding.publisher?.publish();\n }, BOOT_PUBLISH_DELAY_MS);\n });\n // Turns still refresh active-tool costs, including for older pull-only MCP providers.\n // Identical compositions are skipped rather than journaled again.\n pi.on('turn_start', () => {\n void contextBinding.publisher?.publish();\n });\n const connection = await connectDoomCordisHost(pi, PACKAGE_SOURCE);\n const fiber = connection.root.plugin((cordis: Context) => {\n contextBinding.publisher = createContextPublisher(pi, cordis, {\n readMinorModes: () => activeMinorModes(activeCatalog),\n readSessionId: () => activeCatalog.sessionId,\n writeDetail: (sessionId, revision, items) => void writeContextDetail(sessionId, revision, items),\n removeDetail: removeContextDetail,\n });\n cordis.inject([DOOM_MCP_STATUS_SERVICE], (mcpContext) => {\n const publish = () => void contextBinding.publisher?.publish();\n const unsubscribe = readDoomMcpStatus(mcpContext)?.onChange?.(publish);\n // Subscribe first, then read: discovery may already have finished before binding.\n publish();\n return unsubscribe;\n });\n modeCatalogPlugin(cordis, pi, activeCatalog, () => void contextBinding.publisher?.publish());\n return () => {\n contextBinding.publisher?.dispose();\n contextBinding.publisher = undefined;\n };\n });\n try {\n await fiber;\n } catch (error) {\n await fiber.dispose();\n await connection.dispose();\n throw error;\n }\n let disposal: Promise<void> | undefined;\n pi.on(\n 'session_shutdown',\n () =>\n (disposal ??= (async () => {\n try {\n await fiber.dispose();\n } finally {\n await connection.dispose();\n }\n })()),\n );\n}\n\nfunction modeCatalogPlugin(\n cordis: Context,\n pi: Pick<ExtensionAPI, 'appendEntry'>,\n activeCatalog: CatalogBinding,\n onCatalogChanged: () => void,\n): void {\n cordis.inject([DOOM_HELP_SERVICE], (helpContext) => {\n const contribution = requireDoomHelpService(helpContext).register({\n source: HELP_CONTRIBUTION_SOURCE,\n moduleUrl: import.meta.url,\n skills: [\n {\n name: 'doompi-author-extension',\n description:\n 'Create or update a DoomPi extension package inside the DoomPi monorepo or as an external npm package. Use for package layout, Pi discovery entries, shared Cordis lifecycle, package-owned Help, and extension verification.',\n },\n ],\n });\n return () => contribution.dispose();\n });\n\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: MinorModeCatalogHost = 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: 'minor-mode', action: request, requesterSource },\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.provide(DOOM_MINOR_MODE_CATALOG_SERVICE, catalog);\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 onCatalogChanged();\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\nexport default modeCatalogExtension;\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agimon-ai/doompi",
|
|
3
|
-
"version": "0.0.1-alpha.
|
|
3
|
+
"version": "0.0.1-alpha.59",
|
|
4
4
|
"description": "Opinionated, composable Pi distribution for scoped agent tools, skills, MCP servers, and developer workflows.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"ai",
|
|
@@ -320,17 +320,17 @@
|
|
|
320
320
|
"rolldown": "1.2.6",
|
|
321
321
|
"typebox": "1.3.19",
|
|
322
322
|
"yaml": "2.9.0",
|
|
323
|
-
"@agimon-ai/doompi-autostop": "0.0.1-alpha.
|
|
324
|
-
"@agimon-ai/doompi-config": "0.0.1-alpha.
|
|
325
|
-
"@agimon-ai/doompi-
|
|
326
|
-
"@agimon-ai/doompi-
|
|
327
|
-
"@agimon-ai/doompi-
|
|
328
|
-
"@agimon-ai/doompi-major-mode": "0.0.1-alpha.
|
|
329
|
-
"@agimon-ai/doompi-
|
|
330
|
-
"@agimon-ai/doompi-
|
|
331
|
-
"@agimon-ai/doompi-
|
|
332
|
-
"@agimon-ai/doompi-
|
|
333
|
-
"@agimon-ai/doompi-
|
|
323
|
+
"@agimon-ai/doompi-autostop": "0.0.1-alpha.35",
|
|
324
|
+
"@agimon-ai/doompi-config": "0.0.1-alpha.57",
|
|
325
|
+
"@agimon-ai/doompi-domain": "0.0.1-alpha.36",
|
|
326
|
+
"@agimon-ai/doompi-extension-contracts": "0.0.1-alpha.57",
|
|
327
|
+
"@agimon-ai/doompi-cache": "0.0.1-alpha.24",
|
|
328
|
+
"@agimon-ai/doompi-major-mode": "0.0.1-alpha.36",
|
|
329
|
+
"@agimon-ai/doompi-notification": "0.0.1-alpha.35",
|
|
330
|
+
"@agimon-ai/doompi-skill": "0.0.1-alpha.36",
|
|
331
|
+
"@agimon-ai/doompi-telemetry": "0.0.1-alpha.56",
|
|
332
|
+
"@agimon-ai/doompi-ui": "0.0.1-alpha.58",
|
|
333
|
+
"@agimon-ai/doompi-profile": "0.0.1-alpha.36"
|
|
334
334
|
},
|
|
335
335
|
"devDependencies": {
|
|
336
336
|
"@earendil-works/pi-ai": "0.85.0",
|
|
@@ -340,7 +340,7 @@
|
|
|
340
340
|
"@vitest/coverage-v8": "4.1.11",
|
|
341
341
|
"typescript": "7.0.2",
|
|
342
342
|
"vitest": "4.1.11",
|
|
343
|
-
"@agimon-ai/doompi-runner": "0.0.1-alpha.
|
|
343
|
+
"@agimon-ai/doompi-runner": "0.0.1-alpha.58"
|
|
344
344
|
},
|
|
345
345
|
"peerDependencies": {
|
|
346
346
|
"@earendil-works/pi-tui": "0.85.0"
|