@stratusagent/agents 0.11.3 → 0.11.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (53) hide show
  1. package/dist/define.d.ts +22 -0
  2. package/dist/define.d.ts.map +1 -0
  3. package/dist/define.js +64 -0
  4. package/dist/define.js.map +1 -0
  5. package/dist/frontmatter.d.ts +65 -0
  6. package/dist/frontmatter.d.ts.map +1 -0
  7. package/dist/frontmatter.js +260 -0
  8. package/dist/frontmatter.js.map +1 -0
  9. package/dist/identity.d.ts +139 -0
  10. package/dist/identity.d.ts.map +1 -0
  11. package/dist/identity.js +259 -0
  12. package/dist/identity.js.map +1 -0
  13. package/dist/index.d.ts +11 -643
  14. package/dist/index.d.ts.map +1 -1
  15. package/dist/index.js +16 -1516
  16. package/dist/index.js.map +1 -1
  17. package/dist/router.d.ts +18 -0
  18. package/dist/router.d.ts.map +1 -0
  19. package/dist/router.js +44 -0
  20. package/dist/router.js.map +1 -0
  21. package/dist/schedules.d.ts +163 -0
  22. package/dist/schedules.d.ts.map +1 -0
  23. package/dist/schedules.js +215 -0
  24. package/dist/schedules.js.map +1 -0
  25. package/dist/skills.d.ts +135 -0
  26. package/dist/skills.d.ts.map +1 -0
  27. package/dist/skills.js +167 -0
  28. package/dist/skills.js.map +1 -0
  29. package/dist/soul.d.ts +44 -0
  30. package/dist/soul.d.ts.map +1 -0
  31. package/dist/soul.js +98 -0
  32. package/dist/soul.js.map +1 -0
  33. package/dist/tools/delegate.d.ts +93 -0
  34. package/dist/tools/delegate.d.ts.map +1 -0
  35. package/dist/tools/delegate.js +223 -0
  36. package/dist/tools/delegate.js.map +1 -0
  37. package/dist/tools/gateway-only.d.ts +19 -0
  38. package/dist/tools/gateway-only.d.ts.map +1 -0
  39. package/dist/tools/gateway-only.js +29 -0
  40. package/dist/tools/gateway-only.js.map +1 -0
  41. package/dist/tools/memory.d.ts +51 -0
  42. package/dist/tools/memory.d.ts.map +1 -0
  43. package/dist/tools/memory.js +306 -0
  44. package/dist/tools/memory.js.map +1 -0
  45. package/dist/tools/message.d.ts +26 -0
  46. package/dist/tools/message.d.ts.map +1 -0
  47. package/dist/tools/message.js +46 -0
  48. package/dist/tools/message.js.map +1 -0
  49. package/dist/tools/schedule.d.ts +20 -0
  50. package/dist/tools/schedule.d.ts.map +1 -0
  51. package/dist/tools/schedule.js +146 -0
  52. package/dist/tools/schedule.js.map +1 -0
  53. package/package.json +2 -2
