@hcflabs/pi-subagent 28.3.4 → 28.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.js +24 -6
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -269,6 +269,8 @@ Role Markdown files in `~/.pi/agent/config/pi-subagent/` require frontmatter and
|
|
|
269
269
|
| `mcps` | Optional exact global server names from `~/.pi/agent/mcp.json`, using native `mcpServers` format. Omitted or `[]` denies access to `mcp.json` servers. Servers that Role extensions register always connect. |
|
|
270
270
|
| body | Required system instructions |
|
|
271
271
|
|
|
272
|
+
A Role's `modelClass` selects a Task Profile. When the profile has a primary and a fallback that resolve in Main, the worker selects the Task Profile Model `task/<profile>`. A retryable error on the primary then moves the worker to the fallback. The launch record names the primary route. A designated `model` uses no fallback.
|
|
273
|
+
|
|
272
274
|
The package ships `implementer`, `reviewer`, and `scout`; same-name user Roles override built-ins. Roles define capabilities, not access or isolation. Unknown frontmatter keys invalidate that file and report its path and key. Other valid Roles load; duplicate names become unavailable. Delegation to an invalid file's claimed Role fails with that file's error. Inspect `/subagent roles`.
|
|
273
275
|
|
|
274
276
|
The built-in reviewer answers exactly `PASS` when it finds no actionable correctness risk. Otherwise, each finding starts with a priority and a confidence (`high`, `medium`, or `low`), for example `[P1] confidence: high`. Then it gives file and line evidence, the trigger, the impact, and the smallest fix. Each finding blocks approval.
|
package/dist/index.d.ts
CHANGED
|
@@ -73,6 +73,11 @@ export interface PreparedRoleLaunch extends ResolvedRoleLaunch {
|
|
|
73
73
|
export interface CreateRoleLaunchInput {
|
|
74
74
|
role: Role;
|
|
75
75
|
route: ResolvedTaskRoute;
|
|
76
|
+
/**
|
|
77
|
+
* Task Profile of the route. When set, the child selects the Task Profile Model `task/<profile>`,
|
|
78
|
+
* so a retryable error on the primary route moves the child to the fallback route.
|
|
79
|
+
*/
|
|
80
|
+
failoverProfile?: ProfileName;
|
|
76
81
|
extensions?: readonly string[];
|
|
77
82
|
tools?: readonly string[];
|
|
78
83
|
env?: Readonly<Record<string, string>>;
|
package/dist/index.js
CHANGED
|
@@ -6,7 +6,7 @@ import { createConfigStore, extensionConfigDir, field, formatConfigIssues, parse
|
|
|
6
6
|
import { hasDisplayControlCharacters } from "./display-text.js";
|
|
7
7
|
import { DEFAULT_MAX_TURNS } from "./ephemeral.js";
|
|
8
8
|
import { loadRoleMcpConfig, parseRoleMcpAllowlist } from "./mcp-role.js";
|
|
9
|
-
import { loadTaskModelsConfig, modelReference, orderedProfileRoutes, PROFILE_NAMES, resolveConfiguredTaskRoute, resolveTaskModelRoute, } from "@hcflabs/pi-task-models";
|
|
9
|
+
import { loadTaskModelsConfig, modelReference, orderedProfileRoutes, PROFILE_NAMES, resolveConfiguredTaskRoute, resolveTaskModelRoute, TASK_PROFILE_MODELS_EXTENSION, taskProfileModelReference, } from "@hcflabs/pi-task-models";
|
|
10
10
|
export { DISPLAY_TEXT_CONTRACT, hasDisplayControlCharacters } from "./display-text.js";
|
|
11
11
|
export { loadRoleMcpConfig, parseRoleMcpAllowlist } from "./mcp-role.js";
|
|
12
12
|
export { addUsage, capEphemeralSubagentOutput, createEphemeralSubagentExecutor, DEFAULT_MAX_TURNS, EphemeralSubagentError, EXECUTION_BUDGET_ENV, formatDuration, } from "./ephemeral.js";
|
|
@@ -450,6 +450,14 @@ function resolveConfiguredRoute(ctx, profileName, profile) {
|
|
|
450
450
|
}
|
|
451
451
|
throw new Error(`No usable ${profileName} task model route. Run /task-models.`);
|
|
452
452
|
}
|
|
453
|
+
/** Return the profile when it has a primary and a fallback route that resolve in this session, so failover can help. */
|
|
454
|
+
function failoverProfile(ctx, profileName, agentDir = getAgentDir()) {
|
|
455
|
+
const profile = loadTaskModelsConfig(agentDir).value.profiles[profileName];
|
|
456
|
+
if (!profile)
|
|
457
|
+
return undefined;
|
|
458
|
+
const usable = orderedProfileRoutes(profile).filter((route) => resolveTaskModelRoute(ctx, route) !== undefined);
|
|
459
|
+
return usable.length > 1 ? profileName : undefined;
|
|
460
|
+
}
|
|
453
461
|
export function resolveRoleSkills(pi, role) {
|
|
454
462
|
const skills = new Map(pi.getCommands()
|
|
455
463
|
.filter((command) => command.source === "skill")
|
|
@@ -512,6 +520,8 @@ function prepareRoleLaunchFromSkills(ctx, input, skills) {
|
|
|
512
520
|
ROLE_MCP_EXTENSION,
|
|
513
521
|
...(role.tools.includes("git_read") ? [GIT_READ_EXTENSION] : []),
|
|
514
522
|
ROLE_TOOLS_EXTENSION,
|
|
523
|
+
// The child runs with --no-extensions, so it loads the Task Profile Models only from this path.
|
|
524
|
+
...(input.failoverProfile ? [TASK_PROFILE_MODELS_EXTENSION] : []),
|
|
515
525
|
];
|
|
516
526
|
const env = Object.fromEntries(Object.entries(input.env ?? {}).map(([key, value]) => {
|
|
517
527
|
if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(key))
|
|
@@ -527,7 +537,7 @@ function prepareRoleLaunchFromSkills(ctx, input, skills) {
|
|
|
527
537
|
for (const skill of skills.paths)
|
|
528
538
|
args.push("--skill", skill);
|
|
529
539
|
args.push(`--${ROLE_TOOL_POLICY_FLAG}`, JSON.stringify(tools));
|
|
530
|
-
args.push("--model", modelReference(input.route.model));
|
|
540
|
+
args.push("--model", input.failoverProfile ? taskProfileModelReference(input.failoverProfile) : modelReference(input.route.model));
|
|
531
541
|
if (input.route.thinkingLevel)
|
|
532
542
|
args.push("--thinking", input.route.thinkingLevel);
|
|
533
543
|
args.push(ctx.isProjectTrusted() ? "--approve" : "--no-approve");
|
|
@@ -546,11 +556,16 @@ function prepareRoleLaunchFromSkills(ctx, input, skills) {
|
|
|
546
556
|
function prepareResolvedRoleLaunch(pi, ctx, input) {
|
|
547
557
|
const { task, modelClass, agentDir, ...launchInput } = input;
|
|
548
558
|
const selectedClass = modelClass ?? input.role.modelClass;
|
|
559
|
+
const route = selectedClass === undefined
|
|
560
|
+
? resolveConfiguredTaskRoute(ctx, task, agentDir)
|
|
561
|
+
: resolveTaskRoute(ctx, selectedClass, agentDir);
|
|
562
|
+
// The route resolved, so the config loads. A task without a class uses its assigned or declared profile.
|
|
563
|
+
const profileName = selectedClass ?? loadTaskModelsConfig(agentDir).value.tasks[task.id] ?? task.defaultProfile;
|
|
564
|
+
const failover = failoverProfile(ctx, profileName, agentDir);
|
|
549
565
|
return prepareRoleLaunchFromSkills(ctx, {
|
|
550
566
|
...launchInput,
|
|
551
|
-
route
|
|
552
|
-
|
|
553
|
-
: resolveTaskRoute(ctx, selectedClass, agentDir),
|
|
567
|
+
route,
|
|
568
|
+
...(failover ? { failoverProfile: failover } : {}),
|
|
554
569
|
}, resolveRoleSkills(pi, input.role));
|
|
555
570
|
}
|
|
556
571
|
export function resolveRoleLaunch(pi, ctx, input) {
|
|
@@ -589,9 +604,12 @@ export async function resolveConfiguredRoleLaunch(pi, ctx, input) {
|
|
|
589
604
|
...namedSkills,
|
|
590
605
|
paths: [...new Set([...namedSkills.paths, ...resources.skills])],
|
|
591
606
|
};
|
|
607
|
+
const route = resolveTaskRoute(ctx, input.modelClass);
|
|
608
|
+
const failover = failoverProfile(ctx, input.modelClass);
|
|
592
609
|
const prepared = prepareRoleLaunchFromSkills(ctx, {
|
|
593
610
|
role: effectiveRole,
|
|
594
|
-
route
|
|
611
|
+
route,
|
|
612
|
+
...(failover ? { failoverProfile: failover } : {}),
|
|
595
613
|
}, skills);
|
|
596
614
|
assertNoMissingRoleSkills(effectiveRole, prepared);
|
|
597
615
|
const args = [
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hcflabs/pi-subagent",
|
|
3
|
-
"version": "28.
|
|
3
|
+
"version": "28.4.0",
|
|
4
4
|
"description": "Delegate bounded direct work or durable checked isolated task graphs to Pi roles.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"pi-package",
|
|
@@ -74,7 +74,7 @@
|
|
|
74
74
|
"@hcflabs/pi-herdr": "^0.7.0",
|
|
75
75
|
"@hcflabs/pi-process": "^0.3.0",
|
|
76
76
|
"@hcflabs/pi-repo": "^0.1.0",
|
|
77
|
-
"@hcflabs/pi-task-models": "^9.
|
|
77
|
+
"@hcflabs/pi-task-models": "^9.3.0",
|
|
78
78
|
"proper-lockfile": "^4.1.2"
|
|
79
79
|
},
|
|
80
80
|
"devDependencies": {
|