@stratusagent/agents 0.11.4 → 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 -654
  14. package/dist/index.d.ts.map +1 -1
  15. package/dist/index.js +16 -1641
  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
package/dist/index.d.ts CHANGED
@@ -1,655 +1,12 @@
1
- import { type ListensMode, AgentRegistry, type AgentDefinition, type AgentMemoryStore, type AgentRunner, type AvatarTheme, type JsonObject, type Session, type Skill, type Tool, type TrustLevel } from '@stratusagent/core';
2
- /**
3
- * The one house style every Stratus agent avatar is drawn in. Surfaces
4
- * (CLI, web, macOS) render this style; agents differ by their name-derived
5
- * hue and palette, so the team looks cohesive while each member is
6
- * recognizable.
7
- */
8
- export declare const AVATAR_STYLE = "stratus";
9
- /**
10
- * Generate a human-ish first name. Deterministic when a seed is supplied;
11
- * random otherwise.
12
- */
13
- export declare const generateAgentName: (seed?: string) => string;
14
- /**
15
- * Derive an avatar theme from a name: a stable hue and a small palette in
16
- * the shared Stratus house style. Consumers (CLI, web, macOS) draw the
17
- * actual image from this so the agent looks the same on every surface.
18
- */
19
- export declare const generateAvatarTheme: (name: string) => AvatarTheme;
20
- /**
21
- * The shape an id is *minted* in: lowercase alphanumerics and internal
22
- * hyphens, starting with an alphanumeric. Everything `slugify` produces
23
- * matches it, so every id this module derives does.
24
- *
25
- * Not what validation enforces. A hand-written `id:` predates any shape
26
- * rule and `Ava_1` was as valid as `ava` — see `isValidAgentId`.
27
- */
28
- export declare const AGENT_ID_PATTERN: RegExp;
29
- /**
30
- * How long an id we *build* is allowed to get. A construction bound, not a
31
- * validation rule — `isValidAgentId` deliberately does not check it.
32
- *
33
- * Every id derived from a long name predates this bound, and enforcing it
34
- * retroactively drops working agents off the roster, while trimming them
35
- * silently re-keys their sessions, memory, and credentials to an id nobody
36
- * has ever used. So the bound applies where an id is minted fresh and
37
- * nothing is keyed to it yet, and nowhere else. File systems still have
38
- * limits, and an id long enough to hit them fails at the join with a name
39
- * that says so.
40
- */
41
- export declare const MAX_AGENT_ID_LENGTH = 64;
42
- /**
43
- * Whether `id` is safe to key an agent's resources and paths by.
44
- *
45
- * Ids are not labels. They key sessions, memory, credentials, Slack channel
46
- * tokens, and every per-agent path on disk — and an explicit frontmatter
47
- * `id` is untrusted input: a soul file travels with a repository, and in
48
- * the hosted profile it comes from a tenant. `id: ../../escape` reaches
49
- * every one of those joins intact, so it is stopped once here rather than
50
- * defended at each of them.
51
- *
52
- * **Unsafe is the rule, not un-sluglike.** Nothing before this checked an
53
- * explicit id at all, so `Ava_1`, `team.alpha`, and `AVA` are all out there
54
- * keying real sessions and real credentials. Holding them to the shape ids
55
- * are minted in would not make anything safer — none of them can leave
56
- * their directory — and `loadRosterSouls` degrades a soul that will not
57
- * parse to a warning, so the only thing it would accomplish is dropping
58
- * those agents off the roster on upgrade, quietly, while their data stays
59
- * behind under the old id. Reserving the slug shape for ids nobody has
60
- * chosen yet costs nothing; imposing it on ids people are already using
61
- * costs them their agent.
62
- *
63
- * Rejected, never sanitized: rewriting `../../escape` into `escape` hands
64
- * back an agent nobody asked for, keyed to resources nobody named.
65
- */
66
- export declare const isValidAgentId: (id: string) => boolean;
67
- /**
68
- * Whether a `delegates` entry is one the soul can hold: any agent id, or
69
- * the wildcard — the same rule as {@link isValidAgentId}, so every agent a
70
- * roster can hold can be named as a target. Exported so the control API
71
- * refuses a bad entry as the client's error rather than discovering it in
72
- * the soul round-trip.
73
- */
74
- export declare const isValidDelegateEntry: (entry: string) => boolean;
75
- /**
76
- * How much of a new session id is the *client's* to spend, on top of the
77
- * agent id it addresses.
78
- *
79
- * Every id in circulation is a colon-joined address that embeds the agent
80
- * id — `web:<agentId>:<uuid>` from the dashboard, a channel key of
81
- * `<channel>:<agentId>:<team>:<conversation>:<thread>`, with a bare UUID
82
- * from the CLI the one exception. So a flat cap is the wrong shape: agent
83
- * ids are deliberately unbounded (see {@link isValidAgentId}), and a flat
84
- * 200 refused every dashboard conversation for an agent whose id ran past
85
- * 159 characters — an agent that stays on the roster and simply stops being
86
- * chattable, which is the quiet-breakage failure the unbounded rule exists
87
- * to avoid.
88
- *
89
- * Budgeting the composition instead keeps the bound meaningful without
90
- * capping the agent id through the back door. It cannot be gamed to widen
91
- * itself: the allowance comes from an agent id already checked against the
92
- * roster, not from the caller's own string.
93
- */
94
- export declare const MAX_SESSION_ID_LENGTH = 200;
95
- /**
96
- * Whether `id` may open a *new* conversation.
97
- *
98
- * Session ids are client-minted and a `POST` to an unknown one creates it,
99
- * so this is the only thing standing between an HTTP caller and a durable
100
- * row. `undefined`, `null`, and a bare space have all reached the session
101
- * table through that door — the dashboard shipped the first of them.
102
- *
103
- * **Checked where an id is minted, never where one is used.** An id already
104
- * in the store addresses a real conversation, whatever shape it is, and
105
- * re-validating on read would lock someone out of their own history to
106
- * enforce a rule that postdates it. Same reasoning as
107
- * {@link MAX_AGENT_ID_LENGTH}, which is why the length bound lives here and
108
- * not in {@link isValidAgentId}.
109
- *
110
- * `agentId` is the agent the id addresses, when the caller knows it — every
111
- * client convention embeds it, so its length is part of the budget rather
112
- * than something the bound gets to cap. The allowance applies only to an id
113
- * that actually contains it, since those are the characters being paid for;
114
- * a bare UUID and an unrelated string are both held to
115
- * {@link MAX_SESSION_ID_LENGTH} alone, as they are when `agentId` is
116
- * omitted.
117
- *
118
- * Shape is deliberately not enforced. Every id above is a legitimate
119
- * address, and no pattern admitting all of them excludes `undefined` — so
120
- * the safety rule, a bound, and {@link STRINGIFIED_NOTHING} are what catch
121
- * the real mistakes. Rejected, never sanitized: trimming an id hands the
122
- * caller back a conversation at an address it never asked for.
123
- */
124
- export declare const isValidSessionId: (id: string, agentId?: string) => boolean;
125
- /**
126
- * A freshly minted id, bounded — `base` trimmed so that appending `suffix`
127
- * still fits, with any hyphen left dangling by the trim removed.
128
- *
129
- * Only for ids nothing is keyed to yet: a generated agent's
130
- * name-plus-suffix, and `agent new` retrying a filename collision. Both mint
131
- * an id in the same breath as the agent, so trimming takes nothing away.
132
- * Shared rather than re-derived so the two do not each own half of the bound
133
- * and drift. An id derived from a name someone chose does *not* come through
134
- * here — that name may already have an agent behind it.
135
- */
136
- export declare const agentIdWithSuffix: (base: string, suffix?: string) => string;
137
- export interface DefineAgentInput {
138
- name?: string;
139
- id?: string;
140
- instructions?: string;
141
- tools?: string[];
142
- skills?: string[];
143
- credentials?: string[];
144
- delegates?: string[];
145
- /** See `AgentDefinition.listens`. */
146
- listens?: ListensMode;
147
- avatar?: AvatarTheme;
148
- /** Seed for deterministic identity generation (used in tests). */
149
- seed?: string;
150
- }
151
- /**
152
- * One-call agent creation. Everything is optional: with no input you get a
153
- * fresh identity with a human-ish name and a matching avatar theme.
154
- * Explicitly named agents keep a clean, predictable slug id.
155
- */
156
- export declare const defineAgent: (input?: DefineAgentInput) => AgentDefinition;
157
- /**
158
- * Whether `agent` may delegate to the agent with id `targetId`. Exact ids
159
- * or `*`; no namespace globs, because agent ids have no namespaces. Omitted
160
- * is nobody — see `AgentDefinition.delegates`.
161
- */
162
- export declare const isDelegateAllowed: (agent: Pick<AgentDefinition, "delegates">, targetId: string) => boolean;
163
- /**
164
- * A parsed soul file: the agent it defines plus optional runtime hints.
165
- * Souls are markdown with frontmatter — the frontmatter carries structured
166
- * identity (name, tools, credentials, provider, model) and the body is the
167
- * persona itself, written in prose.
168
- */
169
- export interface ParsedSoul {
170
- agent: AgentDefinition;
171
- /** Provider the soul prefers (e.g. "anthropic"). Runtimes may override. */
172
- provider?: string;
173
- /** Model the soul prefers (e.g. "claude-opus-5"). Runtimes may override. */
174
- model?: string;
175
- }
176
- export interface ParseSoulOptions {
177
- /** Seed for deterministic identity generation when the soul has no name. */
178
- seed?: string;
179
- }
180
- /**
181
- * Parse a soul file (markdown with optional frontmatter) into an agent
182
- * definition. The body becomes the agent's instructions; a missing name is
183
- * generated, so the smallest possible soul is just prose.
184
- */
185
- export declare const parseSoul: (source: string, options?: ParseSoulOptions) => ParsedSoul;
186
- export declare const formatSoul: (soul: ParsedSoul) => string;
187
- /**
188
- * The shape a skill id is written in — the Agent Skills spec's rule for
189
- * `name`, which is also the directory name: lowercase letters and digits
190
- * in hyphen-separated runs (`web-research`), at most 64 characters, no
191
- * leading, trailing, or doubled hyphen. One pattern for the manifest's
192
- * declared ids, the operator directory's folder names, and install-time
193
- * validation — two copies would drift into two answers to what a valid
194
- * id is.
195
- */
196
- export declare const SKILL_ID_PATTERN: RegExp;
197
- /** The spec's ceiling on `name`, and so on a skill id. */
198
- export declare const SKILL_ID_MAX_LENGTH = 64;
199
- export declare const isValidSkillId: (id: string) => boolean;
200
- /**
201
- * Whether an id that is already on this machine — a directory under
202
- * `~/.stratus/skills/`, a plugin manifest's declared id — is served.
203
- * Wider than `isValidSkillId` on purpose: the spec's rule arrived after
204
- * some of these were written, and tightening the *loader* would silently
205
- * drop an enabled procedure from an agent on upgrade. Installing and
206
- * validating use the strict rule; loading uses this one, and warns.
207
- */
208
- export declare const isLoadableSkillId: (id: string) => boolean;
209
- /** What a skill id refusal says, everywhere one is refused. */
210
- export declare const SKILL_ID_RULE = "Skill ids are lowercase letters, digits, and single hyphens (web-research), at most 64 characters.";
211
- /** The spec's ceiling on `description`. */
212
- export declare const SKILL_DESCRIPTION_MAX_LENGTH = 1024;
213
- /** The spec's ceiling on `compatibility`. */
214
- export declare const SKILL_COMPATIBILITY_MAX_LENGTH = 500;
215
- /**
216
- * A parsed `SKILL.md`: the one-line identity that reaches the system
217
- * prompt, and the body that only ever travels through `skill.read`.
218
- */
219
- export interface ParsedSkillDocument {
220
- /**
221
- * The skill's name — under the spec, its id, and equal to its directory
222
- * name. Optional here because loading stays tolerant of what is already
223
- * installed; the registered skill falls back to its id.
224
- */
225
- name?: string;
226
- /**
227
- * When to reach for this skill — what routing runs on, so it earns its
228
- * place by saying when, not what the body contains.
229
- */
230
- description: string;
231
- /** The spec's `license`: a name, or a bundled file. Informational. */
232
- license?: string;
233
- /**
234
- * The spec's `compatibility`: what the skill needs from its environment,
235
- * in prose — for the operator installing it, since nothing here can act
236
- * on it.
237
- */
238
- compatibility?: string;
239
- /** The spec's `metadata:` map, verbatim — every value a string. */
240
- metadata?: Record<string, string>;
241
- /** `metadata.version`, or the legacy top-level key. Informational. */
242
- version?: string;
243
- /**
244
- * Toolset globs the procedure expects (`browser.*`), from
245
- * `metadata.requires` (space-separated) or the legacy top-level list.
246
- * Advisory — see `Skill.requires`.
247
- */
248
- requires?: string[];
249
- /**
250
- * Top-level keys outside the spec, in file order — the legacy Stratus
251
- * keys and other hosts' fields alike. What validation warns about.
252
- */
253
- unknownKeys: string[];
254
- body: string;
255
- }
256
- /**
257
- * Parse a `SKILL.md` — the same frontmatter dialect souls use (`key: value`
258
- * scalars, block lists), plus the spec's `metadata:` map. The body is the
259
- * procedure itself, markdown, untouched.
260
- *
261
- * `description` is required: it is the only thing the model sees before
262
- * deciding to load the body, and a skill without one is unreachable by the
263
- * mechanism that makes skills cheap. Everything the spec constrains beyond
264
- * presence — the name rule, the length ceilings — is
265
- * `validateSkillDocument`'s, so that loading what is already installed
266
- * stays lenient while installing is strict.
267
- */
268
- export declare const parseSkillDocument: (source: string) => ParsedSkillDocument;
269
- export interface ValidateSkillDocumentOptions {
270
- /**
271
- * The directory the skill sits in (its basename), which the spec
272
- * requires `name` to equal. Omit where the directory is circumstance
273
- * rather than identity — a repository whose root is the skill, checked
274
- * out wherever git put it.
275
- */
276
- directoryName?: string;
277
- /**
278
- * What to suggest when `name` is missing — the directory name, or for a
279
- * root skill the repository's. Only ever read for the error text.
280
- */
281
- suggestedName?: string;
282
- }
283
- /** What `validateSkillDocument` found: errors refuse an install, warnings ride along. */
284
- export interface SkillValidation {
285
- errors: string[];
286
- warnings: string[];
287
- }
288
- /**
289
- * Check a parsed `SKILL.md` against the Agent Skills spec — the checks
290
- * `skills-ref validate` runs, so a skill that passes here passes there:
291
- * `name` present, shaped like an id, equal to the directory name;
292
- * `description` and `compatibility` under their ceilings. Errors are what
293
- * refuses an install. Top-level keys the spec does not define are
294
- * warnings, not errors: the reference validator refuses them, but the
295
- * ecosystem's skills carry other hosts' fields routinely, and refusing a
296
- * skill over a field that changes nothing here fails the whole point of
297
- * conforming. The legacy Stratus keys get their own warning, naming the
298
- * `metadata:` form that ports.
299
- *
300
- * Loading never calls this — an installed skill keeps loading whatever
301
- * the spec says today. Installing always does.
302
- */
303
- export declare const validateSkillDocument: (document: ParsedSkillDocument, options?: ValidateSkillDocumentOptions) => SkillValidation;
304
- export interface LazySkillInput {
305
- /** The id the skill registers under — qualified for a plugin's skill. */
306
- id: string;
307
- /** The parsed document, from the load-time read that validated the file. */
308
- document: ParsedSkillDocument;
309
- /** Re-read the file's source. Called on demand; the registry caches. */
310
- read: () => Promise<string>;
311
- }
312
- /**
313
- * A `Skill` whose body stays on disk until somebody asks. The identity
314
- * comes from the load-time parse (which is also what validated the file);
315
- * `load()` re-reads rather than closing over the body, so an
316
- * enabled-but-unused skill costs its description line and nothing else —
317
- * in the prompt and in memory.
318
- */
319
- export declare const createLazySkill: ({ id, document, read }: LazySkillInput) => Skill;
320
- export declare const MEMORY_TOOL_NAME = "memory.remember";
321
- /**
322
- * A tool that lets an agent write to its own long-term memory. Entries are
323
- * keyed by the session's agent id, so what one agent learns stays exclusively
324
- * that agent's knowledge — and follows it to every channel and thread.
325
- */
326
- export declare const createRememberTool: (store: AgentMemoryStore) => Tool;
327
- export declare const RECALL_TOOL_NAME = "memory.recall";
328
- /**
329
- * Searches the agent's own long-term memory. `safe` by the same rule as
330
- * `memory.remember`: reading what this agent already knows. The query is
331
- * literal text — the store does whatever escaping its backend needs, so no
332
- * query a model writes is ever a syntax error; matching nothing is a normal
333
- * result, because an agent that has learned nothing yet is the ordinary
334
- * starting state, not a broken tool.
335
- */
336
- export declare const createRecallTool: (store: AgentMemoryStore) => Tool;
337
- export declare const FORGET_TOOL_NAME = "memory.forget";
338
- /**
339
- * Retires one of the agent's own memories, by id. Tombstoned rather than
340
- * deleted — which is what makes `safe` defensible for it: the entry stops
341
- * being live but does not stop existing, so an operator can still see what
342
- * an agent chose to drop.
343
- */
344
- export declare const createForgetTool: (store: AgentMemoryStore) => Tool;
345
- export declare const DELEGATE_TOOL_NAME = "agent.delegate";
346
- /**
347
- * Metadata a delegated sub-session carries: which agent delegated, and the
348
- * session at the root of the chain. Written by `agent.delegate` and read by
349
- * the gateway's restart sweep, which is why the keys are named here rather
350
- * than spelled twice — a sub-session's parent is a turn in some other
351
- * process's memory, and after a restart nothing can consume its reply.
352
- */
353
- export declare const DELEGATED_BY_METADATA_KEY = "delegatedBy";
354
- export declare const ROOT_SESSION_ID_METADATA_KEY = "rootSessionId";
355
- export declare const DELEGATION_DEPTH_METADATA_KEY = "delegationDepth";
356
- /**
357
- * The segment `agent.delegate` mints into every sub-session's id —
358
- * `<parent>:delegate:<agent>:<depth>:<suffix>`. The second half of what
359
- * identifies a sub-session, beside the metadata above: the gateway refuses
360
- * the metadata keys at its public door, but rows written before it did
361
- * cannot be told apart by their metadata alone, and a caller who wrote
362
- * `delegatedBy` onto a session of its own would not also have minted an
363
- * id in this shape.
364
- */
365
- export declare const DELEGATED_SESSION_ID_MARKER = ":delegate:";
366
- /**
367
- * Whether this session is a delegated sub-session — one whose reply is
368
- * consumed by a parent turn's `agent.delegate` call and by nothing else.
369
- * Both halves are required: the metadata `agent.delegate` writes, and the
370
- * id shape it mints.
371
- */
372
- export declare const isDelegatedSession: (session: Pick<Session, "id" | "metadata">) => boolean;
373
- /**
374
- * The id of the session whose `agent.delegate` call started this one, read
375
- * off the id shape above — the text before the last marker, since a nested
376
- * sub-session embeds its parent's id whole. Undefined for an id that was
377
- * not minted that way.
378
- */
379
- export declare const delegatingSessionIdOf: (sessionId: string) => string | undefined;
380
- /**
381
- * The id of the `agent.delegate` call in `parent` that is still awaiting
382
- * `child`, or undefined when none is.
383
- *
384
- * The one thing about a delegation nothing outside the runner can forge:
385
- * a caller can name a session in the sub-session id shape and write the
386
- * metadata keys, but only the runner writes assistant tool calls, and only
387
- * a delegation in flight leaves one with no result behind it. Matched to
388
- * the child and not merely counted, because a parent can be inside one
389
- * delegation while an earlier sub-session of its — continued from outside
390
- * under a version that kept the markers — is parked on something of its
391
- * own. The call names its target and its prompt, and `agent.delegate`
392
- * made the prompt the child's first user message. Read against the
393
- * transcript order so a re-used call id cannot make a later call look
394
- * answered.
395
- */
396
- export declare const outstandingDelegationFor: (parent: Pick<Session, "messages">, child: Pick<Session, "agent" | "messages">) => string | undefined;
397
- /**
398
- * `metadata` with the delegation markers removed — what a sub-session
399
- * carries once it has been addressed from outside. The delegation ended
400
- * with the turn that awaited it; a conversation somebody continues on the
401
- * same id afterwards is an ordinary one, and must not be closed as an
402
- * orphan by a later restart.
403
- */
404
- export declare const withoutDelegation: (metadata: JsonObject) => JsonObject;
405
- /**
406
- * Runs a delegated sub-session. A plain runner works when every agent
407
- * shares one provider; a host with per-agent provider routing (the
408
- * gateway) supplies its own dispatcher so the target runs on the
409
- * target's resolved provider and credentials — never the delegator's.
410
- */
411
- export type DelegateDispatch = (input: {
412
- sessionId: string;
413
- agent: AgentDefinition;
414
- userMessage: string;
415
- metadata: JsonObject;
416
- /** The parent turn's abort signal — a cancelled parent cancels the delegated run too. */
417
- signal?: AbortSignal;
418
- }) => Promise<Session>;
419
- export type DelegateToolOptions = {
420
- registry: AgentRegistry;
421
- /** Maximum delegation depth to stop orchestrator loops. Default 3. */
422
- maxDepth?: number;
423
- } & ({
424
- runner: AgentRunner;
425
- dispatch?: never;
426
- } | {
427
- dispatch: DelegateDispatch;
428
- runner?: never;
429
- });
430
- /**
431
- * The orchestrator primitive: a tool that runs another agent in its own
432
- * sub-session (with that agent's memory, tool allowlist, and credentials)
433
- * and returns its final reply as the tool result.
434
- */
435
- export declare const createDelegateTool: ({ registry, runner, dispatch, maxDepth, }: DelegateToolOptions) => Tool;
436
- export interface AgentRouteRule {
437
- /** Regex or predicate matched against the routing key (e.g. channel or message). */
438
- match: RegExp | ((input: string) => boolean);
439
- agent: AgentDefinition;
440
- }
441
- export interface AgentRouter {
442
- route(input: string): AgentDefinition;
443
- }
444
- /**
445
- * Route inbound work (a channel name, a message, a thread key) to an agent.
446
- * The Slack transport will feed channel/mention strings through this so the
447
- * same person consistently answers in the same places.
448
- */
449
- export declare const createAgentRouter: (rules: AgentRouteRule[], fallback: AgentDefinition) => AgentRouter;
450
- /** Register a set of agents and get the registry back. */
451
- export declare const createAgentTeam: (agents: AgentDefinition[]) => AgentRegistry;
452
- /**
453
- * Where a schedule reports, or a `message.send` speaks: a channel kind plus
454
- * a channel-native id — the same convention approver lists use, because
455
- * mapping through a Stratus identity adds a lookup that can only be wrong.
456
- */
457
- export interface ScheduleDestination {
458
- /** Channel kind, e.g. 'slack' — which adapter must do the talking. */
459
- channel: string;
460
- /** Channel-native conversation id (Slack: `C…`/`G…`/`D…`). */
461
- to: string;
462
- }
463
- /**
464
- * The one string form of a destination, `<channel>:<native id>`, used
465
- * everywhere a destination is *compared*: `Tool.destinationFor`, the
466
- * permission policy's pre-authorization check, and the schedule row it is
467
- * checked against. One canonicalization, or two writers of `slack:C01` and
468
- * `SLACK:C01` would disagree about the same channel.
469
- */
470
- export declare const canonicalDestination: (destination: ScheduleDestination) => string;
471
- /**
472
- * When a schedule runs. Three shapes rather than one string, because the
473
- * three are advanced differently: an interval adds itself to the previous
474
- * slot, a cron expression is searched forward, and a one-shot has no next
475
- * at all.
476
- */
477
- export type ScheduleCadence = {
478
- kind: 'every';
479
- intervalMs: number;
480
- } | {
481
- kind: 'cron';
482
- expression: string;
483
- } | {
484
- kind: 'at';
485
- at: string;
486
- };
487
- /** One durable schedule, exactly as the human approved it. */
488
- export interface ScheduleRecord {
489
- id: string;
490
- agentId: string;
491
- cadence: ScheduleCadence;
492
- /** The user message each firing dispatches — the payload of the feature. */
493
- prompt: string;
494
- /**
495
- * Where firings are pre-authorized to report. Absent for a silent
496
- * schedule, whose firings face the gate like any inbound turn.
497
- */
498
- destination?: ScheduleDestination;
499
- createdAt: string;
500
- /** The session whose turn created it, for the audit trail. */
501
- createdBy?: string;
502
- /**
503
- * The trust label of the session that set the schedule. The prompt is
504
- * that session's text, so each firing's "sender" is the agent's past
505
- * self at that label — a tainted session must not launder attacker text
506
- * into a fresh, trusted firing. Absent on a schedule set before
507
- * provenance was tracked, and a firing reads that as `unknown`.
508
- */
509
- trust?: TrustLevel;
510
- /**
511
- * The next slot, ISO-8601. Consumed — advanced — BEFORE the dispatch, so
512
- * a daemon that dies mid-firing can never run the same window twice.
513
- * Absent for a spent one-shot: it will not fire again and its row stays
514
- * only until the firing it pre-authorized has finished.
515
- */
516
- nextFireAt?: string;
517
- lastFiredAt?: string;
518
- /**
519
- * The session id of the most recent firing. What the restart sweep uses
520
- * to tell a spent one-shot whose turn is parked on a human (keep the row
521
- * — it is the approval's scope) from one whose turn is over (delete it).
522
- */
523
- lastSessionId?: string;
524
- }
525
- /** `every` strings: a positive integer and one unit — `90s`, `10m`, `2h`, `1d`. */
526
- export declare const parseInterval: (text: string) => number | undefined;
527
- interface CronFields {
528
- minutes: Set<number>;
529
- hours: Set<number>;
530
- daysOfMonth: Set<number>;
531
- months: Set<number>;
532
- daysOfWeek: Set<number>;
533
- /**
534
- * Whether the day fields were written as anything but `*`. Standard cron
535
- * semantics: when BOTH are restricted, a day matches if EITHER does —
536
- * `0 0 1 * 1` is "the 1st, and every Monday", not "the 1st when it is a
537
- * Monday".
538
- */
539
- domRestricted: boolean;
540
- dowRestricted: boolean;
541
- }
542
- /**
543
- * Five fields — minute, hour, day-of-month, month, day-of-week — with `*`,
544
- * lists, ranges, and steps. Numbers only; day-of-week 0-7 with both 0 and 7
545
- * as Sunday. Evaluated in the daemon's local time, which is what "every
546
- * morning at 7" means to the person whose machine it is.
547
- */
548
- export declare const parseCronExpression: (expression: string) => CronFields;
549
- /**
550
- * The slot after `after`, or undefined when there is none — a one-shot
551
- * already past, or a cron expression that matches no real date. One
552
- * implementation, because the scheduler advancing a fired slot and the
553
- * creation path computing the first one must never disagree.
554
- */
555
- export declare const nextFireAfter: (cadence: ScheduleCadence, after: Date) => Date | undefined;
556
- /** One line for a human: `every 30m`, `cron 0 7 * * *`, `once at 2026-…`. */
557
- export declare const describeCadence: (cadence: ScheduleCadence) => string;
558
- /**
559
- * Metadata a firing's session carries. The schedule id is what the
560
- * permission carve-out resolves the approved destination from, and
561
- * `scheduled: true` is what lets a renderer say a turn arrived from a
562
- * schedule rather than a person.
563
- */
564
- export declare const SCHEDULE_ID_METADATA_KEY = "scheduleId";
565
- export declare const SCHEDULED_TURN_METADATA_KEY = "scheduled";
566
- export declare const SCHEDULE_EVERY_TOOL_NAME = "schedule.every";
567
- export declare const SCHEDULE_AT_TOOL_NAME = "schedule.at";
568
- export declare const SCHEDULE_LIST_TOOL_NAME = "schedule.list";
569
- export declare const SCHEDULE_CANCEL_TOOL_NAME = "schedule.cancel";
570
- export declare const MESSAGE_SEND_TOOL_NAME = "message.send";
571
- /**
572
- * The tools only a running gateway registers. Each needs the dispatcher,
573
- * the store, or the channels, and nothing else in the tree has them — so a
574
- * soul naming one is correct while a host without them cannot call it,
575
- * which is a different thing from a name that does not exist. `stratus
576
- * run` reads this to say which it is rather than reporting a daemon soul's
577
- * `schedule.*` as a typo.
578
- *
579
- * It lives here, with the names, rather than in `@stratusagent/gateway`
580
- * where the registrations are: the CLI imports the gateway only through
581
- * `await import`, because `bin.ts` has to load the CLI to print the Node
582
- * version message and the gateway pulls in `node:sqlite` at module scope.
583
- * A static import for a list of strings would have made the floor guard
584
- * fail with the exact builtin-module error it exists to replace. The
585
- * gateway's own test pins this set against what it actually registers,
586
- * which holds the two together better than proximity would.
587
- */
588
- export declare const GATEWAY_ONLY_TOOL_NAMES: readonly string[];
589
- export interface ScheduleCreateInput {
590
- agentId: string;
591
- cadence: ScheduleCadence;
592
- prompt: string;
593
- destination?: ScheduleDestination;
594
- /** The session whose turn asked, for the audit trail. */
595
- createdBy?: string;
596
- /** That session's trust label at the time — see `ScheduleRecord.trust`. */
597
- trust?: TrustLevel;
598
- }
599
- /**
600
- * The gateway-supplied handle the schedule tools close over — the same
601
- * pattern as `agent.delegate`'s dispatcher, because the scheduler needs the
602
- * store, the roster, and the channels, and none of those are this package's
603
- * to hold. `create` owns every refusal that needs daemon knowledge: the
604
- * interval floor, and a destination the agent's channel cannot address —
605
- * checked NOW, while a person is present to hear why, not at 6am.
606
- */
607
- export interface SchedulerHandle {
608
- create(input: ScheduleCreateInput): Promise<ScheduleRecord>;
609
- list(agentId: string): Promise<ScheduleRecord[]>;
610
- /** True when a schedule of this agent's was cancelled; false when nothing matched. */
611
- cancel(agentId: string, scheduleId: string): Promise<boolean>;
612
- }
613
- /**
614
- * One schedule as a surface shows it — the CLI table, the control API's
615
- * listing, and the tool results all render this one projection, so the
616
- * operator's view and the agent's cannot drift.
617
- */
618
- export declare const describeSchedule: (record: ScheduleRecord) => JsonObject;
619
- /**
620
- * The four `schedule.*` tools over one handle.
621
- *
622
- * Risk is split per tool, not per toolset: creating a schedule spends
623
- * future money unattended and (with a destination) mints a standing
624
- * permission to speak, so `schedule.every` and `schedule.at` are `gated` —
625
- * the approval of THAT call is the human decision the whole step leans on.
626
- * `schedule.list` is a read, and `schedule.cancel` only ever narrows
627
- * authority — it is the reversal the risk note in the spec names — so both
628
- * are `safe`: a headless agent that set a bad schedule must be able to
629
- * undo it without waiting for the human whose absence is the problem.
630
- */
631
- export declare const createScheduleTools: (scheduler: SchedulerHandle) => Tool[];
632
- /**
633
- * Delivers one outbound message through the agent's channel. The gateway
634
- * implements it over the channel contract's `resolveOutbound`; rejecting is
635
- * the way to say a destination cannot be served.
636
- */
637
- export type OutboundMessenger = (input: {
638
- agentId: string;
639
- destination: ScheduleDestination;
640
- text: string;
641
- }) => Promise<void>;
642
- /**
643
- * Post to a channel or DM outside the current conversation — what makes a
644
- * scheduled turn observable.
645
- *
646
- * `gated`, and deliberately not `safe` the way `agent.delegate` is: the
647
- * delegate stays inside the fleet, under every per-agent allowlist and the
648
- * same approval policy, while this speaks to people who did not ask. The
649
- * unattended path is the schedule carve-out — `destinationFor` names where
650
- * this call would speak, and the policy allows it exactly when the firing's
651
- * schedule was approved with that destination.
652
- */
653
- export declare const createMessageSendTool: (send: OutboundMessenger) => Tool;
654
- export {};
1
+ export { AVATAR_STYLE, generateAgentName, generateAvatarTheme, AGENT_ID_PATTERN, MAX_AGENT_ID_LENGTH, isValidAgentId, isValidDelegateEntry, MAX_SESSION_ID_LENGTH, isValidSessionId, agentIdWithSuffix, } from './identity.ts';
2
+ export { type DefineAgentInput, defineAgent } from './define.ts';
3
+ export { isDelegateAllowed, type ParsedSoul, type ParseSoulOptions, parseSoul, formatSoul, } from './soul.ts';
4
+ export { SKILL_ID_PATTERN, SKILL_ID_MAX_LENGTH, isValidSkillId, isLoadableSkillId, SKILL_ID_RULE, SKILL_DESCRIPTION_MAX_LENGTH, SKILL_COMPATIBILITY_MAX_LENGTH, type ParsedSkillDocument, parseSkillDocument, type ValidateSkillDocumentOptions, type SkillValidation, validateSkillDocument, type LazySkillInput, createLazySkill, } from './skills.ts';
5
+ export { type ScheduleDestination, canonicalDestination, type ScheduleCadence, type ScheduleRecord, parseInterval, parseCronExpression, nextFireAfter, describeCadence, SCHEDULE_ID_METADATA_KEY, SCHEDULED_TURN_METADATA_KEY, type ScheduleCreateInput, type SchedulerHandle, describeSchedule, } from './schedules.ts';
6
+ export { type AgentRouteRule, type AgentRouter, createAgentRouter, createAgentTeam, } from './router.ts';
7
+ export { MEMORY_TOOL_NAME, createRememberTool, RECALL_TOOL_NAME, createRecallTool, FORGET_TOOL_NAME, createForgetTool, PIN_TOOL_NAME, createPinTool, type MemoryToolOptions, } from './tools/memory.ts';
8
+ export { DELEGATE_TOOL_NAME, DELEGATED_BY_METADATA_KEY, ROOT_SESSION_ID_METADATA_KEY, DELEGATION_DEPTH_METADATA_KEY, DELEGATED_SESSION_ID_MARKER, isDelegatedSession, delegatingSessionIdOf, outstandingDelegationFor, withoutDelegation, type DelegateDispatch, type DelegateToolOptions, createDelegateTool, } from './tools/delegate.ts';
9
+ export { SCHEDULE_EVERY_TOOL_NAME, SCHEDULE_AT_TOOL_NAME, SCHEDULE_LIST_TOOL_NAME, SCHEDULE_CANCEL_TOOL_NAME, createScheduleTools, } from './tools/schedule.ts';
10
+ export { MESSAGE_SEND_TOOL_NAME, type OutboundMessenger, createMessageSendTool, } from './tools/message.ts';
11
+ export { GATEWAY_ONLY_TOOL_NAMES } from './tools/gateway-only.ts';
655
12
  //# sourceMappingURL=index.d.ts.map