@xandreed/core 0.12.0 → 0.14.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.
Files changed (155) hide show
  1. package/README.md +1 -1
  2. package/dist/conformance.functions.d.ts +34 -0
  3. package/dist/conformance.functions.js +25 -0
  4. package/dist/domain/bash.entity.d.ts +82 -0
  5. package/dist/domain/bash.entity.functions.d.ts +17 -0
  6. package/dist/domain/bash.entity.functions.js +26 -0
  7. package/dist/domain/bash.entity.functions.test.d.ts +1 -0
  8. package/dist/domain/bash.entity.js +30 -0
  9. package/dist/domain/file-system.entity.d.ts +91 -0
  10. package/dist/domain/file-system.entity.functions.d.ts +18 -0
  11. package/dist/domain/file-system.entity.functions.js +30 -0
  12. package/dist/domain/file-system.entity.js +37 -0
  13. package/dist/domain/loop-event.entity.d.ts +9 -0
  14. package/dist/domain/media.entity.d.ts +79 -0
  15. package/dist/domain/media.entity.functions.d.ts +76 -0
  16. package/dist/domain/media.entity.functions.js +110 -0
  17. package/dist/domain/media.entity.js +38 -0
  18. package/dist/domain/media.entity.test.d.ts +1 -0
  19. package/dist/domain/message.entity.d.ts +157 -5
  20. package/dist/domain/message.entity.js +8 -4
  21. package/dist/domain/model-catalog.entity.d.ts +2 -0
  22. package/dist/domain/model-catalog.entity.js +2 -1
  23. package/dist/domain/token-usage.entity.d.ts +45 -1
  24. package/dist/domain/token-usage.entity.functions.d.ts +30 -1
  25. package/dist/domain/token-usage.entity.functions.js +24 -4
  26. package/dist/domain/token-usage.entity.js +19 -2
  27. package/dist/domain/token-usage.entity.test.d.ts +1 -0
  28. package/dist/harness/capability.entity.functions.js +2 -1
  29. package/dist/harness/plugin.adapter.d.ts +3 -0
  30. package/dist/harness/plugin.adapter.js +7 -1
  31. package/dist/harness/skill-files.entity.d.ts +101 -0
  32. package/dist/harness/skill-files.entity.functions.d.ts +58 -0
  33. package/dist/harness/skill-files.entity.functions.js +150 -0
  34. package/dist/harness/skill-files.entity.functions.test.d.ts +1 -0
  35. package/dist/harness/skill-files.entity.js +25 -0
  36. package/dist/index.d.ts +48 -10
  37. package/dist/index.js +67 -14
  38. package/dist/loop/cacheKey.d.ts +1 -1
  39. package/dist/loop/mapping.d.ts +13 -7
  40. package/dist/loop/mapping.js +30 -6
  41. package/dist/loop/stepContext.d.ts +8 -0
  42. package/dist/loop/stepContext.js +1 -1
  43. package/dist/loop/traceContent.d.ts +29 -0
  44. package/dist/loop/traceContent.js +4 -0
  45. package/dist/loop/traceContent.test.d.ts +1 -0
  46. package/dist/memory/memory-log.entity.d.ts +152 -14
  47. package/dist/memory/memory-log.entity.functions.d.ts +35 -5
  48. package/dist/memory/memory-log.entity.functions.js +59 -20
  49. package/dist/memory/memory-log.entity.js +19 -6
  50. package/dist/memory/memory-session.js +10 -6
  51. package/dist/memory/memory.conformance.d.ts +8 -1
  52. package/dist/memory/memory.conformance.js +32 -0
  53. package/dist/models/auth-store.conformance.d.ts +13 -0
  54. package/dist/models/auth-store.conformance.js +73 -0
  55. package/dist/models/auth-store.conformance.test.d.ts +1 -0
  56. package/dist/models/model-catalog.conformance.d.ts +15 -0
  57. package/dist/models/model-catalog.conformance.js +27 -0
  58. package/dist/models/model-catalog.conformance.test.d.ts +1 -0
  59. package/dist/models/settings-store.conformance.d.ts +26 -0
  60. package/dist/models/settings-store.conformance.js +80 -0
  61. package/dist/models/settings-store.conformance.test.d.ts +1 -0
  62. package/dist/ports/activity.port.d.ts +35 -0
  63. package/dist/ports/activity.port.js +7 -0
  64. package/dist/ports/auth-store.port.d.ts +7 -5
  65. package/dist/ports/bash.port.d.ts +22 -0
  66. package/dist/ports/bash.port.js +4 -0
  67. package/dist/ports/capability.port.d.ts +11 -1
  68. package/dist/ports/file-system.port.d.ts +44 -15
  69. package/dist/ports/file-system.port.js +1 -7
  70. package/dist/ports/harness.port.d.ts +1 -99
  71. package/dist/ports/harness.port.js +0 -24
  72. package/dist/ports/memory.port.d.ts +13 -1
  73. package/dist/ports/model-catalog.port.d.ts +4 -1
  74. package/dist/ports/run-context.port.d.ts +6 -1
  75. package/dist/ports/session-log.port.d.ts +4 -1
  76. package/dist/ports/sessions.port.d.ts +35 -6
  77. package/dist/ports/settings-store.port.d.ts +11 -7
  78. package/dist/ports/step-loop.port.d.ts +30 -2
  79. package/dist/ports/tasks.port.d.ts +5 -1
  80. package/dist/ports/turn-admission.port.d.ts +8 -2
  81. package/dist/ports/turn-events.port.d.ts +8 -1
  82. package/dist/ports/turn-scope.port.d.ts +19 -1
  83. package/dist/ports/turn.port.d.ts +70 -5
  84. package/dist/ports/utility-llm.port.d.ts +2 -0
  85. package/dist/session/activity.entity.d.ts +42 -0
  86. package/dist/session/activity.entity.functions.d.ts +21 -0
  87. package/dist/session/activity.entity.functions.js +23 -0
  88. package/dist/session/activity.entity.functions.test.d.ts +1 -0
  89. package/dist/session/activity.entity.js +15 -0
  90. package/dist/session/chassis.js +2 -1
  91. package/dist/session/session-event.entity.d.ts +68 -6
  92. package/dist/session/session-event.entity.functions.d.ts +34 -2
  93. package/dist/session/session-event.entity.functions.js +54 -16
  94. package/dist/session/session-event.entity.js +19 -2
  95. package/dist/session/session-log.conformance.d.ts +4 -3
  96. package/dist/session/session-log.conformance.js +16 -14
  97. package/dist/session/session-log.recovery.conformance.d.ts +40 -0
  98. package/dist/session/session-log.recovery.conformance.js +143 -0
  99. package/dist/session/session-log.recovery.conformance.test.d.ts +1 -0
  100. package/dist/session/sessions.conformance.d.ts +79 -0
  101. package/dist/session/sessions.conformance.js +355 -0
  102. package/dist/session/sessions.entity.d.ts +36 -3
  103. package/dist/session/sessions.entity.functions.d.ts +42 -0
  104. package/dist/session/sessions.entity.functions.js +26 -0
  105. package/dist/session/sessions.entity.js +17 -4
  106. package/dist/session/sessions.entity.test.d.ts +1 -0
  107. package/dist/session/tasks.conformance.d.ts +70 -0
  108. package/dist/session/tasks.conformance.js +213 -0
  109. package/dist/session/tasks.conformance.test.d.ts +1 -0
  110. package/dist/turn/model-request.entity.d.ts +4 -0
  111. package/dist/turn/model-request.entity.js +7 -2
  112. package/dist/turn/step-loop.conformance.d.ts +4 -1
  113. package/dist/turn/step-loop.conformance.js +73 -7
  114. package/dist/turn/tool-registry.conformance.d.ts +38 -0
  115. package/dist/turn/tool-registry.conformance.js +206 -0
  116. package/dist/turn/turn-bus.js +4 -3
  117. package/dist/turn/turn-event.entity.d.ts +134 -34
  118. package/dist/turn/turn-event.entity.functions.d.ts +11 -0
  119. package/dist/turn/turn-event.entity.functions.js +9 -1
  120. package/dist/turn/turn-event.entity.js +76 -3
  121. package/dist/turn/turn-event.entity.test.d.ts +1 -0
  122. package/dist/turn/turn-lifecycle.d.ts +46 -8
  123. package/dist/turn/turn-lifecycle.js +33 -3
  124. package/dist/turn/turn-lifecycle.test.d.ts +1 -0
  125. package/dist/turn/turn-run.d.ts +15 -3
  126. package/dist/turn/turn-run.js +37 -9
  127. package/dist/turn/turn.adapter.d.ts +6 -5
  128. package/dist/turn/turn.adapter.js +15 -3
  129. package/dist/turn/turn.conformance.d.ts +11 -2
  130. package/dist/turn/turn.conformance.js +63 -2
  131. package/dist/turn/user-message.entity.d.ts +14 -4
  132. package/dist/turn/user-message.entity.functions.d.ts +21 -0
  133. package/dist/turn/user-message.entity.functions.js +24 -0
  134. package/dist/turn/user-message.entity.js +6 -8
  135. package/dist/turn/user-message.entity.test.d.ts +1 -0
  136. package/dist/util/glob.d.ts +30 -0
  137. package/dist/util/glob.js +91 -0
  138. package/dist/util/glob.test.d.ts +1 -0
  139. package/dist/workspace/bash.conformance.d.ts +37 -0
  140. package/dist/workspace/bash.conformance.js +120 -0
  141. package/dist/workspace/bash.conformance.test.d.ts +1 -0
  142. package/dist/workspace/file-system.conformance.d.ts +38 -0
  143. package/dist/workspace/file-system.conformance.js +254 -0
  144. package/dist/workspace/file-system.conformance.test.d.ts +1 -0
  145. package/dist/workspace/file-system.memory.adapter.d.ts +23 -0
  146. package/dist/workspace/file-system.memory.adapter.js +132 -0
  147. package/package.json +6 -6
  148. package/dist/harness/session.entity.d.ts +0 -33
  149. package/dist/harness/session.entity.js +0 -25
  150. package/dist/harness/skill-files.d.ts +0 -17
  151. package/dist/harness/skill-files.js +0 -25
  152. package/dist/ports/conversation-store.port.d.ts +0 -127
  153. package/dist/ports/conversation-store.port.js +0 -36
  154. package/dist/ports/shell.port.d.ts +0 -32
  155. package/dist/ports/shell.port.js +0 -16
