@rowan-agent/agent 0.9.0 → 0.9.2
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/dist/index.d.ts +6 -0
- package/dist/index.js +46 -16
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -590,6 +590,10 @@ type AgentContext = {
|
|
|
590
590
|
phases?: PhaseRegistry;
|
|
591
591
|
};
|
|
592
592
|
|
|
593
|
+
/**
|
|
594
|
+
* `root` anchors relative paths and the Bash working directory. It is not a
|
|
595
|
+
* filesystem sandbox: core Tools use the permissions of the host process.
|
|
596
|
+
*/
|
|
593
597
|
type CoreToolContext = {
|
|
594
598
|
root?: string;
|
|
595
599
|
maxReadBytes?: number;
|
|
@@ -607,6 +611,8 @@ type AgentDefinition = Readonly<{
|
|
|
607
611
|
prompt: string;
|
|
608
612
|
tools?: readonly string[];
|
|
609
613
|
skills?: readonly string[];
|
|
614
|
+
/** Host-supplied Skills private to this Agent Definition/Bundle. */
|
|
615
|
+
bundledSkills?: readonly Skill[];
|
|
610
616
|
phases?: PhaseRegistrySelection;
|
|
611
617
|
contexts?: readonly string[];
|
|
612
618
|
model?: ModelRef;
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// src/harness/tools/index.ts
|
|
2
2
|
import { mkdir, readFile as readFile2, stat, writeFile } from "fs/promises";
|
|
3
|
-
import { basename as basename2, dirname as dirname2,
|
|
3
|
+
import { basename as basename2, dirname as dirname2, relative as relative2, resolve as resolve2 } from "path";
|
|
4
4
|
import Type2 from "typebox";
|
|
5
5
|
import Schema from "typebox/schema";
|
|
6
6
|
|
|
@@ -308,9 +308,6 @@ function resolveCoreToolPath(context, path = ".") {
|
|
|
308
308
|
const inputPath = normalizeCoreToolInputPath(path);
|
|
309
309
|
const absolutePath = resolve2(root, inputPath);
|
|
310
310
|
const relativePath = relative2(root, absolutePath);
|
|
311
|
-
if (relativePath === ".." || relativePath.startsWith(`..${sep2}`) || isAbsolute2(relativePath)) {
|
|
312
|
-
throw new Error(`Path escapes workspace root: ${path}`);
|
|
313
|
-
}
|
|
314
311
|
return {
|
|
315
312
|
root,
|
|
316
313
|
inputPath,
|
|
@@ -465,7 +462,7 @@ async function captureStream(stream, maxBytes) {
|
|
|
465
462
|
function createReadTool(context) {
|
|
466
463
|
return {
|
|
467
464
|
name: "read",
|
|
468
|
-
description: "Read a file
|
|
465
|
+
description: "Read a file using the host process filesystem permissions.",
|
|
469
466
|
parameters: ReadArgsSchema,
|
|
470
467
|
promptSnippet: "Read file contents.",
|
|
471
468
|
promptGuidelines: ["Read files before editing them."],
|
|
@@ -536,7 +533,7 @@ function createReadTool(context) {
|
|
|
536
533
|
function createWriteTool(context) {
|
|
537
534
|
return {
|
|
538
535
|
name: "write",
|
|
539
|
-
description: "Create or overwrite a file
|
|
536
|
+
description: "Create or overwrite a file using the host process filesystem permissions.",
|
|
540
537
|
parameters: WriteArgsSchema,
|
|
541
538
|
promptSnippet: "Create or overwrite files.",
|
|
542
539
|
promptGuidelines: ["Use edit for partial changes."],
|
|
@@ -588,7 +585,7 @@ function applyEditReplacements(current, edits) {
|
|
|
588
585
|
function createEditTool(context) {
|
|
589
586
|
return {
|
|
590
587
|
name: "edit",
|
|
591
|
-
description: "Apply exact text replacements
|
|
588
|
+
description: "Apply exact text replacements using the host process filesystem permissions.",
|
|
592
589
|
parameters: EditArgsSchema,
|
|
593
590
|
promptSnippet: "Apply exact text replacements.",
|
|
594
591
|
promptGuidelines: ["Read the file first; each oldText must match exactly once."],
|
|
@@ -624,7 +621,7 @@ function createEditTool(context) {
|
|
|
624
621
|
function createBashTool(context) {
|
|
625
622
|
return {
|
|
626
623
|
name: "bash",
|
|
627
|
-
description: "Run a bash command
|
|
624
|
+
description: "Run a bash command with the host process filesystem permissions; root is the working directory.",
|
|
628
625
|
parameters: BashArgsSchema,
|
|
629
626
|
promptSnippet: "Run shell commands.",
|
|
630
627
|
promptGuidelines: ["Use read/write/edit for file operations."],
|
|
@@ -1049,6 +1046,7 @@ function assertAgentDefinition(value) {
|
|
|
1049
1046
|
requiredString(value.prompt, "definition.prompt");
|
|
1050
1047
|
optionalStringList(value.tools, "definition.tools");
|
|
1051
1048
|
optionalStringList(value.skills, "definition.skills");
|
|
1049
|
+
optionalBundledSkills(value.bundledSkills, "definition.bundledSkills");
|
|
1052
1050
|
optionalPhaseRegistrySelection(value.phases, "definition.phases");
|
|
1053
1051
|
optionalStringList(value.contexts, "definition.contexts");
|
|
1054
1052
|
if ("extensions" in value) throw new TypeError("definition.extensions is not supported; Extensions are Runtime-global");
|
|
@@ -1120,6 +1118,19 @@ function optionalStringList(value, field) {
|
|
|
1120
1118
|
}
|
|
1121
1119
|
return names;
|
|
1122
1120
|
}
|
|
1121
|
+
function optionalBundledSkills(value, field) {
|
|
1122
|
+
if (value === void 0) return;
|
|
1123
|
+
if (!Array.isArray(value)) throw new TypeError(`${field} must be an array of Skills`);
|
|
1124
|
+
const names = /* @__PURE__ */ new Set();
|
|
1125
|
+
for (const [index, item] of value.entries()) {
|
|
1126
|
+
if (!isRecord(item) || typeof item.name !== "string" || item.name.trim() === "" || typeof item.description !== "string" || typeof item.filePath !== "string" || typeof item.baseDir !== "string" || typeof item.content !== "string" || typeof item.disableModelInvocation !== "boolean") {
|
|
1127
|
+
throw new TypeError(`${field}[${index}] is invalid`);
|
|
1128
|
+
}
|
|
1129
|
+
if (names.has(item.name)) throw new TypeError(`Duplicate bundled Skill "${item.name}".`);
|
|
1130
|
+
names.add(item.name);
|
|
1131
|
+
}
|
|
1132
|
+
return value;
|
|
1133
|
+
}
|
|
1123
1134
|
function optionalPhaseRegistrySelection(value, field) {
|
|
1124
1135
|
if (value === void 0) return void 0;
|
|
1125
1136
|
if (!isRecord(value)) throw new TypeError(`${field} must be an object`);
|
|
@@ -1514,6 +1525,13 @@ function selectNamedResources(candidates, names, kind) {
|
|
|
1514
1525
|
}
|
|
1515
1526
|
return selected;
|
|
1516
1527
|
}
|
|
1528
|
+
function mergeSkills(...layers) {
|
|
1529
|
+
const byName = /* @__PURE__ */ new Map();
|
|
1530
|
+
for (const layer of layers) {
|
|
1531
|
+
for (const skill of layer ?? []) byName.set(skill.name, skill);
|
|
1532
|
+
}
|
|
1533
|
+
return [...byName.values()];
|
|
1534
|
+
}
|
|
1517
1535
|
|
|
1518
1536
|
// src/harness/context/system-prompt.ts
|
|
1519
1537
|
function buildSystemPrompt(options) {
|
|
@@ -1540,7 +1558,7 @@ function buildSystemPrompt(options) {
|
|
|
1540
1558
|
}
|
|
1541
1559
|
const guidelines = guidelinesList.map((g) => `- ${g}`).join("\n");
|
|
1542
1560
|
const skillsSection = skillsBlock ? `The following skills provide specialized instructions for specific tasks.
|
|
1543
|
-
|
|
1561
|
+
Use the read tool to load a skill's file when the task matches its description.
|
|
1544
1562
|
When a skill file references a relative path, resolve it against the skill directory (parent of SKILL.md) and use that absolute path in tool commands.
|
|
1545
1563
|
|
|
1546
1564
|
${skillsBlock}
|
|
@@ -2043,7 +2061,7 @@ async function runPhaseLoop(config, state, registry) {
|
|
|
2043
2061
|
const toolExecutionManager = createToolExecutionManager();
|
|
2044
2062
|
const execution = createPhaseExecution(config, state, phase, messageManager, toolExecutionManager, registry);
|
|
2045
2063
|
const phaseTools = selectPhaseTools(allTools, phase.tools);
|
|
2046
|
-
const phaseSkills =
|
|
2064
|
+
const phaseSkills = mergeSkills(config.context.skills, phase.skills);
|
|
2047
2065
|
let phaseContext = {
|
|
2048
2066
|
systemPrompt: config.context.systemPrompt,
|
|
2049
2067
|
messages: messageManager.visible(),
|
|
@@ -2534,7 +2552,7 @@ async function executeParallelPhase(config, state, registry, phase, payload, con
|
|
|
2534
2552
|
const messages = [...context];
|
|
2535
2553
|
const allTools = buildToolsWithRouting(config, availablePhases);
|
|
2536
2554
|
const phaseTools = selectPhaseTools(allTools, phase.tools);
|
|
2537
|
-
const phaseSkills =
|
|
2555
|
+
const phaseSkills = mergeSkills(config.context.skills, phase.skills);
|
|
2538
2556
|
const systemPrompt = config.context.systemPrompt;
|
|
2539
2557
|
const phaseContext = {
|
|
2540
2558
|
systemPrompt,
|
|
@@ -3016,6 +3034,9 @@ function snapshotConfig(config) {
|
|
|
3016
3034
|
...config.definition,
|
|
3017
3035
|
...config.definition.tools ? { tools: Object.freeze([...config.definition.tools]) } : {},
|
|
3018
3036
|
...config.definition.skills ? { skills: Object.freeze([...config.definition.skills]) } : {},
|
|
3037
|
+
...config.definition.bundledSkills ? {
|
|
3038
|
+
bundledSkills: Object.freeze(config.definition.bundledSkills.map((skill) => Object.freeze({ ...skill })))
|
|
3039
|
+
} : {},
|
|
3019
3040
|
...config.definition.phases ? {
|
|
3020
3041
|
phases: Object.freeze({
|
|
3021
3042
|
entryPhaseId: config.definition.phases.entryPhaseId,
|
|
@@ -3494,10 +3515,9 @@ function resolveDefinitionContext(config, assembled = {}) {
|
|
|
3494
3515
|
config.definition.tools,
|
|
3495
3516
|
"Tool"
|
|
3496
3517
|
);
|
|
3497
|
-
const skills =
|
|
3498
|
-
config.resources.skills,
|
|
3499
|
-
config.definition.
|
|
3500
|
-
"Skill"
|
|
3518
|
+
const skills = mergeSkills(
|
|
3519
|
+
selectNamedResources(config.resources.skills, config.definition.skills, "Skill"),
|
|
3520
|
+
config.definition.bundledSkills
|
|
3501
3521
|
);
|
|
3502
3522
|
const contexts = selectNamedResources(
|
|
3503
3523
|
config.resources.contexts ?? [],
|
|
@@ -4691,6 +4711,13 @@ var ResourceRegistry = class {
|
|
|
4691
4711
|
}
|
|
4692
4712
|
};
|
|
4693
4713
|
function snapshotResourceValue(kind, value) {
|
|
4714
|
+
if (kind === "agent") {
|
|
4715
|
+
const agent = value;
|
|
4716
|
+
return Object.freeze({
|
|
4717
|
+
...agent,
|
|
4718
|
+
...agent.bundledSkills ? { bundledSkills: Object.freeze(agent.bundledSkills.map((skill) => Object.freeze({ ...skill }))) } : {}
|
|
4719
|
+
});
|
|
4720
|
+
}
|
|
4694
4721
|
if (kind !== "phase") return value;
|
|
4695
4722
|
const phase = value;
|
|
4696
4723
|
const snapshot = {
|
|
@@ -4964,7 +4991,10 @@ function resolveConfigurationSnapshot(registry, input) {
|
|
|
4964
4991
|
const layer = input.definition.layer;
|
|
4965
4992
|
const definition = applyDefinitionLayer(base, layer);
|
|
4966
4993
|
const tools = selectNamedResources(resolved.tools, definition.tools, "Tool");
|
|
4967
|
-
const skills =
|
|
4994
|
+
const skills = mergeSkills(
|
|
4995
|
+
selectNamedResources(resolved.skills, definition.skills, "Skill"),
|
|
4996
|
+
definition.bundledSkills
|
|
4997
|
+
);
|
|
4968
4998
|
const phases = resolvePhases(resolved.phases, definition.phases);
|
|
4969
4999
|
const contexts = selectNamedResources(input.contexts ?? [], base.contexts, "Context");
|
|
4970
5000
|
return {
|