@theokit/sdk 2.23.0 → 2.25.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 +56 -0
- package/dist/a2a/index.cjs +259 -192
- package/dist/a2a/index.cjs.map +1 -1
- package/dist/a2a/index.js +259 -192
- package/dist/a2a/index.js.map +1 -1
- package/dist/create-skill.d.ts +8 -0
- package/dist/{cron-7CruUd_0.d.ts → cron-B44D-678.d.ts} +67 -4
- package/dist/{cron-Bpt_1khA.d.cts → cron-qI-dbG7c.d.cts} +67 -4
- package/dist/cron.cjs +246 -181
- package/dist/cron.cjs.map +1 -1
- package/dist/cron.d.cts +2 -2
- package/dist/cron.d.ts +2 -2
- package/dist/cron.js +246 -181
- package/dist/cron.js.map +1 -1
- package/dist/define-tool.d.ts +33 -20
- package/dist/{errors-CkCaIqVP.d.cts → errors-DIKBXffg.d.cts} +1 -1
- package/dist/{errors-BuwwkrAk.d.ts → errors-DRS-kqOK.d.ts} +1 -1
- package/dist/errors.d.cts +2 -2
- package/dist/eval.cjs +246 -181
- package/dist/eval.cjs.map +1 -1
- package/dist/eval.js +246 -181
- package/dist/eval.js.map +1 -1
- package/dist/index.cjs +299 -186
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +75 -27
- package/dist/index.d.ts +75 -27
- package/dist/index.js +299 -187
- package/dist/index.js.map +1 -1
- package/dist/internal/runtime/local-agent/local-agent-bootstrap.d.ts +2 -4
- package/dist/internal/runtime/skills/skill-frontmatter.d.ts +6 -0
- package/dist/{run-CrIulPF7.d.cts → run-Cr0C6cOM.d.cts} +17 -0
- package/dist/{run-CrIulPF7.d.ts → run-Cr0C6cOM.d.ts} +17 -0
- package/dist/skills.cjs.map +1 -1
- package/dist/skills.js.map +1 -1
- package/dist/types/agent.d.ts +57 -2
- package/dist/types/run.d.ts +17 -0
- package/dist/workflow.cjs +37 -0
- package/dist/workflow.cjs.map +1 -1
- package/dist/workflow.d.cts +47 -1
- package/dist/workflow.d.ts +47 -1
- package/dist/workflow.js +37 -2
- package/dist/workflow.js.map +1 -1
- package/package.json +1 -1
package/dist/define-tool.d.ts
CHANGED
|
@@ -1,13 +1,21 @@
|
|
|
1
1
|
import type { z as ZodNamespace, ZodType } from "zod";
|
|
2
2
|
import type { SanitizeOptions } from "./sanitize/types.js";
|
|
3
3
|
import type { CustomTool } from "./types/agent.js";
|
|
4
|
+
import type { ToolResultContentBlock } from "./types/content-blocks.js";
|
|
4
5
|
/**
|
|
5
6
|
* Spec accepted by {@link defineTool}. `inputSchema` is a Zod schema; the
|
|
6
7
|
* `handler` argument type is inferred via `z.infer<T>` — no `as` casts.
|
|
7
8
|
*
|
|
8
9
|
* @public
|
|
9
10
|
*/
|
|
10
|
-
|
|
11
|
+
/**
|
|
12
|
+
* SE16 — the handler's return type. With no `outputSchema` the tool returns a
|
|
13
|
+
* plain `string` (pre-SE16 shape). With an `outputSchema` the handler returns the
|
|
14
|
+
* STRUCTURED output inferred from it (validated + serialized to the tool result).
|
|
15
|
+
* The `[O]` tuple wrap prevents distribution so `never` maps cleanly to `string`.
|
|
16
|
+
*/
|
|
17
|
+
type ToolHandlerReturn<O extends ZodType> = [O] extends [never] ? string : ZodNamespace.infer<O>;
|
|
18
|
+
export interface DefineToolSpec<T extends ZodType, O extends ZodType = never> {
|
|
11
19
|
/** Tool name surfaced to the LLM. Same constraints as {@link CustomTool.name}. */
|
|
12
20
|
name: string;
|
|
13
21
|
/** Description surfaced to the LLM. */
|
|
@@ -15,7 +23,16 @@ export interface DefineToolSpec<T extends ZodType> {
|
|
|
15
23
|
/** Zod schema describing the input. Must be `z.object(...)` at the root for the LLM tool contract. */
|
|
16
24
|
inputSchema: T;
|
|
17
25
|
/**
|
|
18
|
-
*
|
|
26
|
+
* SE16 — optional Zod schema describing the OUTPUT. When set, the handler
|
|
27
|
+
* returns the structured value inferred from it; the value is validated against
|
|
28
|
+
* this schema and serialized to the tool result (a string stays as-is, an object
|
|
29
|
+
* is JSON-stringified). A validation failure raises `ZodError`, converted to a
|
|
30
|
+
* `tool_result(isError)`. Absent ⇒ the handler returns a plain string (unchanged).
|
|
31
|
+
*/
|
|
32
|
+
outputSchema?: O;
|
|
33
|
+
/**
|
|
34
|
+
* Handler invoked with the parsed input. Type is inferred via `z.infer<T>`; the
|
|
35
|
+
* return type is `z.infer<O>` when `outputSchema` is set, else `string`.
|
|
19
36
|
* #65 — an optional 2nd `ToolContext` argument carries the run's `AbortSignal`,
|
|
20
37
|
* so a cooperative handler can stop early when the run is cancelled. Existing
|
|
21
38
|
* single-argument handlers are unaffected.
|
|
@@ -23,7 +40,18 @@ export interface DefineToolSpec<T extends ZodType> {
|
|
|
23
40
|
handler: (input: ZodNamespace.infer<T>, ctx?: {
|
|
24
41
|
signal?: AbortSignal;
|
|
25
42
|
context?: unknown;
|
|
26
|
-
}) =>
|
|
43
|
+
}) => ToolHandlerReturn<O> | Promise<ToolHandlerReturn<O>>;
|
|
44
|
+
/**
|
|
45
|
+
* SE17 — map the handler's (validated) output to the compact / multimodal
|
|
46
|
+
* representation the MODEL sees in the tool_result. The handler keeps returning
|
|
47
|
+
* the FULL result (validated by `outputSchema`); `toModelOutput` shapes only what
|
|
48
|
+
* reaches the model, so app-facing detail is not forced into model context.
|
|
49
|
+
* Returns a string OR SE7 `ToolResultContentBlock[]` (text + image). Absent ⇒
|
|
50
|
+
* the tool_result is the serialized handler output (SE16 / pre-SE17 behavior).
|
|
51
|
+
* Note: observability (`onToolEnd`) sees the model-facing result this returns,
|
|
52
|
+
* not the raw handler output — the full result lives in the handler's own scope.
|
|
53
|
+
*/
|
|
54
|
+
toModelOutput?: (output: ToolHandlerReturn<O>) => string | ToolResultContentBlock[];
|
|
27
55
|
/**
|
|
28
56
|
* Sanitize the raw model-emitted args BEFORE schema validation (`@theokit/sdk/sanitize`).
|
|
29
57
|
* `true` trims whitespace; an object opts into coercion / JSON-repair. Coercion is schema-aware
|
|
@@ -32,20 +60,5 @@ export interface DefineToolSpec<T extends ZodType> {
|
|
|
32
60
|
*/
|
|
33
61
|
sanitize?: boolean | SanitizeOptions;
|
|
34
62
|
}
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
* Schema (for the LLM-facing `inputSchema` field), wraps the handler with a
|
|
38
|
-
* runtime `schema.parse` step, and preserves type inference.
|
|
39
|
-
*
|
|
40
|
-
* Behaviour (ADR D24):
|
|
41
|
-
* - JSON Schema conversion uses Zod 4's native `z.toJSONSchema` with
|
|
42
|
-
* `unrepresentable: "any"` so transforms/refinements round-trip.
|
|
43
|
-
* - Runtime parse failures throw `ZodError`; the SDK's tool-dispatch converts
|
|
44
|
-
* them to `tool_result(isError)` with the Zod message.
|
|
45
|
-
* - Handler signature is `(input: z.infer<T>)`, not `Record<string, unknown>`.
|
|
46
|
-
* - `zod` loads lazily via `createRequire` — consumers who don't call
|
|
47
|
-
* `defineTool` don't need `zod` installed.
|
|
48
|
-
*
|
|
49
|
-
* @public
|
|
50
|
-
*/
|
|
51
|
-
export declare function defineTool<T extends ZodType>(spec: DefineToolSpec<T>): CustomTool;
|
|
63
|
+
export declare function defineTool<T extends ZodType, O extends ZodType = never>(spec: DefineToolSpec<T, O>): CustomTool;
|
|
64
|
+
export {};
|
package/dist/errors.d.cts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export { A as AgentDisposedError, c as AgentRunError, d as AgentRunErrorCode, e as AuthenticationError, g as BudgetExceededError, C as ConfigurationError, u as CredentialPoolExhaustedError, m as ErrorCode, E as ErrorMetadata, I as IntegrationNotConnectedError, n as InvalidTaskIdError, K as KnownAgentRunErrorCode, M as MemoryAdapterError, o as MemoryAdapterErrorCode, N as NetworkError, R as RateLimitError, p as TaskNotFoundError, T as TheokitAgentError, U as UnknownAgentError, q as UnsupportedBudgetOperationError, r as UnsupportedRunOperationError, s as UnsupportedTaskOperationError, t as isTransientError } from './errors-
|
|
2
|
-
import './run-
|
|
1
|
+
export { A as AgentDisposedError, c as AgentRunError, d as AgentRunErrorCode, e as AuthenticationError, g as BudgetExceededError, C as ConfigurationError, u as CredentialPoolExhaustedError, m as ErrorCode, E as ErrorMetadata, I as IntegrationNotConnectedError, n as InvalidTaskIdError, K as KnownAgentRunErrorCode, M as MemoryAdapterError, o as MemoryAdapterErrorCode, N as NetworkError, R as RateLimitError, p as TaskNotFoundError, T as TheokitAgentError, U as UnknownAgentError, q as UnsupportedBudgetOperationError, r as UnsupportedRunOperationError, s as UnsupportedTaskOperationError, t as isTransientError } from './errors-DIKBXffg.cjs';
|
|
2
|
+
import './run-Cr0C6cOM.cjs';
|
|
3
3
|
import 'zod';
|
package/dist/eval.cjs
CHANGED
|
@@ -3457,7 +3457,8 @@ function stripSecretsFromOptions(options) {
|
|
|
3457
3457
|
local: serializeLocal(options.local),
|
|
3458
3458
|
cloud: serializeCloud(options.cloud),
|
|
3459
3459
|
memory: serializeMemory(options.memory),
|
|
3460
|
-
|
|
3460
|
+
// SE22 — a SkillsResolver function isn't serializable; persist only the static form.
|
|
3461
|
+
skills: serializeEnabledList(typeof options.skills === "function" ? void 0 : options.skills),
|
|
3461
3462
|
// Code-`Plugin` objects are closures and cannot be persisted (like custom
|
|
3462
3463
|
// tools); only the named-enable settings form is serialized.
|
|
3463
3464
|
plugins: serializeEnabledList(asPluginsSettings(options.plugins)),
|
|
@@ -3765,6 +3766,7 @@ function serializeCloud2(cloud) {
|
|
|
3765
3766
|
return result;
|
|
3766
3767
|
}
|
|
3767
3768
|
function serializeSkills(skills) {
|
|
3769
|
+
if (typeof skills === "function") return void 0;
|
|
3768
3770
|
if (skills?.enabled === void 0 || skills.enabled.length === 0) return void 0;
|
|
3769
3771
|
return { enabled: [...skills.enabled] };
|
|
3770
3772
|
}
|
|
@@ -5236,6 +5238,7 @@ init_errors();
|
|
|
5236
5238
|
function validateCloudToolParity(options) {
|
|
5237
5239
|
if (options.cloud === void 0) return;
|
|
5238
5240
|
rejectFunctionSystemPrompt(options);
|
|
5241
|
+
rejectFunctionSkills(options);
|
|
5239
5242
|
rejectStdioMcpLocalPaths(options);
|
|
5240
5243
|
}
|
|
5241
5244
|
function rejectFunctionSystemPrompt(options) {
|
|
@@ -5246,6 +5249,14 @@ function rejectFunctionSystemPrompt(options) {
|
|
|
5246
5249
|
);
|
|
5247
5250
|
}
|
|
5248
5251
|
}
|
|
5252
|
+
function rejectFunctionSkills(options) {
|
|
5253
|
+
if (typeof options.skills === "function") {
|
|
5254
|
+
throw new ConfigurationError(
|
|
5255
|
+
"Cloud agents require skills as a static settings object. SkillsResolver functions can't run on PaaS \u2014 resolve to a SkillsSettings object before Agent.create() or move the dynamic logic into a hook rule.",
|
|
5256
|
+
{ code: "cloud_incompatible_function_resolver" }
|
|
5257
|
+
);
|
|
5258
|
+
}
|
|
5259
|
+
}
|
|
5249
5260
|
function rejectStdioMcpLocalPaths(options) {
|
|
5250
5261
|
if (options.mcpServers === void 0) return;
|
|
5251
5262
|
for (const [name, config] of Object.entries(options.mcpServers)) {
|
|
@@ -7102,9 +7113,223 @@ function parseFrontmatterFields(frontmatter) {
|
|
|
7102
7113
|
return out;
|
|
7103
7114
|
}
|
|
7104
7115
|
|
|
7116
|
+
// src/internal/runtime/skills/discover-skills.ts
|
|
7117
|
+
init_errors();
|
|
7118
|
+
|
|
7119
|
+
// src/internal/runtime/skills/skill-frontmatter.ts
|
|
7120
|
+
init_errors();
|
|
7121
|
+
init_yaml_frontmatter();
|
|
7122
|
+
function asString(v) {
|
|
7123
|
+
return typeof v === "string" ? v : void 0;
|
|
7124
|
+
}
|
|
7125
|
+
function toStringFields(raw) {
|
|
7126
|
+
const out = {};
|
|
7127
|
+
for (const [k, v] of Object.entries(raw)) out[k] = asString(v);
|
|
7128
|
+
return out;
|
|
7129
|
+
}
|
|
7130
|
+
function parseSkillFrontmatter(raw, fallbackName) {
|
|
7131
|
+
const fields = extractAndParseFrontmatter(raw, fallbackName);
|
|
7132
|
+
const name = resolveName(fields, fallbackName);
|
|
7133
|
+
ensureRequiredFields(fields, name);
|
|
7134
|
+
return buildFrontmatter(fields, name);
|
|
7135
|
+
}
|
|
7136
|
+
function stripSkillFrontmatter(raw) {
|
|
7137
|
+
const match = /^---\s*\n[\s\S]*?\n---\s*\n/.exec(raw);
|
|
7138
|
+
return (match === null ? raw : raw.slice(match[0].length)).trim();
|
|
7139
|
+
}
|
|
7140
|
+
function extractAndParseFrontmatter(raw, fallbackName) {
|
|
7141
|
+
const match = /^---\s*\n([\s\S]*?)\n---\s*\n/.exec(raw);
|
|
7142
|
+
if (match === null) {
|
|
7143
|
+
throw new ConfigurationError(`Skill ${fallbackName} is missing frontmatter`, {
|
|
7144
|
+
code: "missing_frontmatter"
|
|
7145
|
+
});
|
|
7146
|
+
}
|
|
7147
|
+
const frontmatter = match[1] ?? "";
|
|
7148
|
+
try {
|
|
7149
|
+
return toStringFields(parseSimpleYaml(frontmatter));
|
|
7150
|
+
} catch (cause) {
|
|
7151
|
+
const detail = cause instanceof Error ? cause.message : String(cause);
|
|
7152
|
+
throw new ConfigurationError(
|
|
7153
|
+
`Skill ${fallbackName} has malformed YAML frontmatter: ${detail}`,
|
|
7154
|
+
{ code: "schema_invalid", cause }
|
|
7155
|
+
);
|
|
7156
|
+
}
|
|
7157
|
+
}
|
|
7158
|
+
function resolveName(fields, fallbackName) {
|
|
7159
|
+
if (hasContent(fields.name)) return fields.name;
|
|
7160
|
+
if (hasContent(fallbackName)) return fallbackName;
|
|
7161
|
+
throw new ConfigurationError("Skill at unknown path is missing required field: name", {
|
|
7162
|
+
code: "schema_invalid"
|
|
7163
|
+
});
|
|
7164
|
+
}
|
|
7165
|
+
function ensureRequiredFields(fields, name) {
|
|
7166
|
+
if (!hasContent(fields.description)) {
|
|
7167
|
+
throw new ConfigurationError(`Skill ${name} is missing required field: description`, {
|
|
7168
|
+
code: "schema_invalid"
|
|
7169
|
+
});
|
|
7170
|
+
}
|
|
7171
|
+
}
|
|
7172
|
+
function buildFrontmatter(fields, name) {
|
|
7173
|
+
const description = fields.description;
|
|
7174
|
+
if (description === void 0) {
|
|
7175
|
+
throw new ConfigurationError(`Skill ${name} missing description`, { code: "schema_invalid" });
|
|
7176
|
+
}
|
|
7177
|
+
const result = { name, description };
|
|
7178
|
+
if (hasContent(fields.category)) result.category = fields.category;
|
|
7179
|
+
const deps = parseDependencies(fields.dependencies);
|
|
7180
|
+
if (deps !== void 0) result.dependencies = deps;
|
|
7181
|
+
return result;
|
|
7182
|
+
}
|
|
7183
|
+
function parseDependencies(raw) {
|
|
7184
|
+
if (!hasContent(raw)) return void 0;
|
|
7185
|
+
const deps = raw.split(",").map((s) => s.trim()).filter((s) => s.length > 0);
|
|
7186
|
+
return deps.length > 0 ? deps : void 0;
|
|
7187
|
+
}
|
|
7188
|
+
function hasContent(value) {
|
|
7189
|
+
return value !== void 0 && value.trim().length > 0;
|
|
7190
|
+
}
|
|
7191
|
+
|
|
7192
|
+
// src/internal/runtime/skills/discover-skills.ts
|
|
7193
|
+
async function discoverSkills(dir, options) {
|
|
7194
|
+
let entries;
|
|
7195
|
+
try {
|
|
7196
|
+
entries = await readWorkspaceDir(dir, "skills_read_error", "skills directory");
|
|
7197
|
+
} catch {
|
|
7198
|
+
return [];
|
|
7199
|
+
}
|
|
7200
|
+
const skills = [];
|
|
7201
|
+
for (const entry of entries) {
|
|
7202
|
+
if (!entry.isDirectory()) continue;
|
|
7203
|
+
let skillDir;
|
|
7204
|
+
try {
|
|
7205
|
+
skillDir = safePathJoin(dir, entry.name);
|
|
7206
|
+
assertNoSymlinkEscape(skillDir, dir);
|
|
7207
|
+
} catch {
|
|
7208
|
+
continue;
|
|
7209
|
+
}
|
|
7210
|
+
const skillPath = path.join(skillDir, "SKILL.md");
|
|
7211
|
+
let raw;
|
|
7212
|
+
try {
|
|
7213
|
+
raw = await promises.readFile(skillPath, "utf8");
|
|
7214
|
+
} catch {
|
|
7215
|
+
continue;
|
|
7216
|
+
}
|
|
7217
|
+
const skill = tryParseSkill(raw, entry.name, skillPath, options);
|
|
7218
|
+
if (skill !== void 0) skills.push(skill);
|
|
7219
|
+
}
|
|
7220
|
+
return skills;
|
|
7221
|
+
}
|
|
7222
|
+
function tryParseSkill(raw, fallbackName, source, options) {
|
|
7223
|
+
try {
|
|
7224
|
+
const frontmatter = parseSkillFrontmatter(raw, fallbackName);
|
|
7225
|
+
const skill = {
|
|
7226
|
+
name: frontmatter.name,
|
|
7227
|
+
description: frontmatter.description,
|
|
7228
|
+
source
|
|
7229
|
+
};
|
|
7230
|
+
if (frontmatter.category !== void 0) skill.category = frontmatter.category;
|
|
7231
|
+
if (frontmatter.dependencies !== void 0) skill.dependencies = frontmatter.dependencies;
|
|
7232
|
+
return skill;
|
|
7233
|
+
} catch (cause) {
|
|
7234
|
+
if (cause instanceof ConfigurationError) {
|
|
7235
|
+
options?.onInvalidSkill?.({
|
|
7236
|
+
name: fallbackName,
|
|
7237
|
+
source,
|
|
7238
|
+
code: cause.code ?? "unknown",
|
|
7239
|
+
message: cause.message
|
|
7240
|
+
});
|
|
7241
|
+
return void 0;
|
|
7242
|
+
}
|
|
7243
|
+
throw cause;
|
|
7244
|
+
}
|
|
7245
|
+
}
|
|
7246
|
+
|
|
7247
|
+
// src/internal/runtime/skills/skills-manager.ts
|
|
7248
|
+
var SkillsManager = class {
|
|
7249
|
+
constructor(cwd, _enabled, settingSourcesIncludeProject, skillsDir, inline) {
|
|
7250
|
+
this.cwd = cwd;
|
|
7251
|
+
this.settingSourcesIncludeProject = settingSourcesIncludeProject;
|
|
7252
|
+
this.skillsDir = skillsDir;
|
|
7253
|
+
this.inline = inline;
|
|
7254
|
+
}
|
|
7255
|
+
cwd;
|
|
7256
|
+
settingSourcesIncludeProject;
|
|
7257
|
+
skillsDir;
|
|
7258
|
+
inline;
|
|
7259
|
+
skills = [];
|
|
7260
|
+
async initialize() {
|
|
7261
|
+
if (!this.settingSourcesIncludeProject) {
|
|
7262
|
+
this.skills = this.mergeInline([]);
|
|
7263
|
+
return;
|
|
7264
|
+
}
|
|
7265
|
+
await this.refresh();
|
|
7266
|
+
}
|
|
7267
|
+
async refresh() {
|
|
7268
|
+
const skillsRoot = this.skillsDir ?? path.join(this.cwd, ".theokit", "skills");
|
|
7269
|
+
const discovered = await discoverSkills(skillsRoot, {
|
|
7270
|
+
onInvalidSkill: (info) => {
|
|
7271
|
+
process.stderr.write(
|
|
7272
|
+
`[theokit-sdk] skill ${info.name} skipped (${info.code}): ${info.message}
|
|
7273
|
+
`
|
|
7274
|
+
);
|
|
7275
|
+
}
|
|
7276
|
+
});
|
|
7277
|
+
this.skills = this.mergeInline(discovered);
|
|
7278
|
+
}
|
|
7279
|
+
/** M22 — merge inline skills over discovered ones; inline wins on a name conflict. */
|
|
7280
|
+
mergeInline(discovered) {
|
|
7281
|
+
if (this.inline === void 0 || this.inline.length === 0) return discovered;
|
|
7282
|
+
const inlineNames = new Set(this.inline.map((s) => s.name));
|
|
7283
|
+
return [...discovered.filter((s) => !inlineNames.has(s.name)), ...this.inline];
|
|
7284
|
+
}
|
|
7285
|
+
list() {
|
|
7286
|
+
return Promise.resolve(this.skills);
|
|
7287
|
+
}
|
|
7288
|
+
/**
|
|
7289
|
+
* SE20 — resolve a skill by name INCLUDING its body. Inline (`createSkill`)
|
|
7290
|
+
* skills carry `instructions` on the object; filesystem skills read the body
|
|
7291
|
+
* from their `source` SKILL.md (frontmatter stripped). `undefined` when no
|
|
7292
|
+
* enabled skill matches (malformed skills were already excluded at discovery).
|
|
7293
|
+
*/
|
|
7294
|
+
async get(name) {
|
|
7295
|
+
const skill = this.skills.find((s) => s.name === name);
|
|
7296
|
+
if (skill === void 0) return void 0;
|
|
7297
|
+
const instructions = typeof skill.instructions === "string" ? skill.instructions : stripSkillFrontmatter(await promises.readFile(skill.source, "utf8"));
|
|
7298
|
+
const references = skill.references;
|
|
7299
|
+
return {
|
|
7300
|
+
name: skill.name,
|
|
7301
|
+
description: skill.description,
|
|
7302
|
+
instructions,
|
|
7303
|
+
...references !== void 0 ? { references } : {}
|
|
7304
|
+
};
|
|
7305
|
+
}
|
|
7306
|
+
};
|
|
7307
|
+
|
|
7105
7308
|
// src/internal/runtime/system-prompt/local-assembly.ts
|
|
7106
|
-
async function
|
|
7107
|
-
const skills = inputs.
|
|
7309
|
+
async function resolveSendSkills(inputs, userText, memoryFacts) {
|
|
7310
|
+
const skills = inputs.options.skills;
|
|
7311
|
+
if (typeof skills !== "function") {
|
|
7312
|
+
return { manager: inputs.skillsManager, autoInject: skills?.autoInject ?? true };
|
|
7313
|
+
}
|
|
7314
|
+
const settings = await skills({
|
|
7315
|
+
agentId: inputs.agentId,
|
|
7316
|
+
cwd: inputs.workspaceCwd,
|
|
7317
|
+
model: inputs.model,
|
|
7318
|
+
userMessage: userText,
|
|
7319
|
+
memory: memoryFacts.map((fact) => ({ text: fact.text }))
|
|
7320
|
+
});
|
|
7321
|
+
const manager = new SkillsManager(
|
|
7322
|
+
inputs.workspaceCwd,
|
|
7323
|
+
settings.enabled,
|
|
7324
|
+
inputs.settingSourcesIncludeProject,
|
|
7325
|
+
settings.skillsDir,
|
|
7326
|
+
settings.inline
|
|
7327
|
+
);
|
|
7328
|
+
await manager.initialize();
|
|
7329
|
+
return { manager, autoInject: settings.autoInject ?? true };
|
|
7330
|
+
}
|
|
7331
|
+
async function buildSystemPromptContext(inputs, userText, memoryFacts, manager = inputs.skillsManager) {
|
|
7332
|
+
const skills = manager !== void 0 ? await manager.list() : [];
|
|
7108
7333
|
return {
|
|
7109
7334
|
agentId: inputs.agentId,
|
|
7110
7335
|
cwd: inputs.workspaceCwd,
|
|
@@ -7115,10 +7340,11 @@ async function buildSystemPromptContext(inputs, userText, memoryFacts) {
|
|
|
7115
7340
|
};
|
|
7116
7341
|
}
|
|
7117
7342
|
async function buildAssemblyContext(inputs, userText, baseSystemPrompt, memoryFacts, activeMemorySummary) {
|
|
7118
|
-
const
|
|
7343
|
+
const resolved = await resolveSendSkills(inputs, userText, memoryFacts);
|
|
7344
|
+
const baseCtx = await buildSystemPromptContext(inputs, userText, memoryFacts, resolved.manager);
|
|
7119
7345
|
const assemblyCtx = {
|
|
7120
7346
|
...baseCtx,
|
|
7121
|
-
skillsAutoInject:
|
|
7347
|
+
skillsAutoInject: resolved.autoInject,
|
|
7122
7348
|
memoryAutoInject: inputs.options.memory?.autoInject ?? true
|
|
7123
7349
|
};
|
|
7124
7350
|
if (baseSystemPrompt !== void 0) assemblyCtx.baseSystemPrompt = baseSystemPrompt;
|
|
@@ -8370,176 +8596,6 @@ async function loadPluginManifestFromMarkdown(pluginsRoot, folderName) {
|
|
|
8370
8596
|
return metadata;
|
|
8371
8597
|
}
|
|
8372
8598
|
|
|
8373
|
-
// src/internal/runtime/skills/discover-skills.ts
|
|
8374
|
-
init_errors();
|
|
8375
|
-
|
|
8376
|
-
// src/internal/runtime/skills/skill-frontmatter.ts
|
|
8377
|
-
init_errors();
|
|
8378
|
-
init_yaml_frontmatter();
|
|
8379
|
-
function asString(v) {
|
|
8380
|
-
return typeof v === "string" ? v : void 0;
|
|
8381
|
-
}
|
|
8382
|
-
function toStringFields(raw) {
|
|
8383
|
-
const out = {};
|
|
8384
|
-
for (const [k, v] of Object.entries(raw)) out[k] = asString(v);
|
|
8385
|
-
return out;
|
|
8386
|
-
}
|
|
8387
|
-
function parseSkillFrontmatter(raw, fallbackName) {
|
|
8388
|
-
const fields = extractAndParseFrontmatter(raw, fallbackName);
|
|
8389
|
-
const name = resolveName(fields, fallbackName);
|
|
8390
|
-
ensureRequiredFields(fields, name);
|
|
8391
|
-
return buildFrontmatter(fields, name);
|
|
8392
|
-
}
|
|
8393
|
-
function extractAndParseFrontmatter(raw, fallbackName) {
|
|
8394
|
-
const match = /^---\s*\n([\s\S]*?)\n---\s*\n/.exec(raw);
|
|
8395
|
-
if (match === null) {
|
|
8396
|
-
throw new ConfigurationError(`Skill ${fallbackName} is missing frontmatter`, {
|
|
8397
|
-
code: "missing_frontmatter"
|
|
8398
|
-
});
|
|
8399
|
-
}
|
|
8400
|
-
const frontmatter = match[1] ?? "";
|
|
8401
|
-
try {
|
|
8402
|
-
return toStringFields(parseSimpleYaml(frontmatter));
|
|
8403
|
-
} catch (cause) {
|
|
8404
|
-
const detail = cause instanceof Error ? cause.message : String(cause);
|
|
8405
|
-
throw new ConfigurationError(
|
|
8406
|
-
`Skill ${fallbackName} has malformed YAML frontmatter: ${detail}`,
|
|
8407
|
-
{ code: "schema_invalid", cause }
|
|
8408
|
-
);
|
|
8409
|
-
}
|
|
8410
|
-
}
|
|
8411
|
-
function resolveName(fields, fallbackName) {
|
|
8412
|
-
if (hasContent(fields.name)) return fields.name;
|
|
8413
|
-
if (hasContent(fallbackName)) return fallbackName;
|
|
8414
|
-
throw new ConfigurationError("Skill at unknown path is missing required field: name", {
|
|
8415
|
-
code: "schema_invalid"
|
|
8416
|
-
});
|
|
8417
|
-
}
|
|
8418
|
-
function ensureRequiredFields(fields, name) {
|
|
8419
|
-
if (!hasContent(fields.description)) {
|
|
8420
|
-
throw new ConfigurationError(`Skill ${name} is missing required field: description`, {
|
|
8421
|
-
code: "schema_invalid"
|
|
8422
|
-
});
|
|
8423
|
-
}
|
|
8424
|
-
}
|
|
8425
|
-
function buildFrontmatter(fields, name) {
|
|
8426
|
-
const description = fields.description;
|
|
8427
|
-
if (description === void 0) {
|
|
8428
|
-
throw new ConfigurationError(`Skill ${name} missing description`, { code: "schema_invalid" });
|
|
8429
|
-
}
|
|
8430
|
-
const result = { name, description };
|
|
8431
|
-
if (hasContent(fields.category)) result.category = fields.category;
|
|
8432
|
-
const deps = parseDependencies(fields.dependencies);
|
|
8433
|
-
if (deps !== void 0) result.dependencies = deps;
|
|
8434
|
-
return result;
|
|
8435
|
-
}
|
|
8436
|
-
function parseDependencies(raw) {
|
|
8437
|
-
if (!hasContent(raw)) return void 0;
|
|
8438
|
-
const deps = raw.split(",").map((s) => s.trim()).filter((s) => s.length > 0);
|
|
8439
|
-
return deps.length > 0 ? deps : void 0;
|
|
8440
|
-
}
|
|
8441
|
-
function hasContent(value) {
|
|
8442
|
-
return value !== void 0 && value.trim().length > 0;
|
|
8443
|
-
}
|
|
8444
|
-
|
|
8445
|
-
// src/internal/runtime/skills/discover-skills.ts
|
|
8446
|
-
async function discoverSkills(dir, options) {
|
|
8447
|
-
let entries;
|
|
8448
|
-
try {
|
|
8449
|
-
entries = await readWorkspaceDir(dir, "skills_read_error", "skills directory");
|
|
8450
|
-
} catch {
|
|
8451
|
-
return [];
|
|
8452
|
-
}
|
|
8453
|
-
const skills = [];
|
|
8454
|
-
for (const entry of entries) {
|
|
8455
|
-
if (!entry.isDirectory()) continue;
|
|
8456
|
-
let skillDir;
|
|
8457
|
-
try {
|
|
8458
|
-
skillDir = safePathJoin(dir, entry.name);
|
|
8459
|
-
assertNoSymlinkEscape(skillDir, dir);
|
|
8460
|
-
} catch {
|
|
8461
|
-
continue;
|
|
8462
|
-
}
|
|
8463
|
-
const skillPath = path.join(skillDir, "SKILL.md");
|
|
8464
|
-
let raw;
|
|
8465
|
-
try {
|
|
8466
|
-
raw = await promises.readFile(skillPath, "utf8");
|
|
8467
|
-
} catch {
|
|
8468
|
-
continue;
|
|
8469
|
-
}
|
|
8470
|
-
const skill = tryParseSkill(raw, entry.name, skillPath, options);
|
|
8471
|
-
if (skill !== void 0) skills.push(skill);
|
|
8472
|
-
}
|
|
8473
|
-
return skills;
|
|
8474
|
-
}
|
|
8475
|
-
function tryParseSkill(raw, fallbackName, source, options) {
|
|
8476
|
-
try {
|
|
8477
|
-
const frontmatter = parseSkillFrontmatter(raw, fallbackName);
|
|
8478
|
-
const skill = {
|
|
8479
|
-
name: frontmatter.name,
|
|
8480
|
-
description: frontmatter.description,
|
|
8481
|
-
source
|
|
8482
|
-
};
|
|
8483
|
-
if (frontmatter.category !== void 0) skill.category = frontmatter.category;
|
|
8484
|
-
if (frontmatter.dependencies !== void 0) skill.dependencies = frontmatter.dependencies;
|
|
8485
|
-
return skill;
|
|
8486
|
-
} catch (cause) {
|
|
8487
|
-
if (cause instanceof ConfigurationError) {
|
|
8488
|
-
options?.onInvalidSkill?.({
|
|
8489
|
-
name: fallbackName,
|
|
8490
|
-
source,
|
|
8491
|
-
code: cause.code ?? "unknown",
|
|
8492
|
-
message: cause.message
|
|
8493
|
-
});
|
|
8494
|
-
return void 0;
|
|
8495
|
-
}
|
|
8496
|
-
throw cause;
|
|
8497
|
-
}
|
|
8498
|
-
}
|
|
8499
|
-
|
|
8500
|
-
// src/internal/runtime/skills/skills-manager.ts
|
|
8501
|
-
var SkillsManager = class {
|
|
8502
|
-
constructor(cwd, _enabled, settingSourcesIncludeProject, skillsDir, inline) {
|
|
8503
|
-
this.cwd = cwd;
|
|
8504
|
-
this.settingSourcesIncludeProject = settingSourcesIncludeProject;
|
|
8505
|
-
this.skillsDir = skillsDir;
|
|
8506
|
-
this.inline = inline;
|
|
8507
|
-
}
|
|
8508
|
-
cwd;
|
|
8509
|
-
settingSourcesIncludeProject;
|
|
8510
|
-
skillsDir;
|
|
8511
|
-
inline;
|
|
8512
|
-
skills = [];
|
|
8513
|
-
async initialize() {
|
|
8514
|
-
if (!this.settingSourcesIncludeProject) {
|
|
8515
|
-
this.skills = this.mergeInline([]);
|
|
8516
|
-
return;
|
|
8517
|
-
}
|
|
8518
|
-
await this.refresh();
|
|
8519
|
-
}
|
|
8520
|
-
async refresh() {
|
|
8521
|
-
const skillsRoot = this.skillsDir ?? path.join(this.cwd, ".theokit", "skills");
|
|
8522
|
-
const discovered = await discoverSkills(skillsRoot, {
|
|
8523
|
-
onInvalidSkill: (info) => {
|
|
8524
|
-
process.stderr.write(
|
|
8525
|
-
`[theokit-sdk] skill ${info.name} skipped (${info.code}): ${info.message}
|
|
8526
|
-
`
|
|
8527
|
-
);
|
|
8528
|
-
}
|
|
8529
|
-
});
|
|
8530
|
-
this.skills = this.mergeInline(discovered);
|
|
8531
|
-
}
|
|
8532
|
-
/** M22 — merge inline skills over discovered ones; inline wins on a name conflict. */
|
|
8533
|
-
mergeInline(discovered) {
|
|
8534
|
-
if (this.inline === void 0 || this.inline.length === 0) return discovered;
|
|
8535
|
-
const inlineNames = new Set(this.inline.map((s) => s.name));
|
|
8536
|
-
return [...discovered.filter((s) => !inlineNames.has(s.name)), ...this.inline];
|
|
8537
|
-
}
|
|
8538
|
-
list() {
|
|
8539
|
-
return Promise.resolve(this.skills);
|
|
8540
|
-
}
|
|
8541
|
-
};
|
|
8542
|
-
|
|
8543
8599
|
// src/internal/runtime/local-agent/local-agent-bootstrap.ts
|
|
8544
8600
|
function registerLocalAgent(args) {
|
|
8545
8601
|
registerAgent({
|
|
@@ -8575,16 +8631,23 @@ function bootstrapSubmanagers(args) {
|
|
|
8575
8631
|
);
|
|
8576
8632
|
}
|
|
8577
8633
|
if (args.options.skills !== void 0 || args.settingSourcesIncludeProject) {
|
|
8634
|
+
const staticSkills = typeof args.options.skills === "function" ? void 0 : args.options.skills;
|
|
8578
8635
|
out.skillsManager = new SkillsManager(
|
|
8579
8636
|
args.workspaceCwd,
|
|
8580
|
-
|
|
8637
|
+
staticSkills?.enabled,
|
|
8581
8638
|
args.settingSourcesIncludeProject,
|
|
8582
8639
|
// M22 — custom skills directory + inline (code-defined) skills.
|
|
8583
|
-
|
|
8584
|
-
|
|
8640
|
+
staticSkills?.skillsDir,
|
|
8641
|
+
staticSkills?.inline
|
|
8585
8642
|
);
|
|
8586
8643
|
const localSkills = out.skillsManager;
|
|
8587
|
-
out.skills = {
|
|
8644
|
+
out.skills = {
|
|
8645
|
+
// Project to the public shape (name + description only). Inline skills carry
|
|
8646
|
+
// their body + references on the object; `list()` must never leak them —
|
|
8647
|
+
// the body is reachable exclusively through `get()`.
|
|
8648
|
+
list: async () => (await localSkills.list()).map((s) => ({ name: s.name, description: s.description })),
|
|
8649
|
+
get: (name) => localSkills.get(name)
|
|
8650
|
+
};
|
|
8588
8651
|
}
|
|
8589
8652
|
if (args.options.plugins !== void 0 || args.settingSourcesIncludePlugins) {
|
|
8590
8653
|
out.pluginsManager = new PluginsManager(
|
|
@@ -13302,6 +13365,7 @@ function levenshtein(a, b) {
|
|
|
13302
13365
|
}
|
|
13303
13366
|
|
|
13304
13367
|
// src/internal/runtime/local-agent/real-local-run.ts
|
|
13368
|
+
init_async_local_storage();
|
|
13305
13369
|
function createRealLocalRun(options) {
|
|
13306
13370
|
const { userText, id, startTime } = prepareRunContext(options.message);
|
|
13307
13371
|
const supported = /* @__PURE__ */ new Set(["stream", "wait", "cancel", "conversation"]);
|
|
@@ -13413,6 +13477,7 @@ function buildLoopInputs(options, runId, userText) {
|
|
|
13413
13477
|
...options.onStep !== void 0 ? { onStep: options.onStep } : {},
|
|
13414
13478
|
...options.onDelta !== void 0 ? { onDelta: options.onDelta } : {},
|
|
13415
13479
|
...options.sendOptions.toolChoice !== void 0 ? { toolChoice: options.sendOptions.toolChoice } : {},
|
|
13480
|
+
...options.sendOptions.activeTools !== void 0 ? { activeTools: options.sendOptions.activeTools } : {},
|
|
13416
13481
|
...options.priorMessages !== void 0 ? { priorMessages: options.priorMessages } : {},
|
|
13417
13482
|
...options.memoryTools !== void 0 && options.memoryTools.length > 0 ? { memoryTools: options.memoryTools } : {},
|
|
13418
13483
|
...buildCustomToolsInput(
|
|
@@ -13543,7 +13608,7 @@ var RealLocalRun = class extends FixtureRunBase {
|
|
|
13543
13608
|
}
|
|
13544
13609
|
async executeAgentLoop(inputs) {
|
|
13545
13610
|
try {
|
|
13546
|
-
const output = await runAgentLoop(inputs);
|
|
13611
|
+
const output = inputs.activeTools !== void 0 ? await withToolWhitelist(new Set(inputs.activeTools), () => runAgentLoop(inputs)) : await runAgentLoop(inputs);
|
|
13547
13612
|
this.applyAgentLoopOutput(output);
|
|
13548
13613
|
this.transitionTo(output.finalStatus);
|
|
13549
13614
|
} catch (cause) {
|
|
@@ -16428,7 +16493,7 @@ var LocalAgent = class {
|
|
|
16428
16493
|
}
|
|
16429
16494
|
// biome-ignore format: G8 budget — thin accessor for the assembly inputs.
|
|
16430
16495
|
assemblyInputs() {
|
|
16431
|
-
return { agentId: this.agentId, workspaceCwd: this.workspaceCwd, model: this.model, options: this.options, context: this.context, skillsManager: this.skillsManager, systemPromptPipeline: this.systemPromptPipeline };
|
|
16496
|
+
return { agentId: this.agentId, workspaceCwd: this.workspaceCwd, model: this.model, options: this.options, context: this.context, skillsManager: this.skillsManager, settingSourcesIncludeProject: this.settingSourcesIncludeProject, systemPromptPipeline: this.systemPromptPipeline };
|
|
16432
16497
|
}
|
|
16433
16498
|
async resolveSystemPrompt(userText, options, memoryFacts) {
|
|
16434
16499
|
const base = await resolveSystemPromptForSend(
|