@theokit/sdk 4.49.0 → 4.51.0
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/CHANGELOG.md +17 -0
- package/dist/{agent-JA4ILE5O.cjs → agent-B2WU3JP6.cjs} +10 -9
- package/dist/{agent-JA4ILE5O.cjs.map → agent-B2WU3JP6.cjs.map} +1 -1
- package/dist/{agent-GKX5FE5K.js → agent-DI2QQHSJ.js} +9 -8
- package/dist/{agent-GKX5FE5K.js.map → agent-DI2QQHSJ.js.map} +1 -1
- package/dist/{chunk-3NLOQEJR.js → chunk-34XOCZJO.js} +5 -16
- package/dist/chunk-34XOCZJO.js.map +1 -0
- package/dist/{chunk-64TJCXY5.cjs → chunk-3G6ZDZ6L.cjs} +5 -5
- package/dist/{chunk-64TJCXY5.cjs.map → chunk-3G6ZDZ6L.cjs.map} +1 -1
- package/dist/{chunk-JO76RWCA.cjs → chunk-72HEBGWN.cjs} +4 -4
- package/dist/{chunk-JO76RWCA.cjs.map → chunk-72HEBGWN.cjs.map} +1 -1
- package/dist/{chunk-XARLSCKA.js → chunk-ACHVCIDQ.js} +11 -11
- package/dist/chunk-ACHVCIDQ.js.map +1 -0
- package/dist/{chunk-RJBHWM6D.js → chunk-E54KDYOE.js} +3 -3
- package/dist/{chunk-RJBHWM6D.js.map → chunk-E54KDYOE.js.map} +1 -1
- package/dist/{chunk-2S6B5B2A.js → chunk-E7WDXT4X.js} +3 -3
- package/dist/{chunk-2S6B5B2A.js.map → chunk-E7WDXT4X.js.map} +1 -1
- package/dist/{chunk-TSK4VVBW.cjs → chunk-F7OBYH2X.cjs} +52 -52
- package/dist/chunk-F7OBYH2X.cjs.map +1 -0
- package/dist/{chunk-6FSQ3CHQ.js → chunk-JGYYNDAZ.js} +5 -6
- package/dist/chunk-JGYYNDAZ.js.map +1 -0
- package/dist/{chunk-UU7MAO2D.cjs → chunk-OKLYRPKL.cjs} +4 -16
- package/dist/chunk-OKLYRPKL.cjs.map +1 -0
- package/dist/{chunk-EON4YTR6.js → chunk-R2A3WIJY.js} +3 -3
- package/dist/{chunk-EON4YTR6.js.map → chunk-R2A3WIJY.js.map} +1 -1
- package/dist/chunk-RIAM53CP.js +22 -0
- package/dist/chunk-RIAM53CP.js.map +1 -0
- package/dist/{chunk-GH52NOCL.cjs → chunk-RWMNTFHZ.cjs} +9 -9
- package/dist/{chunk-GH52NOCL.cjs.map → chunk-RWMNTFHZ.cjs.map} +1 -1
- package/dist/{chunk-MZQHVN7C.js → chunk-SEZJGV7C.js} +3 -3
- package/dist/{chunk-MZQHVN7C.js.map → chunk-SEZJGV7C.js.map} +1 -1
- package/dist/{chunk-FAUKVJCC.cjs → chunk-UQHIEUDY.cjs} +3 -3
- package/dist/{chunk-FAUKVJCC.cjs.map → chunk-UQHIEUDY.cjs.map} +1 -1
- package/dist/{chunk-UJ7HK7BX.js → chunk-VK7SIDYI.js} +3 -3
- package/dist/{chunk-UJ7HK7BX.js.map → chunk-VK7SIDYI.js.map} +1 -1
- package/dist/chunk-VKJ7V7EB.cjs +25 -0
- package/dist/chunk-VKJ7V7EB.cjs.map +1 -0
- package/dist/{chunk-74VVGK7P.cjs → chunk-WUUSAMFC.cjs} +5 -5
- package/dist/{chunk-74VVGK7P.cjs.map → chunk-WUUSAMFC.cjs.map} +1 -1
- package/dist/{chunk-XA3TSBAH.cjs → chunk-XABN5HY6.cjs} +4 -5
- package/dist/chunk-XABN5HY6.cjs.map +1 -0
- package/dist/{compact-session-UUCBTBCZ.cjs → compact-session-FKYCJRAK.cjs} +4 -3
- package/dist/{compact-session-UUCBTBCZ.cjs.map → compact-session-FKYCJRAK.cjs.map} +1 -1
- package/dist/{compact-session-GF2CBKXB.js → compact-session-LF4YOT5S.js} +4 -3
- package/dist/{compact-session-GF2CBKXB.js.map → compact-session-LF4YOT5S.js.map} +1 -1
- package/dist/context/index.cjs +6 -5
- package/dist/context/index.cjs.map +1 -1
- package/dist/context/index.js +3 -2
- package/dist/context/index.js.map +1 -1
- package/dist/cron.cjs +9 -8
- package/dist/cron.js +8 -7
- package/dist/eval.cjs +8 -7
- package/dist/eval.cjs.map +1 -1
- package/dist/eval.js +7 -6
- package/dist/eval.js.map +1 -1
- package/dist/filesystem/index.cjs +6 -5
- package/dist/filesystem/index.cjs.map +1 -1
- package/dist/filesystem/index.js +2 -1
- package/dist/filesystem/index.js.map +1 -1
- package/dist/{index-manager-YFFEPISE.cjs → index-manager-34ELCOAP.cjs} +6 -5
- package/dist/{index-manager-YFFEPISE.cjs.map → index-manager-34ELCOAP.cjs.map} +1 -1
- package/dist/index-manager-OMJVYS2U.js +12 -0
- package/dist/{index-manager-X5IPG2JL.js.map → index-manager-OMJVYS2U.js.map} +1 -1
- package/dist/index.cjs +183 -35
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +320 -1
- package/dist/index.d.ts +320 -1
- package/dist/index.js +152 -13
- package/dist/index.js.map +1 -1
- package/dist/{inject-session-I3HK3AHB.cjs → inject-session-J7Y6XACY.cjs} +4 -4
- package/dist/{inject-session-I3HK3AHB.cjs.map → inject-session-J7Y6XACY.cjs.map} +1 -1
- package/dist/{inject-session-NR64GB3T.js → inject-session-MWRJENH4.js} +3 -3
- package/dist/{inject-session-NR64GB3T.js.map → inject-session-MWRJENH4.js.map} +1 -1
- package/dist/internal/memory/adapters/index.cjs +2 -1
- package/dist/internal/memory/adapters/index.js +2 -1
- package/dist/internal/security/index.cjs +9 -8
- package/dist/internal/security/index.js +2 -1
- package/dist/path-safety.cjs +9 -8
- package/dist/path-safety.js +2 -1
- package/dist/skills.cjs +5 -4
- package/dist/skills.js +3 -2
- package/dist/workflow.cjs +11 -10
- package/dist/workflow.js +3 -2
- package/package.json +1 -1
- package/dist/chunk-3NLOQEJR.js.map +0 -1
- package/dist/chunk-6FSQ3CHQ.js.map +0 -1
- package/dist/chunk-TSK4VVBW.cjs.map +0 -1
- package/dist/chunk-UU7MAO2D.cjs.map +0 -1
- package/dist/chunk-XA3TSBAH.cjs.map +0 -1
- package/dist/chunk-XARLSCKA.js.map +0 -1
- package/dist/index-manager-X5IPG2JL.js +0 -11
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/filesystem/types.ts","../../src/filesystem/local-filesystem.ts"],"names":["fsReadFile","fsWriteFile","fsStat"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * Filesystem backend protocol — a pluggable file *storage* provider for agent\n * tools, the storage-side twin of {@link SandboxBackend} (execution-side).\n *\n * SE31 (a peer framework Workspaces comparison). Mirrors `SandboxBackend`'s shape: a small\n * set of abstract methods (`readFile` / `writeFile` / `stat` / `list`) with\n * `exists()` derived on the base class, a boundary `basePath`, a `readOnly`\n * flag, and typed errors. Unlike `SandboxBackend` (whose file ops shell out via\n * `execute`, requiring command execution and giving NO structured `stat`), a\n * `FilesystemBackend` serves a *filesystem-only* workspace with no sandbox and\n * exposes a real `stat().mtimeMs` — the primitive SE32's read-before-write\n * safety compares against. See ADR 0011.\n *\n * New backends (S3, GCS, in-memory) implement the four abstract methods; higher\n * level helpers derive on the base. This is the backend *seam* — it does NOT\n * ship agent-facing tools nor a bundled workspace (bring-your-own-tools stands).\n *\n * @public\n */\n\n/** Structured file metadata. `mtimeMs` is the read-before-write oracle (SE32). */\nexport interface FileStat {\n readonly size: number;\n readonly mtimeMs: number;\n readonly isFile: boolean;\n readonly isDirectory: boolean;\n}\n\n/** Options a write may carry. SE32 adds `expectedMtime` (stale-write guard). */\nexport interface WriteFileOptions {\n /**\n * SE32 — when set, the write fails with {@link StaleFileError} if the file's\n * current `mtimeMs` differs (someone changed it since it was last read).\n */\n readonly expectedMtime?: number;\n}\n\nexport interface FilesystemConfig {\n /** Boundary root. Every path is resolved within it; escapes are rejected. */\n readonly basePath?: string;\n /** When true, every write throws {@link FilesystemReadOnlyError}. */\n readonly readOnly?: boolean;\n}\n\n/** A path escaped the backend's `basePath` (traversal or symlink). */\nexport class FilesystemSecurityError extends Error {\n readonly code = \"filesystem_security\" as const;\n constructor(message: string) {\n super(message);\n this.name = \"FilesystemSecurityError\";\n }\n}\n\n/** A write was attempted on a read-only backend. */\nexport class FilesystemReadOnlyError extends Error {\n readonly code = \"filesystem_readonly\" as const;\n constructor(message: string) {\n super(message);\n this.name = \"FilesystemReadOnlyError\";\n }\n}\n\n/** A read/stat targeted a path that does not exist. */\nexport class FileNotFoundError extends Error {\n readonly code = \"filesystem_not_found\" as const;\n constructor(public readonly path: string) {\n super(`File not found: ${path}`);\n this.name = \"FileNotFoundError\";\n }\n}\n\n/**\n * A filesystem I/O operation failed for a reason other than not-found /\n * read-only / stale / security (e.g. `ENOTDIR` — a path component is a file, or\n * `EACCES` / `ENOSPC`). Carries the original error as `cause` so no raw,\n * untyped Node `SystemError` ever escapes the backend (Unbreakable Rule 8).\n */\nexport class FilesystemError extends Error {\n readonly code = \"filesystem_io\" as const;\n constructor(\n public readonly path: string,\n cause: unknown,\n ) {\n super(\n `Filesystem operation failed on \"${path}\": ${(cause as { message?: string })?.message ?? cause}`,\n {\n cause,\n },\n );\n this.name = \"FilesystemError\";\n }\n}\n\n/**\n * SE32 — a write's `expectedMtime` did not match the file's current mtime: the\n * file changed since it was last read, so the write would silently clobber.\n */\nexport class StaleFileError extends Error {\n readonly code = \"filesystem_stale\" as const;\n constructor(\n public readonly path: string,\n public readonly expectedMtime: number,\n public readonly actualMtime: number,\n ) {\n super(\n `Stale write to \"${path}\": expected mtime ${expectedMtime}, found ${actualMtime} ` +\n `(file changed since last read — re-read before writing)`,\n );\n this.name = \"StaleFileError\";\n }\n}\n\n/**\n * Pluggable filesystem backend. Implement the four abstract methods; `exists()`\n * and the `readOnly`/`basePath` accessors derive on the base class.\n *\n * @public\n */\nexport abstract class FilesystemBackend {\n protected readonly _basePath: string;\n protected readonly _readOnly: boolean;\n\n constructor(config: FilesystemConfig = {}) {\n this._basePath = config.basePath ?? process.cwd();\n this._readOnly = config.readOnly ?? false;\n }\n\n /** Read a boundary-relative file as UTF-8. Throws {@link FileNotFoundError}. */\n abstract readFile(path: string): Promise<string>;\n\n /**\n * Write UTF-8 content to a boundary-relative path (creating parents). Returns\n * the new {@link FileStat}. Throws {@link FilesystemReadOnlyError} on a\n * read-only backend and {@link StaleFileError} when `opts.expectedMtime`\n * mismatches (SE32).\n */\n abstract writeFile(path: string, content: string, opts?: WriteFileOptions): Promise<FileStat>;\n\n /** Structured metadata for a path. Throws {@link FileNotFoundError}. */\n abstract stat(path: string): Promise<FileStat>;\n\n /** Directory entry names (not recursive). Throws {@link FileNotFoundError}. */\n abstract list(path: string): Promise<string[]>;\n\n /** Derived — true iff `stat(path)` resolves (absent ⇒ false). */\n async exists(path: string): Promise<boolean> {\n try {\n await this.stat(path);\n return true;\n } catch (err) {\n if (err instanceof FileNotFoundError) return false;\n throw err;\n }\n }\n\n /** Throw {@link FilesystemReadOnlyError} when the backend is read-only. */\n protected assertWritable(): void {\n if (this._readOnly) {\n throw new FilesystemReadOnlyError(`Filesystem is read-only (basePath: ${this._basePath})`);\n }\n }\n\n get readOnly(): boolean {\n return this._readOnly;\n }\n\n get basePath(): string {\n return this._basePath;\n }\n}\n\n/**\n * A backend OR a per-request resolver of one. A resolver runs at tool-execution\n * time (the request scope), so multi-tenant / multi-role agents get a distinct\n * root or permission set per request without a shared mutable backend.\n *\n * @public\n */\nexport type FilesystemProvider<Ctx = unknown> =\n | FilesystemBackend\n | ((ctx: Ctx) => FilesystemBackend | Promise<FilesystemBackend>);\n\n/** Resolve a {@link FilesystemProvider} to a concrete backend for `ctx`. */\nexport async function resolveFilesystem<Ctx>(\n provider: FilesystemProvider<Ctx>,\n ctx: Ctx,\n): Promise<FilesystemBackend> {\n return provider instanceof FilesystemBackend ? provider : provider(ctx);\n}\n","/**\n * LocalFilesystem — a {@link FilesystemBackend} over the local process\n * filesystem (`node:fs/promises`), boundary-enforced against `basePath`.\n *\n * **This is NOT an isolation boundary** (same OS, same user). Its safety\n * affordances are path-boundary enforcement (traversal + symlink escape,\n * reusing the core `internal/security/path-guard` primitives) and the optional\n * `readOnly` flag. For untrusted code, run it inside a container/VM sandbox.\n *\n * The check-then-use gap between `assertNoSymlinkEscape` and the subsequent\n * `fs` call is a known TOCTOU: a local attacker could atomically swap an\n * in-boundary symlink after the check. Closing it needs `O_NOFOLLOW`, which\n * Node's `fs/promises` does not expose — accepted for same-user local contexts.\n *\n * SE31 (a peer framework Workspaces comparison). See ADR 0011.\n *\n * @public\n */\n\nimport {\n readFile as fsReadFile,\n stat as fsStat,\n writeFile as fsWriteFile,\n mkdir,\n readdir,\n} from \"node:fs/promises\";\nimport { dirname } from \"node:path\";\n\nimport {\n assertNoSymlinkEscape,\n PathTraversalError,\n safePathJoin,\n} from \"../internal/security/path-guard.js\";\nimport {\n FileNotFoundError,\n type FileStat,\n FilesystemBackend,\n type FilesystemConfig,\n FilesystemError,\n FilesystemSecurityError,\n StaleFileError,\n type WriteFileOptions,\n} from \"./types.js\";\n\nexport class LocalFilesystem extends FilesystemBackend {\n constructor(config: FilesystemConfig = {}) {\n super(config);\n }\n\n async readFile(path: string): Promise<string> {\n const abs = this.resolve(path);\n try {\n return await fsReadFile(abs, \"utf-8\");\n } catch (err) {\n throw this.mapError(err, path);\n }\n }\n\n async writeFile(path: string, content: string, opts?: WriteFileOptions): Promise<FileStat> {\n // Security boundary FIRST (a traversal path on a read-only backend must\n // report the security error, not the read-only one — fail-clear).\n const abs = this.resolve(path);\n this.assertWritable();\n // SE32 — stale-write guard: if the caller passed the mtime it last read,\n // reject when the file changed underneath it (never a silent clobber).\n if (opts?.expectedMtime !== undefined) {\n await this.assertNotStale(path, abs, opts.expectedMtime);\n }\n try {\n await mkdir(dirname(abs), { recursive: true });\n await fsWriteFile(abs, content, \"utf-8\");\n } catch (err) {\n throw this.mapError(err, path);\n }\n return this.statAbs(abs, path);\n }\n\n async stat(path: string): Promise<FileStat> {\n const abs = this.resolve(path);\n return this.statAbs(abs, path);\n }\n\n async list(path: string): Promise<string[]> {\n const abs = this.resolve(path);\n try {\n return await readdir(abs);\n } catch (err) {\n throw this.mapError(err, path);\n }\n }\n\n private async statAbs(abs: string, relPath: string): Promise<FileStat> {\n try {\n const s = await fsStat(abs);\n return {\n size: s.size,\n mtimeMs: s.mtimeMs,\n isFile: s.isFile(),\n isDirectory: s.isDirectory(),\n };\n } catch (err) {\n throw this.mapError(err, relPath);\n }\n }\n\n /** SE32 — compare the on-disk mtime against the caller's expected value. */\n private async assertNotStale(relPath: string, abs: string, expectedMtime: number): Promise<void> {\n let current: number | undefined;\n try {\n current = (await fsStat(abs)).mtimeMs;\n } catch (err) {\n // A brand-new file (does not exist yet) cannot be stale — allow the write.\n if ((err as { code?: string }).code === \"ENOENT\") return;\n throw this.mapError(err, relPath);\n }\n if (current !== expectedMtime) {\n throw new StaleFileError(relPath, expectedMtime, current);\n }\n }\n\n /**\n * Resolve a boundary-relative path to an absolute one, rejecting lexical\n * traversal (`..`, absolute, NUL) and symlink escape — both reusing the core\n * path-guard primitives, remapped to {@link FilesystemSecurityError}.\n */\n private resolve(path: string): string {\n let abs: string;\n try {\n abs = safePathJoin(this._basePath, path);\n } catch (err) {\n if (err instanceof PathTraversalError) {\n throw new FilesystemSecurityError(`Path escapes basePath: ${path}`);\n }\n throw err;\n }\n try {\n assertNoSymlinkEscape(abs, this._basePath);\n } catch (err) {\n if (err instanceof PathTraversalError) {\n throw new FilesystemSecurityError(`Path escapes basePath via symlink: ${path}`);\n }\n throw err;\n }\n return abs;\n }\n\n private mapError(err: unknown, path: string): Error {\n if (\n err instanceof FilesystemSecurityError ||\n err instanceof FilesystemError ||\n err instanceof FileNotFoundError ||\n err instanceof StaleFileError\n ) {\n return err;\n }\n if ((err as { code?: string }).code === \"ENOENT\") return new FileNotFoundError(path);\n // ENOTDIR (a path component is a file), EACCES, ENOSPC, … — never leak a\n // raw untyped Node SystemError (Rule 8); wrap with the original as cause.\n return new FilesystemError(path, err);\n }\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../../src/filesystem/types.ts","../../src/filesystem/local-filesystem.ts"],"names":["fsReadFile","fsWriteFile","fsStat"],"mappings":";;;;;;;;AA6CO,IAAM,uBAAA,GAAN,cAAsC,KAAA,CAAM;AAAA,EACxC,IAAA,GAAO,qBAAA;AAAA,EAChB,YAAY,OAAA,EAAiB;AAC3B,IAAA,KAAA,CAAM,OAAO,CAAA;AACb,IAAA,IAAA,CAAK,IAAA,GAAO,yBAAA;AAAA,EACd;AACF;AAGO,IAAM,uBAAA,GAAN,cAAsC,KAAA,CAAM;AAAA,EACxC,IAAA,GAAO,qBAAA;AAAA,EAChB,YAAY,OAAA,EAAiB;AAC3B,IAAA,KAAA,CAAM,OAAO,CAAA;AACb,IAAA,IAAA,CAAK,IAAA,GAAO,yBAAA;AAAA,EACd;AACF;AAGO,IAAM,iBAAA,GAAN,cAAgC,KAAA,CAAM;AAAA,EAE3C,YAA4B,IAAA,EAAc;AACxC,IAAA,KAAA,CAAM,CAAA,gBAAA,EAAmB,IAAI,CAAA,CAAE,CAAA;AADL,IAAA,IAAA,CAAA,IAAA,GAAA,IAAA;AAE1B,IAAA,IAAA,CAAK,IAAA,GAAO,mBAAA;AAAA,EACd;AAAA,EAH4B,IAAA;AAAA,EADnB,IAAA,GAAO,sBAAA;AAKlB;AAQO,IAAM,eAAA,GAAN,cAA8B,KAAA,CAAM;AAAA,EAEzC,WAAA,CACkB,MAChB,KAAA,EACA;AACA,IAAA,KAAA;AAAA,MACE,CAAA,gCAAA,EAAmC,IAAI,CAAA,GAAA,EAAO,KAAA,EAAgC,WAAW,KAAK,CAAA,CAAA;AAAA,MAC9F;AAAA,QACE;AAAA;AACF,KACF;AARgB,IAAA,IAAA,CAAA,IAAA,GAAA,IAAA;AAShB,IAAA,IAAA,CAAK,IAAA,GAAO,iBAAA;AAAA,EACd;AAAA,EAVkB,IAAA;AAAA,EAFT,IAAA,GAAO,eAAA;AAalB;AAMO,IAAM,cAAA,GAAN,cAA6B,KAAA,CAAM;AAAA,EAExC,WAAA,CACkB,IAAA,EACA,aAAA,EACA,WAAA,EAChB;AACA,IAAA,KAAA;AAAA,MACE,CAAA,gBAAA,EAAmB,IAAI,CAAA,kBAAA,EAAqB,aAAa,WAAW,WAAW,CAAA,6DAAA;AAAA,KAEjF;AAPgB,IAAA,IAAA,CAAA,IAAA,GAAA,IAAA;AACA,IAAA,IAAA,CAAA,aAAA,GAAA,aAAA;AACA,IAAA,IAAA,CAAA,WAAA,GAAA,WAAA;AAMhB,IAAA,IAAA,CAAK,IAAA,GAAO,gBAAA;AAAA,EACd;AAAA,EATkB,IAAA;AAAA,EACA,aAAA;AAAA,EACA,WAAA;AAAA,EAJT,IAAA,GAAO,kBAAA;AAYlB;AAQO,IAAe,oBAAf,MAAiC;AAAA,EACnB,SAAA;AAAA,EACA,SAAA;AAAA,EAEnB,WAAA,CAAY,MAAA,GAA2B,EAAC,EAAG;AACzC,IAAA,IAAA,CAAK,SAAA,GAAY,MAAA,CAAO,QAAA,IAAY,OAAA,CAAQ,GAAA,EAAI;AAChD,IAAA,IAAA,CAAK,SAAA,GAAY,OAAO,QAAA,IAAY,KAAA;AAAA,EACtC;AAAA;AAAA,EAoBA,MAAM,OAAO,IAAA,EAAgC;AAC3C,IAAA,IAAI;AACF,MAAA,MAAM,IAAA,CAAK,KAAK,IAAI,CAAA;AACpB,MAAA,OAAO,IAAA;AAAA,IACT,SAAS,GAAA,EAAK;AACZ,MAAA,IAAI,GAAA,YAAe,mBAAmB,OAAO,KAAA;AAC7C,MAAA,MAAM,GAAA;AAAA,IACR;AAAA,EACF;AAAA;AAAA,EAGU,cAAA,GAAuB;AAC/B,IAAA,IAAI,KAAK,SAAA,EAAW;AAClB,MAAA,MAAM,IAAI,uBAAA,CAAwB,CAAA,mCAAA,EAAsC,IAAA,CAAK,SAAS,CAAA,CAAA,CAAG,CAAA;AAAA,IAC3F;AAAA,EACF;AAAA,EAEA,IAAI,QAAA,GAAoB;AACtB,IAAA,OAAO,IAAA,CAAK,SAAA;AAAA,EACd;AAAA,EAEA,IAAI,QAAA,GAAmB;AACrB,IAAA,OAAO,IAAA,CAAK,SAAA;AAAA,EACd;AACF;AAcA,eAAsB,iBAAA,CACpB,UACA,GAAA,EAC4B;AAC5B,EAAA,OAAO,QAAA,YAAoB,iBAAA,GAAoB,QAAA,GAAW,QAAA,CAAS,GAAG,CAAA;AACxE;;;AChJO,IAAM,eAAA,GAAN,cAA8B,iBAAA,CAAkB;AAAA,EACrD,WAAA,CAAY,MAAA,GAA2B,EAAC,EAAG;AACzC,IAAA,KAAA,CAAM,MAAM,CAAA;AAAA,EACd;AAAA,EAEA,MAAM,SAAS,IAAA,EAA+B;AAC5C,IAAA,MAAM,GAAA,GAAM,IAAA,CAAK,OAAA,CAAQ,IAAI,CAAA;AAC7B,IAAA,IAAI;AACF,MAAA,OAAO,MAAMA,QAAA,CAAW,GAAA,EAAK,OAAO,CAAA;AAAA,IACtC,SAAS,GAAA,EAAK;AACZ,MAAA,MAAM,IAAA,CAAK,QAAA,CAAS,GAAA,EAAK,IAAI,CAAA;AAAA,IAC/B;AAAA,EACF;AAAA,EAEA,MAAM,SAAA,CAAU,IAAA,EAAc,OAAA,EAAiB,IAAA,EAA4C;AAGzF,IAAA,MAAM,GAAA,GAAM,IAAA,CAAK,OAAA,CAAQ,IAAI,CAAA;AAC7B,IAAA,IAAA,CAAK,cAAA,EAAe;AAGpB,IAAA,IAAI,IAAA,EAAM,kBAAkB,MAAA,EAAW;AACrC,MAAA,MAAM,IAAA,CAAK,cAAA,CAAe,IAAA,EAAM,GAAA,EAAK,KAAK,aAAa,CAAA;AAAA,IACzD;AACA,IAAA,IAAI;AACF,MAAA,MAAM,MAAM,OAAA,CAAQ,GAAG,GAAG,EAAE,SAAA,EAAW,MAAM,CAAA;AAC7C,MAAA,MAAMC,SAAA,CAAY,GAAA,EAAK,OAAA,EAAS,OAAO,CAAA;AAAA,IACzC,SAAS,GAAA,EAAK;AACZ,MAAA,MAAM,IAAA,CAAK,QAAA,CAAS,GAAA,EAAK,IAAI,CAAA;AAAA,IAC/B;AACA,IAAA,OAAO,IAAA,CAAK,OAAA,CAAQ,GAAA,EAAK,IAAI,CAAA;AAAA,EAC/B;AAAA,EAEA,MAAM,KAAK,IAAA,EAAiC;AAC1C,IAAA,MAAM,GAAA,GAAM,IAAA,CAAK,OAAA,CAAQ,IAAI,CAAA;AAC7B,IAAA,OAAO,IAAA,CAAK,OAAA,CAAQ,GAAA,EAAK,IAAI,CAAA;AAAA,EAC/B;AAAA,EAEA,MAAM,KAAK,IAAA,EAAiC;AAC1C,IAAA,MAAM,GAAA,GAAM,IAAA,CAAK,OAAA,CAAQ,IAAI,CAAA;AAC7B,IAAA,IAAI;AACF,MAAA,OAAO,MAAM,QAAQ,GAAG,CAAA;AAAA,IAC1B,SAAS,GAAA,EAAK;AACZ,MAAA,MAAM,IAAA,CAAK,QAAA,CAAS,GAAA,EAAK,IAAI,CAAA;AAAA,IAC/B;AAAA,EACF;AAAA,EAEA,MAAc,OAAA,CAAQ,GAAA,EAAa,OAAA,EAAoC;AACrE,IAAA,IAAI;AACF,MAAA,MAAM,CAAA,GAAI,MAAMC,IAAA,CAAO,GAAG,CAAA;AAC1B,MAAA,OAAO;AAAA,QACL,MAAM,CAAA,CAAE,IAAA;AAAA,QACR,SAAS,CAAA,CAAE,OAAA;AAAA,QACX,MAAA,EAAQ,EAAE,MAAA,EAAO;AAAA,QACjB,WAAA,EAAa,EAAE,WAAA;AAAY,OAC7B;AAAA,IACF,SAAS,GAAA,EAAK;AACZ,MAAA,MAAM,IAAA,CAAK,QAAA,CAAS,GAAA,EAAK,OAAO,CAAA;AAAA,IAClC;AAAA,EACF;AAAA;AAAA,EAGA,MAAc,cAAA,CAAe,OAAA,EAAiB,GAAA,EAAa,aAAA,EAAsC;AAC/F,IAAA,IAAI,OAAA;AACJ,IAAA,IAAI;AACF,MAAA,OAAA,GAAA,CAAW,MAAMA,IAAA,CAAO,GAAG,CAAA,EAAG,OAAA;AAAA,IAChC,SAAS,GAAA,EAAK;AAEZ,MAAA,IAAK,GAAA,CAA0B,SAAS,QAAA,EAAU;AAClD,MAAA,MAAM,IAAA,CAAK,QAAA,CAAS,GAAA,EAAK,OAAO,CAAA;AAAA,IAClC;AACA,IAAA,IAAI,YAAY,aAAA,EAAe;AAC7B,MAAA,MAAM,IAAI,cAAA,CAAe,OAAA,EAAS,aAAA,EAAe,OAAO,CAAA;AAAA,IAC1D;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOQ,QAAQ,IAAA,EAAsB;AACpC,IAAA,IAAI,GAAA;AACJ,IAAA,IAAI;AACF,MAAA,GAAA,GAAM,YAAA,CAAa,IAAA,CAAK,SAAA,EAAW,IAAI,CAAA;AAAA,IACzC,SAAS,GAAA,EAAK;AACZ,MAAA,IAAI,eAAe,kBAAA,EAAoB;AACrC,QAAA,MAAM,IAAI,uBAAA,CAAwB,CAAA,uBAAA,EAA0B,IAAI,CAAA,CAAE,CAAA;AAAA,MACpE;AACA,MAAA,MAAM,GAAA;AAAA,IACR;AACA,IAAA,IAAI;AACF,MAAA,qBAAA,CAAsB,GAAA,EAAK,KAAK,SAAS,CAAA;AAAA,IAC3C,SAAS,GAAA,EAAK;AACZ,MAAA,IAAI,eAAe,kBAAA,EAAoB;AACrC,QAAA,MAAM,IAAI,uBAAA,CAAwB,CAAA,mCAAA,EAAsC,IAAI,CAAA,CAAE,CAAA;AAAA,MAChF;AACA,MAAA,MAAM,GAAA;AAAA,IACR;AACA,IAAA,OAAO,GAAA;AAAA,EACT;AAAA,EAEQ,QAAA,CAAS,KAAc,IAAA,EAAqB;AAClD,IAAA,IACE,eAAe,uBAAA,IACf,GAAA,YAAe,mBACf,GAAA,YAAe,iBAAA,IACf,eAAe,cAAA,EACf;AACA,MAAA,OAAO,GAAA;AAAA,IACT;AACA,IAAA,IAAK,IAA0B,IAAA,KAAS,QAAA,EAAU,OAAO,IAAI,kBAAkB,IAAI,CAAA;AAGnF,IAAA,OAAO,IAAI,eAAA,CAAgB,IAAA,EAAM,GAAG,CAAA;AAAA,EACtC;AACF","file":"index.js","sourcesContent":["/**\n * Filesystem backend protocol — a pluggable file *storage* provider for agent\n * tools, the storage-side twin of {@link SandboxBackend} (execution-side).\n *\n * SE31 (a peer framework Workspaces comparison). Mirrors `SandboxBackend`'s shape: a small\n * set of abstract methods (`readFile` / `writeFile` / `stat` / `list`) with\n * `exists()` derived on the base class, a boundary `basePath`, a `readOnly`\n * flag, and typed errors. Unlike `SandboxBackend` (whose file ops shell out via\n * `execute`, requiring command execution and giving NO structured `stat`), a\n * `FilesystemBackend` serves a *filesystem-only* workspace with no sandbox and\n * exposes a real `stat().mtimeMs` — the primitive SE32's read-before-write\n * safety compares against. See ADR 0011.\n *\n * New backends (S3, GCS, in-memory) implement the four abstract methods; higher\n * level helpers derive on the base. This is the backend *seam* — it does NOT\n * ship agent-facing tools nor a bundled workspace (bring-your-own-tools stands).\n *\n * @public\n */\n\n/** Structured file metadata. `mtimeMs` is the read-before-write oracle (SE32). */\nexport interface FileStat {\n readonly size: number;\n readonly mtimeMs: number;\n readonly isFile: boolean;\n readonly isDirectory: boolean;\n}\n\n/** Options a write may carry. SE32 adds `expectedMtime` (stale-write guard). */\nexport interface WriteFileOptions {\n /**\n * SE32 — when set, the write fails with {@link StaleFileError} if the file's\n * current `mtimeMs` differs (someone changed it since it was last read).\n */\n readonly expectedMtime?: number;\n}\n\nexport interface FilesystemConfig {\n /** Boundary root. Every path is resolved within it; escapes are rejected. */\n readonly basePath?: string;\n /** When true, every write throws {@link FilesystemReadOnlyError}. */\n readonly readOnly?: boolean;\n}\n\n/** A path escaped the backend's `basePath` (traversal or symlink). */\nexport class FilesystemSecurityError extends Error {\n readonly code = \"filesystem_security\" as const;\n constructor(message: string) {\n super(message);\n this.name = \"FilesystemSecurityError\";\n }\n}\n\n/** A write was attempted on a read-only backend. */\nexport class FilesystemReadOnlyError extends Error {\n readonly code = \"filesystem_readonly\" as const;\n constructor(message: string) {\n super(message);\n this.name = \"FilesystemReadOnlyError\";\n }\n}\n\n/** A read/stat targeted a path that does not exist. */\nexport class FileNotFoundError extends Error {\n readonly code = \"filesystem_not_found\" as const;\n constructor(public readonly path: string) {\n super(`File not found: ${path}`);\n this.name = \"FileNotFoundError\";\n }\n}\n\n/**\n * A filesystem I/O operation failed for a reason other than not-found /\n * read-only / stale / security (e.g. `ENOTDIR` — a path component is a file, or\n * `EACCES` / `ENOSPC`). Carries the original error as `cause` so no raw,\n * untyped Node `SystemError` ever escapes the backend (Unbreakable Rule 8).\n */\nexport class FilesystemError extends Error {\n readonly code = \"filesystem_io\" as const;\n constructor(\n public readonly path: string,\n cause: unknown,\n ) {\n super(\n `Filesystem operation failed on \"${path}\": ${(cause as { message?: string })?.message ?? cause}`,\n {\n cause,\n },\n );\n this.name = \"FilesystemError\";\n }\n}\n\n/**\n * SE32 — a write's `expectedMtime` did not match the file's current mtime: the\n * file changed since it was last read, so the write would silently clobber.\n */\nexport class StaleFileError extends Error {\n readonly code = \"filesystem_stale\" as const;\n constructor(\n public readonly path: string,\n public readonly expectedMtime: number,\n public readonly actualMtime: number,\n ) {\n super(\n `Stale write to \"${path}\": expected mtime ${expectedMtime}, found ${actualMtime} ` +\n `(file changed since last read — re-read before writing)`,\n );\n this.name = \"StaleFileError\";\n }\n}\n\n/**\n * Pluggable filesystem backend. Implement the four abstract methods; `exists()`\n * and the `readOnly`/`basePath` accessors derive on the base class.\n *\n * @public\n */\nexport abstract class FilesystemBackend {\n protected readonly _basePath: string;\n protected readonly _readOnly: boolean;\n\n constructor(config: FilesystemConfig = {}) {\n this._basePath = config.basePath ?? process.cwd();\n this._readOnly = config.readOnly ?? false;\n }\n\n /** Read a boundary-relative file as UTF-8. Throws {@link FileNotFoundError}. */\n abstract readFile(path: string): Promise<string>;\n\n /**\n * Write UTF-8 content to a boundary-relative path (creating parents). Returns\n * the new {@link FileStat}. Throws {@link FilesystemReadOnlyError} on a\n * read-only backend and {@link StaleFileError} when `opts.expectedMtime`\n * mismatches (SE32).\n */\n abstract writeFile(path: string, content: string, opts?: WriteFileOptions): Promise<FileStat>;\n\n /** Structured metadata for a path. Throws {@link FileNotFoundError}. */\n abstract stat(path: string): Promise<FileStat>;\n\n /** Directory entry names (not recursive). Throws {@link FileNotFoundError}. */\n abstract list(path: string): Promise<string[]>;\n\n /** Derived — true iff `stat(path)` resolves (absent ⇒ false). */\n async exists(path: string): Promise<boolean> {\n try {\n await this.stat(path);\n return true;\n } catch (err) {\n if (err instanceof FileNotFoundError) return false;\n throw err;\n }\n }\n\n /** Throw {@link FilesystemReadOnlyError} when the backend is read-only. */\n protected assertWritable(): void {\n if (this._readOnly) {\n throw new FilesystemReadOnlyError(`Filesystem is read-only (basePath: ${this._basePath})`);\n }\n }\n\n get readOnly(): boolean {\n return this._readOnly;\n }\n\n get basePath(): string {\n return this._basePath;\n }\n}\n\n/**\n * A backend OR a per-request resolver of one. A resolver runs at tool-execution\n * time (the request scope), so multi-tenant / multi-role agents get a distinct\n * root or permission set per request without a shared mutable backend.\n *\n * @public\n */\nexport type FilesystemProvider<Ctx = unknown> =\n | FilesystemBackend\n | ((ctx: Ctx) => FilesystemBackend | Promise<FilesystemBackend>);\n\n/** Resolve a {@link FilesystemProvider} to a concrete backend for `ctx`. */\nexport async function resolveFilesystem<Ctx>(\n provider: FilesystemProvider<Ctx>,\n ctx: Ctx,\n): Promise<FilesystemBackend> {\n return provider instanceof FilesystemBackend ? provider : provider(ctx);\n}\n","/**\n * LocalFilesystem — a {@link FilesystemBackend} over the local process\n * filesystem (`node:fs/promises`), boundary-enforced against `basePath`.\n *\n * **This is NOT an isolation boundary** (same OS, same user). Its safety\n * affordances are path-boundary enforcement (traversal + symlink escape,\n * reusing the core `internal/security/path-guard` primitives) and the optional\n * `readOnly` flag. For untrusted code, run it inside a container/VM sandbox.\n *\n * The check-then-use gap between `assertNoSymlinkEscape` and the subsequent\n * `fs` call is a known TOCTOU: a local attacker could atomically swap an\n * in-boundary symlink after the check. Closing it needs `O_NOFOLLOW`, which\n * Node's `fs/promises` does not expose — accepted for same-user local contexts.\n *\n * SE31 (a peer framework Workspaces comparison). See ADR 0011.\n *\n * @public\n */\n\nimport {\n readFile as fsReadFile,\n stat as fsStat,\n writeFile as fsWriteFile,\n mkdir,\n readdir,\n} from \"node:fs/promises\";\nimport { dirname } from \"node:path\";\n\nimport {\n assertNoSymlinkEscape,\n PathTraversalError,\n safePathJoin,\n} from \"../internal/security/path-guard.js\";\nimport {\n FileNotFoundError,\n type FileStat,\n FilesystemBackend,\n type FilesystemConfig,\n FilesystemError,\n FilesystemSecurityError,\n StaleFileError,\n type WriteFileOptions,\n} from \"./types.js\";\n\nexport class LocalFilesystem extends FilesystemBackend {\n constructor(config: FilesystemConfig = {}) {\n super(config);\n }\n\n async readFile(path: string): Promise<string> {\n const abs = this.resolve(path);\n try {\n return await fsReadFile(abs, \"utf-8\");\n } catch (err) {\n throw this.mapError(err, path);\n }\n }\n\n async writeFile(path: string, content: string, opts?: WriteFileOptions): Promise<FileStat> {\n // Security boundary FIRST (a traversal path on a read-only backend must\n // report the security error, not the read-only one — fail-clear).\n const abs = this.resolve(path);\n this.assertWritable();\n // SE32 — stale-write guard: if the caller passed the mtime it last read,\n // reject when the file changed underneath it (never a silent clobber).\n if (opts?.expectedMtime !== undefined) {\n await this.assertNotStale(path, abs, opts.expectedMtime);\n }\n try {\n await mkdir(dirname(abs), { recursive: true });\n await fsWriteFile(abs, content, \"utf-8\");\n } catch (err) {\n throw this.mapError(err, path);\n }\n return this.statAbs(abs, path);\n }\n\n async stat(path: string): Promise<FileStat> {\n const abs = this.resolve(path);\n return this.statAbs(abs, path);\n }\n\n async list(path: string): Promise<string[]> {\n const abs = this.resolve(path);\n try {\n return await readdir(abs);\n } catch (err) {\n throw this.mapError(err, path);\n }\n }\n\n private async statAbs(abs: string, relPath: string): Promise<FileStat> {\n try {\n const s = await fsStat(abs);\n return {\n size: s.size,\n mtimeMs: s.mtimeMs,\n isFile: s.isFile(),\n isDirectory: s.isDirectory(),\n };\n } catch (err) {\n throw this.mapError(err, relPath);\n }\n }\n\n /** SE32 — compare the on-disk mtime against the caller's expected value. */\n private async assertNotStale(relPath: string, abs: string, expectedMtime: number): Promise<void> {\n let current: number | undefined;\n try {\n current = (await fsStat(abs)).mtimeMs;\n } catch (err) {\n // A brand-new file (does not exist yet) cannot be stale — allow the write.\n if ((err as { code?: string }).code === \"ENOENT\") return;\n throw this.mapError(err, relPath);\n }\n if (current !== expectedMtime) {\n throw new StaleFileError(relPath, expectedMtime, current);\n }\n }\n\n /**\n * Resolve a boundary-relative path to an absolute one, rejecting lexical\n * traversal (`..`, absolute, NUL) and symlink escape — both reusing the core\n * path-guard primitives, remapped to {@link FilesystemSecurityError}.\n */\n private resolve(path: string): string {\n let abs: string;\n try {\n abs = safePathJoin(this._basePath, path);\n } catch (err) {\n if (err instanceof PathTraversalError) {\n throw new FilesystemSecurityError(`Path escapes basePath: ${path}`);\n }\n throw err;\n }\n try {\n assertNoSymlinkEscape(abs, this._basePath);\n } catch (err) {\n if (err instanceof PathTraversalError) {\n throw new FilesystemSecurityError(`Path escapes basePath via symlink: ${path}`);\n }\n throw err;\n }\n return abs;\n }\n\n private mapError(err: unknown, path: string): Error {\n if (\n err instanceof FilesystemSecurityError ||\n err instanceof FilesystemError ||\n err instanceof FileNotFoundError ||\n err instanceof StaleFileError\n ) {\n return err;\n }\n if ((err as { code?: string }).code === \"ENOENT\") return new FileNotFoundError(path);\n // ENOTDIR (a path component is a file), EACCES, ENOSPC, … — never leak a\n // raw untyped Node SystemError (Rule 8); wrap with the original as cause.\n return new FilesystemError(path, err);\n }\n}\n"]}
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
3
|
+
var chunkRWMNTFHZ_cjs = require('./chunk-RWMNTFHZ.cjs');
|
|
4
4
|
require('./chunk-2RW7K6FN.cjs');
|
|
5
5
|
require('./chunk-MUUQ2WFJ.cjs');
|
|
6
6
|
require('./chunk-BV42CCRP.cjs');
|
|
7
7
|
require('./chunk-YLQQX5W2.cjs');
|
|
8
8
|
require('./chunk-NETYW4V3.cjs');
|
|
9
|
-
require('./chunk-
|
|
9
|
+
require('./chunk-XABN5HY6.cjs');
|
|
10
|
+
require('./chunk-VKJ7V7EB.cjs');
|
|
10
11
|
require('./chunk-YULF6FPB.cjs');
|
|
11
12
|
require('./chunk-ZHPET3LZ.cjs');
|
|
12
13
|
|
|
@@ -14,7 +15,7 @@ require('./chunk-ZHPET3LZ.cjs');
|
|
|
14
15
|
|
|
15
16
|
Object.defineProperty(exports, "IndexManager", {
|
|
16
17
|
enumerable: true,
|
|
17
|
-
get: function () { return
|
|
18
|
+
get: function () { return chunkRWMNTFHZ_cjs.IndexManager; }
|
|
18
19
|
});
|
|
19
|
-
//# sourceMappingURL=index-manager-
|
|
20
|
-
//# sourceMappingURL=index-manager-
|
|
20
|
+
//# sourceMappingURL=index-manager-34ELCOAP.cjs.map
|
|
21
|
+
//# sourceMappingURL=index-manager-34ELCOAP.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":[],"names":[],"mappings":"","file":"index-manager-
|
|
1
|
+
{"version":3,"sources":[],"names":[],"mappings":"","file":"index-manager-34ELCOAP.cjs"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export { IndexManager } from './chunk-E54KDYOE.js';
|
|
2
|
+
import './chunk-OXNYIMZZ.js';
|
|
3
|
+
import './chunk-FD2UT76F.js';
|
|
4
|
+
import './chunk-2WB6EIYW.js';
|
|
5
|
+
import './chunk-2XLKLVVR.js';
|
|
6
|
+
import './chunk-VQFSEKU5.js';
|
|
7
|
+
import './chunk-JGYYNDAZ.js';
|
|
8
|
+
import './chunk-RIAM53CP.js';
|
|
9
|
+
import './chunk-MRKSSN36.js';
|
|
10
|
+
import './chunk-PBML2FHN.js';
|
|
11
|
+
//# sourceMappingURL=index-manager-OMJVYS2U.js.map
|
|
12
|
+
//# sourceMappingURL=index-manager-OMJVYS2U.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":[],"names":[],"mappings":"","file":"index-manager-
|
|
1
|
+
{"version":3,"sources":[],"names":[],"mappings":"","file":"index-manager-OMJVYS2U.js"}
|
package/dist/index.cjs
CHANGED
|
@@ -5,12 +5,12 @@ var chunkUJMEWGO6_cjs = require('./chunk-UJMEWGO6.cjs');
|
|
|
5
5
|
var chunk57KX5WTP_cjs = require('./chunk-57KX5WTP.cjs');
|
|
6
6
|
var chunkGC44RATP_cjs = require('./chunk-GC44RATP.cjs');
|
|
7
7
|
require('./chunk-WIGJGFH4.cjs');
|
|
8
|
-
var
|
|
8
|
+
var chunk72HEBGWN_cjs = require('./chunk-72HEBGWN.cjs');
|
|
9
9
|
require('./chunk-RBQYHEZD.cjs');
|
|
10
10
|
require('./chunk-PNVDQL5Y.cjs');
|
|
11
|
-
var
|
|
12
|
-
var
|
|
13
|
-
require('./chunk-
|
|
11
|
+
var chunkWUUSAMFC_cjs = require('./chunk-WUUSAMFC.cjs');
|
|
12
|
+
var chunkF7OBYH2X_cjs = require('./chunk-F7OBYH2X.cjs');
|
|
13
|
+
require('./chunk-UQHIEUDY.cjs');
|
|
14
14
|
require('./chunk-BV2MWEMV.cjs');
|
|
15
15
|
var chunkKCQUYQ3V_cjs = require('./chunk-KCQUYQ3V.cjs');
|
|
16
16
|
require('./chunk-BUUUWQMB.cjs');
|
|
@@ -19,10 +19,10 @@ var chunkQFFNMJAS_cjs = require('./chunk-QFFNMJAS.cjs');
|
|
|
19
19
|
require('./chunk-4JBHSLQO.cjs');
|
|
20
20
|
require('./chunk-HLNLYLNN.cjs');
|
|
21
21
|
require('./chunk-FZ4YMZA3.cjs');
|
|
22
|
-
var
|
|
22
|
+
var chunkRWMNTFHZ_cjs = require('./chunk-RWMNTFHZ.cjs');
|
|
23
23
|
require('./chunk-HECR7KF5.cjs');
|
|
24
24
|
require('./chunk-BBZYXVLZ.cjs');
|
|
25
|
-
require('./chunk-
|
|
25
|
+
require('./chunk-OKLYRPKL.cjs');
|
|
26
26
|
require('./chunk-6X2HUT4A.cjs');
|
|
27
27
|
require('./chunk-7PESI6YD.cjs');
|
|
28
28
|
require('./chunk-S4Q5OMIK.cjs');
|
|
@@ -49,13 +49,14 @@ var chunkVYHJZVL5_cjs = require('./chunk-VYHJZVL5.cjs');
|
|
|
49
49
|
var chunkGLEKLAUW_cjs = require('./chunk-GLEKLAUW.cjs');
|
|
50
50
|
require('./chunk-4JRRFRV4.cjs');
|
|
51
51
|
require('./chunk-C6Y6CWYD.cjs');
|
|
52
|
-
require('./chunk-
|
|
53
|
-
require('./chunk-
|
|
52
|
+
require('./chunk-3G6ZDZ6L.cjs');
|
|
53
|
+
require('./chunk-XABN5HY6.cjs');
|
|
54
|
+
require('./chunk-VKJ7V7EB.cjs');
|
|
54
55
|
require('./chunk-BRHRQOJA.cjs');
|
|
55
56
|
var chunkYULF6FPB_cjs = require('./chunk-YULF6FPB.cjs');
|
|
56
57
|
var chunkZHPET3LZ_cjs = require('./chunk-ZHPET3LZ.cjs');
|
|
57
|
-
var zod = require('zod');
|
|
58
58
|
var crypto = require('crypto');
|
|
59
|
+
var zod = require('zod');
|
|
59
60
|
var promises = require('fs/promises');
|
|
60
61
|
var path = require('path');
|
|
61
62
|
var fs = require('fs');
|
|
@@ -63,8 +64,8 @@ var fs = require('fs');
|
|
|
63
64
|
// src/agent-factory.ts
|
|
64
65
|
function createAgentFactory(common) {
|
|
65
66
|
return {
|
|
66
|
-
forSession: (agentId, overrides) =>
|
|
67
|
-
getOrCreate: (agentId, overrides) =>
|
|
67
|
+
forSession: (agentId, overrides) => chunkF7OBYH2X_cjs.Agent.create(mergeAgentOptions(common, overrides, agentId)),
|
|
68
|
+
getOrCreate: (agentId, overrides) => chunkF7OBYH2X_cjs.Agent.getOrCreate(agentId, mergeAgentOptions(common, overrides, agentId))
|
|
68
69
|
};
|
|
69
70
|
}
|
|
70
71
|
function mergeAgentOptions(common, overrides, agentId) {
|
|
@@ -103,6 +104,39 @@ var AgentFactory = class {
|
|
|
103
104
|
}
|
|
104
105
|
};
|
|
105
106
|
|
|
107
|
+
// src/approval-policy.ts
|
|
108
|
+
var BY_MODE = {
|
|
109
|
+
ask: { outcome: "ask", reason: "mode-ask" },
|
|
110
|
+
"never-ask": { outcome: "allow", reason: "mode-never-ask" },
|
|
111
|
+
"refuse-all": { outcome: "deny", reason: "mode-refuse-all" }
|
|
112
|
+
};
|
|
113
|
+
function decideApproval(input) {
|
|
114
|
+
const { tool } = input;
|
|
115
|
+
if ((input.denied ?? []).includes(tool)) {
|
|
116
|
+
return { outcome: "deny", reason: "explicitly-denied", tool };
|
|
117
|
+
}
|
|
118
|
+
if ((input.allowed ?? []).includes(tool)) {
|
|
119
|
+
return { outcome: "allow", reason: "explicitly-allowed", tool };
|
|
120
|
+
}
|
|
121
|
+
const fromMode = BY_MODE[input.mode];
|
|
122
|
+
return { outcome: fromMode.outcome, reason: fromMode.reason, tool };
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// src/blast-radius.ts
|
|
126
|
+
function evaluateBlastRadius(input) {
|
|
127
|
+
const { scope, reversible } = input.action;
|
|
128
|
+
if (scope.length === 0) {
|
|
129
|
+
return { outcome: "refuse", reason: "scope-undeclared", scope };
|
|
130
|
+
}
|
|
131
|
+
if (!input.granted.includes(scope)) {
|
|
132
|
+
return { outcome: "refuse", reason: "scope-not-granted", scope };
|
|
133
|
+
}
|
|
134
|
+
if (!reversible && !(input.irreversibleAllowed ?? []).includes(scope)) {
|
|
135
|
+
return { outcome: "require-approval", reason: "irreversible", scope };
|
|
136
|
+
}
|
|
137
|
+
return { outcome: "allow", reason: "within-granted-scope", scope };
|
|
138
|
+
}
|
|
139
|
+
|
|
106
140
|
// src/internal/budget/calendar-window.ts
|
|
107
141
|
function startOfDayUtc(now = /* @__PURE__ */ new Date()) {
|
|
108
142
|
return new Date(Date.UTC(now.getUTCFullYear(), now.getUTCMonth(), now.getUTCDate()));
|
|
@@ -568,6 +602,18 @@ var Skill = class {
|
|
|
568
602
|
return createSkill(spec);
|
|
569
603
|
}
|
|
570
604
|
};
|
|
605
|
+
function describeCredential(input) {
|
|
606
|
+
const secret = (input.value ?? "").trim();
|
|
607
|
+
if (secret.length === 0) {
|
|
608
|
+
return { provider: input.provider, present: false, source: input.source };
|
|
609
|
+
}
|
|
610
|
+
return {
|
|
611
|
+
provider: input.provider,
|
|
612
|
+
present: true,
|
|
613
|
+
source: input.source,
|
|
614
|
+
fingerprint: crypto.createHash("sha256").update(secret).digest("hex").slice(0, 8)
|
|
615
|
+
};
|
|
616
|
+
}
|
|
571
617
|
|
|
572
618
|
// src/define-provider.ts
|
|
573
619
|
function defineProvider(profile, opts) {
|
|
@@ -967,7 +1013,7 @@ function foldLayers(entries, accumulatingKeys = []) {
|
|
|
967
1013
|
return combined;
|
|
968
1014
|
}
|
|
969
1015
|
function diaryPath(cwd) {
|
|
970
|
-
return path.join(
|
|
1016
|
+
return path.join(chunkRWMNTFHZ_cjs.memoryDir(cwd), "dream-diary.md");
|
|
971
1017
|
}
|
|
972
1018
|
function renderDiaryEntry(entry) {
|
|
973
1019
|
const stamp = new Date(entry.timestampMs).toISOString();
|
|
@@ -1114,7 +1160,7 @@ async function runInner(options) {
|
|
|
1114
1160
|
const now = options.now ?? Date.now;
|
|
1115
1161
|
const timestampMs = now();
|
|
1116
1162
|
try {
|
|
1117
|
-
const facts = await
|
|
1163
|
+
const facts = await chunkRWMNTFHZ_cjs.readFactsFromMarkdown(options.cwd);
|
|
1118
1164
|
if (facts.length === 0) {
|
|
1119
1165
|
return emptyResult("skipped");
|
|
1120
1166
|
}
|
|
@@ -1148,7 +1194,7 @@ async function runInner(options) {
|
|
|
1148
1194
|
}
|
|
1149
1195
|
async function writeConsolidatedNotes(cwd, clusters, timestampMs) {
|
|
1150
1196
|
if (clusters.length === 0) return 0;
|
|
1151
|
-
const notesDir = path.join(
|
|
1197
|
+
const notesDir = path.join(chunkRWMNTFHZ_cjs.memoryDir(cwd), "notes");
|
|
1152
1198
|
await promises.mkdir(notesDir, { recursive: true });
|
|
1153
1199
|
const isoSlug = new Date(timestampMs).toISOString().replace(/[^\dT]/g, "-");
|
|
1154
1200
|
const file = path.join(notesDir, `dreamed-${isoSlug}.md`);
|
|
@@ -1214,8 +1260,8 @@ var Memory = {
|
|
|
1214
1260
|
openArgs.embedding = await resolveEmbedding(opts.embedding, peer.MEMORY_EMBEDDING_ADAPTERS);
|
|
1215
1261
|
return await peer.IndexManager.open(openArgs);
|
|
1216
1262
|
}
|
|
1217
|
-
const { IndexManager } = await import('./index-manager-
|
|
1218
|
-
openArgs.embedding = await resolveEmbedding(opts.embedding,
|
|
1263
|
+
const { IndexManager } = await import('./index-manager-34ELCOAP.cjs');
|
|
1264
|
+
openArgs.embedding = await resolveEmbedding(opts.embedding, chunkF7OBYH2X_cjs.MEMORY_EMBEDDING_ADAPTERS);
|
|
1219
1265
|
return await IndexManager.open(openArgs);
|
|
1220
1266
|
},
|
|
1221
1267
|
/**
|
|
@@ -1226,7 +1272,7 @@ var Memory = {
|
|
|
1226
1272
|
*/
|
|
1227
1273
|
async runDreamingSweep(opts) {
|
|
1228
1274
|
const peer = await tryLoadSdkMemoryPeer();
|
|
1229
|
-
const catalog = peer !== null ? peer.MEMORY_EMBEDDING_ADAPTERS :
|
|
1275
|
+
const catalog = peer !== null ? peer.MEMORY_EMBEDDING_ADAPTERS : chunkF7OBYH2X_cjs.MEMORY_EMBEDDING_ADAPTERS;
|
|
1230
1276
|
const sweepArgs = await buildDreamingSweepArgs(opts, catalog);
|
|
1231
1277
|
const result = peer !== null ? (
|
|
1232
1278
|
// biome-ignore lint/suspicious/noExplicitAny: peer is dynamically loaded — structural compat ensured by sdk-memory
|
|
@@ -1292,9 +1338,9 @@ function extractRawId(id, expectedAdapterId) {
|
|
|
1292
1338
|
return id.slice(prefix.length);
|
|
1293
1339
|
}
|
|
1294
1340
|
async function readAllSqliteFacts(cwd) {
|
|
1295
|
-
const dbPath =
|
|
1341
|
+
const dbPath = chunkRWMNTFHZ_cjs.defaultIndexPath(cwd);
|
|
1296
1342
|
if (!fs.existsSync(dbPath)) return [];
|
|
1297
|
-
const db = await
|
|
1343
|
+
const db = await chunkRWMNTFHZ_cjs.openMemoryDb({ filePath: dbPath });
|
|
1298
1344
|
try {
|
|
1299
1345
|
const stmt = db.prepare("SELECT id, path, source, start_line, end_line, text FROM chunks");
|
|
1300
1346
|
const rows = stmt.all();
|
|
@@ -1313,7 +1359,7 @@ function nfcEqual(a, b) {
|
|
|
1313
1359
|
}
|
|
1314
1360
|
async function migrateSqliteToLance(opts) {
|
|
1315
1361
|
const cwd = opts.cwd;
|
|
1316
|
-
const finalPath =
|
|
1362
|
+
const finalPath = chunkRWMNTFHZ_cjs.lanceStoragePath(cwd);
|
|
1317
1363
|
const newPath = path.join(cwd, ".theokit", "memory", "lance-new");
|
|
1318
1364
|
const rawLog = opts.logger ?? ((m) => console.log(m));
|
|
1319
1365
|
const log = (m) => rawLog(chunkZHPET3LZ_cjs.redactSecrets(m));
|
|
@@ -1357,7 +1403,7 @@ async function migrateSqliteToLance(opts) {
|
|
|
1357
1403
|
};
|
|
1358
1404
|
fs.mkdirSync(newPath, { recursive: true });
|
|
1359
1405
|
log(`Writing Lance index to ${newPath} ...`);
|
|
1360
|
-
const lance = await
|
|
1406
|
+
const lance = await chunkRWMNTFHZ_cjs.LanceIndex.open({
|
|
1361
1407
|
cwd,
|
|
1362
1408
|
embedding: placeholderEmbedding,
|
|
1363
1409
|
storagePath: newPath
|
|
@@ -1571,6 +1617,60 @@ function loadProjectEnv(env = process.env, load = typeof process.loadEnvFile ===
|
|
|
1571
1617
|
}
|
|
1572
1618
|
}
|
|
1573
1619
|
|
|
1620
|
+
// src/reap-plan.ts
|
|
1621
|
+
var RetentionPolicyError = class extends chunkYULF6FPB_cjs.TheokitAgentError {
|
|
1622
|
+
name = "RetentionPolicyError";
|
|
1623
|
+
};
|
|
1624
|
+
function assertPolicy(retention) {
|
|
1625
|
+
const { maxAgeMs, keepLast } = retention;
|
|
1626
|
+
if (!Number.isFinite(maxAgeMs) || maxAgeMs < 0) {
|
|
1627
|
+
throw new RetentionPolicyError(
|
|
1628
|
+
`retention.maxAgeMs must be a non-negative number of milliseconds, got ${String(maxAgeMs)}`
|
|
1629
|
+
);
|
|
1630
|
+
}
|
|
1631
|
+
if (!Number.isInteger(keepLast) || keepLast < 0) {
|
|
1632
|
+
throw new RetentionPolicyError(
|
|
1633
|
+
`retention.keepLast must be a non-negative integer, got ${String(keepLast)}`
|
|
1634
|
+
);
|
|
1635
|
+
}
|
|
1636
|
+
}
|
|
1637
|
+
function classifyByOwnReason(input) {
|
|
1638
|
+
const keep = [];
|
|
1639
|
+
const atRisk = [];
|
|
1640
|
+
for (const artifact of input.artifacts) {
|
|
1641
|
+
if (artifact.live === "unknown") continue;
|
|
1642
|
+
if (artifact.live === true) {
|
|
1643
|
+
keep.push({ ...artifact, reason: "live" });
|
|
1644
|
+
continue;
|
|
1645
|
+
}
|
|
1646
|
+
if (input.nowMs - artifact.lastModifiedMs <= input.retention.maxAgeMs) {
|
|
1647
|
+
keep.push({ ...artifact, reason: "within-retention" });
|
|
1648
|
+
continue;
|
|
1649
|
+
}
|
|
1650
|
+
atRisk.push(artifact);
|
|
1651
|
+
}
|
|
1652
|
+
return { keep, atRisk };
|
|
1653
|
+
}
|
|
1654
|
+
function applyFloor(kept, atRisk, keepLast) {
|
|
1655
|
+
const shortfall = Math.max(0, keepLast - kept.length);
|
|
1656
|
+
const newestFirst = [...atRisk].sort((a, b) => b.lastModifiedMs - a.lastModifiedMs);
|
|
1657
|
+
const spared = new Set(newestFirst.slice(0, shortfall).map((a) => a.id));
|
|
1658
|
+
const rescued = [];
|
|
1659
|
+
const reap = [];
|
|
1660
|
+
for (const artifact of atRisk) {
|
|
1661
|
+
if (spared.has(artifact.id)) rescued.push({ ...artifact, reason: "keep-last" });
|
|
1662
|
+
else reap.push(artifact);
|
|
1663
|
+
}
|
|
1664
|
+
return { rescued, reap };
|
|
1665
|
+
}
|
|
1666
|
+
function planReaping(input) {
|
|
1667
|
+
assertPolicy(input.retention);
|
|
1668
|
+
const undetermined = input.artifacts.filter((a) => a.live === "unknown");
|
|
1669
|
+
const { keep, atRisk } = classifyByOwnReason(input);
|
|
1670
|
+
const { rescued, reap } = applyFloor(keep, atRisk, input.retention.keepLast);
|
|
1671
|
+
return { reap, keep: [...keep, ...rescued], undetermined };
|
|
1672
|
+
}
|
|
1673
|
+
|
|
1574
1674
|
// src/schema-normalizer.ts
|
|
1575
1675
|
function isJsonSchemaObject(s) {
|
|
1576
1676
|
if (typeof s !== "object" || s === null) return false;
|
|
@@ -1701,6 +1801,28 @@ function applySecurityFloor(input) {
|
|
|
1701
1801
|
return input.layers[input.override] ?? tightenOnly(input, baseline(input));
|
|
1702
1802
|
}
|
|
1703
1803
|
|
|
1804
|
+
// src/session-guard.ts
|
|
1805
|
+
var LiveSessionError = class extends chunkYULF6FPB_cjs.TheokitAgentError {
|
|
1806
|
+
name = "LiveSessionError";
|
|
1807
|
+
sessionId;
|
|
1808
|
+
reason;
|
|
1809
|
+
constructor(sessionId, reason) {
|
|
1810
|
+
super(
|
|
1811
|
+
reason === "session-is-live" ? `refusing to destroy session ${sessionId}: it is live \u2014 another process is probably still appending to it. Switch to another session first.` : `refusing to destroy session ${sessionId}: the set of live sessions could not be determined, so this cannot be shown to be safe. Resolve that before deleting.`
|
|
1812
|
+
);
|
|
1813
|
+
this.sessionId = sessionId;
|
|
1814
|
+
this.reason = reason;
|
|
1815
|
+
}
|
|
1816
|
+
};
|
|
1817
|
+
function guardSessionDestruction(sessionId, live) {
|
|
1818
|
+
if (live === void 0) {
|
|
1819
|
+
throw new LiveSessionError(sessionId, "liveness-undetermined");
|
|
1820
|
+
}
|
|
1821
|
+
if (live.includes(sessionId)) {
|
|
1822
|
+
throw new LiveSessionError(sessionId, "session-is-live");
|
|
1823
|
+
}
|
|
1824
|
+
}
|
|
1825
|
+
|
|
1704
1826
|
// src/session-scope.ts
|
|
1705
1827
|
function scopedConversationId(scope, id) {
|
|
1706
1828
|
return `${scope}__${id}`;
|
|
@@ -1714,7 +1836,7 @@ function isBuiltAgent(m) {
|
|
|
1714
1836
|
return typeof m.send === "function";
|
|
1715
1837
|
}
|
|
1716
1838
|
async function materialize(def, index) {
|
|
1717
|
-
const { Agent: Agent2 } = await import('./agent-
|
|
1839
|
+
const { Agent: Agent2 } = await import('./agent-B2WU3JP6.cjs');
|
|
1718
1840
|
return Agent2.create({
|
|
1719
1841
|
// `AgentDefinition.model` admits the sentinel `'inherit'`, which is not a model id. Inheriting
|
|
1720
1842
|
// here means "declare nothing and let the default apply" — forwarding the literal would create
|
|
@@ -1746,13 +1868,13 @@ function createSquad(options) {
|
|
|
1746
1868
|
};
|
|
1747
1869
|
}
|
|
1748
1870
|
async function buildPipeline(agents, nome) {
|
|
1749
|
-
let builder =
|
|
1871
|
+
let builder = chunk72HEBGWN_cjs.Workflow.create({ name: nome ?? "squad" });
|
|
1750
1872
|
for (let i = 0; i < agents.length; i++) {
|
|
1751
1873
|
const member = agents[i];
|
|
1752
1874
|
if (member === void 0) continue;
|
|
1753
1875
|
const agent = isBuiltAgent(member) ? member : await materialize(member, i);
|
|
1754
1876
|
const opts = i > 0 ? { origin: { kind: "peer", from: `agent-${i - 1}` } } : void 0;
|
|
1755
|
-
builder = builder.then(
|
|
1877
|
+
builder = builder.then(chunk72HEBGWN_cjs.agentStep(`agent-${i}`, agent, (prev) => String(prev), opts));
|
|
1756
1878
|
}
|
|
1757
1879
|
return builder.commit();
|
|
1758
1880
|
}
|
|
@@ -1856,7 +1978,7 @@ var FIXTURE_USER = {
|
|
|
1856
1978
|
};
|
|
1857
1979
|
var FIXTURE_MODELS = [
|
|
1858
1980
|
{
|
|
1859
|
-
id:
|
|
1981
|
+
id: chunkF7OBYH2X_cjs.DEFAULT_AGENTIC_MODEL_ID,
|
|
1860
1982
|
name: "Gemini 2.0 Flash",
|
|
1861
1983
|
displayName: "Gemini 2.0 Flash",
|
|
1862
1984
|
parameters: [
|
|
@@ -2059,7 +2181,7 @@ var Theokit = class {
|
|
|
2059
2181
|
envVars: p.envVars
|
|
2060
2182
|
}));
|
|
2061
2183
|
},
|
|
2062
|
-
embeddingAdapters: () => Object.entries(
|
|
2184
|
+
embeddingAdapters: () => Object.entries(chunkF7OBYH2X_cjs.MEMORY_EMBEDDING_ADAPTERS).map(([id, adapter]) => ({
|
|
2063
2185
|
id,
|
|
2064
2186
|
transport: adapter.transport,
|
|
2065
2187
|
defaultModel: adapter.defaultModel
|
|
@@ -2091,7 +2213,7 @@ function resolveLocalProviderBaseUrl(providerName, fallback) {
|
|
|
2091
2213
|
return fallback;
|
|
2092
2214
|
}
|
|
2093
2215
|
async function executeCatalogRequest(request) {
|
|
2094
|
-
const apiKey =
|
|
2216
|
+
const apiKey = chunkF7OBYH2X_cjs.resolveApiKey(request.apiKey);
|
|
2095
2217
|
if (apiKey === void 0) {
|
|
2096
2218
|
throw new chunkYULF6FPB_cjs.AuthenticationError("Missing API key", { code: "missing_api_key" });
|
|
2097
2219
|
}
|
|
@@ -2104,6 +2226,23 @@ async function executeCatalogRequest(request) {
|
|
|
2104
2226
|
return chunkQFFNMJAS_cjs.httpRequest(request.path, { apiKey });
|
|
2105
2227
|
}
|
|
2106
2228
|
|
|
2229
|
+
// src/tool-blast-radius.ts
|
|
2230
|
+
var DECLARED = /* @__PURE__ */ Symbol.for("@theokit/sdk.blastRadius");
|
|
2231
|
+
function withBlastRadius(tool, action) {
|
|
2232
|
+
return Object.defineProperty(tool, DECLARED, {
|
|
2233
|
+
value: action,
|
|
2234
|
+
// `enumerable: false` is defensive and NOT load-bearing — checked, not assumed. Flipping it to
|
|
2235
|
+
// true leaves every case green, because the symbol key already excludes this from `Object.keys`
|
|
2236
|
+
// and `JSON.stringify`. It stays because a future string-keyed variant would need it, and the
|
|
2237
|
+
// next reader should not have to discover that the flag has no test behind it.
|
|
2238
|
+
enumerable: false,
|
|
2239
|
+
configurable: true
|
|
2240
|
+
});
|
|
2241
|
+
}
|
|
2242
|
+
function describeAction(tool) {
|
|
2243
|
+
return tool[DECLARED];
|
|
2244
|
+
}
|
|
2245
|
+
|
|
2107
2246
|
// src/trajectory-helpers.ts
|
|
2108
2247
|
function toShareGptTrajectory(result, options) {
|
|
2109
2248
|
if (!result.ok) return null;
|
|
@@ -2249,35 +2388,35 @@ Object.defineProperty(exports, "GenerateObjectError", {
|
|
|
2249
2388
|
});
|
|
2250
2389
|
Object.defineProperty(exports, "Cron", {
|
|
2251
2390
|
enumerable: true,
|
|
2252
|
-
get: function () { return
|
|
2391
|
+
get: function () { return chunkWUUSAMFC_cjs.Cron; }
|
|
2253
2392
|
});
|
|
2254
2393
|
Object.defineProperty(exports, "Agent", {
|
|
2255
2394
|
enumerable: true,
|
|
2256
|
-
get: function () { return
|
|
2395
|
+
get: function () { return chunkF7OBYH2X_cjs.Agent; }
|
|
2257
2396
|
});
|
|
2258
2397
|
Object.defineProperty(exports, "AgentBuilder", {
|
|
2259
2398
|
enumerable: true,
|
|
2260
|
-
get: function () { return
|
|
2399
|
+
get: function () { return chunkF7OBYH2X_cjs.AgentBuilder; }
|
|
2261
2400
|
});
|
|
2262
2401
|
Object.defineProperty(exports, "Tool", {
|
|
2263
2402
|
enumerable: true,
|
|
2264
|
-
get: function () { return
|
|
2403
|
+
get: function () { return chunkF7OBYH2X_cjs.Tool; }
|
|
2265
2404
|
});
|
|
2266
2405
|
Object.defineProperty(exports, "ToolError", {
|
|
2267
2406
|
enumerable: true,
|
|
2268
|
-
get: function () { return
|
|
2407
|
+
get: function () { return chunkF7OBYH2X_cjs.ToolError; }
|
|
2269
2408
|
});
|
|
2270
2409
|
Object.defineProperty(exports, "UsageAccumulator", {
|
|
2271
2410
|
enumerable: true,
|
|
2272
|
-
get: function () { return
|
|
2411
|
+
get: function () { return chunkF7OBYH2X_cjs.UsageAccumulator; }
|
|
2273
2412
|
});
|
|
2274
2413
|
Object.defineProperty(exports, "computeCost", {
|
|
2275
2414
|
enumerable: true,
|
|
2276
|
-
get: function () { return
|
|
2415
|
+
get: function () { return chunkF7OBYH2X_cjs.computeCost; }
|
|
2277
2416
|
});
|
|
2278
2417
|
Object.defineProperty(exports, "getPricingEntry", {
|
|
2279
2418
|
enumerable: true,
|
|
2280
|
-
get: function () { return
|
|
2419
|
+
get: function () { return chunkF7OBYH2X_cjs.getPricingEntry; }
|
|
2281
2420
|
});
|
|
2282
2421
|
Object.defineProperty(exports, "emitRunEvent", {
|
|
2283
2422
|
enumerable: true,
|
|
@@ -2364,12 +2503,14 @@ exports.Budget = Budget;
|
|
|
2364
2503
|
exports.EventBus = EventBus;
|
|
2365
2504
|
exports.JobQueue = JobQueue;
|
|
2366
2505
|
exports.LayerOrderError = LayerOrderError;
|
|
2506
|
+
exports.LiveSessionError = LiveSessionError;
|
|
2367
2507
|
exports.Memory = Memory;
|
|
2368
2508
|
exports.NoopMemoryProvider = NoopMemoryProvider;
|
|
2369
2509
|
exports.PermissionEngine = PermissionEngine;
|
|
2370
2510
|
exports.PermissionPlugin = PermissionPlugin;
|
|
2371
2511
|
exports.Plugin = Plugin;
|
|
2372
2512
|
exports.Provider = Provider;
|
|
2513
|
+
exports.RetentionPolicyError = RetentionPolicyError;
|
|
2373
2514
|
exports.SOVEREIGN_ENV_KEYS = SOVEREIGN_ENV_KEYS;
|
|
2374
2515
|
exports.Security = Security;
|
|
2375
2516
|
exports.Skill = Skill;
|
|
@@ -2385,15 +2526,21 @@ exports.applySecurityFloor = applySecurityFloor;
|
|
|
2385
2526
|
exports.auditEnvReachability = auditEnvReachability;
|
|
2386
2527
|
exports.chargeAndCheckThresholds = chargeAndCheckThresholds;
|
|
2387
2528
|
exports.createCounterBudgetTracker = createCounterBudgetTracker;
|
|
2529
|
+
exports.decideApproval = decideApproval;
|
|
2530
|
+
exports.describeAction = describeAction;
|
|
2531
|
+
exports.describeCredential = describeCredential;
|
|
2388
2532
|
exports.estimateTokens = estimateTokens;
|
|
2533
|
+
exports.evaluateBlastRadius = evaluateBlastRadius;
|
|
2389
2534
|
exports.extractRawId = extractRawId;
|
|
2390
2535
|
exports.foldLayers = foldLayers;
|
|
2536
|
+
exports.guardSessionDestruction = guardSessionDestruction;
|
|
2391
2537
|
exports.inferApiMode = inferApiMode;
|
|
2392
2538
|
exports.loadProjectEnv = loadProjectEnv;
|
|
2393
2539
|
exports.migrateSqliteToLance = migrateSqliteToLance2;
|
|
2394
2540
|
exports.mkMemoryId = mkMemoryId;
|
|
2395
2541
|
exports.normalizeSchema = normalizeSchema;
|
|
2396
2542
|
exports.normalizeUsage = normalizeUsage;
|
|
2543
|
+
exports.planReaping = planReaping;
|
|
2397
2544
|
exports.preflightCheck = preflightCheck;
|
|
2398
2545
|
exports.recordWiring = recordWiring;
|
|
2399
2546
|
exports.resolveTrustPosture = resolveTrustPosture;
|
|
@@ -2402,5 +2549,6 @@ exports.scopedConversationId = scopedConversationId;
|
|
|
2402
2549
|
exports.sessionScopePrefix = sessionScopePrefix;
|
|
2403
2550
|
exports.toShareGptTrajectory = toShareGptTrajectory;
|
|
2404
2551
|
exports.verifyLayerOrdering = verifyLayerOrdering;
|
|
2552
|
+
exports.withBlastRadius = withBlastRadius;
|
|
2405
2553
|
//# sourceMappingURL=index.cjs.map
|
|
2406
2554
|
//# sourceMappingURL=index.cjs.map
|