@pasko70/pibo 1.9.13 → 1.10.1
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-profiles.js +2 -2
- package/dist/apps/chat/agent-store.js +263 -250
- package/dist/apps/chat/chat-request-normalizers.js +17 -0
- package/dist/apps/chat/data/chat-data-mappers.js +2 -0
- 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 +19 -19
- package/dist/apps/chat/loop-api.js +181 -0
- package/dist/apps/chat/static-assets.js +854 -854
- package/dist/apps/chat/web-app.js +36 -16
- package/dist/apps/chat/workflow-manual-trigger-runtime.js +149 -46
- package/dist/apps/chat/workflow-persistence.js +255 -255
- package/dist/apps/chat-ui/assets/{dist-BZ2eTC4f.js → dist-3Sts0Afa.js} +1 -1
- package/dist/apps/chat-ui/assets/{dist-BHa-kcGl.js → dist-4NlLjLs7.js} +1 -1
- package/dist/apps/chat-ui/assets/{dist-yCYNNb5d.js → dist-BA6mhAec.js} +1 -1
- package/dist/apps/chat-ui/assets/{dist-D811wJeV.js → dist-BPl-fzRB.js} +1 -1
- package/dist/apps/chat-ui/assets/{dist-Dq4GxJi3.js → dist-BPnn9e2B.js} +1 -1
- package/dist/apps/chat-ui/assets/{dist-CzE6k3F3.js → dist-BpfBSMzK.js} +1 -1
- package/dist/apps/chat-ui/assets/{dist-CnVsqwSG.js → dist-Cvx5M97R.js} +1 -1
- package/dist/apps/chat-ui/assets/{dist-WyXdYl-w.js → dist-DnXWNQRm.js} +1 -1
- package/dist/apps/chat-ui/assets/{dist-BNMu92bb.js → dist-hU-2oAb6.js} +1 -1
- package/dist/apps/chat-ui/assets/{dist-BCB6zezO.js → dist-r31x5Fcc.js} +1 -1
- package/dist/apps/chat-ui/assets/{dist-HqTN67dc.js → dist-uF6UXzI7.js} +1 -1
- package/dist/apps/chat-ui/assets/index-CaTGYBOS.js +173 -0
- package/dist/apps/chat-ui/assets/{index-C0x9nEcf.css → index-al8DeEjA.css} +1 -1
- package/dist/apps/chat-ui/index.html +18 -18
- package/dist/apps/chat-ui/manifest.webmanifest +25 -25
- package/dist/apps/chat-ui/sw.js +47 -47
- package/dist/apps/chat-vscode-web/assets/index-CK4SMZuu.js +41 -0
- package/dist/apps/chat-vscode-web/index.html +13 -13
- package/dist/apps/cli-ui/cliSessionsCommand.js +23 -23
- package/dist/apps/context-files-ui/index.html +11 -11
- package/dist/cli-session/localSessionSource.js +34 -12
- package/dist/cli.js +61 -44
- package/dist/compute/cli.js +54 -54
- package/dist/compute/resource-health.js +35 -2
- package/dist/core/events.js +6 -1
- package/dist/core/routed-session.js +97 -5
- package/dist/core/runtime.js +6 -1
- package/dist/core/session-router.js +27 -8
- 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 +3 -1
- package/dist/data/message-store.js +27 -27
- 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 -433
- 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 +231 -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/trace.js +42 -7
- 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/gateway/server.js +4 -2
- package/dist/gateway/web.js +2 -2
- package/dist/index.js +1 -0
- package/dist/loops/accounting.js +19 -0
- package/dist/loops/channel.js +8 -0
- package/dist/loops/cli.js +224 -0
- package/dist/loops/plugin.js +16 -0
- package/dist/loops/prompts.js +86 -0
- package/dist/loops/service.js +446 -0
- package/dist/loops/stopping.js +170 -0
- package/dist/loops/store.js +642 -0
- package/dist/loops/templates.js +232 -0
- package/dist/loops/tools.js +184 -0
- package/dist/loops/types.js +1 -0
- 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/builtin.js +8 -0
- package/dist/plugins/context-files-store.js +110 -110
- package/dist/plugins/context-files.js +4 -4
- package/dist/plugins/registry.js +23 -12
- package/dist/ralph/cli.js +18 -18
- package/dist/ralph/templates.js +140 -140
- package/dist/reliability/store.js +256 -229
- package/dist/runs/lifecycle.js +59 -0
- package/dist/runs/registry.js +47 -1
- package/dist/runs/tools.js +31 -13
- package/dist/session-ui/terminalRows.js +66 -2
- 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-async-agent-runs.js +4 -4
- package/dist/shared/trace-event-projection.js +59 -19
- package/dist/shared/trace-nodes.js +5 -0
- package/dist/shared/trace-page-merge.js +15 -0
- package/dist/shared/trace-run-notifications.js +3 -1
- package/dist/signals/projector.js +6 -2
- package/dist/tools/agent-browser-wrapper.js +80 -80
- package/dist/tools/browser-pool.js +50 -0
- package/dist/tools/browser-use-cdp.js +12 -12
- package/dist/tools/browser-use-leases.js +12 -8
- package/dist/tools/browser-use-wrapper.js +762 -762
- package/dist/tools/guides.js +596 -538
- package/dist/tools/index.js +123 -99
- package/dist/tools/registry.js +21 -3
- 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 +99 -95
- package/skills/builtin/graphify/SKILL.md +52 -52
- package/skills/builtin/loop/SKILL.md +78 -0
- 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 +361 -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/apps/chat-ui/assets/index-DwHJfmiF.js +0 -173
- package/dist/apps/chat-vscode-web/assets/index-BAMxIaI_.js +0 -41
- package/dist/apps/vscode-artifacts/latest.vsix +0 -0
- package/dist/apps/vscode-artifacts/pibo-vscode-ext-1.9.13.vsix +0 -0
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
export class PiboRunExecutionTimeoutError extends Error {
|
|
2
|
+
timeoutPhase;
|
|
3
|
+
constructor(message, timeoutPhase) {
|
|
4
|
+
super(message);
|
|
5
|
+
this.timeoutPhase = timeoutPhase;
|
|
6
|
+
this.name = "PiboRunExecutionTimeoutError";
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
export function resolveRunTimeoutMs(toolName, params) {
|
|
10
|
+
if (!params || typeof params !== "object" || Array.isArray(params))
|
|
11
|
+
return undefined;
|
|
12
|
+
const input = params;
|
|
13
|
+
if (typeof input.timeoutMs === "number")
|
|
14
|
+
return normalizePositiveTimeout(input.timeoutMs, "arguments.timeoutMs");
|
|
15
|
+
if (toolName === "bash" && typeof input.timeout === "number")
|
|
16
|
+
return normalizePositiveTimeout(input.timeout * 1000, "arguments.timeout");
|
|
17
|
+
return undefined;
|
|
18
|
+
}
|
|
19
|
+
export function foregroundServiceWarning(toolName, params, timeoutMs) {
|
|
20
|
+
if (toolName !== "bash" || timeoutMs === undefined || !params || typeof params !== "object" || Array.isArray(params))
|
|
21
|
+
return undefined;
|
|
22
|
+
const command = typeof params.command === "string" ? String(params.command) : "";
|
|
23
|
+
if (!isKnownForegroundServiceCommand(command))
|
|
24
|
+
return undefined;
|
|
25
|
+
return `Known long-lived service command is running in a finite yielded run (${timeoutMs}ms). It can start successfully and later end as timed_out. Use the managed gateway CLI, or launch a detached/background service with a separate bounded health check.`;
|
|
26
|
+
}
|
|
27
|
+
export function isConfiguredTimeoutError(error) {
|
|
28
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
29
|
+
return /(?:timed?\s*out|timeout)/i.test(message);
|
|
30
|
+
}
|
|
31
|
+
export function hasMeaningfulTimeoutOutput(value) {
|
|
32
|
+
const text = extractText(value);
|
|
33
|
+
if (!text)
|
|
34
|
+
return false;
|
|
35
|
+
return text.split(/\r?\n/).some((line) => {
|
|
36
|
+
const trimmed = line.trim();
|
|
37
|
+
return !!trimmed && !/(?:timed?\s*out|timeout|command exited with code|process exited with code)/i.test(trimmed);
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
function isKnownForegroundServiceCommand(command) {
|
|
41
|
+
return /(?:^|[;&|]\s*|\b)(?:pibo\s+gateway(?::web|\s+web|\s+dev)?(?:\s|$)|node\s+[^\n]*pibo(?:\.js)?\s+gateway:web(?:\s|$)|(?:\.\/)?(?:scripts\/)?docker-entrypoint\.sh\s+gateway:web(?:\s|$)|npm\s+(?:run\s+)?gateway(?::web)?(?:\s|$)|(?:npm\s+run\s+)?(?:dev|start)\s+--[^\n]*\bgateway(?::web)?\b|vite(?:\s|$))/i.test(command);
|
|
42
|
+
}
|
|
43
|
+
function normalizePositiveTimeout(value, field) {
|
|
44
|
+
if (!Number.isFinite(value) || value <= 0)
|
|
45
|
+
throw new Error(`${field} must be a positive number`);
|
|
46
|
+
return Math.max(1, Math.round(value));
|
|
47
|
+
}
|
|
48
|
+
function extractText(value) {
|
|
49
|
+
if (typeof value === "string")
|
|
50
|
+
return value;
|
|
51
|
+
if (!value || typeof value !== "object")
|
|
52
|
+
return "";
|
|
53
|
+
const candidate = value;
|
|
54
|
+
if (typeof candidate.text === "string")
|
|
55
|
+
return candidate.text;
|
|
56
|
+
if (!Array.isArray(candidate.content))
|
|
57
|
+
return "";
|
|
58
|
+
return candidate.content.map((part) => part && typeof part === "object" && typeof part.text === "string" ? String(part.text) : "").filter(Boolean).join("\n");
|
|
59
|
+
}
|
package/dist/runs/registry.js
CHANGED
|
@@ -4,6 +4,14 @@ const DEFAULT_DETACHED_TERMINAL_TTL_MS = 60 * 1000;
|
|
|
4
4
|
function now() {
|
|
5
5
|
return new Date().toISOString();
|
|
6
6
|
}
|
|
7
|
+
function runTimeoutAt(createdAt, timeoutMs) {
|
|
8
|
+
return timeoutMs === undefined ? undefined : new Date(Date.parse(createdAt) + timeoutMs).toISOString();
|
|
9
|
+
}
|
|
10
|
+
function formatTimeout(timeoutMs) {
|
|
11
|
+
if (timeoutMs === undefined)
|
|
12
|
+
return "its configured timeout";
|
|
13
|
+
return timeoutMs % 1000 === 0 ? `${timeoutMs / 1000}s timeout` : `${timeoutMs}ms timeout`;
|
|
14
|
+
}
|
|
7
15
|
function snapshot(record) {
|
|
8
16
|
const output = {
|
|
9
17
|
runId: record.runId,
|
|
@@ -18,12 +26,20 @@ function snapshot(record) {
|
|
|
18
26
|
};
|
|
19
27
|
if (record.summary)
|
|
20
28
|
output.summary = record.summary;
|
|
29
|
+
if (record.timeoutMs !== undefined)
|
|
30
|
+
output.timeoutMs = record.timeoutMs;
|
|
31
|
+
if (record.timeoutAt)
|
|
32
|
+
output.timeoutAt = record.timeoutAt;
|
|
33
|
+
if (record.timeoutPhase)
|
|
34
|
+
output.timeoutPhase = record.timeoutPhase;
|
|
35
|
+
if (record.serviceWarning)
|
|
36
|
+
output.serviceWarning = record.serviceWarning;
|
|
21
37
|
if (record.completedAt)
|
|
22
38
|
output.completedAt = record.completedAt;
|
|
23
39
|
return output;
|
|
24
40
|
}
|
|
25
41
|
function terminal(status) {
|
|
26
|
-
return status === "completed" || status === "failed" || status === "cancelled";
|
|
42
|
+
return status === "completed" || status === "failed" || status === "timed_out" || status === "cancelled";
|
|
27
43
|
}
|
|
28
44
|
export class PiboRunRegistry {
|
|
29
45
|
options;
|
|
@@ -53,6 +69,8 @@ export class PiboRunRegistry {
|
|
|
53
69
|
params: input.params,
|
|
54
70
|
retryable: input.retryable ?? false,
|
|
55
71
|
maxAttempts: input.maxAttempts ?? 1,
|
|
72
|
+
timeoutMs: input.timeoutMs,
|
|
73
|
+
serviceWarning: input.serviceWarning,
|
|
56
74
|
});
|
|
57
75
|
const record = recordFromStored(stored);
|
|
58
76
|
this.runs.set(record.runId, record);
|
|
@@ -75,6 +93,8 @@ export class PiboRunRegistry {
|
|
|
75
93
|
summary: `${input.toolName} run is running.`,
|
|
76
94
|
retryable: input.retryable ?? false,
|
|
77
95
|
maxAttempts: Math.max(1, input.maxAttempts ?? 1),
|
|
96
|
+
...(input.timeoutMs !== undefined ? { timeoutMs: input.timeoutMs, timeoutAt: runTimeoutAt(timestamp, input.timeoutMs) } : {}),
|
|
97
|
+
...(input.serviceWarning ? { serviceWarning: input.serviceWarning } : {}),
|
|
78
98
|
};
|
|
79
99
|
this.runs.set(runId, record);
|
|
80
100
|
const output = snapshot(record);
|
|
@@ -113,6 +133,25 @@ export class PiboRunRegistry {
|
|
|
113
133
|
this.notify({ type: "run_changed", run: output, previousStatus, reason: error });
|
|
114
134
|
return output;
|
|
115
135
|
}
|
|
136
|
+
timeOut(runId, error, timeoutPhase) {
|
|
137
|
+
const record = this.runs.get(runId);
|
|
138
|
+
if (!record || terminal(record.status))
|
|
139
|
+
return undefined;
|
|
140
|
+
const previousStatus = record.status;
|
|
141
|
+
record.status = "timed_out";
|
|
142
|
+
record.error = error;
|
|
143
|
+
record.timeoutPhase = timeoutPhase;
|
|
144
|
+
record.summary = timeoutPhase === "lifetime"
|
|
145
|
+
? `${record.toolName} run started successfully, then reached ${formatTimeout(record.timeoutMs)}.`
|
|
146
|
+
: `${record.toolName} run reached ${formatTimeout(record.timeoutMs)} before startup was confirmed.`;
|
|
147
|
+
this.finish(record);
|
|
148
|
+
this.options.store?.updateRun(runId, record);
|
|
149
|
+
if (record.jobId)
|
|
150
|
+
this.options.store?.fail(record.jobId, `run-registry:${process.pid}`, error);
|
|
151
|
+
const output = snapshot(record);
|
|
152
|
+
this.notify({ type: "run_changed", run: output, previousStatus, reason: error });
|
|
153
|
+
return output;
|
|
154
|
+
}
|
|
116
155
|
list(controllerPiboSessionId, options = {}) {
|
|
117
156
|
this.prune();
|
|
118
157
|
return [...this.runs.values()]
|
|
@@ -219,6 +258,7 @@ export class PiboRunRegistry {
|
|
|
219
258
|
const notification = {
|
|
220
259
|
completed: [],
|
|
221
260
|
failed: [],
|
|
261
|
+
timedOut: [],
|
|
222
262
|
cancelled: [],
|
|
223
263
|
running: [],
|
|
224
264
|
};
|
|
@@ -228,6 +268,8 @@ export class PiboRunRegistry {
|
|
|
228
268
|
notification.completed.push(item);
|
|
229
269
|
else if (record.status === "failed")
|
|
230
270
|
notification.failed.push(item);
|
|
271
|
+
else if (record.status === "timed_out")
|
|
272
|
+
notification.timedOut.push(item);
|
|
231
273
|
else if (record.status === "cancelled")
|
|
232
274
|
notification.cancelled.push(item);
|
|
233
275
|
else
|
|
@@ -356,5 +398,9 @@ function recordFromStored(record) {
|
|
|
356
398
|
jobId: record.jobId,
|
|
357
399
|
retryable: record.retryable,
|
|
358
400
|
maxAttempts: record.maxAttempts,
|
|
401
|
+
timeoutMs: record.timeoutMs,
|
|
402
|
+
timeoutAt: record.timeoutAt,
|
|
403
|
+
timeoutPhase: record.timeoutPhase,
|
|
404
|
+
serviceWarning: record.serviceWarning,
|
|
359
405
|
};
|
|
360
406
|
}
|
package/dist/runs/tools.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { StringEnum, Type } from "@earendil-works/pi-ai";
|
|
2
2
|
import { defineTool } from "@earendil-works/pi-coding-agent";
|
|
3
|
+
import { foregroundServiceWarning, hasMeaningfulTimeoutOutput, isConfiguredTimeoutError, PiboRunExecutionTimeoutError, resolveRunTimeoutMs } from "./lifecycle.js";
|
|
3
4
|
function resultText(prefix, value) {
|
|
4
5
|
return `${prefix}\n${JSON.stringify(value, null, 2)}`;
|
|
5
6
|
}
|
|
@@ -30,7 +31,7 @@ export function createRunToolDefinitions(yieldableTools, controller) {
|
|
|
30
31
|
defineTool({
|
|
31
32
|
name: "pibo_run_start",
|
|
32
33
|
label: "Pibo Run Start",
|
|
33
|
-
description: "Start a yieldable tool as a yielded run.
|
|
34
|
+
description: "Start a yieldable tool as a yielded run. The run records its configured timeout and classifies lifetime expiry separately from command failure. Use detached only for intentional fire-and-forget work.",
|
|
34
35
|
promptSnippet: "Use pibo_run_start to run a yieldable tool in the background. It returns a runId. Use pibo_run_read for completed results and pibo_run_wait/status/list/cancel/ack to manage runs.",
|
|
35
36
|
executionMode: "parallel",
|
|
36
37
|
parameters: Type.Object({
|
|
@@ -43,25 +44,42 @@ export function createRunToolDefinitions(yieldableTools, controller) {
|
|
|
43
44
|
}),
|
|
44
45
|
async execute(toolCallId, params, signal, onUpdate, ctx) {
|
|
45
46
|
const tool = requireTool(yieldableTools, params.toolName);
|
|
47
|
+
const timeoutMs = resolveRunTimeoutMs(tool.name, params.arguments);
|
|
48
|
+
const serviceWarning = foregroundServiceWarning(tool.name, params.arguments, timeoutMs);
|
|
49
|
+
let observedOutput = false;
|
|
46
50
|
const run = controller.startToolRun({
|
|
47
51
|
toolName: tool.name,
|
|
48
52
|
params: params.arguments,
|
|
49
53
|
completionPolicy: params.completionPolicy,
|
|
54
|
+
timeoutMs,
|
|
55
|
+
serviceWarning,
|
|
50
56
|
async execute() {
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
57
|
+
try {
|
|
58
|
+
const result = await tool.execute(toolCallId, params.arguments, signal, (update) => {
|
|
59
|
+
observedOutput ||= hasMeaningfulTimeoutOutput(update);
|
|
60
|
+
onUpdate?.(update);
|
|
61
|
+
}, ctx);
|
|
62
|
+
const resultObject = result;
|
|
63
|
+
const text = textFromToolResult(resultObject);
|
|
64
|
+
if (resultObject.isError === true) {
|
|
65
|
+
if (timeoutMs !== undefined && isConfiguredTimeoutError(text ?? ""))
|
|
66
|
+
throw new PiboRunExecutionTimeoutError(text ?? `${tool.name} timed out.`, observedOutput || hasMeaningfulTimeoutOutput(text) ? "lifetime" : "startup");
|
|
67
|
+
throw new Error(text ?? `${tool.name} returned an error result.`);
|
|
68
|
+
}
|
|
69
|
+
return { text, details: resultObject.details ?? result };
|
|
70
|
+
}
|
|
71
|
+
catch (error) {
|
|
72
|
+
if (error instanceof PiboRunExecutionTimeoutError)
|
|
73
|
+
throw error;
|
|
74
|
+
if (timeoutMs !== undefined && isConfiguredTimeoutError(error))
|
|
75
|
+
throw new PiboRunExecutionTimeoutError(error instanceof Error ? error.message : String(error), observedOutput ? "lifetime" : "startup");
|
|
76
|
+
throw error;
|
|
56
77
|
}
|
|
57
|
-
return {
|
|
58
|
-
text,
|
|
59
|
-
details: resultObject.details ?? result,
|
|
60
|
-
};
|
|
61
78
|
},
|
|
62
79
|
});
|
|
80
|
+
const prefix = serviceWarning ? `Started yielded run ${run.runId}.\nWarning: ${serviceWarning}` : `Started yielded run ${run.runId}.`;
|
|
63
81
|
return {
|
|
64
|
-
content: [{ type: "text", text: resultText(
|
|
82
|
+
content: [{ type: "text", text: resultText(prefix, run) }],
|
|
65
83
|
details: run,
|
|
66
84
|
};
|
|
67
85
|
},
|
|
@@ -132,8 +150,8 @@ export function createRunToolDefinitions(yieldableTools, controller) {
|
|
|
132
150
|
defineTool({
|
|
133
151
|
name: "pibo_run_read",
|
|
134
152
|
label: "Pibo Run Read",
|
|
135
|
-
description: "Read the terminal result or error for a yielded run.",
|
|
136
|
-
promptSnippet: "Use pibo_run_read to retrieve a completed or
|
|
153
|
+
description: "Read the terminal result, timeout reason, or error for a yielded run.",
|
|
154
|
+
promptSnippet: "Use pibo_run_read to retrieve a completed, failed, or timed_out run result. Reading terminal tracked runs consumes reminders.",
|
|
137
155
|
executionMode: "parallel",
|
|
138
156
|
parameters: Type.Object({
|
|
139
157
|
runId: Type.String({ description: "Run id returned by pibo_run_start" }),
|
|
@@ -11,7 +11,7 @@ export function buildCompactTerminalRows(traceView, options) {
|
|
|
11
11
|
.filter((item) => item.node.type !== "agent.turn" && (options.showThinking || item.node.type !== "model.reasoning"));
|
|
12
12
|
const candidates = syncThinkingToolRows(flatNodes.map((item) => createRowCandidate(item.node, item.turnId)));
|
|
13
13
|
applyCompletedTurnTiming(candidates, turnById);
|
|
14
|
-
return groupRelatedToolCandidates(candidates).map((candidate) => candidate.row);
|
|
14
|
+
return groupRelatedToolCandidates(reconcileConceptualRowCandidates(candidates)).map((candidate) => candidate.row);
|
|
15
15
|
}
|
|
16
16
|
export function findActiveTurnStartedAt(traceView) {
|
|
17
17
|
if (!traceView)
|
|
@@ -100,7 +100,71 @@ function createRowCandidate(node, turnId) {
|
|
|
100
100
|
};
|
|
101
101
|
break;
|
|
102
102
|
}
|
|
103
|
-
return {
|
|
103
|
+
return {
|
|
104
|
+
...candidate,
|
|
105
|
+
row: {
|
|
106
|
+
...candidate.row,
|
|
107
|
+
id: compactTerminalRowIdentity(node),
|
|
108
|
+
...debugFields(node),
|
|
109
|
+
},
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
export function compactTerminalRowIdentity(node) {
|
|
113
|
+
if (node.type === "tool.call" || node.type === "tool.result" || node.type === "agent.delegation") {
|
|
114
|
+
const toolCallId = node.toolCallId ?? stableKeySuffix(node.stableKey, "tool:");
|
|
115
|
+
if (toolCallId)
|
|
116
|
+
return `terminal:tool:${toolCallId}`;
|
|
117
|
+
if (node.type === "agent.delegation" && node.linkedPiboSessionId) {
|
|
118
|
+
return `terminal:delegation:${node.linkedPiboSessionId}`;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
if ((node.type === "agent.async" || node.type === "yielded.run") && node.runId) {
|
|
122
|
+
return `terminal:run:${node.runId}`;
|
|
123
|
+
}
|
|
124
|
+
if (node.type === "assistant.message") {
|
|
125
|
+
const assistantId = stableKeySuffix(node.stableKey, "assistant:");
|
|
126
|
+
if (assistantId)
|
|
127
|
+
return `terminal:assistant:${assistantId}`;
|
|
128
|
+
}
|
|
129
|
+
if (node.type === "model.reasoning") {
|
|
130
|
+
const reasoningId = stableKeySuffix(node.stableKey, "reasoning:");
|
|
131
|
+
if (reasoningId)
|
|
132
|
+
return `terminal:reasoning:${reasoningId}`;
|
|
133
|
+
}
|
|
134
|
+
return node.id;
|
|
135
|
+
}
|
|
136
|
+
function stableKeySuffix(stableKey, prefix) {
|
|
137
|
+
if (!stableKey?.startsWith(prefix))
|
|
138
|
+
return undefined;
|
|
139
|
+
const suffix = stableKey.slice(prefix.length);
|
|
140
|
+
return suffix && suffix !== "undefined" ? suffix : undefined;
|
|
141
|
+
}
|
|
142
|
+
function reconcileConceptualRowCandidates(candidates) {
|
|
143
|
+
const reconciled = [];
|
|
144
|
+
const indexById = new Map();
|
|
145
|
+
for (const candidate of candidates) {
|
|
146
|
+
const existingIndex = indexById.get(candidate.row.id);
|
|
147
|
+
if (existingIndex === undefined) {
|
|
148
|
+
indexById.set(candidate.row.id, reconciled.length);
|
|
149
|
+
reconciled.push(candidate);
|
|
150
|
+
continue;
|
|
151
|
+
}
|
|
152
|
+
const existing = reconciled[existingIndex];
|
|
153
|
+
reconciled[existingIndex] = {
|
|
154
|
+
...candidate,
|
|
155
|
+
turnId: candidate.turnId ?? existing.turnId,
|
|
156
|
+
row: {
|
|
157
|
+
...existing.row,
|
|
158
|
+
...candidate.row,
|
|
159
|
+
sourceNodeIds: [...new Set([...existing.row.sourceNodeIds, ...candidate.row.sourceNodeIds])],
|
|
160
|
+
input: candidate.row.input ?? existing.row.input,
|
|
161
|
+
output: candidate.row.output ?? existing.row.output,
|
|
162
|
+
error: candidate.row.error ?? existing.row.error,
|
|
163
|
+
payloadRefs: { ...existing.row.payloadRefs, ...candidate.row.payloadRefs },
|
|
164
|
+
},
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
return reconciled;
|
|
104
168
|
}
|
|
105
169
|
function applyCompletedTurnTiming(candidates, turnById) {
|
|
106
170
|
for (const turn of turnById.values()) {
|
|
@@ -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 = {}) {
|