@pasko70/pibo 1.9.11 → 1.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/apps/chat/agent-profiles.js +2 -2
- package/dist/apps/chat/agent-store.js +16 -3
- package/dist/apps/chat/chat-request-normalizers.js +10 -0
- package/dist/apps/chat/data/timeline-query-service.js +11 -0
- package/dist/apps/chat/loop-api.js +176 -0
- package/dist/apps/chat/trace.js +2 -0
- package/dist/apps/chat/web-app.js +13 -6
- package/dist/apps/chat/workflow-manual-trigger-runtime.js +149 -46
- package/dist/apps/chat-ui/assets/{dist-yCYNNb5d.js → dist-BwKObYnX.js} +1 -1
- package/dist/apps/chat-ui/assets/{dist-BCB6zezO.js → dist-CKtT8YGm.js} +1 -1
- package/dist/apps/chat-ui/assets/{dist-CnVsqwSG.js → dist-CS7wdk0Z.js} +1 -1
- package/dist/apps/chat-ui/assets/{dist-HqTN67dc.js → dist-D-cxLQO1.js} +1 -1
- package/dist/apps/chat-ui/assets/{dist-BNMu92bb.js → dist-DUlaXAk7.js} +1 -1
- package/dist/apps/chat-ui/assets/{dist-CzE6k3F3.js → dist-DlATLa-U.js} +1 -1
- package/dist/apps/chat-ui/assets/{dist-Dq4GxJi3.js → dist-GdEM8UW1.js} +1 -1
- package/dist/apps/chat-ui/assets/{dist-BZ2eTC4f.js → dist-LHRs1Nhr.js} +1 -1
- package/dist/apps/chat-ui/assets/{dist-D811wJeV.js → dist-Y-AA2omI.js} +1 -1
- package/dist/apps/chat-ui/assets/{dist-WyXdYl-w.js → dist-nOLTkZrJ.js} +1 -1
- package/dist/apps/chat-ui/assets/{dist-BHa-kcGl.js → dist-wE9nop9V.js} +1 -1
- package/dist/apps/chat-ui/assets/{index-DwHJfmiF.js → index-8W_yMHQI.js} +6 -6
- package/dist/apps/chat-ui/index.html +1 -1
- package/dist/cli.js +23 -6
- package/dist/core/routed-session.js +30 -1
- package/dist/core/runtime.js +6 -1
- package/dist/core/session-router.js +4 -2
- package/dist/data/ingest-service.js +7 -0
- package/dist/data/message-store.js +11 -0
- package/dist/data/schema.js +2 -0
- package/dist/gateway/server.js +4 -2
- package/dist/gateway/web.js +2 -2
- package/dist/loops/channel.js +8 -0
- package/dist/loops/cli.js +208 -0
- package/dist/loops/plugin.js +16 -0
- package/dist/loops/prompts.js +83 -0
- package/dist/loops/service.js +357 -0
- package/dist/loops/stopping.js +170 -0
- package/dist/loops/store.js +531 -0
- package/dist/loops/templates.js +232 -0
- package/dist/loops/tools.js +167 -0
- package/dist/loops/types.js +1 -0
- package/dist/plugins/builtin.js +8 -0
- package/dist/plugins/registry.js +23 -12
- package/dist/resources/lifecycle.js +4 -6
- package/dist/resources/reaper-state.js +30 -3
- package/dist/resources/reaper.js +43 -15
- package/dist/shared/trace-engine.js +3 -2
- package/dist/shared/trace-event-projection.js +26 -0
- package/dist/tools/guides.js +51 -0
- package/dist/tools/index.js +23 -0
- package/dist/tools/registry.js +21 -3
- package/package.json +5 -2
- package/skills/builtin/loop/SKILL.md +69 -0
- package/skills/builtin/ralph-loop/SKILL.md +4 -2
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) {
|
|
@@ -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 = [];
|
package/dist/tools/guides.js
CHANGED
|
@@ -1,3 +1,54 @@
|
|
|
1
|
+
export const LOOP_GUIDE = {
|
|
2
|
+
name: 'loop',
|
|
3
|
+
description: 'Create, inspect, and control Pibo Goal and legacy Ralph loops from the CLI.',
|
|
4
|
+
content: `---
|
|
5
|
+
name: loop
|
|
6
|
+
description: Creates and controls persistent Goal Loops and legacy fresh-session Ralph loops.
|
|
7
|
+
allowed-tools: Bash(pibo:*), Bash(npm:*)
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# Loop CLI Tool
|
|
11
|
+
|
|
12
|
+
Use \`pibo loop\` as the standard continuous-work CLI. Goal mode is the default and continues one Pibo Session across turns. Use \`--mode ralph\` or \`pibo ralph\` only for legacy fresh-session runs.
|
|
13
|
+
|
|
14
|
+
## Discover
|
|
15
|
+
|
|
16
|
+
\`\`\`bash
|
|
17
|
+
pibo loop --help
|
|
18
|
+
pibo loop add --help
|
|
19
|
+
pibo loop templates --json
|
|
20
|
+
pibo loop conditions
|
|
21
|
+
\`\`\`
|
|
22
|
+
|
|
23
|
+
## Create a Goal Loop
|
|
24
|
+
|
|
25
|
+
\`\`\`bash
|
|
26
|
+
pibo loop add \\
|
|
27
|
+
--room <room-id> \\
|
|
28
|
+
--profile <profile> \\
|
|
29
|
+
--prompt "<complete objective>" \\
|
|
30
|
+
--token-budget <optional-positive-token-count> \\
|
|
31
|
+
--max-iterations <optional-run-fallback> \\
|
|
32
|
+
--start
|
|
33
|
+
\`\`\`
|
|
34
|
+
|
|
35
|
+
Goal-capable agents use native \`get_goal\`, \`create_goal\`, and \`update_goal\` tools. Agent Designer can disable the default-enabled \`pibo-goal-control\` package.
|
|
36
|
+
|
|
37
|
+
Use \`update_goal\` with \`complete\` only after current evidence proves every requirement. Use \`blocked\` only after the same impasse repeats for at least three consecutive Goal turns and progress requires user input or external change.
|
|
38
|
+
|
|
39
|
+
## Inspect and Control
|
|
40
|
+
|
|
41
|
+
\`\`\`bash
|
|
42
|
+
pibo loop list --all --json
|
|
43
|
+
pibo loop runs --job <job-id> --json
|
|
44
|
+
pibo loop start <job-id>
|
|
45
|
+
pibo loop stop <job-id>
|
|
46
|
+
pibo loop cancel <job-id>
|
|
47
|
+
\`\`\`
|
|
48
|
+
|
|
49
|
+
Token budgets count usage reported by completed assistant model messages. One request can overshoot because usage is known after the response returns.
|
|
50
|
+
`,
|
|
51
|
+
};
|
|
1
52
|
export const RALPH_GUIDE = {
|
|
2
53
|
name: 'ralph',
|
|
3
54
|
description: 'Create, inspect, and control Pibo Ralph jobs from the CLI.',
|
package/dist/tools/index.js
CHANGED
|
@@ -97,6 +97,10 @@ function printShow(name) {
|
|
|
97
97
|
if (entry.name === 'agent-browser') {
|
|
98
98
|
console.log(' pibo tools agent-browser');
|
|
99
99
|
}
|
|
100
|
+
if (entry.name === 'loop') {
|
|
101
|
+
console.log(' pibo tools loop');
|
|
102
|
+
console.log(' pibo loop templates');
|
|
103
|
+
}
|
|
100
104
|
if (entry.name === 'ralph') {
|
|
101
105
|
console.log(' pibo tools ralph');
|
|
102
106
|
console.log(' pibo ralph templates');
|
|
@@ -600,6 +604,21 @@ Next:
|
|
|
600
604
|
pibo tools agent-browser health
|
|
601
605
|
pibo tools agent-browser lease acquire`);
|
|
602
606
|
}
|
|
607
|
+
function printLoopDiscovery() {
|
|
608
|
+
console.log(`pibo tools loop - Goal-first Loop helpers
|
|
609
|
+
|
|
610
|
+
Commands:
|
|
611
|
+
pibo loop templates --json
|
|
612
|
+
pibo loop add --template goal-objective --room <room-id> --start --json
|
|
613
|
+
pibo loop list --all --json
|
|
614
|
+
pibo loop runs --job <job-id> --json
|
|
615
|
+
pibo loop stop <job-id>
|
|
616
|
+
pibo loop cancel <job-id>
|
|
617
|
+
|
|
618
|
+
Next:
|
|
619
|
+
pibo tools guide loop loop
|
|
620
|
+
pibo loop templates`);
|
|
621
|
+
}
|
|
603
622
|
function printRalphDiscovery() {
|
|
604
623
|
console.log(`pibo tools ralph - Ralph job helpers
|
|
605
624
|
|
|
@@ -702,6 +721,10 @@ export async function runToolsCli(argv = process.argv) {
|
|
|
702
721
|
.argument('<name>')
|
|
703
722
|
.description('Print shell exports for using the tool directly')
|
|
704
723
|
.action(printEnv);
|
|
724
|
+
program
|
|
725
|
+
.command('loop')
|
|
726
|
+
.description('Goal-first Loop helper commands')
|
|
727
|
+
.action(printLoopDiscovery);
|
|
705
728
|
program
|
|
706
729
|
.command('ralph')
|
|
707
730
|
.description('Ralph job helper commands')
|
package/dist/tools/registry.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { existsSync } from 'node:fs';
|
|
2
2
|
import { ensureAgentBrowserWrapper } from './agent-browser-wrapper.js';
|
|
3
3
|
import { detectDesktopEnv, hasDesktopDisplay, printDesktopEnvStatus, printLinuxVirtualDisplayHint } from './desktop-env.js';
|
|
4
|
-
import { AGENT_BROWSER_GUIDE, BROWSER_USE_GUIDE, GRAPHIFY_GUIDE, RALPH_GUIDE, REMOTE_BROWSER_GUIDE } from './guides.js';
|
|
4
|
+
import { AGENT_BROWSER_GUIDE, BROWSER_USE_GUIDE, GRAPHIFY_GUIDE, LOOP_GUIDE, RALPH_GUIDE, REMOTE_BROWSER_GUIDE } from './guides.js';
|
|
5
5
|
import { ensureLinuxVirtualDisplay } from './linux-virtual-display.js';
|
|
6
6
|
import { getToolNpmRuntimePaths, installToolNpmRuntime, printToolNpmRuntimeDoctor, removeToolNpmRuntime, } from './npm-runtime.js';
|
|
7
7
|
import { getToolPythonRuntimePaths, installToolPythonRuntime, runInheritedCommand, printToolPythonRuntimeDoctor, removeToolPythonRuntime, } from './python-runtime.js';
|
|
@@ -83,13 +83,31 @@ const REGISTRY = [
|
|
|
83
83
|
'Guide: `npm run dev -- tools guide graphify graphify`.',
|
|
84
84
|
].join('\n'),
|
|
85
85
|
},
|
|
86
|
+
{
|
|
87
|
+
name: 'loop',
|
|
88
|
+
description: 'Pibo-native goal-first continuous agent loop runner.',
|
|
89
|
+
kind: 'internal',
|
|
90
|
+
guides: [LOOP_GUIDE],
|
|
91
|
+
notes: [
|
|
92
|
+
'Loop is built into the pibo CLI; no external runtime installation is required.',
|
|
93
|
+
'Goal mode reuses one Pibo Session and is the default; Ralph mode remains available for fresh-session compatibility.',
|
|
94
|
+
'Goal lifecycle tools and token budgets are available when the selected agent enables pibo-goal-control.',
|
|
95
|
+
],
|
|
96
|
+
agentContextSnippet: [
|
|
97
|
+
'Goal-first continuous Pibo agent loop runner.',
|
|
98
|
+
'Use `pibo loop templates`, then create with `pibo loop add --template goal-objective --room <room-id> --start`.',
|
|
99
|
+
'Optional budgets: `--token-budget <n>` and `--max-iterations <n>`.',
|
|
100
|
+
'Inspect/control with `pibo loop list --json`, `runs --job <id> --json`, `stop <id>`, `cancel <id>`.',
|
|
101
|
+
'Guide: `pibo tools guide loop loop`.',
|
|
102
|
+
].join('\n'),
|
|
103
|
+
},
|
|
86
104
|
{
|
|
87
105
|
name: 'ralph',
|
|
88
|
-
description: 'Pibo
|
|
106
|
+
description: 'Legacy Pibo Ralph alias for fresh-session continuous agent jobs.',
|
|
89
107
|
kind: 'internal',
|
|
90
108
|
guides: [RALPH_GUIDE],
|
|
91
109
|
notes: [
|
|
92
|
-
'Ralph is
|
|
110
|
+
'Ralph is the legacy fresh-session alias; prefer pibo loop for new Goal work.',
|
|
93
111
|
'Ralph jobs are app-global; use room targets or the shared default target when creating jobs.',
|
|
94
112
|
'Prefer templates for repeatable jobs, and use --json for automation-safe inspection.',
|
|
95
113
|
],
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pasko70/pibo",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.10.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"imports": {
|
|
6
6
|
"vscode": "./src/apps/chat-vscode/extension/src/vscode-shim.js"
|
|
@@ -56,6 +56,8 @@
|
|
|
56
56
|
"@earendil-works/pi-ai": "0.80.6",
|
|
57
57
|
"@earendil-works/pi-coding-agent": "0.80.6",
|
|
58
58
|
"@earendil-works/pi-tui": "0.80.6",
|
|
59
|
+
"@langchain/core": "^1.2.3",
|
|
60
|
+
"@langchain/langgraph": "^1.4.8",
|
|
59
61
|
"@mdxeditor/editor": "^3.55.0",
|
|
60
62
|
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
61
63
|
"@tailwindcss/vite": "^4.2.4",
|
|
@@ -76,7 +78,8 @@
|
|
|
76
78
|
"react-markdown": "^10.1.0",
|
|
77
79
|
"react-virtuoso": "^4.18.6",
|
|
78
80
|
"remark-gfm": "^4.0.1",
|
|
79
|
-
"tailwindcss": "^4.2.4"
|
|
81
|
+
"tailwindcss": "^4.2.4",
|
|
82
|
+
"zod": "4.4.1"
|
|
80
83
|
},
|
|
81
84
|
"devDependencies": {
|
|
82
85
|
"@tanstack/router-plugin": "^1.167.28",
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: loop
|
|
3
|
+
description: Plan, create, run, monitor, resume, and review Pibo Goal Loops and legacy Ralph loops. Use whenever the user asks for a persistent goal, continuous loop, autonomous multi-turn objective, token-budgeted goal, Loop job, Goal status, blocked Goal, or the pibo loop CLI.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Pibo Loop Workflow
|
|
7
|
+
|
|
8
|
+
Use Goal mode for persistent objectives that should continue in the same Pibo Session. Use legacy Ralph mode only when each run should start with fresh session context.
|
|
9
|
+
|
|
10
|
+
Discover the live CLI progressively:
|
|
11
|
+
|
|
12
|
+
```bash
|
|
13
|
+
pibo loop --help
|
|
14
|
+
pibo loop add --help
|
|
15
|
+
pibo loop templates --json
|
|
16
|
+
pibo loop conditions
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## Goal lifecycle
|
|
20
|
+
|
|
21
|
+
Goal-capable profiles expose native tools:
|
|
22
|
+
|
|
23
|
+
- `get_goal`: inspect authoritative status, objective, token budget, tokens used, remaining tokens, and elapsed active time.
|
|
24
|
+
- `create_goal`: create a persistent Goal only when the user or system explicitly requests one.
|
|
25
|
+
- `update_goal`: mark the current Goal `complete` after a strict completion audit, or `blocked` after the same impasse repeats for at least three consecutive Goal turns.
|
|
26
|
+
|
|
27
|
+
These are native Pibo tools, not MCP tools. Agent Designer exposes them as the default-enabled `pibo-goal-control` package. If that package is disabled, the agent cannot change Goal lifecycle status itself.
|
|
28
|
+
|
|
29
|
+
## CLI creation
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
pibo loop add \
|
|
33
|
+
--room <room-id> \
|
|
34
|
+
--profile <profile> \
|
|
35
|
+
--prompt "<complete objective>" \
|
|
36
|
+
--token-budget <optional-positive-token-count> \
|
|
37
|
+
--max-iterations <optional-run-fallback> \
|
|
38
|
+
--start
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
Prefer creating the job stopped when its prompt, target, profile, or safety boundaries still need review.
|
|
42
|
+
|
|
43
|
+
## Completion and blocked rules
|
|
44
|
+
|
|
45
|
+
- Treat completion as unproven until current evidence covers every explicit requirement and deliverable.
|
|
46
|
+
- Do not use `complete` for partial progress, a plausible result, budget exhaustion, or because the current turn is ending.
|
|
47
|
+
- Do not use `blocked` on the first blocker occurrence.
|
|
48
|
+
- Use `blocked` only after the same condition repeats for at least three consecutive Goal turns and meaningful progress requires user input or an external-state change.
|
|
49
|
+
- Resuming a blocked Goal begins a fresh blocked audit.
|
|
50
|
+
|
|
51
|
+
## Token budgets
|
|
52
|
+
|
|
53
|
+
Pibo accumulates model usage reported by completed assistant model messages. A Goal becomes `budget_limited` when reported usage reaches or exceeds its budget. One provider request can overshoot because usage is known only after the response reports it.
|
|
54
|
+
|
|
55
|
+
Increase or clear the token budget before resuming a budget-limited Goal.
|
|
56
|
+
|
|
57
|
+
## Operations
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
pibo loop list --all --json
|
|
61
|
+
pibo loop runs --job <job-id> --json
|
|
62
|
+
pibo loop start <job-id>
|
|
63
|
+
pibo loop stop <job-id>
|
|
64
|
+
pibo loop cancel <job-id>
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
Use `stop` for graceful pause after the current session. Use `cancel` only when the active session must be aborted.
|
|
68
|
+
|
|
69
|
+
For implementation work involving Docker workers, worktrees, browser checks, or pull requests, also use `pibo-docker-system` and `github-server-flow`.
|
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: ralph-loop
|
|
3
|
-
description: Plan, create, run, monitor, and review Ralph implementation loops
|
|
3
|
+
description: Plan, create, run, monitor, and review legacy Ralph fresh-session implementation loops. Use when the user explicitly asks for Ralph compatibility, Ralph PRD batches, or a new Pibo Session per run; use the loop skill for standard persistent Goal Loops.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Ralph Loop Workflow
|
|
7
7
|
|
|
8
|
-
Use this skill to create and operate a Ralph implementation loop safely. Ralph
|
|
8
|
+
Use this skill to create and operate a legacy Ralph implementation loop safely. Ralph starts a fresh Pibo Session for each run. For new same-session persistent goals, use the `loop` skill and `pibo loop` instead.
|
|
9
|
+
|
|
10
|
+
Ralph runs repeated Pibo agent sessions against an objective, usually from PRD stories. The core pattern is:
|
|
9
11
|
|
|
10
12
|
1. Prepare a clean git worktree.
|
|
11
13
|
2. Reuse a dedicated Docker dev worker for runtime, builds, tests, gateway, and browser checks.
|