pi-herdsman 0.22.2 → 0.23.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/dist/index.js +180 -4
- package/dist/index.js.map +3 -3
- package/dist/integrations/pi-codex-context-sharing.js +42 -0
- package/dist/integrations/pi-codex-context-sharing.js.map +7 -0
- package/docs/guides/customizing-agents.md +32 -0
- package/docs/reference/agent.md +46 -0
- package/package.json +8 -1
package/dist/index.js
CHANGED
|
@@ -15,7 +15,7 @@ import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
|
15
15
|
// package.json
|
|
16
16
|
var package_default = {
|
|
17
17
|
name: "pi-herdsman",
|
|
18
|
-
version: "0.
|
|
18
|
+
version: "0.23.0",
|
|
19
19
|
type: "module",
|
|
20
20
|
description: "Asynchronous Pi subagents and agent fleet orchestration for parallel coding agents with nested delegation, background work, and supervision in herdr.",
|
|
21
21
|
license: "Apache-2.0",
|
|
@@ -90,12 +90,14 @@ var package_default = {
|
|
|
90
90
|
"@earendil-works/pi-ai": "*",
|
|
91
91
|
"@earendil-works/pi-coding-agent": "*",
|
|
92
92
|
"@earendil-works/pi-tui": "*",
|
|
93
|
+
"@howaboua/pi-codex-conversion": "^3.0.45",
|
|
93
94
|
typebox: "*"
|
|
94
95
|
},
|
|
95
96
|
devDependencies: {
|
|
96
97
|
"@earendil-works/pi-ai": "1.1.0",
|
|
97
98
|
"@earendil-works/pi-coding-agent": "1.1.0",
|
|
98
99
|
"@earendil-works/pi-tui": "1.1.0",
|
|
100
|
+
"@howaboua/pi-codex-conversion": "3.0.45",
|
|
99
101
|
esbuild: "^0.28.2",
|
|
100
102
|
typebox: "^1.3.7"
|
|
101
103
|
},
|
|
@@ -112,6 +114,11 @@ var package_default = {
|
|
|
112
114
|
],
|
|
113
115
|
publishConfig: {
|
|
114
116
|
registry: "https://registry.npmjs.org/"
|
|
117
|
+
},
|
|
118
|
+
peerDependenciesMeta: {
|
|
119
|
+
"@howaboua/pi-codex-conversion": {
|
|
120
|
+
optional: true
|
|
121
|
+
}
|
|
115
122
|
}
|
|
116
123
|
};
|
|
117
124
|
|
|
@@ -553,6 +560,8 @@ function releaseProcessLock(claimDir, ownerPath, claim, name) {
|
|
|
553
560
|
}
|
|
554
561
|
|
|
555
562
|
// extension/mailbox.ts
|
|
563
|
+
var MANAGED_AGENT_BOOTSTRAP_LIMIT_BYTES = 64 * 1024;
|
|
564
|
+
var BOOTSTRAP_ID = /^[A-Za-z0-9][A-Za-z0-9._:/-]{0,127}$/;
|
|
556
565
|
var UUID2 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
|
|
557
566
|
var PREFIX = "__PI_HERDSMAN_AGENT_V5__:";
|
|
558
567
|
var MAILBOX_PROTOCOL_LIMIT_BYTES = 1024 * 1024;
|
|
@@ -563,6 +572,7 @@ var MailboxClaimOccupiedError = class extends Error {
|
|
|
563
572
|
code = "MAILBOX_CLAIM_OCCUPIED";
|
|
564
573
|
};
|
|
565
574
|
var LIMITS = {
|
|
575
|
+
bootstrap: MANAGED_AGENT_BOOTSTRAP_LIMIT_BYTES,
|
|
566
576
|
state: 64 * 1024,
|
|
567
577
|
request: MAILBOX_PROTOCOL_LIMIT_BYTES,
|
|
568
578
|
ask: MAILBOX_PROTOCOL_LIMIT_BYTES,
|
|
@@ -699,6 +709,41 @@ function validate(value2, kind) {
|
|
|
699
709
|
if (Buffer.byteLength(text, "utf8") > LIMITS[kind])
|
|
700
710
|
throw new Error("Mailbox record is too large");
|
|
701
711
|
const v = value2;
|
|
712
|
+
if (kind === "bootstrap") {
|
|
713
|
+
const allowed2 = [
|
|
714
|
+
"version",
|
|
715
|
+
"build",
|
|
716
|
+
"runId",
|
|
717
|
+
"ownerSessionId",
|
|
718
|
+
"workspaceId",
|
|
719
|
+
"agentLabel",
|
|
720
|
+
"participants"
|
|
721
|
+
];
|
|
722
|
+
if (Object.keys(v).some((key) => !allowed2.includes(key)))
|
|
723
|
+
throw new Error("Unknown mailbox field");
|
|
724
|
+
if (!isRuntimeBuild(v.build))
|
|
725
|
+
throw new Error("Invalid runtime build identity");
|
|
726
|
+
for (const field of [
|
|
727
|
+
"runId",
|
|
728
|
+
"ownerSessionId",
|
|
729
|
+
"workspaceId",
|
|
730
|
+
"agentLabel"
|
|
731
|
+
])
|
|
732
|
+
if (typeof v[field] !== "string" || !v[field].trim())
|
|
733
|
+
throw new Error(`Invalid mailbox field: ${field}`);
|
|
734
|
+
if (!UUID2.test(v.runId)) throw new Error("Invalid mailbox UUID");
|
|
735
|
+
if (!Array.isArray(v.participants) || !v.participants.length)
|
|
736
|
+
throw new Error("Invalid bootstrap participants");
|
|
737
|
+
const ids = /* @__PURE__ */ new Set();
|
|
738
|
+
for (const participant of v.participants) {
|
|
739
|
+
if (!participant || typeof participant !== "object" || Object.keys(participant).some(
|
|
740
|
+
(key) => !["id", "payload"].includes(key)
|
|
741
|
+
) || typeof participant.id !== "string" || !BOOTSTRAP_ID.test(participant.id) || ids.has(participant.id) || typeof participant.payload !== "string")
|
|
742
|
+
throw new Error("Invalid or duplicate bootstrap participant");
|
|
743
|
+
ids.add(participant.id);
|
|
744
|
+
}
|
|
745
|
+
return;
|
|
746
|
+
}
|
|
702
747
|
const allowed = kind === "state" ? [
|
|
703
748
|
"version",
|
|
704
749
|
"build",
|
|
@@ -975,6 +1020,7 @@ function resetAgentMailbox(path) {
|
|
|
975
1020
|
for (const name of [
|
|
976
1021
|
"state.json",
|
|
977
1022
|
"ask.json",
|
|
1023
|
+
"bootstrap.json",
|
|
978
1024
|
...readdirSync3(path).filter(
|
|
979
1025
|
(x) => /^(request|result)-.*\.json$/.test(x)
|
|
980
1026
|
)
|
|
@@ -986,6 +1032,24 @@ function resetAgentMailbox(path) {
|
|
|
986
1032
|
}
|
|
987
1033
|
}
|
|
988
1034
|
}
|
|
1035
|
+
function writeAgentBootstrap(path, record) {
|
|
1036
|
+
atomic(file(path, "bootstrap.json"), record, "bootstrap");
|
|
1037
|
+
}
|
|
1038
|
+
function readAgentBootstrap(path) {
|
|
1039
|
+
const value2 = read(
|
|
1040
|
+
file(path, "bootstrap.json"),
|
|
1041
|
+
"bootstrap"
|
|
1042
|
+
);
|
|
1043
|
+
if (value2) validate(value2, "bootstrap");
|
|
1044
|
+
return value2;
|
|
1045
|
+
}
|
|
1046
|
+
function removeAgentBootstrap(path) {
|
|
1047
|
+
try {
|
|
1048
|
+
unlinkSync2(file(path, "bootstrap.json"));
|
|
1049
|
+
} catch (error2) {
|
|
1050
|
+
if (error2.code !== "ENOENT") throw error2;
|
|
1051
|
+
}
|
|
1052
|
+
}
|
|
989
1053
|
function removeAgentMailbox(path) {
|
|
990
1054
|
let names2;
|
|
991
1055
|
try {
|
|
@@ -1189,6 +1253,7 @@ function currentTurnIsSoleToolCall(ctx, name) {
|
|
|
1189
1253
|
const calls = turn.content.filter((part) => part?.type === "toolCall");
|
|
1190
1254
|
return calls.length === 1 && calls[0]?.name === name;
|
|
1191
1255
|
}
|
|
1256
|
+
var MANAGED_AGENT_BOOTSTRAP_EVENT = "pi-herdsman:managed-agent-bootstrap";
|
|
1192
1257
|
var FILE_HANDOFF_GUIDANCE = "Pass every user-supplied or already-available artifact relevant to the recipient's assignment, decisions, integration, validation, or onward handoff through `files`; do not assume the recipient inherits the sender's conversation or attachments. Preserve exact supplied result refs when forwarding them and omit unrelated evidence. `files` carries evidence, not runtime capability.";
|
|
1193
1258
|
function failUnknownResultRef(input, operation) {
|
|
1194
1259
|
fail(
|
|
@@ -12144,6 +12209,7 @@ function createAgentController(pi, options) {
|
|
|
12144
12209
|
let promptWriteFailed = false;
|
|
12145
12210
|
let started;
|
|
12146
12211
|
let accepted = false;
|
|
12212
|
+
const preparedBootstrap = [];
|
|
12147
12213
|
try {
|
|
12148
12214
|
try {
|
|
12149
12215
|
promptPaths = writePrivatePromptSnapshots([
|
|
@@ -12171,6 +12237,69 @@ function createAgentController(pi, options) {
|
|
|
12171
12237
|
);
|
|
12172
12238
|
ownerDisplay = displayIdentity(definition2, parentLabel);
|
|
12173
12239
|
}
|
|
12240
|
+
if (p.action === "delegate") {
|
|
12241
|
+
const registrations = /* @__PURE__ */ new Map();
|
|
12242
|
+
let open = true;
|
|
12243
|
+
let registrationError;
|
|
12244
|
+
pi.events.emit(MANAGED_AGENT_BOOTSTRAP_EVENT, {
|
|
12245
|
+
protocol: 1,
|
|
12246
|
+
phase: "prepare",
|
|
12247
|
+
context: ctx,
|
|
12248
|
+
agent: label,
|
|
12249
|
+
register(id, prepare) {
|
|
12250
|
+
if (!open)
|
|
12251
|
+
throw new Error(
|
|
12252
|
+
"Managed-agent bootstrap registration is closed"
|
|
12253
|
+
);
|
|
12254
|
+
if (!/^[A-Za-z0-9][A-Za-z0-9._:/-]{0,127}$/.test(id)) {
|
|
12255
|
+
registrationError ??= new Error(
|
|
12256
|
+
"Invalid managed-agent bootstrap participant ID"
|
|
12257
|
+
);
|
|
12258
|
+
return;
|
|
12259
|
+
}
|
|
12260
|
+
if (registrations.has(id)) {
|
|
12261
|
+
registrationError ??= new Error(
|
|
12262
|
+
`Duplicate managed-agent bootstrap participant ID: ${id}`
|
|
12263
|
+
);
|
|
12264
|
+
return;
|
|
12265
|
+
}
|
|
12266
|
+
if (typeof prepare !== "function") {
|
|
12267
|
+
registrationError ??= new Error(
|
|
12268
|
+
"Invalid managed-agent bootstrap prepare callback"
|
|
12269
|
+
);
|
|
12270
|
+
return;
|
|
12271
|
+
}
|
|
12272
|
+
registrations.set(id, prepare);
|
|
12273
|
+
}
|
|
12274
|
+
});
|
|
12275
|
+
open = false;
|
|
12276
|
+
if (registrationError) throw registrationError;
|
|
12277
|
+
const participants = [];
|
|
12278
|
+
for (const [id, prepare] of registrations) {
|
|
12279
|
+
const result = await prepare();
|
|
12280
|
+
if (result !== void 0) {
|
|
12281
|
+
if (!result || typeof result.payload !== "string" || result.commit !== void 0 && typeof result.commit !== "function")
|
|
12282
|
+
throw new Error(
|
|
12283
|
+
`Invalid preparation from managed-agent bootstrap participant "${id}"`
|
|
12284
|
+
);
|
|
12285
|
+
participants.push({ id, payload: result.payload });
|
|
12286
|
+
preparedBootstrap.push({
|
|
12287
|
+
id,
|
|
12288
|
+
...result.commit ? { commit: result.commit } : {}
|
|
12289
|
+
});
|
|
12290
|
+
}
|
|
12291
|
+
}
|
|
12292
|
+
if (participants.length)
|
|
12293
|
+
writeAgentBootstrap(mailbox, {
|
|
12294
|
+
version: 5,
|
|
12295
|
+
build: options.build,
|
|
12296
|
+
runId,
|
|
12297
|
+
ownerSessionId: owner,
|
|
12298
|
+
workspaceId,
|
|
12299
|
+
agentLabel: label,
|
|
12300
|
+
participants
|
|
12301
|
+
});
|
|
12302
|
+
}
|
|
12174
12303
|
const env = [
|
|
12175
12304
|
`PI_HERDSMAN_MAILBOX=${mailbox}`,
|
|
12176
12305
|
`PI_HERDSMAN_RUN_ID=${runId}`,
|
|
@@ -12360,6 +12489,8 @@ ${result.stderr ?? ""}`.trim(),
|
|
|
12360
12489
|
signal,
|
|
12361
12490
|
waitForSession: true
|
|
12362
12491
|
});
|
|
12492
|
+
for (const participant of preparedBootstrap)
|
|
12493
|
+
await participant.commit?.();
|
|
12363
12494
|
runtimes.set(label, runtime);
|
|
12364
12495
|
options.onChanged();
|
|
12365
12496
|
const requestId = await submit(
|
|
@@ -15644,8 +15775,53 @@ function registerManagedAgentSessionStartHandler(pi, execution, options) {
|
|
|
15644
15775
|
}
|
|
15645
15776
|
}
|
|
15646
15777
|
}
|
|
15647
|
-
if (!existing)
|
|
15778
|
+
if (!existing) {
|
|
15648
15779
|
validateManagedAgentDefinition(await options.getAgentDefinitions(ctx));
|
|
15780
|
+
const bootstrap = readAgentBootstrap(mailbox);
|
|
15781
|
+
if (bootstrap) {
|
|
15782
|
+
if (bootstrap.runId !== candidate.runId || bootstrap.ownerSessionId !== candidate.ownerSessionId || bootstrap.workspaceId !== candidate.workspaceId || bootstrap.agentLabel !== candidate.agentLabel)
|
|
15783
|
+
throw new Error("Managed-agent bootstrap identity mismatch");
|
|
15784
|
+
if (!sameRuntimeBuild(options.build, bootstrap.build))
|
|
15785
|
+
throw new Error("Managed-agent bootstrap Herdsman build mismatch");
|
|
15786
|
+
for (const participant of bootstrap.participants) {
|
|
15787
|
+
let initializer;
|
|
15788
|
+
let acceptCount = 0;
|
|
15789
|
+
let invalidInitializer = false;
|
|
15790
|
+
pi.events.emit(MANAGED_AGENT_BOOTSTRAP_EVENT, {
|
|
15791
|
+
protocol: 1,
|
|
15792
|
+
phase: "initialize",
|
|
15793
|
+
context: ctx,
|
|
15794
|
+
agent: candidate.agentLabel,
|
|
15795
|
+
participant: { id: participant.id, payload: participant.payload },
|
|
15796
|
+
accept(callback) {
|
|
15797
|
+
acceptCount++;
|
|
15798
|
+
if (typeof callback !== "function") {
|
|
15799
|
+
invalidInitializer = true;
|
|
15800
|
+
return;
|
|
15801
|
+
}
|
|
15802
|
+
if (acceptCount === 1) initializer = callback;
|
|
15803
|
+
}
|
|
15804
|
+
});
|
|
15805
|
+
if (acceptCount === 0 || invalidInitializer)
|
|
15806
|
+
throw new Error(
|
|
15807
|
+
`Managed-agent bootstrap participant "${participant.id}" is unavailable or invalid`
|
|
15808
|
+
);
|
|
15809
|
+
if (acceptCount > 1)
|
|
15810
|
+
throw new Error(
|
|
15811
|
+
`Managed-agent bootstrap participant "${participant.id}" has multiple initializers`
|
|
15812
|
+
);
|
|
15813
|
+
try {
|
|
15814
|
+
await initializer();
|
|
15815
|
+
} catch (error2) {
|
|
15816
|
+
throw new Error(
|
|
15817
|
+
`Managed-agent bootstrap participant "${participant.id}" failed: ${String(error2)}`,
|
|
15818
|
+
{ cause: error2 }
|
|
15819
|
+
);
|
|
15820
|
+
}
|
|
15821
|
+
}
|
|
15822
|
+
removeAgentBootstrap(mailbox);
|
|
15823
|
+
}
|
|
15824
|
+
}
|
|
15649
15825
|
const release = options.claimAssignmentLock(mailbox, "session_start", {
|
|
15650
15826
|
label: execution.assignment.agentLabel,
|
|
15651
15827
|
paneId: execution.assignment.paneId
|
|
@@ -22570,7 +22746,7 @@ async function workspacePresentationProvenance(pi, ctx, workspaceIds, workspaceC
|
|
|
22570
22746
|
);
|
|
22571
22747
|
return new Map(entries);
|
|
22572
22748
|
}
|
|
22573
|
-
function
|
|
22749
|
+
function extension_default(pi) {
|
|
22574
22750
|
let leadRuntimes;
|
|
22575
22751
|
let leadStatusRuntime;
|
|
22576
22752
|
let leadHerdRunRuntime;
|
|
@@ -23799,6 +23975,6 @@ ${summary}`,
|
|
|
23799
23975
|
});
|
|
23800
23976
|
}
|
|
23801
23977
|
export {
|
|
23802
|
-
|
|
23978
|
+
extension_default as default
|
|
23803
23979
|
};
|
|
23804
23980
|
//# sourceMappingURL=index.js.map
|