@@ -0,0 +1,101 @@
1
+ import { Schema } from "effect";
2
+ /**
3
+ * One file of a skills tree, as read: its path relative to the tree's root
4
+ * (POSIX, `/`-separated: `SKILL.md`, `git/SKILL.md`,
5
+ * `git/references/style.md`) and its text. `size` is set only for a file
6
+ * that was not read because it is too large (`collectSkillFiles`'
7
+ * `maxFileBytes`): its size in bytes, with an empty `text`;
8
+ * `readSkillFiles` leaves such a file out with a warning.
9
+ */
10
+ export declare const SkillFile: Schema.Struct<{
11
+ readonly path: Schema.String;
12
+ readonly text: Schema.String;
13
+ readonly size: Schema.optionalKey<Schema.Int>;
14
+ }>;
15
+ export type SkillFile = typeof SkillFile.Type;
16
+ /**
17
+ * Something met while reading a skills tree, at a path relative to its root.
18
+ * An `error` leaves the skill out (its `SKILL.md` has no frontmatter or no
19
+ * description, its id is taken); a `warning` leaves out part of a skill (a
20
+ * reference over the size limit, or one whose path is not a valid id) or a
21
+ * value it could not read.
22
+ */
23
+ export declare const SkillFileIssue: Schema.Struct<{
24
+ readonly path: Schema.String;
25
+ readonly severity: Schema.Literals<readonly ["error", "warning"]>;
26
+ readonly message: Schema.String;
27
+ }>;
28
+ export type SkillFileIssue = typeof SkillFileIssue.Type;
29
+ /** One skill of a tree: the directory its `SKILL.md` is in, relative to the tree's root (`""` for the root itself), and the skill. */
30
+ export declare const SkillTreeEntry: Schema.Struct<{
31
+ readonly directory: Schema.String;
32
+ readonly skill: Schema.Struct<{
33
+ readonly id: Schema.Trimmed;
34
+ readonly version: Schema.Trimmed;
35
+ readonly summary: Schema.Trimmed;
36
+ readonly instructions: Schema.String;
37
+ readonly tools: Schema.$Array<Schema.Trimmed>;
38
+ readonly always: Schema.Boolean;
39
+ readonly permissions: Schema.$Array<Schema.String>;
40
+ readonly references: Schema.$Array<Schema.Struct<{
41
+ readonly id: Schema.Trimmed;
42
+ readonly title: Schema.Trimmed;
43
+ readonly text: Schema.String;
44
+ }>>;
45
+ }>;
46
+ }>;
47
+ export type SkillTreeEntry = typeof SkillTreeEntry.Type;
48
+ /** A directory tree of skills as read: every skill that loaded, by the path of its `SKILL.md`, and the issues met. */
49
+ export declare const SkillTree: Schema.Struct<{
50
+ readonly skills: Schema.$Array<Schema.Struct<{
51
+ readonly directory: Schema.String;
52
+ readonly skill: Schema.Struct<{
53
+ readonly id: Schema.Trimmed;
54
+ readonly version: Schema.Trimmed;
55
+ readonly summary: Schema.Trimmed;
56
+ readonly instructions: Schema.String;
57
+ readonly tools: Schema.$Array<Schema.Trimmed>;
58
+ readonly always: Schema.Boolean;
59
+ readonly permissions: Schema.$Array<Schema.String>;
60
+ readonly references: Schema.$Array<Schema.Struct<{
61
+ readonly id: Schema.Trimmed;
62
+ readonly title: Schema.Trimmed;
63
+ readonly text: Schema.String;
64
+ }>>;
65
+ }>;
66
+ }>>;
67
+ readonly issues: Schema.$Array<Schema.Struct<{
68
+ readonly path: Schema.String;
69
+ readonly severity: Schema.Literals<readonly ["error", "warning"]>;
70
+ readonly message: Schema.String;
71
+ }>>;
72
+ }>;
73
+ export type SkillTree = typeof SkillTree.Type;
74
+ /**
75
+ * How `readSkillFiles` reads a tree. `tools`: `"declared"` (the default)
76
+ * keeps each skill's `tools` field, `"ignore"` drops it, so loading a skill
77
+ * from the tree activates no tool. `maxReferenceBytes`: a reference larger
78
+ * than this (UTF-8 bytes) is left out with a warning; no limit when absent.
79
+ * `rootName`: the id of a `SKILL.md` at the tree's root that names none; a
80
+ * root `SKILL.md` without an id is an error when absent.
81
+ */
82
+ export declare const SkillFilesOptions: Schema.Struct<{
83
+ readonly tools: Schema.optionalKey<Schema.Literals<readonly ["declared", "ignore"]>>;
84
+ readonly maxReferenceBytes: Schema.optionalKey<Schema.Int>;
85
+ readonly rootName: Schema.optionalKey<Schema.String>;
86
+ }>;
87
+ export type SkillFilesOptions = typeof SkillFilesOptions.Type;
88
+ /**
89
+ * How much of a directory `collectSkillFiles` reads: at most `maxFiles`
90
+ * files and `maxBytes` bytes of text, or it fails with `skills.limit`.
91
+ * `maxFileBytes`: a file other than a `SKILL.md` larger than this is not
92
+ * read and does not count toward `maxBytes`; it is collected with its
93
+ * `size` (give `readSkillFiles` the same `maxReferenceBytes`). No limit when
94
+ * absent.
95
+ */
96
+ export declare const CollectSkillFilesOptions: Schema.Struct<{
97
+ readonly maxFiles: Schema.Int;
98
+ readonly maxBytes: Schema.Int;
99
+ readonly maxFileBytes: Schema.optionalKey<Schema.Int>;
100
+ }>;
101
+ export type CollectSkillFilesOptions = typeof CollectSkillFilesOptions.Type;
@@ -0,0 +1,58 @@
1
+ import { Effect } from "effect";
2
+ import type { FsError } from "../domain/file-system.entity.js";
3
+ import { FileSystem } from "../ports/file-system.port.js";
4
+ import { SkillDefinition } from "./capability.entity.js";
5
+ import { HarnessError } from "./plugin.entity.js";
6
+ import type { CollectSkillFilesOptions, SkillFile, SkillFileIssue, SkillFilesOptions, SkillTree } from "./skill-files.entity.js";
7
+ /**
8
+ * Skills from a tree of files (paths relative to the tree's root, as
9
+ * `collectSkillFiles` reads them). Never fails: what cannot be read is an
10
+ * issue, and the rest loads.
11
+ *
12
+ * - Every `SKILL.md`, at any depth, is a skill, and its directory is the
13
+ * skill's. A file belongs to the deepest skill directory it is in; a
14
+ * nested skill's files are its own, never its parent's. Files outside every
15
+ * skill directory are not read.
16
+ * - A `SKILL.md` opens with `---` frontmatter (see the fields below); its
17
+ * body is the skill's instructions (what `load_skill` returns).
18
+ * - Every other file of a skill is a reference (what `read_skill_reference`
19
+ * serves), its id the path below the skill's directory
20
+ * (`references/formats.md`, `scripts/check.sh`).
21
+ *
22
+ * Fields: `id` (else `name`, else the directory's path below the root, else
23
+ * for a `SKILL.md` at the root `options.rootName`), `summary` (else
24
+ * `description`; required; its whitespace and line ends collapsed to one
25
+ * line, the catalogue's), `version` (default: a fingerprint of the skill as
26
+ * read, its `SKILL.md` and the references it serves), `tools` and
27
+ * `permissions` (a list, or text split on commas and whitespace), `always`
28
+ * (`true` or `false`, any case). Other fields (`license`, `metadata`,
29
+ * `allowed-tools`, ...) are ignored. A second skill with an id already used
30
+ * is left out with an error; a reference that cannot be served (over
31
+ * `maxReferenceBytes`, not read, a path that is not a valid id) is left out
32
+ * with a warning.
33
+ */
34
+ export declare const readSkillFiles: (files: ReadonlyArray<SkillFile>, options?: SkillFilesOptions) => SkillTree;
35
+ /** Issues as one message: `<path>: <message>` each, in order. */
36
+ export declare const skillIssuesText: (issues: ReadonlyArray<SkillFileIssue>) => string;
37
+ /**
38
+ * `readSkillFiles`, strict: any issue, error or warning, fails with
39
+ * `skills.files` naming each one, so nothing is left out silently.
40
+ */
41
+ export declare const skillsFromFiles: (files: ReadonlyArray<SkillFile>, options?: SkillFilesOptions) => Effect.Effect<ReadonlyArray<SkillDefinition>, HarnessError>;
42
+ /**
43
+ * The text files under `root` (an absolute directory), as `readSkillFiles`
44
+ * takes them: paths relative to `root`, in `glob` order. The walk is the
45
+ * port's `glob("**\/*")`: links are not entered, entries whose name starts
46
+ * with a dot and `node_modules` directories are skipped. A binary file (a
47
+ * NUL byte or bytes that are not UTF-8) is left out and does not count
48
+ * toward `maxBytes`, told by its first 8 KB or, once read whole, by all of
49
+ * it; without `maxFileBytes`, one whose first sign of binary lies past what
50
+ * the budget has left fails it. A file other than a `SKILL.md` larger than
51
+ * `maxFileBytes` is not read: it is collected with its `size` and no text,
52
+ * and does not count toward `maxBytes` either.
53
+ * More than `maxFiles` files, or more than `maxBytes` bytes of text, fails
54
+ * with `skills.limit`. A file gone between the walk and its read is skipped;
55
+ * any other read failure, or a `root` that cannot be listed, is the
56
+ * `FsError`.
57
+ */
58
+ export declare const collectSkillFiles: (root: string, options: CollectSkillFilesOptions) => Effect.Effect<ReadonlyArray<SkillFile>, FsError | HarnessError, FileSystem>;
@@ -0,0 +1,150 @@
1
+ import { Effect, Option, Result, Schema } from "effect";
2
+ import { canonicalJson, fingerprintOf } from "../memory/memory-log.entity.functions.js";
3
+ import { FileSystem } from "../ports/file-system.port.js";
4
+ import { SkillDefinition, SkillReference } from "./capability.entity.js";
5
+ import { HarnessError } from "./plugin.entity.js";
6
+ const normalized = (text) => text.replace(/^\uFEFF/, "").replace(/\r\n?/g, `
7
+ `), keyLine = /^([^\s#:\-][^:]*):[ \t]*(.*)$/, blockScalar = /^([|>])[+-]?[1-9]?[+-]?$/, isBlank = (line) => line.trim().length === 0, indentOf = (line) => line.length - line.trimStart().length, unquoted = (value) => {
8
+ if (value.length >= 2 && value.startsWith('"') && value.endsWith('"'))
9
+ return value.slice(1, -1).replace(/\\(["\\nt])/g, (_, escaped) => escaped === "n" ? `
10
+ ` : escaped === "t" ? "\t" : escaped);
11
+ return value.length >= 2 && value.startsWith("'") && value.endsWith("'") ? value.slice(1, -1).replaceAll("''", "'") : value;
12
+ }, quoted = /^("(?:[^"\\]|\\.)*"|'(?:[^']|'')*')(.*)$/, withoutComment = (value) => {
13
+ if (!value.startsWith('"') && !value.startsWith("'"))
14
+ return value.replace(/(^|\s)#.*$/, "").trim();
15
+ const found = quoted.exec(value), after = (found?.[2] ?? "").trim();
16
+ return found !== null && (after.length === 0 || after.startsWith("#")) ? found[1] ?? value : value;
17
+ }, dedented = (lines) => {
18
+ const indent = Math.min(...lines.filter((line) => !isBlank(line)).map(indentOf)), kept = lines.map((line) => isBlank(line) ? "" : line.slice(indent)), last = kept.findLastIndex((line) => line.length > 0);
19
+ return kept.slice(0, last + 1);
20
+ }, blockText = (style, lines) => {
21
+ const content = dedented(lines);
22
+ if (style === "|")
23
+ return content.join(`
24
+ `);
25
+ return content.reduce((paragraphs, line) => line.length === 0 ? [...paragraphs, []] : [...paragraphs.slice(0, -1), [...paragraphs.at(-1) ?? [], line.trim()]], [[]]).map((paragraph) => paragraph.join(" ")).join(`
26
+ `).trim();
27
+ }, textValue = (text) => ({ text: Option.some(text), items: Option.none() }), listValue = (items) => ({ text: Option.none(), items: Option.some(items) }), flowItems = (value) => value.slice(1, -1).split(",").map((item) => unquoted(item.trim())).filter((item) => item.length > 0), valueOf = (block) => {
28
+ const inline = withoutComment(block.inline), lines = block.rest.filter((line) => !isBlank(line)), style = blockScalar.exec(inline);
29
+ if (style !== null)
30
+ return textValue(blockText(style[1] ?? "|", block.rest));
31
+ if (inline.length === 0) {
32
+ if (lines.length > 0 && lines.every((line) => line.trim() === "-" || line.trim().startsWith("- ")))
33
+ return listValue(lines.map((line) => unquoted(withoutComment(line.trim().slice(1).trim()))).filter((item) => item.length > 0));
34
+ return lines.some((line) => keyLine.test(line.trim())) ? { text: Option.none(), items: Option.none() } : textValue(lines.map((line) => line.trim()).join(" "));
35
+ }
36
+ const whole = [inline, ...lines.map((line) => line.trim())].join(" ");
37
+ if (whole.startsWith("[") && whole.endsWith("]"))
38
+ return listValue(flowItems(whole));
39
+ return textValue(unquoted(whole));
40
+ }, documentOf = (text) => {
41
+ const lines = normalized(text).split(`
42
+ `);
43
+ if (lines[0]?.trimEnd() !== "---")
44
+ return Option.none();
45
+ const close = lines.findIndex((line, index) => index > 0 && line.trimEnd() === "---");
46
+ if (close < 0)
47
+ return Option.none();
48
+ const grouped = lines.slice(1, close).reduce((state, line, index) => {
49
+ const current = state.blocks.at(-1), attach = () => current === void 0 ? state : { ...state, blocks: [...state.blocks.slice(0, -1), { ...current, rest: [...current.rest, line] }] };
50
+ if (isBlank(line) || indentOf(line) > 0 || line.startsWith("- ") || line === "-")
51
+ return attach();
52
+ if (line.startsWith("#"))
53
+ return state;
54
+ const found = keyLine.exec(line);
55
+ if (found === null)
56
+ return { ...state, unread: [...state.unread, index + 2] };
57
+ return { ...state, blocks: [...state.blocks, { key: (found[1] ?? "").trim(), inline: (found[2] ?? "").trim(), rest: [] }] };
58
+ }, { blocks: [], unread: [] });
59
+ return Option.some({
60
+ fields: new Map(grouped.blocks.map((block) => [block.key, valueOf(block)])),
61
+ body: lines.slice(close + 1).join(`
62
+ `),
63
+ unread: grouped.unread
64
+ });
65
+ }, textField = (document, key) => Option.filter(Option.flatMap(Option.fromNullishOr(document.fields.get(key)), (value) => Option.map(value.text, (text) => text.trim())), (text) => text.length > 0), listField = (document, key) => Option.match(Option.fromNullishOr(document.fields.get(key)), {
66
+ onNone: () => [],
67
+ onSome: (value) => Option.getOrElse(Option.orElse(value.items, () => Option.map(value.text, (text) => text.split(/[\s,]+/))), () => []).map((item) => item.trim()).filter((item) => item.length > 0)
68
+ }), skillFileName = "SKILL.md", encoder = new TextEncoder, segmentsOf = (path) => path.split("/").filter((segment) => segment.length > 0 && segment !== "."), directoryOf = (path) => segmentsOf(path).slice(0, -1).join("/"), isSkillFile = (path) => segmentsOf(path).at(-1) === skillFileName, within = (directory, path) => directory === "" || path.startsWith(`${directory}/`), relativeTo = (directory, path) => directory === "" ? path : path.slice(directory.length + 1), byPath = (left, right) => left.path < right.path ? -1 : left.path > right.path ? 1 : 0, issue = (path, severity, message) => ({ path, severity, message }), oneLine = (text) => text.replace(/\s+/g, " ").trim(), headingOf = (body) => Option.fromNullishOr(body.split(`
69
+ `).filter((line) => line.startsWith("# ")).map((line) => line.slice(2).trim()).find((title) => title.length > 0)), referenceOf = (directory, file) => {
70
+ const id = relativeTo(directory, file.path), text = normalized(file.text), markdown = /\.(md|markdown)$/i.test(id), document = markdown ? documentOf(text) : Option.none(), body = Option.match(document, { onNone: () => text, onSome: (found) => found.body }), title = Option.orElse(Option.flatMap(document, (found) => textField(found, "title")), () => markdown ? headingOf(body) : Option.none());
71
+ return Result.mapError(Schema.decodeUnknownResult(SkillReference)({ id, title: oneLine(Option.getOrElse(title, () => id)), text: body.trim() }), (error) => issue(file.path, "warning", `left out: not a valid reference: ${oneLine(error.message)}`));
72
+ }, ownedOf = (directory, file, limit) => {
73
+ const unread = Option.fromNullishOr(file.size), bytes = Option.getOrElse(unread, () => encoder.encode(file.text).length);
74
+ return Option.match(Option.filter(limit, (max) => bytes > max), {
75
+ onSome: (max) => Result.fail(issue(file.path, "warning", `left out: ${bytes} bytes, more than the ${max}-byte reference limit (maxReferenceBytes)`)),
76
+ onNone: () => Option.isSome(unread) ? Result.fail(issue(file.path, "warning", `left out: ${bytes} bytes, too large to be read (maxFileBytes)`)) : referenceOf(directory, file)
77
+ });
78
+ }, skillOf = (skillFile, owned, options) => {
79
+ const directory = directoryOf(skillFile.path), failed = (message) => ({ entry: Option.none(), issues: [issue(skillFile.path, "error", message)] }), unread = Option.fromNullishOr(skillFile.size);
80
+ if (Option.isSome(unread))
81
+ return failed(`not read: ${unread.value} bytes, too large to be read (maxFileBytes)`);
82
+ return Option.match(documentOf(skillFile.text), {
83
+ onNone: () => failed("no frontmatter: a SKILL.md opens with a --- fence holding at least a description"),
84
+ onSome: (document) => {
85
+ const fallbackId = directory === "" ? Option.fromNullishOr(options.rootName) : Option.some(directory), id = Option.orElse(Option.orElse(textField(document, "id"), () => textField(document, "name")), () => fallbackId), summary = Option.orElse(textField(document, "summary"), () => textField(document, "description"));
86
+ if (Option.isNone(id))
87
+ return failed("a SKILL.md at the root names its skill: give it an id or a name");
88
+ if (Option.isNone(summary))
89
+ return failed("no description: the frontmatter needs a description (or summary)");
90
+ const always = textField(document, "always").pipe(Option.map((value) => value.toLowerCase())), parts = owned.map((file) => ownedOf(directory, file, Option.fromNullishOr(options.maxReferenceBytes))), references = parts.flatMap((part) => Option.toArray(Result.getSuccess(part))), warnings = [
91
+ ...document.unread.map((line) => issue(skillFile.path, "warning", `frontmatter line ${line} is not \`key: value\` and was not read`)),
92
+ ...Option.isSome(always) && always.value !== "true" && always.value !== "false" ? [issue(skillFile.path, "warning", `always is true or false, not "${always.value}"; read as false`)] : [],
93
+ ...parts.flatMap((part) => Option.toArray(Result.getFailure(part)))
94
+ ], read = {
95
+ id: id.value,
96
+ summary: oneLine(summary.value),
97
+ instructions: normalized(document.body).trim(),
98
+ tools: (options.tools ?? "declared") === "ignore" ? [] : listField(document, "tools"),
99
+ always: Option.contains(always, "true"),
100
+ permissions: listField(document, "permissions"),
101
+ references
102
+ }, version = Option.getOrElse(textField(document, "version"), () => fingerprintOf(canonicalJson(read)));
103
+ return Result.match(Schema.decodeUnknownResult(SkillDefinition)({ ...read, version }), {
104
+ onFailure: (error) => ({ entry: Option.none(), issues: [...warnings, issue(skillFile.path, "error", error.message)] }),
105
+ onSuccess: (skill) => ({ entry: Option.some({ directory, skill }), issues: warnings })
106
+ });
107
+ }
108
+ });
109
+ };
110
+ export const readSkillFiles = (files, options = {}) => {
111
+ const sorted = files.map((file) => ({ ...file, path: segmentsOf(file.path).join("/") })).toSorted(byPath), skillFiles = sorted.filter((file) => isSkillFile(file.path)), directories = skillFiles.map((file) => directoryOf(file.path)), ownerOf = (path) => Option.fromNullishOr(directories.filter((directory) => within(directory, path)).reduce((deepest, directory) => deepest === void 0 || directory.length > deepest.length ? directory : deepest, void 0)), owners = new Map(sorted.map((file) => [file, ownerOf(file.path)]));
112
+ return skillFiles.map((skillFile) => {
113
+ const directory = directoryOf(skillFile.path), owned = sorted.filter((file) => file !== skillFile && Option.contains(owners.get(file) ?? Option.none(), directory));
114
+ return { path: skillFile.path, ...skillOf(skillFile, owned, options) };
115
+ }).reduce((tree, { path, entry, issues }) => Option.match(entry, {
116
+ onNone: () => ({ ...tree, issues: [...tree.issues, ...issues] }),
117
+ onSome: (found) => {
118
+ const taken = tree.skills.find((other) => other.skill.id === found.skill.id);
119
+ return taken === void 0 ? { skills: [...tree.skills, found], issues: [...tree.issues, ...issues] } : { ...tree, issues: [...tree.issues, ...issues, issue(path, "error", `the skill id ${found.skill.id} is already used by ${taken.directory === "" ? "" : `${taken.directory}/`}${skillFileName}`)] };
120
+ }
121
+ }), { skills: [], issues: [] });
122
+ }, skillIssuesText = (issues) => issues.map((found) => `${found.path}: ${found.message}`).join("; "), skillsFromFiles = (files, options = {}) => {
123
+ const tree = readSkillFiles(files, options);
124
+ return tree.issues.length > 0 ? Effect.fail(new HarnessError({ code: "skills.files", message: skillIssuesText(tree.issues) })) : Effect.succeed(tree.skills.map((entry) => entry.skill));
125
+ };
126
+ const probeBytes = 8192, limited = (message) => new HarnessError({ code: "skills.limit", message }), under = (root, path) => root.endsWith("/") ? `${root}${path}` : `${root}/${path}`, textOf = (bytes) => bytes.includes(0) ? Option.none() : Result.getSuccess(Result.try({ try: () => new TextDecoder("utf-8", { fatal: !0 }).decode(bytes), catch: () => "not UTF-8" })), beginsText = (bytes) => !bytes.includes(0) && Result.isSuccess(Result.try({ try: () => new TextDecoder("utf-8", { fatal: !0 }).decode(bytes, { stream: !0 }), catch: () => "not UTF-8" }));
127
+ export const collectSkillFiles = (root, options) => Effect.gen(function* () {
128
+ const fs = yield* FileSystem, found = yield* fs.glob("**/*", { cwd: root, onlyFiles: !0, exclude: ["node_modules"], limit: options.maxFiles });
129
+ if (found.truncated)
130
+ return yield* Effect.fail(limited(`${root} holds more than ${options.maxFiles} files (maxFiles)`));
131
+ const overBudget = limited(`the text files under ${root} hold more than ${options.maxBytes} bytes (maxBytes)`);
132
+ return (yield* Effect.reduce(found.paths, () => ({ files: [], bytes: 0 }), (state, path) => {
133
+ const full = under(root, path), remaining = options.maxBytes - state.bytes, cap = isSkillFile(path) ? Option.none() : Option.fromNullishOr(options.maxFileBytes), unread = (size) => ({ ...state, files: [...state.files, { path, text: "", size }] }), add = (content, complete) => {
134
+ if (!complete)
135
+ return beginsText(content) ? Effect.fail(overBudget) : Effect.succeed(state);
136
+ return Option.match(textOf(content), {
137
+ onNone: () => Effect.succeed(state),
138
+ onSome: (text) => content.length > remaining ? Effect.fail(overBudget) : Effect.succeed({ files: [...state.files, { path, text }], bytes: state.bytes + content.length })
139
+ });
140
+ };
141
+ return fs.readBytes(full, { length: probeBytes }).pipe(Effect.flatMap((probe) => {
142
+ if (!beginsText(probe))
143
+ return Effect.succeed(state);
144
+ if (probe.length < probeBytes)
145
+ return Option.isSome(Option.filter(cap, (max) => probe.length > max)) ? Effect.succeed(unread(probe.length)) : add(probe, !0);
146
+ const asked = Option.getOrElse(cap, () => remaining) + 1;
147
+ return Effect.flatMap(fs.readBytes(full, { length: asked }), (bytes) => Option.isSome(Option.filter(cap, (max) => bytes.length > max)) ? Effect.map(fs.stat(full), (info) => unread(info.size)) : add(bytes, bytes.length < asked));
148
+ }), Effect.catchTag("FsError", (error) => error.reason === "NotFound" ? Effect.succeed(state) : Effect.fail(error)));
149
+ })).files;
150
+ });
@@ -0,0 +1,25 @@
1
+ import { Schema } from "effect";
2
+ import { SkillDefinition } from "./capability.entity.js";
3
+ export const SkillFile = Schema.Struct({
4
+ path: Schema.String,
5
+ text: Schema.String,
6
+ size: Schema.optionalKey(Schema.Int.check(Schema.isGreaterThanOrEqualTo(0)))
7
+ }), SkillFileIssue = Schema.Struct({
8
+ path: Schema.String,
9
+ severity: Schema.Literals(["error", "warning"]),
10
+ message: Schema.String
11
+ }), SkillTreeEntry = Schema.Struct({
12
+ directory: Schema.String,
13
+ skill: SkillDefinition
14
+ }), SkillTree = Schema.Struct({
15
+ skills: Schema.Array(SkillTreeEntry),
16
+ issues: Schema.Array(SkillFileIssue)
17
+ }), SkillFilesOptions = Schema.Struct({
18
+ tools: Schema.optionalKey(Schema.Literals(["declared", "ignore"])),
19
+ maxReferenceBytes: Schema.optionalKey(Schema.Int.check(Schema.isGreaterThanOrEqualTo(0))),
20
+ rootName: Schema.optionalKey(Schema.String)
21
+ }), CollectSkillFilesOptions = Schema.Struct({
22
+ maxFiles: Schema.Int.check(Schema.isGreaterThanOrEqualTo(1)),
23
+ maxBytes: Schema.Int.check(Schema.isGreaterThanOrEqualTo(1)),
24
+ maxFileBytes: Schema.optionalKey(Schema.Int.check(Schema.isGreaterThanOrEqualTo(0)))
25
+ });
package/dist/index.d.ts CHANGED
@@ -1,11 +1,14 @@
1
- export { AgentMessage, AgentResult, AssistantMessage, Checkpoint, ConversationId, ReasoningPart, TextPart, ToolCallId, ToolCallPart, ToolMessage, ToolResultPart, UserRoleMessage, } from "./domain/message.entity.js";
1
+ export { AgentMessage, AgentResult, AssistantMessage, Checkpoint, ConversationId, ReasoningPart, TextPart, ToolCallId, ToolCallPart, ToolMessage, ToolResultPart, UserContentPart, UserRoleMessage, } from "./domain/message.entity.js";
2
+ export { AttachmentRejected, AttachmentRejectedReason, ImageMediaType, Media, MEDIA_LIMITS, MediaFingerprint, MediaSlot, } from "./domain/media.entity.js";
3
+ export { base64Length, elideMediaData, IMAGE_TOKEN_ESTIMATE, imageSizeOf, isMediaValue, mediaAt, mediaFingerprintOf, mediaFromBase64, mediaFromBytes, mediaLabel, mediaSlotsOf, normalizeMedia, sniffImageType, toolResultMedia, } from "./domain/media.entity.functions.js";
4
+ export type { ImageSize, MediaDescription, ToolResultMedia } from "./domain/media.entity.functions.js";
2
5
  export { Failure } from "./domain/failure.entity.js";
