@rowan-agent/agent 0.8.6 → 0.8.7
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/README.md +77 -8
- package/dist/index.d.ts +3 -3
- package/dist/index.js +21 -13
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -11,24 +11,39 @@ import {
|
|
|
11
11
|
AgentRuntime,
|
|
12
12
|
createCoreTools,
|
|
13
13
|
InMemoryStore,
|
|
14
|
+
loadPhases,
|
|
15
|
+
loadSkills,
|
|
14
16
|
} from "@rowan-agent/agent";
|
|
15
17
|
|
|
18
|
+
const skills = await loadSkills("./.rowan/skills");
|
|
19
|
+
const phases = await loadPhases("./.rowan/phases");
|
|
16
20
|
const runtime = await AgentRuntime.init({
|
|
17
21
|
store: new InMemoryStore(),
|
|
18
22
|
});
|
|
19
23
|
|
|
20
24
|
const agentId = await runtime.createAgent({
|
|
21
25
|
identity: "example:v1", // Stable config snapshot identity, not the Agent ID
|
|
22
|
-
model: {
|
|
23
|
-
|
|
26
|
+
model: {
|
|
27
|
+
provider: "openai",
|
|
28
|
+
id: "gpt-4o",
|
|
29
|
+
protocol: "openai-responses",
|
|
30
|
+
baseUrl: "https://api.openai.com/v1",
|
|
31
|
+
apiKey: process.env.OPENAI_API_KEY!,
|
|
32
|
+
},
|
|
24
33
|
definition: {
|
|
25
34
|
name: "workspace-assistant",
|
|
26
35
|
description: "Assist with the current workspace.",
|
|
27
|
-
|
|
36
|
+
prompt: "You are helpful.",
|
|
37
|
+
contexts: ["workspace"],
|
|
28
38
|
},
|
|
29
39
|
resources: {
|
|
30
40
|
tools: createCoreTools({ root: process.cwd() }),
|
|
31
|
-
skills
|
|
41
|
+
skills,
|
|
42
|
+
contexts: [{
|
|
43
|
+
name: "workspace",
|
|
44
|
+
value: { root: process.cwd() },
|
|
45
|
+
}],
|
|
46
|
+
phases,
|
|
32
47
|
},
|
|
33
48
|
});
|
|
34
49
|
|
|
@@ -126,7 +141,7 @@ await runtime.loadAgents({
|
|
|
126
141
|
values: [{
|
|
127
142
|
name: "workspace-assistant",
|
|
128
143
|
description: "Assist with the current workspace.",
|
|
129
|
-
|
|
144
|
+
prompt: "You are helpful.",
|
|
130
145
|
}],
|
|
131
146
|
});
|
|
132
147
|
await runtime.loadTools({
|
|
@@ -143,8 +158,13 @@ const agentId = await runtime.createAgent({
|
|
|
143
158
|
skills: [],
|
|
144
159
|
phases: [],
|
|
145
160
|
},
|
|
146
|
-
model: {
|
|
147
|
-
|
|
161
|
+
model: {
|
|
162
|
+
provider: "openai",
|
|
163
|
+
id: "gpt-4o",
|
|
164
|
+
protocol: "openai-responses",
|
|
165
|
+
baseUrl: "https://api.openai.com/v1",
|
|
166
|
+
apiKey: process.env.OPENAI_API_KEY!,
|
|
167
|
+
},
|
|
148
168
|
});
|
|
149
169
|
```
|
|
150
170
|
|
|
@@ -156,4 +176,53 @@ Tool and `default` Phase are always available and cannot be overridden.
|
|
|
156
176
|
Extensions are Runtime-global. Load them only during `AgentRuntime.init()` via
|
|
157
177
|
`bootstrap`; after initialization they are frozen until the Runtime closes.
|
|
158
178
|
Definition name lists narrow the selected Tools, Skills, and Phases: omission
|
|
159
|
-
inherits all candidates, `[]` selects none, and missing names are skipped.
|
|
179
|
+
inherits all candidates, `[]` selects none, and missing names are skipped. The
|
|
180
|
+
same rule applies to `definition.contexts`.
|
|
181
|
+
|
|
182
|
+
### Resources and Definition
|
|
183
|
+
|
|
184
|
+
`resources` and `definition` have different jobs:
|
|
185
|
+
|
|
186
|
+
- `resources` supplies the concrete candidates available to one Agent. Its
|
|
187
|
+
Tools contain executable `execute()` functions; Skills and Phases contain
|
|
188
|
+
their loaded content; Contexts contain JSON-safe values.
|
|
189
|
+
- `definition` declares which candidates this Agent uses. `tools`, `skills`,
|
|
190
|
+
`contexts`, and `phases` are name-based selectors; they cannot create a
|
|
191
|
+
resource that is absent from `resources`.
|
|
192
|
+
|
|
193
|
+
For a single-process embedding, provide concrete resources directly and omit
|
|
194
|
+
the selectors when the Agent should use everything:
|
|
195
|
+
|
|
196
|
+
```ts
|
|
197
|
+
const agentId = await runtime.createAgent({
|
|
198
|
+
identity: "workspace:v1",
|
|
199
|
+
definition: {
|
|
200
|
+
name: "workspace-assistant",
|
|
201
|
+
description: "Assist with the current workspace.",
|
|
202
|
+
prompt: "You are helpful.",
|
|
203
|
+
},
|
|
204
|
+
resources: { tools, skills, contexts, phases },
|
|
205
|
+
model,
|
|
206
|
+
});
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
Use selectors when several Agents share a candidate pool:
|
|
210
|
+
|
|
211
|
+
```ts
|
|
212
|
+
definition: {
|
|
213
|
+
name: "read-only-assistant",
|
|
214
|
+
description: "Inspect the workspace without changing it.",
|
|
215
|
+
prompt: "You are helpful.",
|
|
216
|
+
tools: ["read"],
|
|
217
|
+
contexts: ["workspace"],
|
|
218
|
+
phases: { entryPhaseId: "review", phaseIds: ["review"] },
|
|
219
|
+
}
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
For process-boundary persistence, use the Resource Registry form shown above:
|
|
223
|
+
`resourceView` stores stable source IDs instead of executable resource
|
|
224
|
+
closures, and the Runtime resolves those sources into an immutable
|
|
225
|
+
Configuration Snapshot. This lets a restarted Runtime resolve the same
|
|
226
|
+
resource revisions while keeping each Run pinned to the snapshot that created
|
|
227
|
+
it. Direct `resources` are simpler for embedding; `resourceView` is the
|
|
228
|
+
declarative form for shared, reloadable, and restart-resolvable resources.
|
package/dist/index.d.ts
CHANGED
|
@@ -627,11 +627,11 @@ type PhaseRegistrySelection = Readonly<{
|
|
|
627
627
|
type AgentDefinition = Readonly<{
|
|
628
628
|
name: string;
|
|
629
629
|
description: string;
|
|
630
|
-
|
|
630
|
+
prompt: string;
|
|
631
631
|
tools?: readonly string[];
|
|
632
632
|
skills?: readonly string[];
|
|
633
633
|
phases?: PhaseRegistrySelection;
|
|
634
|
-
|
|
634
|
+
contexts?: readonly string[];
|
|
635
635
|
model?: ModelRef;
|
|
636
636
|
}>;
|
|
637
637
|
/** Parse one Markdown definition using the same frontmatter vocabulary as Phase resources. */
|
|
@@ -1233,7 +1233,7 @@ declare class RuntimeBootstrapRegistry extends ResourceRegistry {
|
|
|
1233
1233
|
|
|
1234
1234
|
type DefinitionLayer = Readonly<{
|
|
1235
1235
|
description?: string;
|
|
1236
|
-
|
|
1236
|
+
prompt?: string;
|
|
1237
1237
|
model?: ModelRef;
|
|
1238
1238
|
tools?: readonly string[];
|
|
1239
1239
|
skills?: readonly string[];
|
package/dist/index.js
CHANGED
|
@@ -1045,13 +1045,15 @@ import { dirname as dirname3, join, resolve as resolve3 } from "path";
|
|
|
1045
1045
|
import { parseModelRef } from "@rowan-agent/models";
|
|
1046
1046
|
function assertAgentDefinition(value) {
|
|
1047
1047
|
if (!isRecord(value)) throw new TypeError("config.definition is invalid");
|
|
1048
|
+
if ("content" in value) throw new TypeError("definition.content is not supported; use definition.prompt");
|
|
1049
|
+
if ("context" in value) throw new TypeError("definition.context is not supported; use definition.contexts");
|
|
1048
1050
|
requiredString(value.name, "definition.name");
|
|
1049
1051
|
requiredString(value.description, "definition.description");
|
|
1050
|
-
requiredString(value.
|
|
1052
|
+
requiredString(value.prompt, "definition.prompt");
|
|
1051
1053
|
optionalStringList(value.tools, "definition.tools");
|
|
1052
1054
|
optionalStringList(value.skills, "definition.skills");
|
|
1053
1055
|
optionalPhaseRegistrySelection(value.phases, "definition.phases");
|
|
1054
|
-
optionalStringList(value.
|
|
1056
|
+
optionalStringList(value.contexts, "definition.contexts");
|
|
1055
1057
|
if ("extensions" in value) throw new TypeError("definition.extensions is not supported; Extensions are Runtime-global");
|
|
1056
1058
|
if ("entryPhase" in value) throw new TypeError("definition.entryPhase is not supported; use definition.phases.entryPhaseId");
|
|
1057
1059
|
if (value.model !== void 0) {
|
|
@@ -1064,17 +1066,19 @@ function parseAgentDefinition(raw) {
|
|
|
1064
1066
|
const { frontmatter, body } = parseFrontmatter(raw);
|
|
1065
1067
|
return normalizeAgentDefinition(frontmatter, body);
|
|
1066
1068
|
}
|
|
1067
|
-
function normalizeAgentDefinition(frontmatter,
|
|
1069
|
+
function normalizeAgentDefinition(frontmatter, prompt, options = {}) {
|
|
1070
|
+
if (frontmatter.content !== void 0) throw new TypeError("content is not supported; use prompt and the document body");
|
|
1071
|
+
if (frontmatter.context !== void 0) throw new TypeError("context is not supported; use contexts");
|
|
1068
1072
|
const name = frontmatter.name === void 0 && options.fallbackName ? options.fallbackName : requiredString(frontmatter.name, "name");
|
|
1069
1073
|
const description = requiredString(frontmatter.description, "description");
|
|
1070
|
-
const
|
|
1074
|
+
const normalizedPrompt = requiredString(prompt, "prompt");
|
|
1071
1075
|
const tools = optionalStringList(frontmatter.tools, "tools");
|
|
1072
1076
|
const skills = optionalStringList(frontmatter.skills, "skills");
|
|
1073
1077
|
const phases = optionalPhaseRegistrySelection(frontmatter.phases, "phases");
|
|
1074
1078
|
if (frontmatter.extensions !== void 0) {
|
|
1075
1079
|
throw new TypeError("extensions is not supported; Extensions are Runtime-global");
|
|
1076
1080
|
}
|
|
1077
|
-
const
|
|
1081
|
+
const contexts = optionalStringList(frontmatter.contexts, "contexts");
|
|
1078
1082
|
if (frontmatter.entryPhase !== void 0) {
|
|
1079
1083
|
throw new TypeError("entryPhase is not supported; use phases.entryPhaseId");
|
|
1080
1084
|
}
|
|
@@ -1082,11 +1086,11 @@ function normalizeAgentDefinition(frontmatter, content, options = {}) {
|
|
|
1082
1086
|
return {
|
|
1083
1087
|
name,
|
|
1084
1088
|
description,
|
|
1085
|
-
|
|
1089
|
+
prompt: normalizedPrompt,
|
|
1086
1090
|
...tools ? { tools } : {},
|
|
1087
1091
|
...skills ? { skills } : {},
|
|
1088
1092
|
...phases ? { phases } : {},
|
|
1089
|
-
...
|
|
1093
|
+
...contexts ? { contexts } : {},
|
|
1090
1094
|
...model ? { model } : {}
|
|
1091
1095
|
};
|
|
1092
1096
|
}
|
|
@@ -1273,7 +1277,7 @@ async function loadPhase(targetPath) {
|
|
|
1273
1277
|
isolated: metadata.isolated,
|
|
1274
1278
|
filePath: resolved,
|
|
1275
1279
|
baseDir,
|
|
1276
|
-
content: definition.
|
|
1280
|
+
content: definition.prompt,
|
|
1277
1281
|
model: definition.model
|
|
1278
1282
|
};
|
|
1279
1283
|
const codePath = await discoverPhaseCode(baseDir);
|
|
@@ -2784,6 +2788,9 @@ function assertAgentConfigRequest(config) {
|
|
|
2784
2788
|
if (!config.definition || typeof config.definition.name !== "string" || config.definition.name.trim() === "") {
|
|
2785
2789
|
throw new TypeError("config.definition.name must be non-empty");
|
|
2786
2790
|
}
|
|
2791
|
+
if (config.definition.layer && "content" in config.definition.layer) {
|
|
2792
|
+
throw new TypeError("definition.layer.content is not supported; use definition.layer.prompt");
|
|
2793
|
+
}
|
|
2787
2794
|
const view = config.resourceView;
|
|
2788
2795
|
if (!view || !Array.isArray(view.agents) || !Array.isArray(view.tools) || !Array.isArray(view.skills) || !Array.isArray(view.phases)) {
|
|
2789
2796
|
throw new TypeError("config.resourceView is invalid");
|
|
@@ -2901,7 +2908,7 @@ function snapshotConfig(config) {
|
|
|
2901
2908
|
phaseIds: Object.freeze([...config.definition.phases.phaseIds])
|
|
2902
2909
|
})
|
|
2903
2910
|
} : {},
|
|
2904
|
-
...config.definition.
|
|
2911
|
+
...config.definition.contexts ? { contexts: Object.freeze([...config.definition.contexts]) } : {}
|
|
2905
2912
|
});
|
|
2906
2913
|
const resources = Object.freeze({
|
|
2907
2914
|
...config.resources,
|
|
@@ -3365,7 +3372,7 @@ function resolveDefinitionContext(config, assembled = {}) {
|
|
|
3365
3372
|
);
|
|
3366
3373
|
const contexts = selectNamedResources(
|
|
3367
3374
|
config.resources.contexts ?? [],
|
|
3368
|
-
config.definition.
|
|
3375
|
+
config.definition.contexts,
|
|
3369
3376
|
"Context"
|
|
3370
3377
|
);
|
|
3371
3378
|
const candidateRegistry = assembled.phases ?? config.resources.phases;
|
|
@@ -3381,7 +3388,7 @@ function resolveDefinitionContext(config, assembled = {}) {
|
|
|
3381
3388
|
console.warn(`Phase entry "${requestedEntry}" is not available; Rowan will use "default".`);
|
|
3382
3389
|
}
|
|
3383
3390
|
return {
|
|
3384
|
-
systemPrompt: [config.definition.
|
|
3391
|
+
systemPrompt: [config.definition.prompt, buildContextDescription(contexts)].filter((section) => section.length > 0).join("\n\n"),
|
|
3385
3392
|
tools,
|
|
3386
3393
|
skills,
|
|
3387
3394
|
phases: { phases, entryPhaseId }
|
|
@@ -4568,6 +4575,7 @@ var ResourceRegistry = class {
|
|
|
4568
4575
|
assertSourceId(sourceId);
|
|
4569
4576
|
const names = /* @__PURE__ */ new Set();
|
|
4570
4577
|
for (const value of values) {
|
|
4578
|
+
if (kind === "agent") assertAgentDefinition(value);
|
|
4571
4579
|
assertNamedResource(value, kind, sourceId);
|
|
4572
4580
|
if (isImplicitCoreName(kind, value.name) && sourceId !== "rowan.core") {
|
|
4573
4581
|
throw new ResourceRegistryError(
|
|
@@ -4922,7 +4930,7 @@ function resolveConfigurationSnapshot(registry, input) {
|
|
|
4922
4930
|
const tools = selectNamedResources(resolved.tools, definition.tools, "Tool");
|
|
4923
4931
|
const skills = selectNamedResources(resolved.skills, definition.skills, "Skill");
|
|
4924
4932
|
const phases = resolvePhases(resolved.phases, definition.phases);
|
|
4925
|
-
const contexts = selectNamedResources(input.contexts ?? [], base.
|
|
4933
|
+
const contexts = selectNamedResources(input.contexts ?? [], base.contexts, "Context");
|
|
4926
4934
|
return {
|
|
4927
4935
|
identity: input.identity,
|
|
4928
4936
|
definition,
|
|
@@ -4973,7 +4981,7 @@ function applyDefinitionLayer(base, layer) {
|
|
|
4973
4981
|
return {
|
|
4974
4982
|
...base,
|
|
4975
4983
|
...layer.description === void 0 ? {} : { description: layer.description },
|
|
4976
|
-
...layer.
|
|
4984
|
+
...layer.prompt === void 0 ? {} : { prompt: layer.prompt },
|
|
4977
4985
|
...layer.model === void 0 ? {} : { model: layer.model },
|
|
4978
4986
|
...layer.tools === void 0 ? {} : { tools: intersectNames(base.tools, layer.tools, "Tool") },
|
|
4979
4987
|
...layer.skills === void 0 ? {} : { skills: intersectNames(base.skills, layer.skills, "Skill") },
|