@@ -0,0 +1,135 @@
1
+ import type { Skill } from '@stratusagent/core';
2
+ /**
3
+ * The shape a skill id is written in — the Agent Skills spec's rule for
4
+ * `name`, which is also the directory name: lowercase letters and digits
5
+ * in hyphen-separated runs (`web-research`), at most 64 characters, no
6
+ * leading, trailing, or doubled hyphen. One pattern for the manifest's
7
+ * declared ids, the operator directory's folder names, and install-time
8
+ * validation — two copies would drift into two answers to what a valid
9
+ * id is.
10
+ */
11
+ export declare const SKILL_ID_PATTERN: RegExp;
12
+ /** The spec's ceiling on `name`, and so on a skill id. */
13
+ export declare const SKILL_ID_MAX_LENGTH = 64;
14
+ export declare const isValidSkillId: (id: string) => boolean;
15
+ /**
16
+ * Whether an id that is already on this machine — a directory under
17
+ * `~/.stratus/skills/`, a plugin manifest's declared id — is served.
18
+ * Wider than `isValidSkillId` on purpose: the spec's rule arrived after
19
+ * some of these were written, and tightening the *loader* would silently
20
+ * drop an enabled procedure from an agent on upgrade. Installing and
21
+ * validating use the strict rule; loading uses this one, and warns.
22
+ */
23
+ export declare const isLoadableSkillId: (id: string) => boolean;
24
+ /** What a skill id refusal says, everywhere one is refused. */
25
+ export declare const SKILL_ID_RULE = "Skill ids are lowercase letters, digits, and single hyphens (web-research), at most 64 characters.";
26
+ /** The spec's ceiling on `description`. */
27
+ export declare const SKILL_DESCRIPTION_MAX_LENGTH = 1024;
28
+ /** The spec's ceiling on `compatibility`. */
29
+ export declare const SKILL_COMPATIBILITY_MAX_LENGTH = 500;
30
+ /**
31
+ * A parsed `SKILL.md`: the one-line identity that reaches the system
32
+ * prompt, and the body that only ever travels through `skill.read`.
33
+ */
34
+ export interface ParsedSkillDocument {
35
+ /**
36
+ * The skill's name — under the spec, its id, and equal to its directory
37
+ * name. Optional here because loading stays tolerant of what is already
38
+ * installed; the registered skill falls back to its id.
39
+ */
40
+ name?: string;
41
+ /**
42
+ * When to reach for this skill — what routing runs on, so it earns its
43
+ * place by saying when, not what the body contains.
44
+ */
45
+ description: string;
46
+ /** The spec's `license`: a name, or a bundled file. Informational. */
47
+ license?: string;
48
+ /**
49
+ * The spec's `compatibility`: what the skill needs from its environment,
50
+ * in prose — for the operator installing it, since nothing here can act
51
+ * on it.
52
+ */
53
+ compatibility?: string;
54
+ /** The spec's `metadata:` map, verbatim — every value a string. */
55
+ metadata?: Record<string, string>;
56
+ /** `metadata.version`, or the legacy top-level key. Informational. */
57
+ version?: string;
58
+ /**
59
+ * Toolset globs the procedure expects (`browser.*`), from
60
+ * `metadata.requires` (space-separated) or the legacy top-level list.
61
+ * Advisory — see `Skill.requires`.
62
+ */
63
+ requires?: string[];
64
+ /**
65
+ * Top-level keys outside the spec, in file order — the legacy Stratus
66
+ * keys and other hosts' fields alike. What validation warns about.
67
+ */
68
+ unknownKeys: string[];
69
+ body: string;
70
+ }
71
+ /**
72
+ * Parse a `SKILL.md` — the same frontmatter dialect souls use (`key: value`
73
+ * scalars, block lists), plus the spec's `metadata:` map. The body is the
74
+ * procedure itself, markdown, untouched.
75
+ *
76
+ * `description` is required: it is the only thing the model sees before
77
+ * deciding to load the body, and a skill without one is unreachable by the
78
+ * mechanism that makes skills cheap. Everything the spec constrains beyond
79
+ * presence — the name rule, the length ceilings — is
80
+ * `validateSkillDocument`'s, so that loading what is already installed
81
+ * stays lenient while installing is strict.
82
+ */
83
+ export declare const parseSkillDocument: (source: string) => ParsedSkillDocument;
84
+ export interface ValidateSkillDocumentOptions {
85
+ /**
86
+ * The directory the skill sits in (its basename), which the spec
87
+ * requires `name` to equal. Omit where the directory is circumstance
88
+ * rather than identity — a repository whose root is the skill, checked
89
+ * out wherever git put it.
90
+ */
91
+ directoryName?: string;
92
+ /**
93
+ * What to suggest when `name` is missing — the directory name, or for a
94
+ * root skill the repository's. Only ever read for the error text.
95
+ */
96
+ suggestedName?: string;
97
+ }
98
+ /** What `validateSkillDocument` found: errors refuse an install, warnings ride along. */
99
+ export interface SkillValidation {
100
+ errors: string[];
101
+ warnings: string[];
102
+ }
103
+ /**
104
+ * Check a parsed `SKILL.md` against the Agent Skills spec — the checks
105
+ * `skills-ref validate` runs, so a skill that passes here passes there:
106
+ * `name` present, shaped like an id, equal to the directory name;
107
+ * `description` and `compatibility` under their ceilings. Errors are what
108
+ * refuses an install. Top-level keys the spec does not define are
109
+ * warnings, not errors: the reference validator refuses them, but the
110
+ * ecosystem's skills carry other hosts' fields routinely, and refusing a
111
+ * skill over a field that changes nothing here fails the whole point of
112
+ * conforming. The legacy Stratus keys get their own warning, naming the
113
+ * `metadata:` form that ports.
114
+ *
115
+ * Loading never calls this — an installed skill keeps loading whatever
116
+ * the spec says today. Installing always does.
117
+ */
118
+ export declare const validateSkillDocument: (document: ParsedSkillDocument, options?: ValidateSkillDocumentOptions) => SkillValidation;
119
+ export interface LazySkillInput {
120
+ /** The id the skill registers under — qualified for a plugin's skill. */
121
+ id: string;
122
+ /** The parsed document, from the load-time read that validated the file. */
123
+ document: ParsedSkillDocument;
124
+ /** Re-read the file's source. Called on demand; the registry caches. */
125
+ read: () => Promise<string>;
126
+ }
127
+ /**
128
+ * A `Skill` whose body stays on disk until somebody asks. The identity
129
+ * comes from the load-time parse (which is also what validated the file);
130
+ * `load()` re-reads rather than closing over the body, so an
131
+ * enabled-but-unused skill costs its description line and nothing else —
132
+ * in the prompt and in memory.
133
+ */
134
+ export declare const createLazySkill: ({ id, document, read }: LazySkillInput) => Skill;
135
+ //# sourceMappingURL=skills.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skills.d.ts","sourceRoot":"","sources":["../src/skills.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAGhD;;;;;;;;GAQG;AACH,eAAO,MAAM,gBAAgB,QAA+B,CAAC;AAE7D,0DAA0D;AAC1D,eAAO,MAAM,mBAAmB,KAAK,CAAC;AAEtC,eAAO,MAAM,cAAc,GAAI,IAAI,MAAM,KAAG,OACmB,CAAC;AAOhE;;;;;;;GAOG;AACH,eAAO,MAAM,iBAAiB,GAAI,IAAI,MAAM,KAAG,OAA2C,CAAC;AAE3F,+DAA+D;AAC/D,eAAO,MAAM,aAAa,uGAC4E,CAAC;AAEvG,2CAA2C;AAC3C,eAAO,MAAM,4BAA4B,OAAO,CAAC;AAEjD,6CAA6C;AAC7C,eAAO,MAAM,8BAA8B,MAAM,CAAC;AAsBlD;;;GAGG;AACH,MAAM,WAAW,mBAAmB;IAClC;;;;OAIG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;OAGG;IACH,WAAW,EAAE,MAAM,CAAC;IACpB,sEAAsE;IACtE,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;;OAIG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,mEAAmE;IACnE,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAClC,sEAAsE;IACtE,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;;OAIG;IACH,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB;;;OAGG;IACH,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,IAAI,EAAE,MAAM,CAAC;CACd;AAED;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,kBAAkB,GAAI,QAAQ,MAAM,KAAG,mBAyCnD,CAAC;AAEF,MAAM,WAAW,4BAA4B;IAC3C;;;;;OAKG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB;;;OAGG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAID,yFAAyF;AACzF,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AAED;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,qBAAqB,GAChC,UAAU,mBAAmB,EAC7B,UAAS,4BAAiC,KACzC,eAmDF,CAAC;AAEF,MAAM,WAAW,cAAc;IAC7B,yEAAyE;IACzE,EAAE,EAAE,MAAM,CAAC;IACX,4EAA4E;IAC5E,QAAQ,EAAE,mBAAmB,CAAC;IAC9B,wEAAwE;IACxE,IAAI,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,CAAC;CAC7B;AAED;;;;;;GAMG;AACH,eAAO,MAAM,eAAe,GAAI,wBAAwB,cAAc,KAAG,KAMvE,CAAC"}
package/dist/skills.js ADDED
@@ -0,0 +1,167 @@
1
+ import { parseFrontmatterLines, extractFrontmatter } from "./frontmatter.js";
2
+ /**
3
+ * The shape a skill id is written in — the Agent Skills spec's rule for
4
+ * `name`, which is also the directory name: lowercase letters and digits
5
+ * in hyphen-separated runs (`web-research`), at most 64 characters, no
6
+ * leading, trailing, or doubled hyphen. One pattern for the manifest's
7
+ * declared ids, the operator directory's folder names, and install-time
8
+ * validation — two copies would drift into two answers to what a valid
9
+ * id is.
10
+ */
11
+ export const SKILL_ID_PATTERN = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
12
+ /** The spec's ceiling on `name`, and so on a skill id. */
13
+ export const SKILL_ID_MAX_LENGTH = 64;
14
+ export const isValidSkillId = (id) => id.length <= SKILL_ID_MAX_LENGTH && SKILL_ID_PATTERN.test(id);
15
+ // The rule before the spec's: any lowercase kebab-ish run, doubled and
16
+ // trailing hyphens and all, no length cap. What a directory or manifest
17
+ // id that loaded yesterday was checked against.
18
+ const LEGACY_SKILL_ID_PATTERN = /^[a-z0-9][a-z0-9-]*$/;
19
+ /**
20
+ * Whether an id that is already on this machine — a directory under
21
+ * `~/.stratus/skills/`, a plugin manifest's declared id — is served.
22
+ * Wider than `isValidSkillId` on purpose: the spec's rule arrived after
23
+ * some of these were written, and tightening the *loader* would silently
24
+ * drop an enabled procedure from an agent on upgrade. Installing and
25
+ * validating use the strict rule; loading uses this one, and warns.
26
+ */
27
+ export const isLoadableSkillId = (id) => LEGACY_SKILL_ID_PATTERN.test(id);
28
+ /** What a skill id refusal says, everywhere one is refused. */
29
+ export const SKILL_ID_RULE = 'Skill ids are lowercase letters, digits, and single hyphens (web-research), at most 64 characters.';
30
+ /** The spec's ceiling on `description`. */
31
+ export const SKILL_DESCRIPTION_MAX_LENGTH = 1024;
32
+ /** The spec's ceiling on `compatibility`. */
33
+ export const SKILL_COMPATIBILITY_MAX_LENGTH = 500;
34
+ // The frontmatter keys the Agent Skills spec defines. Everything else at
35
+ // the top level belongs to some other host — read past, and reported by
36
+ // `validateSkillDocument`. `allowed-tools` is read so it is not reported,
37
+ // and then deliberately unused: it is another host's pre-approval list,
38
+ // and here the two gates (a trusted config, a soul's allowlist) are the
39
+ // only things that grant a tool.
40
+ const SKILL_SPEC_KEYS = ['name', 'description', 'license', 'compatibility', 'metadata', 'allowed-tools'];
41
+ // `version` and `requires` at the top level are the pre-spec Stratus form;
42
+ // the spec keeps host extensions under `metadata:`, and that is where a
43
+ // skill written today puts them. The old form still reads, so an installed
44
+ // skill keeps working — and validation says which form it found.
45
+ const SKILL_SCALAR_KEYS = ['name', 'description', 'license', 'compatibility', 'allowed-tools', 'version'];
46
+ const SKILL_LIST_KEYS = ['requires'];
47
+ const SKILL_MAP_KEYS = ['metadata'];
48
+ const SKILL_LEGACY_KEYS = ['version', 'requires'];
49
+ /**
50
+ * Parse a `SKILL.md` — the same frontmatter dialect souls use (`key: value`
51
+ * scalars, block lists), plus the spec's `metadata:` map. The body is the
52
+ * procedure itself, markdown, untouched.
53
+ *
54
+ * `description` is required: it is the only thing the model sees before
55
+ * deciding to load the body, and a skill without one is unreachable by the
56
+ * mechanism that makes skills cheap. Everything the spec constrains beyond
57
+ * presence — the name rule, the length ceilings — is
58
+ * `validateSkillDocument`'s, so that loading what is already installed
59
+ * stays lenient while installing is strict.
60
+ */
61
+ export const parseSkillDocument = (source) => {
62
+ const { lines, body } = extractFrontmatter(source, 'skill');
63
+ if (!lines) {
64
+ throw new Error('Skill file has no frontmatter. A SKILL.md starts with --- and needs at least a description.');
65
+ }
66
+ const { scalars, lists, maps, unknownKeys } = parseFrontmatterLines(lines, {
67
+ kind: 'skill',
68
+ scalarKeys: SKILL_SCALAR_KEYS,
69
+ listKeys: SKILL_LIST_KEYS,
70
+ mapKeys: SKILL_MAP_KEYS,
71
+ // Skills travel the wider agent-skills ecosystem (skills.sh and the
72
+ // registries behind it), whose frontmatter carries fields other hosts
73
+ // own. Those are metadata to skip, not defects to refuse — see
74
+ // FrontmatterShape.tolerant, and note souls do NOT set this.
75
+ tolerant: true,
76
+ });
77
+ const description = scalars.description;
78
+ if (!description) {
79
+ throw new Error('Skill frontmatter has no "description". The description is what an agent routes on — say when to reach for this skill.');
80
+ }
81
+ const metadata = maps.metadata;
82
+ const version = metadata?.version ?? scalars.version;
83
+ const requires = metadata?.requires !== undefined
84
+ ? metadata.requires.split(/\s+/).filter((entry) => entry.length > 0)
85
+ : lists.requires;
86
+ // The legacy keys are read, and still not the spec's: a validator names
87
+ // them so a skill written here can be moved to the form that ports.
88
+ const legacy = SKILL_LEGACY_KEYS.filter((key) => (key === 'requires' ? lists.requires : scalars[key]) !== undefined);
89
+ return {
90
+ ...(scalars.name ? { name: scalars.name } : {}),
91
+ description,
92
+ ...(scalars.license ? { license: scalars.license } : {}),
93
+ ...(scalars.compatibility ? { compatibility: scalars.compatibility } : {}),
94
+ ...(metadata ? { metadata } : {}),
95
+ ...(version ? { version } : {}),
96
+ ...(requires && requires.length > 0 ? { requires } : {}),
97
+ unknownKeys: [...legacy, ...unknownKeys.filter((key) => !SKILL_SPEC_KEYS.includes(key))],
98
+ body: body.trim(),
99
+ };
100
+ };
101
+ const characterCount = (text) => Array.from(text).length;
102
+ /**
103
+ * Check a parsed `SKILL.md` against the Agent Skills spec — the checks
104
+ * `skills-ref validate` runs, so a skill that passes here passes there:
105
+ * `name` present, shaped like an id, equal to the directory name;
106
+ * `description` and `compatibility` under their ceilings. Errors are what
107
+ * refuses an install. Top-level keys the spec does not define are
108
+ * warnings, not errors: the reference validator refuses them, but the
109
+ * ecosystem's skills carry other hosts' fields routinely, and refusing a
110
+ * skill over a field that changes nothing here fails the whole point of
111
+ * conforming. The legacy Stratus keys get their own warning, naming the
112
+ * `metadata:` form that ports.
113
+ *
114
+ * Loading never calls this — an installed skill keeps loading whatever
115
+ * the spec says today. Installing always does.
116
+ */
117
+ export const validateSkillDocument = (document, options = {}) => {
118
+ const errors = [];
119
+ const warnings = [];
120
+ if (document.name === undefined) {
121
+ const suggestion = options.suggestedName ?? options.directoryName;
122
+ errors.push(`frontmatter has no "name". The Agent Skills spec requires one, equal to the directory name${suggestion !== undefined ? ` — add: name: ${suggestion}` : ''}.`);
123
+ }
124
+ else if (!isValidSkillId(document.name)) {
125
+ errors.push(`name ${JSON.stringify(document.name)} is not a skill id. ${SKILL_ID_RULE}`);
126
+ }
127
+ else if (options.directoryName !== undefined && document.name !== options.directoryName) {
128
+ errors.push(`name ${JSON.stringify(document.name)} does not match the directory name ${JSON.stringify(options.directoryName)}. The spec requires the two to agree — rename one.`);
129
+ }
130
+ // Characters, as the spec and its Python reference count them — code
131
+ // points, not the UTF-16 units `.length` reports, which would count an
132
+ // emoji twice and refuse a description the reference validator passes.
133
+ const descriptionLength = characterCount(document.description);
134
+ if (descriptionLength > SKILL_DESCRIPTION_MAX_LENGTH) {
135
+ errors.push(`description is ${descriptionLength} characters, past the spec's ceiling of ${SKILL_DESCRIPTION_MAX_LENGTH}. Say when to reach for the skill, and move the rest into the body.`);
136
+ }
137
+ const compatibilityLength = document.compatibility !== undefined ? characterCount(document.compatibility) : 0;
138
+ if (compatibilityLength > SKILL_COMPATIBILITY_MAX_LENGTH) {
139
+ errors.push(`compatibility is ${compatibilityLength} characters, past the spec's ceiling of ${SKILL_COMPATIBILITY_MAX_LENGTH}.`);
140
+ }
141
+ const legacy = document.unknownKeys.filter((key) => SKILL_LEGACY_KEYS.includes(key));
142
+ const foreign = document.unknownKeys.filter((key) => !SKILL_LEGACY_KEYS.includes(key));
143
+ for (const key of legacy) {
144
+ warnings.push(key === 'requires'
145
+ ? 'top-level "requires" is the pre-spec Stratus form, and the reference validator refuses it. Write it as metadata.requires, one space-separated string: "browser.* fs.read".'
146
+ : 'top-level "version" is the pre-spec Stratus form, and the reference validator refuses it. Write it as metadata.version.');
147
+ }
148
+ if (foreign.length > 0) {
149
+ warnings.push(`frontmatter key${foreign.length > 1 ? 's' : ''} outside the Agent Skills spec: ${foreign.map((key) => JSON.stringify(key)).join(', ')}. Another host's; ignored here, and the reference validator refuses ${foreign.length > 1 ? 'them' : 'it'}.`);
150
+ }
151
+ return { errors, warnings };
152
+ };
153
+ /**
154
+ * A `Skill` whose body stays on disk until somebody asks. The identity
155
+ * comes from the load-time parse (which is also what validated the file);
156
+ * `load()` re-reads rather than closing over the body, so an
157
+ * enabled-but-unused skill costs its description line and nothing else —
158
+ * in the prompt and in memory.
159
+ */
160
+ export const createLazySkill = ({ id, document, read }) => ({
161
+ id,
162
+ name: document.name ?? id,
163
+ description: document.description,
164
+ ...(document.requires ? { requires: document.requires } : {}),
165
+ load: async () => parseSkillDocument(await read()).body,
166
+ });
167
+ //# sourceMappingURL=skills.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skills.js","sourceRoot":"","sources":["../src/skills.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,qBAAqB,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAE7E;;;;;;;;GAQG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG,4BAA4B,CAAC;AAE7D,0DAA0D;AAC1D,MAAM,CAAC,MAAM,mBAAmB,GAAG,EAAE,CAAC;AAEtC,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,EAAU,EAAW,EAAE,CACpD,EAAE,CAAC,MAAM,IAAI,mBAAmB,IAAI,gBAAgB,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;AAEhE,uEAAuE;AACvE,wEAAwE;AACxE,gDAAgD;AAChD,MAAM,uBAAuB,GAAG,sBAAsB,CAAC;AAEvD;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,EAAU,EAAW,EAAE,CAAC,uBAAuB,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;AAE3F,+DAA+D;AAC/D,MAAM,CAAC,MAAM,aAAa,GACxB,oGAAoG,CAAC;AAEvG,2CAA2C;AAC3C,MAAM,CAAC,MAAM,4BAA4B,GAAG,IAAI,CAAC;AAEjD,6CAA6C;AAC7C,MAAM,CAAC,MAAM,8BAA8B,GAAG,GAAG,CAAC;AAElD,yEAAyE;AACzE,wEAAwE;AACxE,0EAA0E;AAC1E,wEAAwE;AACxE,wEAAwE;AACxE,iCAAiC;AACjC,MAAM,eAAe,GAAsB,CAAC,MAAM,EAAE,aAAa,EAAE,SAAS,EAAE,eAAe,EAAE,UAAU,EAAE,eAAe,CAAC,CAAC;AAE5H,2EAA2E;AAC3E,wEAAwE;AACxE,2EAA2E;AAC3E,iEAAiE;AACjE,MAAM,iBAAiB,GAAG,CAAC,MAAM,EAAE,aAAa,EAAE,SAAS,EAAE,eAAe,EAAE,eAAe,EAAE,SAAS,CAAU,CAAC;AAEnH,MAAM,eAAe,GAAG,CAAC,UAAU,CAAU,CAAC;AAE9C,MAAM,cAAc,GAAG,CAAC,UAAU,CAAU,CAAC;AAE7C,MAAM,iBAAiB,GAAsB,CAAC,SAAS,EAAE,UAAU,CAAC,CAAC;AA4CrE;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,MAAc,EAAuB,EAAE;IACxE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,GAAG,kBAAkB,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC5D,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,MAAM,IAAI,KAAK,CAAC,6FAA6F,CAAC,CAAC;IACjH,CAAC;IACD,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,WAAW,EAAE,GAAG,qBAAqB,CAAC,KAAK,EAAE;QACzE,IAAI,EAAE,OAAO;QACb,UAAU,EAAE,iBAAiB;QAC7B,QAAQ,EAAE,eAAe;QACzB,OAAO,EAAE,cAAc;QACvB,oEAAoE;QACpE,sEAAsE;QACtE,+DAA+D;QAC/D,6DAA6D;QAC7D,QAAQ,EAAE,IAAI;KACf,CAAC,CAAC;IACH,MAAM,WAAW,GAAG,OAAO,CAAC,WAAW,CAAC;IACxC,IAAI,CAAC,WAAW,EAAE,CAAC;QACjB,MAAM,IAAI,KAAK,CACb,wHAAwH,CACzH,CAAC;IACJ,CAAC;IACD,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC;IAC/B,MAAM,OAAO,GAAG,QAAQ,EAAE,OAAO,IAAI,OAAO,CAAC,OAAO,CAAC;IACrD,MAAM,QAAQ,GAAG,QAAQ,EAAE,QAAQ,KAAK,SAAS;QAC/C,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC;QACpE,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC;IACnB,wEAAwE;IACxE,oEAAoE;IACpE,MAAM,MAAM,GAAG,iBAAiB,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,GAAG,KAAK,UAAU,CAAC,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,KAAK,SAAS,CAAC,CAAC;IACrH,OAAO;QACL,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC/C,WAAW;QACX,GAAG,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACxD,GAAG,CAAC,OAAO,CAAC,aAAa,CAAC,CAAC,CAAC,EAAE,aAAa,EAAE,OAAO,CAAC,aAAa,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC1E,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACjC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC/B,GAAG,CAAC,QAAQ,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACxD,WAAW,EAAE,CAAC,GAAG,MAAM,EAAE,GAAG,WAAW,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,eAAe,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC;QACxF,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE;KAClB,CAAC;AACJ,CAAC,CAAC;AAiBF,MAAM,cAAc,GAAG,CAAC,IAAY,EAAU,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC;AAQzE;;;;;;;;;;;;;;GAcG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAAG,CACnC,QAA6B,EAC7B,UAAwC,EAAE,EACzB,EAAE;IACnB,MAAM,MAAM,GAAa,EAAE,CAAC;IAC5B,MAAM,QAAQ,GAAa,EAAE,CAAC;IAE9B,IAAI,QAAQ,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;QAChC,MAAM,UAAU,GAAG,OAAO,CAAC,aAAa,IAAI,OAAO,CAAC,aAAa,CAAC;QAClE,MAAM,CAAC,IAAI,CACT,6FACE,UAAU,KAAK,SAAS,CAAC,CAAC,CAAC,iBAAiB,UAAU,EAAE,CAAC,CAAC,CAAC,EAC7D,GAAG,CACJ,CAAC;IACJ,CAAC;SAAM,IAAI,CAAC,cAAc,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;QAC1C,MAAM,CAAC,IAAI,CAAC,QAAQ,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,IAAI,CAAC,uBAAuB,aAAa,EAAE,CAAC,CAAC;IAC3F,CAAC;SAAM,IAAI,OAAO,CAAC,aAAa,KAAK,SAAS,IAAI,QAAQ,CAAC,IAAI,KAAK,OAAO,CAAC,aAAa,EAAE,CAAC;QAC1F,MAAM,CAAC,IAAI,CACT,QAAQ,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,IAAI,CAAC,sCAAsC,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,aAAa,CAAC,oDAAoD,CACrK,CAAC;IACJ,CAAC;IAED,qEAAqE;IACrE,uEAAuE;IACvE,uEAAuE;IACvE,MAAM,iBAAiB,GAAG,cAAc,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC;IAC/D,IAAI,iBAAiB,GAAG,4BAA4B,EAAE,CAAC;QACrD,MAAM,CAAC,IAAI,CACT,kBAAkB,iBAAiB,2CAA2C,4BAA4B,qEAAqE,CAChL,CAAC;IACJ,CAAC;IACD,MAAM,mBAAmB,GAAG,QAAQ,CAAC,aAAa,KAAK,SAAS,CAAC,CAAC,CAAC,cAAc,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAC9G,IAAI,mBAAmB,GAAG,8BAA8B,EAAE,CAAC;QACzD,MAAM,CAAC,IAAI,CACT,oBAAoB,mBAAmB,2CAA2C,8BAA8B,GAAG,CACpH,CAAC;IACJ,CAAC;IAED,MAAM,MAAM,GAAG,QAAQ,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,iBAAiB,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC;IACrF,MAAM,OAAO,GAAG,QAAQ,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,iBAAiB,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC;IACvF,KAAK,MAAM,GAAG,IAAI,MAAM,EAAE,CAAC;QACzB,QAAQ,CAAC,IAAI,CACX,GAAG,KAAK,UAAU;YAChB,CAAC,CAAC,4KAA4K;YAC9K,CAAC,CAAC,yHAAyH,CAC9H,CAAC;IACJ,CAAC;IACD,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACvB,QAAQ,CAAC,IAAI,CACX,kBAAkB,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,mCAAmC,OAAO,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,uEAAuE,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,GAAG,CACnP,CAAC;IACJ,CAAC;IAED,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC;AAC9B,CAAC,CAAC;AAWF;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,EAAE,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAkB,EAAS,EAAE,CAAC,CAAC;IACjF,EAAE;IACF,IAAI,EAAE,QAAQ,CAAC,IAAI,IAAI,EAAE;IACzB,WAAW,EAAE,QAAQ,CAAC,WAAW;IACjC,GAAG,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,QAAQ,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;IAC7D,IAAI,EAAE,KAAK,IAAI,EAAE,CAAC,kBAAkB,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC,IAAI;CACxD,CAAC,CAAC"}
package/dist/soul.d.ts ADDED
@@ -0,0 +1,44 @@
1
+ import { type AgentDefinition } from '@stratusagent/core';
2
+ /**
3
+ * Whether `agent` may delegate to the agent with id `targetId`. Exact ids
4
+ * or `*`; no namespace globs, because agent ids have no namespaces. Omitted
5
+ * is nobody — see `AgentDefinition.delegates`.
6
+ */
7
+ export declare const isDelegateAllowed: (agent: Pick<AgentDefinition, "delegates">, targetId: string) => boolean;
8
+ /**
9
+ * A parsed soul file: the agent it defines plus optional runtime hints.
10
+ * Souls are markdown with frontmatter — the frontmatter carries structured
11
+ * identity (name, tools, credentials, provider, model) and the body is the
12
+ * persona itself, written in prose.
13
+ */
14
+ export interface ParsedSoul {
15
+ agent: AgentDefinition;
16
+ /** Provider the soul prefers (e.g. "anthropic"). Runtimes may override. */
17
+ provider?: string;
18
+ /** Model the soul prefers (e.g. "claude-opus-5"). Runtimes may override. */
19
+ model?: string;
20
+ }
21
+ export interface ParseSoulOptions {
22
+ /** Seed for deterministic identity generation when the soul has no name. */
23
+ seed?: string;
24
+ }
25
+ /**
26
+ * The soul edit that grants one delegate, as the refusal suggests it. The
27
+ * inline form, `delegates: [a, "b, c"]`, quoted when the inline parser
28
+ * would otherwise split or unquote the id, in whichever quote it does not
29
+ * contain — and the block form when the id holds both quotes, since no
30
+ * inline spelling of `a"',b` reads back as one entry, while a block line
31
+ * is never split and is unquoted only for matching outer quotes, which
32
+ * {@link writeScalar} guards. Rendered this carefully because
33
+ * `delegates: [foo,bar]` is a grant to two agents and a refusal of the
34
+ * one the message was about.
35
+ */
36
+ export declare const suggestedDelegatesEdit: (value: string) => string;
37
+ /**
38
+ * Parse a soul file (markdown with optional frontmatter) into an agent
39
+ * definition. The body becomes the agent's instructions; a missing name is
40
+ * generated, so the smallest possible soul is just prose.
41
+ */
42
+ export declare const parseSoul: (source: string, options?: ParseSoulOptions) => ParsedSoul;
43
+ export declare const formatSoul: (soul: ParsedSoul) => string;
44
+ //# sourceMappingURL=soul.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"soul.d.ts","sourceRoot":"","sources":["../src/soul.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgC,KAAK,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAUxF;;;;GAIG;AACH,eAAO,MAAM,iBAAiB,GAAI,OAAO,IAAI,CAAC,eAAe,EAAE,WAAW,CAAC,EAAE,UAAU,MAAM,KAAG,OAClB,CAAC;AAE/E;;;;;GAKG;AACH,MAAM,WAAW,UAAU;IACzB,KAAK,EAAE,eAAe,CAAC;IACvB,2EAA2E;IAC3E,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,4EAA4E;IAC5E,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,gBAAgB;IAC/B,4EAA4E;IAC5E,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAMD;;;;;;;;;;GAUG;AACH,eAAO,MAAM,sBAAsB,GAAI,OAAO,MAAM,KAAG,MAWtD,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,SAAS,GAAI,QAAQ,MAAM,EAAE,UAAS,gBAAqB,KAAG,UAkC1E,CAAC;AAEF,eAAO,MAAM,UAAU,GAAI,MAAM,UAAU,KAAG,MA8B7C,CAAC"}
package/dist/soul.js ADDED
@@ -0,0 +1,98 @@
1
+ import { isListensMode, LISTENS_MODES } from '@stratusagent/core';
2
+ import { defineAgent } from "./define.js";
3
+ import { unquote, parseFrontmatterLines, extractFrontmatter, writeScalar, } from "./frontmatter.js";
4
+ /**
5
+ * Whether `agent` may delegate to the agent with id `targetId`. Exact ids
6
+ * or `*`; no namespace globs, because agent ids have no namespaces. Omitted
7
+ * is nobody — see `AgentDefinition.delegates`.
8
+ */
9
+ export const isDelegateAllowed = (agent, targetId) => (agent.delegates ?? []).some((entry) => entry === '*' || entry === targetId);
10
+ const SOUL_SCALAR_KEYS = ['name', 'id', 'provider', 'model', 'listens'];
11
+ const SOUL_LIST_KEYS = ['tools', 'skills', 'credentials', 'delegates'];
12
+ /**
13
+ * The soul edit that grants one delegate, as the refusal suggests it. The
14
+ * inline form, `delegates: [a, "b, c"]`, quoted when the inline parser
15
+ * would otherwise split or unquote the id, in whichever quote it does not
16
+ * contain — and the block form when the id holds both quotes, since no
17
+ * inline spelling of `a"',b` reads back as one entry, while a block line
18
+ * is never split and is unquoted only for matching outer quotes, which
19
+ * {@link writeScalar} guards. Rendered this carefully because
20
+ * `delegates: [foo,bar]` is a grant to two agents and a refusal of the
21
+ * one the message was about.
22
+ */
23
+ export const suggestedDelegatesEdit = (value) => {
24
+ if (!/[,"'\s]/.test(value) && unquote(value) === value) {
25
+ return `delegates: [${value}]`;
26
+ }
27
+ if (!value.includes('"')) {
28
+ return `delegates: ["${value}"]`;
29
+ }
30
+ if (!value.includes("'")) {
31
+ return `delegates: ['${value}']`;
32
+ }
33
+ return `a delegates: list with the line "- ${writeScalar(value)}"`;
34
+ };
35
+ /**
36
+ * Parse a soul file (markdown with optional frontmatter) into an agent
37
+ * definition. The body becomes the agent's instructions; a missing name is
38
+ * generated, so the smallest possible soul is just prose.
39
+ */
40
+ export const parseSoul = (source, options = {}) => {
41
+ const { lines, body } = extractFrontmatter(source, 'soul');
42
+ const { scalars, lists } = lines
43
+ ? parseFrontmatterLines(lines, { kind: 'soul', scalarKeys: SOUL_SCALAR_KEYS, listKeys: SOUL_LIST_KEYS })
44
+ : { scalars: {}, lists: {}, maps: {}, unknownKeys: [] };
45
+ const instructions = body.trim();
46
+ // Strict, like every soul key: a misspelled mode would otherwise load as
47
+ // the default, and an agent that answers every reply when it was meant
48
+ // to judge is the failure this file is read to prevent.
49
+ if (scalars.listens !== undefined && !isListensMode(scalars.listens)) {
50
+ throw new Error(`Soul frontmatter listens: ${JSON.stringify(scalars.listens)} is not a listening mode; use one of ${LISTENS_MODES.join(', ')}.`);
51
+ }
52
+ const agent = defineAgent({
53
+ ...(scalars.name ? { name: scalars.name } : {}),
54
+ ...(scalars.id ? { id: scalars.id } : {}),
55
+ ...(instructions ? { instructions } : {}),
56
+ ...(lists.tools ? { tools: lists.tools } : {}),
57
+ ...(lists.skills ? { skills: lists.skills } : {}),
58
+ ...(lists.credentials ? { credentials: lists.credentials } : {}),
59
+ ...(lists.delegates ? { delegates: lists.delegates } : {}),
60
+ ...(isListensMode(scalars.listens) ? { listens: scalars.listens } : {}),
61
+ ...(options.seed !== undefined ? { seed: options.seed } : {}),
62
+ });
63
+ return {
64
+ agent,
65
+ ...(scalars.provider ? { provider: scalars.provider } : {}),
66
+ ...(scalars.model ? { model: scalars.model } : {}),
67
+ };
68
+ };
69
+ export const formatSoul = (soul) => {
70
+ const lines = ['---', `name: ${writeScalar(soul.agent.name)}`, `id: ${writeScalar(soul.agent.id)}`];
71
+ if (soul.provider) {
72
+ lines.push(`provider: ${soul.provider}`);
73
+ }
74
+ if (soul.model) {
75
+ lines.push(`model: ${soul.model}`);
76
+ }
77
+ if (soul.agent.listens) {
78
+ lines.push(`listens: ${soul.agent.listens}`);
79
+ }
80
+ for (const [key, values] of [
81
+ ['tools', soul.agent.tools],
82
+ ['skills', soul.agent.skills],
83
+ ['credentials', soul.agent.credentials],
84
+ ['delegates', soul.agent.delegates],
85
+ ]) {
86
+ if (values && values.length > 0) {
87
+ lines.push(`${key}:`);
88
+ for (const value of values) {
89
+ lines.push(` - ${writeScalar(value)}`);
90
+ }
91
+ }
92
+ }
93
+ lines.push('---', '');
94
+ lines.push(soul.agent.instructions ?? 'Describe who this agent is and how they talk.');
95
+ lines.push('');
96
+ return lines.join('\n');
97
+ };
98
+ //# sourceMappingURL=soul.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"soul.js","sourceRoot":"","sources":["../src/soul.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,93 @@
1
+ import { AgentRegistry, type AgentDefinition, type AgentRunner, type JsonObject, type Session, type Tool } from '@stratusagent/core';
2
+ export declare const DELEGATE_TOOL_NAME = "agent.delegate";
3
+ /**
4
+ * Metadata a delegated sub-session carries: which agent delegated, and the
5
+ * session at the root of the chain. Written by `agent.delegate` and read by
6
+ * the gateway's restart sweep, which is why the keys are named here rather
7
+ * than spelled twice — a sub-session's parent is a turn in some other
8
+ * process's memory, and after a restart nothing can consume its reply.
9
+ */
10
+ export declare const DELEGATED_BY_METADATA_KEY = "delegatedBy";
11
+ export declare const ROOT_SESSION_ID_METADATA_KEY = "rootSessionId";
12
+ export declare const DELEGATION_DEPTH_METADATA_KEY = "delegationDepth";
13
+ /**
14
+ * The segment `agent.delegate` mints into every sub-session's id —
15
+ * `<parent>:delegate:<agent>:<depth>:<suffix>`. The second half of what
16
+ * identifies a sub-session, beside the metadata above: the gateway refuses
17
+ * the metadata keys at its public door, but rows written before it did
18
+ * cannot be told apart by their metadata alone, and a caller who wrote
19
+ * `delegatedBy` onto a session of its own would not also have minted an
20
+ * id in this shape.
21
+ */
22
+ export declare const DELEGATED_SESSION_ID_MARKER = ":delegate:";
23
+ /**
24
+ * Whether this session is a delegated sub-session — one whose reply is
25
+ * consumed by a parent turn's `agent.delegate` call and by nothing else.
26
+ * Both halves are required: the metadata `agent.delegate` writes, and the
27
+ * id shape it mints.
28
+ */
29
+ export declare const isDelegatedSession: (session: Pick<Session, "id" | "metadata">) => boolean;
30
+ /**
31
+ * The id of the session whose `agent.delegate` call started this one, read
32
+ * off the id shape above — the text before the last marker, since a nested
33
+ * sub-session embeds its parent's id whole. Undefined for an id that was
34
+ * not minted that way.
35
+ */
36
+ export declare const delegatingSessionIdOf: (sessionId: string) => string | undefined;
37
+ /**
38
+ * The id of the `agent.delegate` call in `parent` that is still awaiting
39
+ * `child`, or undefined when none is.
40
+ *
41
+ * The one thing about a delegation nothing outside the runner can forge:
42
+ * a caller can name a session in the sub-session id shape and write the
43
+ * metadata keys, but only the runner writes assistant tool calls, and only
44
+ * a delegation in flight leaves one with no result behind it. Matched to
45
+ * the child and not merely counted, because a parent can be inside one
46
+ * delegation while an earlier sub-session of its — continued from outside
47
+ * under a version that kept the markers — is parked on something of its
48
+ * own. The call names its target and its prompt, and `agent.delegate`
49
+ * made the prompt the child's first user message. Read against the
50
+ * transcript order so a re-used call id cannot make a later call look
51
+ * answered.
52
+ */
53
+ export declare const outstandingDelegationFor: (parent: Pick<Session, "messages">, child: Pick<Session, "agent" | "messages">) => string | undefined;
54
+ /**
55
+ * `metadata` with the delegation markers removed — what a sub-session
56
+ * carries once it has been addressed from outside. The delegation ended
57
+ * with the turn that awaited it; a conversation somebody continues on the
58
+ * same id afterwards is an ordinary one, and must not be closed as an
59
+ * orphan by a later restart.
60
+ */
61
+ export declare const withoutDelegation: (metadata: JsonObject) => JsonObject;
62
+ /**
63
+ * Runs a delegated sub-session. A plain runner works when every agent
64
+ * shares one provider; a host with per-agent provider routing (the
65
+ * gateway) supplies its own dispatcher so the target runs on the
66
+ * target's resolved provider and credentials — never the delegator's.
67
+ */
68
+ export type DelegateDispatch = (input: {
69
+ sessionId: string;
70
+ agent: AgentDefinition;
71
+ userMessage: string;
72
+ metadata: JsonObject;
73
+ /** The parent turn's abort signal — a cancelled parent cancels the delegated run too. */
74
+ signal?: AbortSignal;
75
+ }) => Promise<Session>;
76
+ export type DelegateToolOptions = {
77
+ registry: AgentRegistry;
78
+ /** Maximum delegation depth to stop orchestrator loops. Default 3. */
79
+ maxDepth?: number;
80
+ } & ({
81
+ runner: AgentRunner;
82
+ dispatch?: never;
83
+ } | {
84
+ dispatch: DelegateDispatch;
85
+ runner?: never;
86
+ });
87
+ /**
88
+ * The orchestrator primitive: a tool that runs another agent in its own
89
+ * sub-session (with that agent's memory, tool allowlist, and credentials)
90
+ * and returns its final reply as the tool result.
91
+ */
92
+ export declare const createDelegateTool: ({ registry, runner, dispatch, maxDepth, }: DelegateToolOptions) => Tool;
93
+ //# sourceMappingURL=delegate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"delegate.d.ts","sourceRoot":"","sources":["../../src/tools/delegate.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,aAAa,EAIb,KAAK,eAAe,EACpB,KAAK,WAAW,EAChB,KAAK,UAAU,EACf,KAAK,OAAO,EACZ,KAAK,IAAI,EACV,MAAM,oBAAoB,CAAC;AAG5B,eAAO,MAAM,kBAAkB,mBAAmB,CAAC;AAEnD;;;;;;GAMG;AACH,eAAO,MAAM,yBAAyB,gBAAgB,CAAC;AAEvD,eAAO,MAAM,4BAA4B,kBAAkB,CAAC;AAE5D,eAAO,MAAM,6BAA6B,oBAAoB,CAAC;AAE/D;;;;;;;;GAQG;AACH,eAAO,MAAM,2BAA2B,eAAe,CAAC;AAExD;;;;;GAKG;AACH,eAAO,MAAM,kBAAkB,GAAI,SAAS,IAAI,CAAC,OAAO,EAAE,IAAI,GAAG,UAAU,CAAC,KAAG,OAE1B,CAAC;AAEtD;;;;;GAKG;AACH,eAAO,MAAM,qBAAqB,GAAI,WAAW,MAAM,KAAG,MAAM,GAAG,SAGlE,CAAC;AAEF;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,wBAAwB,GACnC,QAAQ,IAAI,CAAC,OAAO,EAAE,UAAU,CAAC,EACjC,OAAO,IAAI,CAAC,OAAO,EAAE,OAAO,GAAG,UAAU,CAAC,KACzC,MAAM,GAAG,SA8BX,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,iBAAiB,GAAI,UAAU,UAAU,KAAG,UAQxD,CAAC;AAEF;;;;;GAKG;AACH,MAAM,MAAM,gBAAgB,GAAG,CAAC,KAAK,EAAE;IACrC,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,eAAe,CAAC;IACvB,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,UAAU,CAAC;IACrB,yFAAyF;IACzF,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;AAEvB,MAAM,MAAM,mBAAmB,GAAG;IAChC,QAAQ,EAAE,aAAa,CAAC;IACxB,sEAAsE;IACtE,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB,GAAG,CAAC;IAAE,MAAM,EAAE,WAAW,CAAC;IAAC,QAAQ,CAAC,EAAE,KAAK,CAAA;CAAE,GAAG;IAAE,QAAQ,EAAE,gBAAgB,CAAC;IAAC,MAAM,CAAC,EAAE,KAAK,CAAA;CAAE,CAAC,CAAC;AAIjG;;;;GAIG;AACH,eAAO,MAAM,kBAAkB,GAAI,2CAKhC,mBAAmB,KAAG,IA6HxB,CAAC"}