3
6
  export { toFailure } from "./domain/failure.entity.functions.js";
4
7
  export { AgentFailure, AgentFailureCategory } from "./domain/agent-failure.entity.js";
5
8
  export type { AgentFailure as AgentFailureType, AgentFailureCategory as AgentFailureCategoryType } from "./domain/agent-failure.entity.js";
6
9
  export { toAgentFailure, toolResultFailure } from "./domain/agent-failure.entity.functions.js";
7
- export { TokenUsage } from "./domain/token-usage.entity.js";
8
- export { addUsage, zeroUsage } from "./domain/token-usage.entity.functions.js";
10
+ export { BudgetTokens, ModelPrice, TokenUsage, UsageBreakdown } from "./domain/token-usage.entity.js";
11
+ export { addUsage, costOf, isBudgetTokens, sumUsage, tokenUsage, uncachedInputTokens, usageBreakdown, zeroUsage, } from "./domain/token-usage.entity.functions.js";
9
12
  export { ModelId, ModelSelection, ProviderId, } from "./domain/model-selection.entity.js";
10
13
  export { ModelCallPolicy, ReasoningEffort } from "./domain/model-call-policy.entity.js";
11
14
  export type { ReasoningEffort as ReasoningEffortType } from "./domain/model-call-policy.entity.js";
