@pasko70/pibo 3.2.3 → 3.2.5
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/auth.js +3 -5
- package/dist/agent-runtime/portable-history.js +1 -1
- package/dist/agent-runtimes/codex-native/client.js +2 -5
- package/dist/agent-runtimes/codex-native/redaction.js +3 -27
- package/dist/agent-runtimes/omp/client.js +2 -4
- package/dist/agent-runtimes/pi/adapter.js +1 -0
- package/dist/agent-runtimes/pi/runtime.js +1 -1
- package/dist/apps/chat/agent-store.js +1 -1
- package/dist/apps/chat/chat-files.js +3 -1
- package/dist/apps/chat/chat-request-normalizers.js +1 -1
- package/dist/apps/chat/chat-user-skill-routes.js +7 -0
- package/dist/apps/chat/data/project-service.js +49 -1
- package/dist/apps/chat/data/session-query-service.js +46 -6
- package/dist/apps/chat/loop-api.js +10 -1
- package/dist/apps/chat/ralph-api.js +10 -1
- package/dist/apps/chat/web-app.js +22 -5
- package/dist/apps/chat-ui/assets/{dist-CTsyojIh.js → dist-CTC-_3l0.js} +1 -1
- package/dist/apps/chat-ui/assets/{dist-BHio-Mzx.js → dist-CftLEFd5.js} +1 -1
- package/dist/apps/chat-ui/assets/{dist-DJ6Bhcuk.js → dist-Dq27Wt2q.js} +1 -1
- package/dist/apps/chat-ui/assets/{dist-CPKEoSPK.js → dist-Y4fHV5-Z.js} +1 -1
- package/dist/apps/chat-ui/assets/{dist-DNHFRMCk.js → dist-dGF-PDGY.js} +1 -1
- package/dist/apps/chat-ui/assets/index-C_P0gXvJ.js +228 -0
- package/dist/apps/chat-ui/assets/{index-Dc-6Xupt.css → index-DUGVw259.css} +1 -1
- package/dist/apps/chat-ui/index.html +2 -2
- package/dist/apps/chat-vscode-web/assets/{index-B1TuQNY5.js → index-B5X0NaRo.js} +4 -4
- package/dist/apps/chat-vscode-web/index.html +1 -1
- package/dist/apps/cli-ui/InkSessionApp.js +38 -28
- package/dist/auth/cli.js +4 -6
- package/dist/auth/machine-keys.js +20 -3
- package/dist/cli-session/localSessionSource.js +2 -4
- package/dist/compute/cli.js +16 -13
- package/dist/compute/docker.js +96 -48
- package/dist/core/base-prompt.js +27 -5
- package/dist/core/context-build.js +5 -15
- package/dist/core/sensitive-data-redaction.js +2 -2
- package/dist/core/session-router.js +15 -4
- package/dist/cron/cli.js +42 -10
- package/dist/cron/store.js +1 -1
- package/dist/data/cli.js +15 -7
- package/dist/data/payload-store.js +55 -7
- package/dist/data/schema.js +65 -23
- package/dist/debug/index.js +5 -0
- package/dist/debug/pty.js +45 -10
- package/dist/gateway/cli.js +18 -2
- package/dist/gateway/server.js +1 -0
- package/dist/loops/service.js +32 -16
- package/dist/mcp/runtime-session.js +2 -1
- package/dist/pi-packages/cli.js +5 -0
- package/dist/previews/cli.js +2 -6
- package/dist/previews/config.js +10 -0
- package/dist/previews/manager.js +2 -9
- package/dist/ralph/service.js +21 -10
- package/dist/session-ui/statusViewModel.js +2 -4
- package/dist/sessions/pibo-data-store.js +18 -0
- package/dist/sessions/store.js +9 -0
- package/dist/setup/cli.js +14 -7
- package/dist/setup/installation-profiles.js +20 -7
- package/dist/shared/trace-event-projection.js +32 -1
- package/dist/subagents/tool.js +3 -3
- package/dist/tools/browser-use-leases.js +11 -3
- package/dist/tools/index.js +0 -1
- package/dist/tools/mcp-bridge.js +1 -1
- package/dist/tools/runtime/node-worker-source.js +39 -5
- package/dist/tools/runtime/python-backend.js +6 -2
- package/dist/tools/runtime/registry.js +38 -6
- package/dist/vscode/cli.js +1 -2
- package/dist/vscode/install.js +21 -14
- package/npm-shrinkwrap.json +2 -2
- package/package.json +3 -1
- package/dist/apps/chat-ui/assets/index-Y6jYzsaC.js +0 -228
|
@@ -1196,7 +1196,7 @@ export class PiboSessionRouter {
|
|
|
1196
1196
|
const status = current.getStatus();
|
|
1197
1197
|
if (status.disposed || status.processing || status.streaming || status.queuedMessages > 0)
|
|
1198
1198
|
return;
|
|
1199
|
-
await this.resetCachedSession(piboSessionId
|
|
1199
|
+
await this.resetCachedSession(piboSessionId);
|
|
1200
1200
|
}
|
|
1201
1201
|
async getOrCreateSession(piboSessionId) {
|
|
1202
1202
|
if (this.closing)
|
|
@@ -1391,6 +1391,7 @@ export class PiboSessionRouter {
|
|
|
1391
1391
|
...(runtimeBindingPersistence ? { runtimeBindingPersistence } : {}),
|
|
1392
1392
|
compatibility: {
|
|
1393
1393
|
persistSession: this.options.persistSession,
|
|
1394
|
+
piPackageStoreCwd: this.options.piPackageStoreCwd,
|
|
1394
1395
|
thinkingLevel: initialThinkingLevel ?? this.options.thinkingLevel,
|
|
1395
1396
|
retryDefaults: resolvePiboSessionRetryDefaults(piboSession.kind, this.options.retryDefaults),
|
|
1396
1397
|
extensionFactories: [
|
|
@@ -2015,6 +2016,8 @@ export class PiboSessionRouter {
|
|
|
2015
2016
|
resolveSettled = resolve;
|
|
2016
2017
|
});
|
|
2017
2018
|
const untrack = this.trackActiveSubagent(parentPiboSessionId, {
|
|
2019
|
+
agentId: child.id,
|
|
2020
|
+
requestId,
|
|
2018
2021
|
abortController: parentAbortController,
|
|
2019
2022
|
settled,
|
|
2020
2023
|
});
|
|
@@ -2098,8 +2101,14 @@ export class PiboSessionRouter {
|
|
|
2098
2101
|
const child = this.requireManagedAgent(parentPiboSessionId, agentId);
|
|
2099
2102
|
const ids = [agentId, ...this.descendantSessionIds(agentId)];
|
|
2100
2103
|
const idSet = new Set(ids);
|
|
2104
|
+
const activeParentRunIds = new Set([...(this.activeSubagentRequests.get(parentPiboSessionId) ?? [])]
|
|
2105
|
+
.filter((request) => idSet.has(request.agentId))
|
|
2106
|
+
.map((request) => request.requestId));
|
|
2101
2107
|
const cancellableRuns = this.runRegistry.listAll({ includeConsumed: true, includeDetached: true })
|
|
2102
|
-
.filter((run) =>
|
|
2108
|
+
.filter((run) => !isTerminalRunStatus(run.status) && (idSet.has(run.controllerPiboSessionId)
|
|
2109
|
+
|| (run.controllerPiboSessionId === parentPiboSessionId && activeParentRunIds.has(run.runId))));
|
|
2110
|
+
const reason = `killed by parent ${parentPiboSessionId}`;
|
|
2111
|
+
await this.cancelRunsAfterSettlement(cancellableRuns.filter((run) => run.controllerPiboSessionId === parentPiboSessionId), reason);
|
|
2103
2112
|
await Promise.allSettled(ids.flatMap((id) => this.sessions.has(id)
|
|
2104
2113
|
? [this.emit({ type: "execution", piboSessionId: id, action: "abort", id: randomUUID() })]
|
|
2105
2114
|
: []));
|
|
@@ -2112,7 +2121,7 @@ export class PiboSessionRouter {
|
|
|
2112
2121
|
},
|
|
2113
2122
|
});
|
|
2114
2123
|
}
|
|
2115
|
-
await this.disposeSessionSubtree(agentId,
|
|
2124
|
+
await this.disposeSessionSubtree(agentId, reason, { cancelRuns: true });
|
|
2116
2125
|
const cancelledRuns = cancellableRuns.flatMap((run) => {
|
|
2117
2126
|
const current = this.runRegistry.status(run.controllerPiboSessionId, run.runId);
|
|
2118
2127
|
return current.status === "cancelled" ? [run.runId] : [];
|
|
@@ -2368,9 +2377,11 @@ export class PiboSessionRouter {
|
|
|
2368
2377
|
: eventId
|
|
2369
2378
|
? this.subagentRequestIdsByEvent.get(subagentRequestEventKey(session.id, eventId))
|
|
2370
2379
|
: undefined;
|
|
2380
|
+
const sequence = this.sessionStore.claimAgentObservationSequence?.(session.parentId, this.nextAgentObservationSequence) ?? this.nextAgentObservationSequence;
|
|
2381
|
+
this.nextAgentObservationSequence = Math.max(this.nextAgentObservationSequence, sequence + 1);
|
|
2371
2382
|
const observation = {
|
|
2372
2383
|
managingParentId: session.parentId,
|
|
2373
|
-
sequence
|
|
2384
|
+
sequence,
|
|
2374
2385
|
createdAt: new Date().toISOString(),
|
|
2375
2386
|
...(requestId ? { requestId } : {}),
|
|
2376
2387
|
agentId: session.id,
|
package/dist/cron/cli.js
CHANGED
|
@@ -34,18 +34,44 @@ function maybeTargetFromOptions(options) {
|
|
|
34
34
|
return undefined;
|
|
35
35
|
return targetFromOptions(options);
|
|
36
36
|
}
|
|
37
|
+
function scheduleSelectors(options, positionalCron) {
|
|
38
|
+
const candidates = [
|
|
39
|
+
["--in", typeof options.in === "string"],
|
|
40
|
+
["--at", typeof options.at === "string"],
|
|
41
|
+
["--every", typeof options.every === "string"],
|
|
42
|
+
["--daily", typeof options.daily === "string"],
|
|
43
|
+
["--weekly", typeof options.weekly === "string"],
|
|
44
|
+
["--monthly", typeof options.monthly === "string" || typeof options.monthly === "number"],
|
|
45
|
+
["--cron", typeof options.cron === "string"],
|
|
46
|
+
["positional cron expression", Boolean(positionalCron)],
|
|
47
|
+
];
|
|
48
|
+
return candidates.filter(([, selected]) => selected).map(([selector]) => selector);
|
|
49
|
+
}
|
|
37
50
|
function hasScheduleOptions(options, positionalCron) {
|
|
38
|
-
return
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
51
|
+
return scheduleSelectors(options, positionalCron).length > 0;
|
|
52
|
+
}
|
|
53
|
+
function scheduleWithTimezone(job, tz) {
|
|
54
|
+
if (job.schedule.kind !== "cron")
|
|
55
|
+
throw new Error("--tz can only update an existing wall-clock cron schedule");
|
|
56
|
+
let scheduleUi;
|
|
57
|
+
if (job.scheduleUi) {
|
|
58
|
+
switch (job.scheduleUi.preset) {
|
|
59
|
+
case "daily":
|
|
60
|
+
case "weekly":
|
|
61
|
+
case "monthly":
|
|
62
|
+
case "advanced":
|
|
63
|
+
scheduleUi = { ...job.scheduleUi, tz };
|
|
64
|
+
break;
|
|
65
|
+
default:
|
|
66
|
+
scheduleUi = job.scheduleUi;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
return { schedule: { ...job.schedule, tz }, scheduleUi };
|
|
47
70
|
}
|
|
48
71
|
function scheduleFromOptions(options, positionalCron) {
|
|
72
|
+
const selectors = scheduleSelectors(options, positionalCron);
|
|
73
|
+
if (selectors.length > 1)
|
|
74
|
+
throw new Error(`Conflicting schedule selectors: ${selectors.join(", ")}. Choose exactly one schedule source.`);
|
|
49
75
|
if (typeof options.in === "string")
|
|
50
76
|
return parseFriendlySchedule({ kind: "in", value: options.in });
|
|
51
77
|
if (typeof options.at === "string")
|
|
@@ -169,7 +195,13 @@ export async function runCronCli(argv = process.argv) {
|
|
|
169
195
|
.action((id, cronExprParts, options) => {
|
|
170
196
|
const store = createDefaultPiboCronStore({ path: program.opts().store });
|
|
171
197
|
const positionalCron = Array.isArray(cronExprParts) && cronExprParts.length ? cronExprParts.join(" ") : undefined;
|
|
172
|
-
|
|
198
|
+
let normalized = hasScheduleOptions(options, positionalCron) ? scheduleFromOptions(options, positionalCron) : undefined;
|
|
199
|
+
if (!normalized && typeof options.tz === "string") {
|
|
200
|
+
const existing = store.getJob(id);
|
|
201
|
+
if (!existing)
|
|
202
|
+
throw new Error("Cron job not found");
|
|
203
|
+
normalized = scheduleWithTimezone(existing, options.tz);
|
|
204
|
+
}
|
|
173
205
|
const target = maybeTargetFromOptions(options);
|
|
174
206
|
const patch = {
|
|
175
207
|
...(options.name !== undefined ? { name: options.name } : {}),
|
package/dist/cron/store.js
CHANGED
|
@@ -144,7 +144,7 @@ export class PiboCronStore {
|
|
|
144
144
|
runningAt: existing.state.runningAt,
|
|
145
145
|
nextRunAt: next.enabled ? computeNextRunAt(next.schedule, now)?.toISOString() : undefined,
|
|
146
146
|
};
|
|
147
|
-
if (next.enabled && !next.state.nextRunAt
|
|
147
|
+
if (next.enabled && !next.state.nextRunAt)
|
|
148
148
|
throw new Error("schedule has no future run");
|
|
149
149
|
this.writeJob(next);
|
|
150
150
|
return this.getJob(id);
|
package/dist/data/cli.js
CHANGED
|
@@ -86,15 +86,19 @@ function migrateSessionsToV2(input) {
|
|
|
86
86
|
if (!report.inputExists)
|
|
87
87
|
return report;
|
|
88
88
|
const source = new DatabaseSync(input.from, { readOnly: true });
|
|
89
|
-
|
|
89
|
+
let target;
|
|
90
90
|
try {
|
|
91
|
-
if (!hasTable(source, "pibo_sessions"))
|
|
92
|
-
|
|
91
|
+
if (!hasTable(source, "pibo_sessions")) {
|
|
92
|
+
throw new Error(`Cannot migrate sessions from "${input.from}": required legacy table "pibo_sessions" is missing.`);
|
|
93
|
+
}
|
|
94
|
+
target = new PiboDataStore(input.to);
|
|
93
95
|
const rows = source.prepare("SELECT * FROM pibo_sessions ORDER BY created_at ASC").all();
|
|
94
96
|
report.read = rows.length;
|
|
95
97
|
for (const row of rows) {
|
|
96
98
|
const existing = target.db.prepare("SELECT updated_at FROM sessions WHERE id = ?").get(row.id);
|
|
97
99
|
const metadata = parseJsonObject(row.metadata_json);
|
|
100
|
+
let migrateBinding = false;
|
|
101
|
+
const roomId = typeof metadata.chatRoomId === "string" ? metadata.chatRoomId : null;
|
|
98
102
|
const rootSessionId = row.parent_id ? (typeof metadata.rootSessionId === "string" ? metadata.rootSessionId : row.parent_id) : row.id;
|
|
99
103
|
if (!existing) {
|
|
100
104
|
const columns = [
|
|
@@ -105,22 +109,26 @@ function migrateSessionsToV2(input) {
|
|
|
105
109
|
target.db.prepare(`
|
|
106
110
|
INSERT INTO sessions (${columns.join(", ")})
|
|
107
111
|
VALUES (${columns.map(() => "?").join(", ")})
|
|
108
|
-
`).run(row.id, row.pi_session_id,
|
|
112
|
+
`).run(row.id, row.pi_session_id, roomId, rootSessionId, row.parent_id, row.origin_id, row.channel, row.kind, row.profile, row.active_model_json, row.workspace, row.title ?? "Untitled Session", "idle", JSON.stringify(metadata), row.created_at, row.updated_at, row.updated_at);
|
|
109
113
|
report.inserted++;
|
|
114
|
+
migrateBinding = true;
|
|
110
115
|
}
|
|
111
116
|
else if (row.updated_at > existing.updated_at) {
|
|
112
117
|
target.db.prepare(`
|
|
113
118
|
UPDATE sessions SET
|
|
114
|
-
pi_session_id = ?, root_session_id = ?, parent_id = ?, origin_id = ?,
|
|
119
|
+
pi_session_id = ?, room_id = ?, root_session_id = ?, parent_id = ?, origin_id = ?,
|
|
115
120
|
channel = ?, kind = ?, profile = ?, active_model_json = ?, workspace = ?, title = ?,
|
|
116
121
|
metadata_json = ?, updated_at = ?, last_activity_at = MAX(last_activity_at, ?)
|
|
117
122
|
WHERE id = ?
|
|
118
|
-
`).run(row.pi_session_id, rootSessionId, row.parent_id, row.origin_id, row.channel, row.kind, row.profile, row.active_model_json, row.workspace, row.title ?? "Untitled Session", JSON.stringify(metadata), row.updated_at, row.updated_at, row.id);
|
|
123
|
+
`).run(row.pi_session_id, roomId, rootSessionId, row.parent_id, row.origin_id, row.channel, row.kind, row.profile, row.active_model_json, row.workspace, row.title ?? "Untitled Session", JSON.stringify(metadata), row.updated_at, row.updated_at, row.id);
|
|
119
124
|
report.updated++;
|
|
125
|
+
migrateBinding = true;
|
|
120
126
|
}
|
|
121
127
|
else {
|
|
122
128
|
report.skipped++;
|
|
123
129
|
}
|
|
130
|
+
if (!migrateBinding)
|
|
131
|
+
continue;
|
|
124
132
|
target.db.prepare(`
|
|
125
133
|
INSERT INTO session_runtime_bindings (
|
|
126
134
|
pibo_session_id, runtime_instance_id, runtime_adapter_id, native_session_id,
|
|
@@ -142,7 +150,7 @@ function migrateSessionsToV2(input) {
|
|
|
142
150
|
}
|
|
143
151
|
finally {
|
|
144
152
|
source.close();
|
|
145
|
-
target
|
|
153
|
+
target?.close();
|
|
146
154
|
}
|
|
147
155
|
return report;
|
|
148
156
|
}
|
|
@@ -4,6 +4,22 @@ import { closeSync, existsSync, fstatSync, mkdirSync, openSync, readFileSync, re
|
|
|
4
4
|
import { dirname, extname, join, resolve } from "node:path";
|
|
5
5
|
import { piboHomePath } from "../core/pibo-home.js";
|
|
6
6
|
const MAX_SYNC_PAYLOAD_GZIP_BYTES = 512 * 1024;
|
|
7
|
+
export class PiboPayloadMetadataConflictError extends Error {
|
|
8
|
+
sha256;
|
|
9
|
+
existingContentType;
|
|
10
|
+
requestedContentType;
|
|
11
|
+
existingRetentionClass;
|
|
12
|
+
requestedRetentionClass;
|
|
13
|
+
constructor(sha256, existingContentType, requestedContentType, existingRetentionClass, requestedRetentionClass) {
|
|
14
|
+
super(`Payload bytes already exist with incompatible metadata: content type ${existingContentType} vs ${requestedContentType}; retention class ${existingRetentionClass} vs ${requestedRetentionClass}`);
|
|
15
|
+
this.sha256 = sha256;
|
|
16
|
+
this.existingContentType = existingContentType;
|
|
17
|
+
this.requestedContentType = requestedContentType;
|
|
18
|
+
this.existingRetentionClass = existingRetentionClass;
|
|
19
|
+
this.requestedRetentionClass = requestedRetentionClass;
|
|
20
|
+
this.name = "PiboPayloadMetadataConflictError";
|
|
21
|
+
}
|
|
22
|
+
}
|
|
7
23
|
export class PayloadStore {
|
|
8
24
|
db;
|
|
9
25
|
rootDir;
|
|
@@ -18,7 +34,7 @@ export class PayloadStore {
|
|
|
18
34
|
const createdAt = input.createdAt ?? new Date().toISOString();
|
|
19
35
|
const bytes = payloadToBytes(input.value, contentType);
|
|
20
36
|
const sha256 = createHash("sha256").update(bytes).digest("hex");
|
|
21
|
-
const existing = this.
|
|
37
|
+
const existing = this.findByIdentity(sha256, contentType, input.retentionClass);
|
|
22
38
|
if (existing) {
|
|
23
39
|
this.db.prepare("UPDATE payloads SET ref_count = ref_count + 1 WHERE id = ?").run(existing.id);
|
|
24
40
|
return this.getPayload(existing.id) ?? existing;
|
|
@@ -27,7 +43,7 @@ export class PayloadStore {
|
|
|
27
43
|
const encoding = shouldCompress ? "gzip" : "identity";
|
|
28
44
|
const bytesToStore = shouldCompress ? gzipSync(bytes) : bytes;
|
|
29
45
|
const compressedByteSize = shouldCompress ? bytesToStore.byteLength : null;
|
|
30
|
-
const relativePath = buildRelativePayloadPath(sha256, contentType, encoding);
|
|
46
|
+
const relativePath = buildRelativePayloadPath(sha256, contentType, input.retentionClass, encoding);
|
|
31
47
|
const absolutePath = this.rootDir === ":memory:" ? relativePath : join(this.rootDir, relativePath);
|
|
32
48
|
writePayloadFile(absolutePath, bytesToStore);
|
|
33
49
|
const id = input.id ?? `payload_${randomUUID()}`;
|
|
@@ -108,9 +124,35 @@ export class PayloadStore {
|
|
|
108
124
|
return JSON.parse(Buffer.from(this.readPayloadBytesBounded(id, maxBytes)).toString("utf8"));
|
|
109
125
|
}
|
|
110
126
|
findBySha256(sha256) {
|
|
111
|
-
const row = this.db.prepare("SELECT * FROM payloads WHERE sha256 = ?").get(sha256);
|
|
127
|
+
const row = this.db.prepare("SELECT * FROM payloads WHERE sha256 = ? ORDER BY created_at ASC, id ASC LIMIT 1").get(sha256);
|
|
128
|
+
return row ? payloadFromRow(row) : undefined;
|
|
129
|
+
}
|
|
130
|
+
findByIdentity(sha256, contentType, retentionClass) {
|
|
131
|
+
const row = this.db.prepare(`
|
|
132
|
+
SELECT * FROM payloads
|
|
133
|
+
WHERE sha256 = ? AND content_type = ? AND retention_class = ?
|
|
134
|
+
`).get(sha256, contentType, retentionClass);
|
|
112
135
|
return row ? payloadFromRow(row) : undefined;
|
|
113
136
|
}
|
|
137
|
+
releaseReferences(id, count = 1) {
|
|
138
|
+
if (!Number.isSafeInteger(count) || count < 1)
|
|
139
|
+
throw new RangeError("count must be a positive safe integer");
|
|
140
|
+
const row = this.db.prepare("SELECT * FROM payloads WHERE id = ?").get(id);
|
|
141
|
+
if (!row)
|
|
142
|
+
return undefined;
|
|
143
|
+
if (row.ref_count > count) {
|
|
144
|
+
this.db.prepare("UPDATE payloads SET ref_count = ref_count - ? WHERE id = ?").run(count, id);
|
|
145
|
+
return undefined;
|
|
146
|
+
}
|
|
147
|
+
this.db.prepare("DELETE FROM payloads WHERE id = ?").run(id);
|
|
148
|
+
return payloadFromRow(row);
|
|
149
|
+
}
|
|
150
|
+
removeReleasedFile(payload) {
|
|
151
|
+
if (payload.storageKind !== "file" || !payload.storagePath)
|
|
152
|
+
return;
|
|
153
|
+
const absolutePath = this.rootDir === ":memory:" ? payload.storagePath : join(this.rootDir, payload.storagePath);
|
|
154
|
+
rmSync(absolutePath, { force: true });
|
|
155
|
+
}
|
|
114
156
|
}
|
|
115
157
|
function readFileBounded(path, maxBytes) {
|
|
116
158
|
const descriptor = openSync(path, "r");
|
|
@@ -147,12 +189,12 @@ function defaultContentType(value) {
|
|
|
147
189
|
return "application/json";
|
|
148
190
|
}
|
|
149
191
|
function payloadToBytes(value, contentType) {
|
|
150
|
-
if (typeof value === "string")
|
|
151
|
-
return Buffer.from(value, "utf8");
|
|
152
192
|
if (value instanceof Uint8Array)
|
|
153
193
|
return value;
|
|
154
194
|
if (contentType.includes("json"))
|
|
155
195
|
return Buffer.from(JSON.stringify(value), "utf8");
|
|
196
|
+
if (typeof value === "string")
|
|
197
|
+
return Buffer.from(value, "utf8");
|
|
156
198
|
return Buffer.from(String(value), "utf8");
|
|
157
199
|
}
|
|
158
200
|
function previewTextFromValue(value) {
|
|
@@ -162,10 +204,16 @@ function previewTextFromValue(value) {
|
|
|
162
204
|
const normalized = text.replace(/\s+/g, " ").trim();
|
|
163
205
|
return normalized ? normalized.slice(0, 1024) : undefined;
|
|
164
206
|
}
|
|
165
|
-
function buildRelativePayloadPath(sha256, contentType, encoding) {
|
|
207
|
+
function buildRelativePayloadPath(sha256, contentType, retentionClass, encoding) {
|
|
166
208
|
const extension = extensionForContentType(contentType);
|
|
167
209
|
const suffix = encoding === "gzip" ? `${extension}.gz` : extension;
|
|
168
|
-
|
|
210
|
+
const metadataHash = createHash("sha256")
|
|
211
|
+
.update(contentType)
|
|
212
|
+
.update("\0")
|
|
213
|
+
.update(retentionClass)
|
|
214
|
+
.digest("hex")
|
|
215
|
+
.slice(0, 16);
|
|
216
|
+
return join("sha256", sha256.slice(0, 2), sha256.slice(2, 4), `${sha256}.${metadataHash}.${suffix}`);
|
|
169
217
|
}
|
|
170
218
|
function extensionForContentType(contentType) {
|
|
171
219
|
if (contentType.includes("json"))
|
package/dist/data/schema.js
CHANGED
|
@@ -1,5 +1,27 @@
|
|
|
1
|
-
export const PIBO_DATA_SCHEMA_VERSION =
|
|
1
|
+
export const PIBO_DATA_SCHEMA_VERSION = 8;
|
|
2
|
+
const NATIVE_HISTORY_FALLBACK_SCHEMA_VERSION = 5;
|
|
2
3
|
const retiredScopeColumn = ["owner", "scope"].join("_");
|
|
4
|
+
const payloadTableDefinition = `
|
|
5
|
+
id TEXT PRIMARY KEY,
|
|
6
|
+
sha256 TEXT NOT NULL,
|
|
7
|
+
storage_kind TEXT NOT NULL,
|
|
8
|
+
storage_path TEXT,
|
|
9
|
+
content_type TEXT NOT NULL,
|
|
10
|
+
encoding TEXT NOT NULL DEFAULT 'gzip',
|
|
11
|
+
byte_size INTEGER NOT NULL,
|
|
12
|
+
compressed_byte_size INTEGER,
|
|
13
|
+
preview_text TEXT,
|
|
14
|
+
retention_class TEXT NOT NULL,
|
|
15
|
+
ref_count INTEGER NOT NULL DEFAULT 0,
|
|
16
|
+
status TEXT NOT NULL DEFAULT 'committed',
|
|
17
|
+
created_at TEXT NOT NULL,
|
|
18
|
+
last_verified_at TEXT
|
|
19
|
+
`;
|
|
20
|
+
const payloadTableColumns = [
|
|
21
|
+
"id", "sha256", "storage_kind", "storage_path", "content_type", "encoding",
|
|
22
|
+
"byte_size", "compressed_byte_size", "preview_text", "retention_class", "ref_count",
|
|
23
|
+
"status", "created_at", "last_verified_at",
|
|
24
|
+
];
|
|
3
25
|
const retiredScopeTables = [
|
|
4
26
|
{
|
|
5
27
|
name: "sessions",
|
|
@@ -92,6 +114,26 @@ function rebuildRetiredScopeTables(db, tablesToRebuild) {
|
|
|
92
114
|
`);
|
|
93
115
|
}
|
|
94
116
|
}
|
|
117
|
+
function payloadTableNeedsMetadataIdentityRebuild(db) {
|
|
118
|
+
const table = db.prepare("SELECT 1 FROM sqlite_schema WHERE type = 'table' AND name = 'payloads'").get();
|
|
119
|
+
if (!table)
|
|
120
|
+
return false;
|
|
121
|
+
const indexes = db.prepare("SELECT name FROM pragma_index_list('payloads') WHERE \"unique\" = 1").all();
|
|
122
|
+
return indexes.some((index) => {
|
|
123
|
+
const columns = db.prepare("SELECT name FROM pragma_index_info(?) ORDER BY seqno").all(index.name);
|
|
124
|
+
return columns.length === 1 && columns[0]?.name === "sha256";
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
function rebuildPayloadTableForMetadataIdentity(db) {
|
|
128
|
+
const columns = payloadTableColumns.join(", ");
|
|
129
|
+
db.exec(`
|
|
130
|
+
DROP TABLE IF EXISTS __pibo_schema_v8_payloads;
|
|
131
|
+
CREATE TABLE __pibo_schema_v8_payloads (${payloadTableDefinition});
|
|
132
|
+
INSERT INTO __pibo_schema_v8_payloads (${columns}) SELECT ${columns} FROM payloads;
|
|
133
|
+
DROP TABLE payloads;
|
|
134
|
+
ALTER TABLE __pibo_schema_v8_payloads RENAME TO payloads;
|
|
135
|
+
`);
|
|
136
|
+
}
|
|
95
137
|
export function assertSupportedPiboDataSchemaVersion(db) {
|
|
96
138
|
const version = Number(db.prepare("PRAGMA user_version").get()?.user_version ?? 0);
|
|
97
139
|
if (version > PIBO_DATA_SCHEMA_VERSION) {
|
|
@@ -100,6 +142,7 @@ export function assertSupportedPiboDataSchemaVersion(db) {
|
|
|
100
142
|
return version;
|
|
101
143
|
}
|
|
102
144
|
export const PIBO_DATA_SCHEMA_MIGRATION_STEPS = [
|
|
145
|
+
"payload-metadata-identity",
|
|
103
146
|
"schema",
|
|
104
147
|
"runtime-bindings",
|
|
105
148
|
"render-high-water",
|
|
@@ -113,20 +156,22 @@ export const PIBO_DATA_SCHEMA_MIGRATION_STEPS = [
|
|
|
113
156
|
export function applyPiboDataSchema(db, hooks = {}) {
|
|
114
157
|
const previousVersion = assertSupportedPiboDataSchemaVersion(db);
|
|
115
158
|
const tablesToRebuild = retiredScopeTablesToRebuild(db);
|
|
159
|
+
const rebuildPayloadTable = payloadTableNeedsMetadataIdentityRebuild(db);
|
|
160
|
+
const requiresTableRebuild = tablesToRebuild.length > 0 || rebuildPayloadTable;
|
|
116
161
|
const ownsTransaction = !db.isTransaction;
|
|
117
|
-
if (!ownsTransaction &&
|
|
162
|
+
if (!ownsTransaction && requiresTableRebuild) {
|
|
118
163
|
throw new Error("Pibo data schema migration requires an independent transaction");
|
|
119
164
|
}
|
|
120
165
|
const foreignKeysEnabled = ownsTransaction
|
|
121
|
-
&&
|
|
166
|
+
&& requiresTableRebuild
|
|
122
167
|
&& Number(db.prepare("PRAGMA foreign_keys").get().foreign_keys ?? 0) === 1;
|
|
123
168
|
if (foreignKeysEnabled)
|
|
124
169
|
db.exec("PRAGMA foreign_keys = OFF");
|
|
125
170
|
try {
|
|
126
171
|
if (ownsTransaction)
|
|
127
172
|
db.exec("BEGIN IMMEDIATE");
|
|
128
|
-
applyPiboDataSchemaInTransaction(db, hooks, previousVersion, tablesToRebuild);
|
|
129
|
-
if (
|
|
173
|
+
applyPiboDataSchemaInTransaction(db, hooks, previousVersion, tablesToRebuild, rebuildPayloadTable);
|
|
174
|
+
if (requiresTableRebuild) {
|
|
130
175
|
const violations = db.prepare("PRAGMA foreign_key_check").all();
|
|
131
176
|
if (violations.length > 0) {
|
|
132
177
|
throw new Error(`Pibo data schema migration would retain ${violations.length} foreign-key violation(s)`);
|
|
@@ -145,11 +190,14 @@ export function applyPiboDataSchema(db, hooks = {}) {
|
|
|
145
190
|
db.exec("PRAGMA foreign_keys = ON");
|
|
146
191
|
}
|
|
147
192
|
}
|
|
148
|
-
function applyPiboDataSchemaInTransaction(db, hooks, previousVersion, tablesToRebuild) {
|
|
193
|
+
function applyPiboDataSchemaInTransaction(db, hooks, previousVersion, tablesToRebuild, rebuildPayloadTable) {
|
|
149
194
|
const existingSessionCount = db.prepare("SELECT COUNT(*) AS count FROM sqlite_schema WHERE type = 'table' AND name = 'sessions'").get();
|
|
150
195
|
const hadSessionsBeforeMigration = existingSessionCount.count > 0
|
|
151
196
|
&& Number(db.prepare("SELECT COUNT(*) AS count FROM sessions").get().count) > 0;
|
|
152
197
|
rebuildRetiredScopeTables(db, tablesToRebuild);
|
|
198
|
+
if (rebuildPayloadTable)
|
|
199
|
+
rebuildPayloadTableForMetadataIdentity(db);
|
|
200
|
+
hooks.afterStep?.("payload-metadata-identity");
|
|
153
201
|
db.exec(`
|
|
154
202
|
CREATE TABLE IF NOT EXISTS sessions (
|
|
155
203
|
id TEXT PRIMARY KEY,
|
|
@@ -199,6 +247,13 @@ function applyPiboDataSchemaInTransaction(db, hooks, previousVersion, tablesToRe
|
|
|
199
247
|
FOREIGN KEY (pibo_session_id) REFERENCES sessions(id) ON DELETE CASCADE
|
|
200
248
|
);
|
|
201
249
|
|
|
250
|
+
CREATE TABLE IF NOT EXISTS session_agent_observation_counters (
|
|
251
|
+
parent_pibo_session_id TEXT PRIMARY KEY,
|
|
252
|
+
next_sequence INTEGER NOT NULL CHECK(next_sequence >= 1),
|
|
253
|
+
updated_at TEXT NOT NULL,
|
|
254
|
+
FOREIGN KEY (parent_pibo_session_id) REFERENCES sessions(id) ON DELETE CASCADE
|
|
255
|
+
);
|
|
256
|
+
|
|
202
257
|
CREATE TABLE IF NOT EXISTS session_output_part_counters (
|
|
203
258
|
pibo_session_id TEXT NOT NULL,
|
|
204
259
|
event_id TEXT NOT NULL,
|
|
@@ -292,22 +347,9 @@ function applyPiboDataSchemaInTransaction(db, hooks, previousVersion, tablesToRe
|
|
|
292
347
|
);
|
|
293
348
|
|
|
294
349
|
|
|
295
|
-
CREATE TABLE IF NOT EXISTS payloads (
|
|
296
|
-
|
|
297
|
-
sha256
|
|
298
|
-
storage_kind TEXT NOT NULL,
|
|
299
|
-
storage_path TEXT,
|
|
300
|
-
content_type TEXT NOT NULL,
|
|
301
|
-
encoding TEXT NOT NULL DEFAULT 'gzip',
|
|
302
|
-
byte_size INTEGER NOT NULL,
|
|
303
|
-
compressed_byte_size INTEGER,
|
|
304
|
-
preview_text TEXT,
|
|
305
|
-
retention_class TEXT NOT NULL,
|
|
306
|
-
ref_count INTEGER NOT NULL DEFAULT 0,
|
|
307
|
-
status TEXT NOT NULL DEFAULT 'committed',
|
|
308
|
-
created_at TEXT NOT NULL,
|
|
309
|
-
last_verified_at TEXT
|
|
310
|
-
);
|
|
350
|
+
CREATE TABLE IF NOT EXISTS payloads (${payloadTableDefinition});
|
|
351
|
+
CREATE UNIQUE INDEX IF NOT EXISTS idx_payloads_identity
|
|
352
|
+
ON payloads(sha256, content_type, retention_class);
|
|
311
353
|
|
|
312
354
|
CREATE TABLE IF NOT EXISTS event_log (
|
|
313
355
|
stream_id INTEGER PRIMARY KEY,
|
|
@@ -784,7 +826,7 @@ function applyPiboDataSchemaInTransaction(db, hooks, previousVersion, tablesToRe
|
|
|
784
826
|
hooks.afterStep?.("sequence-repair-backfill");
|
|
785
827
|
db.exec("DROP TABLE pibo_v7_sequence_repair_sessions");
|
|
786
828
|
hooks.afterStep?.("sequence-repair-cleanup");
|
|
787
|
-
if (previousVersion <
|
|
829
|
+
if (previousVersion < NATIVE_HISTORY_FALLBACK_SCHEMA_VERSION && hadSessionsBeforeMigration) {
|
|
788
830
|
const rows = db.prepare("SELECT pibo_session_id, metadata_json FROM session_runtime_bindings").all();
|
|
789
831
|
const update = db.prepare("UPDATE session_runtime_bindings SET metadata_json = ? WHERE pibo_session_id = ?");
|
|
790
832
|
for (const row of rows) {
|
package/dist/debug/index.js
CHANGED
|
@@ -322,6 +322,11 @@ async function runDebugDb(args) {
|
|
|
322
322
|
const command = args[0];
|
|
323
323
|
const options = parseOptions(args.slice(1));
|
|
324
324
|
if (command === "stores") {
|
|
325
|
+
const unknownOption = options.positionals.find((value) => value.startsWith("-"));
|
|
326
|
+
if (unknownOption)
|
|
327
|
+
throw new Error(`Unknown option "${unknownOption}" for pibo debug db stores. Run pibo debug db --help.`);
|
|
328
|
+
if (options.positionals.length > 0)
|
|
329
|
+
throw new Error("pibo debug db stores accepts no positional arguments. Run pibo debug db --help.");
|
|
325
330
|
const stores = resolveDebugStores();
|
|
326
331
|
if (options.json) {
|
|
327
332
|
console.log(JSON.stringify({ stores }, null, 2));
|
package/dist/debug/pty.js
CHANGED
|
@@ -96,6 +96,26 @@ if exit_code is None:
|
|
|
96
96
|
exit_code = proc.wait(timeout=1)
|
|
97
97
|
sys.exit(exit_code if exit_code is not None else 1)
|
|
98
98
|
`;
|
|
99
|
+
const PTY_SCENARIO_FIELDS = new Set([
|
|
100
|
+
"name",
|
|
101
|
+
"command",
|
|
102
|
+
"cwd",
|
|
103
|
+
"workdir",
|
|
104
|
+
"env",
|
|
105
|
+
"rows",
|
|
106
|
+
"cols",
|
|
107
|
+
"timeoutMs",
|
|
108
|
+
"idleTimeoutMs",
|
|
109
|
+
"inputDelayMs",
|
|
110
|
+
"providerMode",
|
|
111
|
+
"maxIterations",
|
|
112
|
+
"artifactDir",
|
|
113
|
+
"artifact",
|
|
114
|
+
"steps",
|
|
115
|
+
"expect",
|
|
116
|
+
"reject",
|
|
117
|
+
"stopPatterns",
|
|
118
|
+
]);
|
|
99
119
|
class WallClockTimeoutError extends Error {
|
|
100
120
|
constructor(timeoutMs) {
|
|
101
121
|
super(`PTY command timed out after ${timeoutMs}ms`);
|
|
@@ -234,17 +254,17 @@ function parsePtyOptions(args) {
|
|
|
234
254
|
else if (arg === "--env")
|
|
235
255
|
options.env.push(requireOptionValue(args, ++index, arg));
|
|
236
256
|
else if (arg === "--expect")
|
|
237
|
-
options.expect.push(
|
|
257
|
+
options.expect.push(requireTextOptionValue(args, ++index, arg));
|
|
238
258
|
else if (arg === "--reject")
|
|
239
|
-
options.reject.push(
|
|
259
|
+
options.reject.push(requireTextOptionValue(args, ++index, arg));
|
|
240
260
|
else if (arg === "--stop-pattern")
|
|
241
|
-
options.stopPatterns.push(
|
|
261
|
+
options.stopPatterns.push(requireTextOptionValue(args, ++index, arg));
|
|
242
262
|
else if (arg === "--type")
|
|
243
|
-
options.steps.push({ typeText:
|
|
263
|
+
options.steps.push({ typeText: requireTextOptionValue(args, ++index, arg) });
|
|
244
264
|
else if (arg === "--press")
|
|
245
265
|
options.steps.push({ press: requireOptionValue(args, ++index, arg) });
|
|
246
266
|
else if (arg === "--wait-for")
|
|
247
|
-
options.steps.push({ waitFor:
|
|
267
|
+
options.steps.push({ waitFor: requireTextOptionValue(args, ++index, arg) });
|
|
248
268
|
else if (arg === "--sleep-ms")
|
|
249
269
|
options.steps.push({ sleepMs: parseNonNegativeInteger(requireOptionValue(args, ++index, arg), arg) });
|
|
250
270
|
else if (arg === "--builtin")
|
|
@@ -269,6 +289,12 @@ function requireOptionValue(args, index, option) {
|
|
|
269
289
|
throw new Error(`${option} requires a value`);
|
|
270
290
|
return value;
|
|
271
291
|
}
|
|
292
|
+
function requireTextOptionValue(args, index, option) {
|
|
293
|
+
const value = args[index];
|
|
294
|
+
if (value === undefined)
|
|
295
|
+
throw new Error(`${option} requires a value`);
|
|
296
|
+
return value;
|
|
297
|
+
}
|
|
272
298
|
function scenarioFromRunOptions(options) {
|
|
273
299
|
return {
|
|
274
300
|
name: options.name ?? "adhoc-run",
|
|
@@ -363,6 +389,10 @@ function validateScenario(value, source) {
|
|
|
363
389
|
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
364
390
|
throw new Error(`${source}: scenario must be an object`);
|
|
365
391
|
const raw = value;
|
|
392
|
+
for (const field of Object.keys(raw)) {
|
|
393
|
+
if (!PTY_SCENARIO_FIELDS.has(field))
|
|
394
|
+
throw new Error(`${source}: unknown field "${field}"`);
|
|
395
|
+
}
|
|
366
396
|
if (!Array.isArray(raw.command) || raw.command.some((item) => typeof item !== "string") || raw.command.length === 0) {
|
|
367
397
|
throw new Error(`${source}: command must be a non-empty string array`);
|
|
368
398
|
}
|
|
@@ -425,6 +455,7 @@ async function executePtyScenario(input, options) {
|
|
|
425
455
|
let stopReason = "completed";
|
|
426
456
|
let exitCode = null;
|
|
427
457
|
let signal = null;
|
|
458
|
+
const waitCursor = { cleanOffset: 0 };
|
|
428
459
|
try {
|
|
429
460
|
validateProviderSafety(scenario, options);
|
|
430
461
|
runner = await startRunner(scenario);
|
|
@@ -449,7 +480,7 @@ async function executePtyScenario(input, options) {
|
|
|
449
480
|
}
|
|
450
481
|
}
|
|
451
482
|
await checkIdle(runner, refreshOutputTimestamp, scenario.idleTimeoutMs);
|
|
452
|
-
await runStep(runner, scenario, step, assertions, refreshOutputTimestamp, deadline);
|
|
483
|
+
await runStep(runner, scenario, step, assertions, refreshOutputTimestamp, deadline, waitCursor);
|
|
453
484
|
throwIfDeadlineExpired(deadline);
|
|
454
485
|
refreshOutputTimestamp();
|
|
455
486
|
const clean = cleanTerminalText(runner.getRawOutput());
|
|
@@ -667,9 +698,9 @@ function wrapChild(child, backend, ptyMethod) {
|
|
|
667
698
|
getEvents: () => events,
|
|
668
699
|
};
|
|
669
700
|
}
|
|
670
|
-
async function runStep(runner, scenario, step, assertions, markOutput, deadline) {
|
|
701
|
+
async function runStep(runner, scenario, step, assertions, markOutput, deadline, waitCursor) {
|
|
671
702
|
if (step.waitFor !== undefined) {
|
|
672
|
-
await waitForText(runner, step.waitFor, step.timeoutMs ?? scenario.timeoutMs, scenario.idleTimeoutMs, markOutput, deadline);
|
|
703
|
+
await waitForText(runner, step.waitFor, step.timeoutMs ?? scenario.timeoutMs, scenario.idleTimeoutMs, markOutput, deadline, waitCursor);
|
|
673
704
|
return;
|
|
674
705
|
}
|
|
675
706
|
if (step.typeText !== undefined) {
|
|
@@ -706,13 +737,17 @@ async function runStep(runner, scenario, step, assertions, markOutput, deadline)
|
|
|
706
737
|
if (step.reject !== undefined)
|
|
707
738
|
assertPatterns(clean, [], [step.reject], assertions);
|
|
708
739
|
}
|
|
709
|
-
async function waitForText(runner, pattern, timeoutMs, idleTimeoutMs, markOutput, globalDeadline) {
|
|
740
|
+
async function waitForText(runner, pattern, timeoutMs, idleTimeoutMs, markOutput, globalDeadline, cursor) {
|
|
710
741
|
const stepDeadline = performance.now() + timeoutMs;
|
|
711
742
|
while (true) {
|
|
712
743
|
throwIfDeadlineExpired(globalDeadline);
|
|
713
744
|
const lastOutputAt = markOutput();
|
|
714
|
-
|
|
745
|
+
const clean = cleanTerminalText(runner.getRawOutput());
|
|
746
|
+
const matchIndex = clean.indexOf(pattern, Math.min(cursor.cleanOffset, clean.length));
|
|
747
|
+
if (matchIndex >= 0) {
|
|
748
|
+
cursor.cleanOffset = matchIndex + pattern.length;
|
|
715
749
|
return;
|
|
750
|
+
}
|
|
716
751
|
const now = performance.now();
|
|
717
752
|
if (now - lastOutputAt > idleTimeoutMs) {
|
|
718
753
|
await runner.terminate("idle_timeout");
|
package/dist/gateway/cli.js
CHANGED
|
@@ -52,7 +52,19 @@ function expectedMode(target) {
|
|
|
52
52
|
}
|
|
53
53
|
function gatewayServiceName(target) {
|
|
54
54
|
const fromEnv = target === "web" ? process.env.PIBO_GATEWAY_WEB_SERVICE : process.env.PIBO_GATEWAY_DEV_SERVICE;
|
|
55
|
-
|
|
55
|
+
if (fromEnv)
|
|
56
|
+
return fromEnv;
|
|
57
|
+
if (target === "web") {
|
|
58
|
+
try {
|
|
59
|
+
const persisted = readFileSync(join(managedGatewayHome(target), "gateway-web-service"), "utf8").trim();
|
|
60
|
+
if (/^[A-Za-z0-9_.@-]+$/.test(persisted))
|
|
61
|
+
return persisted;
|
|
62
|
+
}
|
|
63
|
+
catch {
|
|
64
|
+
// Fall back to the default service name when setup has not persisted an override.
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
return target === "web" ? "pibo-web" : "pibo-web-dev";
|
|
56
68
|
}
|
|
57
69
|
function gatewayManagerCommand() {
|
|
58
70
|
return process.env.PIBO_GATEWAY_MANAGER_COMMAND || "systemctl";
|
|
@@ -62,7 +74,11 @@ function shouldUseWindowsGatewayManager() {
|
|
|
62
74
|
}
|
|
63
75
|
function managedGatewayHome(target) {
|
|
64
76
|
const fromEnv = target === "web" ? process.env.PIBO_GATEWAY_WEB_HOME : process.env.PIBO_GATEWAY_DEV_HOME;
|
|
65
|
-
|
|
77
|
+
if (fromEnv)
|
|
78
|
+
return fromEnv;
|
|
79
|
+
if (target === "web" && process.env.PIBO_HOME)
|
|
80
|
+
return process.env.PIBO_HOME;
|
|
81
|
+
return join(homedir(), target === "web" ? ".pibo" : ".pibo-dev");
|
|
66
82
|
}
|
|
67
83
|
function targetGatewayPort(target) {
|
|
68
84
|
const fromEnv = target === "web" ? process.env.PIBO_GATEWAY_WEB_AGENT_PORT : process.env.PIBO_GATEWAY_DEV_AGENT_PORT;
|
package/dist/gateway/server.js
CHANGED
|
@@ -159,6 +159,7 @@ export class PiboGatewayServer {
|
|
|
159
159
|
&& (this.options.persistSession !== false || hasExplicitPersistentStore);
|
|
160
160
|
this.router = new PiboSessionRouter({
|
|
161
161
|
persistSession: this.options.persistSession,
|
|
162
|
+
piPackageStoreCwd: this.options.piPackageStoreCwd ?? process.cwd(),
|
|
162
163
|
pluginRegistry: this.pluginRegistry,
|
|
163
164
|
sessionStore: this.sessionStore,
|
|
164
165
|
messagePreflight: createLoopMessagePreflight({ path: this.options.loopStorePath }),
|