@wrongstack/runtime 0.293.0 → 0.295.1

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 CHANGED
@@ -1,20 +1,19 @@
1
1
  # @wrongstack/runtime
2
2
 
3
- Default runtime implementations and host composition types for WrongStack.
3
+ Host composition and platform adapters for WrongStack.
4
4
 
5
- `@wrongstack/core` should stay focused on the agent kernel, public contracts,
6
- registries, and lifecycle primitives. This package is the migration target for
7
- concrete defaults such as storage, config, permissions, metrics, compaction,
8
- models, skills, and host-level assembly helpers.
5
+ `@wrongstack/runtime` owns container composition, canonical host-tool
6
+ registration, image routing, clipboard access, the local-model probe, and
7
+ light-subagent assembly. These are real implementations, not aliases.
9
8
 
10
- In the first refactor slice, runtime re-exports the existing default
11
- implementations from `@wrongstack/core/defaults`. That lets CLI, TUI, WebUI,
12
- and future hosts start importing defaults from `@wrongstack/runtime` while the
13
- physical module moves happen incrementally.
9
+ Core defaults are intentionally not re-exported. Import their declared Core
10
+ subpaths directly. The R4 observability pilot proved that moving a Core-owned
11
+ implementation here while retaining Core compatibility would create the
12
+ `Core -> Runtime -> Core` package cycle prohibited by ADR-004.
14
13
 
15
14
  ```ts
16
- import { DefaultSessionStore, DefaultPermissionPolicy } from '@wrongstack/runtime';
17
- import { Agent, Container, EventBus } from '@wrongstack/core';
15
+ import { createDefaultContainer } from '@wrongstack/runtime';
16
+ import { DefaultTokenCounter } from '@wrongstack/core/infrastructure';
18
17
  ```
19
18
 
20
19
  The `WrongStackPack` interface in `@wrongstack/runtime/pack` is the target shape
package/dist/clipboard.js CHANGED
@@ -4,7 +4,7 @@ import { randomUUID } from "node:crypto";
4
4
  import * as fs from "node:fs/promises";
5
5
  import * as os from "node:os";
6
6
  import * as path from "node:path";
7
- import { buildChildEnv } from "@wrongstack/core";
7
+ import { buildChildEnv } from "@wrongstack/core/utils";
8
8
  var MAX_IMAGE_BYTES = 10 * 1024 * 1024;