@@ -15,18 +18,30 @@ export type { ModelCallPolicy as ModelCallPolicyType } from "./domain/model-call
15
18
  export { CurrentEmptyResponseTolerance, CurrentModelCallPolicy } from "./loop/modelPolicy.js";
16
19
  export { formatModelSelection, parseModelSelection } from "./domain/model-selection.entity.functions.js";
17
20
  export type { LoopEvent, ToolCallSummary } from "./domain/loop-event.entity.js";
18
- export { ConversationStore, ConversationSummary, RunOutcomeRecord, StoredMessage, StoreError, } from "./ports/conversation-store.port.js";
21
+ export { DirEntry, FileInfo, FileKind, FsError, FsReason, GlobOptions, GlobResult, ReadRange, RecursiveOptions, StatOptions, WriteOptions } from "./domain/file-system.entity.js";
22
+ export { walkGlob } from "./domain/file-system.entity.functions.js";
23
+ export { BASH_ENV_ALLOWLIST, BashChunk, BashError, BashErrorReason, BashEvent, BashExit, BashOptions, BashResult, BashTermination } from "./domain/bash.entity.js";
24
+ export { collectBashResult, resolveBashEnv } from "./domain/bash.entity.functions.js";
19
25
  export { EngineSettings, SETTINGS_KEYS, SettingsError, SettingsStore, } from "./ports/settings-store.port.js";
