@pasko70/pibo 2.2.5 → 2.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/dist/agent-runtime/context-build.js +5 -2
- package/dist/agent-runtimes/pi/adapter.js +1 -1
- package/dist/agent-runtimes/pi/runtime.js +25 -16
- package/dist/apps/chat-ui/assets/{dist-BK7eaoLT.js → dist-Byygd1lH.js} +1 -1
- package/dist/apps/chat-ui/assets/{dist-fNgdnmyE.js → dist-C9BrS7sL.js} +1 -1
- package/dist/apps/chat-ui/assets/{dist-wq3P0LZj.js → dist-CUcAofmV.js} +1 -1
- package/dist/apps/chat-ui/assets/{dist-BCRR_a0Z.js → dist-D4RU6xu3.js} +1 -1
- package/dist/apps/chat-ui/assets/{dist-CTUT484B.js → dist-DusFwy0L.js} +1 -1
- package/dist/apps/chat-ui/assets/{index-DsFKL_EZ.js → index-Bifi_kjN.js} +90 -90
- package/dist/apps/chat-ui/index.html +1 -1
- package/dist/apps/chat-vscode-web/assets/{index-R4FTxr78.js → index-WsLm1mo3.js} +5 -5
- package/dist/apps/chat-vscode-web/index.html +1 -1
- package/dist/apps/vscode-artifacts/latest.vsix +0 -0
- package/dist/apps/vscode-artifacts/{pibo-vscode-ext-2.2.5.vsix → pibo-vscode-ext-2.4.0.vsix} +0 -0
- package/dist/compute/cli.js +13 -0
- package/dist/compute/pool/artifacts.js +116 -0
- package/dist/compute/pool/cli.js +156 -0
- package/dist/compute/pool/config.js +101 -0
- package/dist/compute/pool/docker.js +157 -0
- package/dist/compute/pool/seeds.js +201 -0
- package/dist/compute/pool/service.js +402 -0
- package/dist/compute/pool/store.js +239 -0
- package/dist/compute/pool/types.js +1 -0
- package/dist/core/codex-compat.js +1 -3
- package/dist/core/context-build.js +16 -7
- package/dist/core/session-router.js +221 -45
- package/dist/data/ingest-service.js +12 -0
- package/dist/debug/agents.js +391 -0
- package/dist/debug/index.js +7 -0
- package/dist/index.js +1 -1
- package/dist/resources/lifecycle.js +22 -2
- package/dist/resources/reaper.js +1 -0
- package/dist/session-ui/delegation.js +4 -2
- package/dist/shared/trace-async-agent-runs.js +4 -2
- package/dist/shared/trace-event-projection.js +8 -2
- package/dist/shared/trace-subagent-links.js +19 -6
- package/dist/subagents/observations.js +149 -0
- package/dist/subagents/tool.js +177 -46
- package/dist/tools/session-service.js +1 -0
- package/dist/tools/session-tool-set.js +9 -5
- package/dist/web/channel.js +9 -3
- package/npm-shrinkwrap.json +2 -2
- package/package.json +1 -1
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
import { mkdirSync } from "node:fs";
|
|
2
|
+
import { chmodSync } from "node:fs";
|
|
3
|
+
import { dirname, resolve } from "node:path";
|
|
4
|
+
import { DatabaseSync } from "node:sqlite";
|
|
5
|
+
function slotFromRow(row) {
|
|
6
|
+
return {
|
|
7
|
+
id: row.id,
|
|
8
|
+
ordinal: row.ordinal,
|
|
9
|
+
webPort: row.web_port,
|
|
10
|
+
gatewayPort: row.gateway_port,
|
|
11
|
+
publicUrl: row.public_url ?? undefined,
|
|
12
|
+
state: row.state,
|
|
13
|
+
activeLeaseId: row.active_lease_id ?? undefined,
|
|
14
|
+
dirtyReason: row.dirty_reason ?? undefined,
|
|
15
|
+
updatedAt: row.updated_at,
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
function leaseFromRow(row) {
|
|
19
|
+
return {
|
|
20
|
+
id: row.id,
|
|
21
|
+
slotId: row.slot_id,
|
|
22
|
+
holder: row.holder,
|
|
23
|
+
seedMode: row.seed_mode,
|
|
24
|
+
artifactSha256: row.artifact_sha256,
|
|
25
|
+
artifactRuntimePath: row.artifact_runtime_path,
|
|
26
|
+
packageVersion: row.package_version ?? undefined,
|
|
27
|
+
commit: row.commit_sha ?? undefined,
|
|
28
|
+
containerName: row.container_name,
|
|
29
|
+
publicUrl: row.public_url ?? undefined,
|
|
30
|
+
status: row.status,
|
|
31
|
+
createdAt: row.created_at,
|
|
32
|
+
expiresAt: row.expires_at,
|
|
33
|
+
renewedAt: row.renewed_at ?? undefined,
|
|
34
|
+
releasedAt: row.released_at ?? undefined,
|
|
35
|
+
failedAt: row.failed_at ?? undefined,
|
|
36
|
+
failureSnapshotPath: row.failure_snapshot_path ?? undefined,
|
|
37
|
+
lastError: row.last_error ?? undefined,
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
export class DeploymentPoolStore {
|
|
41
|
+
path;
|
|
42
|
+
db;
|
|
43
|
+
constructor(path, slots) {
|
|
44
|
+
this.path = path === ":memory:" ? path : resolve(path);
|
|
45
|
+
if (this.path !== ":memory:")
|
|
46
|
+
mkdirSync(dirname(this.path), { recursive: true, mode: 0o700 });
|
|
47
|
+
this.db = new DatabaseSync(this.path);
|
|
48
|
+
this.db.exec("PRAGMA busy_timeout = 10000");
|
|
49
|
+
if (this.path !== ":memory:")
|
|
50
|
+
this.db.exec("PRAGMA journal_mode = WAL");
|
|
51
|
+
this.applySchema();
|
|
52
|
+
this.ensureSlots(slots);
|
|
53
|
+
if (this.path !== ":memory:")
|
|
54
|
+
chmodSync(this.path, 0o600);
|
|
55
|
+
}
|
|
56
|
+
applySchema() {
|
|
57
|
+
this.db.exec(`
|
|
58
|
+
CREATE TABLE IF NOT EXISTS deployment_pool_slots (
|
|
59
|
+
id TEXT PRIMARY KEY,
|
|
60
|
+
ordinal INTEGER NOT NULL UNIQUE,
|
|
61
|
+
web_port INTEGER NOT NULL UNIQUE,
|
|
62
|
+
gateway_port INTEGER NOT NULL UNIQUE,
|
|
63
|
+
public_url TEXT,
|
|
64
|
+
state TEXT NOT NULL,
|
|
65
|
+
active_lease_id TEXT,
|
|
66
|
+
dirty_reason TEXT,
|
|
67
|
+
updated_at TEXT NOT NULL
|
|
68
|
+
);
|
|
69
|
+
CREATE TABLE IF NOT EXISTS deployment_pool_leases (
|
|
70
|
+
id TEXT PRIMARY KEY,
|
|
71
|
+
slot_id TEXT NOT NULL,
|
|
72
|
+
holder TEXT NOT NULL,
|
|
73
|
+
seed_mode TEXT NOT NULL,
|
|
74
|
+
artifact_sha256 TEXT NOT NULL,
|
|
75
|
+
artifact_runtime_path TEXT NOT NULL,
|
|
76
|
+
package_version TEXT,
|
|
77
|
+
commit_sha TEXT,
|
|
78
|
+
container_name TEXT NOT NULL,
|
|
79
|
+
public_url TEXT,
|
|
80
|
+
status TEXT NOT NULL,
|
|
81
|
+
created_at TEXT NOT NULL,
|
|
82
|
+
expires_at TEXT NOT NULL,
|
|
83
|
+
renewed_at TEXT,
|
|
84
|
+
released_at TEXT,
|
|
85
|
+
failed_at TEXT,
|
|
86
|
+
failure_snapshot_path TEXT,
|
|
87
|
+
last_error TEXT
|
|
88
|
+
);
|
|
89
|
+
CREATE INDEX IF NOT EXISTS deployment_pool_leases_status_idx
|
|
90
|
+
ON deployment_pool_leases (status, expires_at);
|
|
91
|
+
CREATE INDEX IF NOT EXISTS deployment_pool_leases_slot_idx
|
|
92
|
+
ON deployment_pool_leases (slot_id, created_at DESC);
|
|
93
|
+
`);
|
|
94
|
+
}
|
|
95
|
+
ensureSlots(slots) {
|
|
96
|
+
const now = new Date().toISOString();
|
|
97
|
+
const insert = this.db.prepare(`
|
|
98
|
+
INSERT INTO deployment_pool_slots (id, ordinal, web_port, gateway_port, public_url, state, updated_at)
|
|
99
|
+
VALUES (?, ?, ?, ?, ?, 'free', ?)
|
|
100
|
+
ON CONFLICT(id) DO UPDATE SET
|
|
101
|
+
ordinal=excluded.ordinal,
|
|
102
|
+
web_port=excluded.web_port,
|
|
103
|
+
gateway_port=excluded.gateway_port,
|
|
104
|
+
public_url=excluded.public_url
|
|
105
|
+
`);
|
|
106
|
+
for (const slot of slots)
|
|
107
|
+
insert.run(slot.id, slot.ordinal, slot.webPort, slot.gatewayPort, slot.publicUrl ?? null, now);
|
|
108
|
+
}
|
|
109
|
+
listSlots() {
|
|
110
|
+
return this.db.prepare("SELECT * FROM deployment_pool_slots ORDER BY ordinal").all().map(slotFromRow);
|
|
111
|
+
}
|
|
112
|
+
getSlot(id) {
|
|
113
|
+
const row = this.db.prepare("SELECT * FROM deployment_pool_slots WHERE id = ?").get(id);
|
|
114
|
+
return row ? slotFromRow(row) : undefined;
|
|
115
|
+
}
|
|
116
|
+
listLeases(options = {}) {
|
|
117
|
+
const where = options.includeInactive ? "" : "WHERE status IN ('provisioning', 'ready', 'releasing')";
|
|
118
|
+
return this.db.prepare(`SELECT * FROM deployment_pool_leases ${where} ORDER BY created_at DESC`).all().map(leaseFromRow);
|
|
119
|
+
}
|
|
120
|
+
getLease(id) {
|
|
121
|
+
const row = this.db.prepare("SELECT * FROM deployment_pool_leases WHERE id = ?").get(id);
|
|
122
|
+
return row ? leaseFromRow(row) : undefined;
|
|
123
|
+
}
|
|
124
|
+
reserveLease(input) {
|
|
125
|
+
this.db.exec("BEGIN IMMEDIATE");
|
|
126
|
+
try {
|
|
127
|
+
const active = this.db.prepare("SELECT COUNT(*) AS count FROM deployment_pool_slots WHERE state IN ('provisioning', 'ready', 'releasing')").get();
|
|
128
|
+
if (Number(active.count) >= input.maxActive) {
|
|
129
|
+
const nearest = this.db.prepare(`
|
|
130
|
+
SELECT MIN(l.expires_at) AS nearest_expiry
|
|
131
|
+
FROM deployment_pool_slots s
|
|
132
|
+
JOIN deployment_pool_leases l ON l.id = s.active_lease_id
|
|
133
|
+
WHERE s.state IN ('provisioning', 'ready', 'releasing')
|
|
134
|
+
`).get();
|
|
135
|
+
throw new Error(`Deployment pool capacity reached (${input.maxActive} active)${nearest.nearest_expiry ? `; nearest expiry ${nearest.nearest_expiry}` : ""}`);
|
|
136
|
+
}
|
|
137
|
+
const row = this.db.prepare("SELECT * FROM deployment_pool_slots WHERE state = 'free' ORDER BY ordinal LIMIT 1").get();
|
|
138
|
+
if (!row)
|
|
139
|
+
throw new Error("No free deployment pool slot is available");
|
|
140
|
+
const slot = slotFromRow(row);
|
|
141
|
+
const containerName = `pibo-pool-${slot.id}`;
|
|
142
|
+
this.db.prepare(`
|
|
143
|
+
INSERT INTO deployment_pool_leases (
|
|
144
|
+
id, slot_id, holder, seed_mode, artifact_sha256, artifact_runtime_path,
|
|
145
|
+
package_version, commit_sha, container_name, public_url, status, created_at, expires_at
|
|
146
|
+
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 'provisioning', ?, ?)
|
|
147
|
+
`).run(input.id, slot.id, input.holder, input.seedMode, input.artifactSha256, input.artifactRuntimePath, input.packageVersion ?? null, input.commit ?? null, containerName, slot.publicUrl ?? null, input.createdAt, input.expiresAt);
|
|
148
|
+
this.db.prepare("UPDATE deployment_pool_slots SET state='provisioning', active_lease_id=?, dirty_reason=NULL, updated_at=? WHERE id=?")
|
|
149
|
+
.run(input.id, input.createdAt, slot.id);
|
|
150
|
+
this.db.exec("COMMIT");
|
|
151
|
+
return { slot: this.getSlot(slot.id), lease: this.getLease(input.id) };
|
|
152
|
+
}
|
|
153
|
+
catch (error) {
|
|
154
|
+
this.db.exec("ROLLBACK");
|
|
155
|
+
throw error;
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
markReady(leaseId, now = new Date().toISOString()) {
|
|
159
|
+
const lease = this.requireLease(leaseId);
|
|
160
|
+
this.db.exec("BEGIN IMMEDIATE");
|
|
161
|
+
try {
|
|
162
|
+
this.db.prepare("UPDATE deployment_pool_leases SET status='ready', last_error=NULL WHERE id=?").run(leaseId);
|
|
163
|
+
this.db.prepare("UPDATE deployment_pool_slots SET state='ready', dirty_reason=NULL, updated_at=? WHERE id=? AND active_lease_id=?")
|
|
164
|
+
.run(now, lease.slotId, leaseId);
|
|
165
|
+
this.db.exec("COMMIT");
|
|
166
|
+
return this.requireLease(leaseId);
|
|
167
|
+
}
|
|
168
|
+
catch (error) {
|
|
169
|
+
this.db.exec("ROLLBACK");
|
|
170
|
+
throw error;
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
markReleasing(leaseId, now = new Date().toISOString()) {
|
|
174
|
+
const lease = this.requireLease(leaseId);
|
|
175
|
+
this.db.prepare("UPDATE deployment_pool_leases SET status='releasing' WHERE id=? AND status IN ('provisioning','ready','releasing')").run(leaseId);
|
|
176
|
+
this.db.prepare("UPDATE deployment_pool_slots SET state='releasing', updated_at=? WHERE id=? AND active_lease_id=?").run(now, lease.slotId, leaseId);
|
|
177
|
+
return this.requireLease(leaseId);
|
|
178
|
+
}
|
|
179
|
+
markReleased(leaseId, status, now = new Date().toISOString()) {
|
|
180
|
+
const lease = this.requireLease(leaseId);
|
|
181
|
+
this.db.exec("BEGIN IMMEDIATE");
|
|
182
|
+
try {
|
|
183
|
+
this.db.prepare("UPDATE deployment_pool_leases SET status=?, released_at=?, last_error=NULL WHERE id=?").run(status, now, leaseId);
|
|
184
|
+
this.db.prepare("UPDATE deployment_pool_slots SET state='free', active_lease_id=NULL, dirty_reason=NULL, updated_at=? WHERE id=? AND active_lease_id=?")
|
|
185
|
+
.run(now, lease.slotId, leaseId);
|
|
186
|
+
this.db.exec("COMMIT");
|
|
187
|
+
return this.requireLease(leaseId);
|
|
188
|
+
}
|
|
189
|
+
catch (error) {
|
|
190
|
+
this.db.exec("ROLLBACK");
|
|
191
|
+
throw error;
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
markFailed(leaseId, error, snapshotPath, options = { slotClean: false }) {
|
|
195
|
+
const lease = this.requireLease(leaseId);
|
|
196
|
+
const now = options.now ?? new Date().toISOString();
|
|
197
|
+
this.db.exec("BEGIN IMMEDIATE");
|
|
198
|
+
try {
|
|
199
|
+
this.db.prepare("UPDATE deployment_pool_leases SET status='failed', failed_at=?, failure_snapshot_path=?, last_error=? WHERE id=?")
|
|
200
|
+
.run(now, snapshotPath ?? null, error, leaseId);
|
|
201
|
+
if (options.slotClean) {
|
|
202
|
+
this.db.prepare("UPDATE deployment_pool_slots SET state='free', active_lease_id=NULL, dirty_reason=NULL, updated_at=? WHERE id=? AND active_lease_id=?")
|
|
203
|
+
.run(now, lease.slotId, leaseId);
|
|
204
|
+
}
|
|
205
|
+
else {
|
|
206
|
+
this.db.prepare("UPDATE deployment_pool_slots SET state='dirty', dirty_reason=?, updated_at=? WHERE id=? AND active_lease_id=?")
|
|
207
|
+
.run(error, now, lease.slotId, leaseId);
|
|
208
|
+
}
|
|
209
|
+
this.db.exec("COMMIT");
|
|
210
|
+
return this.requireLease(leaseId);
|
|
211
|
+
}
|
|
212
|
+
catch (caught) {
|
|
213
|
+
this.db.exec("ROLLBACK");
|
|
214
|
+
throw caught;
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
renewLease(leaseId, holder, expiresAt, now = new Date().toISOString()) {
|
|
218
|
+
const result = this.db.prepare(`
|
|
219
|
+
UPDATE deployment_pool_leases SET expires_at=?, renewed_at=?
|
|
220
|
+
WHERE id=? AND holder=? AND status='ready'
|
|
221
|
+
`).run(expiresAt, now, leaseId, holder);
|
|
222
|
+
if (Number(result.changes ?? 0) !== 1)
|
|
223
|
+
throw new Error(`Active deployment lease "${leaseId}" for holder "${holder}" was not found`);
|
|
224
|
+
return this.requireLease(leaseId);
|
|
225
|
+
}
|
|
226
|
+
freeDirtySlot(slotId, now = new Date().toISOString()) {
|
|
227
|
+
this.db.prepare("UPDATE deployment_pool_slots SET state='free', active_lease_id=NULL, dirty_reason=NULL, updated_at=? WHERE id=?")
|
|
228
|
+
.run(now, slotId);
|
|
229
|
+
}
|
|
230
|
+
requireLease(id) {
|
|
231
|
+
const lease = this.getLease(id);
|
|
232
|
+
if (!lease)
|
|
233
|
+
throw new Error(`Deployment lease "${id}" was not found`);
|
|
234
|
+
return lease;
|
|
235
|
+
}
|
|
236
|
+
close() {
|
|
237
|
+
this.db.close();
|
|
238
|
+
}
|
|
239
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
const CODEX_COMPAT_SUBAGENTS = ["default", "explorer", "worker"];
|
|
2
1
|
function currentDate() {
|
|
3
2
|
return new Date().toISOString().slice(0, 10);
|
|
4
3
|
}
|
|
@@ -15,7 +14,7 @@ export function buildCodexCompatSystemPrompt(options) {
|
|
|
15
14
|
const compatibilityInstructions = [
|
|
16
15
|
"# Codex-Compatible Runtime",
|
|
17
16
|
"You are running in Pibo through the codex-compat profile. Match Codex-style tool use where the exposed Pibo tools support it, while staying truthful about implemented behavior.",
|
|
18
|
-
"Use Pibo's pibo_run_*
|
|
17
|
+
"Use Pibo's pibo_run_* and pibo_agents_* tools for parallel work, yielded runs, and delegated-agent lifecycle management.",
|
|
19
18
|
"Use direct execution for normal coding tasks. If a structured planning or user-input tool is not present, ask concise questions in normal chat.",
|
|
20
19
|
"When web_search is selected by the profile, use it for current or externally sourced information.",
|
|
21
20
|
childInstructions,
|
|
@@ -24,7 +23,6 @@ export function buildCodexCompatSystemPrompt(options) {
|
|
|
24
23
|
` <shell>${options.shell}</shell>`,
|
|
25
24
|
` <current_date>${options.currentDate ?? currentDate()}</current_date>`,
|
|
26
25
|
` <timezone>${options.timezone ?? currentTimezone()}</timezone>`,
|
|
27
|
-
` <subagents>${CODEX_COMPAT_SUBAGENTS.join(", ")}</subagents>`,
|
|
28
26
|
"</environment_context>",
|
|
29
27
|
options.baseSystemPrompt,
|
|
30
28
|
];
|
|
@@ -139,11 +139,20 @@ function sanitizeNode(input, parentId, order = 0) {
|
|
|
139
139
|
function countNodes(nodes) {
|
|
140
140
|
return nodes.reduce((count, node) => count + 1 + countNodes(node.children ?? []), 0);
|
|
141
141
|
}
|
|
142
|
-
function
|
|
142
|
+
function inspectionAgentsController() {
|
|
143
|
+
const fail = () => {
|
|
144
|
+
throw new Error("Context build inspection cannot execute delegated-agent tools");
|
|
145
|
+
};
|
|
143
146
|
return {
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
+
sendMessage: fail,
|
|
148
|
+
listAgents: () => [],
|
|
149
|
+
observe: (input) => ({
|
|
150
|
+
filters: input,
|
|
151
|
+
observations: [],
|
|
152
|
+
nextAfterSequence: input.afterSequence ?? 0,
|
|
153
|
+
truncated: false,
|
|
154
|
+
}),
|
|
155
|
+
killAgent: fail,
|
|
147
156
|
};
|
|
148
157
|
}
|
|
149
158
|
function inspectionRunToolController() {
|
|
@@ -196,8 +205,8 @@ function toolDefinitionSchema(definition, toolInfo) {
|
|
|
196
205
|
function generatedOriginForTool(name, profile) {
|
|
197
206
|
if (name === "runtime")
|
|
198
207
|
return "Generated Pibo runtime tool selected by the profile.";
|
|
199
|
-
if (name.startsWith("
|
|
200
|
-
return "Generated
|
|
208
|
+
if (name.startsWith("pibo_agents_"))
|
|
209
|
+
return "Generated shared agent-management tool from the profile's delegated-agent list.";
|
|
201
210
|
if (name.startsWith("pibo_run_"))
|
|
202
211
|
return "Generated run-control tool from the pibo-run-control capability package.";
|
|
203
212
|
if (PIBO_GOAL_TOOL_NAMES.includes(name))
|
|
@@ -298,7 +307,7 @@ export async function inspectPiboContextBuild(options = {}) {
|
|
|
298
307
|
profile: inspectionProfile,
|
|
299
308
|
activeModel: undefined,
|
|
300
309
|
persistSession: false,
|
|
301
|
-
|
|
310
|
+
agentsController: options.agentsController ?? (hasEnabledSubagents ? inspectionAgentsController() : undefined),
|
|
302
311
|
runToolController: options.runToolController ?? (hasYieldableTools ? inspectionRunToolController() : undefined),
|
|
303
312
|
});
|
|
304
313
|
try {
|