9
9
  async function readClipboardImage() {
10
10
  const platform = process.platform;
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/clipboard.ts"],
4
- "sourcesContent": ["import { spawn } from 'node:child_process';\nimport { randomUUID } from 'node:crypto';\nimport * as fs from 'node:fs/promises';\nimport * as os from 'node:os';\nimport * as path from 'node:path';\nimport { buildChildEnv } from '@wrongstack/core';\n\nexport interface ClipboardImage {\n base64: string;\n mediaType: 'image/png';\n bytes: number;\n}\n\nconst MAX_IMAGE_BYTES = 10 * 1024 * 1024;\n\nexport async function readClipboardImage(): Promise<ClipboardImage | null> {\n const platform = process.platform;\n if (platform === 'win32') return readWindows();\n if (platform === 'darwin') return readDarwin();\n if (platform === 'linux') return readLinux();\n return null;\n}\n\n/**\n * Read plain text from the system clipboard. Returns `null` when the clipboard\n * holds no text (or only an image), the read failed, or the platform is\n * unsupported. Used by the TUI's Ctrl+V handler: terminals in raw mode deliver\n * Ctrl+V to the app as a control byte rather than performing a native paste, so\n * we read the clipboard ourselves.\n */\nexport async function readClipboardText(): Promise<string | null> {\n const platform = process.platform;\n if (platform === 'win32') {\n // -Raw preserves embedded newlines; force UTF-8 so non-ASCII survives the\n // pipe. PowerShell appends one trailing newline to stdout \u2014 strip it.\n const ps = '[Console]::OutputEncoding = [System.Text.Encoding]::UTF8; Get-Clipboard -Raw';\n const out = await runCmd('powershell', ['-NoProfile', '-Command', ps]);\n if (out == null) return null;\n const text = out.replace(/\\r?\\n$/, '');\n return text.length > 0 ? text : null;\n }\n if (platform === 'darwin') {\n const out = await runCmd('pbpaste', []);\n return out && out.length > 0 ? out : null;\n }\n if (platform === 'linux') {\n const tries: Array<[string, string[]]> = [\n ['wl-paste', ['--no-newline']],\n ['xclip', ['-selection', 'clipboard', '-o']],\n ];\n for (const [cmd, args] of tries) {\n const out = await runCmd(cmd, args);\n if (out && out.length > 0) return out;\n }\n return null;\n }\n return null;\n}\n\nasync function readWindows(): Promise<ClipboardImage | null> {\n const tmp = path.join(os.tmpdir(), `wstack-clip-${randomUUID()}.png`);\n const ps = [\n 'Add-Type -AssemblyName System.Windows.Forms',\n 'Add-Type -AssemblyName System.Drawing',\n '$img = [System.Windows.Forms.Clipboard]::GetImage()',\n 'if ($img -eq $null) { Write-Output \"NO_IMAGE\"; exit 0 }',\n `$img.Save('${tmp.replace(/\\\\/g, '\\\\\\\\')}', [System.Drawing.Imaging.ImageFormat]::Png)`,\n 'Write-Output \"OK\"',\n ].join('; ');\n const out = await runCmd('powershell', ['-NoProfile', '-Command', ps]);\n if (!out || out.trim() === 'NO_IMAGE') return null;\n if (!out.includes('OK')) return null;\n return readPngFile(tmp);\n}\n\nasync function readDarwin(): Promise<ClipboardImage | null> {\n const tmp = path.join(os.tmpdir(), `wstack-clip-${randomUUID()}.png`);\n const script = [\n 'try',\n ` set the_file to (open for access POSIX file \"${tmp}\" with write permission)`,\n ' write (the clipboard as \u00ABclass PNGf\u00BB) to the_file',\n ' close access the_file',\n 'on error',\n ' try',\n ' close access POSIX file \"' + tmp + '\"',\n ' end try',\n ' return \"NO_IMAGE\"',\n 'end try',\n 'return \"OK\"',\n ].join('\\n');\n const out = await runCmd('osascript', ['-e', script]);\n if (out?.trim() !== 'OK') return null;\n return readPngFile(tmp);\n}\n\nasync function readLinux(): Promise<ClipboardImage | null> {\n const tmp = path.join(os.tmpdir(), `wstack-clip-${randomUUID()}.png`);\n const tries: Array<[string, string[]]> = [\n ['wl-paste', ['--type', 'image/png']],\n ['xclip', ['-selection', 'clipboard', '-t', 'image/png', '-o']],\n ];\n for (const [cmd, args] of tries) {\n const ok = await runCmdToFile(cmd, args, tmp).catch(() => false);\n if (ok) return readPngFile(tmp);\n }\n return null;\n}\n\nasync function readPngFile(p: string): Promise<ClipboardImage | null> {\n try {\n const buf = await fs.readFile(p);\n if (buf.length === 0) {\n await fs.unlink(p).catch(() => undefined);\n return null;\n }\n if (buf.length > MAX_IMAGE_BYTES) {\n await fs.unlink(p).catch(() => undefined);\n throw new Error(`Clipboard image exceeds ${MAX_IMAGE_BYTES / 1024 / 1024}MB limit`);\n }\n if (buf[0] !== 0x89 || buf[1] !== 0x50 || buf[2] !== 0x4e || buf[3] !== 0x47) {\n await fs.unlink(p).catch(() => undefined);\n return null;\n }\n await fs.unlink(p).catch(() => undefined);\n return { base64: buf.toString('base64'), mediaType: 'image/png', bytes: buf.length };\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code === 'ENOENT') return null;\n throw err;\n }\n}\n\n/**\n * Hard ceiling for a clipboard subprocess. Reading the clipboard must never\n * hang the TUI: on a headless/loaded CI runner the PowerShell/xclip/wl-paste\n * read can stall indefinitely (no display, slow shell start). After this we\n * kill the child and resolve the safe default.\n */\nconst CLIPBOARD_CMD_TIMEOUT_MS = 5_000;\n\nfunction runCmd(cmd: string, args: string[]): Promise<string | null> {\n return new Promise((resolve) => {\n const child = spawn(cmd, args, {\n env: buildChildEnv(),\n stdio: ['ignore', 'pipe', 'pipe'],\n windowsHide: true,\n });\n let out = '';\n let settled = false;\n let killedByTimeout = false;\n const finish = (value: string | null) => {\n if (settled) return;\n settled = true;\n clearTimeout(timer);\n clearTimeout(killCap);\n resolve(value);\n };\n const timer = setTimeout(() => {\n killedByTimeout = true;\n child.kill('SIGTERM');\n }, CLIPBOARD_CMD_TIMEOUT_MS);\n // Safety cap: if the child ignores SIGTERM, do not hang forever.\n const killCap = setTimeout(() => finish(null), CLIPBOARD_CMD_TIMEOUT_MS + 2_000);\n child.stdout.on('data', (c) => {\n out += String(c);\n });\n child.on('error', () => finish(null));\n child.on('exit', (code) => {\n if (killedByTimeout) return finish(null);\n finish(code === 0 ? out : null);\n });\n });\n}\n\nfunction runCmdToFile(cmd: string, args: string[], outPath: string): Promise<boolean> {\n return new Promise((resolve) => {\n const child = spawn(cmd, args, {\n env: buildChildEnv(),\n stdio: ['ignore', 'pipe', 'pipe'],\n windowsHide: true,\n });\n const chunks: Buffer[] = [];\n let settled = false;\n let killedByTimeout = false;\n const finish = (value: boolean) => {\n if (settled) return;\n settled = true;\n clearTimeout(timer);\n clearTimeout(killCap);\n resolve(value);\n };\n const timer = setTimeout(() => {\n killedByTimeout = true;\n child.kill('SIGTERM');\n }, CLIPBOARD_CMD_TIMEOUT_MS);\n // Safety cap: if the child ignores SIGTERM, do not hang forever.\n const killCap = setTimeout(() => finish(false), CLIPBOARD_CMD_TIMEOUT_MS + 2_000);\n child.stdout.on('data', (c: Buffer) => chunks.push(c));\n child.on('error', () => finish(false));\n child.on('exit', async (code) => {\n if (killedByTimeout) return finish(false);\n if (code !== 0 || chunks.length === 0) return finish(false);\n try {\n await fs.writeFile(outPath, Buffer.concat(chunks));\n finish(true);\n } catch {\n finish(false);\n }\n });\n });\n}\n"],
4
+ "sourcesContent": ["import { spawn } from 'node:child_process';\nimport { randomUUID } from 'node:crypto';\nimport * as fs from 'node:fs/promises';\nimport * as os from 'node:os';\nimport * as path from 'node:path';\nimport { buildChildEnv } from '@wrongstack/core/utils';\n\nexport interface ClipboardImage {\n base64: string;\n mediaType: 'image/png';\n bytes: number;\n}\n\nconst MAX_IMAGE_BYTES = 10 * 1024 * 1024;\n\nexport async function readClipboardImage(): Promise<ClipboardImage | null> {\n const platform = process.platform;\n if (platform === 'win32') return readWindows();\n if (platform === 'darwin') return readDarwin();\n if (platform === 'linux') return readLinux();\n return null;\n}\n\n/**\n * Read plain text from the system clipboard. Returns `null` when the clipboard\n * holds no text (or only an image), the read failed, or the platform is\n * unsupported. Used by the TUI's Ctrl+V handler: terminals in raw mode deliver\n * Ctrl+V to the app as a control byte rather than performing a native paste, so\n * we read the clipboard ourselves.\n */\nexport async function readClipboardText(): Promise<string | null> {\n const platform = process.platform;\n if (platform === 'win32') {\n // -Raw preserves embedded newlines; force UTF-8 so non-ASCII survives the\n // pipe. PowerShell appends one trailing newline to stdout \u2014 strip it.\n const ps = '[Console]::OutputEncoding = [System.Text.Encoding]::UTF8; Get-Clipboard -Raw';\n const out = await runCmd('powershell', ['-NoProfile', '-Command', ps]);\n if (out == null) return null;\n const text = out.replace(/\\r?\\n$/, '');\n return text.length > 0 ? text : null;\n }\n if (platform === 'darwin') {\n const out = await runCmd('pbpaste', []);\n return out && out.length > 0 ? out : null;\n }\n if (platform === 'linux') {\n const tries: Array<[string, string[]]> = [\n ['wl-paste', ['--no-newline']],\n ['xclip', ['-selection', 'clipboard', '-o']],\n ];\n for (const [cmd, args] of tries) {\n const out = await runCmd(cmd, args);\n if (out && out.length > 0) return out;\n }\n return null;\n }\n return null;\n}\n\nasync function readWindows(): Promise<ClipboardImage | null> {\n const tmp = path.join(os.tmpdir(), `wstack-clip-${randomUUID()}.png`);\n const ps = [\n 'Add-Type -AssemblyName System.Windows.Forms',\n 'Add-Type -AssemblyName System.Drawing',\n '$img = [System.Windows.Forms.Clipboard]::GetImage()',\n 'if ($img -eq $null) { Write-Output \"NO_IMAGE\"; exit 0 }',\n `$img.Save('${tmp.replace(/\\\\/g, '\\\\\\\\')}', [System.Drawing.Imaging.ImageFormat]::Png)`,\n 'Write-Output \"OK\"',\n ].join('; ');\n const out = await runCmd('powershell', ['-NoProfile', '-Command', ps]);\n if (!out || out.trim() === 'NO_IMAGE') return null;\n if (!out.includes('OK')) return null;\n return readPngFile(tmp);\n}\n\nasync function readDarwin(): Promise<ClipboardImage | null> {\n const tmp = path.join(os.tmpdir(), `wstack-clip-${randomUUID()}.png`);\n const script = [\n 'try',\n ` set the_file to (open for access POSIX file \"${tmp}\" with write permission)`,\n ' write (the clipboard as \u00ABclass PNGf\u00BB) to the_file',\n ' close access the_file',\n 'on error',\n ' try',\n ' close access POSIX file \"' + tmp + '\"',\n ' end try',\n ' return \"NO_IMAGE\"',\n 'end try',\n 'return \"OK\"',\n ].join('\\n');\n const out = await runCmd('osascript', ['-e', script]);\n if (out?.trim() !== 'OK') return null;\n return readPngFile(tmp);\n}\n\nasync function readLinux(): Promise<ClipboardImage | null> {\n const tmp = path.join(os.tmpdir(), `wstack-clip-${randomUUID()}.png`);\n const tries: Array<[string, string[]]> = [\n ['wl-paste', ['--type', 'image/png']],\n ['xclip', ['-selection', 'clipboard', '-t', 'image/png', '-o']],\n ];\n for (const [cmd, args] of tries) {\n const ok = await runCmdToFile(cmd, args, tmp).catch(() => false);\n if (ok) return readPngFile(tmp);\n }\n return null;\n}\n\nasync function readPngFile(p: string): Promise<ClipboardImage | null> {\n try {\n const buf = await fs.readFile(p);\n if (buf.length === 0) {\n await fs.unlink(p).catch(() => undefined);\n return null;\n }\n if (buf.length > MAX_IMAGE_BYTES) {\n await fs.unlink(p).catch(() => undefined);\n throw new Error(`Clipboard image exceeds ${MAX_IMAGE_BYTES / 1024 / 1024}MB limit`);\n }\n if (buf[0] !== 0x89 || buf[1] !== 0x50 || buf[2] !== 0x4e || buf[3] !== 0x47) {\n await fs.unlink(p).catch(() => undefined);\n return null;\n }\n await fs.unlink(p).catch(() => undefined);\n return { base64: buf.toString('base64'), mediaType: 'image/png', bytes: buf.length };\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code === 'ENOENT') return null;\n throw err;\n }\n}\n\n/**\n * Hard ceiling for a clipboard subprocess. Reading the clipboard must never\n * hang the TUI: on a headless/loaded CI runner the PowerShell/xclip/wl-paste\n * read can stall indefinitely (no display, slow shell start). After this we\n * kill the child and resolve the safe default.\n */\nconst CLIPBOARD_CMD_TIMEOUT_MS = 5_000;\n\nfunction runCmd(cmd: string, args: string[]): Promise<string | null> {\n return new Promise((resolve) => {\n const child = spawn(cmd, args, {\n env: buildChildEnv(),\n stdio: ['ignore', 'pipe', 'pipe'],\n windowsHide: true,\n });\n let out = '';\n let settled = false;\n let killedByTimeout = false;\n const finish = (value: string | null) => {\n if (settled) return;\n settled = true;\n clearTimeout(timer);\n clearTimeout(killCap);\n resolve(value);\n };\n const timer = setTimeout(() => {\n killedByTimeout = true;\n child.kill('SIGTERM');\n }, CLIPBOARD_CMD_TIMEOUT_MS);\n // Safety cap: if the child ignores SIGTERM, do not hang forever.\n const killCap = setTimeout(() => finish(null), CLIPBOARD_CMD_TIMEOUT_MS + 2_000);\n child.stdout.on('data', (c) => {\n out += String(c);\n });\n child.on('error', () => finish(null));\n child.on('exit', (code) => {\n if (killedByTimeout) return finish(null);\n finish(code === 0 ? out : null);\n });\n });\n}\n\nfunction runCmdToFile(cmd: string, args: string[], outPath: string): Promise<boolean> {\n return new Promise((resolve) => {\n const child = spawn(cmd, args, {\n env: buildChildEnv(),\n stdio: ['ignore', 'pipe', 'pipe'],\n windowsHide: true,\n });\n const chunks: Buffer[] = [];\n let settled = false;\n let killedByTimeout = false;\n const finish = (value: boolean) => {\n if (settled) return;\n settled = true;\n clearTimeout(timer);\n clearTimeout(killCap);\n resolve(value);\n };\n const timer = setTimeout(() => {\n killedByTimeout = true;\n child.kill('SIGTERM');\n }, CLIPBOARD_CMD_TIMEOUT_MS);\n // Safety cap: if the child ignores SIGTERM, do not hang forever.\n const killCap = setTimeout(() => finish(false), CLIPBOARD_CMD_TIMEOUT_MS + 2_000);\n child.stdout.on('data', (c: Buffer) => chunks.push(c));\n child.on('error', () => finish(false));\n child.on('exit', async (code) => {\n if (killedByTimeout) return finish(false);\n if (code !== 0 || chunks.length === 0) return finish(false);\n try {\n await fs.writeFile(outPath, Buffer.concat(chunks));\n finish(true);\n } catch {\n finish(false);\n }\n });\n });\n}\n"],
5
5
  "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -1,11 +1,14 @@
1
- import { type Config, Container, type DefaultSystemPromptBuilderOptions, type EventBus, type Logger, type ModelsRegistry, type Tool, type WstackPaths } from '@wrongstack/core';
1
+ import { type DefaultSystemPromptBuilderOptions } from '@wrongstack/core/agent';
2
+ import { Container, type EventBus } from '@wrongstack/core/kernel';
3
+ import type { Config, Logger, ModelsRegistry, Tool } from '@wrongstack/core/types';
4
+ import type { WstackPaths } from '@wrongstack/core/utils';
2
5
  export interface CreateContainerOptions {
3
6
  config: Config;
4
7
  wpaths: WstackPaths;
5
8
  logger: Logger;
6
9
  modelsRegistry: ModelsRegistry;
7
10
  /**
8
- * Optional event bus — passed to SuperMemoryStore so plugins and
11
+ * Optional event bus — passed to SageStore so plugins and
9
12
  * subsystems can react to memory mutations in real time.
10
13
  */
11
14
  events?: EventBus | undefined;
@@ -1 +1 @@
1
- {"version":3,"file":"container.d.ts","sourceRoot":"","sources":["../src/container.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,MAAM,EACX,SAAS,EAaT,KAAK,iCAAiC,EACtC,KAAK,QAAQ,EACb,KAAK,MAAM,EACX,KAAK,cAAc,EAEnB,KAAK,IAAI,EACT,KAAK,WAAW,EACjB,MAAM,kBAAkB,CAAC;AAS1B,MAAM,WAAW,sBAAsB;IACrC,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,WAAW,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;IACf,cAAc,EAAE,cAAc,CAAC;IAC/B;;;OAGG;IACH,MAAM,CAAC,EAAE,QAAQ,GAAG,SAAS,CAAC;IAC9B,UAAU,CAAC,EAAE;QACX,IAAI,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;QAC3B,cAAc,CAAC,EAAE,CACf,IAAI,EAAE,IAAI,EACV,KAAK,EAAE,OAAO,EACd,gBAAgB,EAAE,MAAM,KACrB,OAAO,CAAC,KAAK,GAAG,IAAI,GAAG,QAAQ,GAAG,MAAM,CAAC,CAAC;KAChD,CAAC;IACF,SAAS,CAAC,EAAE;QAAE,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;QAAC,cAAc,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;KAAE,CAAC;IACpF,YAAY,CAAC,EAAE,OAAO,CAAC,iCAAiC,CAAC,GAAG,SAAS,CAAC;IACtE,6DAA6D;IAC7D,gBAAgB,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACtC,uFAAuF;IACvF,iBAAiB,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CACxC;AAED;;;GAGG;AACH,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,sBAAsB,GAAG,SAAS,CAuK9E"}
1
+ {"version":3,"file":"container.d.ts","sourceRoot":"","sources":["../src/container.ts"],"names":[],"mappings":"AAEA,OAAO,EAEL,KAAK,iCAAiC,EAEvC,MAAM,wBAAwB,CAAC;AAQhC,OAAO,EAAE,SAAS,EAAE,KAAK,QAAQ,EAAU,MAAM,yBAAyB,CAAC;AAS3E,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,cAAc,EAAE,IAAI,EAAE,MAAM,wBAAwB,CAAC;AACnF,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAQ1D,MAAM,WAAW,sBAAsB;IACrC,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,WAAW,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;IACf,cAAc,EAAE,cAAc,CAAC;IAC/B;;;OAGG;IACH,MAAM,CAAC,EAAE,QAAQ,GAAG,SAAS,CAAC;IAC9B,UAAU,CAAC,EAAE;QACX,IAAI,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;QAC3B,cAAc,CAAC,EAAE,CACf,IAAI,EAAE,IAAI,EACV,KAAK,EAAE,OAAO,EACd,gBAAgB,EAAE,MAAM,KACrB,OAAO,CAAC,KAAK,GAAG,IAAI,GAAG,QAAQ,GAAG,MAAM,CAAC,CAAC;KAChD,CAAC;IACF,SAAS,CAAC,EAAE;QAAE,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;QAAC,cAAc,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;KAAE,CAAC;IACpF,YAAY,CAAC,EAAE,OAAO,CAAC,iCAAiC,CAAC,GAAG,SAAS,CAAC;IACtE,6DAA6D;IAC7D,gBAAgB,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACtC,uFAAuF;IACvF,iBAAiB,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CACxC;AAED;;;GAGG;AACH,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,sBAAsB,GAAG,SAAS,CA4L9E"}
@@ -1,4 +1,8 @@
1
- import { Agent, type AgentFactory, type Container, type ModelsRegistry, type ProviderRegistry, type SessionWriter, ToolRegistry } from '@wrongstack/core';
1
+ import { Agent } from '@wrongstack/core/agent';
2
+ import { type AgentFactory } from '@wrongstack/core/coordination';
3
+ import { type Container } from '@wrongstack/core/kernel';
4
+ import { type ProviderRegistry, ToolRegistry } from '@wrongstack/core/registry';
5
+ import type { ModelsRegistry, SessionWriter } from '@wrongstack/core/types';
2
6
  export interface LightSubagentFactoryDeps {
3
7
  /** DI container — used to resolve configStore / tokenCounter / scrubber / prompt builder. */
4
8
  container: Container;
@@ -14,6 +18,12 @@ export interface LightSubagentFactoryDeps {
14
18
  projectRoot: string;
15
19
  /** Default cwd when a SubagentConfig doesn't pin one (worktree path otherwise). */
16
20
  cwd?: string | undefined;
21
+ /**
22
+ * Test hook — overrides the fallback extension's `now()` so cooldown
23
+ * assertions don't depend on real wall-clock time. Production callers
24
+ * should leave this unset.
25
+ */
26
+ now?: (() => number) | undefined;
17
27
  }
18
28
  /**
19
29
  * Retrieve and abort a light subagent's AbortController (stored in ctx.meta
@@ -1 +1 @@
1
- {"version":3,"file":"light-subagent-factory.d.ts","sourceRoot":"","sources":["../../src/fleet/light-subagent-factory.ts"],"names":[],"mappings":"AAmBA,OAAO,EACL,KAAK,EACL,KAAK,YAAY,EAKjB,KAAK,SAAS,EAOd,KAAK,cAAc,EAEnB,KAAK,gBAAgB,EAIrB,KAAK,aAAa,EAMlB,YAAY,EAEb,MAAM,kBAAkB,CAAC;AAE1B,MAAM,WAAW,wBAAwB;IACvC,6FAA6F;IAC7F,SAAS,EAAE,SAAS,CAAC;IACrB,8FAA8F;IAC9F,gBAAgB,EAAE,gBAAgB,CAAC;IACnC,uEAAuE;IACvE,YAAY,EAAE,YAAY,CAAC;IAC3B,4EAA4E;IAC5E,cAAc,CAAC,EAAE,cAAc,GAAG,SAAS,CAAC;IAC5C,iFAAiF;IACjF,OAAO,EAAE,aAAa,CAAC;IACvB,2BAA2B;IAC3B,WAAW,EAAE,MAAM,CAAC;IACpB,mFAAmF;IACnF,GAAG,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAC1B;AAcD;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI,CAGrD;AAED,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,wBAAwB,GAAG,YAAY,CAgJrF"}
1
+ {"version":3,"file":"light-subagent-factory.d.ts","sourceRoot":"","sources":["../../src/fleet/light-subagent-factory.ts"],"names":[],"mappings":"AAmBA,OAAO,EACL,KAAK,EAKN,MAAM,wBAAwB,CAAC;AAChC,OAAO,EACL,KAAK,YAAY,EAGlB,MAAM,+BAA+B,CAAC;AAOvC,OAAO,EAAE,KAAK,SAAS,EAAoB,MAAM,yBAAyB,CAAC;AAC3E,OAAO,EAAE,KAAK,gBAAgB,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AAEhF,OAAO,KAAK,EAEV,cAAc,EAGd,aAAa,EAId,MAAM,wBAAwB,CAAC;AAEhC,MAAM,WAAW,wBAAwB;IACvC,6FAA6F;IAC7F,SAAS,EAAE,SAAS,CAAC;IACrB,8FAA8F;IAC9F,gBAAgB,EAAE,gBAAgB,CAAC;IACnC,uEAAuE;IACvE,YAAY,EAAE,YAAY,CAAC;IAC3B,4EAA4E;IAC5E,cAAc,CAAC,EAAE,cAAc,GAAG,SAAS,CAAC;IAC5C,iFAAiF;IACjF,OAAO,EAAE,aAAa,CAAC;IACvB,2BAA2B;IAC3B,WAAW,EAAE,MAAM,CAAC;IACpB,mFAAmF;IACnF,GAAG,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACzB;;;;OAIG;IACH,GAAG,CAAC,EAAE,CAAC,MAAM,MAAM,CAAC,GAAG,SAAS,CAAC;CAClC;AAcD;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI,CAGrD;AAED,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,wBAAwB,GAAG,YAAY,CAoKrF"}
package/dist/host.d.ts CHANGED
@@ -1,4 +1,8 @@
1
- import type { Agent, Context, EventBus, ExtensionRegistry, PluginAPI, ProviderRegistry, SessionWriter, SlashCommandRegistry, ToolRegistry } from '@wrongstack/core';
1
+ import type { Agent, Context } from '@wrongstack/core/agent';
2
+ import type { ExtensionRegistry } from '@wrongstack/core/extension';
3
+ import type { EventBus } from '@wrongstack/core/kernel';
4
+ import type { ProviderRegistry, SlashCommandRegistry, ToolRegistry } from '@wrongstack/core/registry';
5
+ import type { PluginAPI, SessionWriter } from '@wrongstack/core/types';
2
6
  import type { WrongStackPack } from './pack.js';
3
7
  export interface RuntimeHost {
4
8
  agent: Agent;
@@ -1 +1 @@
1
- {"version":3,"file":"host.d.ts","sourceRoot":"","sources":["../src/host.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,KAAK,EACL,OAAO,EACP,QAAQ,EACR,iBAAiB,EACjB,SAAS,EACT,gBAAgB,EAChB,aAAa,EACb,oBAAoB,EACpB,YAAY,EACb,MAAM,kBAAkB,CAAC;AAC1B,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAEhD,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,KAAK,CAAC;IACb,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,QAAQ,CAAC;IACjB,KAAK,EAAE,YAAY,CAAC;IACpB,SAAS,EAAE,gBAAgB,CAAC;IAC5B,aAAa,EAAE,oBAAoB,CAAC;IACpC,OAAO,EAAE,aAAa,CAAC;IACvB,UAAU,CAAC,EAAE,iBAAiB,GAAG,SAAS,CAAC;IAC3C,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CAC3B;AAED,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,KAAK,CAAC;IACb,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,QAAQ,CAAC;IACjB,KAAK,EAAE,YAAY,CAAC;IACpB,SAAS,EAAE,gBAAgB,CAAC;IAC5B,aAAa,EAAE,oBAAoB,CAAC;IACpC,OAAO,EAAE,aAAa,CAAC;IACvB,UAAU,CAAC,EAAE,iBAAiB,GAAG,SAAS,CAAC;IAC3C,QAAQ,CAAC,EAAE,CAAC,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,GAAG,SAAS,CAAC;CACrD;AAED,wBAAgB,0BAA0B,CAAC,KAAK,EAAE,gBAAgB,GAAG,WAAW,CAc/E;AAED,MAAM,WAAW,gBAAgB;IAC/B,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC3B,GAAG,CAAC,EAAE,SAAS,GAAG,SAAS,CAAC;CAC7B;AAED,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,cAAc,CAAC;IACrB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CAC3B;AAED,wBAAsB,mBAAmB,CACvC,IAAI,EAAE,IAAI,CAAC,WAAW,EAAE,OAAO,GAAG,WAAW,GAAG,eAAe,CAAC,GAAG;IACjE,UAAU,CAAC,EAAE,iBAAiB,GAAG,SAAS,CAAC;CAC5C,EACD,IAAI,EAAE,cAAc,EACpB,IAAI,GAAE,gBAAqB,GAC1B,OAAO,CAAC,WAAW,CAAC,CA0FtB;AAED,wBAAsB,oBAAoB,CACxC,IAAI,EAAE,IAAI,CAAC,WAAW,EAAE,OAAO,GAAG,WAAW,GAAG,eAAe,CAAC,GAAG;IACjE,UAAU,CAAC,EAAE,iBAAiB,GAAG,SAAS,CAAC;CAC5C,EACD,KAAK,EAAE,SAAS,cAAc,EAAE,EAChC,IAAI,GAAE,gBAAqB,GAC1B,OAAO,CAAC,WAAW,EAAE,CAAC,CAwBxB"}
1
+ {"version":3,"file":"host.d.ts","sourceRoot":"","sources":["../src/host.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,wBAAwB,CAAC;AAC7D,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,4BAA4B,CAAC;AACpE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAC;AACxD,OAAO,KAAK,EACV,gBAAgB,EAChB,oBAAoB,EACpB,YAAY,EACb,MAAM,2BAA2B,CAAC;AACnC,OAAO,KAAK,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AACvE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAEhD,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,KAAK,CAAC;IACb,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,QAAQ,CAAC;IACjB,KAAK,EAAE,YAAY,CAAC;IACpB,SAAS,EAAE,gBAAgB,CAAC;IAC5B,aAAa,EAAE,oBAAoB,CAAC;IACpC,OAAO,EAAE,aAAa,CAAC;IACvB,UAAU,CAAC,EAAE,iBAAiB,GAAG,SAAS,CAAC;IAC3C,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CAC3B;AAED,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,KAAK,CAAC;IACb,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,QAAQ,CAAC;IACjB,KAAK,EAAE,YAAY,CAAC;IACpB,SAAS,EAAE,gBAAgB,CAAC;IAC5B,aAAa,EAAE,oBAAoB,CAAC;IACpC,OAAO,EAAE,aAAa,CAAC;IACvB,UAAU,CAAC,EAAE,iBAAiB,GAAG,SAAS,CAAC;IAC3C,QAAQ,CAAC,EAAE,CAAC,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,GAAG,SAAS,CAAC;CACrD;AAED,wBAAgB,0BAA0B,CAAC,KAAK,EAAE,gBAAgB,GAAG,WAAW,CAc/E;AAED,MAAM,WAAW,gBAAgB;IAC/B,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC3B,GAAG,CAAC,EAAE,SAAS,GAAG,SAAS,CAAC;CAC7B;AAED,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,cAAc,CAAC;IACrB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CAC3B;AAED,wBAAsB,mBAAmB,CACvC,IAAI,EAAE,IAAI,CAAC,WAAW,EAAE,OAAO,GAAG,WAAW,GAAG,eAAe,CAAC,GAAG;IACjE,UAAU,CAAC,EAAE,iBAAiB,GAAG,SAAS,CAAC;CAC5C,EACD,IAAI,EAAE,cAAc,EACpB,IAAI,GAAE,gBAAqB,GAC1B,OAAO,CAAC,WAAW,CAAC,CA0FtB;AAED,wBAAsB,oBAAoB,CACxC,IAAI,EAAE,IAAI,CAAC,WAAW,EAAE,OAAO,GAAG,WAAW,GAAG,eAAe,CAAC,GAAG;IACjE,UAAU,CAAC,EAAE,iBAAiB,GAAG,SAAS,CAAC;CAC5C,EACD,KAAK,EAAE,SAAS,cAAc,EAAE,EAChC,IAAI,GAAE,gBAAqB,GAC1B,OAAO,CAAC,WAAW,EAAE,CAAC,CAwBxB"}
package/dist/host.js.map CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/host.ts"],
4
- "sourcesContent": ["import type {\n Agent,\n Context,\n EventBus,\n ExtensionRegistry,\n PluginAPI,\n ProviderRegistry,\n SessionWriter,\n SlashCommandRegistry,\n ToolRegistry,\n} from '@wrongstack/core';\nimport type { WrongStackPack } from './pack.js';\n\nexport interface RuntimeHost {\n agent: Agent;\n context: Context;\n events: EventBus;\n tools: ToolRegistry;\n providers: ProviderRegistry;\n slashCommands: SlashCommandRegistry;\n session: SessionWriter;\n extensions?: ExtensionRegistry | undefined;\n shutdown(): Promise<void>;\n}\n\nexport interface RuntimeHostParts {\n agent: Agent;\n context: Context;\n events: EventBus;\n tools: ToolRegistry;\n providers: ProviderRegistry;\n slashCommands: SlashCommandRegistry;\n session: SessionWriter;\n extensions?: ExtensionRegistry | undefined;\n shutdown?: (() => void | Promise<void>) | undefined;\n}\n\nexport function createRuntimeHostFromParts(parts: RuntimeHostParts): RuntimeHost {\n return {\n agent: parts.agent,\n context: parts.context,\n events: parts.events,\n tools: parts.tools,\n providers: parts.providers,\n slashCommands: parts.slashCommands,\n session: parts.session,\n extensions: parts.extensions,\n async shutdown() {\n await parts.shutdown?.();\n },\n };\n}\n\nexport interface ApplyPackOptions {\n owner?: string | undefined;\n api?: PluginAPI | undefined;\n}\n\nexport interface AppliedPack {\n pack: WrongStackPack;\n owner: string;\n teardown(): Promise<void>;\n}\n\nexport async function applyWrongStackPack(\n host: Pick<RuntimeHost, 'tools' | 'providers' | 'slashCommands'> & {\n extensions?: ExtensionRegistry | undefined;\n },\n pack: WrongStackPack,\n opts: ApplyPackOptions = {},\n): Promise<AppliedPack> {\n const owner = opts.owner ?? pack.name;\n const unregisterExtensions: Array<() => void> = [];\n\n // Track registered tool names, command names, and provider types so teardown\n // can reverse everything in registration order.\n const registeredToolNames: string[] = [];\n const registeredCommandNames: string[] = [];\n const registeredProviderTypes: string[] = [];\n\n if (pack.tools) {\n const tools = [...pack.tools];\n host.tools.registerAllOrThrow(tools, owner);\n for (const t of tools) registeredToolNames.push(t.name);\n }\n if (pack.providers) {\n const providers = [...pack.providers];\n host.providers.registerAll(providers);\n for (const p of providers) registeredProviderTypes.push(p.type);\n }\n if (pack.slashCommands) {\n const cmds = [...pack.slashCommands];\n host.slashCommands.registerAll(cmds, owner);\n // SlashCommandRegistry stores plugin-owned commands under `${owner}:${name}`;\n // track the real lookup key so teardown can unregister them.\n for (const c of cmds)\n registeredCommandNames.push(owner === 'core' ? c.name : `${owner}:${c.name}`);\n }\n if (pack.extensions && host.extensions) {\n for (const ext of pack.extensions) {\n unregisterExtensions.push(host.extensions.register(ext));\n }\n }\n\n // If setup() throws after registration, roll back everything we registered above.\n // This makes applyWrongStackPack() transactional from the caller's perspective \u2014\n // either the pack is fully applied or it is not.\n if (pack.setup) {\n if (!opts.api) {\n throw new Error(`Pack \"${pack.name}\" defines setup() but no PluginAPI was provided`);\n }\n try {\n await pack.setup(opts.api);\n } catch (setupErr) {\n // Roll back in reverse order: extensions first, then commands,\n // then tools, then providers. Extensions are unregistered before\n // tools/commands because extensions may depend on those capabilities;\n // tearing them down first avoids dangling refs.\n for (let i = unregisterExtensions.length - 1; i >= 0; i--) {\n unregisterExtensions[i]!();\n }\n for (let i = registeredCommandNames.length - 1; i >= 0; i--) {\n host.slashCommands.unregister(registeredCommandNames[i]!);\n }\n for (let i = registeredToolNames.length - 1; i >= 0; i--) {\n host.tools.unregister(registeredToolNames[i]!);\n }\n for (let i = registeredProviderTypes.length - 1; i >= 0; i--) {\n host.providers.unregister(registeredProviderTypes[i]!);\n }\n throw setupErr;\n }\n }\n\n return {\n pack,\n owner,\n async teardown() {\n for (let i = unregisterExtensions.length - 1; i >= 0; i--) {\n unregisterExtensions[i]!();\n }\n // Unregister commands, tools, and providers so the same pack can be\n // re-loaded cleanly without name/type conflicts.\n for (let i = registeredCommandNames.length - 1; i >= 0; i--) {\n host.slashCommands.unregister(registeredCommandNames[i]!);\n }\n for (let i = registeredToolNames.length - 1; i >= 0; i--) {\n host.tools.unregister(registeredToolNames[i]!);\n }\n for (let i = registeredProviderTypes.length - 1; i >= 0; i--) {\n host.providers.unregister(registeredProviderTypes[i]!);\n }\n if (pack.teardown) {\n if (!opts.api) {\n throw new Error(`Pack \"${pack.name}\" defines teardown() but no PluginAPI was provided`);\n }\n await pack.teardown(opts.api);\n }\n },\n };\n}\n\nexport async function applyWrongStackPacks(\n host: Pick<RuntimeHost, 'tools' | 'providers' | 'slashCommands'> & {\n extensions?: ExtensionRegistry | undefined;\n },\n packs: readonly WrongStackPack[],\n opts: ApplyPackOptions = {},\n): Promise<AppliedPack[]> {\n const applied: AppliedPack[] = [];\n try {\n for (const pack of packs) {\n applied.push(await applyWrongStackPack(host, pack, opts));\n }\n return applied;\n } catch (err) {\n // Roll back already-mounted packs. Surface teardown failures via\n // process.emitWarning so they don't mask the original error but\n // remain visible \u2014 a silent teardown failure can leave state\n // half-initialized in ways that make the next run fail mysteriously.\n for (let i = applied.length - 1; i >= 0; i--) {\n const mounted = applied[i]!;\n await mounted.teardown().catch((teardownErr) => {\n const detail = teardownErr instanceof Error ? teardownErr.message : String(teardownErr);\n process.emitWarning(\n `Pack teardown during error rollback failed: ${detail}`,\n 'PackRollbackWarning',\n );\n });\n }\n throw err;\n }\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import type { Agent, Context } from '@wrongstack/core/agent';\nimport type { ExtensionRegistry } from '@wrongstack/core/extension';\nimport type { EventBus } from '@wrongstack/core/kernel';\nimport type {\n ProviderRegistry,\n SlashCommandRegistry,\n ToolRegistry,\n} from '@wrongstack/core/registry';\nimport type { PluginAPI, SessionWriter } from '@wrongstack/core/types';\nimport type { WrongStackPack } from './pack.js';\n\nexport interface RuntimeHost {\n agent: Agent;\n context: Context;\n events: EventBus;\n tools: ToolRegistry;\n providers: ProviderRegistry;\n slashCommands: SlashCommandRegistry;\n session: SessionWriter;\n extensions?: ExtensionRegistry | undefined;\n shutdown(): Promise<void>;\n}\n\nexport interface RuntimeHostParts {\n agent: Agent;\n context: Context;\n events: EventBus;\n tools: ToolRegistry;\n providers: ProviderRegistry;\n slashCommands: SlashCommandRegistry;\n session: SessionWriter;\n extensions?: ExtensionRegistry | undefined;\n shutdown?: (() => void | Promise<void>) | undefined;\n}\n\nexport function createRuntimeHostFromParts(parts: RuntimeHostParts): RuntimeHost {\n return {\n agent: parts.agent,\n context: parts.context,\n events: parts.events,\n tools: parts.tools,\n providers: parts.providers,\n slashCommands: parts.slashCommands,\n session: parts.session,\n extensions: parts.extensions,\n async shutdown() {\n await parts.shutdown?.();\n },\n };\n}\n\nexport interface ApplyPackOptions {\n owner?: string | undefined;\n api?: PluginAPI | undefined;\n}\n\nexport interface AppliedPack {\n pack: WrongStackPack;\n owner: string;\n teardown(): Promise<void>;\n}\n\nexport async function applyWrongStackPack(\n host: Pick<RuntimeHost, 'tools' | 'providers' | 'slashCommands'> & {\n extensions?: ExtensionRegistry | undefined;\n },\n pack: WrongStackPack,\n opts: ApplyPackOptions = {},\n): Promise<AppliedPack> {\n const owner = opts.owner ?? pack.name;\n const unregisterExtensions: Array<() => void> = [];\n\n // Track registered tool names, command names, and provider types so teardown\n // can reverse everything in registration order.\n const registeredToolNames: string[] = [];\n const registeredCommandNames: string[] = [];\n const registeredProviderTypes: string[] = [];\n\n if (pack.tools) {\n const tools = [...pack.tools];\n host.tools.registerAllOrThrow(tools, owner);\n for (const t of tools) registeredToolNames.push(t.name);\n }\n if (pack.providers) {\n const providers = [...pack.providers];\n host.providers.registerAll(providers);\n for (const p of providers) registeredProviderTypes.push(p.type);\n }\n if (pack.slashCommands) {\n const cmds = [...pack.slashCommands];\n host.slashCommands.registerAll(cmds, owner);\n // SlashCommandRegistry stores plugin-owned commands under `${owner}:${name}`;\n // track the real lookup key so teardown can unregister them.\n for (const c of cmds)\n registeredCommandNames.push(owner === 'core' ? c.name : `${owner}:${c.name}`);\n }\n if (pack.extensions && host.extensions) {\n for (const ext of pack.extensions) {\n unregisterExtensions.push(host.extensions.register(ext));\n }\n }\n\n // If setup() throws after registration, roll back everything we registered above.\n // This makes applyWrongStackPack() transactional from the caller's perspective \u2014\n // either the pack is fully applied or it is not.\n if (pack.setup) {\n if (!opts.api) {\n throw new Error(`Pack \"${pack.name}\" defines setup() but no PluginAPI was provided`);\n }\n try {\n await pack.setup(opts.api);\n } catch (setupErr) {\n // Roll back in reverse order: extensions first, then commands,\n // then tools, then providers. Extensions are unregistered before\n // tools/commands because extensions may depend on those capabilities;\n // tearing them down first avoids dangling refs.\n for (let i = unregisterExtensions.length - 1; i >= 0; i--) {\n unregisterExtensions[i]!();\n }\n for (let i = registeredCommandNames.length - 1; i >= 0; i--) {\n host.slashCommands.unregister(registeredCommandNames[i]!);\n }\n for (let i = registeredToolNames.length - 1; i >= 0; i--) {\n host.tools.unregister(registeredToolNames[i]!);\n }\n for (let i = registeredProviderTypes.length - 1; i >= 0; i--) {\n host.providers.unregister(registeredProviderTypes[i]!);\n }\n throw setupErr;\n }\n }\n\n return {\n pack,\n owner,\n async teardown() {\n for (let i = unregisterExtensions.length - 1; i >= 0; i--) {\n unregisterExtensions[i]!();\n }\n // Unregister commands, tools, and providers so the same pack can be\n // re-loaded cleanly without name/type conflicts.\n for (let i = registeredCommandNames.length - 1; i >= 0; i--) {\n host.slashCommands.unregister(registeredCommandNames[i]!);\n }\n for (let i = registeredToolNames.length - 1; i >= 0; i--) {\n host.tools.unregister(registeredToolNames[i]!);\n }\n for (let i = registeredProviderTypes.length - 1; i >= 0; i--) {\n host.providers.unregister(registeredProviderTypes[i]!);\n }\n if (pack.teardown) {\n if (!opts.api) {\n throw new Error(`Pack \"${pack.name}\" defines teardown() but no PluginAPI was provided`);\n }\n await pack.teardown(opts.api);\n }\n },\n };\n}\n\nexport async function applyWrongStackPacks(\n host: Pick<RuntimeHost, 'tools' | 'providers' | 'slashCommands'> & {\n extensions?: ExtensionRegistry | undefined;\n },\n packs: readonly WrongStackPack[],\n opts: ApplyPackOptions = {},\n): Promise<AppliedPack[]> {\n const applied: AppliedPack[] = [];\n try {\n for (const pack of packs) {\n applied.push(await applyWrongStackPack(host, pack, opts));\n }\n return applied;\n } catch (err) {\n // Roll back already-mounted packs. Surface teardown failures via\n // process.emitWarning so they don't mask the original error but\n // remain visible \u2014 a silent teardown failure can leave state\n // half-initialized in ways that make the next run fail mysteriously.\n for (let i = applied.length - 1; i >= 0; i--) {\n const mounted = applied[i]!;\n await mounted.teardown().catch((teardownErr) => {\n const detail = teardownErr instanceof Error ? teardownErr.message : String(teardownErr);\n process.emitWarning(\n `Pack teardown during error rollback failed: ${detail}`,\n 'PackRollbackWarning',\n );\n });\n }\n throw err;\n }\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
package/dist/index.d.ts CHANGED
@@ -1,23 +1,13 @@
1
1
  /**
2
2
  * @wrongstack/runtime
3
3
  *
4
- * Transitional home for concrete runtime implementations.
5
- *
6
- * The long-term package boundary is:
7
- * - @wrongstack/core: kernel, agent runtime, registries, public contracts.
8
- * - @wrongstack/runtime: default storage, security, config, observability,
9
- * compaction, models, skills, and host composition helpers.
10
- *
11
- * For this first refactor slice, the implementations still physically live in
12
- * @wrongstack/core and are re-exported here. That gives hosts a stable import
13
- * target while later moves can happen behind this facade.
4
+ * Concrete host composition and platform adapters. Core-owned defaults are
5
+ * deliberately not re-exported: doing so obscures ownership and makes a
6
+ * Core-compatible Runtime implementation move cyclic at package level.
14
7
  */
15
- export { DefaultSystemPromptBuilder, type DefaultSystemPromptBuilderOptions, } from '@wrongstack/core';
16
- export * from '@wrongstack/core/defaults';
17
- export { DefaultPathResolver, DefaultTokenCounter, } from '@wrongstack/core/infrastructure';
18
8
  export * from './clipboard.js';
19
9
  export * from './container.js';
20
- export { type LightSubagentFactoryDeps, makeLightSubagentFactory, } from './fleet/light-subagent-factory.js';
10
+ export { abortLightSubagent, type LightSubagentFactoryDeps, makeLightSubagentFactory, } from './fleet/light-subagent-factory.js';
21
11
  export * from './host.js';
22
12
  export { type ProbeOptions, type ProbeResult, probeLocalLlm } from './local-llm-probe.js';
23
13
  export * from './pack.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,EACL,0BAA0B,EAC1B,KAAK,iCAAiC,GACvC,MAAM,kBAAkB,CAAC;AAC1B,cAAc,2BAA2B,CAAC;AAC1C,OAAO,EACL,mBAAmB,EACnB,mBAAmB,GACpB,MAAM,iCAAiC,CAAC;AACzC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,gBAAgB,CAAC;AAC/B,OAAO,EACL,KAAK,wBAAwB,EAC7B,wBAAwB,GACzB,MAAM,mCAAmC,CAAC;AAC3C,cAAc,WAAW,CAAC;AAC1B,OAAO,EAAE,KAAK,YAAY,EAAE,KAAK,WAAW,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAC1F,cAAc,WAAW,CAAC;AAC1B,cAAc,aAAa,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,cAAc,gBAAgB,CAAC;AAC/B,cAAc,gBAAgB,CAAC;AAC/B,OAAO,EACL,kBAAkB,EAClB,KAAK,wBAAwB,EAC7B,wBAAwB,GACzB,MAAM,mCAAmC,CAAC;AAC3C,cAAc,WAAW,CAAC;AAC1B,OAAO,EAAE,KAAK,YAAY,EAAE,KAAK,WAAW,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAC1F,cAAc,WAAW,CAAC;AAC1B,cAAc,aAAa,CAAC"}
package/dist/index.js CHANGED
@@ -1,20 +1,10 @@
1
- // src/index.ts
2
- import {
3
- DefaultSystemPromptBuilder as DefaultSystemPromptBuilder2
4
- } from "@wrongstack/core";
5
- export * from "@wrongstack/core/defaults";
6
- import {
7
- DefaultPathResolver,
8
- DefaultTokenCounter as DefaultTokenCounter2
9
- } from "@wrongstack/core/infrastructure";
10
-
11
1
  // src/clipboard.ts
12
2
  import { spawn } from "node:child_process";
13
3
  import { randomUUID } from "node:crypto";
14
4
  import * as fs from "node:fs/promises";
15
5
  import * as os from "node:os";
16
6
  import * as path from "node:path";
17
- import { buildChildEnv } from "@wrongstack/core";
7
+ import { buildChildEnv } from "@wrongstack/core/utils";
18
8
  var MAX_IMAGE_BYTES = 10 * 1024 * 1024;
19
9
  async function readClipboardImage() {
20
10
  const platform = process.platform;
@@ -188,26 +178,32 @@ function runCmdToFile(cmd, args, outPath) {
188
178
  }
189
179
 
190
180
  // src/container.ts
181
+ import * as fs2 from "node:fs";
182
+ import * as path2 from "node:path";
183
+ import {
184
+ DefaultSystemPromptBuilder,
185
+ FallbackProfileManager
186
+ } from "@wrongstack/core/agent";
191
187
  import {
192
- Container,
193
188
  createStrategyCompactor,
194
- DefaultConfigStore,
195
189
  DefaultErrorHandler,
196
- FallbackProfileManager,
197
- DefaultModeStore,
198
- DefaultPermissionPolicy,
199
190
  DefaultPromptLoader,
200
191
  DefaultRetryPolicy,
192
+ DefaultSkillLoader
193
+ } from "@wrongstack/core/execution";
194
+ import { Container, TOKENS } from "@wrongstack/core/kernel";
195
+ import { DefaultModeStore } from "@wrongstack/core/models";
196
+ import {
197
+ DirectoryPermissionPolicy,
198
+ DefaultPermissionPolicy,
201
199
  DefaultSecretScrubber,
202
- DefaultSessionStore,
203
- DefaultSkillLoader,
204
- DefaultSystemPromptBuilder,
205
- TOKENS
206
- } from "@wrongstack/core";
200
+ validateDirectoryPolicy
201
+ } from "@wrongstack/core/security";
202
+ import { DefaultConfigStore, DefaultSessionStore } from "@wrongstack/core/storage";
207
203
  import { buildRecoveryStrategies } from "@wrongstack/core/execution";
208
204
  import { DefaultTokenCounter } from "@wrongstack/core/infrastructure";
209
205
  import { getSessionRegistry } from "@wrongstack/core/storage";
210
- import { SuperMemoryStore, SqliteSuperMemoryStore, isSqliteAvailable } from "@wrongstack/super-memory";
206
+ import { createSqliteMemoryPort, isSqliteAvailable } from "@wrongstack/sage";
211
207
  function createDefaultContainer(opts) {
212
208
  const { config, wpaths, logger, modelsRegistry } = opts;
213
209
  const container = new Container();
@@ -268,23 +264,18 @@ function createDefaultContainer(opts) {
268
264
  }
269
265
  })
270
266
  );
271
- const wantSqlite = config.superMemory?.storage?.engine === "sqlite";
272
- const useSqlite = wantSqlite && isSqliteAvailable();
273
- if (wantSqlite && !useSqlite) {
274
- logger.warn(
275
- "Super Memory: SQLite engine requested but node:sqlite is unavailable in this runtime. Falling back to JSONL backend. (SQLite requires Node >= 22.5.)"
267
+ if (!isSqliteAvailable()) {
268
+ throw new Error(
269
+ "SAGE requires Node built-in SQLite (node:sqlite; Node >= 22.5). The JSONL compatibility fallback has been removed."
276
270
  );
277
271
  }
278
- const memoryStore = useSqlite ? new SqliteSuperMemoryStore({
279
- projectRoot: wpaths.projectRoot,
280
- directory: config.superMemory?.storage?.directory,
281
- events: opts.events
282
- }) : new SuperMemoryStore({
272
+ const memoryStore = createSqliteMemoryPort({
283
273
  projectRoot: wpaths.projectRoot,
284
- directory: config.superMemory?.storage?.directory,
274
+ directory: config.Sage?.storage?.directory,
285
275
  events: opts.events
286
276
  });
287
277
  container.bind(TOKENS.MemoryStore, () => memoryStore);
278
+ container.bind(TOKENS.MemoryPort, () => memoryStore);
288
279
  const skillLoader = new DefaultSkillLoader({
289
280
  paths: wpaths,
290
281
  bundledDir: opts.bundledSkillsDir,
@@ -308,7 +299,7 @@ function createDefaultContainer(opts) {
308
299
  },
309
300
  skillMode: config.skills?.mode,
310
301
  skillEagerMaxChars: config.skills?.eagerMaxChars,
311
- // Super Memory's turn middleware owns memory injection — don't also
302
+ // SAGE's turn middleware owns memory injection — don't also
312
303
  // inject a static prompt section. Callers may override via
313
304
  // opts.systemPrompt if they truly want the static section.
314
305
  injectMemory: false,
@@ -316,6 +307,28 @@ function createDefaultContainer(opts) {
316
307
  })
317
308
  );
318
309
  }
310
+ const directoryPolicyPath = path2.join(wpaths.projectRoot, ".wrongstack", "directory-rules.json");
311
+ let directoryPolicy = {
312
+ schemaVersion: 1,
313
+ rules: []
314
+ };
315
+ try {
316
+ const parsed = JSON.parse(fs2.readFileSync(directoryPolicyPath, "utf8"));
317
+ const validation = validateDirectoryPolicy(parsed);
318
+ if (!validation.ok) {
319
+ throw new Error(
320
+ validation.diagnostics.map((diagnostic) => `${diagnostic.path}: ${diagnostic.message}`).join("; ")
321
+ );
322
+ }
323
+ directoryPolicy = validation.policy;
324
+ } catch (error) {
325
+ if (error.code !== "ENOENT") {
326
+ throw new Error(
327
+ `Invalid directory permission policy at ${directoryPolicyPath}: ${error instanceof Error ? error.message : String(error)}`,
328
+ { cause: error }
329
+ );
330
+ }
331
+ }
319
332
  container.bind(TOKENS.PermissionPolicy, () => {
320
333
  const policyOptions = {
321
334
  trustFile: wpaths.projectTrust,
@@ -324,7 +337,9 @@ function createDefaultContainer(opts) {
324
337
  if (opts.permission?.promptDelegate !== void 0) {
325
338
  policyOptions.promptDelegate = opts.permission.promptDelegate;
326
339
  }
327
- return new DefaultPermissionPolicy(policyOptions);
340
+ return new DirectoryPermissionPolicy(new DefaultPermissionPolicy(policyOptions), {
341
+ policy: directoryPolicy
342
+ });
328
343
  });
329
344
  container.bind(
330
345
  TOKENS.Compactor,
@@ -354,27 +369,36 @@ function createDefaultContainer(opts) {
354
369
  import { randomUUID as randomUUID2 } from "node:crypto";
355
370
  import {
356
371
  Agent,
357
- AutoApprovePermissionPolicy,
358
- applyModelRuntime,
359
372
  FallbackProfileManager as FallbackProfileManager2,
360
373
  Context,
361
374
  createDefaultPipelines,
362
- createFallbackModelExtension,
363
- EventBus,
375
+ createFallbackModelExtension
376
+ } from "@wrongstack/core/agent";
377
+ import {
378
+ resolveSubagentModelTarget
379
+ } from "@wrongstack/core/coordination";
380
+ import {
381
+ applyModelRuntime,
364
382
  installSubagentAutoCompaction,
365
383
  mergeModelRuntime,
366
- resolveSubagentModelTarget,
367
- TOKENS as TOKENS2,
368
- ToolExecutor,
369
- ToolRegistry,
370
- WIDE_SUBAGENT_CAPABILITIES
371
- } from "@wrongstack/core";
384
+ ToolExecutor
385
+ } from "@wrongstack/core/execution";
386
+ import { EventBus, TOKENS as TOKENS2 } from "@wrongstack/core/kernel";
387
+ import { ToolRegistry } from "@wrongstack/core/registry";
388
+ import { AutoApprovePermissionPolicy, WIDE_SUBAGENT_CAPABILITIES } from "@wrongstack/core/security";
372
389
  var SUBAGENT_BASELINE = "You are a subagent executing one delegated task end-to-end. Work autonomously with your tools; do not ask for confirmation on routine in-project actions. Keep output concise.";
373
390
  var _SUBAGENT_ABORT = "wrongstack:subagent-abort-controller";
391
+ function abortLightSubagent(agent) {
392
+ const ac = agent.ctx.meta[_SUBAGENT_ABORT];
393
+ ac?.abort();
394
+ }
374
395
  function makeLightSubagentFactory(deps) {
375
396
  const configStore = deps.container.resolve(TOKENS2.ConfigStore);
376
- const fallbackProfileManager = deps.container.safeResolve(TOKENS2.FallbackProfileManager) ?? new FallbackProfileManager2(configStore.get());
377
- configStore.watch((next) => fallbackProfileManager.reload(next));
397
+ const existingManager = deps.container.safeResolve(TOKENS2.FallbackProfileManager);
398
+ const fallbackProfileManager = existingManager ?? new FallbackProfileManager2(configStore.get());
399
+ if (!existingManager) {
400
+ configStore.watch((next) => fallbackProfileManager.reload(next));
401
+ }
378
402
  const tokenCounter = deps.container.resolve(TOKENS2.TokenCounter);
379
403
  const secretScrubber = deps.container.resolve(TOKENS2.SecretScrubber);
380
404
  const systemPromptBuilder = deps.container.resolve(TOKENS2.SystemPromptBuilder);
@@ -469,15 +493,25 @@ function makeLightSubagentFactory(deps) {
469
493
  });
470
494
  agent.extensions.register(
471
495
  createFallbackModelExtension({
472
- getConfig: () => configStore.get(),
496
+ // Pin provider/model to THIS worker's target so the extension restores
497
+ // to the worker, not the leader. Other fields stay live so WebUI edits
498
+ // to chains/profiles still reach active workers.
499
+ getConfig: () => ({ ...configStore.get(), provider: effProvider, model: effModel }),
473
500
  fallbackProfileManager,
474
501
  getFallbackModels: () => subCfg.fallbackModels,
475
502
  getFallbackProfile: () => fallbackProfile,
476
- buildProvider: (id, model) => buildProvider(deps.providerRegistry, configStore.get(), id, model ?? effModel),
503
+ buildProvider: (id, model) => buildProvider(
504
+ deps.providerRegistry,
505
+ configStore.get(),
506
+ id,
507
+ /* v8 ignore next -- core fallback entries always carry a model; keep the interface fallback defensive */
508
+ model ?? effModel
509
+ ),
477
510
  onModelSwitch: async (id, model) => {
478
511
  subReasoningConfig = await resolveReasoningConfig(modelsRegistry, id, model);
479
512
  },
480
- events
513
+ events,
514
+ ...deps.now ? { now: deps.now } : {}
481
515
  })
482
516
  );
483
517
  return { agent, events };
@@ -763,10 +797,10 @@ async function probeLocalLlm(opts) {
763
797
  }
764
798
 
765
799
  // src/vision.ts
766
- import * as fs2 from "node:fs/promises";
800
+ import * as fs3 from "node:fs/promises";
767
801
  import * as os2 from "node:os";
768
- import * as path2 from "node:path";
769
- import { assertNotPrivateHost } from "@wrongstack/core";
802
+ import * as path3 from "node:path";
803
+ import { assertNotPrivateHost } from "@wrongstack/core/utils";
770
804
  var ImageInputUnsupportedError = class extends Error {
771
805
  constructor(opts) {
772
806
  const target = [opts.providerId, opts.model].filter(Boolean).join("/") || "current model";
@@ -935,8 +969,8 @@ async function buildToolPayload(tool, image, prompt = "Describe this image for a
935
969
  const p = await writeTempImage(data, mediaType);
936
970
  payload[pathKey] = p;
937
971
  cleanup = async () => {
938
- await fs2.unlink(p).catch(() => void 0);
939
- await fs2.rmdir(path2.dirname(p)).catch(() => void 0);
972
+ await fs3.unlink(p).catch(() => void 0);
973
+ await fs3.rmdir(path3.dirname(p)).catch(() => void 0);
940
974
  };
941
975
  } else if ("image" in props) {
942
976
  payload.image = image.source.type === "base64" ? { type: "base64", mediaType, media_type: mediaType, data } : { type: "url", url };
@@ -968,9 +1002,9 @@ function firstPresent(props, keys) {
968
1002
  }
969
1003
  async function writeTempImage(data, mediaType) {
970
1004
  const ext = mediaType.includes("jpeg") || mediaType.includes("jpg") ? "jpg" : "png";
971
- const dir = await fs2.mkdtemp(path2.join(os2.tmpdir(), "wstack-vision-"));
972
- const file = path2.join(dir, `image.${ext}`);
973
- await fs2.writeFile(file, data, "base64");
1005
+ const dir = await fs3.mkdtemp(path3.join(os2.tmpdir(), "wstack-vision-"));
1006
+ const file = path3.join(dir, `image.${ext}`);
1007
+ await fs3.writeFile(file, data, "base64");
974
1008
  return file;
975
1009
  }
976
1010
  function schemaProperties(tool) {
@@ -995,15 +1029,13 @@ function stringifyToolResult(value) {
995
1029
  return JSON.stringify(value);
996
1030
  }
997
1031
  export {
998
- DefaultPathResolver,
999
- DefaultSystemPromptBuilder2 as DefaultSystemPromptBuilder,
1000
- DefaultTokenCounter2 as DefaultTokenCounter,
1001
1032
  ImageInputUnsupportedError,
1002
1033
  VISION_IMAGE_KEYS,
1003
1034
  VISION_MEDIA_TYPE_KEYS,
1004
1035
  VISION_PATH_KEYS,
1005
1036
  VISION_PROMPT_KEYS,
1006
1037
  VisionUrlBlockedError,
1038
+ abortLightSubagent,
1007
1039
  applyWrongStackPack,
1008
1040
  applyWrongStackPacks,
1009
1041
  createDefaultContainer,