@theokit/sdk 5.5.0 → 5.6.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 +601 -0
- package/dist/{agent-YWSIHHFM.cjs → agent-47NS6ZVL.cjs} +13 -13
- package/dist/{agent-YWSIHHFM.cjs.map → agent-47NS6ZVL.cjs.map} +1 -1
- package/dist/{agent-DyB_lzrx.d.cts → agent-82d_DrCL.d.cts} +11 -2
- package/dist/{agent-CjMVbhhY.d.ts → agent-G6g-uwcB.d.ts} +11 -2
- package/dist/{agent-G3T7Q3SQ.js → agent-JJZM2VIK.js} +12 -12
- package/dist/{agent-G3T7Q3SQ.js.map → agent-JJZM2VIK.js.map} +1 -1
- package/dist/{chunk-ODBID5TG.js → chunk-2UXQASTX.js} +225 -30
- package/dist/chunk-2UXQASTX.js.map +1 -0
- package/dist/{chunk-VPK6PHIE.cjs → chunk-52FDUJSV.cjs} +8 -8
- package/dist/{chunk-VPK6PHIE.cjs.map → chunk-52FDUJSV.cjs.map} +1 -1
- package/dist/{chunk-2XRAWOZZ.js → chunk-5NELQ6LB.js} +65 -3
- package/dist/chunk-5NELQ6LB.js.map +1 -0
- package/dist/{chunk-VY6NKMOA.cjs → chunk-7IZKTQ5G.cjs} +34 -6
- package/dist/chunk-7IZKTQ5G.cjs.map +1 -0
- package/dist/{chunk-7SZAV6QG.js → chunk-7MMTZBTT.js} +3 -3
- package/dist/{chunk-7SZAV6QG.js.map → chunk-7MMTZBTT.js.map} +1 -1
- package/dist/{chunk-SADXXGWU.js → chunk-BZ3YMAMP.js} +3 -3
- package/dist/{chunk-NQTNSHSB.cjs.map → chunk-BZ3YMAMP.js.map} +1 -1
- package/dist/{chunk-LX7SEXOQ.js → chunk-CA5VUAP3.js} +25 -7
- package/dist/chunk-CA5VUAP3.js.map +1 -0
- package/dist/{chunk-IU5N5224.cjs → chunk-EIOMN5VA.cjs} +8 -8
- package/dist/chunk-EIOMN5VA.cjs.map +1 -0
- package/dist/{chunk-M3ZGRGOG.js → chunk-FPIY5CLV.js} +3 -3
- package/dist/{chunk-M3ZGRGOG.js.map → chunk-FPIY5CLV.js.map} +1 -1
- package/dist/{chunk-UKJJRU7C.cjs → chunk-GCHZMH42.cjs} +283 -86
- package/dist/chunk-GCHZMH42.cjs.map +1 -0
- package/dist/{chunk-NQTNSHSB.cjs → chunk-GFFBXSQT.cjs} +5 -5
- package/dist/chunk-GFFBXSQT.cjs.map +1 -0
- package/dist/{chunk-2ZLQZHZC.cjs → chunk-HG4UN4MN.cjs} +4 -4
- package/dist/{chunk-2ZLQZHZC.cjs.map → chunk-HG4UN4MN.cjs.map} +1 -1
- package/dist/{chunk-N6OOOYFZ.js → chunk-HUDNLFY4.js} +4 -4
- package/dist/chunk-HUDNLFY4.js.map +1 -0
- package/dist/{chunk-LOHMT36V.cjs → chunk-LD6HASA5.cjs} +65 -2
- package/dist/chunk-LD6HASA5.cjs.map +1 -0
- package/dist/{chunk-QATRS7JD.cjs → chunk-MYJGWS2J.cjs} +26 -8
- package/dist/chunk-MYJGWS2J.cjs.map +1 -0
- package/dist/{chunk-S6B5XYC3.js → chunk-N2KAIZ5D.js} +33 -6
- package/dist/chunk-N2KAIZ5D.js.map +1 -0
- package/dist/{chunk-HW7SEELD.cjs → chunk-QRVS2PRE.cjs} +31 -8
- package/dist/chunk-QRVS2PRE.cjs.map +1 -0
- package/dist/{chunk-AYA65JA5.cjs → chunk-RWPLWMCZ.cjs} +25 -9
- package/dist/chunk-RWPLWMCZ.cjs.map +1 -0
- package/dist/{chunk-WS5ULCL4.js → chunk-STGSMJMJ.js} +3 -3
- package/dist/{chunk-WS5ULCL4.js.map → chunk-STGSMJMJ.js.map} +1 -1
- package/dist/{chunk-O7L7M42F.js → chunk-T3ZDEYTJ.js} +21 -5
- package/dist/chunk-T3ZDEYTJ.js.map +1 -0
- package/dist/{chunk-43YXGD3P.cjs → chunk-TY56BKSK.cjs} +8 -4
- package/dist/chunk-TY56BKSK.cjs.map +1 -0
- package/dist/chunk-UOLBAPDM.js +66 -0
- package/dist/chunk-UOLBAPDM.js.map +1 -0
- package/dist/{chunk-Z2JFX372.cjs → chunk-VUHXC74Q.cjs} +15 -15
- package/dist/{chunk-Z2JFX372.cjs.map → chunk-VUHXC74Q.cjs.map} +1 -1
- package/dist/{chunk-NSLHPAC7.js → chunk-X7EUUHXU.js} +6 -5
- package/dist/chunk-X7EUUHXU.js.map +1 -0
- package/dist/context/index.cjs +7 -7
- package/dist/context/index.js +3 -3
- package/dist/{context-JTGSBJT6.cjs → context-HR4KMXMA.cjs} +7 -7
- package/dist/{context-JTGSBJT6.cjs.map → context-HR4KMXMA.cjs.map} +1 -1
- package/dist/context-J5BJ3LBS.js +6 -0
- package/dist/{context-3HPU754C.js.map → context-J5BJ3LBS.js.map} +1 -1
- package/dist/{cron-Bgivg88c.d.cts → cron-DWv69ZSD.d.cts} +1 -1
- package/dist/{cron-CNUa7PDo.d.ts → cron-GynWtAax.d.ts} +1 -1
- package/dist/cron.cjs +12 -12
- package/dist/cron.d.cts +2 -2
- package/dist/cron.d.ts +2 -2
- package/dist/cron.js +11 -11
- package/dist/eval.cjs +11 -11
- package/dist/eval.js +10 -10
- package/dist/{index-manager-W7FDMGEG.js → index-manager-27WLNQEE.js} +5 -5
- package/dist/{index-manager-W7FDMGEG.js.map → index-manager-27WLNQEE.js.map} +1 -1
- package/dist/{index-manager-3UNPYH34.cjs → index-manager-BBHDKMQS.cjs} +6 -6
- package/dist/{index-manager-3UNPYH34.cjs.map → index-manager-BBHDKMQS.cjs.map} +1 -1
- package/dist/index.cjs +274 -40
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +168 -5
- package/dist/index.d.ts +168 -5
- package/dist/index.js +246 -23
- package/dist/index.js.map +1 -1
- package/dist/internal/memory/storage/index.cjs +32 -32
- package/dist/internal/memory/storage/index.js +3 -3
- package/dist/internal/memory/storage/memory-root.d.cts +27 -0
- package/dist/internal/memory/storage/memory-root.d.ts +27 -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 +17 -4
- package/dist/internal/runtime/compat/managed-settings.d.ts +80 -0
- package/dist/internal/runtime/context/context-discovery-runner.d.ts +14 -0
- package/dist/internal/runtime/context/context-discovery.d.ts +37 -0
- package/dist/internal/runtime/context/context-manager.d.ts +21 -1
- package/dist/internal/runtime/context/yaml-frontmatter.d.ts +6 -3
- package/dist/internal/runtime/hooks/hooks-executor.d.ts +13 -1
- package/dist/internal/runtime/hooks/hooks-source.d.ts +36 -1
- package/dist/internal/runtime/skills/discover-skills.d.ts +4 -0
- package/dist/project.cjs +3 -3
- package/dist/project.js +1 -1
- package/dist/skills.cjs +5 -5
- package/dist/skills.js +2 -2
- package/dist/subagents-loader-CJFYQQU2.js +7 -0
- package/dist/{subagents-loader-AIVDQ2D5.js.map → subagents-loader-CJFYQQU2.js.map} +1 -1
- package/dist/subagents-loader-MOO7DC4E.cjs +16 -0
- package/dist/{subagents-loader-DN4LETGL.cjs.map → subagents-loader-MOO7DC4E.cjs.map} +1 -1
- package/dist/subagents-loader.cjs +4 -4
- package/dist/subagents-loader.d.cts +1 -1
- package/dist/subagents-loader.d.ts +1 -1
- package/dist/subagents-loader.js +3 -3
- package/dist/types/agent.d.ts +6 -1
- package/docs/error-codes.md +20 -18
- package/docs/harness-capability-map.md +9 -1
- package/package.json +1 -1
- package/dist/chunk-2XRAWOZZ.js.map +0 -1
- package/dist/chunk-43YXGD3P.cjs.map +0 -1
- package/dist/chunk-AYA65JA5.cjs.map +0 -1
- package/dist/chunk-HW7SEELD.cjs.map +0 -1
- package/dist/chunk-IU5N5224.cjs.map +0 -1
- package/dist/chunk-JNAA4G4H.js +0 -43
- package/dist/chunk-JNAA4G4H.js.map +0 -1
- package/dist/chunk-LOHMT36V.cjs.map +0 -1
- package/dist/chunk-LX7SEXOQ.js.map +0 -1
- package/dist/chunk-N6OOOYFZ.js.map +0 -1
- package/dist/chunk-NSLHPAC7.js.map +0 -1
- package/dist/chunk-O7L7M42F.js.map +0 -1
- package/dist/chunk-ODBID5TG.js.map +0 -1
- package/dist/chunk-QATRS7JD.cjs.map +0 -1
- package/dist/chunk-S6B5XYC3.js.map +0 -1
- package/dist/chunk-SADXXGWU.js.map +0 -1
- package/dist/chunk-UKJJRU7C.cjs.map +0 -1
- package/dist/chunk-VY6NKMOA.cjs.map +0 -1
- package/dist/context-3HPU754C.js +0 -6
- package/dist/subagents-loader-AIVDQ2D5.js +0 -7
- package/dist/subagents-loader-DN4LETGL.cjs +0 -16
package/dist/project.cjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
3
|
+
var chunkLD6HASA5_cjs = require('./chunk-LD6HASA5.cjs');
|
|
4
4
|
var chunkJLRLCBJ4_cjs = require('./chunk-JLRLCBJ4.cjs');
|
|
5
5
|
var chunkJ7J7J2GN_cjs = require('./chunk-J7J7J2GN.cjs');
|
|
6
6
|
require('./chunk-6LHQPOMI.cjs');
|
|
@@ -11,7 +11,7 @@ var DEFAULT_FILENAME = "THEO.md";
|
|
|
11
11
|
async function readProjectInstructions(cwd, options) {
|
|
12
12
|
const filename = options?.filename ?? DEFAULT_FILENAME;
|
|
13
13
|
const scope = options?.scope ?? "nearest";
|
|
14
|
-
const paths =
|
|
14
|
+
const paths = chunkLD6HASA5_cjs.walkUpForFile(cwd, filename, options?.stopDir);
|
|
15
15
|
const files = [];
|
|
16
16
|
for (const path of paths) {
|
|
17
17
|
try {
|
|
@@ -30,7 +30,7 @@ function reduceContent(files, scope) {
|
|
|
30
30
|
}
|
|
31
31
|
async function writeProjectInstructions(cwd, content, options) {
|
|
32
32
|
const filename = options?.filename ?? DEFAULT_FILENAME;
|
|
33
|
-
if (!
|
|
33
|
+
if (!chunkLD6HASA5_cjs.isSafePattern(filename)) {
|
|
34
34
|
throw new chunkJ7J7J2GN_cjs.ConfigurationError(
|
|
35
35
|
`writeProjectInstructions: unsafe filename ${JSON.stringify(filename)} (no path traversal, separators, or absolute paths)`,
|
|
36
36
|
{ code: "unsafe_filename" }
|
package/dist/project.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { walkUpForFile, isSafePattern } from './chunk-
|
|
1
|
+
import { walkUpForFile, isSafePattern } from './chunk-5NELQ6LB.js';
|
|
2
2
|
import { replaceFileAtomic } from './chunk-3JHIFQ4I.js';
|
|
3
3
|
import { ConfigurationError } from './chunk-ALUN2B4W.js';
|
|
4
4
|
import './chunk-CZJ6Q7CW.js';
|
package/dist/skills.cjs
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
3
|
+
var chunkMYJGWS2J_cjs = require('./chunk-MYJGWS2J.cjs');
|
|
4
4
|
require('./chunk-7A6535RA.cjs');
|
|
5
5
|
require('./chunk-SA6K24NB.cjs');
|
|
6
|
-
require('./chunk-
|
|
6
|
+
require('./chunk-QRVS2PRE.cjs');
|
|
7
7
|
require('./chunk-J7J7J2GN.cjs');
|
|
8
8
|
require('./chunk-6LHQPOMI.cjs');
|
|
9
9
|
|
|
@@ -11,15 +11,15 @@ require('./chunk-6LHQPOMI.cjs');
|
|
|
11
11
|
|
|
12
12
|
Object.defineProperty(exports, "buildSkillsBlock", {
|
|
13
13
|
enumerable: true,
|
|
14
|
-
get: function () { return
|
|
14
|
+
get: function () { return chunkMYJGWS2J_cjs.buildSkillsBlock; }
|
|
15
15
|
});
|
|
16
16
|
Object.defineProperty(exports, "discoverSkills", {
|
|
17
17
|
enumerable: true,
|
|
18
|
-
get: function () { return
|
|
18
|
+
get: function () { return chunkMYJGWS2J_cjs.discoverSkills; }
|
|
19
19
|
});
|
|
20
20
|
Object.defineProperty(exports, "loadSkillInstructions", {
|
|
21
21
|
enumerable: true,
|
|
22
|
-
get: function () { return
|
|
22
|
+
get: function () { return chunkMYJGWS2J_cjs.loadSkillInstructions; }
|
|
23
23
|
});
|
|
24
24
|
//# sourceMappingURL=skills.cjs.map
|
|
25
25
|
//# sourceMappingURL=skills.cjs.map
|
package/dist/skills.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
export { buildSkillsBlock, discoverSkills, loadSkillInstructions } from './chunk-
|
|
1
|
+
export { buildSkillsBlock, discoverSkills, loadSkillInstructions } from './chunk-CA5VUAP3.js';
|
|
2
2
|
import './chunk-EH6XD3FY.js';
|
|
3
3
|
import './chunk-UKMBRMGT.js';
|
|
4
|
-
import './chunk-
|
|
4
|
+
import './chunk-UOLBAPDM.js';
|
|
5
5
|
import './chunk-ALUN2B4W.js';
|
|
6
6
|
import './chunk-CZJ6Q7CW.js';
|
|
7
7
|
//# sourceMappingURL=skills.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export { loadSubagents } from './chunk-T3ZDEYTJ.js';
|
|
2
|
+
import './chunk-X7EUUHXU.js';
|
|
3
|
+
import './chunk-UOLBAPDM.js';
|
|
4
|
+
import './chunk-ALUN2B4W.js';
|
|
5
|
+
import './chunk-CZJ6Q7CW.js';
|
|
6
|
+
//# sourceMappingURL=subagents-loader-CJFYQQU2.js.map
|
|
7
|
+
//# sourceMappingURL=subagents-loader-CJFYQQU2.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":[],"names":[],"mappings":"","file":"subagents-loader-
|
|
1
|
+
{"version":3,"sources":[],"names":[],"mappings":"","file":"subagents-loader-CJFYQQU2.js"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var chunkRWPLWMCZ_cjs = require('./chunk-RWPLWMCZ.cjs');
|
|
4
|
+
require('./chunk-TY56BKSK.cjs');
|
|
5
|
+
require('./chunk-QRVS2PRE.cjs');
|
|
6
|
+
require('./chunk-J7J7J2GN.cjs');
|
|
7
|
+
require('./chunk-6LHQPOMI.cjs');
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
Object.defineProperty(exports, "loadSubagents", {
|
|
12
|
+
enumerable: true,
|
|
13
|
+
get: function () { return chunkRWPLWMCZ_cjs.loadSubagents; }
|
|
14
|
+
});
|
|
15
|
+
//# sourceMappingURL=subagents-loader-MOO7DC4E.cjs.map
|
|
16
|
+
//# sourceMappingURL=subagents-loader-MOO7DC4E.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":[],"names":[],"mappings":"","file":"subagents-loader-
|
|
1
|
+
{"version":3,"sources":[],"names":[],"mappings":"","file":"subagents-loader-MOO7DC4E.cjs"}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
4
|
-
require('./chunk-
|
|
5
|
-
require('./chunk-
|
|
3
|
+
var chunkRWPLWMCZ_cjs = require('./chunk-RWPLWMCZ.cjs');
|
|
4
|
+
require('./chunk-TY56BKSK.cjs');
|
|
5
|
+
require('./chunk-QRVS2PRE.cjs');
|
|
6
6
|
var chunkJ7J7J2GN_cjs = require('./chunk-J7J7J2GN.cjs');
|
|
7
7
|
require('./chunk-6LHQPOMI.cjs');
|
|
8
8
|
|
|
@@ -23,7 +23,7 @@ function resolveSources(options) {
|
|
|
23
23
|
}
|
|
24
24
|
async function discoverSubagents(cwd, options) {
|
|
25
25
|
const sources = resolveSources(options);
|
|
26
|
-
return
|
|
26
|
+
return chunkRWPLWMCZ_cjs.loadSubagents(cwd, sources.includes("project"), void 0, options?.compatSources ?? []);
|
|
27
27
|
}
|
|
28
28
|
async function loadSubagentDefinition(name, cwd, options) {
|
|
29
29
|
return (await discoverSubagents(cwd, options))[name];
|
package/dist/subagents-loader.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { loadSubagents } from './chunk-
|
|
2
|
-
import './chunk-
|
|
3
|
-
import './chunk-
|
|
1
|
+
import { loadSubagents } from './chunk-T3ZDEYTJ.js';
|
|
2
|
+
import './chunk-X7EUUHXU.js';
|
|
3
|
+
import './chunk-UOLBAPDM.js';
|
|
4
4
|
import { ConfigurationError } from './chunk-ALUN2B4W.js';
|
|
5
5
|
import './chunk-CZJ6Q7CW.js';
|
|
6
6
|
|
package/dist/types/agent.d.ts
CHANGED
|
@@ -40,9 +40,14 @@ export type CompatSource = "claude-code" | "theokit" | CompatSourceAdapter;
|
|
|
40
40
|
* Reusing the skills you already wrote for another product is a reasonable thing to want, and it is
|
|
41
41
|
* not a reason to hand that product's directory the right to run commands.
|
|
42
42
|
*
|
|
43
|
+
* `context` is the foreign root's INSTRUCTIONS — `.claude/rules/*.md`. Same risk class as `skills`:
|
|
44
|
+
* text a cloned repository wrote, entering the system prompt as if the consumer had written it. It
|
|
45
|
+
* was missing until usetheokit/theokit-sdk#652, so the four surfaces above failed closed while this
|
|
46
|
+
* one was admitted by a path that consulted no grant at all.
|
|
47
|
+
*
|
|
43
48
|
* @public
|
|
44
49
|
*/
|
|
45
|
-
export type CompatSurface = "hooks" | "plugins" | "skills" | "subagents";
|
|
50
|
+
export type CompatSurface = "context" | "hooks" | "plugins" | "skills" | "subagents";
|
|
46
51
|
/**
|
|
47
52
|
* A foreign source admitted to named surfaces only.
|
|
48
53
|
*
|
package/docs/error-codes.md
CHANGED
|
@@ -6,7 +6,7 @@ Branch on `code`, never on the message: messages carry context (an id, a path, a
|
|
|
6
6
|
|
|
7
7
|
**Transport codes vs the rest.** `ErrorCode` in `errors.ts` is the small canonical union a provider failure maps onto — the codes marked *transport* below. Everything else is raised by a specific subsystem at a specific place, and a `catch` that only handles the union will meet them anyway.
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
243 distinct code(s).
|
|
10
10
|
|
|
11
11
|
| Code | Kind | Raised by | Sites |
|
|
12
12
|
|---|---|---|---|
|
|
@@ -47,18 +47,18 @@ Branch on `code`, never on the message: messages carry context (an id, a path, a
|
|
|
47
47
|
| `cloud_stdio_cwd_rejected` | domain | ConfigurationError | `packages/sdk/src/internal/runtime/validation/validate-agent-options.ts:121` |
|
|
48
48
|
| `compression_failed` | domain | — | `packages/sdk/src/internal/runtime/compression/compression-summarizer.ts:41` |
|
|
49
49
|
| `compression_model_unresolved` | domain | — | `packages/sdk/src/internal/runtime/compression/compression-model-registry.ts:102` +1 |
|
|
50
|
-
| `context_config_shape` | domain | ConfigurationError | `packages/sdk/src/internal/runtime/context/context-manager.ts:
|
|
50
|
+
| `context_config_shape` | domain | ConfigurationError | `packages/sdk/src/internal/runtime/context/context-manager.ts:288` |
|
|
51
51
|
| `context_frontmatter_invalid` | domain | ConfigurationError | `packages/sdk/src/internal/runtime/context/context-frontmatter.ts:38` |
|
|
52
|
-
| `context_json_invalid` | domain | ConfigurationError | `packages/sdk/src/internal/runtime/context/context-manager.ts:
|
|
53
|
-
| `context_read_error` | domain | ConfigurationError | `packages/sdk/src/internal/runtime/context/context-manager.ts:
|
|
54
|
-
| `context_sources_shape` | domain | ConfigurationError | `packages/sdk/src/internal/runtime/context/context-manager.ts:
|
|
52
|
+
| `context_json_invalid` | domain | ConfigurationError | `packages/sdk/src/internal/runtime/context/context-manager.ts:282` |
|
|
53
|
+
| `context_read_error` | domain | ConfigurationError | `packages/sdk/src/internal/runtime/context/context-manager.ts:269` |
|
|
54
|
+
| `context_sources_shape` | domain | ConfigurationError | `packages/sdk/src/internal/runtime/context/context-manager.ts:309` |
|
|
55
55
|
| `credential_pool_ambiguous` | domain | ConfigurationError | `packages/sdk/src/internal/runtime/validation/validate-agent-options.ts:68` +1 |
|
|
56
56
|
| `credential_pool_empty` | domain | ConfigurationError | `packages/sdk/src/internal/llm/credential-pool.ts:91` |
|
|
57
57
|
| `cron_ambiguous_target` | domain | ConfigurationError | `packages/sdk/src/cron.ts:215` |
|
|
58
58
|
| `cron_missing_message` | domain | ConfigurationError | `packages/sdk/src/cron.ts:233` +1 |
|
|
59
59
|
| `cron_no_target` | domain | ConfigurationError | `packages/sdk/src/cron.ts:221` +1 |
|
|
60
60
|
| `cron_workflow_message` | domain | ConfigurationError | `packages/sdk/src/cron.ts:227` |
|
|
61
|
-
| `duplicate_skill_name` | domain | ConfigurationError | `packages/sdk/src/define-skill-read-tool.ts:
|
|
61
|
+
| `duplicate_skill_name` | domain | ConfigurationError | `packages/sdk/src/define-skill-read-tool.ts:155` |
|
|
62
62
|
| `duplicate_tool_name` | domain | ConfigurationError | `packages/sdk/src/internal/runtime/validation/validate-agent-options.ts:201` |
|
|
63
63
|
| `effective_tools_expected_options` | domain | ConfigurationError | `packages/sdk/src/internal/runtime/validation/effective-tools.ts:102` +1 |
|
|
64
64
|
| `embedding_dimension_mismatch` | domain | ConfigurationError | `packages/sdk/src/internal/memory/lance-index.ts:146` +1 |
|
|
@@ -79,10 +79,11 @@ Branch on `code`, never on the message: messages carry context (an id, a path, a
|
|
|
79
79
|
| `handoff_target_required` | domain | ConfigurationError | `packages/sdk-handoff/src/handoff.ts:111` |
|
|
80
80
|
| `hitl_timeout` | domain | HitlTimeoutError | `packages/sdk/src/internal/runtime/tools/hitl-middleware.ts:42` +1 |
|
|
81
81
|
| `hook_denied` | domain | ConfigurationError | `packages/sdk/src/internal/local-agent/local-agent.ts:454` |
|
|
82
|
-
| `hooks_invalid_command` | domain | ConfigurationError | `packages/sdk/src/internal/runtime/hooks/hooks-source.ts:
|
|
83
|
-
| `hooks_json_invalid` | domain | ConfigurationError | `packages/sdk/src/internal/runtime/hooks/hooks-source.ts:
|
|
84
|
-
| `hooks_read_error` | domain | ConfigurationError | `packages/sdk/src/internal/runtime/hooks/hooks-source.ts:
|
|
85
|
-
| `
|
|
82
|
+
| `hooks_invalid_command` | domain | ConfigurationError | `packages/sdk/src/internal/runtime/hooks/hooks-source.ts:406` |
|
|
83
|
+
| `hooks_json_invalid` | domain | ConfigurationError | `packages/sdk/src/internal/runtime/hooks/hooks-source.ts:252` +2 |
|
|
84
|
+
| `hooks_read_error` | domain | ConfigurationError | `packages/sdk/src/internal/runtime/hooks/hooks-source.ts:243` |
|
|
85
|
+
| `hooks_unsupported_field` | domain | ConfigurationError | `packages/sdk/src/internal/runtime/hooks/hooks-source.ts:384` |
|
|
86
|
+
| `hooks_unsupported_type` | domain | ConfigurationError | `packages/sdk/src/internal/runtime/hooks/hooks-source.ts:400` |
|
|
86
87
|
| `interactive_unavailable` | domain | InteractiveUnavailableError | `packages/sdk/src/interactive/types.ts:28` +1 |
|
|
87
88
|
| `INTERNAL_SERVER_ERROR` | domain | — | `packages/sdk/src/server/errors-envelope.ts:100` |
|
|
88
89
|
| `invalid_argument` | domain | TheokitAgentError | `packages/sdk/src/compaction.ts:79` |
|
|
@@ -99,7 +100,7 @@ Branch on `code`, never on the message: messages carry context (an id, a path, a
|
|
|
99
100
|
| `invalid_input` | domain | MemoryAdapterError | `packages/memory-honcho/src/adapter.ts:98` +9 |
|
|
100
101
|
| `invalid_max_iterations` | domain | ConfigurationError | `packages/sdk/src/internal/local-agent/real-local-run.ts:71` |
|
|
101
102
|
| `invalid_memory_backend` | domain | ConfigurationError | `packages/sdk/src/internal/memory/index-manager-dispatch.ts:24` +1 |
|
|
102
|
-
| `invalid_memory_directory` | domain | ConfigurationError | `packages/sdk/src/internal/memory/storage/memory-root.ts:
|
|
103
|
+
| `invalid_memory_directory` | domain | ConfigurationError | `packages/sdk/src/internal/memory/storage/memory-root.ts:151` |
|
|
103
104
|
| `invalid_memory_kind` | domain | ConfigurationError | `packages/sdk/src/internal/memory/storage/markdown-store.ts:206` |
|
|
104
105
|
| `invalid_model_selection` | domain | ConfigurationError | `packages/sdk/src/internal/runtime/model-selection.ts:21` |
|
|
105
106
|
| `invalid_processor_options` | domain | ConfigurationError | `packages/sdk/src/built-in-processors.ts:86` |
|
|
@@ -136,7 +137,7 @@ Branch on `code`, never on the message: messages carry context (an id, a path, a
|
|
|
136
137
|
| `migration_destination_exists` | domain | ConfigurationError | `packages/sdk/src/internal/memory/migrate-sqlite-to-lance.ts:159` +1 |
|
|
137
138
|
| `missing_api_key` | domain | AuthenticationError, ConfigurationError | `packages/sdk/src/internal/agent/helpers.ts:215` +2 |
|
|
138
139
|
| `missing_credential` | domain | AuthenticationError | `packages/sdk/src/internal/providers/builtin/openai-chatgpt.ts:72` |
|
|
139
|
-
| `missing_frontmatter` | domain | ConfigurationError | `packages/sdk/src/internal/runtime/skills/skill-frontmatter.ts:
|
|
140
|
+
| `missing_frontmatter` | domain | ConfigurationError | `packages/sdk/src/internal/runtime/skills/skill-frontmatter.ts:88` |
|
|
140
141
|
| `missing_model` | domain | ConfigurationError | `packages/sdk/src/internal/runtime/validation/validate-agent-options.ts:35` |
|
|
141
142
|
| `model_unavailable` | domain | buildErrorMetadata | `packages/sdk/src/internal/error-mappers/ollama.ts:75` +1 |
|
|
142
143
|
| `network` | domain | MemoryAdapterError, buildErrorMetadata | `packages/memory-honcho/src/adapter.ts:258` +5 |
|
|
@@ -161,6 +162,7 @@ Branch on `code`, never on the message: messages carry context (an id, a path, a
|
|
|
161
162
|
| `parse_failed` | domain | — | `packages/sdk/src/errors.ts:653` |
|
|
162
163
|
| `path_traversal` | domain | — | `packages/sdk/src/internal/security/path-guard.ts:37` |
|
|
163
164
|
| `permission_enforcement_unavailable` | domain | ConfigurationError | `packages/acp/src/permission-plugin.ts:138` +1 |
|
|
165
|
+
| `permission_rule_invalid` | domain | ConfigurationError | `packages/sdk/src/permission-rules.ts:82` +2 |
|
|
164
166
|
| `personality_empty_body` | domain | ConfigurationError | `packages/sdk/src/internal/personality/registry.ts:117` |
|
|
165
167
|
| `personality_not_found` | domain | ConfigurationError | `packages/sdk/src/internal/personality/switch.ts:60` |
|
|
166
168
|
| `personality_reserved_name` | domain | ConfigurationError | `packages/sdk/src/internal/personality/registry.ts:110` |
|
|
@@ -184,7 +186,7 @@ Branch on `code`, never on the message: messages carry context (an id, a path, a
|
|
|
184
186
|
| `sandbox_derived_helper_failed` | domain | ConfigurationError | `packages/sdk/src/sandbox/types.ts:185` +1 |
|
|
185
187
|
| `sandbox_not_available` | domain | SandboxNotAvailableError | `packages/sdk/src/sandbox/types.ts:92` +1 |
|
|
186
188
|
| `sandbox_security` | domain | SandboxSecurityError | `packages/sdk/src/sandbox/types.ts:73` +1 |
|
|
187
|
-
| `schema_invalid` | domain | ConfigurationError | `packages/sdk/src/internal/runtime/skills/skill-frontmatter.ts:
|
|
189
|
+
| `schema_invalid` | domain | ConfigurationError | `packages/sdk/src/internal/runtime/skills/skill-frontmatter.ts:99` +5 |
|
|
188
190
|
| `server_error` | domain | buildErrorMetadata | `packages/sdk/src/internal/error-mappers/ollama.ts:92` +1 |
|
|
189
191
|
| `session_busy` | domain | — | `packages/sdk/src/internal/persistence/session-writer.ts:56` +1 |
|
|
190
192
|
| `sql_injection_blocked` | domain | ConfigurationError | `packages/sdk/src/internal/memory/lance-index.ts:256` +3 |
|
|
@@ -196,13 +198,13 @@ Branch on `code`, never on the message: messages carry context (an id, a path, a
|
|
|
196
198
|
| `ssrf_blocked` | domain | — | `packages/sdk-tools/src/internal/network-guard.ts:23` |
|
|
197
199
|
| `stream_idle_timeout` | domain | NetworkError | `packages/sdk/src/internal/llm/sse.ts:95` |
|
|
198
200
|
| `stream_truncated` | domain | NetworkError | `packages/sdk/src/internal/llm/anthropic.ts:184` +1 |
|
|
199
|
-
| `subagent_mcp_unsupported_local` | domain | ConfigurationError | `packages/sdk/src/internal/runtime/skills/subagents-loader.ts:
|
|
201
|
+
| `subagent_mcp_unsupported_local` | domain | ConfigurationError | `packages/sdk/src/internal/runtime/skills/subagents-loader.ts:207` |
|
|
200
202
|
| `subagent_missing_description` | domain | ConfigurationError | `packages/sdk/src/internal/runtime/validation/validate-agent-options.ts:142` |
|
|
201
|
-
| `subagent_missing_frontmatter` | domain | ConfigurationError | `packages/sdk/src/internal/runtime/skills/subagents-loader.ts:
|
|
203
|
+
| `subagent_missing_frontmatter` | domain | ConfigurationError | `packages/sdk/src/internal/runtime/skills/subagents-loader.ts:284` |
|
|
202
204
|
| `subagent_missing_prompt` | domain | ConfigurationError | `packages/sdk/src/internal/runtime/validation/validate-agent-options.ts:147` |
|
|
203
|
-
| `subagent_reasoning_effort_without_model` | domain | ConfigurationError | `packages/sdk/src/internal/runtime/skills/subagents-loader.ts:
|
|
204
|
-
| `subagent_sandbox_not_boolean` | domain | ConfigurationError | `packages/sdk/src/internal/runtime/skills/subagents-loader.ts:
|
|
205
|
-
| `subagent_unknown_field` | domain | ConfigurationError | `packages/sdk/src/internal/runtime/skills/subagents-loader.ts:
|
|
205
|
+
| `subagent_reasoning_effort_without_model` | domain | ConfigurationError | `packages/sdk/src/internal/runtime/skills/subagents-loader.ts:227` |
|
|
206
|
+
| `subagent_sandbox_not_boolean` | domain | ConfigurationError | `packages/sdk/src/internal/runtime/skills/subagents-loader.ts:247` |
|
|
207
|
+
| `subagent_unknown_field` | domain | ConfigurationError | `packages/sdk/src/internal/runtime/skills/subagents-loader.ts:192` |
|
|
206
208
|
| `subagent_unknown_setting_source` | domain | ConfigurationError | `packages/sdk/src/subagents-loader.ts:96` |
|
|
207
209
|
| `subscribe_baseUrl_missing` | domain | SubscriptionError | `packages/sdk/src/subscription/theokit-subscribe.ts:77` |
|
|
208
210
|
| `subscribe_name_invalid` | domain | SubscriptionError | `packages/sdk/src/subscription/theokit-subscribe.ts:72` |
|
|
@@ -4,7 +4,7 @@ Every public symbol the TheoKit workspace publishes, and the exact specifier to
|
|
|
4
4
|
|
|
5
5
|
A symbol listed under two specifiers is reachable from both, but that does NOT make the two interchangeable: a class emitted separately into a subpath entry is a distinct nominal type from the one in the root bundle, so passing one where the other is expected fails on a private field. When a symbol appears twice, import it and everything it is passed to from the SAME specifier.
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
1212 export(s) across 46 entry point(s).
|
|
8
8
|
|
|
9
9
|
## `@theokit/acp`
|
|
10
10
|
|
|
@@ -200,6 +200,7 @@ A symbol listed under two specifiers is reachable from both, but that does NOT m
|
|
|
200
200
|
| `InteractionUpdate` | type | Lowest-level raw update from a run. |
|
|
201
201
|
| `InvalidateCacheOptions` | interface | Options for {@link SDKAgent.invalidateCache } . |
|
|
202
202
|
| `InvalidTaskIdError` | class | Thrown when a user-supplied task ID violates the grammar `^[a-z0-9][a-z0-9_-]*$` (D368) OR starts with a reserved adapter prefix (`wf-` / `b-` / `cron-`, EC-5). |
|
|
203
|
+
| `isInside` | function | Whether `child` is inside `parent`. |
|
|
203
204
|
| `isTransientError` | function | Is this error transient (worth retrying)? |
|
|
204
205
|
| `isValidTaskId` | function | Validates a task ID against the public grammar + reserved prefixes. |
|
|
205
206
|
| `JobQueue` | class | An in-process queue of background jobs with status tracking, cancellation, and an optional concurrency bound. |
|
|
@@ -218,6 +219,8 @@ A symbol listed under two specifiers is reachable from both, but that does NOT m
|
|
|
218
219
|
| `LiveSessionReason` | type | Why the destruction was refused. |
|
|
219
220
|
| `loadProjectEnv` | function | Read the project's `.env` into `env`, then restore every {@link SOVEREIGN_ENV_KEYS } entry to the value it had BEFORE the load — including restoring it to absent. |
|
|
220
221
|
| `LocalOptions` | interface | Local agent configuration. |
|
|
222
|
+
| `ManagedSettings` | interface | What an operator may impose. |
|
|
223
|
+
| `managedSettingsPathFor` | function | Where the platform keeps its managed settings. |
|
|
221
224
|
| `McpAuthConfig` | interface | OAuth-style auth bundle for HTTP/SSE MCP servers. |
|
|
222
225
|
| `McpHttpServerConfig` | type | HTTP or SSE MCP server. |
|
|
223
226
|
| `McpOAuthConfig` | interface | OAuth 2.1 PKCE flow descriptor. |
|
|
@@ -257,10 +260,13 @@ A symbol listed under two specifiers is reachable from both, but that does NOT m
|
|
|
257
260
|
| `normalizeUsage` | function | Convert a provider's raw `usage` object into the SDK's canonical `TokenUsage`. |
|
|
258
261
|
| `OTelSpan` | interface | The subset of the OpenTelemetry `Span` API this SDK calls. |
|
|
259
262
|
| `OutputProcessorContext` | interface | Context passed to {@link Processor.processOutput } . |
|
|
263
|
+
| `parsePermissionRules` | function | Parse a rule set into engine rules, DENY first. |
|
|
260
264
|
| `PartialToolCallUpdate` | interface | Tool call arguments streaming in incrementally. |
|
|
261
265
|
| `PermissionAction` | type | `PermissionEngine` — first-match permission rules for tool invocations. |
|
|
262
266
|
| `PermissionEngine` | class | Ordered first-match permission rules for tool invocations — the policy object you hand to `PermissionPlugin.create()` to have it enforced. |
|
|
263
267
|
| `PermissionEngineOptions` | interface | Options for {@link PermissionEngine } . |
|
|
268
|
+
| `PermissionFloorContext` | interface | Where the floor is anchored. |
|
|
269
|
+
| `permissionFloorReason` | function | Why this call may not be approved, or `undefined` when the floor has no objection. |
|
|
264
270
|
| `PermissionGate` | type | SE1 — the enriched `canUseTool` gate (the Anthropic-parity shape). |
|
|
265
271
|
| `PermissionGateContext` | interface | SE1 — context passed to the {@link PermissionGate } . |
|
|
266
272
|
| `PermissionGateDecision` | type | SE1 — the resolution of an `"ask"` verdict by the host gate. |
|
|
@@ -268,6 +274,7 @@ A symbol listed under two specifiers is reachable from both, but that does NOT m
|
|
|
268
274
|
| `PermissionPlugin` | class | SE36 — `PermissionPlugin.create` replaces `createPermissionPlugin` (ADR 0015). |
|
|
269
275
|
| `PermissionPluginOptions` | interface | Options for {@link createPermissionPlugin } . |
|
|
270
276
|
| `PermissionRule` | interface | One entry in a {@link PermissionEngine } 's ordered rule list. |
|
|
277
|
+
| `PermissionRuleSet` | interface | A policy as an operator writes it: three lists of rule strings. |
|
|
271
278
|
| `PersonalityPreset` | interface | Resolved personality preset surfaced via {@link SDKAgent.usePersonality } (Hermes #26, ADRs D160-D169). |
|
|
272
279
|
| `planReaping` | function | Sort artifacts into keep, reap, and undetermined — and delete nothing. |
|
|
273
280
|
| `Plugin` | type | SE36 — `Plugin.create` replaces `definePlugin` (ADR 0015). |
|
|
@@ -293,6 +300,7 @@ A symbol listed under two specifiers is reachable from both, but that does NOT m
|
|
|
293
300
|
| `ProviderTransform` | interface | M41 — the one OPTIONAL behavior seam on a provider profile. |
|
|
294
301
|
| `ProviderTransformContext` | interface | M41 (agent-builder provider framework) — the context a provider's `transform` receives per request. |
|
|
295
302
|
| `RateLimitError` | class | Too many requests or usage limits exceeded. |
|
|
303
|
+
| `readManagedSettings` | function | Read the deployed policy, or `{}` when none is. |
|
|
296
304
|
| `readSessionMessages` | function | Read the messages a session already contains, for a surface that needs to re-render it. |
|
|
297
305
|
| `ReadSessionMessagesOptions` | interface | Which session to read, in the terms a host already has. |
|
|
298
306
|
| `ReapableArtifact` | interface | One artifact the caller is considering deleting, described well enough to decide about. |
|
package/package.json
CHANGED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/internal/runtime/context/context-discovery.ts"],"names":[],"mappings":"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","file":"chunk-2XRAWOZZ.js","sourcesContent":["/**\n * Context file discovery (T1.1, ADRs D150 / D151).\n *\n * Discovers context files via three scopes:\n * - `cwd-only` — single dir, single path lookup\n * - `git-root-walk` — walk cwd → git-root, collect every directory's match\n * (nearest-first ordering)\n * - `globbed` — glob pattern relative to cwd (e.g. `.cursor/rules/*.mdc`)\n *\n * Pure `existsSync` checks — **no `.gitignore` parsing** (EC-A, KISS) and\n * **no invented `.theokitignore`** (EC-B). Paths normalized via\n * `realpath` to dedup symlink chains pointing to the same physical file\n * (EC-F). Git worktrees work transparently because `.git` exists as a\n * file in that case (EC-N).\n *\n * @internal\n */\n\nimport { existsSync, realpathSync } from \"node:fs\";\nimport { glob } from \"node:fs/promises\";\nimport { dirname, isAbsolute, join, resolve } from \"node:path\";\n\n/** Single filename (\"AGENTS.md\") or relative glob (\".cursor/rules/*.mdc\"). */\nexport type DiscoveryScope = \"cwd-only\" | \"git-root-walk\" | \"globbed\";\n\n/** Parser to apply once file is read. */\nexport type DiscoveryParser = \"plain-markdown\" | \"mdc\" | \"frontmatter-zod\" | \"rules-frontmatter\";\n\n/**\n * One kind of context file the runner knows how to find and read. The shipped registry is\n * `DEFAULT_DISCOVERY_SPECS`; a caller supplies its own array to change the set.\n *\n * `scope` decides how `pattern` is used and how many files a single spec can yield:\n * `cwd-only` looks for one path and stops, `git-root-walk` collects a match in every directory\n * from `cwd` up to the git root (nearest first), and `globbed` expands `pattern` as a glob\n * relative to `cwd`. So `pattern` is a filename for the first two and a glob for the third —\n * putting a glob on a walk scope silently finds nothing.\n *\n * `priority` orders the merged prompt, ascending, and is a plain number rather than an index, so\n * a new spec can be slotted between two existing ones. Lower means earlier and therefore more\n * general; later content wins on conflict.\n *\n * `parser` must match the file format — `plain-markdown` reads the whole file, `mdc` and\n * `rules-frontmatter` parse frontmatter and can DECLINE the file when its activation conditions\n * do not hold, and `frontmatter-zod` is the legacy path the runner currently skips entirely.\n *\n * `followImports` is honored only by `plain-markdown`, and turns `@path` directives in the body\n * into inlined content bounded by the import root. Setting it on a frontmatter parser does\n * nothing.\n *\n * `id` names the source in `<source name=\"\">` and in telemetry. When one spec matches files in\n * several directories, the runner suffixes it with the path relative to the git root to keep them\n * apart.\n *\n * @public — re-exported from `@theokit/sdk/context`, and therefore under semver.\n */\nexport interface DiscoverySpec {\n /** Stable identifier — used as `<source name=\"\">` and telemetry key. */\n readonly id: string;\n /** Priority for merge (lower = earlier in prompt). */\n readonly priority: number;\n /** Filename (cwd-only/git-root-walk) or glob (globbed). */\n readonly pattern: string;\n readonly scope: DiscoveryScope;\n readonly parser: DiscoveryParser;\n /** Whether to follow `@path` import directives (CLAUDE.md / GEMINI.md). */\n readonly followImports: boolean;\n}\n\n/**\n * The context files theokit looks for out of the box, in the order they are concatenated.\n *\n * Two things follow from the ordering. `AGENTS.md` comes first at priority 10 and `THEO.md` last,\n * so theokit-specific instruction wins over the vendor-neutral file on conflict. And the array is\n * consumed in the order written — the runner does not re-sort it — so a caller passing its own\n * array is responsible for keeping `priority` and array position consistent.\n *\n * `CLAUDE.md` and `GEMINI.md` are the only two entries with `followImports: true`, which means\n * they are the only files whose `@path` directives pull other files into the prompt. Those\n * imports cannot escape the import root.\n *\n * Frozen only by type: `ReadonlyArray` is a compile-time constraint, and the array and its\n * elements are not deep-frozen at runtime. Build a new array rather than mutating this one.\n *\n * @public — re-exported from `@theokit/sdk/context`, and therefore under semver.\n */\nexport const DEFAULT_DISCOVERY_SPECS: ReadonlyArray<DiscoverySpec> = [\n {\n id: \"AGENTS.md\",\n pattern: \"AGENTS.md\",\n scope: \"git-root-walk\",\n parser: \"plain-markdown\",\n followImports: false,\n priority: 10,\n },\n {\n id: \"GEMINI.md\",\n pattern: \"GEMINI.md\",\n scope: \"git-root-walk\",\n parser: \"plain-markdown\",\n followImports: true,\n priority: 20,\n },\n {\n id: \"CLAUDE.md\",\n pattern: \"CLAUDE.md\",\n scope: \"git-root-walk\",\n parser: \"plain-markdown\",\n followImports: true,\n priority: 30,\n },\n {\n id: \"cursor-rules\",\n pattern: \".cursor/rules/*.mdc\",\n scope: \"globbed\",\n parser: \"mdc\",\n followImports: false,\n priority: 40,\n },\n {\n id: \"theokit-rules\",\n pattern: \".theokit/rules/*.md\",\n scope: \"globbed\",\n parser: \"rules-frontmatter\",\n followImports: false,\n priority: 45,\n },\n {\n // Rules written for the Claude Code CLI. Measured 2026-08-26 over this repository's 32 rule\n // files: none carries frontmatter, and `rules-frontmatter` already reads a file without it as\n // `alwaysApply: true` — the format needed nothing, only a spec pointing at the directory.\n //\n // 47, not 46. Specs sort ascending and a context budget drops the tail first, so it must land\n // AFTER `.theokit/rules` (45) — the explicit namespace should survive a squeeze the borrowed one\n // does not. It must also leave a slot on BOTH sides: B-127 makes these numbers a public contract\n // precisely so a consumer can place its own source between two defaults, and 46 would have left\n // no room between 45 and itself. 47 keeps 46 free below and 48–49 free above.\n //\n // The reckoning B-127's docblock asks for: no published priority MOVES, so a consumer that chose\n // 46, 48 or 49 is unaffected. A consumer that had chosen 47 now collides — that is the cost of\n // an eighth default, paid once and recorded here rather than discovered later.\n id: \"claude-rules\",\n pattern: \".claude/rules/*.md\",\n scope: \"globbed\",\n parser: \"rules-frontmatter\",\n followImports: false,\n priority: 47,\n },\n {\n id: \"theokit-context\",\n pattern: \".theokit/context/*.md\",\n scope: \"globbed\",\n parser: \"frontmatter-zod\",\n followImports: false,\n priority: 50,\n },\n {\n // usetheokit/theokit-sdk#531 — THEO.md was the only context file that could not live at the\n // project root: every sibling here is `git-root-walk`, and this one was `cwd-only` pointed\n // at `.theokit/THEO.md` specifically, with no warning that a root THEO.md was inert.\n //\n // ADDED rather than moving the existing entry below: a project already using\n // `.theokit/THEO.md` keeps working unchanged. 55 sits between `theokit-context` (50) and the\n // existing `THEO.md` (60), leaving room on both sides — the numbering discipline\n // `claude-rules` (47) already established for this array.\n //\n // `followImports: true`, unlike the existing entry (`false`) and unlike `AGENTS.md`. This is\n // a DELIBERATE divergence between the two THEO.md specs, not an inconsistency: a root-level\n // file is edited by the same people, in the same place, as CLAUDE.md/GEMINI.md — the two\n // other root-level, human-facing files that both carry `followImports: true` — so it belongs\n // in their category rather than AGENTS.md's vendor-neutral, import-free one. Because this is a\n // NEW spec, choosing `true` here changes nothing for `.theokit/THEO.md`, which keeps `false`.\n id: \"THEO.md.root\",\n pattern: \"THEO.md\",\n scope: \"git-root-walk\",\n parser: \"plain-markdown\",\n followImports: true,\n priority: 55,\n },\n {\n id: \"THEO.md\",\n pattern: \".theokit/THEO.md\",\n scope: \"cwd-only\",\n parser: \"plain-markdown\",\n followImports: false,\n priority: 60,\n },\n];\n\nconst SAFE_FILENAME = /^[a-zA-Z0-9_.\\-/*]+$/;\nconst TRAVERSAL_RE = /(^|\\/)\\.\\.(\\/|$)/;\n\n/**\n * Reject patterns that contain path traversal (`..`) or non-allowed\n * characters (D81 parity, EC-4).\n *\n * @internal\n */\nexport function isSafePattern(pattern: string): boolean {\n if (typeof pattern !== \"string\" || pattern.length === 0) return false;\n if (TRAVERSAL_RE.test(pattern)) return false;\n if (isAbsolute(pattern)) return false;\n return SAFE_FILENAME.test(pattern);\n}\n\n/**\n * Walk upward from `cwd` looking for the closest directory containing\n * a `.git` entry (file OR directory — worktrees use a `.git` FILE,\n * EC-N). Returns the absolute path of that directory, or `undefined`\n * when no git root exists at or above `cwd`.\n *\n * @internal\n */\nexport function findGitRoot(cwd: string): string | undefined {\n if (typeof cwd !== \"string\" || cwd.length === 0) return undefined;\n let current = resolve(cwd);\n // Guard against infinite loops on weird filesystems.\n for (let i = 0; i < 64; i += 1) {\n if (existsSync(join(current, \".git\"))) return current;\n const parent = dirname(current);\n if (parent === current) return undefined;\n current = parent;\n }\n return undefined;\n}\n\n/**\n * Walk `cwd` upward to `stopDir` (inclusive) collecting every existing\n * occurrence of `filename`. Returns absolute, realpath-deduped paths in\n * nearest-first order (innermost dir first).\n *\n * No `.gitignore` parsing (EC-A). Realpath collapses symlink chains\n * pointing to the same physical file (EC-F). Filesystem races (file\n * deleted mid-walk) are skipped silently (EC-5).\n *\n * @internal\n */\n// biome-ignore lint/complexity/noExcessiveCognitiveComplexity: walk-up loop combines validation + realpath dedup + FS-race handling + stopDir guard in a single bounded loop; splitting fragments the dedup invariant.\nexport function walkUpForFile(\n cwd: string,\n filename: string,\n stopDir: string | undefined,\n): string[] {\n if (!isSafePattern(filename)) {\n return [];\n }\n const start = resolve(cwd);\n const stop = stopDir !== undefined ? resolve(stopDir) : undefined;\n const found: string[] = [];\n const seenReal = new Set<string>();\n let current = start;\n // 64-level depth cap.\n for (let i = 0; i < 64; i += 1) {\n const candidate = join(current, filename);\n if (existsSync(candidate)) {\n let real: string;\n try {\n real = realpathSync(candidate);\n } catch {\n // FS race (deleted mid-walk) — skip.\n real = candidate;\n }\n if (!seenReal.has(real)) {\n seenReal.add(real);\n found.push(real);\n }\n }\n if (stop !== undefined && current === stop) break;\n const parent = dirname(current);\n if (parent === current) break;\n current = parent;\n }\n return found;\n}\n\n/**\n * Glob-style discovery under `cwd` (e.g. `.cursor/rules/*.mdc`, `.theokit/rules/**\\/*.md`).\n * Returns absolute, lex-sorted paths.\n *\n * `*` matches within one path segment and `**` spans any depth, including zero — so\n * `.theokit/rules/**\\/*.md` finds `rules/top.md` as well as `rules/deep/nested/inner.md`, while\n * `.theokit/rules/*.md` keeps its flat meaning and finds only the first. That distinction is the\n * compatibility contract: every existing spec uses a single `*`, and widening it would silently\n * start absorbing nested files nobody chose to expose.\n *\n * ## Why this used to be flat, and what changed (B-119)\n *\n * The previous implementation split the pattern at its LAST `/`, treated the prefix as a literal\n * directory and did one `readdir` — documented as \"nested directories deferred to v2\" (EC-R). The\n * deferral was deliberate; what made it a defect was measured from a consumer. TheoCode's own rule\n * loader descends recursively, so migrating it onto the `theokit-rules` spec would have silently\n * dropped every nested rule — on the path that decides whether a repository's hooks execute. And a\n * pattern written to say so, `.theokit/rules/**\\/*.md`, resolved its directory part to a literal\n * `**` and matched NOTHING, not even the top-level file it matched before the globstar was added.\n *\n * ## Why the stdlib rather than a walker\n *\n * `fs.promises.glob` (Node ≥ 22, and this package requires ≥ 22.12) implements exactly these\n * semantics, verified against a fixture before adoption: `**\\/*.md` returns all three depths,\n * `*.md` returns one, and it emits no experimental warning. Writing a recursive walker here would\n * have been a third implementation of matching inside one package — the same duplication that let\n * the enumerator and the compiler in `context-glob.ts` disagree in the first place. `globToRegex`\n * stays where it belongs: deciding whether a rule APPLIES to a set of paths, which is a different\n * question from which files exist.\n *\n * `isSafePattern` still runs first and is unchanged, so `..` is refused before any I/O.\n *\n * @internal\n */\nexport async function walkUpForGlob(cwd: string, pattern: string): Promise<string[]> {\n if (!isSafePattern(pattern)) return [];\n const found: string[] = [];\n try {\n for await (const entry of glob(pattern, { cwd })) {\n found.push(resolve(cwd, entry));\n }\n } catch {\n // A pattern whose directory does not exist is the ordinary case — most projects have no\n // `.cursor/rules/`. Same outcome as matching nothing.\n return [];\n }\n // Sorted, because discovery order becomes prompt order and must not vary with the filesystem.\n //\n // The comparator is explicit and deliberately NOT `localeCompare`, which is the usual suggestion\n // for a bare `.sort()`. `localeCompare` orders by the machine's locale, so the same tree would\n // assemble a different prompt on a differently-configured machine — trading one source of\n // non-determinism for a subtler one. Code-unit ordering is what a bare `.sort()` already does for\n // strings; writing it out states the intent and keeps the result machine-independent.\n return found.sort((a, b) => (a < b ? -1 : a > b ? 1 : 0));\n}\n"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/internal/runtime/compat/foreign-config-sources.ts","../src/internal/persistence/paths.ts"],"names":["join","existsSync","diagFailure","homedir"],"mappings":"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","file":"chunk-43YXGD3P.cjs","sourcesContent":["import { existsSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport type { CompatSurface } from \"../../../types/agent.js\";\nimport { diagFailure } from \"../../diagnostics.js\";\n\n/*\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 FOREIGN_SOURCES: readonly ConfigSourceAdapter[] = [CLAUDE_CODE_SOURCE];\n\nconst BY_DIR_NAME: ReadonlyMap<string, ConfigSourceAdapter> = new Map(\n [NATIVE_SOURCE, ...FOREIGN_SOURCES].map((a) => [a.dirName, a]),\n);\n\n/**\n * The adapters a caller declared, in declaration order, skipping any name that names no adapter.\n *\n * An unknown name is DROPPED rather than turned into `<cwd>/<name>`: a typo must fail closed. Making\n * a directory out of an unrecognised string would import a dialect nothing knows how to parse — and\n * the whole reason this exists is that a directory name was never enough to describe a dialect.\n */\nexport function adaptersFor(kinds: readonly string[]): ConfigSourceAdapter[] {\n const byKind = new Map(FOREIGN_SOURCES.map((a) => [a.kind, a]));\n const out: ConfigSourceAdapter[] = [];\n for (const kind of kinds) {\n const adapter = byKind.get(kind);\n if (adapter !== undefined && !out.includes(adapter)) out.push(adapter);\n }\n return out;\n}\n\n/**\n * #586 — re-exported from `types/agent.ts` rather than declared here, which is what it used to be.\n *\n * Two independent declarations of one public contract: `AgentOptions.local.compatSources` was typed\n * by the public one, `persistence/paths.ts` by this one, and neither imported the other. Measured:\n * adding a member to one alone produced ZERO type errors, because structurally-identical unions\n * compare equal and the two halves would simply stop agreeing about which surfaces exist.\n *\n * Neither direction of that drift raises anything. Widen the public type and a caller declares a\n * surface the admission logic ignores; widen this one and the loader admits a surface no public\n * caller can name. Both produce a declaration that reads as honoured and is not — the failure #524\n * exists to prevent, one layer down.\n *\n * `types/` is a leaf by design (theokit#146), so the public declaration is the one that stays and\n * this module imports it. The docblock that lived here — a skill is text entering the system prompt,\n * a hook is command execution, a plugin is code loading — is on the declaration in `types/agent.ts`.\n */\nexport type { CompatSurface };\n\n/**\n * The runtime list. A type cannot be enumerated at runtime, so this is the one place the members are\n * written twice by necessity — and {@link assertCompatSurfacesExhaustive} below is what stops that\n * second copy from being a second source of truth.\n *\n * `as const satisfies` rather than an annotation, and the difference is the whole guard: annotating\n * it `readonly CompatSurface[]` widens each entry back to `CompatSurface`, so the check below\n * compares a type against itself and passes on any drift. Measured on the first attempt — a member\n * added to the public type alone produced zero errors. `satisfies` keeps the literals while still\n * rejecting an entry that is not a surface, which is both directions at once.\n */\nconst COMPAT_SURFACES = [\n \"hooks\",\n \"plugins\",\n \"skills\",\n \"subagents\",\n] as const satisfies readonly CompatSurface[];\n\n/**\n * Compile-time guard: adding a member to {@link CompatSurface} without adding it to\n * {@link COMPAT_SURFACES} fails `tsc` here.\n *\n * Never called. It exists so the pairing is checked by the compiler rather than by whoever\n * remembers — which is the entire lesson of #586, applied to the copy that could not be removed.\n */\nfunction assertCompatSurfacesExhaustive(surface: CompatSurface): (typeof COMPAT_SURFACES)[number] {\n return surface;\n}\nvoid assertCompatSurfacesExhaustive;\n\n/**\n * A declared foreign source: a bare kind, or a kind with the surfaces it may be read for.\n */\nexport type CompatSourceDeclaration =\n | string\n | { readonly kind: string; readonly import?: readonly string[] };\n\n/**\n * The adapters admitted to ONE surface.\n *\n * Three rules, and each one fails closed:\n *\n * - A bare string admits every surface. It is what `5.0.0-next.1` published, so narrowing it\n * silently would turn a working opt-in into a no-op — the exact defect #524 is about, one level\n * up.\n * - An object with no `import` admits nothing. The issue's own rule, and safe to apply strictly\n * because the object form is new and nobody can be depending on it.\n * - An unrecognised surface name is dropped rather than matched loosely, for the same reason an\n * unrecognised KIND is dropped in {@link adaptersFor}: a typo must not silently widen access.\n */\nexport function adaptersForSurface(\n sources: readonly CompatSourceDeclaration[],\n surface: CompatSurface,\n): ConfigSourceAdapter[] {\n const admitted: string[] = [];\n for (const source of sources) {\n if (typeof source === \"string\") {\n admitted.push(source);\n continue;\n }\n const wanted = source.import ?? [];\n if (wanted.some((s) => s === surface && COMPAT_SURFACES.includes(s as CompatSurface))) {\n admitted.push(source.kind);\n }\n }\n return adaptersFor(admitted);\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/**\n * Workspaces already reported, so repeated agent construction in one process says it once.\n *\n * Keyed by the resolved directory rather than by dialect kind, so a long-lived host that drives\n * several workspaces still reports each of them.\n */\nconst reported = new Set<string>();\n\n/**\n * Reports a foreign configuration directory that exists in the workspace and was not declared.\n *\n * ## Why the flip needs a voice\n *\n * Before #524 a `.claude/` was read with no opt-in; after it, the same directory is ignored. From\n * inside the repository the two states are indistinguishable — the hook file is there, it is\n * executable, and it does not run. The only remaining way to learn why is a CHANGELOG entry for a\n * version the reader may not know they crossed.\n *\n * ## Why `diagFailure` rather than `diag` (#563)\n *\n * This used `diag`, on the reasoning that ignoring an undeclared directory is not a failure and\n * that a repository which does NOT want the import should not pay a stderr line for behaving as\n * instructed. The reasoning was sound and rested on a premise nobody checked: that a host would\n * have installed a sink.\n *\n * Measured against the published `5.0.0`. `diag` returns without doing anything when no sink is\n * installed. The SDK installs none — `currentSink()` reads a `globalThis` slot only\n * `setDiagnosticsSink` fills. Neither observable host installs one either: `theocode` renamed the\n * key, and `theokit` exports `installDiagnosticSink` and never calls it. Two hosts out of two, and\n * the SDK itself. So the message the CHANGELOG promised — \"says so once, on the diagnostics\n * channel\" — reached nobody, while the consumer lost hooks, skills, subagents and plugins.\n *\n * A mitigation announced in release notes for a silent loss of capability is not a diagnostic. It\n * is the error path of the breaking change itself, and `diagFailure` exists for exactly the message\n * that must not be swallowed.\n *\n * The cost the old reasoning named is real and is now paid: a repository that wants the directory\n * ignored sees a line. What makes that acceptable — ONCE per directory per process, not per turn\n * (`reported` below); and before #524 that repository was having `.claude/` imported anyway, so the\n * line it now sees confirms the fix it wanted. The asymmetry is one line of text against silently\n * losing four subsystems.\n *\n * A host that installs a sink still owns its render surface: `diagFailure` prefers the sink and\n * only falls back to stderr when there is none.\n *\n * NOT solved here: there is no way to say \"I know, and I want none\". `compatSources: []` would be\n * the natural spelling, but `resolveCompatSources` collapses it into the same `[]` an absent option\n * produces, so this function cannot tell them apart. If the noise turns out to matter, threading\n * that distinction through is the shape of the fix.\n */\nexport function reportUndeclaredSources(\n cwd: string,\n declared: readonly CompatSourceDeclaration[],\n): void {\n // A kind named with a NARROW import list has still been declared: the consumer knows the\n // directory is there and chose which surfaces to admit. Warning them anyway would be the noise\n // that gets a warning ignored, and this one has exactly one job — telling somebody who does NOT\n // know the directory is being skipped.\n const declaredKinds = new Set(\n adaptersFor(declared.map((d) => (typeof d === \"string\" ? d : d.kind))).map((a) => a.kind),\n );\n for (const adapter of FOREIGN_SOURCES) {\n if (declaredKinds.has(adapter.kind)) continue;\n const dir = join(cwd, adapter.dirName);\n if (!existsSync(dir)) continue;\n if (reported.has(dir)) continue;\n reported.add(dir);\n // THE FILE IS NAMED FIRST because it is the entry point this message's reader can use.\n //\n // #524 gives the declaration two entry points for one shape: `.theokit/config.json`'s\n // `compat.adapters`, and `local.compatSources` in code. Until this change the warning named\n // only the second — and `local` is an argument the SDK's EMBEDDER passes, not something the\n // person reading the line can reach. Reported by the `theocode` session against 5.0.1: a user\n // of a host that embeds this SDK is told to pass an option that does not exist on their\n // surface, which is advice that is true about the mechanism and unusable as an action.\n //\n // The file is writable by anyone holding the workspace, which is exactly who sees this line.\n //\n // WHAT THIS LINE CANNOT KNOW, and it is a real limit rather than a caveat for form's sake. It\n // reports one fact: this SDK is ignoring the directory because nothing declared it. A HOST\n // embedding the SDK may be withholding the same directory for its own reasons — `theocode`\n // gates repository configuration on a trust posture — and the SDK cannot see that gate.\n //\n // So in a host that is also withholding, following this advice makes the warning stop and\n // changes nothing the user can do. That silence is honest about the SDK (it did stop ignoring\n // the directory) and uninformative about the outcome. Measured by the `theocode` session with\n // the control that settles it: a NATIVE `.theokit/` hook does not fire there either, so the\n // host's gate — not this declaration — is what holds the capability back.\n //\n // Nothing here can fix that. If a host ever gains a way to say \"I am withholding this too\",\n // this is the line where that belongs.\n diagFailure(\n `[theokit] ${adapter.dirName}/ is present but not declared, so its hooks, skills, subagents ` +\n `and plugins are ignored. To read it, add ` +\n `{\"compat\":{\"adapters\":[\"${adapter.kind}\"]}} to .theokit/config.json — or, if you embed ` +\n `this SDK, pass local: { compatSources: [\"${adapter.kind}\"] } ` +\n `(usetheokit/theokit-sdk#524).\\n`,\n );\n }\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 {\n adaptersForSurface,\n type CompatSourceDeclaration,\n type CompatSurface,\n THEOKIT_DIR_LITERAL,\n} 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 * The project's own configuration root: `<cwd>/.theokit`, always — never `THEOKIT_HOME`.\n *\n * `THEOKIT_HOME` relocates cwd-anchored SDK STATE (sessions, credentials). A project's\n * CONFIGURATION belongs to the repository: hooks, MCP servers, context sources, subagents, the\n * personality a project declares, all committed to git and shared by a team. Following the\n * override for any of them would move where a project's declared capabilities come from — a\n * behaviour change wearing the costume of a refactor, which is exactly what this function exists\n * to make impossible to do by accident: every config-class reader calls this instead of writing\n * `join(cwd, \".theokit\")` by hand.\n *\n * NOT for the `.claude/`-style foreign roots {@link adaptersForSurface} adds — those are additive,\n * opt-in, and each has its own directory name.\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 theokitConfigRoot(cwd: string): string {\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 — via {@link theokitConfigRoot}, so it is NEVER affected by `THEOKIT_HOME` for\n * the reason documented there — then `.claude`. The order is the whole contract: a project that\n * declares a skill, agent or rule in both means the explicit namespace to win, and a caller merging\n * these 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 * 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(\n cwd: string,\n sources: readonly CompatSourceDeclaration[],\n surface: CompatSurface,\n): string[] {\n const own = nativeAdmitsSurface(sources, surface) ? [theokitConfigRoot(cwd)] : [];\n return [\n ...own,\n ...adaptersForSurface(foreignOnly(sources), surface).map((a) => join(cwd, a.dirName)),\n ];\n}\n\n/** The kind a consumer names to declare THIS package's own root. */\nconst NATIVE_KIND = \"theokit\";\n\n/**\n * #631 — whether the native root contributes `surface`.\n *\n * Undeclared means every surface, which is what this function returned unconditionally before and\n * is what every existing caller gets. A consumer that names the kind is opting into the same\n * per-surface contract a foreign dialect already has, and the defaults match on purpose: a bare\n * string admits everything, an object admits exactly what its `import` lists. Two vocabularies that\n * look identical and disagree about the default would be worse than one.\n *\n * The asymmetry this closes had a measured cost. `hookConfigCandidates` reads `settings.json` from\n * every root, so a consumer keeping its own configuration in `.theokit/settings.json` had that\n * file's `hooks` key executed by this package, and `settingSources` gave it no way to decline: it\n * grants a foreign dialect per SOURCE, not per surface, so dropping `claude-code` to avoid its\n * hooks would also drop its skills, agents and rules.\n */\nfunction nativeAdmitsSurface(\n sources: readonly CompatSourceDeclaration[],\n surface: CompatSurface,\n): boolean {\n const declared = sources.filter((s) => (typeof s === \"string\" ? s : s.kind) === NATIVE_KIND);\n if (declared.length === 0) return true;\n return declared.some((s) => (typeof s === \"string\" ? true : (s.import ?? []).includes(surface)));\n}\n\n/**\n * The native declaration is consumed here and must not reach `adaptersForSurface`, which resolves\n * kinds to FOREIGN adapters. It would be dropped there as unrecognised — harmlessly, today — but\n * relying on that would make this behaviour depend on another function failing to find something,\n * which is the kind of coupling that breaks the moment an adapter of that name is added.\n */\nfunction foreignOnly(\n sources: readonly CompatSourceDeclaration[],\n): readonly CompatSourceDeclaration[] {\n return sources.filter((s) => (typeof s === \"string\" ? s : s.kind) !== NATIVE_KIND);\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(\n cwd: string,\n sources: readonly CompatSourceDeclaration[],\n): string[] {\n // Always the `plugins` surface, including when the caller wants the SKILLS a bundle carries.\n // A bundle is code, and its skills arrive attached to it: admitting `skills` alone must not\n // reach inside a foreign plugin directory, or the narrower permission would silently grant the\n // wider one. `skills-manager` and `subagents-loader` both read bundle contents and both go\n // through here, so the rule holds in one place rather than three.\n return projectConfigRoots(cwd, sources, \"plugins\").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"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/internal/runtime/plugin-loader/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-AYA65JA5.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\";\nimport type { CompatSourceDeclaration } from \"../compat/foreign-config-sources.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(\n cwd: string,\n /** Declared foreign dialects (#524). Empty reads `.theokit/plugins` only. */\n compatSources: readonly CompatSourceDeclaration[] = [],\n): Promise<string[]> {\n const dirs: string[] = [];\n for (const root of pluginBundleRoots(cwd, compatSources)) {\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 type { CompatSourceDeclaration } from \"../compat/foreign-config-sources.js\";\nimport { readWorkspaceDir } from \"../config/workspace-dir.js\";\nimport { type FrontmatterValue, parseSimpleYaml } from \"../context/yaml-frontmatter.js\";\nimport { pluginBundleDirs } from \"../plugin-loader/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 /** Declared foreign dialects (#524). Empty reads `.theokit/` only. */\n compatSources: readonly CompatSourceDeclaration[] = [],\n): Promise<Record<string, AgentDefinition>> {\n const result: Record<string, AgentDefinition> = {};\n if (settingSourcesIncludeProject) {\n const projectAgents = await readProjectSubagents(cwd, compatSources);\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(\n cwd: string,\n compatSources: readonly CompatSourceDeclaration[],\n): Promise<Record<string, AgentDefinition>> {\n const subagents: Record<string, AgentDefinition> = {};\n for (const configRoot of projectConfigRoots(cwd, compatSources, \"subagents\")) {\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, compatSources)) {\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 // `path` is computed above to read the file and was then dropped. Keeping it is the whole\n // visibility fix (#524): without it a listing cannot say which root an agent came from.\n subagents[definition.name] = { ...definition.definition, source: path };\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 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/internal/runtime/config/workspace-dir.ts","../src/internal/runtime/context/yaml-frontmatter.ts"],"names":["readdir","ConfigurationError"],"mappings":";;;;;AAyBA,eAAsB,gBAAA,CACpB,IAAA,EACA,SAAA,EACA,QAAA,EAC8B;AAC9B,EAAA,IAAI;AACF,IAAA,OAAQ,MAAMA,gBAAA,CAAQ,IAAA,EAAM,EAAE,aAAA,EAAe,MAAM,CAAA;AAAA,EACrD,SAAS,KAAA,EAAO;AACd,IAAA,MAAM,GAAA,GAAM,KAAA;AACZ,IAAA,IAAI,GAAA,CAAI,IAAA,KAAS,QAAA,EAAU,OAAO,EAAC;AACnC,IAAA,MAAM,IAAIC,oCAAA,CAAmB,CAAA,eAAA,EAAkB,QAAQ,CAAA,EAAA,EAAK,IAAI,CAAA,CAAA,EAAI;AAAA,MAClE,IAAA,EAAM,SAAA;AAAA,MACN;AAAA,KACD,CAAA;AAAA,EACH;AACF;;;AClBO,SAAS,gBAAgB,IAAA,EAA4D;AAC1F,EAAA,MAAM,SAAuD,EAAC;AAC9D,EAAA,KAAA,MAAW,IAAA,IAAQ,IAAA,CAAK,KAAA,CAAM,OAAO,CAAA,EAAG;AACtC,IAAA,MAAM,UAAA,GAAa,IAAA,CAAK,OAAA,CAAQ,GAAG,CAAA;AACnC,IAAA,IAAI,eAAe,EAAA,EAAI;AACvB,IAAA,MAAM,MAAM,IAAA,CAAK,KAAA,CAAM,CAAA,EAAG,UAAU,EAAE,IAAA,EAAK;AAC3C,IAAA,IAAI,GAAA,CAAI,WAAW,CAAA,EAAG;AACtB,IAAA,MAAM,MAAM,IAAA,CAAK,KAAA,CAAM,UAAA,GAAa,CAAC,EAAE,IAAA,EAAK;AAC5C,IAAA,MAAA,CAAO,GAAG,CAAA,GAAI,MAAA,CAAO,GAAG,CAAA;AAAA,EAC1B;AACA,EAAA,OAAO,MAAA;AACT;AAEA,SAAS,OAAO,GAAA,EAA2C;AAEzD,EAAA,IAAI,GAAA,CAAI,MAAA,KAAW,CAAA,EAAG,OAAO,MAAA;AAC7B,EAAA,IAAI,IAAI,UAAA,CAAW,GAAG,KAAK,GAAA,CAAI,QAAA,CAAS,GAAG,CAAA,EAAG;AAC5C,IAAA,OAAO,GAAA,CACJ,MAAM,CAAA,EAAG,EAAE,EACX,KAAA,CAAM,GAAG,EACT,GAAA,CAAI,CAAC,MAAM,CAAA,CAAE,IAAA,EAAM,CAAA,CACnB,MAAA,CAAO,CAAC,CAAA,KAAM,CAAA,CAAE,SAAS,CAAC,CAAA;AAAA,EAC/B;AACA,EAAA,IAAI,GAAA,KAAQ,MAAA,IAAU,GAAA,KAAQ,OAAA,SAAgB,GAAA,KAAQ,MAAA;AACtD,EAAA,MAAM,CAAA,GAAI,OAAO,GAAG,CAAA;AACpB,EAAA,IAAI,MAAA,CAAO,SAAS,CAAC,CAAA,IAAK,QAAQ,MAAA,CAAO,CAAC,GAAG,OAAO,CAAA;AACpD,EAAA,OAAO,GAAA;AACT","file":"chunk-HW7SEELD.cjs","sourcesContent":["import { readdir } from \"node:fs/promises\";\n\nimport { ConfigurationError } from \"../../../errors.js\";\n\n/**\n * Entry returned by `readWorkspaceDir`. Mirrors the subset of\n * `fs.Dirent` the file-based loaders use.\n */\nexport interface WorkspaceDirEntry {\n name: string;\n isDirectory(): boolean;\n isFile(): boolean;\n}\n\n/**\n * Read a workspace subdirectory and return its entries. When the directory\n * does not exist (`ENOENT`), returns an empty array — the file-based loaders\n * (skills, plugins, agents) treat a missing directory as \"no entries\"\n * rather than an error.\n *\n * Any other I/O failure is wrapped as `ConfigurationError` so callers can\n * surface a stable error code.\n *\n * @internal\n */\nexport async function readWorkspaceDir(\n root: string,\n errorCode: string,\n describe: string,\n): Promise<WorkspaceDirEntry[]> {\n try {\n return (await readdir(root, { withFileTypes: true })) as WorkspaceDirEntry[];\n } catch (cause) {\n const err = cause as NodeJS.ErrnoException;\n if (err.code === \"ENOENT\") return [];\n throw new ConfigurationError(`Failed to read ${describe}: ${root}`, {\n code: errorCode,\n cause,\n });\n }\n}\n","/**\n * Tiny YAML-frontmatter parser shared by the file-based loaders (skills,\n * subagents, hooks, context, plugins). Supports four scalar shapes:\n *\n * key: bar → \"bar\" (string)\n * key: 42 → 42 (number)\n * key: true → true (boolean)\n * key: [a, b, c] → [\"a\",\"b\",\"c\"](string[])\n * key: → undefined (caller's Zod default kicks in)\n *\n * Limitations (intentional — keep parser tiny, no dep):\n * - No nested objects (use flat keys like `providerId` not `provider.id`).\n * - No quoted strings — `match: \"1\"` becomes the literal 3-char string `\"1\"`.\n * - List values cannot contain a literal comma inside an element; the\n * `tags: [a,b, c]` splitter is greedy on `,`. Use multi-line lists or\n * reword if you need this.\n *\n * @internal\n */\n\nexport type FrontmatterValue = string | number | boolean | string[];\n\nexport function parseSimpleYaml(text: string): Record<string, FrontmatterValue | undefined> {\n const fields: Record<string, FrontmatterValue | undefined> = {};\n for (const line of text.split(/\\r?\\n/)) {\n const colonIndex = line.indexOf(\":\");\n if (colonIndex === -1) continue;\n const key = line.slice(0, colonIndex).trim();\n if (key.length === 0) continue;\n const raw = line.slice(colonIndex + 1).trim();\n fields[key] = coerce(raw);\n }\n return fields;\n}\n\nfunction coerce(raw: string): FrontmatterValue | undefined {\n // EC-3: empty value → undefined so Zod `.optional().default(...)` applies.\n if (raw.length === 0) return undefined;\n if (raw.startsWith(\"[\") && raw.endsWith(\"]\")) {\n return raw\n .slice(1, -1)\n .split(\",\")\n .map((s) => s.trim())\n .filter((s) => s.length > 0);\n }\n if (raw === \"true\" || raw === \"false\") return raw === \"true\";\n const n = Number(raw);\n if (Number.isFinite(n) && raw === String(n)) return n;\n return raw;\n}\n"]}
|