20
26
  export type { ModelRole, SettingsKey } from "./ports/settings-store.port.js";
21
27
  export { AuthError, AuthStore, Credential } from "./ports/auth-store.port.js";
22
28
  export { ModelCatalog } from "./ports/model-catalog.port.js";
23
- export { FileSystem, FsError } from "./ports/file-system.port.js";
24
- export { Shell, ShellError, ShellResult } from "./ports/shell.port.js";
29
+ export { FileSystem } from "./ports/file-system.port.js";
30
+ export { Bash } from "./ports/bash.port.js";
25
31
  export { UtilityCompletion, UtilityError, UtilityLlm } from "./ports/utility-llm.port.js";
26
32
  export { asJsonRecord, decodeJsonLines, parseJsonOption, parseJsonWarn } from "./util/json.js";
33
+ export { compileGlob, globMatcher } from "./util/glob.js";
34
+ export type { GlobMatcher, GlobMatchOptions } from "./util/glob.js";
35
+ export { FileSystemMemoryLive, makeMemoryFileSystem } from "./workspace/file-system.memory.adapter.js";
36
+ export type { MemoryFileSystem, MemorySeed } from "./workspace/file-system.memory.adapter.js";
37
+ export { fileSystemConformance } from "./workspace/file-system.conformance.js";
38
+ export type { FileSystemFixture, FileSystemSubject } from "./workspace/file-system.conformance.js";
39
+ export { bashConformance } from "./workspace/bash.conformance.js";
40
+ export type { BashFixture, BashSubject } from "./workspace/bash.conformance.js";
27
41
  export { assistantModel, assistantUsage, extractUsage, extractModel, handoffToMessage, safeKeepFrom, responseReasoning, responseText, responseToAgentMessages, responseToolCalls, responseToolResults, toPromptMessages, withToolCallIds, withUsageOnAssistant, } from "./loop/mapping.js";
