@pasko70/pibo 1.9.11 → 1.9.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +183 -183
- package/context/codex-base-prompt.md +148 -148
- package/context/compute-worker.md +23 -23
- package/context/pibo-compaction-prompt.md +100 -100
- package/context/pibo-native-tooling.md +18 -18
- package/context/pibo-system-prompt.md +77 -77
- package/dist/apps/chat/agent-store.js +248 -248
- package/dist/apps/chat/data/project-service.js +168 -168
- package/dist/apps/chat/data/read-state-service.js +18 -18
- package/dist/apps/chat/data/session-query-service.js +25 -25
- package/dist/apps/chat/data/timeline-query-service.js +25 -14
- package/dist/apps/chat/static-assets.js +854 -854
- package/dist/apps/chat/trace.js +2 -0
- package/dist/apps/chat/web-app.js +7 -0
- package/dist/apps/chat/workflow-persistence.js +255 -255
- package/dist/apps/chat-ui/index.html +16 -16
- package/dist/apps/chat-ui/manifest.webmanifest +25 -25
- package/dist/apps/chat-ui/sw.js +47 -47
- package/dist/apps/chat-vscode-web/index.html +12 -12
- package/dist/apps/cli-ui/cliSessionsCommand.js +23 -23
- package/dist/apps/context-files-ui/index.html +11 -11
- package/dist/apps/vscode-artifacts/latest.vsix +0 -0
- package/dist/apps/vscode-artifacts/pibo-vscode-ext-1.9.13.vsix +0 -0
- package/dist/cli.js +39 -39
- package/dist/compute/cli.js +54 -54
- package/dist/cron/cli.js +15 -15
- package/dist/cron/store.js +49 -49
- package/dist/data/cli.js +23 -23
- package/dist/data/event-log.js +23 -23
- package/dist/data/ingest-service.js +7 -0
- package/dist/data/message-store.js +31 -20
- package/dist/data/navigation-store.js +9 -9
- package/dist/data/observation-store.js +4 -4
- package/dist/data/payload-store.js +17 -17
- package/dist/data/schema.js +433 -431
- package/dist/data/session-store.js +4 -4
- package/dist/data/telemetry-queries.js +54 -54
- package/dist/data/telemetry.js +197 -197
- package/dist/debug/events.js +12 -12
- package/dist/debug/failures.js +6 -6
- package/dist/debug/index.js +227 -227
- package/dist/debug/messages.js +6 -6
- package/dist/debug/pty.js +124 -124
- package/dist/debug/session.js +29 -29
- package/dist/debug/tools.js +5 -5
- package/dist/debug/web-snapshot-browser-scripts.js +294 -294
- package/dist/debug/web-streaming-browser-library.js +925 -925
- package/dist/debug/web-streaming-browser-scripts.js +232 -232
- package/dist/debug/web-streaming-provider-telemetry.js +4 -4
- package/dist/debug/web.js +93 -93
- package/dist/gateway/cli.js +19 -19
- package/dist/mcp/config-command.js +53 -53
- package/dist/mcp/index.js +21 -21
- package/dist/mcp/registry.js +11 -11
- package/dist/pi-packages/cli.js +11 -11
- package/dist/plugins/context-files-store.js +110 -110
- package/dist/plugins/context-files.js +4 -4
- package/dist/ralph/cli.js +18 -18
- package/dist/ralph/templates.js +140 -140
- package/dist/reliability/store.js +226 -226
- package/dist/resources/lifecycle.js +4 -6
- package/dist/resources/reaper-state.js +30 -3
- package/dist/resources/reaper.js +43 -15
- package/dist/sessions/pibo-data-store.js +16 -16
- package/dist/sessions/sqlite-store.js +53 -53
- package/dist/setup/cli.js +58 -58
- package/dist/shared/trace-engine.js +3 -2
- package/dist/shared/trace-event-projection.js +26 -0
- package/dist/tools/agent-browser-wrapper.js +80 -80
- package/dist/tools/browser-use-cdp.js +12 -12
- package/dist/tools/browser-use-wrapper.js +762 -762
- package/dist/tools/guides.js +538 -538
- package/dist/tools/index.js +99 -99
- package/dist/tools/runtime/node-worker-source.js +205 -205
- package/dist/tools/runtime/python-worker-source.js +177 -177
- package/dist/vscode/cli.js +9 -9
- package/dist/web-annotations/cdp.js +900 -900
- package/dist/web-annotations/store.js +96 -96
- package/docs/README.md +23 -23
- package/docs/ops/install-developer-host.md +112 -112
- package/docs/ops/install-user-host.md +96 -96
- package/docs/ops/upgrade-user-to-developer-host.md +69 -69
- package/docs/ops/vscode-extension-release.md +160 -160
- package/package.json +95 -95
- package/skills/builtin/graphify/SKILL.md +52 -52
- package/skills/builtin/pi-agent-harness/SKILL.md +319 -319
- package/skills/builtin/pi-agent-harness/agents/openai.yaml +4 -4
- package/skills/builtin/pibo-docker-system/SKILL.md +170 -170
- package/skills/builtin/pibo-spec-writing/SKILL.md +330 -330
- package/skills/builtin/prd/SKILL.md +143 -143
- package/skills/builtin/ralph-loop/SKILL.md +359 -359
- package/skills/builtin/ralph-prd-json/SKILL.md +123 -123
- package/skills/builtin/skill-creator/LICENSE.txt +201 -201
- package/skills/builtin/skill-creator/SKILL.md +513 -513
- package/skills/builtin/skill-creator/agents/analyzer.md +274 -274
- package/skills/builtin/skill-creator/agents/comparator.md +202 -202
- package/skills/builtin/skill-creator/agents/grader.md +223 -223
- package/skills/builtin/skill-creator/assets/eval_review.html +146 -146
- package/skills/builtin/skill-creator/eval-viewer/generate_review.py +471 -471
- package/skills/builtin/skill-creator/eval-viewer/viewer.html +1325 -1325
- package/skills/builtin/skill-creator/references/schemas.md +430 -430
- package/skills/builtin/skill-creator/scripts/aggregate_benchmark.py +401 -401
- package/skills/builtin/skill-creator/scripts/generate_report.py +326 -326
- package/skills/builtin/skill-creator/scripts/improve_description.py +247 -247
- package/skills/builtin/skill-creator/scripts/package_skill.py +136 -136
- package/skills/builtin/skill-creator/scripts/quick_validate.py +102 -102
- package/skills/builtin/skill-creator/scripts/run_eval.py +310 -310
- package/skills/builtin/skill-creator/scripts/run_loop.py +328 -328
- package/skills/builtin/skill-creator/scripts/utils.py +47 -47
- package/skills/builtin/web-annotations/SKILL.md +93 -93
- package/src/mcp/LICENSE.mcp-cli +21 -21
package/dist/resources/reaper.js
CHANGED
|
@@ -9,6 +9,7 @@ export class ResourceReaperService {
|
|
|
9
9
|
plan;
|
|
10
10
|
apply;
|
|
11
11
|
now;
|
|
12
|
+
writeState;
|
|
12
13
|
timer;
|
|
13
14
|
running = false;
|
|
14
15
|
stopped = true;
|
|
@@ -23,6 +24,7 @@ export class ResourceReaperService {
|
|
|
23
24
|
this.plan = options.plan ?? planResourceReap;
|
|
24
25
|
this.apply = options.apply ?? applyResourceReapPlan;
|
|
25
26
|
this.now = options.clock ?? (() => new Date());
|
|
27
|
+
this.writeState = options.writeState ?? writeResourceReaperState;
|
|
26
28
|
}
|
|
27
29
|
async start() {
|
|
28
30
|
if (!this.stopped)
|
|
@@ -47,19 +49,24 @@ export class ResourceReaperService {
|
|
|
47
49
|
if (this.timer)
|
|
48
50
|
clearTimeout(this.timer);
|
|
49
51
|
this.timer = undefined;
|
|
50
|
-
|
|
51
|
-
this.state
|
|
52
|
-
|
|
52
|
+
try {
|
|
53
|
+
if (this.state && this.ownsTimer) {
|
|
54
|
+
this.state = { ...this.state, status: "stopped", nextRunAt: undefined };
|
|
55
|
+
await this.persist();
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
finally {
|
|
59
|
+
if (this.ownsTimer)
|
|
60
|
+
await releaseResourceReaperOwnership(this.lockPath);
|
|
61
|
+
this.ownsTimer = false;
|
|
53
62
|
}
|
|
54
|
-
if (this.ownsTimer)
|
|
55
|
-
await releaseResourceReaperOwnership(this.lockPath);
|
|
56
|
-
this.ownsTimer = false;
|
|
57
63
|
}
|
|
58
64
|
async runNow() {
|
|
59
65
|
if (!this.ownsTimer || this.running)
|
|
60
66
|
return undefined;
|
|
61
67
|
this.running = true;
|
|
62
68
|
const runAt = this.now();
|
|
69
|
+
let result;
|
|
63
70
|
try {
|
|
64
71
|
const plan = await this.plan({
|
|
65
72
|
includeDev: this.options.includeDev,
|
|
@@ -71,7 +78,7 @@ export class ResourceReaperService {
|
|
|
71
78
|
exemptBrowserPids: this.options.exemptBrowserPids,
|
|
72
79
|
now: runAt,
|
|
73
80
|
});
|
|
74
|
-
|
|
81
|
+
result = await this.apply(plan);
|
|
75
82
|
this.state = {
|
|
76
83
|
...(this.state ?? {
|
|
77
84
|
status: "running",
|
|
@@ -91,8 +98,6 @@ export class ResourceReaperService {
|
|
|
91
98
|
lastError: undefined,
|
|
92
99
|
};
|
|
93
100
|
console.error(JSON.stringify({ event: "resource_reaper_finished", at: runAt.toISOString(), ...this.state.lastResult }));
|
|
94
|
-
await this.persist();
|
|
95
|
-
return result;
|
|
96
101
|
}
|
|
97
102
|
catch (error) {
|
|
98
103
|
const message = error instanceof Error ? error.message : String(error);
|
|
@@ -109,12 +114,16 @@ export class ResourceReaperService {
|
|
|
109
114
|
lastError: message,
|
|
110
115
|
};
|
|
111
116
|
console.error(JSON.stringify({ event: "resource_reaper_failed", at: runAt.toISOString(), error: message }));
|
|
112
|
-
await this.persist();
|
|
113
|
-
return undefined;
|
|
114
117
|
}
|
|
115
118
|
finally {
|
|
116
|
-
|
|
119
|
+
try {
|
|
120
|
+
await this.persist();
|
|
121
|
+
}
|
|
122
|
+
finally {
|
|
123
|
+
this.running = false;
|
|
124
|
+
}
|
|
117
125
|
}
|
|
126
|
+
return result;
|
|
118
127
|
}
|
|
119
128
|
arm(delayMs) {
|
|
120
129
|
if (this.stopped)
|
|
@@ -122,13 +131,32 @@ export class ResourceReaperService {
|
|
|
122
131
|
if (this.timer)
|
|
123
132
|
clearTimeout(this.timer);
|
|
124
133
|
this.timer = setTimeout(() => {
|
|
125
|
-
void this.runNow()
|
|
134
|
+
void this.runNow()
|
|
135
|
+
.catch((error) => {
|
|
136
|
+
console.error(JSON.stringify({
|
|
137
|
+
event: "resource_reaper_timer_failed",
|
|
138
|
+
at: new Date().toISOString(),
|
|
139
|
+
error: error instanceof Error ? error.message : String(error),
|
|
140
|
+
}));
|
|
141
|
+
})
|
|
142
|
+
.finally(() => this.arm(this.intervalMs));
|
|
126
143
|
}, delayMs);
|
|
127
144
|
this.timer.unref?.();
|
|
128
145
|
}
|
|
129
146
|
async persist() {
|
|
130
|
-
if (this.state)
|
|
131
|
-
|
|
147
|
+
if (!this.state)
|
|
148
|
+
return;
|
|
149
|
+
try {
|
|
150
|
+
await this.writeState(this.statePath, this.state);
|
|
151
|
+
}
|
|
152
|
+
catch (error) {
|
|
153
|
+
console.error(JSON.stringify({
|
|
154
|
+
event: "resource_reaper_state_persist_failed",
|
|
155
|
+
at: new Date().toISOString(),
|
|
156
|
+
path: this.statePath,
|
|
157
|
+
error: error instanceof Error ? error.message : String(error),
|
|
158
|
+
}));
|
|
159
|
+
}
|
|
132
160
|
}
|
|
133
161
|
}
|
|
134
162
|
function readPositiveInteger(value) {
|
|
@@ -53,20 +53,20 @@ export class PiboDataSessionStore {
|
|
|
53
53
|
activeModel: input.activeModel === null ? undefined : input.activeModel ? { ...input.activeModel } : existing.activeModel,
|
|
54
54
|
updatedAt: new Date().toISOString(),
|
|
55
55
|
};
|
|
56
|
-
this.db.prepare(`
|
|
57
|
-
UPDATE sessions SET
|
|
58
|
-
pi_session_id = ?,
|
|
59
|
-
root_session_id = ?,
|
|
60
|
-
parent_id = ?,
|
|
61
|
-
origin_id = ?,
|
|
62
|
-
profile = ?,
|
|
63
|
-
active_model_json = ?,
|
|
64
|
-
workspace = ?,
|
|
65
|
-
title = ?,
|
|
66
|
-
metadata_json = ?,
|
|
67
|
-
updated_at = ?,
|
|
68
|
-
last_activity_at = MAX(last_activity_at, ?)
|
|
69
|
-
WHERE id = ? AND deleted_at IS NULL
|
|
56
|
+
this.db.prepare(`
|
|
57
|
+
UPDATE sessions SET
|
|
58
|
+
pi_session_id = ?,
|
|
59
|
+
root_session_id = ?,
|
|
60
|
+
parent_id = ?,
|
|
61
|
+
origin_id = ?,
|
|
62
|
+
profile = ?,
|
|
63
|
+
active_model_json = ?,
|
|
64
|
+
workspace = ?,
|
|
65
|
+
title = ?,
|
|
66
|
+
metadata_json = ?,
|
|
67
|
+
updated_at = ?,
|
|
68
|
+
last_activity_at = MAX(last_activity_at, ?)
|
|
69
|
+
WHERE id = ? AND deleted_at IS NULL
|
|
70
70
|
`).run(updated.piSessionId, rootSessionId(updated), updated.parentId ?? null, updated.originId ?? null, updated.profile, updated.activeModel ? JSON.stringify(updated.activeModel) : null, updated.workspace ?? null, updated.title ?? "Untitled Session", JSON.stringify(updated.metadata ?? {}), updated.updatedAt, updated.updatedAt, id);
|
|
71
71
|
return this.get(id);
|
|
72
72
|
}
|
|
@@ -129,8 +129,8 @@ export class PiboDataSessionStore {
|
|
|
129
129
|
"channel", "kind", "profile", "active_model_json", "workspace", "title", "first_message_preview",
|
|
130
130
|
"status", "metadata_json", "created_at", "updated_at", "last_activity_at",
|
|
131
131
|
];
|
|
132
|
-
this.db.prepare(`
|
|
133
|
-
INSERT INTO sessions (${columns.join(", ")}) VALUES (${columns.map(() => "?").join(", ")})
|
|
132
|
+
this.db.prepare(`
|
|
133
|
+
INSERT INTO sessions (${columns.join(", ")}) VALUES (${columns.map(() => "?").join(", ")})
|
|
134
134
|
`).run(session.id, session.piSessionId, roomIdFromMetadata(session.metadata), rootSessionId(session), session.parentId ?? null, session.originId ?? null, session.channel, session.kind, session.profile, session.activeModel ? JSON.stringify(session.activeModel) : null, session.workspace ?? null, session.title ?? "Untitled Session", previewText(session.title ?? "") ?? null, "idle", JSON.stringify(session.metadata ?? {}), session.createdAt, session.updatedAt, session.updatedAt);
|
|
135
135
|
}
|
|
136
136
|
}
|
|
@@ -18,31 +18,31 @@ export class SqlitePiboSessionStore {
|
|
|
18
18
|
this.ensureActiveModelColumn();
|
|
19
19
|
}
|
|
20
20
|
applySchema() {
|
|
21
|
-
this.db.exec(`
|
|
22
|
-
CREATE TABLE IF NOT EXISTS pibo_sessions (
|
|
23
|
-
id TEXT PRIMARY KEY,
|
|
24
|
-
pi_session_id TEXT NOT NULL UNIQUE,
|
|
25
|
-
channel TEXT NOT NULL,
|
|
26
|
-
kind TEXT NOT NULL,
|
|
27
|
-
profile TEXT NOT NULL,
|
|
28
|
-
parent_id TEXT,
|
|
29
|
-
origin_id TEXT,
|
|
30
|
-
workspace TEXT,
|
|
31
|
-
title TEXT,
|
|
32
|
-
metadata_json TEXT,
|
|
33
|
-
active_model_json TEXT,
|
|
34
|
-
created_at TEXT NOT NULL,
|
|
35
|
-
updated_at TEXT NOT NULL,
|
|
36
|
-
FOREIGN KEY(parent_id) REFERENCES pibo_sessions(id),
|
|
37
|
-
FOREIGN KEY(origin_id) REFERENCES pibo_sessions(id)
|
|
38
|
-
);
|
|
39
|
-
|
|
40
|
-
CREATE INDEX IF NOT EXISTS idx_pibo_sessions_parent
|
|
41
|
-
ON pibo_sessions(parent_id, updated_at);
|
|
42
|
-
CREATE INDEX IF NOT EXISTS idx_pibo_sessions_origin
|
|
43
|
-
ON pibo_sessions(origin_id, updated_at);
|
|
44
|
-
CREATE INDEX IF NOT EXISTS idx_pibo_sessions_channel_kind
|
|
45
|
-
ON pibo_sessions(channel, kind, updated_at);
|
|
21
|
+
this.db.exec(`
|
|
22
|
+
CREATE TABLE IF NOT EXISTS pibo_sessions (
|
|
23
|
+
id TEXT PRIMARY KEY,
|
|
24
|
+
pi_session_id TEXT NOT NULL UNIQUE,
|
|
25
|
+
channel TEXT NOT NULL,
|
|
26
|
+
kind TEXT NOT NULL,
|
|
27
|
+
profile TEXT NOT NULL,
|
|
28
|
+
parent_id TEXT,
|
|
29
|
+
origin_id TEXT,
|
|
30
|
+
workspace TEXT,
|
|
31
|
+
title TEXT,
|
|
32
|
+
metadata_json TEXT,
|
|
33
|
+
active_model_json TEXT,
|
|
34
|
+
created_at TEXT NOT NULL,
|
|
35
|
+
updated_at TEXT NOT NULL,
|
|
36
|
+
FOREIGN KEY(parent_id) REFERENCES pibo_sessions(id),
|
|
37
|
+
FOREIGN KEY(origin_id) REFERENCES pibo_sessions(id)
|
|
38
|
+
);
|
|
39
|
+
|
|
40
|
+
CREATE INDEX IF NOT EXISTS idx_pibo_sessions_parent
|
|
41
|
+
ON pibo_sessions(parent_id, updated_at);
|
|
42
|
+
CREATE INDEX IF NOT EXISTS idx_pibo_sessions_origin
|
|
43
|
+
ON pibo_sessions(origin_id, updated_at);
|
|
44
|
+
CREATE INDEX IF NOT EXISTS idx_pibo_sessions_channel_kind
|
|
45
|
+
ON pibo_sessions(channel, kind, updated_at);
|
|
46
46
|
`);
|
|
47
47
|
}
|
|
48
48
|
ensureActiveModelColumn() {
|
|
@@ -60,22 +60,22 @@ export class SqlitePiboSessionStore {
|
|
|
60
60
|
create(input) {
|
|
61
61
|
const session = createPiboSession(input);
|
|
62
62
|
this.db
|
|
63
|
-
.prepare(`
|
|
64
|
-
INSERT INTO pibo_sessions (
|
|
65
|
-
id,
|
|
66
|
-
pi_session_id,
|
|
67
|
-
channel,
|
|
68
|
-
kind,
|
|
69
|
-
profile,
|
|
70
|
-
parent_id,
|
|
71
|
-
origin_id,
|
|
72
|
-
workspace,
|
|
73
|
-
title,
|
|
74
|
-
metadata_json,
|
|
75
|
-
active_model_json,
|
|
76
|
-
created_at,
|
|
77
|
-
updated_at
|
|
78
|
-
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
63
|
+
.prepare(`
|
|
64
|
+
INSERT INTO pibo_sessions (
|
|
65
|
+
id,
|
|
66
|
+
pi_session_id,
|
|
67
|
+
channel,
|
|
68
|
+
kind,
|
|
69
|
+
profile,
|
|
70
|
+
parent_id,
|
|
71
|
+
origin_id,
|
|
72
|
+
workspace,
|
|
73
|
+
title,
|
|
74
|
+
metadata_json,
|
|
75
|
+
active_model_json,
|
|
76
|
+
created_at,
|
|
77
|
+
updated_at
|
|
78
|
+
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
79
79
|
`)
|
|
80
80
|
.run(session.id, session.piSessionId, session.channel, session.kind, session.profile, session.parentId ?? null, session.originId ?? null, session.workspace ?? null, session.title ?? null, JSON.stringify(session.metadata ?? {}), session.activeModel ? JSON.stringify(session.activeModel) : null, session.createdAt, session.updatedAt);
|
|
81
81
|
const created = this.get(session.id);
|
|
@@ -100,18 +100,18 @@ export class SqlitePiboSessionStore {
|
|
|
100
100
|
updatedAt: new Date().toISOString(),
|
|
101
101
|
};
|
|
102
102
|
this.db
|
|
103
|
-
.prepare(`
|
|
104
|
-
UPDATE pibo_sessions SET
|
|
105
|
-
pi_session_id = ?,
|
|
106
|
-
profile = ?,
|
|
107
|
-
parent_id = ?,
|
|
108
|
-
origin_id = ?,
|
|
109
|
-
workspace = ?,
|
|
110
|
-
title = ?,
|
|
111
|
-
metadata_json = ?,
|
|
112
|
-
active_model_json = ?,
|
|
113
|
-
updated_at = ?
|
|
114
|
-
WHERE id = ?
|
|
103
|
+
.prepare(`
|
|
104
|
+
UPDATE pibo_sessions SET
|
|
105
|
+
pi_session_id = ?,
|
|
106
|
+
profile = ?,
|
|
107
|
+
parent_id = ?,
|
|
108
|
+
origin_id = ?,
|
|
109
|
+
workspace = ?,
|
|
110
|
+
title = ?,
|
|
111
|
+
metadata_json = ?,
|
|
112
|
+
active_model_json = ?,
|
|
113
|
+
updated_at = ?
|
|
114
|
+
WHERE id = ?
|
|
115
115
|
`)
|
|
116
116
|
.run(updated.piSessionId, updated.profile, updated.parentId ?? null, updated.originId ?? null, updated.workspace ?? null, updated.title ?? null, JSON.stringify(updated.metadata ?? {}), updated.activeModel ? JSON.stringify(updated.activeModel) : null, updated.updatedAt, id);
|
|
117
117
|
return this.get(id);
|
package/dist/setup/cli.js
CHANGED
|
@@ -23,89 +23,89 @@ function shellQuote(value) {
|
|
|
23
23
|
}
|
|
24
24
|
function serviceUnit(options) {
|
|
25
25
|
const gatewayPortEnv = options.serviceKind === "dev" ? `Environment=PIBO_GATEWAY_DEV_PORT=${options.webPort}\n` : `Environment=PIBO_GATEWAY_WEB_PORT=${options.webPort}\n`;
|
|
26
|
-
return `[Unit]
|
|
27
|
-
Description=${options.description}
|
|
28
|
-
After=network-online.target
|
|
29
|
-
Wants=network-online.target
|
|
30
|
-
|
|
31
|
-
[Service]
|
|
32
|
-
Type=simple
|
|
33
|
-
WorkingDirectory=${options.workingDirectory}
|
|
34
|
-
Environment=HOME=/root
|
|
35
|
-
Environment=PIBO_HOME=${options.piboHome}
|
|
36
|
-
Environment=NODE_ENV=production
|
|
37
|
-
${gatewayPortEnv}ExecStart=${options.execStart}
|
|
38
|
-
Restart=always
|
|
39
|
-
RestartSec=5
|
|
40
|
-
KillSignal=SIGTERM
|
|
41
|
-
TimeoutStopSec=30
|
|
42
|
-
|
|
43
|
-
[Install]
|
|
44
|
-
WantedBy=multi-user.target
|
|
26
|
+
return `[Unit]
|
|
27
|
+
Description=${options.description}
|
|
28
|
+
After=network-online.target
|
|
29
|
+
Wants=network-online.target
|
|
30
|
+
|
|
31
|
+
[Service]
|
|
32
|
+
Type=simple
|
|
33
|
+
WorkingDirectory=${options.workingDirectory}
|
|
34
|
+
Environment=HOME=/root
|
|
35
|
+
Environment=PIBO_HOME=${options.piboHome}
|
|
36
|
+
Environment=NODE_ENV=production
|
|
37
|
+
${gatewayPortEnv}ExecStart=${options.execStart}
|
|
38
|
+
Restart=always
|
|
39
|
+
RestartSec=5
|
|
40
|
+
KillSignal=SIGTERM
|
|
41
|
+
TimeoutStopSec=30
|
|
42
|
+
|
|
43
|
+
[Install]
|
|
44
|
+
WantedBy=multi-user.target
|
|
45
45
|
`;
|
|
46
46
|
}
|
|
47
47
|
function devStartWrapper(options) {
|
|
48
|
-
return `#!/usr/bin/env node
|
|
49
|
-
import { runWebGatewayServer } from ${JSON.stringify(`${options.repoDir}/dist/gateway/web.js`)};
|
|
50
|
-
|
|
51
|
-
await runWebGatewayServer({
|
|
52
|
-
host: "127.0.0.1",
|
|
53
|
-
port: ${options.gatewayPort},
|
|
54
|
-
web: {
|
|
55
|
-
host: "127.0.0.1",
|
|
56
|
-
port: ${options.webPort},
|
|
57
|
-
},
|
|
58
|
-
});
|
|
48
|
+
return `#!/usr/bin/env node
|
|
49
|
+
import { runWebGatewayServer } from ${JSON.stringify(`${options.repoDir}/dist/gateway/web.js`)};
|
|
50
|
+
|
|
51
|
+
await runWebGatewayServer({
|
|
52
|
+
host: "127.0.0.1",
|
|
53
|
+
port: ${options.gatewayPort},
|
|
54
|
+
web: {
|
|
55
|
+
host: "127.0.0.1",
|
|
56
|
+
port: ${options.webPort},
|
|
57
|
+
},
|
|
58
|
+
});
|
|
59
59
|
`;
|
|
60
60
|
}
|
|
61
61
|
function caddyfile(options) {
|
|
62
62
|
const blocks = [];
|
|
63
63
|
if (options.prodDomain) {
|
|
64
|
-
blocks.push(`${options.prodDomain} {
|
|
65
|
-
encode zstd gzip
|
|
66
|
-
reverse_proxy 127.0.0.1:${options.prodPort}
|
|
64
|
+
blocks.push(`${options.prodDomain} {
|
|
65
|
+
encode zstd gzip
|
|
66
|
+
reverse_proxy 127.0.0.1:${options.prodPort}
|
|
67
67
|
}`);
|
|
68
68
|
}
|
|
69
69
|
if (options.prodWwwDomain && options.prodDomain) {
|
|
70
|
-
blocks.push(`${options.prodWwwDomain} {
|
|
71
|
-
redir https://${options.prodDomain}{uri} permanent
|
|
70
|
+
blocks.push(`${options.prodWwwDomain} {
|
|
71
|
+
redir https://${options.prodDomain}{uri} permanent
|
|
72
72
|
}`);
|
|
73
73
|
}
|
|
74
74
|
if (options.devDomain && options.devPort) {
|
|
75
|
-
blocks.push(`${options.devDomain} {
|
|
76
|
-
encode zstd gzip
|
|
77
|
-
reverse_proxy 127.0.0.1:${options.devPort}
|
|
75
|
+
blocks.push(`${options.devDomain} {
|
|
76
|
+
encode zstd gzip
|
|
77
|
+
reverse_proxy 127.0.0.1:${options.devPort}
|
|
78
78
|
}`);
|
|
79
79
|
}
|
|
80
80
|
if (options.devWwwDomain && options.devDomain) {
|
|
81
|
-
blocks.push(`${options.devWwwDomain} {
|
|
82
|
-
redir https://${options.devDomain}{uri} permanent
|
|
81
|
+
blocks.push(`${options.devWwwDomain} {
|
|
82
|
+
redir https://${options.devDomain}{uri} permanent
|
|
83
83
|
}`);
|
|
84
84
|
}
|
|
85
85
|
return `${blocks.join("\n\n")}\n`;
|
|
86
86
|
}
|
|
87
87
|
function userEnvTemplate(options) {
|
|
88
|
-
return `# Pibo user-host setup
|
|
89
|
-
PIBO_HOME=${options.piboHome}
|
|
90
|
-
PIBO_AUTH_BASE_URL=${options.domain ? `https://${options.domain}` : "https://pibo.example.com"}
|
|
91
|
-
# Set through \`pibo config set\` or your secret manager:
|
|
92
|
-
# PIBO_AUTH_SECRET=<at-least-32-characters>
|
|
93
|
-
# PIBO_GOOGLE_CLIENT_ID=<google-client-id>
|
|
94
|
-
# PIBO_GOOGLE_CLIENT_SECRET=<google-client-secret>
|
|
95
|
-
# PIBO_ALLOWED_EMAILS=you@example.com
|
|
88
|
+
return `# Pibo user-host setup
|
|
89
|
+
PIBO_HOME=${options.piboHome}
|
|
90
|
+
PIBO_AUTH_BASE_URL=${options.domain ? `https://${options.domain}` : "https://pibo.example.com"}
|
|
91
|
+
# Set through \`pibo config set\` or your secret manager:
|
|
92
|
+
# PIBO_AUTH_SECRET=<at-least-32-characters>
|
|
93
|
+
# PIBO_GOOGLE_CLIENT_ID=<google-client-id>
|
|
94
|
+
# PIBO_GOOGLE_CLIENT_SECRET=<google-client-secret>
|
|
95
|
+
# PIBO_ALLOWED_EMAILS=you@example.com
|
|
96
96
|
`;
|
|
97
97
|
}
|
|
98
98
|
function developerEnvTemplate(options) {
|
|
99
|
-
return `# Pibo developer-host setup
|
|
100
|
-
PIBO_ORIGIN=${options.origin ?? "git@github.com:<your-fork>/pibo.git"}
|
|
101
|
-
PIBO_UPSTREAM=${options.upstream ?? "git@github.com:Pascapone/pibo.git"}
|
|
102
|
-
PIBO_REPO_DIR=${options.repoDir}
|
|
103
|
-
PIBO_PROD_HOME=${options.prodHome}
|
|
104
|
-
PIBO_DEV_HOME=${options.devHome}
|
|
105
|
-
PIBO_PROD_BASE_URL=${options.prodDomain ? `https://${options.prodDomain}` : "https://pibo.example.com"}
|
|
106
|
-
PIBO_DEV_BASE_URL=${options.devDomain ? `https://${options.devDomain}` : "https://dev.pibo.example.com"}
|
|
107
|
-
# Optional: override the dev deploy reachability probe. If omitted, deploy uses PIBO_DEV_BASE_URL/apps/chat.
|
|
108
|
-
# PIBO_DEV_PUBLIC_URL=${options.devDomain ? `https://${options.devDomain}/apps/chat` : "https://dev.pibo.example.com/apps/chat"}
|
|
99
|
+
return `# Pibo developer-host setup
|
|
100
|
+
PIBO_ORIGIN=${options.origin ?? "git@github.com:<your-fork>/pibo.git"}
|
|
101
|
+
PIBO_UPSTREAM=${options.upstream ?? "git@github.com:Pascapone/pibo.git"}
|
|
102
|
+
PIBO_REPO_DIR=${options.repoDir}
|
|
103
|
+
PIBO_PROD_HOME=${options.prodHome}
|
|
104
|
+
PIBO_DEV_HOME=${options.devHome}
|
|
105
|
+
PIBO_PROD_BASE_URL=${options.prodDomain ? `https://${options.prodDomain}` : "https://pibo.example.com"}
|
|
106
|
+
PIBO_DEV_BASE_URL=${options.devDomain ? `https://${options.devDomain}` : "https://dev.pibo.example.com"}
|
|
107
|
+
# Optional: override the dev deploy reachability probe. If omitted, deploy uses PIBO_DEV_BASE_URL/apps/chat.
|
|
108
|
+
# PIBO_DEV_PUBLIC_URL=${options.devDomain ? `https://${options.devDomain}/apps/chat` : "https://dev.pibo.example.com/apps/chat"}
|
|
109
109
|
`;
|
|
110
110
|
}
|
|
111
111
|
export function createUserHostSetupPlan(options = {}) {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { reconcileAsyncAgentRunStatuses } from "./trace-async-agent-runs.js";
|
|
2
|
-
import { applySingleEventToNodes, contentDeltaPatchNodeId, dedupeTraceEvents, eventsCanAffectAsyncAgentRunStatus, findOpenTranscriptEventIds, isConfirmedUserMessageEcho, latestTraceStreamId, messageTurnTimingsFromEvents, reconcileTranscriptUserMessageTimestamps, traceEventDedupeKey, } from "./trace-event-projection.js";
|
|
2
|
+
import { applySingleEventToNodes, contentDeltaPatchNodeId, dedupeTraceEvents, eventsCanAffectAsyncAgentRunStatus, findOpenTranscriptEventIds, isConfirmedUserMessageEcho, latestTraceStreamId, mergeMessageTurnTimings, messageTurnTimingsFromEvents, reconcileTranscriptUserMessageTimestamps, traceEventDedupeKey, } from "./trace-event-projection.js";
|
|
3
3
|
import { flattenTraceNodes, mapTraceNodesById, nestTraceNodes } from "./trace-nodes.js";
|
|
4
4
|
import { nestMutableCopiedTraceNodes, shareUnchangedTraceNodes } from "./trace-patch-nodes.js";
|
|
5
5
|
import { mapTraceChildSessionsByParent, mapTraceSubagentSessionLinks, } from "./trace-subagent-links.js";
|
|
@@ -14,7 +14,8 @@ export function buildTraceViewFromEvents(input) {
|
|
|
14
14
|
const allEntries = input.transcriptEntries ?? [];
|
|
15
15
|
const openTranscriptEventIds = findOpenTranscriptEventIds(events, sessionStatus);
|
|
16
16
|
const entries = projectTranscriptEntries(allEntries, sessionStatus, openTranscriptEventIds);
|
|
17
|
-
const
|
|
17
|
+
const turnTimings = mergeMessageTurnTimings(input.turnTimings ?? [], messageTurnTimingsFromEvents(events));
|
|
18
|
+
const nodes = traceNodesFromEntries(input.session.id, entries, turnTimings);
|
|
18
19
|
reconcileTranscriptUserMessageTimestamps(nodes, events);
|
|
19
20
|
const byId = mapTraceNodesById(nodes);
|
|
20
21
|
const childByParent = mapTraceChildSessionsByParent(input.sessions ?? []);
|
|
@@ -531,6 +531,32 @@ function shouldKeepTranscriptEchoEvent(event, openTranscriptEventIds) {
|
|
|
531
531
|
function isStaleToolCallEchoEvent(event, sessionStatus) {
|
|
532
532
|
return sessionStatus !== "running" && event.type === "tool_call";
|
|
533
533
|
}
|
|
534
|
+
export function mergeMessageTurnTimings(...groups) {
|
|
535
|
+
const byEventId = new Map();
|
|
536
|
+
for (const timing of groups.flat()) {
|
|
537
|
+
const existing = byEventId.get(timing.eventId);
|
|
538
|
+
if (!existing) {
|
|
539
|
+
byEventId.set(timing.eventId, timing);
|
|
540
|
+
continue;
|
|
541
|
+
}
|
|
542
|
+
const merged = {
|
|
543
|
+
eventId: timing.eventId,
|
|
544
|
+
userText: timing.userText ?? existing.userText,
|
|
545
|
+
startedAt: timing.startedAt ?? existing.startedAt,
|
|
546
|
+
completedAt: timing.completedAt ?? existing.completedAt,
|
|
547
|
+
durationMs: timing.durationMs ?? existing.durationMs,
|
|
548
|
+
};
|
|
549
|
+
if (merged.durationMs === undefined) {
|
|
550
|
+
const startedAtMs = parseTimestamp(merged.startedAt);
|
|
551
|
+
const completedAtMs = parseTimestamp(merged.completedAt);
|
|
552
|
+
if (startedAtMs !== undefined && completedAtMs !== undefined) {
|
|
553
|
+
merged.durationMs = Math.max(0, completedAtMs - startedAtMs);
|
|
554
|
+
}
|
|
555
|
+
}
|
|
556
|
+
byEventId.set(timing.eventId, merged);
|
|
557
|
+
}
|
|
558
|
+
return [...byEventId.values()];
|
|
559
|
+
}
|
|
534
560
|
export function messageTurnTimingsFromEvents(events) {
|
|
535
561
|
const timings = new Map();
|
|
536
562
|
const completedEventIds = [];
|
|
@@ -6,86 +6,86 @@ function shellQuote(value) {
|
|
|
6
6
|
return `'${value.replaceAll("'", "'\\''")}'`;
|
|
7
7
|
}
|
|
8
8
|
function createAgentBrowserWrapper(realExecutablePath, defaultHomeDir) {
|
|
9
|
-
return `#!/usr/bin/env bash
|
|
10
|
-
set -euo pipefail
|
|
11
|
-
|
|
12
|
-
real_agent_browser=${shellQuote(realExecutablePath)}
|
|
13
|
-
default_home=${shellQuote(defaultHomeDir)}
|
|
14
|
-
fresh_flag=${shellQuote(AGENT_BROWSER_FRESH_PROFILE_FLAG)}
|
|
15
|
-
|
|
16
|
-
if [ -z "\${AGENT_BROWSER_HOME:-}" ]; then
|
|
17
|
-
export AGENT_BROWSER_HOME="$default_home"
|
|
18
|
-
fi
|
|
19
|
-
mkdir -p "$AGENT_BROWSER_HOME" "$AGENT_BROWSER_HOME/profiles"
|
|
20
|
-
|
|
21
|
-
# agent-browser@0.27.0 uses HOME for ~/.agent-browser state. Redirect it by
|
|
22
|
-
# default so doctor, config, sockets, and auth vault files stay inside Pibo's
|
|
23
|
-
# tool home. Operators can opt out for upstream debugging.
|
|
24
|
-
if [ "\${PIBO_AGENT_BROWSER_PRESERVE_HOME:-0}" != "1" ]; then
|
|
25
|
-
export HOME="$AGENT_BROWSER_HOME"
|
|
26
|
-
fi
|
|
27
|
-
|
|
28
|
-
explicit_runtime=0
|
|
29
|
-
fresh_profile=0
|
|
30
|
-
show_help=0
|
|
31
|
-
starts_browser=0
|
|
32
|
-
args=()
|
|
33
|
-
|
|
34
|
-
print_wrapper_help() {
|
|
35
|
-
cat <<'HELP'
|
|
36
|
-
Pibo agent-browser wrapper
|
|
37
|
-
- keeps Agent Browser state under AGENT_BROWSER_HOME by default
|
|
38
|
-
- prepends a persistent Pibo profile for browser-launching commands
|
|
39
|
-
- pass --fresh-profile to disable Pibo profile injection
|
|
40
|
-
- explicit --profile, --state, --cdp, --auto-connect, --provider, --engine,
|
|
41
|
-
--executable-path, or --config flags override Pibo defaults
|
|
42
|
-
HELP
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
while [ "$#" -gt 0 ]; do
|
|
46
|
-
case "$1" in
|
|
47
|
-
--help|-h)
|
|
48
|
-
show_help=1
|
|
49
|
-
args+=("$1")
|
|
50
|
-
;;
|
|
51
|
-
--fresh-profile)
|
|
52
|
-
fresh_profile=1
|
|
53
|
-
;;
|
|
54
|
-
--profile|--state|--cdp|--auto-connect|--provider|--engine|--executable-path|--config)
|
|
55
|
-
explicit_runtime=1
|
|
56
|
-
args+=("$1")
|
|
57
|
-
if [ "$#" -gt 1 ]; then
|
|
58
|
-
shift
|
|
59
|
-
args+=("$1")
|
|
60
|
-
fi
|
|
61
|
-
;;
|
|
62
|
-
--profile=*|--state=*|--cdp=*|--auto-connect=*|--provider=*|--engine=*|--executable-path=*|--config=*)
|
|
63
|
-
explicit_runtime=1
|
|
64
|
-
args+=("$1")
|
|
65
|
-
;;
|
|
66
|
-
open|launch|new|goto)
|
|
67
|
-
starts_browser=1
|
|
68
|
-
args+=("$1")
|
|
69
|
-
;;
|
|
70
|
-
*)
|
|
71
|
-
args+=("$1")
|
|
72
|
-
;;
|
|
73
|
-
esac
|
|
74
|
-
shift
|
|
75
|
-
done
|
|
76
|
-
|
|
77
|
-
if [ "$show_help" -eq 1 ]; then
|
|
78
|
-
print_wrapper_help
|
|
79
|
-
exec "$real_agent_browser" "\${args[@]}"
|
|
80
|
-
fi
|
|
81
|
-
|
|
82
|
-
if [ "$starts_browser" -eq 1 ] && [ "$fresh_profile" -eq 0 ] && [ "$explicit_runtime" -eq 0 ]; then
|
|
83
|
-
profile_dir=\${AGENT_BROWSER_PROFILE:-$AGENT_BROWSER_HOME/profiles/${AGENT_BROWSER_DEFAULT_PROFILE}}
|
|
84
|
-
mkdir -p "$profile_dir"
|
|
85
|
-
exec "$real_agent_browser" --profile "$profile_dir" "\${args[@]}"
|
|
86
|
-
fi
|
|
87
|
-
|
|
88
|
-
exec "$real_agent_browser" "\${args[@]}"
|
|
9
|
+
return `#!/usr/bin/env bash
|
|
10
|
+
set -euo pipefail
|
|
11
|
+
|
|
12
|
+
real_agent_browser=${shellQuote(realExecutablePath)}
|
|
13
|
+
default_home=${shellQuote(defaultHomeDir)}
|
|
14
|
+
fresh_flag=${shellQuote(AGENT_BROWSER_FRESH_PROFILE_FLAG)}
|
|
15
|
+
|
|
16
|
+
if [ -z "\${AGENT_BROWSER_HOME:-}" ]; then
|
|
17
|
+
export AGENT_BROWSER_HOME="$default_home"
|
|
18
|
+
fi
|
|
19
|
+
mkdir -p "$AGENT_BROWSER_HOME" "$AGENT_BROWSER_HOME/profiles"
|
|
20
|
+
|
|
21
|
+
# agent-browser@0.27.0 uses HOME for ~/.agent-browser state. Redirect it by
|
|
22
|
+
# default so doctor, config, sockets, and auth vault files stay inside Pibo's
|
|
23
|
+
# tool home. Operators can opt out for upstream debugging.
|
|
24
|
+
if [ "\${PIBO_AGENT_BROWSER_PRESERVE_HOME:-0}" != "1" ]; then
|
|
25
|
+
export HOME="$AGENT_BROWSER_HOME"
|
|
26
|
+
fi
|
|
27
|
+
|
|
28
|
+
explicit_runtime=0
|
|
29
|
+
fresh_profile=0
|
|
30
|
+
show_help=0
|
|
31
|
+
starts_browser=0
|
|
32
|
+
args=()
|
|
33
|
+
|
|
34
|
+
print_wrapper_help() {
|
|
35
|
+
cat <<'HELP'
|
|
36
|
+
Pibo agent-browser wrapper
|
|
37
|
+
- keeps Agent Browser state under AGENT_BROWSER_HOME by default
|
|
38
|
+
- prepends a persistent Pibo profile for browser-launching commands
|
|
39
|
+
- pass --fresh-profile to disable Pibo profile injection
|
|
40
|
+
- explicit --profile, --state, --cdp, --auto-connect, --provider, --engine,
|
|
41
|
+
--executable-path, or --config flags override Pibo defaults
|
|
42
|
+
HELP
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
while [ "$#" -gt 0 ]; do
|
|
46
|
+
case "$1" in
|
|
47
|
+
--help|-h)
|
|
48
|
+
show_help=1
|
|
49
|
+
args+=("$1")
|
|
50
|
+
;;
|
|
51
|
+
--fresh-profile)
|
|
52
|
+
fresh_profile=1
|
|
53
|
+
;;
|
|
54
|
+
--profile|--state|--cdp|--auto-connect|--provider|--engine|--executable-path|--config)
|
|
55
|
+
explicit_runtime=1
|
|
56
|
+
args+=("$1")
|
|
57
|
+
if [ "$#" -gt 1 ]; then
|
|
58
|
+
shift
|
|
59
|
+
args+=("$1")
|
|
60
|
+
fi
|
|
61
|
+
;;
|
|
62
|
+
--profile=*|--state=*|--cdp=*|--auto-connect=*|--provider=*|--engine=*|--executable-path=*|--config=*)
|
|
63
|
+
explicit_runtime=1
|
|
64
|
+
args+=("$1")
|
|
65
|
+
;;
|
|
66
|
+
open|launch|new|goto)
|
|
67
|
+
starts_browser=1
|
|
68
|
+
args+=("$1")
|
|
69
|
+
;;
|
|
70
|
+
*)
|
|
71
|
+
args+=("$1")
|
|
72
|
+
;;
|
|
73
|
+
esac
|
|
74
|
+
shift
|
|
75
|
+
done
|
|
76
|
+
|
|
77
|
+
if [ "$show_help" -eq 1 ]; then
|
|
78
|
+
print_wrapper_help
|
|
79
|
+
exec "$real_agent_browser" "\${args[@]}"
|
|
80
|
+
fi
|
|
81
|
+
|
|
82
|
+
if [ "$starts_browser" -eq 1 ] && [ "$fresh_profile" -eq 0 ] && [ "$explicit_runtime" -eq 0 ]; then
|
|
83
|
+
profile_dir=\${AGENT_BROWSER_PROFILE:-$AGENT_BROWSER_HOME/profiles/${AGENT_BROWSER_DEFAULT_PROFILE}}
|
|
84
|
+
mkdir -p "$profile_dir"
|
|
85
|
+
exec "$real_agent_browser" --profile "$profile_dir" "\${args[@]}"
|
|
86
|
+
fi
|
|
87
|
+
|
|
88
|
+
exec "$real_agent_browser" "\${args[@]}"
|
|
89
89
|
`;
|
|
90
90
|
}
|
|
91
91
|
export function ensureAgentBrowserWrapper(status) {
|