@theokit/sdk 4.63.4-next.0 → 4.63.5
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 +87 -14
- package/dist/{agent-PVINJTUR.cjs → agent-HM326RNG.cjs} +7 -7
- package/dist/{agent-PVINJTUR.cjs.map → agent-HM326RNG.cjs.map} +1 -1
- package/dist/{agent-3JK7VXNN.js → agent-Y25FRHPL.js} +6 -6
- package/dist/{agent-3JK7VXNN.js.map → agent-Y25FRHPL.js.map} +1 -1
- package/dist/agent.d.ts +20 -2
- package/dist/chunk-247ZTLNU.js +73 -0
- package/dist/chunk-247ZTLNU.js.map +1 -0
- package/dist/{chunk-GPKAF7SG.js → chunk-2OQHBPPV.js} +3 -3
- package/dist/{chunk-GPKAF7SG.js.map → chunk-2OQHBPPV.js.map} +1 -1
- package/dist/{chunk-CQBXOJ6U.cjs → chunk-43ZQRWAP.cjs} +5 -5
- package/dist/{chunk-CQBXOJ6U.cjs.map → chunk-43ZQRWAP.cjs.map} +1 -1
- package/dist/chunk-AKJP2STZ.cjs +81 -0
- package/dist/chunk-AKJP2STZ.cjs.map +1 -0
- package/dist/{chunk-JJ3OVRUM.cjs → chunk-BLTTW3KY.cjs} +157 -37
- package/dist/chunk-BLTTW3KY.cjs.map +1 -0
- package/dist/{chunk-ZWRG4NWT.cjs → chunk-EGCKRW36.cjs} +4 -4
- package/dist/{chunk-ZWRG4NWT.cjs.map → chunk-EGCKRW36.cjs.map} +1 -1
- package/dist/{chunk-25BD2R5G.js → chunk-GP7NHU3R.js} +134 -14
- package/dist/chunk-GP7NHU3R.js.map +1 -0
- package/dist/{chunk-LXI4XZEC.js → chunk-LKBEROHN.js} +3 -3
- package/dist/{chunk-LXI4XZEC.js.map → chunk-LKBEROHN.js.map} +1 -1
- package/dist/{chunk-K5OJUYSZ.js → chunk-NDGGJQTZ.js} +13 -4
- package/dist/chunk-NDGGJQTZ.js.map +1 -0
- package/dist/{chunk-ZCIRZE37.cjs → chunk-VCLBZAZU.cjs} +14 -5
- package/dist/chunk-VCLBZAZU.cjs.map +1 -0
- package/dist/{context-AGQ3DIZU.cjs → context-WFLTTMK3.cjs} +7 -7
- package/dist/{context-AGQ3DIZU.cjs.map → context-WFLTTMK3.cjs.map} +1 -1
- package/dist/context-WI2DFG7V.js +7 -0
- package/dist/{context-GQRFBCLP.js.map → context-WI2DFG7V.js.map} +1 -1
- package/dist/cron.cjs +6 -6
- package/dist/cron.js +5 -5
- package/dist/eval.cjs +5 -5
- package/dist/eval.js +4 -4
- package/dist/index.cjs +20 -20
- package/dist/index.d.cts +20 -2
- package/dist/index.d.ts +20 -2
- package/dist/index.js +7 -7
- package/dist/internal/agent-loop/replay-messages.d.ts +41 -0
- package/dist/internal/local-agent/local-option-keys.d.ts +2 -0
- package/dist/internal/persistence/index.cjs +4 -4
- package/dist/internal/persistence/index.js +1 -1
- package/dist/internal/runtime/compat/foreign-config-sources.d.ts +92 -0
- package/dist/internal/runtime/hooks/hooks-executor.d.ts +9 -0
- package/dist/internal/runtime/hooks/hooks-source.d.ts +9 -0
- package/dist/subagents-loader-UCNO7FUH.cjs +17 -0
- package/dist/{subagents-loader-YEUFFPAL.cjs.map → subagents-loader-UCNO7FUH.cjs.map} +1 -1
- package/dist/subagents-loader-XP5ERVDZ.js +8 -0
- package/dist/{subagents-loader-CRT5LLL3.js.map → subagents-loader-XP5ERVDZ.js.map} +1 -1
- package/dist/subagents-loader.cjs +3 -3
- package/dist/subagents-loader.js +2 -2
- package/docs/error-codes.md +5 -5
- package/package.json +1 -1
- package/dist/chunk-25BD2R5G.js.map +0 -1
- package/dist/chunk-AQO3NSRG.cjs +0 -41
- package/dist/chunk-AQO3NSRG.cjs.map +0 -1
- package/dist/chunk-JJ3OVRUM.cjs.map +0 -1
- package/dist/chunk-K5OJUYSZ.js.map +0 -1
- package/dist/chunk-UFLD2HEV.js +0 -35
- package/dist/chunk-UFLD2HEV.js.map +0 -1
- package/dist/chunk-ZCIRZE37.cjs.map +0 -1
- package/dist/context-GQRFBCLP.js +0 -7
- package/dist/subagents-loader-CRT5LLL3.js +0 -8
- package/dist/subagents-loader-YEUFFPAL.cjs +0 -17
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/internal/runtime/plugins/plugin-bundles.ts","../src/internal/runtime/skills/subagents-loader.ts"],"names":["pluginBundleRoots","readdir","join","projectConfigRoots","readWorkspaceDir","path","readFile","diag","ConfigurationError","parseSimpleYaml"],"mappings":"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","file":"chunk-CQBXOJ6U.cjs","sourcesContent":["/**\n * Locating the plugin bundles a project carries.\n *\n * Shared by the skills and subagents loaders, which both need the same answer to \"which folders in\n * this project are plugins\" and would otherwise each grow their own copy of the directory walk.\n *\n * @internal\n */\n\nimport type { Dirent } from \"node:fs\";\nimport { readdir } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport { pluginBundleRoots } from \"../../persistence/paths.js\";\n\n/**\n * Every plugin folder under the project's plugin roots.\n *\n * Returns the FOLDERS, not their contents — what a bundle contributes (`skills/`, `agents/`) is the\n * caller's business, and a loader that also knew the layout would have to change whenever the other\n * one did.\n *\n * A missing root is not an error: most projects carry no plugins, and treating their absence as a\n * failure would make \"none installed\" indistinguishable from \"the directory could not be read\".\n */\nexport async function pluginBundleDirs(cwd: string): Promise<string[]> {\n const dirs: string[] = [];\n for (const root of pluginBundleRoots(cwd)) {\n let entries: Dirent[];\n try {\n entries = await readdir(root, { withFileTypes: true });\n } catch {\n continue;\n }\n for (const entry of entries) {\n if (entry.isDirectory()) dirs.push(join(root, entry.name));\n }\n }\n return dirs;\n}\n","import { readFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\n\nimport { ConfigurationError } from \"../../../errors.js\";\nimport type { AgentDefinition } from \"../../../types/agent.js\";\nimport type { ModelSelection } from \"../../../types/agent-prims.js\";\nimport { diag } from \"../../diagnostics.js\";\nimport { projectConfigRoots } from \"../../persistence/paths.js\";\nimport { readWorkspaceDir } from \"../config/workspace-dir.js\";\nimport { type FrontmatterValue, parseSimpleYaml } from \"../context/yaml-frontmatter.js\";\nimport { pluginBundleDirs } from \"../plugins/plugin-bundles.js\";\n\n/**\n * Load file-based subagents from `.theokit/agents/*.md` and merge with\n * inline definitions. Inline overrides file-based on name conflict.\n *\n * Each markdown file has YAML frontmatter (description + optional model)\n * and a body that becomes the subagent prompt.\n *\n * @internal\n */\nexport async function loadSubagents(\n cwd: string,\n settingSourcesIncludeProject: boolean,\n inline: Record<string, AgentDefinition> | undefined,\n): Promise<Record<string, AgentDefinition>> {\n const result: Record<string, AgentDefinition> = {};\n if (settingSourcesIncludeProject) {\n const projectAgents = await readProjectSubagents(cwd);\n for (const [name, definition] of Object.entries(projectAgents)) {\n result[name] = definition;\n }\n }\n if (inline !== undefined) {\n for (const [name, definition] of Object.entries(inline)) {\n result[name] = definition;\n }\n }\n return result;\n}\n\n/**\n * Read agent declarations from every project config root (`.theokit`, then `.claude`).\n *\n * FIRST occurrence of a name wins, which is what makes `projectConfigRoots`' order a contract rather\n * than a detail: a project declaring the same agent in both means the explicit namespace.\n */\nasync function readProjectSubagents(cwd: string): Promise<Record<string, AgentDefinition>> {\n const subagents: Record<string, AgentDefinition> = {};\n for (const configRoot of projectConfigRoots(cwd)) {\n await readSubagentsFrom(join(configRoot, \"agents\"), subagents);\n }\n // A Claude Code plugin is a BUNDLE, and its `agents/` is what it exists to contribute. Read after\n // the project's own, so a project can shadow an agent a plugin ships without editing the plugin.\n for (const bundle of await pluginBundleDirs(cwd)) {\n await readSubagentsFrom(join(bundle, \"agents\"), subagents);\n }\n return subagents;\n}\n\nasync function readSubagentsFrom(\n root: string,\n subagents: Record<string, AgentDefinition>,\n): Promise<void> {\n const entries = await readWorkspaceDir(root, \"subagents_read_error\", \"subagents directory\");\n for (const entry of entries) {\n if (!entry.isFile() || !entry.name.endsWith(\".md\")) continue;\n const path = join(root, entry.name);\n const raw = await readFile(path, \"utf8\");\n // A markdown file with NO frontmatter is not an agent declaration — a directory of agents\n // written for the Claude Code CLI conventionally carries documentation beside them, and\n // `.claude/agents/README.md` exists in this repository. Throwing on it made ONE such file stop\n // every agent in the directory from loading.\n //\n // Skipped with a warn rather than in silence, and ONLY for the no-frontmatter case: a file that\n // HAS frontmatter and gets it wrong is a broken agent and still fails loudly, which is what\n // keeps a typo'd `sandbox` from returning as a silent gate through this door.\n if (!hasFrontmatter(raw)) {\n diag(`[theokit-sdk] ${entry.name} has no frontmatter — not an agent declaration, skipping`);\n continue;\n }\n const definition = parseSubagentMarkdown(raw, entry.name);\n if (subagents[definition.name] === undefined) {\n subagents[definition.name] = definition.definition;\n }\n }\n}\n\n// The frontmatter keys a disk subagent may declare. Any other key is a typed load\n// error rather than a silent drop — a dropped `sandbox` an operator wrote believing\n// it confines the child is exactly the silent-gate failure class this guards against.\nconst ACCEPTED_FIELDS = new Set([\n \"name\",\n \"description\",\n \"model\",\n \"tools\",\n \"reasoning_effort\",\n \"mcp\",\n \"sandbox\",\n]);\n\n// Fields the Claude Code CLI writes that carry NO behaviour for this runtime. Accepted and ignored,\n// so an agent authored for the CLI loads here unchanged — measured 2026-08-26 across the 59 agent\n// files on one machine, where `color` appeared in 38 of them and made every one of those a\n// `subagent_unknown_field` load error.\n//\n// Named explicitly instead of loosening the check above, because that check's reason is sound: a\n// dropped `sandbox` an operator wrote believing it confines the child is a silent gate. A field that\n// COULD change behaviour must still fail loudly. This set is the difference between \"we know this\n// one and it does nothing\" and \"we have never heard of this\" — two facts a bare allow-everything\n// would collapse into one.\n//\n// Anything added here needs the same justification: inert for THIS runtime, not merely unfamiliar.\nconst INERT_CLAUDE_CODE_FIELDS = new Set([\n /** The CLI's label colour for the agent. Presentation only. */\n \"color\",\n]);\n\nfunction parseSubagentMarkdown(\n raw: string,\n filename: string,\n): { name: string; definition: AgentDefinition } {\n const { frontmatter, body } = splitFrontmatter(raw, filename);\n const fields = parseFrontmatterFields(frontmatter);\n rejectUnknownFields(fields, filename);\n rejectMcp(fields, filename);\n\n const definition: AgentDefinition = {\n description: asString(fields.description) ?? \"\",\n prompt: body,\n };\n const model = resolveModel(fields, filename);\n if (model !== undefined) definition.model = model;\n const tools = toStringList(fields.tools);\n if (tools.length > 0) definition.tools = tools;\n const sandbox = resolveSandbox(fields, filename);\n if (sandbox !== undefined) definition.sandbox = sandbox;\n\n const name = asString(fields.name) ?? filename.replace(/\\.md$/, \"\");\n return { name, definition };\n}\n\nfunction rejectUnknownFields(\n fields: Record<string, FrontmatterValue | undefined>,\n filename: string,\n): void {\n for (const key of Object.keys(fields)) {\n if (INERT_CLAUDE_CODE_FIELDS.has(key)) continue;\n if (!ACCEPTED_FIELDS.has(key)) {\n throw new ConfigurationError(\n `Subagent ${filename}: unknown frontmatter field \"${key}\" (accepted: ${[...ACCEPTED_FIELDS].join(\", \")})`,\n { code: \"subagent_unknown_field\" },\n );\n }\n }\n}\n\n// mcp: a known field, but not yet honored on the LOCAL delegation path. The frontmatter YAML can only\n// express server NAMES (parseSimpleYaml has no nested-object support), while a child's `Agent.create`\n// needs `mcpServers` as a Record<name, config>; resolving names→config per-subagent in local delegation\n// is its own follow-up. Rather than silently drop it (the M26/M32 silent-gate class), it is a typed load\n// error that names the field and points at the alternative.\nfunction rejectMcp(fields: Record<string, FrontmatterValue | undefined>, filename: string): void {\n if (fields.mcp !== undefined) {\n throw new ConfigurationError(\n `Subagent ${filename}: per-subagent \"mcp\" is not yet supported on the local delegation path; declare MCP servers in .theokit/mcp.json (or the parent) instead`,\n { code: \"subagent_mcp_unsupported_local\" },\n );\n }\n}\n\n// model + reasoning_effort — effort rides inside `model.params[thinking]`, so it requires a concrete\n// model id to attach to (a child inheriting the parent's model cannot carry the parent's provider-\n// specific effort param safely).\nfunction resolveModel(\n fields: Record<string, FrontmatterValue | undefined>,\n filename: string,\n): ModelSelection | \"inherit\" | undefined {\n const modelId = asString(fields.model);\n const effort = asString(fields.reasoning_effort);\n // reasoning_effort rides in model.params[thinking], so it needs a CONCRETE model id to attach to.\n // Neither an absent model NOR `model: inherit` can carry it (the inherited id is unknown at load), so\n // both are typed errors rather than a silently-dropped effort — the silent-gate class this guards.\n if (effort !== undefined && (modelId === undefined || modelId === \"inherit\")) {\n throw new ConfigurationError(\n `Subagent ${filename}: reasoning_effort requires a concrete model (effort is a model parameter; an absent model or \"inherit\" cannot carry it)`,\n { code: \"subagent_reasoning_effort_without_model\" },\n );\n }\n if (modelId === undefined) return undefined;\n if (modelId === \"inherit\") return \"inherit\";\n return effort !== undefined\n ? { id: modelId, params: [{ id: \"thinking\", value: effort }] }\n : { id: modelId };\n}\n\n// sandbox: boolean only. A granular mode string (read-only/…) is unsupported by the SDK runtime and is\n// a typed error rather than a silent coercion to a boolean.\nfunction resolveSandbox(\n fields: Record<string, FrontmatterValue | undefined>,\n filename: string,\n): boolean | undefined {\n if (fields.sandbox === undefined) return undefined;\n if (typeof fields.sandbox !== \"boolean\") {\n throw new ConfigurationError(\n `Subagent ${filename}: sandbox must be a boolean (got \"${String(fields.sandbox)}\"); granular sandbox modes are not supported by the runtime`,\n { code: \"subagent_sandbox_not_boolean\" },\n );\n }\n return fields.sandbox;\n}\n\nfunction asString(v: FrontmatterValue | undefined): string | undefined {\n if (typeof v !== \"string\") return undefined;\n // parseSimpleYaml does not strip quotes (documented), and `model`/`reasoning_effort` are fields users\n // habitually quote (`model: \"openai/gpt-4o\"`). Strip a single matching surrounding quote pair so a\n // quoted id/effort does not slip past validation and fail only at the provider.\n const m = /^([\"'])(.*)\\1$/.exec(v);\n return m ? m[2] : v;\n}\n\n/** Accept a YAML list (`string[]`) or a comma/space-separated scalar; trim + drop empties. */\nfunction toStringList(v: FrontmatterValue | undefined): string[] {\n if (Array.isArray(v)) return v.map((t) => t.trim()).filter((t) => t.length > 0);\n if (typeof v === \"string\") {\n return v\n .split(/[\\s,]+/)\n .map((t) => t.trim())\n .filter((t) => t.length > 0);\n }\n return [];\n}\n\n/** Does this file open with a frontmatter block at all? Its ABSENCE means \"not an agent\". */\nfunction hasFrontmatter(raw: string): boolean {\n return /^---\\s*\\n/.test(raw);\n}\n\nfunction splitFrontmatter(raw: string, filename: string): { frontmatter: string; body: string } {\n const match = /^---\\s*\\n([\\s\\S]*?)\\n---\\s*\\n([\\s\\S]*)$/.exec(raw);\n if (match === null) {\n throw new ConfigurationError(`Subagent ${filename} is missing frontmatter`, {\n code: \"subagent_missing_frontmatter\",\n });\n }\n return { frontmatter: match[1] ?? \"\", body: (match[2] ?? \"\").trim() };\n}\n\nfunction parseFrontmatterFields(frontmatter: string): Record<string, FrontmatterValue | undefined> {\n // Preserve the rich YAML value types (boolean/number/string[]): `sandbox: true` and\n // `mcp: [a, b]` are meaningful here, so narrowing everything to string (as the\n // pre-M33 loader did) would drop them. Per-field validation happens in parseSubagentMarkdown.\n return parseSimpleYaml(frontmatter);\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/internal/runtime/plugins/plugin-bundles.ts","../src/internal/runtime/skills/subagents-loader.ts"],"names":["pluginBundleRoots","readdir","join","projectConfigRoots","readWorkspaceDir","path","readFile","diag","ConfigurationError","parseSimpleYaml"],"mappings":";;;;;;;;;AAwBA,eAAsB,iBAAiB,GAAA,EAAgC;AACrE,EAAA,MAAM,OAAiB,EAAC;AACxB,EAAA,KAAA,MAAW,IAAA,IAAQA,mCAAA,CAAkB,GAAG,CAAA,EAAG;AACzC,IAAA,IAAI,OAAA;AACJ,IAAA,IAAI;AACF,MAAA,OAAA,GAAU,MAAMC,gBAAA,CAAQ,IAAA,EAAM,EAAE,aAAA,EAAe,MAAM,CAAA;AAAA,IACvD,CAAA,CAAA,MAAQ;AACN,MAAA;AAAA,IACF;AACA,IAAA,KAAA,MAAW,SAAS,OAAA,EAAS;AAC3B,MAAA,IAAI,KAAA,CAAM,aAAY,EAAG,IAAA,CAAK,KAAKC,SAAA,CAAK,IAAA,EAAM,KAAA,CAAM,IAAI,CAAC,CAAA;AAAA,IAC3D;AAAA,EACF;AACA,EAAA,OAAO,IAAA;AACT;;;ACjBA,eAAsB,aAAA,CACpB,GAAA,EACA,4BAAA,EACA,MAAA,EAC0C;AAC1C,EAAA,MAAM,SAA0C,EAAC;AACjD,EAAA,IAAI,4BAAA,EAA8B;AAChC,IAAA,MAAM,aAAA,GAAgB,MAAM,oBAAA,CAAqB,GAAG,CAAA;AACpD,IAAA,KAAA,MAAW,CAAC,IAAA,EAAM,UAAU,KAAK,MAAA,CAAO,OAAA,CAAQ,aAAa,CAAA,EAAG;AAC9D,MAAA,MAAA,CAAO,IAAI,CAAA,GAAI,UAAA;AAAA,IACjB;AAAA,EACF;AACA,EAAA,IAAI,WAAW,MAAA,EAAW;AACxB,IAAA,KAAA,MAAW,CAAC,IAAA,EAAM,UAAU,KAAK,MAAA,CAAO,OAAA,CAAQ,MAAM,CAAA,EAAG;AACvD,MAAA,MAAA,CAAO,IAAI,CAAA,GAAI,UAAA;AAAA,IACjB;AAAA,EACF;AACA,EAAA,OAAO,MAAA;AACT;AAQA,eAAe,qBAAqB,GAAA,EAAuD;AACzF,EAAA,MAAM,YAA6C,EAAC;AACpD,EAAA,KAAA,MAAW,UAAA,IAAcC,oCAAA,CAAmB,GAAG,CAAA,EAAG;AAChD,IAAA,MAAM,iBAAA,CAAkBD,SAAAA,CAAK,UAAA,EAAY,QAAQ,GAAG,SAAS,CAAA;AAAA,EAC/D;AAGA,EAAA,KAAA,MAAW,MAAA,IAAU,MAAM,gBAAA,CAAiB,GAAG,CAAA,EAAG;AAChD,IAAA,MAAM,iBAAA,CAAkBA,SAAAA,CAAK,MAAA,EAAQ,QAAQ,GAAG,SAAS,CAAA;AAAA,EAC3D;AACA,EAAA,OAAO,SAAA;AACT;AAEA,eAAe,iBAAA,CACb,MACA,SAAA,EACe;AACf,EAAA,MAAM,OAAA,GAAU,MAAME,kCAAA,CAAiB,IAAA,EAAM,wBAAwB,qBAAqB,CAAA;AAC1F,EAAA,KAAA,MAAW,SAAS,OAAA,EAAS;AAC3B,IAAA,IAAI,CAAC,MAAM,MAAA,EAAO,IAAK,CAAC,KAAA,CAAM,IAAA,CAAK,QAAA,CAAS,KAAK,CAAA,EAAG;AACpD,IAAA,MAAMC,MAAA,GAAOH,SAAAA,CAAK,IAAA,EAAM,KAAA,CAAM,IAAI,CAAA;AAClC,IAAA,MAAM,GAAA,GAAM,MAAMI,iBAAA,CAASD,MAAA,EAAM,MAAM,CAAA;AASvC,IAAA,IAAI,CAAC,cAAA,CAAe,GAAG,CAAA,EAAG;AACxB,MAAAE,sBAAA,CAAK,CAAA,cAAA,EAAiB,KAAA,CAAM,IAAI,CAAA,6DAAA,CAA0D,CAAA;AAC1F,MAAA;AAAA,IACF;AACA,IAAA,MAAM,UAAA,GAAa,qBAAA,CAAsB,GAAA,EAAK,KAAA,CAAM,IAAI,CAAA;AACxD,IAAA,IAAI,SAAA,CAAU,UAAA,CAAW,IAAI,CAAA,KAAM,MAAA,EAAW;AAC5C,MAAA,SAAA,CAAU,UAAA,CAAW,IAAI,CAAA,GAAI,UAAA,CAAW,UAAA;AAAA,IAC1C;AAAA,EACF;AACF;AAKA,IAAM,eAAA,uBAAsB,GAAA,CAAI;AAAA,EAC9B,MAAA;AAAA,EACA,aAAA;AAAA,EACA,OAAA;AAAA,EACA,OAAA;AAAA,EACA,kBAAA;AAAA,EACA,KAAA;AAAA,EACA;AACF,CAAC,CAAA;AAcD,IAAM,wBAAA,uBAA+B,GAAA,CAAI;AAAA;AAAA,EAEvC;AACF,CAAC,CAAA;AAED,SAAS,qBAAA,CACP,KACA,QAAA,EAC+C;AAC/C,EAAA,MAAM,EAAE,WAAA,EAAa,IAAA,EAAK,GAAI,gBAAA,CAAiB,KAAK,QAAQ,CAAA;AAC5D,EAAA,MAAM,MAAA,GAAS,uBAAuB,WAAW,CAAA;AACjD,EAAA,mBAAA,CAAoB,QAAQ,QAAQ,CAAA;AACpC,EAAA,SAAA,CAAU,QAAQ,QAAQ,CAAA;AAE1B,EAAA,MAAM,UAAA,GAA8B;AAAA,IAClC,WAAA,EAAa,QAAA,CAAS,MAAA,CAAO,WAAW,CAAA,IAAK,EAAA;AAAA,IAC7C,MAAA,EAAQ;AAAA,GACV;AACA,EAAA,MAAM,KAAA,GAAQ,YAAA,CAAa,MAAA,EAAQ,QAAQ,CAAA;AAC3C,EAAA,IAAI,KAAA,KAAU,MAAA,EAAW,UAAA,CAAW,KAAA,GAAQ,KAAA;AAC5C,EAAA,MAAM,KAAA,GAAQ,YAAA,CAAa,MAAA,CAAO,KAAK,CAAA;AACvC,EAAA,IAAI,KAAA,CAAM,MAAA,GAAS,CAAA,EAAG,UAAA,CAAW,KAAA,GAAQ,KAAA;AACzC,EAAA,MAAM,OAAA,GAAU,cAAA,CAAe,MAAA,EAAQ,QAAQ,CAAA;AAC/C,EAAA,IAAI,OAAA,KAAY,MAAA,EAAW,UAAA,CAAW,OAAA,GAAU,OAAA;AAEhD,EAAA,MAAM,IAAA,GAAO,SAAS,MAAA,CAAO,IAAI,KAAK,QAAA,CAAS,OAAA,CAAQ,SAAS,EAAE,CAAA;AAClE,EAAA,OAAO,EAAE,MAAM,UAAA,EAAW;AAC5B;AAEA,SAAS,mBAAA,CACP,QACA,QAAA,EACM;AACN,EAAA,KAAA,MAAW,GAAA,IAAO,MAAA,CAAO,IAAA,CAAK,MAAM,CAAA,EAAG;AACrC,IAAA,IAAI,wBAAA,CAAyB,GAAA,CAAI,GAAG,CAAA,EAAG;AACvC,IAAA,IAAI,CAAC,eAAA,CAAgB,GAAA,CAAI,GAAG,CAAA,EAAG;AAC7B,MAAA,MAAM,IAAIC,oCAAA;AAAA,QACR,CAAA,SAAA,EAAY,QAAQ,CAAA,6BAAA,EAAgC,GAAG,CAAA,aAAA,EAAgB,CAAC,GAAG,eAAe,CAAA,CAAE,IAAA,CAAK,IAAI,CAAC,CAAA,CAAA,CAAA;AAAA,QACtG,EAAE,MAAM,wBAAA;AAAyB,OACnC;AAAA,IACF;AAAA,EACF;AACF;AAOA,SAAS,SAAA,CAAU,QAAsD,QAAA,EAAwB;AAC/F,EAAA,IAAI,MAAA,CAAO,QAAQ,MAAA,EAAW;AAC5B,IAAA,MAAM,IAAIA,oCAAA;AAAA,MACR,YAAY,QAAQ,CAAA,wIAAA,CAAA;AAAA,MACpB,EAAE,MAAM,gCAAA;AAAiC,KAC3C;AAAA,EACF;AACF;AAKA,SAAS,YAAA,CACP,QACA,QAAA,EACwC;AACxC,EAAA,MAAM,OAAA,GAAU,QAAA,CAAS,MAAA,CAAO,KAAK,CAAA;AACrC,EAAA,MAAM,MAAA,GAAS,QAAA,CAAS,MAAA,CAAO,gBAAgB,CAAA;AAI/C,EAAA,IAAI,MAAA,KAAW,MAAA,KAAc,OAAA,KAAY,MAAA,IAAa,YAAY,SAAA,CAAA,EAAY;AAC5E,IAAA,MAAM,IAAIA,oCAAA;AAAA,MACR,YAAY,QAAQ,CAAA,wHAAA,CAAA;AAAA,MACpB,EAAE,MAAM,yCAAA;AAA0C,KACpD;AAAA,EACF;AACA,EAAA,IAAI,OAAA,KAAY,QAAW,OAAO,MAAA;AAClC,EAAA,IAAI,OAAA,KAAY,WAAW,OAAO,SAAA;AAClC,EAAA,OAAO,WAAW,MAAA,GACd,EAAE,EAAA,EAAI,OAAA,EAAS,QAAQ,CAAC,EAAE,EAAA,EAAI,UAAA,EAAY,OAAO,MAAA,EAAQ,GAAE,GAC3D,EAAE,IAAI,OAAA,EAAQ;AACpB;AAIA,SAAS,cAAA,CACP,QACA,QAAA,EACqB;AACrB,EAAA,IAAI,MAAA,CAAO,OAAA,KAAY,MAAA,EAAW,OAAO,MAAA;AACzC,EAAA,IAAI,OAAO,MAAA,CAAO,OAAA,KAAY,SAAA,EAAW;AACvC,IAAA,MAAM,IAAIA,oCAAA;AAAA,MACR,YAAY,QAAQ,CAAA,kCAAA,EAAqC,MAAA,CAAO,MAAA,CAAO,OAAO,CAAC,CAAA,2DAAA,CAAA;AAAA,MAC/E,EAAE,MAAM,8BAAA;AAA+B,KACzC;AAAA,EACF;AACA,EAAA,OAAO,MAAA,CAAO,OAAA;AAChB;AAEA,SAAS,SAAS,CAAA,EAAqD;AACrE,EAAA,IAAI,OAAO,CAAA,KAAM,QAAA,EAAU,OAAO,MAAA;AAIlC,EAAA,MAAM,CAAA,GAAI,gBAAA,CAAiB,IAAA,CAAK,CAAC,CAAA;AACjC,EAAA,OAAO,CAAA,GAAI,CAAA,CAAE,CAAC,CAAA,GAAI,CAAA;AACpB;AAGA,SAAS,aAAa,CAAA,EAA2C;AAC/D,EAAA,IAAI,MAAM,OAAA,CAAQ,CAAC,GAAG,OAAO,CAAA,CAAE,IAAI,CAAC,CAAA,KAAM,CAAA,CAAE,IAAA,EAAM,CAAA,CAAE,MAAA,CAAO,CAAC,CAAA,KAAM,CAAA,CAAE,SAAS,CAAC,CAAA;AAC9E,EAAA,IAAI,OAAO,MAAM,QAAA,EAAU;AACzB,IAAA,OAAO,EACJ,KAAA,CAAM,QAAQ,CAAA,CACd,GAAA,CAAI,CAAC,CAAA,KAAM,CAAA,CAAE,IAAA,EAAM,EACnB,MAAA,CAAO,CAAC,CAAA,KAAM,CAAA,CAAE,SAAS,CAAC,CAAA;AAAA,EAC/B;AACA,EAAA,OAAO,EAAC;AACV;AAGA,SAAS,eAAe,GAAA,EAAsB;AAC5C,EAAA,OAAO,WAAA,CAAY,KAAK,GAAG,CAAA;AAC7B;AAEA,SAAS,gBAAA,CAAiB,KAAa,QAAA,EAAyD;AAC9F,EAAA,MAAM,KAAA,GAAQ,yCAAA,CAA0C,IAAA,CAAK,GAAG,CAAA;AAChE,EAAA,IAAI,UAAU,IAAA,EAAM;AAClB,IAAA,MAAM,IAAIA,oCAAA,CAAmB,CAAA,SAAA,EAAY,QAAQ,CAAA,uBAAA,CAAA,EAA2B;AAAA,MAC1E,IAAA,EAAM;AAAA,KACP,CAAA;AAAA,EACH;AACA,EAAA,OAAO,EAAE,WAAA,EAAa,KAAA,CAAM,CAAC,CAAA,IAAK,EAAA,EAAI,IAAA,EAAA,CAAO,KAAA,CAAM,CAAC,CAAA,IAAK,EAAA,EAAI,IAAA,EAAK,EAAE;AACtE;AAEA,SAAS,uBAAuB,WAAA,EAAmE;AAIjG,EAAA,OAAOC,kCAAgB,WAAW,CAAA;AACpC","file":"chunk-43ZQRWAP.cjs","sourcesContent":["/**\n * Locating the plugin bundles a project carries.\n *\n * Shared by the skills and subagents loaders, which both need the same answer to \"which folders in\n * this project are plugins\" and would otherwise each grow their own copy of the directory walk.\n *\n * @internal\n */\n\nimport type { Dirent } from \"node:fs\";\nimport { readdir } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport { pluginBundleRoots } from \"../../persistence/paths.js\";\n\n/**\n * Every plugin folder under the project's plugin roots.\n *\n * Returns the FOLDERS, not their contents — what a bundle contributes (`skills/`, `agents/`) is the\n * caller's business, and a loader that also knew the layout would have to change whenever the other\n * one did.\n *\n * A missing root is not an error: most projects carry no plugins, and treating their absence as a\n * failure would make \"none installed\" indistinguishable from \"the directory could not be read\".\n */\nexport async function pluginBundleDirs(cwd: string): Promise<string[]> {\n const dirs: string[] = [];\n for (const root of pluginBundleRoots(cwd)) {\n let entries: Dirent[];\n try {\n entries = await readdir(root, { withFileTypes: true });\n } catch {\n continue;\n }\n for (const entry of entries) {\n if (entry.isDirectory()) dirs.push(join(root, entry.name));\n }\n }\n return dirs;\n}\n","import { readFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\n\nimport { ConfigurationError } from \"../../../errors.js\";\nimport type { AgentDefinition } from \"../../../types/agent.js\";\nimport type { ModelSelection } from \"../../../types/agent-prims.js\";\nimport { diag } from \"../../diagnostics.js\";\nimport { projectConfigRoots } from \"../../persistence/paths.js\";\nimport { readWorkspaceDir } from \"../config/workspace-dir.js\";\nimport { type FrontmatterValue, parseSimpleYaml } from \"../context/yaml-frontmatter.js\";\nimport { pluginBundleDirs } from \"../plugins/plugin-bundles.js\";\n\n/**\n * Load file-based subagents from `.theokit/agents/*.md` and merge with\n * inline definitions. Inline overrides file-based on name conflict.\n *\n * Each markdown file has YAML frontmatter (description + optional model)\n * and a body that becomes the subagent prompt.\n *\n * @internal\n */\nexport async function loadSubagents(\n cwd: string,\n settingSourcesIncludeProject: boolean,\n inline: Record<string, AgentDefinition> | undefined,\n): Promise<Record<string, AgentDefinition>> {\n const result: Record<string, AgentDefinition> = {};\n if (settingSourcesIncludeProject) {\n const projectAgents = await readProjectSubagents(cwd);\n for (const [name, definition] of Object.entries(projectAgents)) {\n result[name] = definition;\n }\n }\n if (inline !== undefined) {\n for (const [name, definition] of Object.entries(inline)) {\n result[name] = definition;\n }\n }\n return result;\n}\n\n/**\n * Read agent declarations from every project config root (`.theokit`, then `.claude`).\n *\n * FIRST occurrence of a name wins, which is what makes `projectConfigRoots`' order a contract rather\n * than a detail: a project declaring the same agent in both means the explicit namespace.\n */\nasync function readProjectSubagents(cwd: string): Promise<Record<string, AgentDefinition>> {\n const subagents: Record<string, AgentDefinition> = {};\n for (const configRoot of projectConfigRoots(cwd)) {\n await readSubagentsFrom(join(configRoot, \"agents\"), subagents);\n }\n // A Claude Code plugin is a BUNDLE, and its `agents/` is what it exists to contribute. Read after\n // the project's own, so a project can shadow an agent a plugin ships without editing the plugin.\n for (const bundle of await pluginBundleDirs(cwd)) {\n await readSubagentsFrom(join(bundle, \"agents\"), subagents);\n }\n return subagents;\n}\n\nasync function readSubagentsFrom(\n root: string,\n subagents: Record<string, AgentDefinition>,\n): Promise<void> {\n const entries = await readWorkspaceDir(root, \"subagents_read_error\", \"subagents directory\");\n for (const entry of entries) {\n if (!entry.isFile() || !entry.name.endsWith(\".md\")) continue;\n const path = join(root, entry.name);\n const raw = await readFile(path, \"utf8\");\n // A markdown file with NO frontmatter is not an agent declaration — a directory of agents\n // written for the Claude Code CLI conventionally carries documentation beside them, and\n // `.claude/agents/README.md` exists in this repository. Throwing on it made ONE such file stop\n // every agent in the directory from loading.\n //\n // Skipped with a warn rather than in silence, and ONLY for the no-frontmatter case: a file that\n // HAS frontmatter and gets it wrong is a broken agent and still fails loudly, which is what\n // keeps a typo'd `sandbox` from returning as a silent gate through this door.\n if (!hasFrontmatter(raw)) {\n diag(`[theokit-sdk] ${entry.name} has no frontmatter — not an agent declaration, skipping`);\n continue;\n }\n const definition = parseSubagentMarkdown(raw, entry.name);\n if (subagents[definition.name] === undefined) {\n subagents[definition.name] = definition.definition;\n }\n }\n}\n\n// The frontmatter keys a disk subagent may declare. Any other key is a typed load\n// error rather than a silent drop — a dropped `sandbox` an operator wrote believing\n// it confines the child is exactly the silent-gate failure class this guards against.\nconst ACCEPTED_FIELDS = new Set([\n \"name\",\n \"description\",\n \"model\",\n \"tools\",\n \"reasoning_effort\",\n \"mcp\",\n \"sandbox\",\n]);\n\n// Fields the Claude Code CLI writes that carry NO behaviour for this runtime. Accepted and ignored,\n// so an agent authored for the CLI loads here unchanged — measured 2026-08-26 across the 59 agent\n// files on one machine, where `color` appeared in 38 of them and made every one of those a\n// `subagent_unknown_field` load error.\n//\n// Named explicitly instead of loosening the check above, because that check's reason is sound: a\n// dropped `sandbox` an operator wrote believing it confines the child is a silent gate. A field that\n// COULD change behaviour must still fail loudly. This set is the difference between \"we know this\n// one and it does nothing\" and \"we have never heard of this\" — two facts a bare allow-everything\n// would collapse into one.\n//\n// Anything added here needs the same justification: inert for THIS runtime, not merely unfamiliar.\nconst INERT_CLAUDE_CODE_FIELDS = new Set([\n /** The CLI's label colour for the agent. Presentation only. */\n \"color\",\n]);\n\nfunction parseSubagentMarkdown(\n raw: string,\n filename: string,\n): { name: string; definition: AgentDefinition } {\n const { frontmatter, body } = splitFrontmatter(raw, filename);\n const fields = parseFrontmatterFields(frontmatter);\n rejectUnknownFields(fields, filename);\n rejectMcp(fields, filename);\n\n const definition: AgentDefinition = {\n description: asString(fields.description) ?? \"\",\n prompt: body,\n };\n const model = resolveModel(fields, filename);\n if (model !== undefined) definition.model = model;\n const tools = toStringList(fields.tools);\n if (tools.length > 0) definition.tools = tools;\n const sandbox = resolveSandbox(fields, filename);\n if (sandbox !== undefined) definition.sandbox = sandbox;\n\n const name = asString(fields.name) ?? filename.replace(/\\.md$/, \"\");\n return { name, definition };\n}\n\nfunction rejectUnknownFields(\n fields: Record<string, FrontmatterValue | undefined>,\n filename: string,\n): void {\n for (const key of Object.keys(fields)) {\n if (INERT_CLAUDE_CODE_FIELDS.has(key)) continue;\n if (!ACCEPTED_FIELDS.has(key)) {\n throw new ConfigurationError(\n `Subagent ${filename}: unknown frontmatter field \"${key}\" (accepted: ${[...ACCEPTED_FIELDS].join(\", \")})`,\n { code: \"subagent_unknown_field\" },\n );\n }\n }\n}\n\n// mcp: a known field, but not yet honored on the LOCAL delegation path. The frontmatter YAML can only\n// express server NAMES (parseSimpleYaml has no nested-object support), while a child's `Agent.create`\n// needs `mcpServers` as a Record<name, config>; resolving names→config per-subagent in local delegation\n// is its own follow-up. Rather than silently drop it (the M26/M32 silent-gate class), it is a typed load\n// error that names the field and points at the alternative.\nfunction rejectMcp(fields: Record<string, FrontmatterValue | undefined>, filename: string): void {\n if (fields.mcp !== undefined) {\n throw new ConfigurationError(\n `Subagent ${filename}: per-subagent \"mcp\" is not yet supported on the local delegation path; declare MCP servers in .theokit/mcp.json (or the parent) instead`,\n { code: \"subagent_mcp_unsupported_local\" },\n );\n }\n}\n\n// model + reasoning_effort — effort rides inside `model.params[thinking]`, so it requires a concrete\n// model id to attach to (a child inheriting the parent's model cannot carry the parent's provider-\n// specific effort param safely).\nfunction resolveModel(\n fields: Record<string, FrontmatterValue | undefined>,\n filename: string,\n): ModelSelection | \"inherit\" | undefined {\n const modelId = asString(fields.model);\n const effort = asString(fields.reasoning_effort);\n // reasoning_effort rides in model.params[thinking], so it needs a CONCRETE model id to attach to.\n // Neither an absent model NOR `model: inherit` can carry it (the inherited id is unknown at load), so\n // both are typed errors rather than a silently-dropped effort — the silent-gate class this guards.\n if (effort !== undefined && (modelId === undefined || modelId === \"inherit\")) {\n throw new ConfigurationError(\n `Subagent ${filename}: reasoning_effort requires a concrete model (effort is a model parameter; an absent model or \"inherit\" cannot carry it)`,\n { code: \"subagent_reasoning_effort_without_model\" },\n );\n }\n if (modelId === undefined) return undefined;\n if (modelId === \"inherit\") return \"inherit\";\n return effort !== undefined\n ? { id: modelId, params: [{ id: \"thinking\", value: effort }] }\n : { id: modelId };\n}\n\n// sandbox: boolean only. A granular mode string (read-only/…) is unsupported by the SDK runtime and is\n// a typed error rather than a silent coercion to a boolean.\nfunction resolveSandbox(\n fields: Record<string, FrontmatterValue | undefined>,\n filename: string,\n): boolean | undefined {\n if (fields.sandbox === undefined) return undefined;\n if (typeof fields.sandbox !== \"boolean\") {\n throw new ConfigurationError(\n `Subagent ${filename}: sandbox must be a boolean (got \"${String(fields.sandbox)}\"); granular sandbox modes are not supported by the runtime`,\n { code: \"subagent_sandbox_not_boolean\" },\n );\n }\n return fields.sandbox;\n}\n\nfunction asString(v: FrontmatterValue | undefined): string | undefined {\n if (typeof v !== \"string\") return undefined;\n // parseSimpleYaml does not strip quotes (documented), and `model`/`reasoning_effort` are fields users\n // habitually quote (`model: \"openai/gpt-4o\"`). Strip a single matching surrounding quote pair so a\n // quoted id/effort does not slip past validation and fail only at the provider.\n const m = /^([\"'])(.*)\\1$/.exec(v);\n return m ? m[2] : v;\n}\n\n/** Accept a YAML list (`string[]`) or a comma/space-separated scalar; trim + drop empties. */\nfunction toStringList(v: FrontmatterValue | undefined): string[] {\n if (Array.isArray(v)) return v.map((t) => t.trim()).filter((t) => t.length > 0);\n if (typeof v === \"string\") {\n return v\n .split(/[\\s,]+/)\n .map((t) => t.trim())\n .filter((t) => t.length > 0);\n }\n return [];\n}\n\n/** Does this file open with a frontmatter block at all? Its ABSENCE means \"not an agent\". */\nfunction hasFrontmatter(raw: string): boolean {\n return /^---\\s*\\n/.test(raw);\n}\n\nfunction splitFrontmatter(raw: string, filename: string): { frontmatter: string; body: string } {\n const match = /^---\\s*\\n([\\s\\S]*?)\\n---\\s*\\n([\\s\\S]*)$/.exec(raw);\n if (match === null) {\n throw new ConfigurationError(`Subagent ${filename} is missing frontmatter`, {\n code: \"subagent_missing_frontmatter\",\n });\n }\n return { frontmatter: match[1] ?? \"\", body: (match[2] ?? \"\").trim() };\n}\n\nfunction parseFrontmatterFields(frontmatter: string): Record<string, FrontmatterValue | undefined> {\n // Preserve the rich YAML value types (boolean/number/string[]): `sandbox: true` and\n // `mcp: [a, b]` are meaningful here, so narrowing everything to string (as the\n // pre-M33 loader did) would drop them. Per-field validation happens in parseSubagentMarkdown.\n return parseSimpleYaml(frontmatter);\n}\n"]}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var os = require('os');
|
|
4
|
+
var path = require('path');
|
|
5
|
+
|
|
6
|
+
// src/internal/persistence/paths.ts
|
|
7
|
+
|
|
8
|
+
// src/internal/runtime/compat/foreign-config-sources.ts
|
|
9
|
+
var THEOKIT_DIR_LITERAL = ".theokit";
|
|
10
|
+
var CLAUDE_DIR_NAME = ".claude";
|
|
11
|
+
var NATIVE_SOURCE = {
|
|
12
|
+
kind: "theokit",
|
|
13
|
+
dirName: THEOKIT_DIR_LITERAL,
|
|
14
|
+
runtimeEnv: () => ({})
|
|
15
|
+
};
|
|
16
|
+
var CLAUDE_CODE_SOURCE = {
|
|
17
|
+
kind: "claude-code",
|
|
18
|
+
dirName: CLAUDE_DIR_NAME,
|
|
19
|
+
runtimeEnv: (cwd) => ({ CLAUDE_PROJECT_DIR: cwd })
|
|
20
|
+
};
|
|
21
|
+
var BY_DIR_NAME = new Map(
|
|
22
|
+
[NATIVE_SOURCE, CLAUDE_CODE_SOURCE].map((a) => [a.dirName, a])
|
|
23
|
+
);
|
|
24
|
+
function adapterForConfigPath(path) {
|
|
25
|
+
for (const segment of path.split(/[\\/]/)) {
|
|
26
|
+
const adapter = BY_DIR_NAME.get(segment);
|
|
27
|
+
if (adapter !== void 0) return adapter;
|
|
28
|
+
}
|
|
29
|
+
return void 0;
|
|
30
|
+
}
|
|
31
|
+
function undefinedVariablesIn(command, supplied, env = process.env) {
|
|
32
|
+
const unquoted = command.replace(/'[^']*'/g, " ");
|
|
33
|
+
const names = /* @__PURE__ */ new Set();
|
|
34
|
+
for (const match of unquoted.matchAll(
|
|
35
|
+
/\$\{([A-Za-z_][A-Za-z0-9_]*)\}|\$([A-Za-z_][A-Za-z0-9_]*)/g
|
|
36
|
+
)) {
|
|
37
|
+
const name = match[1] ?? match[2];
|
|
38
|
+
if (name === void 0) continue;
|
|
39
|
+
if (name in supplied) continue;
|
|
40
|
+
if (env[name] !== void 0) continue;
|
|
41
|
+
names.add(name);
|
|
42
|
+
}
|
|
43
|
+
return [...names];
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// src/internal/persistence/paths.ts
|
|
47
|
+
function getTheokitHome(cwd) {
|
|
48
|
+
const override = process.env.THEOKIT_HOME?.trim();
|
|
49
|
+
if (override !== void 0 && override.length > 0) {
|
|
50
|
+
return override;
|
|
51
|
+
}
|
|
52
|
+
return path.join(cwd, THEOKIT_DIR_LITERAL);
|
|
53
|
+
}
|
|
54
|
+
function projectConfigRoots(cwd) {
|
|
55
|
+
return [path.join(cwd, THEOKIT_DIR_LITERAL), path.join(cwd, CLAUDE_DIR_NAME)];
|
|
56
|
+
}
|
|
57
|
+
function pluginBundleRoots(cwd) {
|
|
58
|
+
return projectConfigRoots(cwd).map((root) => path.join(root, "plugins"));
|
|
59
|
+
}
|
|
60
|
+
function getProfilesRoot() {
|
|
61
|
+
return path.join(os.homedir(), THEOKIT_DIR_LITERAL, "profiles");
|
|
62
|
+
}
|
|
63
|
+
function displayTheokitHome(cwd) {
|
|
64
|
+
const resolved = getTheokitHome(cwd);
|
|
65
|
+
const home = os.homedir();
|
|
66
|
+
if (resolved === home) return "~";
|
|
67
|
+
if (resolved.startsWith(`${home}/`)) {
|
|
68
|
+
return `~${resolved.slice(home.length)}`;
|
|
69
|
+
}
|
|
70
|
+
return resolved;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
exports.adapterForConfigPath = adapterForConfigPath;
|
|
74
|
+
exports.displayTheokitHome = displayTheokitHome;
|
|
75
|
+
exports.getProfilesRoot = getProfilesRoot;
|
|
76
|
+
exports.getTheokitHome = getTheokitHome;
|
|
77
|
+
exports.pluginBundleRoots = pluginBundleRoots;
|
|
78
|
+
exports.projectConfigRoots = projectConfigRoots;
|
|
79
|
+
exports.undefinedVariablesIn = undefinedVariablesIn;
|
|
80
|
+
//# sourceMappingURL=chunk-AKJP2STZ.cjs.map
|
|
81
|
+
//# sourceMappingURL=chunk-AKJP2STZ.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/internal/runtime/compat/foreign-config-sources.ts","../src/internal/persistence/paths.ts"],"names":["join","homedir"],"mappings":"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","file":"chunk-AKJP2STZ.cjs","sourcesContent":["/**\n * The foreign configuration dialects this SDK can read, and what each one PRESUMES.\n *\n * ## Why a registry and not a list of directory names\n *\n * `projectConfigRoots` returned `[\".theokit\", \".claude\"]` — two paths — and that shape is what\n * usetheokit/theokit-sdk#522 fell through. A path says WHERE a file lives. It does not say how the\n * file is parsed, and it does not say what runtime the commands inside it were written against.\n *\n * Claude Code defines `$CLAUDE_PROJECT_DIR` for the hook commands in its `settings.json`, and its\n * documentation tells authors to reach project files through it — an absolute path would break for\n * every other person on the team, so the shape that failed here is the shape upstream recommends.\n * This SDK read the file and ran the command without the variable. `sh` expands an unset variable to\n * the empty string, so\n *\n * bash \"$CLAUDE_PROJECT_DIR/.claude/hooks/guard.sh\" became bash \"/.claude/hooks/guard.sh\"\n *\n * which does not exist, which a hook runner correctly reads as a refusal. Every turn denied, in any\n * repository that also had Claude Code set up, with a message naming a file that was present and\n * executable all along.\n *\n * Importing a format means accepting the contract that format presumes. An adapter is where that\n * contract is written down, so the next dialect (`.codex/` is the obvious one) declares its own\n * instead of inheriting a hole.\n *\n * ## What an adapter deliberately does NOT do\n *\n * It does not make the foreign source trusted, and it does not make its hooks permissive: a script\n * that exits non-zero is still a refusal. It supplies the variables the format's authors were\n * entitled to assume, and nothing else — `env` here is merged over the scrubbed inherit policy by\n * `spawnAndCollect`, so it adds names rather than widening what a child can see.\n *\n * @internal\n */\n\n/**\n * The project config directory literal.\n *\n * Renamed from `THEOKIT_DIR_NAME` in #410. Sharing a name with the (now removed) sovereign env var\n * was the MECHANISM of that defect, not scenery: every grep for the variable landed on that const\n * and looked answered, so \"is it read?\" returned five hits and nobody checked what they were.\n *\n * Lives here rather than in `persistence/paths.ts` because a directory name is one third of what a\n * dialect is — the other two being how it parses and what it presumes — and splitting the three\n * across two modules is what let the third go unwritten.\n */\nexport const THEOKIT_DIR_LITERAL = \".theokit\";\n\n/** The Claude Code CLI's project configuration directory. */\nexport const CLAUDE_DIR_NAME = \".claude\";\n\n/** A configuration dialect this SDK understands. `theokit` is native; the rest are foreign. */\nexport interface ConfigSourceAdapter {\n /** Stable identifier, and what a consumer names to opt in. */\n readonly kind: string;\n /** The project-relative directory the dialect keeps its configuration in. */\n readonly dirName: string;\n /**\n * Variables the dialect's own runtime defines for commands it executes.\n *\n * Empty for the native source: a `.theokit/` hook is written against THIS runtime and inherits it\n * already. Non-empty is what makes a foreign command runnable rather than silently broken.\n */\n runtimeEnv(cwd: string): Record<string, string>;\n}\n\n/** The native source. Always read, never opted into, always first for precedence. */\nexport const NATIVE_SOURCE: ConfigSourceAdapter = {\n kind: \"theokit\",\n dirName: THEOKIT_DIR_LITERAL,\n runtimeEnv: () => ({}),\n};\n\n/**\n * Claude Code.\n *\n * `CLAUDE_PROJECT_DIR` is the documented way for a hook command in `settings.json` to reach a file\n * in the project. Only that one variable is supplied: `$CLAUDE_PLUGIN_ROOT` and the rest of that\n * runtime's surface are NOT defined here, because supplying a name whose value this SDK would have\n * to invent is worse than leaving it unset — an invented root sends a script somewhere real and\n * wrong, where an unset one fails loudly.\n */\nexport const CLAUDE_CODE_SOURCE: ConfigSourceAdapter = {\n kind: \"claude-code\",\n dirName: CLAUDE_DIR_NAME,\n runtimeEnv: (cwd) => ({ CLAUDE_PROJECT_DIR: cwd }),\n};\n\nconst BY_DIR_NAME: ReadonlyMap<string, ConfigSourceAdapter> = new Map(\n [NATIVE_SOURCE, CLAUDE_CODE_SOURCE].map((a) => [a.dirName, a]),\n);\n\n/**\n * The adapter whose directory an absolute config path sits under, or `undefined` for a path that\n * belongs to no registered dialect.\n *\n * Matched on the path SEGMENT rather than with `includes`, so a workspace that happens to live under\n * `/home/me/.claude-backups/repo` does not read as a Claude Code source.\n */\nexport function adapterForConfigPath(path: string): ConfigSourceAdapter | undefined {\n for (const segment of path.split(/[\\\\/]/)) {\n const adapter = BY_DIR_NAME.get(segment);\n if (adapter !== undefined) return adapter;\n }\n return undefined;\n}\n\n/**\n * Variable references in a shell command that nothing will define.\n *\n * The second half of #522, and the half that cost the debugging session. `sh` expands an unset\n * variable to the empty string and says nothing, so the failure surfaces ten characters later as a\n * path: `bash: /.claude/hooks/guard.sh: No such file or directory` — which reads as \"your script is\n * missing\" while the script is present and executable. Nothing in that message contains the name of\n * the variable that was actually missing, so the reader looks in the wrong place.\n *\n * Checked against BOTH the process environment and the variables the dialect supplies, because\n * either is a legitimate source: a hook may reasonably use `$HOME`.\n *\n * ## What it deliberately does not try to be\n *\n * This is not a shell parser. It finds `$NAME` and `${NAME}` outside single quotes, which is the\n * shape a config file's hook commands take. It does NOT understand `${NAME:-default}` (a default\n * makes the variable optional, so it is not reported), assignments earlier in the same command, or\n * variables a sourced script exports. A false NEGATIVE there costs the old behaviour — the confusing\n * path error — and a false positive would deny a hook that would have worked, so the parse errs\n * toward silence and the check only ever ADDS a name to a failure that already happened.\n */\nexport function undefinedVariablesIn(\n command: string,\n supplied: Readonly<Record<string, string>>,\n env: Readonly<Record<string, string | undefined>> = process.env,\n): string[] {\n // Single-quoted spans are literal in `sh`: `echo '$FOO'` prints the dollar sign.\n const unquoted = command.replace(/'[^']*'/g, \" \");\n const names = new Set<string>();\n for (const match of unquoted.matchAll(\n /\\$\\{([A-Za-z_][A-Za-z0-9_]*)\\}|\\$([A-Za-z_][A-Za-z0-9_]*)/g,\n )) {\n const name = match[1] ?? match[2];\n if (name === undefined) continue;\n if (name in supplied) continue;\n if (env[name] !== undefined) continue;\n names.add(name);\n }\n return [...names];\n}\n","/**\n * Path resolution for SDK state files (ADR D60).\n *\n * Theokit anchors state at `<cwd>/.theokit/` by default (per-cwd). An\n * optional `THEOKIT_HOME` environment variable overrides this, enabling\n * test isolation, profile switching, and multi-tenant deployments.\n *\n * Rules:\n * - `getTheokitHome(cwd)` is the canonical resolver **for cwd-anchored state**. Never hardcode\n * `path.join(cwd, \".theokit\")` in callers — use this function so tests\n * and overrides stay consistent.\n *\n * M94 — this comment said \"the ONLY canonical resolver\", and stopped being true: the\n * transcript gained `transcriptRoot()`, which is **home-anchored** (`~/.theokit`) with the same\n * `THEOKIT_HOME` override. The two defaults differ on purpose — unifying would move the\n * transcript of everyone who does NOT set the variable, which is a data migration and not a\n * re-export.\n *\n * A consequence worth writing down: **without `THEOKIT_HOME` the state stays split in two**\n * — registry in `<cwd>/.theokit`, transcript in `~/.theokit`. M94 unifies only for those who set\n * the variable. Unifying both defaults is another milestone's work.\n * - `getProfilesRoot()` is intentionally home-anchored (not affected by\n * `THEOKIT_HOME`) so `theokit profile list` discovers all profiles\n * regardless of which is active.\n * - `displayTheokitHome(cwd)` returns a human-readable path for logs.\n *\n * @internal\n */\n\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\n\nimport { CLAUDE_DIR_NAME, THEOKIT_DIR_LITERAL } from \"../runtime/compat/foreign-config-sources.js\";\n\n// The directory names live with the dialect registry that owns them — a name is one third of what a\n// configuration dialect is, and keeping the three together is what stops the next one shipping\n// without its runtime contract (#522).\n\n/**\n * Resolve the directory cwd-anchored SDK state lives in.\n *\n * `THEOKIT_HOME` wins when it is set and not blank after trimming; the trimmed value is used, and\n * it is used VERBATIM — it is not resolved against `cwd`, so a relative value stays relative and\n * `.theokit` is not appended to it. Otherwise the answer is `<cwd>/.theokit`.\n *\n * The environment is read on every call, so a change to the variable takes effect immediately\n * rather than being frozen at import.\n *\n * This creates nothing and checks nothing: the returned path may not exist, and the caller owns\n * the `mkdir`. Call it instead of writing `join(cwd, \".theokit\")` by hand, or the override stops\n * working for that one call site and tests silently touch the real home.\n *\n * Not the whole story about where state lives — the transcript is home-anchored via\n * `transcriptRoot()`, honoring the same variable but defaulting to `~/.theokit`. With\n * `THEOKIT_HOME` unset, state is genuinely split between two roots.\n *\n * Semver-exempt: reachable via the `@theokit/sdk/internal/persistence` sub-path, which the package\n * declares in `exports` but does NOT cover with its semver contract.\n */\nexport function getTheokitHome(cwd: string): string {\n const override = process.env.THEOKIT_HOME?.trim();\n if (override !== undefined && override.length > 0) {\n return override;\n }\n return join(cwd, THEOKIT_DIR_LITERAL);\n}\n\n/**\n * Every directory a project's configuration may be read from, in precedence order.\n *\n * `.theokit` first, then `.claude`. The order is the whole contract: a project that declares a\n * skill, agent or rule in both means the explicit namespace to win, and a caller merging these\n * roots must therefore keep the FIRST occurrence of a name rather than the last.\n *\n * `.claude` is read because the formats already agree and only the location did not. Measured\n * 2026-08-26: the SKILL.md frontmatter this SDK requires (`name` + `description`) is exactly what\n * the CLI writes, its hook config is the same JSON shape, and 59 of the CLI's agent declarations\n * parse here unchanged. A repository set up for the CLI was failing on the directory name alone.\n *\n * NOT a rename of `.theokit`, and not a migration. Both are read, so nothing that works today stops\n * working — which is why this returns a LIST and not a single resolved answer.\n *\n * Deliberately NOT affected by `THEOKIT_HOME`, and this is the one thing to remember about it.\n * That variable relocates cwd-anchored SDK *state* — sessions, the credential store. A project's\n * *configuration* is a property of the repository, not of where this SDK keeps its state, and the\n * loaders that read these directories have always anchored on `cwd` directly. Honouring the\n * override here would silently move where a project's agents and skills come from, which is a\n * behaviour change wearing the costume of a refactor.\n *\n * Creates nothing and checks nothing; either path may not exist, and the caller owns that.\n *\n * Semver-exempt: reachable via the `@theokit/sdk/internal/persistence` sub-path, which the package\n * declares in `exports` but does NOT cover with its semver contract.\n */\nexport function projectConfigRoots(cwd: string): string[] {\n return [join(cwd, THEOKIT_DIR_LITERAL), join(cwd, CLAUDE_DIR_NAME)];\n}\n\n/**\n * Every directory that may hold a plugin BUNDLE contributed by the Claude Code CLI.\n *\n * A CLI plugin is not a JS entry point — it is a folder whose `skills/` and `agents/` are what it\n * exists to provide. Measured 2026-08-26 on an installed one: seven agents and three skills beside\n * a manifest in `.claude-plugin/plugin.json`. Parsing that manifest and stopping there produced a\n * plugin that loaded and did nothing.\n *\n * Project-scoped deliberately. The CLI also keeps plugins under `~/.claude/plugins/cache`, behind\n * its own installer and enable/disable state — reproducing that is an installation system, not\n * reading a project's configuration, and guessing at someone's enablement would run code they\n * turned off.\n */\nexport function pluginBundleRoots(cwd: string): string[] {\n return projectConfigRoots(cwd).map((root) => join(root, \"plugins\"));\n}\n\n/**\n * The directory holding every profile: always `~/.theokit/profiles`, from `os.homedir()`.\n *\n * Deliberately NOT affected by `THEOKIT_HOME`, which is the one thing to remember about it. If it\n * followed the override, a session pointed at one profile would only be able to see that profile,\n * and `theokit profile list` could never enumerate the rest. Profiles are the thing the override\n * switches between, so their index cannot live behind it.\n *\n * Takes no `cwd` for the same reason. Creates nothing; the path may not exist.\n *\n * Semver-exempt: reachable via the `@theokit/sdk/internal/persistence` sub-path, which the package\n * declares in `exports` but does NOT cover with its semver contract.\n */\nexport function getProfilesRoot(): string {\n return join(homedir(), THEOKIT_DIR_LITERAL, \"profiles\");\n}\n\n/**\n * The same path `getTheokitHome(cwd)` returns, shortened for display: the home directory prefix\n * collapses to `~`, so `/home/ada/.theokit` prints as `~/.theokit`.\n *\n * For humans only — log lines, CLI output, error messages. The result is NOT a usable path: `~`\n * is a shell convention that `fs` does not expand, so passing this to a filesystem call resolves\n * a literal directory named `~` relative to the process cwd. Use `getTheokitHome` for anything\n * that touches disk.\n *\n * Collapsing is a prefix match on the home directory followed by a literal `/`, so a sibling like\n * `/home/adalovelace` is left alone even though `/home/ada` is a string prefix of it. A path\n * outside the home directory comes back unchanged — and so does a Windows path, where the\n * separator is a backslash and the prefix test therefore never matches.\n *\n * Semver-exempt: reachable via the `@theokit/sdk/internal/persistence` sub-path, which the package\n * declares in `exports` but does NOT cover with its semver contract.\n */\nexport function displayTheokitHome(cwd: string): string {\n const resolved = getTheokitHome(cwd);\n const home = homedir();\n if (resolved === home) return \"~\";\n if (resolved.startsWith(`${home}/`)) {\n return `~${resolved.slice(home.length)}`;\n }\n return resolved;\n}\n"]}
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
var chunk3FFAEAUJ_cjs = require('./chunk-3FFAEAUJ.cjs');
|
|
4
4
|
var chunkRMWTPV3M_cjs = require('./chunk-RMWTPV3M.cjs');
|
|
5
5
|
var chunkVLVVJLDH_cjs = require('./chunk-VLVVJLDH.cjs');
|
|
6
|
-
var
|
|
6
|
+
var chunkVCLBZAZU_cjs = require('./chunk-VCLBZAZU.cjs');
|
|
7
7
|
var chunkBV2MWEMV_cjs = require('./chunk-BV2MWEMV.cjs');
|
|
8
8
|
var chunkKQ7TS7WW_cjs = require('./chunk-KQ7TS7WW.cjs');
|
|
9
9
|
var chunkGKEFRLU7_cjs = require('./chunk-GKEFRLU7.cjs');
|
|
@@ -26,8 +26,8 @@ var chunk5HEG4CQH_cjs = require('./chunk-5HEG4CQH.cjs');
|
|
|
26
26
|
var chunkUU36SHFY_cjs = require('./chunk-UU36SHFY.cjs');
|
|
27
27
|
var chunkZF2LDKQQ_cjs = require('./chunk-ZF2LDKQQ.cjs');
|
|
28
28
|
var chunkUALX2J2Q_cjs = require('./chunk-UALX2J2Q.cjs');
|
|
29
|
-
var
|
|
30
|
-
var
|
|
29
|
+
var chunk43ZQRWAP_cjs = require('./chunk-43ZQRWAP.cjs');
|
|
30
|
+
var chunkAKJP2STZ_cjs = require('./chunk-AKJP2STZ.cjs');
|
|
31
31
|
var chunk4CLOXP6H_cjs = require('./chunk-4CLOXP6H.cjs');
|
|
32
32
|
var chunkDXGZ2NUG_cjs = require('./chunk-DXGZ2NUG.cjs');
|
|
33
33
|
var chunk3EE6LVWT_cjs = require('./chunk-3EE6LVWT.cjs');
|
|
@@ -2170,14 +2170,14 @@ async function readState(filePath) {
|
|
|
2170
2170
|
try {
|
|
2171
2171
|
parsed = JSON.parse(raw);
|
|
2172
2172
|
} catch {
|
|
2173
|
-
|
|
2173
|
+
chunkVCLBZAZU_cjs.warnOnce(
|
|
2174
2174
|
"personality-store-json-parse",
|
|
2175
2175
|
"[theokit-sdk] personality.json is malformed; treating as empty"
|
|
2176
2176
|
);
|
|
2177
2177
|
return emptyState();
|
|
2178
2178
|
}
|
|
2179
2179
|
if (!isStateV1(parsed)) {
|
|
2180
|
-
|
|
2180
|
+
chunkVCLBZAZU_cjs.warnOnce(
|
|
2181
2181
|
"personality-store-bad-version",
|
|
2182
2182
|
`[theokit-sdk] personality.json has unknown version; treating as empty (file kept untouched)`
|
|
2183
2183
|
);
|
|
@@ -2208,7 +2208,7 @@ var PersonalityStore = class {
|
|
|
2208
2208
|
try {
|
|
2209
2209
|
await this.#persist(agentId, slug);
|
|
2210
2210
|
} catch (err) {
|
|
2211
|
-
|
|
2211
|
+
chunkVCLBZAZU_cjs.warnOnce(
|
|
2212
2212
|
`personality-store-persist-failure-${agentId}`,
|
|
2213
2213
|
`[theokit-sdk] personality persist failed for ${chunkXL7Q7HB2_cjs.redactSecrets(agentId)}: ${chunkXL7Q7HB2_cjs.redactSecrets(
|
|
2214
2214
|
err.message
|
|
@@ -2225,7 +2225,7 @@ var PersonalityStore = class {
|
|
|
2225
2225
|
try {
|
|
2226
2226
|
state = await readState(filePath);
|
|
2227
2227
|
} catch (err) {
|
|
2228
|
-
|
|
2228
|
+
chunkVCLBZAZU_cjs.warnOnce(
|
|
2229
2229
|
`personality-store-hydrate-failure-${agentId}`,
|
|
2230
2230
|
`[theokit-sdk] personality hydrate failed for ${chunkXL7Q7HB2_cjs.redactSecrets(agentId)}: ${chunkXL7Q7HB2_cjs.redactSecrets(
|
|
2231
2231
|
err.message
|
|
@@ -2254,7 +2254,7 @@ var PersonalityStore = class {
|
|
|
2254
2254
|
});
|
|
2255
2255
|
}
|
|
2256
2256
|
#filePath() {
|
|
2257
|
-
return path.join(
|
|
2257
|
+
return path.join(chunkAKJP2STZ_cjs.getTheokitHome(this.#cwd), FILE_NAME);
|
|
2258
2258
|
}
|
|
2259
2259
|
};
|
|
2260
2260
|
|
|
@@ -2598,6 +2598,8 @@ function spawnAndCollect(options) {
|
|
|
2598
2598
|
settle({ stdout, stderr, exitCode: code, timedOut });
|
|
2599
2599
|
});
|
|
2600
2600
|
if (options.stdin !== void 0 && child.stdin !== null) {
|
|
2601
|
+
child.stdin.on("error", () => {
|
|
2602
|
+
});
|
|
2601
2603
|
child.stdin.end(options.stdin);
|
|
2602
2604
|
}
|
|
2603
2605
|
});
|
|
@@ -2615,7 +2617,7 @@ var HooksExecutor = class {
|
|
|
2615
2617
|
this.config = {};
|
|
2616
2618
|
return;
|
|
2617
2619
|
}
|
|
2618
|
-
this.config = await
|
|
2620
|
+
this.config = await chunkVCLBZAZU_cjs.loadHookConfig(this.cwd);
|
|
2619
2621
|
}
|
|
2620
2622
|
/** Fire every hook registered for `event` and aggregate the decisions. */
|
|
2621
2623
|
async run(payload) {
|
|
@@ -2650,10 +2652,12 @@ var HooksExecutor = class {
|
|
|
2650
2652
|
}
|
|
2651
2653
|
async executeOne(command, payload) {
|
|
2652
2654
|
const timeoutMs = command.timeoutMs ?? 3e4;
|
|
2655
|
+
const env = runtimeEnvFor(command.sourcePath, this.cwd);
|
|
2653
2656
|
const result = await spawnAndCollect({
|
|
2654
2657
|
command: "sh",
|
|
2655
2658
|
args: ["-c", command.command],
|
|
2656
2659
|
cwd: this.cwd,
|
|
2660
|
+
...Object.keys(env).length > 0 ? { env } : {},
|
|
2657
2661
|
timeoutMs,
|
|
2658
2662
|
stdin: JSON.stringify(payload)
|
|
2659
2663
|
});
|
|
@@ -2664,14 +2668,22 @@ var HooksExecutor = class {
|
|
|
2664
2668
|
return { decision: "deny", reason: `Hook spawn failed: ${result.spawnError.message}` };
|
|
2665
2669
|
}
|
|
2666
2670
|
if (result.exitCode !== 0) {
|
|
2671
|
+
const stderr = result.stderr.trim();
|
|
2672
|
+
const base = stderr.length > 0 ? stderr : `Hook exited with code ${result.exitCode}`;
|
|
2673
|
+
const missing = chunkAKJP2STZ_cjs.undefinedVariablesIn(command.command, env);
|
|
2674
|
+
if (missing.length === 0) return { decision: "deny", reason: base };
|
|
2667
2675
|
return {
|
|
2668
2676
|
decision: "deny",
|
|
2669
|
-
reason:
|
|
2677
|
+
reason: `${base} \u2014 this hook came from ${command.sourcePath ?? "an unrecorded source"} and uses ${missing.map((n) => `$${n}`).join(", ")}, which nothing defines here. A variable this runtime does not supply expands to the empty string, so the error above names a path rather than the cause.`
|
|
2670
2678
|
};
|
|
2671
2679
|
}
|
|
2672
2680
|
return parseDecisionFromStdout(result.stdout);
|
|
2673
2681
|
}
|
|
2674
2682
|
};
|
|
2683
|
+
function runtimeEnvFor(sourcePath, cwd) {
|
|
2684
|
+
if (sourcePath === void 0) return {};
|
|
2685
|
+
return chunkAKJP2STZ_cjs.adapterForConfigPath(sourcePath)?.runtimeEnv(cwd) ?? {};
|
|
2686
|
+
}
|
|
2675
2687
|
function parseDecisionFromStdout(stdout) {
|
|
2676
2688
|
const trimmed = stdout.trim();
|
|
2677
2689
|
if (trimmed.length === 0) return { decision: "allow" };
|
|
@@ -2942,8 +2954,8 @@ var SkillsManager = class {
|
|
|
2942
2954
|
}
|
|
2943
2955
|
async refresh() {
|
|
2944
2956
|
const roots = this.skillsDir === void 0 ? [
|
|
2945
|
-
...
|
|
2946
|
-
...(await
|
|
2957
|
+
...chunkAKJP2STZ_cjs.projectConfigRoots(this.cwd).map((root) => path.join(root, "skills")),
|
|
2958
|
+
...(await chunk43ZQRWAP_cjs.pluginBundleDirs(this.cwd)).map((bundle) => path.join(bundle, "skills"))
|
|
2947
2959
|
] : [this.skillsDir];
|
|
2948
2960
|
const discovered = [];
|
|
2949
2961
|
const seen = /* @__PURE__ */ new Set();
|
|
@@ -3448,7 +3460,7 @@ var HISTOGRAM_NAMES = {
|
|
|
3448
3460
|
};
|
|
3449
3461
|
function safeRequire(moduleName) {
|
|
3450
3462
|
try {
|
|
3451
|
-
const r = module$1.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('chunk-
|
|
3463
|
+
const r = module$1.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('chunk-BLTTW3KY.cjs', document.baseURI).href)));
|
|
3452
3464
|
return r(moduleName);
|
|
3453
3465
|
} catch {
|
|
3454
3466
|
return void 0;
|
|
@@ -3676,7 +3688,7 @@ var cachedOtel;
|
|
|
3676
3688
|
function loadOtel() {
|
|
3677
3689
|
if (cachedOtel === void 0) {
|
|
3678
3690
|
try {
|
|
3679
|
-
const r = module$1.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('chunk-
|
|
3691
|
+
const r = module$1.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('chunk-BLTTW3KY.cjs', document.baseURI).href)));
|
|
3680
3692
|
const mod = r("@opentelemetry/api");
|
|
3681
3693
|
cachedOtel = mod;
|
|
3682
3694
|
} catch {
|
|
@@ -4140,7 +4152,7 @@ async function loadContextConfig(cwd) {
|
|
|
4140
4152
|
});
|
|
4141
4153
|
if (mdEntities.length > 0) {
|
|
4142
4154
|
if (fs.existsSync(jsonPath)) {
|
|
4143
|
-
|
|
4155
|
+
chunkVCLBZAZU_cjs.warnOnce(
|
|
4144
4156
|
"context-both-present",
|
|
4145
4157
|
"[theokit-sdk] both .theokit/context/ and .theokit/context.json detected \u2014 using markdown; remove context.json"
|
|
4146
4158
|
);
|
|
@@ -4150,7 +4162,7 @@ async function loadContextConfig(cwd) {
|
|
|
4150
4162
|
};
|
|
4151
4163
|
}
|
|
4152
4164
|
if (!fs.existsSync(jsonPath)) return { sources: [] };
|
|
4153
|
-
|
|
4165
|
+
chunkVCLBZAZU_cjs.warnOnce(
|
|
4154
4166
|
"context-json-deprecated",
|
|
4155
4167
|
"[theokit-sdk] .theokit/context.json is deprecated; migrate to .theokit/context/<name>.md via theokit-migrate-config"
|
|
4156
4168
|
);
|
|
@@ -4286,7 +4298,7 @@ var PluginsManager = class {
|
|
|
4286
4298
|
}
|
|
4287
4299
|
async refresh() {
|
|
4288
4300
|
this.plugins = [];
|
|
4289
|
-
for (const pluginsRoot of
|
|
4301
|
+
for (const pluginsRoot of chunkAKJP2STZ_cjs.pluginBundleRoots(this.cwd)) {
|
|
4290
4302
|
await this.refreshRoot(pluginsRoot);
|
|
4291
4303
|
}
|
|
4292
4304
|
}
|
|
@@ -4308,13 +4320,13 @@ var PluginsManager = class {
|
|
|
4308
4320
|
const jsonPath = path.join(pluginsRoot, folderName, "plugin.json");
|
|
4309
4321
|
const metadata = fs.existsSync(mdPath) ? await loadPluginManifestFromMarkdown(pluginsRoot, folderName) : await loadPluginManifestFromJson(jsonPath, folderName);
|
|
4310
4322
|
if (fs.existsSync(mdPath) && fs.existsSync(jsonPath)) {
|
|
4311
|
-
|
|
4323
|
+
chunkVCLBZAZU_cjs.warnOnce(
|
|
4312
4324
|
`plugin-${folderName}-both`,
|
|
4313
4325
|
`[theokit-sdk] both ${folderName}/PLUGIN.md and ${folderName}/plugin.json detected \u2014 using markdown; remove plugin.json`
|
|
4314
4326
|
);
|
|
4315
4327
|
}
|
|
4316
4328
|
if (!fs.existsSync(mdPath) && fs.existsSync(jsonPath)) {
|
|
4317
|
-
|
|
4329
|
+
chunkVCLBZAZU_cjs.warnOnce(
|
|
4318
4330
|
"plugin-json-deprecated",
|
|
4319
4331
|
"[theokit-sdk] plugin.json manifests are deprecated; migrate to PLUGIN.md via theokit-migrate-config"
|
|
4320
4332
|
);
|
|
@@ -4814,6 +4826,44 @@ var UsageAccumulator = class {
|
|
|
4814
4826
|
}
|
|
4815
4827
|
};
|
|
4816
4828
|
|
|
4829
|
+
// src/internal/agent-loop/replay-messages.ts
|
|
4830
|
+
function replayMessages(prior) {
|
|
4831
|
+
return prior.flatMap(replayTurn);
|
|
4832
|
+
}
|
|
4833
|
+
function replayTurn(msg) {
|
|
4834
|
+
if (msg.parts === void 0 || msg.parts.length === 0) {
|
|
4835
|
+
return [{ role: msg.role, content: [{ type: "text", text: msg.text }] }];
|
|
4836
|
+
}
|
|
4837
|
+
const { own, results } = splitParts(msg.parts);
|
|
4838
|
+
const out = [];
|
|
4839
|
+
if (own.length > 0) out.push({ role: msg.role, content: own });
|
|
4840
|
+
if (results.length > 0) out.push({ role: "user", content: results });
|
|
4841
|
+
return out;
|
|
4842
|
+
}
|
|
4843
|
+
function splitParts(parts) {
|
|
4844
|
+
const own = [];
|
|
4845
|
+
const results = [];
|
|
4846
|
+
for (const part of parts) {
|
|
4847
|
+
if (part.type === "tool_result") {
|
|
4848
|
+
results.push(toToolResult(part));
|
|
4849
|
+
continue;
|
|
4850
|
+
}
|
|
4851
|
+
if (part.type === "text" && part.text.length === 0) continue;
|
|
4852
|
+
own.push({ ...part });
|
|
4853
|
+
}
|
|
4854
|
+
return { own, results };
|
|
4855
|
+
}
|
|
4856
|
+
function toToolResult(part) {
|
|
4857
|
+
return {
|
|
4858
|
+
type: "tool_result",
|
|
4859
|
+
toolUseId: part.toolUseId,
|
|
4860
|
+
// `SessionMessagePart` holds the blocks readonly and `LlmToolResultPart` takes a mutable array:
|
|
4861
|
+
// same elements, different variance, so the copy is the whole conversion.
|
|
4862
|
+
content: typeof part.content === "string" ? part.content : [...part.content],
|
|
4863
|
+
...part.isError === void 0 ? {} : { isError: part.isError }
|
|
4864
|
+
};
|
|
4865
|
+
}
|
|
4866
|
+
|
|
4817
4867
|
// src/internal/agent-loop/live-events.ts
|
|
4818
4868
|
var LiveEventLog = class extends Array {
|
|
4819
4869
|
/**
|
|
@@ -4965,10 +5015,7 @@ async function initLoopContext(inputs) {
|
|
|
4965
5015
|
buildUserEvent(inputs)
|
|
4966
5016
|
]);
|
|
4967
5017
|
if (inputs.onLoopEvent !== void 0) events.subscribe(inputs.onLoopEvent);
|
|
4968
|
-
const priorMessages = (inputs.priorMessages ?? [])
|
|
4969
|
-
role: msg.role,
|
|
4970
|
-
content: [{ type: "text", text: msg.text }]
|
|
4971
|
-
}));
|
|
5018
|
+
const priorMessages = replayMessages(inputs.priorMessages ?? []);
|
|
4972
5019
|
let memorySystemPromptAdditions;
|
|
4973
5020
|
if (inputs.memoryProvider !== void 0 && memoryProviderHandle !== void 0) {
|
|
4974
5021
|
try {
|
|
@@ -7062,7 +7109,7 @@ function applyPersonalityFilter(exposedTools, whitelist, opts) {
|
|
|
7062
7109
|
if (exposedSet.has(name)) continue;
|
|
7063
7110
|
const hint = suggestClosest(name, exposedSet);
|
|
7064
7111
|
const message = hint !== void 0 ? `[theokit-sdk] personality "${opts?.personalityName ?? "?"}" references unknown tool "${name}"; did you mean "${hint}"?` : `[theokit-sdk] personality "${opts?.personalityName ?? "?"}" references unknown tool "${name}" (not exposed)`;
|
|
7065
|
-
|
|
7112
|
+
chunkVCLBZAZU_cjs.warnOnce(
|
|
7066
7113
|
`personality-tool-missing|${opts?.agentId ?? "?"}|${opts?.personalityName ?? "?"}|${name}`,
|
|
7067
7114
|
message
|
|
7068
7115
|
);
|
|
@@ -7787,7 +7834,7 @@ async function reloadLocalAgent(agent) {
|
|
|
7787
7834
|
if (agent.context !== void 0) await agent.context.refresh();
|
|
7788
7835
|
if (agent.skillsManager !== void 0) await agent.skillsManager.refresh();
|
|
7789
7836
|
if (agent.pluginsManager !== void 0) await agent.pluginsManager.refresh();
|
|
7790
|
-
return await
|
|
7837
|
+
return await chunk43ZQRWAP_cjs.loadSubagents(
|
|
7791
7838
|
agent.workspaceCwd,
|
|
7792
7839
|
agent.settingSourcesIncludeProject,
|
|
7793
7840
|
agent.options.agents
|
|
@@ -8879,7 +8926,7 @@ function addEntity(byName, entity, origin, collisionMap) {
|
|
|
8879
8926
|
);
|
|
8880
8927
|
}
|
|
8881
8928
|
if (origin === "project" && collisionMap?.has(fm.name)) {
|
|
8882
|
-
|
|
8929
|
+
chunkVCLBZAZU_cjs.warnOnce(
|
|
8883
8930
|
`personality-collision-${fm.name}`,
|
|
8884
8931
|
`[theokit-sdk] personality "${fm.name}" overridden by project preset`
|
|
8885
8932
|
);
|
|
@@ -8929,14 +8976,14 @@ async function performPersonalitySwitch(args) {
|
|
|
8929
8976
|
|
|
8930
8977
|
// src/internal/local-agent/local-agent-personality-extensions.ts
|
|
8931
8978
|
function resolveActivePersonalityPreset(args) {
|
|
8932
|
-
const forkCtx =
|
|
8979
|
+
const forkCtx = chunkVCLBZAZU_cjs.currentPersonalityContext();
|
|
8933
8980
|
const slug = forkCtx !== void 0 ? forkCtx.slug : args.personalityStore.active(args.agentId);
|
|
8934
8981
|
if (slug === void 0) return void 0;
|
|
8935
8982
|
return args.personalityRegistry?.get(slug);
|
|
8936
8983
|
}
|
|
8937
8984
|
async function ensurePersonalityRegistryIfNeeded(args) {
|
|
8938
8985
|
if (args.personalityRegistry !== void 0) return args.personalityRegistry;
|
|
8939
|
-
const forkSlug =
|
|
8986
|
+
const forkSlug = chunkVCLBZAZU_cjs.currentPersonalityContext()?.slug;
|
|
8940
8987
|
const ownSlug = args.personalityStore.active(args.agentId);
|
|
8941
8988
|
if (forkSlug === void 0 && ownSlug === void 0) return void 0;
|
|
8942
8989
|
return await PersonalityRegistry.load(args.workspaceCwd);
|
|
@@ -8950,8 +8997,8 @@ ${preset.systemPrompt}`;
|
|
|
8950
8997
|
}
|
|
8951
8998
|
async function localAgentUsePersonality(args) {
|
|
8952
8999
|
if (args.disposed) throw new Error("Agent has been disposed");
|
|
8953
|
-
if (
|
|
8954
|
-
|
|
9000
|
+
if (chunkVCLBZAZU_cjs.currentPersonalityContext() !== void 0) {
|
|
9001
|
+
chunkVCLBZAZU_cjs.warnPersonalitySwitchInsideFork(args.agentId);
|
|
8955
9002
|
return null;
|
|
8956
9003
|
}
|
|
8957
9004
|
let registry = args.personalityRegistry;
|
|
@@ -9013,7 +9060,7 @@ async function* localAgentStreamToCompletion(agent, message, options) {
|
|
|
9013
9060
|
async function localAgentFork(parent, options) {
|
|
9014
9061
|
const { forkAgentImpl } = await import('./fork-agent-Y2IK2RYU.cjs');
|
|
9015
9062
|
const { getAgentFacade } = await import('./agent-factory-registry-UU46BUMU.cjs');
|
|
9016
|
-
const { withPersonalityContext } = await import('./context-
|
|
9063
|
+
const { withPersonalityContext } = await import('./context-WFLTTMK3.cjs');
|
|
9017
9064
|
const create = getAgentFacade().create;
|
|
9018
9065
|
return withPersonalityContext(
|
|
9019
9066
|
{ slug: parent.personalitySlugSnapshot, isFork: true },
|
|
@@ -9652,6 +9699,59 @@ function registerRunAsTask(run, agentId, taskOpt, userText) {
|
|
|
9652
9699
|
});
|
|
9653
9700
|
}
|
|
9654
9701
|
|
|
9702
|
+
// src/internal/local-agent/local-option-keys.ts
|
|
9703
|
+
var KNOWN_LOCAL_OPTION_KEYS = /* @__PURE__ */ new Set([
|
|
9704
|
+
"cwd",
|
|
9705
|
+
"settingSources",
|
|
9706
|
+
"sandboxOptions",
|
|
9707
|
+
"sessionDir",
|
|
9708
|
+
"baseDir",
|
|
9709
|
+
"sessionStore"
|
|
9710
|
+
]);
|
|
9711
|
+
var reported = /* @__PURE__ */ new Set();
|
|
9712
|
+
function distance(a, b) {
|
|
9713
|
+
let previous = Array.from({ length: b.length + 1 }, (_, j) => j);
|
|
9714
|
+
for (let i = 1; i <= a.length; i++) {
|
|
9715
|
+
const current = [i, ...new Array(b.length).fill(0)];
|
|
9716
|
+
for (let j = 1; j <= b.length; j++) {
|
|
9717
|
+
const cost = a.charAt(i - 1) === b.charAt(j - 1) ? 0 : 1;
|
|
9718
|
+
current[j] = Math.min(
|
|
9719
|
+
(previous[j] ?? 0) + 1,
|
|
9720
|
+
(current[j - 1] ?? 0) + 1,
|
|
9721
|
+
(previous[j - 1] ?? 0) + cost
|
|
9722
|
+
);
|
|
9723
|
+
}
|
|
9724
|
+
previous = current;
|
|
9725
|
+
}
|
|
9726
|
+
return previous[b.length] ?? 0;
|
|
9727
|
+
}
|
|
9728
|
+
function nearest(key) {
|
|
9729
|
+
let best;
|
|
9730
|
+
let bestDistance = 4;
|
|
9731
|
+
for (const known of KNOWN_LOCAL_OPTION_KEYS) {
|
|
9732
|
+
const d = distance(key.toLowerCase(), known.toLowerCase());
|
|
9733
|
+
if (d < bestDistance) {
|
|
9734
|
+
bestDistance = d;
|
|
9735
|
+
best = known;
|
|
9736
|
+
}
|
|
9737
|
+
}
|
|
9738
|
+
return best;
|
|
9739
|
+
}
|
|
9740
|
+
function reportUnknownLocalOptions(local) {
|
|
9741
|
+
if (local === void 0) return;
|
|
9742
|
+
for (const key of Object.keys(local)) {
|
|
9743
|
+
if (KNOWN_LOCAL_OPTION_KEYS.has(key)) continue;
|
|
9744
|
+
if (reported.has(key)) continue;
|
|
9745
|
+
reported.add(key);
|
|
9746
|
+
const guess = nearest(key);
|
|
9747
|
+
const hint = guess === void 0 ? "" : ` Did you mean \`${guess}\`?`;
|
|
9748
|
+
chunkEG4QM7ZJ_cjs.diag(
|
|
9749
|
+
`[theokit] \`local.${key}\` is not an option this SDK version knows, so it was ignored.${hint}
|
|
9750
|
+
`
|
|
9751
|
+
);
|
|
9752
|
+
}
|
|
9753
|
+
}
|
|
9754
|
+
|
|
9655
9755
|
// src/internal/local-agent/local-agent.ts
|
|
9656
9756
|
var LocalAgent = class {
|
|
9657
9757
|
agentId;
|
|
@@ -9732,6 +9832,7 @@ var LocalAgent = class {
|
|
|
9732
9832
|
if (sub.skills !== void 0) this.skills = sub.skills;
|
|
9733
9833
|
this.pluginsManager = sub.pluginsManager;
|
|
9734
9834
|
if (sub.plugins !== void 0) this.plugins = sub.plugins;
|
|
9835
|
+
reportUnknownLocalOptions(options.local);
|
|
9735
9836
|
this.hooksExecutor = new HooksExecutor(this.workspaceCwd);
|
|
9736
9837
|
this.memoryGlue = new LocalAgentMemory(options, this.workspaceCwd, this.agentId);
|
|
9737
9838
|
this.defaultMemoryProviderForLoop = createLocalAgentMemoryProvider({
|
|
@@ -9760,7 +9861,7 @@ var LocalAgent = class {
|
|
|
9760
9861
|
if (this.pluginsManager !== void 0) await this.pluginsManager.initialize();
|
|
9761
9862
|
const codePlugins = chunkBV2MWEMV_cjs.extractCodePlugins(this.options.plugins);
|
|
9762
9863
|
await this.pluginManagerCode.initialize(codePlugins);
|
|
9763
|
-
this.resolvedSubagents = await
|
|
9864
|
+
this.resolvedSubagents = await chunk43ZQRWAP_cjs.loadSubagents(
|
|
9764
9865
|
this.workspaceCwd,
|
|
9765
9866
|
this.settingSourcesIncludeProject,
|
|
9766
9867
|
this.options.agents
|
|
@@ -10722,7 +10823,7 @@ var Agent = class _Agent {
|
|
|
10722
10823
|
*/
|
|
10723
10824
|
static async describe(agentId) {
|
|
10724
10825
|
const agent = await getRegisteredAgentOrThrow(agentId);
|
|
10725
|
-
const { loadSubagents: loadSubagents2 } = await import('./subagents-loader-
|
|
10826
|
+
const { loadSubagents: loadSubagents2 } = await import('./subagents-loader-UCNO7FUH.cjs');
|
|
10726
10827
|
const settingSources = agent.options.local?.settingSources;
|
|
10727
10828
|
const subagents = await loadSubagents2(
|
|
10728
10829
|
agent.cwd ?? process.cwd(),
|
|
@@ -10753,11 +10854,30 @@ var Agent = class _Agent {
|
|
|
10753
10854
|
};
|
|
10754
10855
|
}
|
|
10755
10856
|
/**
|
|
10756
|
-
* Permanently delete a
|
|
10857
|
+
* Permanently delete a registered agent — local or cloud.
|
|
10858
|
+
*
|
|
10859
|
+
* Backport of #612 (fixed on the 5.x line in `5.3.1`). This HYDRATES before removing, and until it
|
|
10860
|
+
* did the method was a no-op against the persisted registry whenever the agent was not already in
|
|
10861
|
+
* this process's memory. Which is every agent in a freshly started process: `removeRegisteredAgent`
|
|
10862
|
+
* only schedules a save when the entry was in the Map, so `agents.delete()` returned `false`,
|
|
10863
|
+
* nothing was scheduled, and `flushRegistrySaves()` flushed an empty queue. The entry survived and
|
|
10864
|
+
* this returned normally, so a caller had no way to notice.
|
|
10865
|
+
*
|
|
10866
|
+
* Every neighbouring mutator already did this — `rename` and `archive` reach
|
|
10867
|
+
* `getRegisteredAgentOrThrow`, which hydrates on a miss. `delete` was the only one that did not.
|
|
10868
|
+
*
|
|
10869
|
+
* `options.cwd` is read rather than defaulted away: it is declared on `AgentOperationOptions`, and
|
|
10870
|
+
* hydrating `process.cwd()` unconditionally is an option that compiles and does nothing, on the one
|
|
10871
|
+
* path that is supposed to remove data.
|
|
10872
|
+
*
|
|
10873
|
+
* Deleting an unknown id still resolves rather than throwing, deliberately — matching 5.x. It is a
|
|
10874
|
+
* breaking change for callers that delete idempotently, and an entry and its transcript can
|
|
10875
|
+
* legitimately outlive one another in both directions.
|
|
10757
10876
|
*
|
|
10758
10877
|
* @public
|
|
10759
10878
|
*/
|
|
10760
|
-
static async delete(agentId,
|
|
10879
|
+
static async delete(agentId, options = {}) {
|
|
10880
|
+
await hydrateRegistryFromDisk(options.cwd ?? process.cwd());
|
|
10761
10881
|
removeRegisteredAgent(agentId);
|
|
10762
10882
|
await flushRegistrySaves();
|
|
10763
10883
|
}
|
|
@@ -10807,5 +10927,5 @@ exports.computeCost = computeCost;
|
|
|
10807
10927
|
exports.generateCronId = generateCronId;
|
|
10808
10928
|
exports.getPricingEntry = getPricingEntry;
|
|
10809
10929
|
exports.openRouterMemoryEmbeddingProviderAdapter = openRouterMemoryEmbeddingProviderAdapter;
|
|
10810
|
-
//# sourceMappingURL=chunk-
|
|
10811
|
-
//# sourceMappingURL=chunk-
|
|
10930
|
+
//# sourceMappingURL=chunk-BLTTW3KY.cjs.map
|
|
10931
|
+
//# sourceMappingURL=chunk-BLTTW3KY.cjs.map
|