28
42
  export type { ToolResultSummary } from "./loop/mapping.js";
29
43
  export { CurrentPromptCacheKey } from "./loop/cacheKey.js";
44
+ export { CurrentTraceContent, replayableContext } from "./loop/traceContent.js";
30
45
  export { foldStreamParts } from "./loop/streamFold.js";
31
46
  export { strictJsonSchema, toolParametersSchema } from "./loop/toolSchema.js";
32
47
  export type { FoldedTurn, StreamDelta } from "./loop/streamFold.js";
@@ -39,14 +54,27 @@ export * from "./session/session-log.entity.js";
39
54
  export * from "./ports/session-log.port.js";
40
55
  export { SessionLogMemoryLive } from "./session/session-log.memory.adapter.js";
41
56
  export { sessionLogConformance } from "./session/session-log.conformance.js";
57
+ export { sessionLogRecoveryConformance } from "./session/session-log.recovery.conformance.js";
58
+ export type { SessionLogSubject } from "./session/session-log.recovery.conformance.js";
42
59
  export * from "./session/session-event.entity.js";
60
+ export { JOURNAL_KINDS } from "./session/session-event.entity.js";
43
61
  export * from "./session/session-event.entity.functions.js";
62
+ export { turnUsageOf } from "./session/session-event.entity.functions.js";
44
63
  export * from "./session/sessions.entity.js";
64
+ export { resumeRefusal, turnEndingOf } from "./session/sessions.entity.functions.js";
65
+ export type { ResumableTurn } from "./session/sessions.entity.functions.js";
45
66
  export * from "./ports/sessions.port.js";
46
67
  export * from "./ports/turn-admission.port.js";
47
68
  export { TurnAdmissionOpen } from "./session/turn-admission.open.adapter.js";
48
69
  export * from "./session/tasks.entity.js";
49
70
  export * from "./ports/tasks.port.js";
