pi-herdsman 0.15.0 → 0.16.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/SKILL.md +7 -7
- package/dist/index.js +209 -138
- package/dist/index.js.map +3 -3
- package/docs/agent-api.md +1 -1
- package/docs/concepts/agents.md +5 -5
- package/docs/concepts/lifecycle.md +1 -2
- package/docs/development/smoke-testing.md +0 -10
- package/docs/guides/handoffs.md +3 -3
- package/docs/reference/agent-definition-schema.md +21 -22
- package/docs/reference/agent.md +46 -42
- package/docs/reference/supervision.md +7 -3
- package/package.json +1 -1
package/SKILL.md
CHANGED
|
@@ -31,8 +31,8 @@ Use these high-salience rules for the model-facing agent boundary:
|
|
|
31
31
|
- Each unresolved unit of work has one executor. Delegating a scope transfers
|
|
32
32
|
its execution ownership to that agent until the assignment resolves; do not
|
|
33
33
|
execute or assign overlapping work while it is delegated.
|
|
34
|
-
- For agent handoffs, `task`/`files` carry assignment evidence
|
|
35
|
-
|
|
34
|
+
- For agent handoffs, `task`/`files` carry assignment evidence; `continue`
|
|
35
|
+
resumes an exact managed-agent Pi session. Do not assume the caller's
|
|
36
36
|
conversation or attachments are inherited.
|
|
37
37
|
- When agent work is unresolved, handle required agent control, then continue
|
|
38
38
|
only necessary work you still own or end the turn without concluding; agent
|
|
@@ -53,8 +53,9 @@ Use list when fresh agent state or ownership is materially needed for a concrete
|
|
|
53
53
|
control or recovery decision, or to refresh the definition roster after
|
|
54
54
|
configuration changes. Do not use list merely to check progress.
|
|
55
55
|
|
|
56
|
-
Use delegate to start one bounded assignment from an agent definition.
|
|
57
|
-
Use continue to start one bounded assignment from an exact historical
|
|
56
|
+
Use delegate to start one bounded fresh assignment from an agent definition.
|
|
57
|
+
Use continue to start one bounded assignment from an exact historical
|
|
58
|
+
managed-agent Pi session.
|
|
58
59
|
|
|
59
60
|
Each managed agent exists for one assignment only. After its terminal result is
|
|
60
61
|
delivered, Pi Herdsman cleans up that agent automatically. To continue completed
|
|
@@ -128,9 +129,8 @@ are not copied or snapshotted. files transfers inline content or canonical
|
|
|
128
129
|
references, not tools or runtime capabilities.
|
|
129
130
|
|
|
130
131
|
For agent handoffs, task text and `files` carry assignment-specific evidence.
|
|
131
|
-
`
|
|
132
|
-
|
|
133
|
-
are inherited by another agent session.
|
|
132
|
+
`continue` resumes an exact managed-agent Pi session. Fresh delegation does not
|
|
133
|
+
inherit the caller's conversation or caller-side attachments.
|
|
134
134
|
|
|
135
135
|
Pass relevant evidence explicitly through `files`; omit unrelated evidence.
|
|
136
136
|
|
package/dist/index.js
CHANGED
|
@@ -5515,11 +5515,8 @@ function renderExpandedCoordinationCall(tool, args, theme, header) {
|
|
|
5515
5515
|
if (action2 === "delegate") {
|
|
5516
5516
|
if (args.definition) fields.push(["definition", args.definition]);
|
|
5517
5517
|
if (args.label) fields.push(["label", args.label]);
|
|
5518
|
-
if (args.timeoutMs) fields.push(["timeout", args.timeoutMs]);
|
|
5519
|
-
if (args.fork) fields.push(["fork", args.fork]);
|
|
5520
5518
|
} else if (action2 === "continue") {
|
|
5521
5519
|
if (args.session) fields.push(["session", args.session]);
|
|
5522
|
-
if (args.timeoutMs) fields.push(["timeout", args.timeoutMs]);
|
|
5523
5520
|
} else if (args.agent) fields.push(["agent", args.agent]);
|
|
5524
5521
|
} else if (tool === "staff" || tool === "peer") {
|
|
5525
5522
|
if (args.lead) fields.push(["lead", args.lead]);
|
|
@@ -6395,7 +6392,7 @@ function formatMessageLimit(bytes) {
|
|
|
6395
6392
|
}
|
|
6396
6393
|
var AGENT_DELEGATION_GUIDANCE = "Use agent for genuinely independent or context-heavy work; keep small, tightly coupled work local.";
|
|
6397
6394
|
var AGENT_EXECUTION_OWNERSHIP_GUIDANCE = "Each unresolved unit of work has one executor. Delegating a scope transfers its execution ownership to that agent until the assignment resolves. After delegation succeeds, stop executing, inspecting, or analyzing that delegated scope locally; do not assign overlapping work. Continue only concrete, necessary work clearly outside the delegated scope that you still own.";
|
|
6398
|
-
var AGENT_HANDOFF_GUIDANCE = "For agent handoffs, `task`/`files` carry assignment evidence
|
|
6395
|
+
var AGENT_HANDOFF_GUIDANCE = "For agent handoffs, `task`/`files` carry assignment evidence; `continue` resumes an exact managed-agent Pi session. Do not assume the caller's conversation or attachments are inherited.";
|
|
6399
6396
|
var AGENT_UNRESOLVED_GUIDANCE = "When agent work is unresolved, handle required agent control, then continue only necessary work you still own or end the turn without concluding; agent results or attention will resume the session automatically. Do not check progress with list, inspect, transcript, status requests, steering, sleep, or other waiting mechanisms. Stale health attention is diagnosis, not progress polling: use attached evidence first and, when it is absent or insufficient, perform at most one bounded diagnostic read before returning to passive waiting. Repeated reminders alone do not justify another read. Do not invent work merely to remain active.";
|
|
6400
6397
|
var AGENT_OPERATIONAL_DESCRIPTION = `Coordinate managed agents.
|
|
6401
6398
|
|
|
@@ -6404,10 +6401,9 @@ Use list when fresh agent state or ownership is materially needed for a concrete
|
|
|
6404
6401
|
control or recovery decision, or to refresh the definition roster after
|
|
6405
6402
|
configuration changes. Do not use list merely to check progress.
|
|
6406
6403
|
|
|
6407
|
-
Use delegate to start one bounded assignment from an agent definition.
|
|
6408
|
-
|
|
6409
|
-
|
|
6410
|
-
exact historical managed-agent Pi session.
|
|
6404
|
+
Use delegate to start one bounded fresh assignment from an agent definition.
|
|
6405
|
+
Use continue to start one bounded assignment from an exact historical
|
|
6406
|
+
managed-agent Pi session.
|
|
6411
6407
|
|
|
6412
6408
|
Each managed agent exists for one assignment only. After its terminal result is
|
|
6413
6409
|
delivered, Pi Herdsman cleans up that live generation. Agent labels identify the
|
|
@@ -6583,10 +6579,6 @@ async function visibleAgentDefinitionMetadata(ctx, scope) {
|
|
|
6583
6579
|
(definition) => scope.allowedAgentDefinitions.has(definition.name) && definition.enabled !== false
|
|
6584
6580
|
) : definitions;
|
|
6585
6581
|
}
|
|
6586
|
-
function matchesActionFields(value2, required, optional = []) {
|
|
6587
|
-
const allowed = ["action", ...required, ...optional];
|
|
6588
|
-
return required.every((key) => key in value2) && Object.keys(value2).every((key) => allowed.includes(key));
|
|
6589
|
-
}
|
|
6590
6582
|
function invalidRequestInput(operation, message) {
|
|
6591
6583
|
return new OperationError({
|
|
6592
6584
|
category: "invalid_request",
|
|
@@ -6596,6 +6588,31 @@ function invalidRequestInput(operation, message) {
|
|
|
6596
6588
|
retryAttempted: false
|
|
6597
6589
|
});
|
|
6598
6590
|
}
|
|
6591
|
+
function projectedFiles(value2) {
|
|
6592
|
+
const files = value2.files;
|
|
6593
|
+
return files?.length ? { files } : {};
|
|
6594
|
+
}
|
|
6595
|
+
function requiredString(value2, field, action2) {
|
|
6596
|
+
const candidate = value2[field];
|
|
6597
|
+
if (typeof candidate !== "string")
|
|
6598
|
+
throw invalidRequestInput(action2, `${action2} requires ${field}`);
|
|
6599
|
+
return candidate;
|
|
6600
|
+
}
|
|
6601
|
+
function replaceInput(input, canonical) {
|
|
6602
|
+
for (const key of Object.keys(input)) delete input[key];
|
|
6603
|
+
Object.assign(input, canonical);
|
|
6604
|
+
}
|
|
6605
|
+
function projectActionInput(value2, fieldsByAction) {
|
|
6606
|
+
if (!value2 || typeof value2 !== "object" || Array.isArray(value2)) return value2;
|
|
6607
|
+
const input = { ...value2 };
|
|
6608
|
+
const action2 = String(input.action);
|
|
6609
|
+
if (!Object.prototype.hasOwnProperty.call(fieldsByAction, action2))
|
|
6610
|
+
return input;
|
|
6611
|
+
const fields = fieldsByAction[action2];
|
|
6612
|
+
const knownFields = new Set(Object.values(fieldsByAction).flat());
|
|
6613
|
+
for (const key of knownFields) if (!fields.includes(key)) delete input[key];
|
|
6614
|
+
return input;
|
|
6615
|
+
}
|
|
6599
6616
|
var runtimes = /* @__PURE__ */ new Map();
|
|
6600
6617
|
var resultWatchers = /* @__PURE__ */ new Map();
|
|
6601
6618
|
var watchRetryTimers = /* @__PURE__ */ new Map();
|
|
@@ -7190,12 +7207,12 @@ async function resolveManagedSession(ctx, raw) {
|
|
|
7190
7207
|
);
|
|
7191
7208
|
return { path: manager.getSessionFile() ?? path, id };
|
|
7192
7209
|
}
|
|
7193
|
-
async function resolveAssignmentSessionOrFail(
|
|
7210
|
+
async function resolveAssignmentSessionOrFail(resolver) {
|
|
7194
7211
|
try {
|
|
7195
7212
|
return await resolver();
|
|
7196
7213
|
} catch (error2) {
|
|
7197
7214
|
if (!(error2 instanceof AssignmentSessionResolutionError)) throw error2;
|
|
7198
|
-
fail("invalid_request", error2.message,
|
|
7215
|
+
fail("invalid_request", error2.message, "continue");
|
|
7199
7216
|
}
|
|
7200
7217
|
}
|
|
7201
7218
|
async function resolveAssignmentSession(ctx, raw) {
|
|
@@ -7231,13 +7248,13 @@ async function resolveAssignmentSession(ctx, raw) {
|
|
|
7231
7248
|
cwd
|
|
7232
7249
|
};
|
|
7233
7250
|
}
|
|
7234
|
-
async function requireOwnedAssignmentSource(ctx, session
|
|
7251
|
+
async function requireOwnedAssignmentSource(ctx, session) {
|
|
7235
7252
|
const source = SessionManager2.open(session.path);
|
|
7236
7253
|
const entries = source.getEntries();
|
|
7237
7254
|
const deny = () => fail(
|
|
7238
7255
|
"invalid_request",
|
|
7239
7256
|
"Assignment source is outside the caller's proven session ownership tree",
|
|
7240
|
-
|
|
7257
|
+
"continue"
|
|
7241
7258
|
);
|
|
7242
7259
|
let identity;
|
|
7243
7260
|
try {
|
|
@@ -7245,10 +7262,7 @@ async function requireOwnedAssignmentSource(ctx, session, operation) {
|
|
|
7245
7262
|
} catch {
|
|
7246
7263
|
deny();
|
|
7247
7264
|
}
|
|
7248
|
-
if (!identity)
|
|
7249
|
-
if (operation === "delegate") return;
|
|
7250
|
-
deny();
|
|
7251
|
-
}
|
|
7265
|
+
if (!identity) deny();
|
|
7252
7266
|
const callerId = ctx.sessionManager.getSessionId();
|
|
7253
7267
|
const listed = await SessionManager2.listAll();
|
|
7254
7268
|
const sourceMatches = listed.filter((item) => item.id === session.id);
|
|
@@ -8592,7 +8606,7 @@ async function deliverResultUnsafe(pi, runtime, ctx, result, signal) {
|
|
|
8592
8606
|
return false;
|
|
8593
8607
|
}
|
|
8594
8608
|
})();
|
|
8595
|
-
const retirementGuidance = sessionRetired ? "Session retired after context pressure. Do not continue
|
|
8609
|
+
const retirementGuidance = sessionRetired ? "Session retired after context pressure. Do not continue this session. For follow-up, delegate a fresh agent and pass this result/handoff plus the relevant files." : void 0;
|
|
8596
8610
|
const delegationStatus = delegationStatusForResult(
|
|
8597
8611
|
runtime,
|
|
8598
8612
|
result.requestId,
|
|
@@ -10177,7 +10191,6 @@ async function actionUnsafe(pi, ctx, p, signal, scope, pendingStarts) {
|
|
|
10177
10191
|
p.action
|
|
10178
10192
|
);
|
|
10179
10193
|
const resumed = p.action === "continue" ? await resolveAssignmentSessionOrFail(
|
|
10180
|
-
"continue",
|
|
10181
10194
|
() => resolveAssignmentSession(ctx, p.session)
|
|
10182
10195
|
) : void 0;
|
|
10183
10196
|
await herdrVersion(pi, ctx, signal);
|
|
@@ -10195,17 +10208,7 @@ async function actionUnsafe(pi, ctx, p, signal, scope, pendingStarts) {
|
|
|
10195
10208
|
`Agent definition ${agentDefinition} is not allowed for this delegating agent`,
|
|
10196
10209
|
p.action
|
|
10197
10210
|
);
|
|
10198
|
-
if (resumed) await requireOwnedAssignmentSource(ctx, resumed
|
|
10199
|
-
const forkSource = p.action === "delegate" && p.fork ? await resolveAssignmentSessionOrFail("delegate", async () => {
|
|
10200
|
-
const fork = await resolveManagedSession(ctx, p.fork);
|
|
10201
|
-
const manager = SessionManager2.open(fork.path);
|
|
10202
|
-
if (readConfig().contextRetirement && retiredManagedSession(manager))
|
|
10203
|
-
throw new AssignmentSessionResolutionError(
|
|
10204
|
-
`Managed agent session ${manager.getSessionId()} is retired after context pressure. Delegate a fresh agent without fork and pass the previous handoff/result and relevant files.`
|
|
10205
|
-
);
|
|
10206
|
-
await requireOwnedAssignmentSource(ctx, fork, "delegate");
|
|
10207
|
-
return fork.path;
|
|
10208
|
-
}) : void 0;
|
|
10211
|
+
if (resumed) await requireOwnedAssignmentSource(ctx, resumed);
|
|
10209
10212
|
if (definition.projectSource && !sameCwd(agentCwd, ctx.cwd))
|
|
10210
10213
|
fail(
|
|
10211
10214
|
"invalid_request",
|
|
@@ -10221,7 +10224,7 @@ async function actionUnsafe(pi, ctx, p, signal, scope, pendingStarts) {
|
|
|
10221
10224
|
if (resumed && resumed.id === ctx.sessionManager.getSessionId())
|
|
10222
10225
|
fail(
|
|
10223
10226
|
"invalid_request",
|
|
10224
|
-
"Cannot continue the controller's currently active Pi session.
|
|
10227
|
+
"Cannot continue the controller's currently active Pi session.",
|
|
10225
10228
|
p.action
|
|
10226
10229
|
);
|
|
10227
10230
|
const resumedSessionPath = resumed ? (() => {
|
|
@@ -10235,7 +10238,7 @@ async function actionUnsafe(pi, ctx, p, signal, scope, pendingStarts) {
|
|
|
10235
10238
|
);
|
|
10236
10239
|
}
|
|
10237
10240
|
})() : void 0;
|
|
10238
|
-
const sessionArgs = resumed ? ["--session", resumedSessionPath] :
|
|
10241
|
+
const sessionArgs = resumed ? ["--session", resumedSessionPath] : [];
|
|
10239
10242
|
let releaseSessionActivation;
|
|
10240
10243
|
const live = await listedAgents(pi, ctx, void 0, signal);
|
|
10241
10244
|
if (!agentDefinitionEnabled(definition))
|
|
@@ -10491,7 +10494,7 @@ async function actionUnsafe(pi, ctx, p, signal, scope, pendingStarts) {
|
|
|
10491
10494
|
);
|
|
10492
10495
|
const childModel = resolveChildModel({
|
|
10493
10496
|
configured: configuredModel(effectiveDefinition.frontmatter),
|
|
10494
|
-
inherited:
|
|
10497
|
+
inherited: !resumed && ctx.model ? { provider: ctx.model.provider, token: modelToken(ctx.model) } : void 0,
|
|
10495
10498
|
isForeignProvider: (providerId) => registeredProviderIds.has(providerId)
|
|
10496
10499
|
});
|
|
10497
10500
|
const launchArgs = agentLaunchArgs(effectiveDefinition, {
|
|
@@ -10500,7 +10503,7 @@ async function actionUnsafe(pi, ctx, p, signal, scope, pendingStarts) {
|
|
|
10500
10503
|
cwd: agentCwd,
|
|
10501
10504
|
managedAgent: true,
|
|
10502
10505
|
approveProject: agentContext.projectTrusted && sameCwd(agentCwd, ctx.cwd),
|
|
10503
|
-
|
|
10506
|
+
...!resumed ? { inheritedThinking: pi.getThinkingLevel() } : {},
|
|
10504
10507
|
modelDecision: childModel
|
|
10505
10508
|
});
|
|
10506
10509
|
started = await startHerdrAgent(pi, ctx, {
|
|
@@ -10512,7 +10515,6 @@ async function actionUnsafe(pi, ctx, p, signal, scope, pendingStarts) {
|
|
|
10512
10515
|
...placementRevalidator ? { placementRevalidator } : {},
|
|
10513
10516
|
agentArgs: [...launchArgs, ...sessionArgs],
|
|
10514
10517
|
env,
|
|
10515
|
-
timeoutMs: p.timeoutMs,
|
|
10516
10518
|
signal
|
|
10517
10519
|
});
|
|
10518
10520
|
const state = await waitForState(
|
|
@@ -11054,7 +11056,7 @@ function index_default(pi) {
|
|
|
11054
11056
|
),
|
|
11055
11057
|
session: Type.Optional(
|
|
11056
11058
|
Type.String({
|
|
11057
|
-
description: "Required for continue. Exact saved Pi session path or full UUID.",
|
|
11059
|
+
description: "Required for continue. Exact saved managed-agent Pi session path or full UUID.",
|
|
11058
11060
|
pattern: "\\S"
|
|
11059
11061
|
})
|
|
11060
11062
|
),
|
|
@@ -11070,52 +11072,64 @@ function index_default(pi) {
|
|
|
11070
11072
|
pattern: "\\S"
|
|
11071
11073
|
})
|
|
11072
11074
|
),
|
|
11073
|
-
fork: Type.Optional(
|
|
11074
|
-
Type.String({
|
|
11075
|
-
description: "Optional delegate context: exact saved Pi session path or full UUID.",
|
|
11076
|
-
pattern: "\\S"
|
|
11077
|
-
})
|
|
11078
|
-
),
|
|
11079
|
-
timeoutMs: Type.Optional(
|
|
11080
|
-
Type.Integer({
|
|
11081
|
-
minimum: STARTUP_TIMEOUT_MIN,
|
|
11082
|
-
maximum: STARTUP_TIMEOUT_MAX,
|
|
11083
|
-
description: "Optional startup budget for delegate and continue."
|
|
11084
|
-
})
|
|
11085
|
-
),
|
|
11086
11075
|
files: FILES_SCHEMA
|
|
11087
11076
|
},
|
|
11088
11077
|
{ additionalProperties: false }
|
|
11089
11078
|
);
|
|
11090
11079
|
const agentValidator = Compile(agentParameters);
|
|
11091
|
-
const
|
|
11092
|
-
|
|
11080
|
+
const projectAgentInput = (value2) => projectActionInput(value2, {
|
|
11081
|
+
list: [],
|
|
11082
|
+
delegate: ["definition", "label", "task", "files"],
|
|
11083
|
+
continue: ["session", "task", "files"],
|
|
11084
|
+
steer: ["agent", "message", "files"],
|
|
11085
|
+
interrupt: ["agent", "message", "files"],
|
|
11086
|
+
reply: ["agent", "message", "files"],
|
|
11087
|
+
close: ["agent"],
|
|
11088
|
+
inspect: ["agent"],
|
|
11089
|
+
transcript: ["agent"]
|
|
11090
|
+
});
|
|
11091
|
+
const parseAgentParams = (value2) => {
|
|
11092
|
+
value2 = projectAgentInput(value2);
|
|
11093
|
+
if (!agentValidator.Check(value2))
|
|
11094
|
+
throw invalidRequestInput("agent", "Invalid agent input");
|
|
11093
11095
|
const p = value2;
|
|
11096
|
+
const files = projectedFiles(p);
|
|
11094
11097
|
switch (p.action) {
|
|
11095
11098
|
case "list":
|
|
11096
|
-
return
|
|
11099
|
+
return { action: "list" };
|
|
11097
11100
|
case "delegate":
|
|
11098
|
-
return
|
|
11099
|
-
|
|
11100
|
-
|
|
11101
|
-
|
|
11102
|
-
|
|
11101
|
+
return {
|
|
11102
|
+
action: "delegate",
|
|
11103
|
+
definition: requiredString(p, "definition", "delegate"),
|
|
11104
|
+
task: requiredString(p, "task", "delegate"),
|
|
11105
|
+
...typeof p.label === "string" ? { label: p.label } : {},
|
|
11106
|
+
...files
|
|
11107
|
+
};
|
|
11103
11108
|
case "continue":
|
|
11104
|
-
return
|
|
11105
|
-
|
|
11106
|
-
|
|
11107
|
-
|
|
11108
|
-
|
|
11109
|
+
return {
|
|
11110
|
+
action: "continue",
|
|
11111
|
+
session: requiredString(p, "session", "continue"),
|
|
11112
|
+
task: requiredString(p, "task", "continue"),
|
|
11113
|
+
...files
|
|
11114
|
+
};
|
|
11109
11115
|
case "steer":
|
|
11110
11116
|
case "interrupt":
|
|
11111
11117
|
case "reply":
|
|
11112
|
-
return
|
|
11118
|
+
return {
|
|
11119
|
+
action: p.action,
|
|
11120
|
+
agent: requiredString(p, "agent", p.action),
|
|
11121
|
+
message: requiredString(p, "message", p.action),
|
|
11122
|
+
...files
|
|
11123
|
+
};
|
|
11113
11124
|
case "close":
|
|
11114
11125
|
case "inspect":
|
|
11115
11126
|
case "transcript":
|
|
11116
|
-
return
|
|
11127
|
+
return {
|
|
11128
|
+
action: p.action,
|
|
11129
|
+
agent: requiredString(p, "agent", p.action)
|
|
11130
|
+
};
|
|
11117
11131
|
default:
|
|
11118
|
-
|
|
11132
|
+
throw invalidRequestInput("agent", "Invalid agent action");
|
|
11119
11133
|
}
|
|
11120
11134
|
};
|
|
11121
11135
|
const staffParameters = Type.Object(
|
|
@@ -11150,21 +11164,44 @@ function index_default(pi) {
|
|
|
11150
11164
|
{ additionalProperties: false }
|
|
11151
11165
|
);
|
|
11152
11166
|
const staffValidator = Compile(staffParameters);
|
|
11153
|
-
const
|
|
11154
|
-
|
|
11167
|
+
const projectStaffInput = (value2) => projectActionInput(value2, {
|
|
11168
|
+
list: [],
|
|
11169
|
+
inspect: ["lead"],
|
|
11170
|
+
transcript: ["lead"],
|
|
11171
|
+
message: ["lead", "message", "files"],
|
|
11172
|
+
reply: ["lead", "askId", "message", "files"]
|
|
11173
|
+
});
|
|
11174
|
+
const parseStaffParams = (value2) => {
|
|
11175
|
+
value2 = projectStaffInput(value2);
|
|
11176
|
+
if (!staffValidator.Check(value2))
|
|
11177
|
+
throw invalidRequestInput("staff", "Invalid staff action");
|
|
11155
11178
|
const p = value2;
|
|
11156
11179
|
switch (p.action) {
|
|
11157
11180
|
case "list":
|
|
11158
|
-
return
|
|
11181
|
+
return { action: "list" };
|
|
11159
11182
|
case "inspect":
|
|
11160
11183
|
case "transcript":
|
|
11161
|
-
return
|
|
11184
|
+
return {
|
|
11185
|
+
action: p.action,
|
|
11186
|
+
lead: requiredString(p, "lead", `staff ${p.action}`)
|
|
11187
|
+
};
|
|
11162
11188
|
case "message":
|
|
11163
|
-
return
|
|
11189
|
+
return {
|
|
11190
|
+
action: "message",
|
|
11191
|
+
lead: requiredString(p, "lead", "staff message"),
|
|
11192
|
+
message: requiredString(p, "message", "staff message"),
|
|
11193
|
+
...projectedFiles(p)
|
|
11194
|
+
};
|
|
11164
11195
|
case "reply":
|
|
11165
|
-
return
|
|
11196
|
+
return {
|
|
11197
|
+
action: "reply",
|
|
11198
|
+
lead: requiredString(p, "lead", "staff reply"),
|
|
11199
|
+
askId: requiredString(p, "askId", "staff reply"),
|
|
11200
|
+
message: requiredString(p, "message", "staff reply"),
|
|
11201
|
+
...projectedFiles(p)
|
|
11202
|
+
};
|
|
11166
11203
|
default:
|
|
11167
|
-
|
|
11204
|
+
throw invalidRequestInput("staff", "Invalid staff action");
|
|
11168
11205
|
}
|
|
11169
11206
|
};
|
|
11170
11207
|
const peerParameters = Type.Object(
|
|
@@ -11184,16 +11221,71 @@ function index_default(pi) {
|
|
|
11184
11221
|
{ additionalProperties: false }
|
|
11185
11222
|
);
|
|
11186
11223
|
const peerValidator = Compile(peerParameters);
|
|
11187
|
-
const
|
|
11188
|
-
|
|
11224
|
+
const projectPeerInput = (value2) => projectActionInput(value2, {
|
|
11225
|
+
list: [],
|
|
11226
|
+
message: ["lead", "message", "files"]
|
|
11227
|
+
});
|
|
11228
|
+
const parsePeerParams = (value2) => {
|
|
11229
|
+
value2 = projectPeerInput(value2);
|
|
11230
|
+
if (!peerValidator.Check(value2))
|
|
11231
|
+
throw invalidRequestInput("peer", "Invalid peer action");
|
|
11189
11232
|
const p = value2;
|
|
11190
11233
|
switch (p.action) {
|
|
11191
11234
|
case "list":
|
|
11192
|
-
return
|
|
11235
|
+
return { action: "list" };
|
|
11193
11236
|
case "message":
|
|
11194
|
-
return
|
|
11237
|
+
return {
|
|
11238
|
+
action: "message",
|
|
11239
|
+
lead: requiredString(p, "lead", "peer message"),
|
|
11240
|
+
message: requiredString(p, "message", "peer message"),
|
|
11241
|
+
...projectedFiles(p)
|
|
11242
|
+
};
|
|
11195
11243
|
default:
|
|
11196
|
-
|
|
11244
|
+
throw invalidRequestInput("peer", "Invalid peer action");
|
|
11245
|
+
}
|
|
11246
|
+
};
|
|
11247
|
+
const chiefParameters = Type.Object(
|
|
11248
|
+
{
|
|
11249
|
+
action: StringEnum(["message", "ask"]),
|
|
11250
|
+
message: Type.Optional(
|
|
11251
|
+
Type.String({ minLength: 1, description: "Required for message." })
|
|
11252
|
+
),
|
|
11253
|
+
question: Type.Optional(
|
|
11254
|
+
Type.String({
|
|
11255
|
+
minLength: 1,
|
|
11256
|
+
maxLength: 1024,
|
|
11257
|
+
description: "Required for ask."
|
|
11258
|
+
})
|
|
11259
|
+
),
|
|
11260
|
+
files: FILES_SCHEMA
|
|
11261
|
+
},
|
|
11262
|
+
{ additionalProperties: false }
|
|
11263
|
+
);
|
|
11264
|
+
const chiefValidator = Compile(chiefParameters);
|
|
11265
|
+
const projectChiefInput = (value2) => projectActionInput(value2, {
|
|
11266
|
+
message: ["message", "files"],
|
|
11267
|
+
ask: ["question", "files"]
|
|
11268
|
+
});
|
|
11269
|
+
const parseChiefParams = (value2) => {
|
|
11270
|
+
value2 = projectChiefInput(value2);
|
|
11271
|
+
if (!chiefValidator.Check(value2))
|
|
11272
|
+
throw invalidRequestInput("chief", "Invalid chief action");
|
|
11273
|
+
const p = value2;
|
|
11274
|
+
switch (p.action) {
|
|
11275
|
+
case "message":
|
|
11276
|
+
return {
|
|
11277
|
+
action: "message",
|
|
11278
|
+
message: requiredString(p, "message", "chief message"),
|
|
11279
|
+
...projectedFiles(p)
|
|
11280
|
+
};
|
|
11281
|
+
case "ask":
|
|
11282
|
+
return {
|
|
11283
|
+
action: "ask",
|
|
11284
|
+
question: requiredString(p, "question", "chief ask"),
|
|
11285
|
+
...projectedFiles(p)
|
|
11286
|
+
};
|
|
11287
|
+
default:
|
|
11288
|
+
throw invalidRequestInput("chief", "Invalid chief action");
|
|
11197
11289
|
}
|
|
11198
11290
|
};
|
|
11199
11291
|
let startupDefinitionRoster;
|
|
@@ -12166,26 +12258,23 @@ Supervised leads will not be changed.`
|
|
|
12166
12258
|
}
|
|
12167
12259
|
}
|
|
12168
12260
|
if (!controllerScope) return;
|
|
12169
|
-
|
|
12170
|
-
|
|
12171
|
-
|
|
12172
|
-
|
|
12173
|
-
|
|
12174
|
-
|
|
12175
|
-
|
|
12176
|
-
|
|
12177
|
-
|
|
12178
|
-
|
|
12179
|
-
|
|
12180
|
-
|
|
12181
|
-
|
|
12182
|
-
|
|
12183
|
-
|
|
12184
|
-
|
|
12185
|
-
|
|
12186
|
-
block: true,
|
|
12187
|
-
reason: error2.detail.message
|
|
12188
|
-
};
|
|
12261
|
+
try {
|
|
12262
|
+
if (event.toolName === "agent")
|
|
12263
|
+
replaceInput(event.input, parseAgentParams(event.input));
|
|
12264
|
+
else if (event.toolName === "staff")
|
|
12265
|
+
replaceInput(event.input, parseStaffParams(event.input));
|
|
12266
|
+
else if (event.toolName === "peer")
|
|
12267
|
+
replaceInput(event.input, parsePeerParams(event.input));
|
|
12268
|
+
else if (event.toolName === "chief")
|
|
12269
|
+
replaceInput(event.input, parseChiefParams(event.input));
|
|
12270
|
+
} catch (error2) {
|
|
12271
|
+
if (error2 instanceof OperationError && error2.detail.category === "invalid_request")
|
|
12272
|
+
return {
|
|
12273
|
+
block: true,
|
|
12274
|
+
reason: error2.detail.message,
|
|
12275
|
+
terminate: true
|
|
12276
|
+
};
|
|
12277
|
+
throw error2;
|
|
12189
12278
|
}
|
|
12190
12279
|
if (controllerScope.kind !== "lead") return;
|
|
12191
12280
|
if (event.toolName === CHIEF_TOOLS[0] || !isCurrentChief(ctx)) return;
|
|
@@ -13549,33 +13638,12 @@ Active work or pending results may be discarded.`
|
|
|
13549
13638
|
promptSnippet: "Report progress to or ask the active chief supervising this lead",
|
|
13550
13639
|
description: "For ordinary leads only. A lead owns its complete agent tree; the chief supervises leads and never changes ownership. Message and ask require a currently valid chief and reject before mutation when none exists. Use message for meaningful progress, results, warnings, and completion, including exact artifact paths; use ask when a chief decision is genuinely required; call ask alone as the final tool call of the turn, then stop and wait for the reply. Questions are limited to 1,024 characters and 1,024 UTF-8 bytes; channel message records are bounded to 8 KiB, so multibyte content can hit the byte limit first. Chief messages arrive as follow-ups, so integrate them through normal delegation. Descendants use ask_owner, never chief.",
|
|
13551
13640
|
executionMode: "sequential",
|
|
13552
|
-
parameters:
|
|
13553
|
-
|
|
13554
|
-
|
|
13555
|
-
message: Type.Optional(
|
|
13556
|
-
Type.String({
|
|
13557
|
-
minLength: 1,
|
|
13558
|
-
description: "Required for message."
|
|
13559
|
-
})
|
|
13560
|
-
),
|
|
13561
|
-
question: Type.Optional(
|
|
13562
|
-
Type.String({
|
|
13563
|
-
minLength: 1,
|
|
13564
|
-
maxLength: 1024,
|
|
13565
|
-
description: "Required for ask."
|
|
13566
|
-
})
|
|
13567
|
-
),
|
|
13568
|
-
files: FILES_SCHEMA
|
|
13569
|
-
},
|
|
13570
|
-
{ additionalProperties: false }
|
|
13571
|
-
),
|
|
13572
|
-
execute: async (_id, params, _signal, _update, ctx) => {
|
|
13641
|
+
parameters: chiefParameters,
|
|
13642
|
+
prepareArguments: projectChiefInput,
|
|
13643
|
+
execute: async (_id, raw, _signal, _update, ctx) => {
|
|
13573
13644
|
if (controllerScope.kind !== "lead" || chiefMode !== "inactive")
|
|
13574
13645
|
throw new Error("Chief is available only to ordinary leads");
|
|
13575
|
-
|
|
13576
|
-
throw new Error("Invalid chief action");
|
|
13577
|
-
const validFields = params.action === "message" ? matchesActionFields(params, ["message"], ["files"]) : params.action === "ask" ? matchesActionFields(params, ["question"], ["files"]) : false;
|
|
13578
|
-
if (!validFields) throw new Error("Invalid chief action");
|
|
13646
|
+
const params = parseChiefParams(raw);
|
|
13579
13647
|
if (params.action === "message") {
|
|
13580
13648
|
if (typeof params.message !== "string" || !params.message.trim())
|
|
13581
13649
|
throw new Error("Message must contain non-whitespace text");
|
|
@@ -13771,11 +13839,11 @@ Active work or pending results may be discarded.`
|
|
|
13771
13839
|
description: "Other ordinary Lead sessions (peers), not managed agents. Use list for peers, other Leads, or other Lead sessions. list identifies this Lead as self and returns other live Leads as peers; message sends to one peer's exact lead ID and may include ordinary files or exact reusable direct-agent result refs through files.",
|
|
13772
13840
|
executionMode: "sequential",
|
|
13773
13841
|
parameters: peerParameters,
|
|
13774
|
-
|
|
13842
|
+
prepareArguments: projectPeerInput,
|
|
13843
|
+
execute: async (_id, raw, _signal, _update, ctx) => {
|
|
13775
13844
|
if (controllerScope.kind !== "lead" || chiefMode !== "inactive")
|
|
13776
13845
|
throw new Error("Peer is available only to ordinary leads");
|
|
13777
|
-
|
|
13778
|
-
throw invalidRequestInput("peer", "Invalid peer action");
|
|
13846
|
+
const params = parsePeerParams(raw);
|
|
13779
13847
|
if (params.action === "list") {
|
|
13780
13848
|
const self = ctx.sessionManager.getSessionId();
|
|
13781
13849
|
const peers = listPeerLeadRecords(peerRuntime()).filter((record2) => record2.piSessionId !== self).map((record2) => ({
|
|
@@ -13856,13 +13924,13 @@ Active work or pending results may be discarded.`
|
|
|
13856
13924
|
description: "The lead is the exact full Pi session ID shown as lead in a fresh automatic supervision snapshot or returned by staff list; never use display_name. Chief-only supervision coordination. The chief supervises independent leads, does not own their agent trees, and receives no owner controls. A fresh supervision snapshot is automatically supplied at the start of each chief agent run; treat it as the default current coordination state. For ordinary state and coordination, use a fresh snapshot directly; do not call staff list, inspect, transcript, or another read command merely to poll progress. The message and reply actions revalidate exact identity and state themselves. Use list when the automatic snapshot is stale or unavailable, an immediately refreshed exact roster is materially necessary, or you are diagnosing identity or supervision projection problems. Inspect provides bounded live terminal/process evidence; use it only when that evidence matters. Transcript provides bounded persisted Pi conversation/tool evidence; use it only when that evidence materially matters. Use the lead field's exact full Pi session ID and only fresh available_actions, never infer from display state or metadata. Every exact-identity-verified lead accepts message; reply only with the exact pending ask ID and current chief lease. Message is ordinary durable follow-up communication. Messages are bounded and direction-aware, and temporary verification or delivery failures retain queued records. Metadata is presentation-only and never authority. Messages use follow-up delivery. Human conversation remains the dispatch surface.",
|
|
13857
13925
|
executionMode: "sequential",
|
|
13858
13926
|
parameters: staffParameters,
|
|
13859
|
-
|
|
13927
|
+
prepareArguments: projectStaffInput,
|
|
13928
|
+
execute: async (_id, raw, signal, _update, ctx) => {
|
|
13860
13929
|
if (chiefMode !== "active" || !chiefLease)
|
|
13861
13930
|
throw new Error("Staff is available only to the active chief");
|
|
13862
13931
|
if (!await currentChiefAuthority(ctx))
|
|
13863
13932
|
throw new Error("Chief lease is no longer active");
|
|
13864
|
-
|
|
13865
|
-
throw invalidRequestInput("staff", "Invalid staff action");
|
|
13933
|
+
const params = parseStaffParams(raw);
|
|
13866
13934
|
const refresh = async () => loadSupervisionSnapshot(ctx);
|
|
13867
13935
|
const result = (value2) => {
|
|
13868
13936
|
const bounded = truncateModelText(JSON.stringify(value2, null, 2), {
|
|
@@ -15120,13 +15188,13 @@ Active work or pending results may be discarded.`
|
|
|
15120
15188
|
description: controllerDescription(controllerScope),
|
|
15121
15189
|
executionMode: "sequential",
|
|
15122
15190
|
parameters: agentParameters,
|
|
15123
|
-
|
|
15191
|
+
prepareArguments: projectAgentInput,
|
|
15192
|
+
execute: async (_id, raw, signal, _update, ctx) => {
|
|
15193
|
+
let p = { action: "list" };
|
|
15194
|
+
let presentationAction = raw && typeof raw === "object" && typeof raw.action === "string" ? raw.action : p.action;
|
|
15124
15195
|
try {
|
|
15125
|
-
|
|
15126
|
-
|
|
15127
|
-
typeof p?.action === "string" ? p.action : "agent",
|
|
15128
|
-
"Invalid agent input"
|
|
15129
|
-
);
|
|
15196
|
+
p = parseAgentParams(raw);
|
|
15197
|
+
presentationAction = p.action;
|
|
15130
15198
|
const value2 = await action(
|
|
15131
15199
|
pi,
|
|
15132
15200
|
ctx,
|
|
@@ -15181,7 +15249,10 @@ Active work or pending results may be discarded.`
|
|
|
15181
15249
|
if (!(e instanceof OperationError)) throw e;
|
|
15182
15250
|
const detail = e.detail;
|
|
15183
15251
|
const bounded = truncateModelText(
|
|
15184
|
-
formatToolModelResult(
|
|
15252
|
+
formatToolModelResult(presentationAction, {
|
|
15253
|
+
ok: false,
|
|
15254
|
+
error: detail
|
|
15255
|
+
}),
|
|
15185
15256
|
{
|
|
15186
15257
|
keep: "head",
|
|
15187
15258
|
sessionId: ctx.sessionManager.getSessionId(),
|