71
+ export { ActiveTurn, ProcessActivity, TurnsInFlight } from "./session/activity.entity.js";
72
+ export { awaitIdle, processActivity } from "./session/activity.entity.functions.js";
73
+ export { TaskActivity, TurnActivity } from "./ports/activity.port.js";
74
+ export { sessionsConformance } from "./session/sessions.conformance.js";
75
+ export type { SessionsInstance, SessionsProcess, SessionsSubject } from "./session/sessions.conformance.js";
76
+ export { taskRunnerConformance, tasksConformance } from "./session/tasks.conformance.js";
77
+ export type { TaskRunnerFixture, TasksDependencies, TasksFixture } from "./session/tasks.conformance.js";
50
78
  export { DEFAULT_SPEC_LIMITS, renderSpecSection, SpecCheck, SpecDoc, SpecGates, SpecLimits, SpecSlug, SpecStatus, } from "./spec/SpecDoc.js";
51
79
  export { decodeSpecDocText, encodeSpecDocText, SpecDocParseError, specSlug, uniqueSlug, } from "./spec/codec.js";
52
80
  export { parseFrontmatter } from "./spec/frontmatter.js";
@@ -54,12 +82,12 @@ export * from "./harness/plugin.entity.js";
54
82
  export * from "./harness/plugin.adapter.js";
55
83
  export * from "./harness/plugin-stack.adapter.js";
56
84
  export * from "./harness/config.entity.js";
57
- export * from "./harness/session.entity.js";
58
85
  export * from "./ports/harness.port.js";
59
86
  export { defineAgent, defineConfig } from "./harness/config.entity.functions.js";
60
87
  export * from "./domain/prompt-provenance.entity.js";
61
88
  export * from "./loop/promptProvenance.js";
62
- export { CurrentAgentStep } from "./loop/stepContext.js";
89
+ export { CurrentAgentStep, CurrentToolInvocation } from "./loop/stepContext.js";
90
+ export type { ToolInvocation } from "./loop/stepContext.js";
63
91
  export * from "./decision-record.entity.js";
64
92
  export * from "./memory/memory-log.entity.js";
65
93
  export * from "./memory/memory-log.entity.functions.js";
@@ -72,7 +100,9 @@ export * from "./ports/permission.port.js";
72
100
  export * from "./ports/run-context.port.js";
73
101
  export * from "./ports/tool-registry.port.js";
74
102
  export * from "./turn/user-message.entity.js";
103
+ export { attachmentsOf, normalizeUserMessage, sameUserMessage, userMessageText } from "./turn/user-message.entity.functions.js";
75
104
  export * from "./turn/turn-event.entity.js";
105
+ export { StreamFallbackEvent, ToolRefusalReason, ToolRefusedEvent, TURN_EVENT_NAMES } from "./turn/turn-event.entity.js";
76
106
  export * from "./turn/turn-event.entity.functions.js";
77
107
  export * from "./turn/model-request.entity.js";
78
108
  export * from "./turn/model-request.entity.functions.js";
@@ -80,16 +110,24 @@ export * from "./turn/turn-bus.js";
80
110
  export * from "./ports/turn-events.port.js";
81
111
  export * from "./ports/step-loop.port.js";
82
112
  export * from "./ports/turn.port.js";
113
+ export type { TurnResult } from "./ports/turn.port.js";
83
114
  export * from "./ports/turn-scope.port.js";
84
115
  export * from "./turn/prompt-sections.js";
85
116
  export * from "./turn/turn.adapter.js";
86
117
  export * from "./turn/turn-run.js";
87
118
  export * from "./turn/turn-lifecycle.js";
119
+ export { traceTurn } from "./turn/turn-lifecycle.js";
120
+ export type { TurnTraceOptions } from "./turn/turn-lifecycle.js";
88
121
  export * from "./decision-record.entity.functions.js";
89
- export { skillsFromFiles } from "./harness/skill-files.js";
90
- export type { SkillFile } from "./harness/skill-files.js";
122
+ export { CollectSkillFilesOptions, SkillFile, SkillFileIssue, SkillFilesOptions, SkillTree, SkillTreeEntry } from "./harness/skill-files.entity.js";
123
+ export { collectSkillFiles, readSkillFiles, skillIssuesText, skillsFromFiles } from "./harness/skill-files.entity.functions.js";
91
124
  export { ConformanceFailure } from "./conformance.entity.js";
92
125
  export type { ConformanceCheck } from "./conformance.entity.js";
93
126
  export { probeCall, stepLoopConformance, textReply } from "./turn/step-loop.conformance.js";
94
127
  export { inMemoryLog, memoryConformance } from "./memory/memory.conformance.js";
95
128
  export { turnConformance } from "./turn/turn.conformance.js";
129
+ export { toolRegistryConformance } from "./turn/tool-registry.conformance.js";
130
+ export type { ToolRegistryLimits } from "./turn/tool-registry.conformance.js";
131
+ export { authStoreConformance } from "./models/auth-store.conformance.js";
132
+ export { settingsStoreConformance } from "./models/settings-store.conformance.js";
133
+ export { modelCatalogConformance } from "./models/model-catalog.conformance.js";
package/dist/index.js CHANGED
@@ -10,14 +10,49 @@ export {
10
10
  ToolCallPart,
11
11
  ToolMessage,
12
12
  ToolResultPart,
13
+ UserContentPart,
13
14
  UserRoleMessage
14
15
  } from "./domain/message.entity.js";
16
+ export {
17
+ AttachmentRejected,
18
+ AttachmentRejectedReason,
19
+ ImageMediaType,
20
+ Media,
21
+ MEDIA_LIMITS,
22
+ MediaFingerprint,
23
+ MediaSlot
24
+ } from "./domain/media.entity.js";
25
+ export {
26
+ base64Length,
27
+ elideMediaData,
28
+ IMAGE_TOKEN_ESTIMATE,
29
+ imageSizeOf,
30
+ isMediaValue,
31
+ mediaAt,
32
+ mediaFingerprintOf,
33
+ mediaFromBase64,
34
+ mediaFromBytes,
35
+ mediaLabel,
36
+ mediaSlotsOf,
37
+ normalizeMedia,
38
+ sniffImageType,
39
+ toolResultMedia
40
+ } from "./domain/media.entity.functions.js";
15
41
  export { Failure } from "./domain/failure.entity.js";
16
42
  export { toFailure } from "./domain/failure.entity.functions.js";
17
43
  export { AgentFailure, AgentFailureCategory } from "./domain/agent-failure.entity.js";
18
44
  export { toAgentFailure, toolResultFailure } from "./domain/agent-failure.entity.functions.js";
19
- export { TokenUsage } from "./domain/token-usage.entity.js";
20
- export { addUsage, zeroUsage } from "./domain/token-usage.entity.functions.js";
45
+ export { BudgetTokens, ModelPrice, TokenUsage, UsageBreakdown } from "./domain/token-usage.entity.js";
46
+ export {
47
+ addUsage,
48
+ costOf,
49
+ isBudgetTokens,
50
+ sumUsage,
51
+ tokenUsage,
52
+ uncachedInputTokens,
53
+ usageBreakdown,
54
+ zeroUsage
55
+ } from "./domain/token-usage.entity.functions.js";
21
56
  export {
22
57
  ModelId,
23
58
  ModelSelection,
@@ -27,13 +62,10 @@ export { ModelCallPolicy, ReasoningEffort } from "./domain/model-call-policy.ent
27
62
  export { ModelCatalogEntry } from "./domain/model-catalog.entity.js";
28
63
  export { CurrentEmptyResponseTolerance, CurrentModelCallPolicy } from "./loop/modelPolicy.js";
29
64
  export { formatModelSelection, parseModelSelection } from "./domain/model-selection.entity.functions.js";
30
- export {
31
- ConversationStore,
32
- ConversationSummary,
33
- RunOutcomeRecord,
34
- StoredMessage,
35
- StoreError
36
- } from "./ports/conversation-store.port.js";
65
+ export { DirEntry, FileInfo, FileKind, FsError, FsReason, GlobOptions, GlobResult, ReadRange, RecursiveOptions, StatOptions, WriteOptions } from "./domain/file-system.entity.js";
66
+ export { walkGlob } from "./domain/file-system.entity.functions.js";
67
+ export { BASH_ENV_ALLOWLIST, BashChunk, BashError, BashErrorReason, BashEvent, BashExit, BashOptions, BashResult, BashTermination } from "./domain/bash.entity.js";
68
+ export { collectBashResult, resolveBashEnv } from "./domain/bash.entity.functions.js";
37
69
  export {
38
70
  EngineSettings,
39
71
  SETTINGS_KEYS,
@@ -42,10 +74,14 @@ export {
42
74
  } from "./ports/settings-store.port.js";
43
75
  export { AuthError, AuthStore, Credential } from "./ports/auth-store.port.js";
44
76
  export { ModelCatalog } from "./ports/model-catalog.port.js";
45
- export { FileSystem, FsError } from "./ports/file-system.port.js";
46
- export { Shell, ShellError, ShellResult } from "./ports/shell.port.js";
77
+ export { FileSystem } from "./ports/file-system.port.js";
78
+ export { Bash } from "./ports/bash.port.js";
47
79
  export { UtilityCompletion, UtilityError, UtilityLlm } from "./ports/utility-llm.port.js";
48
80
  export { asJsonRecord, decodeJsonLines, parseJsonOption, parseJsonWarn } from "./util/json.js";
81
+ export { compileGlob, globMatcher } from "./util/glob.js";
82
+ export { FileSystemMemoryLive, makeMemoryFileSystem } from "./workspace/file-system.memory.adapter.js";
83
+ export { fileSystemConformance } from "./workspace/file-system.conformance.js";
84
+ export { bashConformance } from "./workspace/bash.conformance.js";
49
85
  export {
50
86
  assistantModel,
51
87
  assistantUsage,
@@ -63,6 +99,7 @@ export {
63
99
  withUsageOnAssistant
64
100
  } from "./loop/mapping.js";
65
101
  export { CurrentPromptCacheKey } from "./loop/cacheKey.js";
102
+ export { CurrentTraceContent, replayableContext } from "./loop/traceContent.js";
66
103
  export { foldStreamParts } from "./loop/streamFold.js";
67
104
  export { strictJsonSchema, toolParametersSchema } from "./loop/toolSchema.js";
68
105
  export { McpCallOutcome, McpClient, McpError, McpToolDescriptor } from "./ports/mcp-client.port.js";
@@ -72,14 +109,23 @@ export * from "./session/session-log.entity.js";
72
109
  export * from "./ports/session-log.port.js";
73
110
  export { SessionLogMemoryLive } from "./session/session-log.memory.adapter.js";
74
111
  export { sessionLogConformance } from "./session/session-log.conformance.js";
112
+ export { sessionLogRecoveryConformance } from "./session/session-log.recovery.conformance.js";
75
113
  export * from "./session/session-event.entity.js";
114
+ export { JOURNAL_KINDS } from "./session/session-event.entity.js";
76
115
  export * from "./session/session-event.entity.functions.js";
116
+ export { turnUsageOf } from "./session/session-event.entity.functions.js";
77
117
  export * from "./session/sessions.entity.js";
118
+ export { resumeRefusal, turnEndingOf } from "./session/sessions.entity.functions.js";
78
119
  export * from "./ports/sessions.port.js";
79
120
  export * from "./ports/turn-admission.port.js";
80
121
  export { TurnAdmissionOpen } from "./session/turn-admission.open.adapter.js";
81
122
  export * from "./session/tasks.entity.js";
82
123
  export * from "./ports/tasks.port.js";
124
+ export { ActiveTurn, ProcessActivity, TurnsInFlight } from "./session/activity.entity.js";
125
+ export { awaitIdle, processActivity } from "./session/activity.entity.functions.js";
126
+ export { TaskActivity, TurnActivity } from "./ports/activity.port.js";
127
+ export { sessionsConformance } from "./session/sessions.conformance.js";
128
+ export { taskRunnerConformance, tasksConformance } from "./session/tasks.conformance.js";
83
129
  export {
84
130
  DEFAULT_SPEC_LIMITS,
85
131
  renderSpecSection,
@@ -102,12 +148,11 @@ export * from "./harness/plugin.entity.js";
102
148
  export * from "./harness/plugin.adapter.js";
103
149
  export * from "./harness/plugin-stack.adapter.js";
104
150
  export * from "./harness/config.entity.js";
105
- export * from "./harness/session.entity.js";
106
151
  export * from "./ports/harness.port.js";
107
152
  export { defineAgent, defineConfig } from "./harness/config.entity.functions.js";
108
153
  export * from "./domain/prompt-provenance.entity.js";
109
154
  export * from "./loop/promptProvenance.js";
110
- export { CurrentAgentStep } from "./loop/stepContext.js";
155
+ export { CurrentAgentStep, CurrentToolInvocation } from "./loop/stepContext.js";
111
156
  export * from "./decision-record.entity.js";
112
157
  export * from "./memory/memory-log.entity.js";
113
158
  export * from "./memory/memory-log.entity.functions.js";
@@ -120,7 +165,9 @@ export * from "./ports/permission.port.js";
120
165
  export * from "./ports/run-context.port.js";
121
166
  export * from "./ports/tool-registry.port.js";
122
167
  export * from "./turn/user-message.entity.js";
168
+ export { attachmentsOf, normalizeUserMessage, sameUserMessage, userMessageText } from "./turn/user-message.entity.functions.js";
123
169
  export * from "./turn/turn-event.entity.js";
170
+ export { StreamFallbackEvent, ToolRefusalReason, ToolRefusedEvent, TURN_EVENT_NAMES } from "./turn/turn-event.entity.js";
124
171
  export * from "./turn/turn-event.entity.functions.js";
125
172
  export * from "./turn/model-request.entity.js";
126
173
  export * from "./turn/model-request.entity.functions.js";
@@ -133,9 +180,15 @@ export * from "./turn/prompt-sections.js";
133
180
  export * from "./turn/turn.adapter.js";
134
181
  export * from "./turn/turn-run.js";
135
182
  export * from "./turn/turn-lifecycle.js";
183
+ export { traceTurn } from "./turn/turn-lifecycle.js";
136
184
  export * from "./decision-record.entity.functions.js";
137
- export { skillsFromFiles } from "./harness/skill-files.js";
185
+ export { CollectSkillFilesOptions, SkillFile, SkillFileIssue, SkillFilesOptions, SkillTree, SkillTreeEntry } from "./harness/skill-files.entity.js";
186
+ export { collectSkillFiles, readSkillFiles, skillIssuesText, skillsFromFiles } from "./harness/skill-files.entity.functions.js";
138
187
  export { ConformanceFailure } from "./conformance.entity.js";
139
188
  export { probeCall, stepLoopConformance, textReply } from "./turn/step-loop.conformance.js";
140
189
  export { inMemoryLog, memoryConformance } from "./memory/memory.conformance.js";
141
190
  export { turnConformance } from "./turn/turn.conformance.js";
191
+ export { toolRegistryConformance } from "./turn/tool-registry.conformance.js";
192
+ export { authStoreConformance } from "./models/auth-store.conformance.js";
193
+ export { settingsStoreConformance } from "./models/settings-store.conformance.js";
194
+ export { modelCatalogConformance } from "./models/model-catalog.conformance.js";