@pasko70/pibo 1.13.0 → 1.15.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/static-assets.js +3 -1
- package/dist/apps/chat/web-app.js +10 -0
- package/dist/apps/{context-files-ui/assets/dist-BFRDpzcv.js → chat-ui/assets/dist-BFwSuVfD.js} +1 -1
- package/dist/apps/chat-ui/assets/{dist-XmG4qG-A.js → dist-BYTi90un.js} +1 -1
- package/dist/apps/{context-files-ui/assets/dist-B_zXPNMb.js → chat-ui/assets/dist-Bi74WdBU.js} +1 -1
- package/dist/apps/chat-ui/assets/{dist-UYBI2F8E.js → dist-CYMM1_bS.js} +1 -1
- package/dist/apps/chat-ui/assets/{dist-DVPXynJE.js → dist-CuIwfDgF.js} +1 -1
- package/dist/apps/{context-files-ui/assets/dist-B5mpygOZ.js → chat-ui/assets/dist-DS1ScAMf.js} +1 -1
- package/dist/apps/chat-ui/assets/{dist-B_8EcoB6.js → dist-DUgrMhHX.js} +1 -1
- package/dist/apps/chat-ui/assets/{dist-CVLKu7NV.js → dist-Dq3i1LVZ.js} +1 -1
- package/dist/apps/chat-ui/assets/{dist-DugRsLaG.js → dist-Dy5L1xOD.js} +1 -1
- package/dist/apps/{context-files-ui/assets/dist-D6pYe6d_.js → chat-ui/assets/dist-Zy3KnDp7.js} +1 -1
- package/dist/apps/chat-ui/assets/index-BZO4zpMi.js +237 -0
- package/dist/apps/chat-ui/assets/index-CoCl8FG8.css +1 -0
- package/dist/apps/chat-ui/index.html +2 -2
- package/dist/apps/chat-vscode-web/assets/index-V_pKPVAm.js +41 -0
- package/dist/apps/chat-vscode-web/index.html +1 -1
- package/dist/apps/{chat-ui/assets/dist-CnX234jg.js → context-files-ui/assets/dist-B7gXtTZC.js} +1 -1
- package/dist/apps/{chat-ui/assets/dist-CELRUR8b.js → context-files-ui/assets/dist-BD262Ouw.js} +1 -1
- package/dist/apps/context-files-ui/assets/{dist-Em3LWmNi.js → dist-BKuGdcnX.js} +1 -1
- package/dist/apps/{chat-ui/assets/dist-CVmpu9FK.js → context-files-ui/assets/dist-C-Jm45P4.js} +1 -1
- package/dist/apps/context-files-ui/assets/{dist-DM6yvMZv.js → dist-CHdx1Jri.js} +1 -1
- package/dist/apps/context-files-ui/assets/{dist-BLI6sQZG.js → dist-CULMH-fB.js} +1 -1
- package/dist/apps/context-files-ui/assets/{dist-CLrlJjPP.js → dist-Cjq6RWEt.js} +1 -1
- package/dist/apps/context-files-ui/assets/{dist-D8ppb7gk.js → dist-CntqFySz.js} +1 -1
- package/dist/apps/context-files-ui/assets/{dist-SEP88Pg7.js → dist-DxEGebCR.js} +1 -1
- package/dist/apps/{chat-ui/assets/dist-KOXty1JB.js → context-files-ui/assets/dist-kPuQud7t.js} +1 -1
- package/dist/apps/context-files-ui/assets/index-DZWsbuvg.js +202 -0
- package/dist/apps/context-files-ui/index.html +1 -1
- package/dist/apps/vscode-artifacts/latest.vsix +0 -0
- package/dist/apps/vscode-artifacts/pibo-vscode-ext-1.15.0.vsix +0 -0
- package/dist/cli-session/localSessionSource.js +2 -0
- package/dist/core/runtime.js +27 -5
- package/dist/core/session-router.js +3 -0
- package/dist/gateway/client.js +8 -0
- package/dist/gateway/server.js +18 -2
- package/dist/gateway/web.js +1 -0
- package/dist/local/extension.js +2 -0
- package/dist/loops/plugin.js +34 -1
- package/dist/loops/service.js +85 -0
- package/dist/mcp/config-command.js +5 -3
- package/dist/plugins/builtin.js +7 -0
- package/dist/plugins/context-files-store.js +287 -101
- package/dist/plugins/context-files.js +102 -154
- package/dist/session-ui/terminalRows.js +12 -2
- package/dist/shared/trace-live-reducer.js +6 -1
- package/dist/tools/browser-use-leases.js +16 -0
- package/dist/tools/codex-browser-node-repl.js +224 -0
- package/dist/tools/codex-browser-node-worker-source.js +403 -0
- package/dist/tools/codex-browser.js +461 -0
- package/dist/web/channel.js +105 -16
- package/dist/web/http.js +14 -2
- package/package.json +13 -7
- package/dist/apps/chat-ui/assets/index-DhFQ1th-.js +0 -237
- package/dist/apps/chat-ui/assets/index-hjygk9Ol.css +0 -1
- package/dist/apps/chat-vscode-web/assets/index-1wWonouX.js +0 -41
- package/dist/apps/context-files-ui/assets/index-C7X2UvWe.js +0 -202
- package/dist/apps/vscode-artifacts/pibo-vscode-ext-1.13.0.vsix +0 -0
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
<meta charset="UTF-8" />
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
6
6
|
<title>Pibo Context Files</title>
|
|
7
|
-
<script type="module" crossorigin src="/apps/context-files/assets/index-
|
|
7
|
+
<script type="module" crossorigin src="/apps/context-files/assets/index-DZWsbuvg.js"></script>
|
|
8
8
|
<link rel="modulepreload" crossorigin href="/apps/context-files/assets/dist-D1KyNDg5.js">
|
|
9
9
|
<link rel="stylesheet" crossorigin href="/apps/context-files/assets/index-Cs4XQITe.css">
|
|
10
10
|
</head>
|
|
Binary file
|
|
Binary file
|
|
@@ -1050,6 +1050,8 @@ function executionParamsForSlash(command, args) {
|
|
|
1050
1050
|
const trimmed = args?.trim();
|
|
1051
1051
|
if (command === "compact" && trimmed)
|
|
1052
1052
|
return { customInstructions: trimmed };
|
|
1053
|
+
if (command === "goal")
|
|
1054
|
+
return { command: trimmed ?? "" };
|
|
1053
1055
|
if (command === "thinking" && trimmed)
|
|
1054
1056
|
return { level: trimmed };
|
|
1055
1057
|
if (command === "model" && trimmed) {
|
package/dist/core/runtime.js
CHANGED
|
@@ -25,6 +25,7 @@ import { registerOpenAiGpt56Models } from "../providers/openai-gpt56.js";
|
|
|
25
25
|
import { PIBO_APP_CONTEXT } from "../app-context.js";
|
|
26
26
|
import { createRuntimeToolDefinition } from "../tools/runtime/tool.js";
|
|
27
27
|
import { RuntimeSessionRegistry } from "../tools/runtime/registry.js";
|
|
28
|
+
import { CODEX_BROWSER_TOOL_NAMES, CodexBrowserSessionController, createCodexBrowserToolDefinitions, } from "../tools/codex-browser.js";
|
|
28
29
|
import { compactValidationToolResultForContext } from "./test-output-compaction.js";
|
|
29
30
|
import { installPiboTranscriptIntegrity } from "./transcript-integrity.js";
|
|
30
31
|
function hasOwnRetrySetting(settings, key) {
|
|
@@ -102,12 +103,18 @@ function getEnabledSkillPaths(cwd, profile) {
|
|
|
102
103
|
.filter((skill) => skill.enabled !== false)
|
|
103
104
|
.map((skill) => resolveProfilePath(cwd, skill.path));
|
|
104
105
|
}
|
|
105
|
-
function getEnabledToolDefinitions(profile, options, subagentRunner, runToolController, runtimeToolController) {
|
|
106
|
+
function getEnabledToolDefinitions(profile, options, subagentRunner, runToolController, runtimeToolController, codexBrowserController) {
|
|
106
107
|
const runtimeProfileTool = profile.tools.find(isEnabledRuntimeTool);
|
|
107
108
|
const runtimeTool = runtimeProfileTool && runtimeToolController
|
|
108
109
|
? createRuntimeToolDefinition(runtimeToolController)
|
|
109
110
|
: undefined;
|
|
110
|
-
const
|
|
111
|
+
const selectedCodexBrowserToolNames = profile.tools
|
|
112
|
+
.filter(isEnabledCodexBrowserTool)
|
|
113
|
+
.map((tool) => tool.name);
|
|
114
|
+
const codexBrowserTools = codexBrowserController
|
|
115
|
+
? createCodexBrowserToolDefinitions(codexBrowserController, selectedCodexBrowserToolNames)
|
|
116
|
+
: [];
|
|
117
|
+
const profileTools = profile.tools.filter((tool) => !isRuntimeTool(tool) && !isCodexBrowserTool(tool)).filter(hasEnabledToolDefinition);
|
|
111
118
|
const profileToolDefinitions = profileTools.map((tool) => getToolDefinition(tool, options.toolContext));
|
|
112
119
|
const codexCompatEnabled = profile.toolPackages.codexCompat === true;
|
|
113
120
|
const runControlEnabled = profile.toolPackages.runControl === true;
|
|
@@ -129,6 +136,7 @@ function getEnabledToolDefinitions(profile, options, subagentRunner, runToolCont
|
|
|
129
136
|
...(runControlBashTool ? [runControlBashTool] : []),
|
|
130
137
|
...profileTools.filter((tool) => tool.yieldable !== false).map((tool) => getToolDefinition(tool, options.toolContext)),
|
|
131
138
|
...(runtimeTool && runtimeProfileTool?.yieldable !== false ? [runtimeTool] : []),
|
|
139
|
+
...codexBrowserTools.filter((definition) => profile.tools.find((tool) => tool.name === definition.name)?.yieldable !== false),
|
|
132
140
|
...subagentTools,
|
|
133
141
|
...codexCompatTools,
|
|
134
142
|
];
|
|
@@ -139,6 +147,7 @@ function getEnabledToolDefinitions(profile, options, subagentRunner, runToolCont
|
|
|
139
147
|
...(runControlBashTool ? [runControlBashTool] : []),
|
|
140
148
|
...profileToolDefinitions,
|
|
141
149
|
...(runtimeTool ? [runtimeTool] : []),
|
|
150
|
+
...codexBrowserTools,
|
|
142
151
|
...subagentTools,
|
|
143
152
|
...codexCompatTools,
|
|
144
153
|
...goalTools,
|
|
@@ -159,6 +168,12 @@ function isRuntimeTool(tool) {
|
|
|
159
168
|
function isEnabledRuntimeTool(tool) {
|
|
160
169
|
return tool.enabled !== false && isRuntimeTool(tool);
|
|
161
170
|
}
|
|
171
|
+
function isCodexBrowserTool(tool) {
|
|
172
|
+
return tool.builtInPiboTool === "codex_browser" || CODEX_BROWSER_TOOL_NAMES.includes(tool.name);
|
|
173
|
+
}
|
|
174
|
+
function isEnabledCodexBrowserTool(tool) {
|
|
175
|
+
return tool.enabled !== false && isCodexBrowserTool(tool);
|
|
176
|
+
}
|
|
162
177
|
function isGeneratedPiboTool(name) {
|
|
163
178
|
return name === "runtime" || name.startsWith("pibo_subagent_") || name.startsWith("pibo_run_") || PIBO_GOAL_TOOL_NAMES.includes(name);
|
|
164
179
|
}
|
|
@@ -280,6 +295,12 @@ export async function createPiboRuntime(options = {}) {
|
|
|
280
295
|
const localRuntimeRegistry = ownsLocalRuntimeRegistry ? new RuntimeSessionRegistry({ cwd: runtimeCwd }) : undefined;
|
|
281
296
|
const runtimeToolController = options.runtimeToolController
|
|
282
297
|
?? localRuntimeRegistry?.createController(profile.sessionId ?? "local");
|
|
298
|
+
const codexBrowserController = profile.tools.some(isEnabledCodexBrowserTool)
|
|
299
|
+
? new CodexBrowserSessionController({
|
|
300
|
+
cwd: runtimeCwd,
|
|
301
|
+
piboSessionId: options.sessionContext?.piboSessionId ?? profile.sessionId ?? runtimeSessionManager.getSessionId(),
|
|
302
|
+
})
|
|
303
|
+
: undefined;
|
|
283
304
|
const customTools = getEnabledToolDefinitions(profile, {
|
|
284
305
|
runtimeCwd,
|
|
285
306
|
shellCommandPrefix: services.settingsManager.getShellCommandPrefix(),
|
|
@@ -290,7 +311,7 @@ export async function createPiboRuntime(options = {}) {
|
|
|
290
311
|
profileName: profile.profileName,
|
|
291
312
|
getActiveMessage: options.sessionContext?.getActiveMessage,
|
|
292
313
|
},
|
|
293
|
-
}, options.subagentRunner, options.runToolController, runtimeToolController);
|
|
314
|
+
}, options.subagentRunner, options.runToolController, runtimeToolController, codexBrowserController);
|
|
294
315
|
const modelDefaults = options.modelDefaults ?? loadPiboModelDefaults(runtimeCwd);
|
|
295
316
|
const created = await createAgentSessionFromServices({
|
|
296
317
|
services,
|
|
@@ -324,6 +345,7 @@ export async function createPiboRuntime(options = {}) {
|
|
|
324
345
|
if (localRuntimeRegistry) {
|
|
325
346
|
void localRuntimeRegistry.closeControllerSessions(profile.sessionId ?? "local", { force: true });
|
|
326
347
|
}
|
|
348
|
+
void codexBrowserController?.dispose();
|
|
327
349
|
originalDispose();
|
|
328
350
|
};
|
|
329
351
|
return {
|
|
@@ -444,8 +466,8 @@ export async function inspectPiboProfile(options = {}) {
|
|
|
444
466
|
})),
|
|
445
467
|
tools: profile.tools.map((tool) => ({
|
|
446
468
|
name: tool.name,
|
|
447
|
-
hasDefinition: Boolean(tool.definition) || Boolean(tool.createDefinition) || isRuntimeTool(tool),
|
|
448
|
-
registered: registeredToolNames.has(tool.name) || tool.providerTool !== undefined || isRuntimeTool(tool),
|
|
469
|
+
hasDefinition: Boolean(tool.definition) || Boolean(tool.createDefinition) || isRuntimeTool(tool) || isCodexBrowserTool(tool),
|
|
470
|
+
registered: registeredToolNames.has(tool.name) || tool.providerTool !== undefined || isRuntimeTool(tool) || isCodexBrowserTool(tool),
|
|
449
471
|
active: activeToolNames.has(tool.name) || tool.providerTool !== undefined,
|
|
450
472
|
})).concat(generatedTools),
|
|
451
473
|
subagents: profile.subagents.map((subagent) => {
|
|
@@ -210,6 +210,9 @@ export class PiboSessionRouter {
|
|
|
210
210
|
recoveredRuns: this.runRegistry.listRecoveredRuns(),
|
|
211
211
|
}) ?? []
|
|
212
212
|
: [];
|
|
213
|
+
if (recoveredRuntimeState.length > 0 && options.runtimeInstanceId) {
|
|
214
|
+
console.error(`[pibo] authoritative runtime ${options.runtimeInstanceId} recovered ${recoveredRuntimeState.length} interrupted turn(s)`);
|
|
215
|
+
}
|
|
213
216
|
for (const recovery of recoveredRuntimeState) {
|
|
214
217
|
const session = this.sessionStore.get(recovery.event.piboSessionId);
|
|
215
218
|
if (session)
|
package/dist/gateway/client.js
CHANGED
|
@@ -186,6 +186,14 @@ export async function runGatewayClient(options = {}) {
|
|
|
186
186
|
});
|
|
187
187
|
continue;
|
|
188
188
|
}
|
|
189
|
+
if (text === "/goal" || text.startsWith("/goal ")) {
|
|
190
|
+
writeFrame(socket, {
|
|
191
|
+
type: "req",
|
|
192
|
+
id: randomUUID(),
|
|
193
|
+
event: { type: "execution", piboSessionId, action: "goal", params: { command: text.slice("/goal".length).trim() } },
|
|
194
|
+
});
|
|
195
|
+
continue;
|
|
196
|
+
}
|
|
189
197
|
writeFrame(socket, {
|
|
190
198
|
type: "req",
|
|
191
199
|
id: randomUUID(),
|
package/dist/gateway/server.js
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
|
+
import { randomUUID } from "node:crypto";
|
|
1
2
|
import { createServer } from "node:net";
|
|
2
3
|
import { createDefaultPiboPluginRegistry, createPiboProfileFromRegistryOrDefault, resolvePiboProfileNameFromRegistryOrDefault } from "../plugins/builtin.js";
|
|
3
4
|
import { PiboSessionRouter } from "../core/session-router.js";
|
|
4
5
|
import { createLoopMessagePreflight } from "../loops/store.js";
|
|
5
6
|
import { loadPiboModelDefaults, selectRequestedModelProfile } from "../core/model-defaults.js";
|
|
6
7
|
import { ResourceReaperService } from "../resources/reaper.js";
|
|
8
|
+
import { InMemoryPiboSessionStore } from "../sessions/store.js";
|
|
7
9
|
import { DEFAULT_GATEWAY_HOST, DEFAULT_GATEWAY_PORT, encodeFrame, errorResponse, isGatewayRequestFrame, isGatewaySubscribeFrame, } from "./protocol.js";
|
|
8
10
|
import { releaseFallbackGatewayPid, releaseGatewayPid, writeFallbackGatewayPid, writeGatewayPid } from "./pidfile.js";
|
|
9
11
|
const DEFAULT_MAX_BACKPRESSURE_FRAMES = 1_000;
|
|
@@ -118,12 +120,15 @@ async function createGatewaySessionStore(options) {
|
|
|
118
120
|
const { SqlitePiboSessionStore } = await import("../sessions/sqlite-store.js");
|
|
119
121
|
return new SqlitePiboSessionStore(options.sessionDbPath);
|
|
120
122
|
}
|
|
123
|
+
if (options.persistSession === false)
|
|
124
|
+
return new InMemoryPiboSessionStore();
|
|
121
125
|
const { createDefaultPiboDataSessionStore } = await import("../sessions/pibo-data-store.js");
|
|
122
126
|
return createDefaultPiboDataSessionStore();
|
|
123
127
|
}
|
|
124
128
|
export class PiboGatewayServer {
|
|
125
129
|
options;
|
|
126
130
|
pluginRegistry;
|
|
131
|
+
runtimeInstanceId;
|
|
127
132
|
sessionStore;
|
|
128
133
|
ownsSessionStore = false;
|
|
129
134
|
router;
|
|
@@ -137,6 +142,7 @@ export class PiboGatewayServer {
|
|
|
137
142
|
constructor(options = {}) {
|
|
138
143
|
this.options = options;
|
|
139
144
|
this.pluginRegistry = options.pluginRegistry ?? createDefaultPiboPluginRegistry();
|
|
145
|
+
this.runtimeInstanceId = options.runtimeInstanceId ?? `gateway:${process.pid}:${randomUUID()}`;
|
|
140
146
|
}
|
|
141
147
|
async start() {
|
|
142
148
|
if (this.server)
|
|
@@ -144,12 +150,16 @@ export class PiboGatewayServer {
|
|
|
144
150
|
this.validateChannels();
|
|
145
151
|
this.sessionStore = this.options.sessionStore ?? (await createGatewaySessionStore(this.options));
|
|
146
152
|
this.ownsSessionStore = !this.options.sessionStore;
|
|
153
|
+
const hasExplicitPersistentStore = this.options.sessionStore !== undefined || this.options.sessionDbPath !== undefined;
|
|
154
|
+
const recoverInterruptedRuntimeState = this.options.authoritativeRuntime === true
|
|
155
|
+
&& (this.options.persistSession !== false || hasExplicitPersistentStore);
|
|
147
156
|
this.router = new PiboSessionRouter({
|
|
148
157
|
persistSession: this.options.persistSession,
|
|
149
158
|
pluginRegistry: this.pluginRegistry,
|
|
150
159
|
sessionStore: this.sessionStore,
|
|
151
160
|
messagePreflight: createLoopMessagePreflight({ path: this.options.loopStorePath }),
|
|
152
|
-
recoverInterruptedRuntimeState
|
|
161
|
+
recoverInterruptedRuntimeState,
|
|
162
|
+
runtimeInstanceId: recoverInterruptedRuntimeState ? this.runtimeInstanceId : undefined,
|
|
153
163
|
});
|
|
154
164
|
this.unsubscribe = this.router.subscribe((event) => this.broadcastRouterEvent(event));
|
|
155
165
|
this.server = createServer((socket) => this.handleSocket(socket));
|
|
@@ -270,6 +280,8 @@ export class PiboGatewayServer {
|
|
|
270
280
|
getDiagnostics() {
|
|
271
281
|
const connectionDetails = [...this.connections].map((connection) => ({ ...connection.diagnostics }));
|
|
272
282
|
return {
|
|
283
|
+
runtimeInstanceId: this.runtimeInstanceId,
|
|
284
|
+
authoritativeRuntime: this.options.authoritativeRuntime === true,
|
|
273
285
|
connections: connectionDetails.length,
|
|
274
286
|
slowConnections: connectionDetails.filter((connection) => connection.slow).length,
|
|
275
287
|
droppedEvents: this.droppedRouterEvents,
|
|
@@ -377,7 +389,11 @@ export async function runGatewayServer(options = {}) {
|
|
|
377
389
|
const releasePid = fallbackMode ? releaseFallbackGatewayPid : releaseGatewayPid;
|
|
378
390
|
let server;
|
|
379
391
|
try {
|
|
380
|
-
server = new PiboGatewayServer({
|
|
392
|
+
server = new PiboGatewayServer({
|
|
393
|
+
...options,
|
|
394
|
+
authoritativeRuntime: options.authoritativeRuntime ?? true,
|
|
395
|
+
resourceReaper: resolveGatewayResourceReaperOptions(options),
|
|
396
|
+
});
|
|
381
397
|
await server.start();
|
|
382
398
|
}
|
|
383
399
|
catch (error) {
|
package/dist/gateway/web.js
CHANGED
|
@@ -195,6 +195,7 @@ export async function runWebGatewayServer(options = {}) {
|
|
|
195
195
|
const pluginRegistry = resolvedOptions.pluginRegistry ?? createWebPiboPluginRegistry(resolvedOptions);
|
|
196
196
|
server = new PiboGatewayServer({
|
|
197
197
|
...resolvedOptions,
|
|
198
|
+
authoritativeRuntime: resolvedOptions.authoritativeRuntime ?? true,
|
|
198
199
|
pluginRegistry,
|
|
199
200
|
resourceReaper: resolveGatewayResourceReaperOptions(resolvedOptions),
|
|
200
201
|
loopStorePath: resolvedOptions.chat?.ralphStorePath,
|
package/dist/local/extension.js
CHANGED
|
@@ -202,6 +202,8 @@ function createExecutionParams(slashCommand, args = "") {
|
|
|
202
202
|
}
|
|
203
203
|
if (slashCommand === "/compact")
|
|
204
204
|
return trimmedArgs ? { customInstructions: trimmedArgs } : undefined;
|
|
205
|
+
if (slashCommand === "/goal")
|
|
206
|
+
return { command: trimmedArgs };
|
|
205
207
|
return undefined;
|
|
206
208
|
}
|
|
207
209
|
function formatExecutionResult(event) {
|
package/dist/loops/plugin.js
CHANGED
|
@@ -1,7 +1,24 @@
|
|
|
1
1
|
import { definePiboPlugin } from '../plugins/registry.js';
|
|
2
|
-
import { createPiboLoopChannel } from './channel.js';
|
|
2
|
+
import { createPiboLoopChannel, getPiboLoopService } from './channel.js';
|
|
3
3
|
import { createBuiltInLoopStopConditions } from './stopping.js';
|
|
4
4
|
import { configurePiboGoalToolStorePath } from './tools.js';
|
|
5
|
+
function objectParams(event) {
|
|
6
|
+
const params = 'params' in event ? event.params : undefined;
|
|
7
|
+
return params && typeof params === 'object' && !Array.isArray(params) ? params : undefined;
|
|
8
|
+
}
|
|
9
|
+
export function parsePiboSessionGoalCommand(event) {
|
|
10
|
+
const command = objectParams(event)?.command;
|
|
11
|
+
if (typeof command !== 'string' || !command.trim())
|
|
12
|
+
throw new Error('Usage: /goal <objective> | /goal pause | /goal resume');
|
|
13
|
+
const normalized = command.trim();
|
|
14
|
+
if (normalized.toLowerCase() === 'pause')
|
|
15
|
+
return { operation: 'pause' };
|
|
16
|
+
if (normalized.toLowerCase() === 'resume')
|
|
17
|
+
return { operation: 'resume' };
|
|
18
|
+
if (normalized.length > 20_000)
|
|
19
|
+
throw new Error('Goal objective is too long');
|
|
20
|
+
return { operation: 'set', objective: normalized };
|
|
21
|
+
}
|
|
5
22
|
export function createPiboLoopPlugin(options = {}) {
|
|
6
23
|
configurePiboGoalToolStorePath(options.loopStorePath);
|
|
7
24
|
return definePiboPlugin({
|
|
@@ -10,6 +27,22 @@ export function createPiboLoopPlugin(options = {}) {
|
|
|
10
27
|
register(api) {
|
|
11
28
|
for (const condition of createBuiltInLoopStopConditions())
|
|
12
29
|
api.registerLoopStopCondition(condition);
|
|
30
|
+
api.registerGatewayAction({
|
|
31
|
+
name: 'goal',
|
|
32
|
+
description: 'Create or update the session Goal Loop. Use /goal pause or /goal resume to control it.',
|
|
33
|
+
slashCommands: ['goal'],
|
|
34
|
+
execute(context, event) {
|
|
35
|
+
const service = getPiboLoopService();
|
|
36
|
+
if (!service)
|
|
37
|
+
throw new Error('Loop service is not running');
|
|
38
|
+
const command = parsePiboSessionGoalCommand(event);
|
|
39
|
+
if (command.operation === 'pause')
|
|
40
|
+
return service.pauseSessionGoal(context.piboSessionId);
|
|
41
|
+
if (command.operation === 'resume')
|
|
42
|
+
return service.resumeSessionGoal(context.piboSessionId);
|
|
43
|
+
return service.setSessionGoal(context.piboSessionId, command.objective);
|
|
44
|
+
},
|
|
45
|
+
});
|
|
13
46
|
api.registerChannel(createPiboLoopChannel(options));
|
|
14
47
|
},
|
|
15
48
|
});
|
package/dist/loops/service.js
CHANGED
|
@@ -44,6 +44,8 @@ function failureRecovery(details) {
|
|
|
44
44
|
return details?.retryable === false ? 'Resolve the reported non-retryable failure, then explicitly restart the Goal.' : 'Pibo will retry automatically after the recorded backoff.';
|
|
45
45
|
}
|
|
46
46
|
function isTerminalGoalStatus(status) { return status === 'complete' || status === 'blocked' || status === 'budget_limited'; }
|
|
47
|
+
function currentGoalStatus(job) { return job.state.goalStatus ?? (job.enabled ? 'active' : 'paused'); }
|
|
48
|
+
function goalName(objective) { return objective.replace(/\s+/g, ' ').trim().slice(0, 80); }
|
|
47
49
|
function retryBackoffMs(consecutiveErrors, baseMs, maxMs, jitterRatio, random) {
|
|
48
50
|
const exponent = Math.max(0, Math.min(30, consecutiveErrors - 1));
|
|
49
51
|
const bounded = Math.min(maxMs, baseMs * (2 ** exponent));
|
|
@@ -145,6 +147,89 @@ export class PiboLoopService {
|
|
|
145
147
|
this.armSoon();
|
|
146
148
|
return this.store.getJob(id);
|
|
147
149
|
}
|
|
150
|
+
setSessionGoal(piboSessionId, objective) {
|
|
151
|
+
const normalizedObjective = objective.trim();
|
|
152
|
+
if (!normalizedObjective)
|
|
153
|
+
throw new Error('Usage: /goal <objective> | /goal pause | /goal resume');
|
|
154
|
+
if (normalizedObjective.length > 20_000)
|
|
155
|
+
throw new Error('Goal objective is too long');
|
|
156
|
+
const session = this.options.context.getSession(piboSessionId);
|
|
157
|
+
if (!session)
|
|
158
|
+
throw new Error('Pibo Session not found');
|
|
159
|
+
const existing = this.store.getSessionGoalOwner(piboSessionId);
|
|
160
|
+
if (!existing) {
|
|
161
|
+
const goal = this.store.createSessionGoal({
|
|
162
|
+
name: goalName(normalizedObjective),
|
|
163
|
+
target: this.sessionGoalTarget(session.metadata?.chatRoomId),
|
|
164
|
+
profile: session.profile,
|
|
165
|
+
prompt: normalizedObjective,
|
|
166
|
+
initialPiboSessionId: piboSessionId,
|
|
167
|
+
}, this.now());
|
|
168
|
+
this.armSoon();
|
|
169
|
+
return { operation: 'created', goal };
|
|
170
|
+
}
|
|
171
|
+
const status = currentGoalStatus(existing);
|
|
172
|
+
if (status === 'complete')
|
|
173
|
+
throw new Error('The current Goal is completing; wait for its active run to finish before creating another Goal');
|
|
174
|
+
if (status === 'blocked')
|
|
175
|
+
throw new Error('The current Goal is blocked; explicitly reopen it before updating or resuming it');
|
|
176
|
+
if (status === 'budget_limited')
|
|
177
|
+
throw new Error('The current Goal is budget limited; increase or clear its token budget before updating and resuming it');
|
|
178
|
+
const goal = this.store.updateJob(existing.id, {
|
|
179
|
+
name: goalName(normalizedObjective),
|
|
180
|
+
prompt: normalizedObjective,
|
|
181
|
+
enabled: true,
|
|
182
|
+
}, this.now());
|
|
183
|
+
if (!goal)
|
|
184
|
+
throw new Error('Goal Loop not found');
|
|
185
|
+
this.armSoon();
|
|
186
|
+
return { operation: 'updated', goal };
|
|
187
|
+
}
|
|
188
|
+
pauseSessionGoal(piboSessionId) {
|
|
189
|
+
const existing = this.requireSessionGoal(piboSessionId);
|
|
190
|
+
const status = currentGoalStatus(existing);
|
|
191
|
+
if (status === 'paused')
|
|
192
|
+
return { operation: 'already-paused', goal: existing };
|
|
193
|
+
if (status !== 'active')
|
|
194
|
+
throw new Error(`Goal Loop cannot be paused while its status is ${status}`);
|
|
195
|
+
const goal = this.store.requestStop(existing.id, this.now());
|
|
196
|
+
if (!goal)
|
|
197
|
+
throw new Error('Goal Loop not found');
|
|
198
|
+
this.armSoon();
|
|
199
|
+
return { operation: 'paused', goal };
|
|
200
|
+
}
|
|
201
|
+
resumeSessionGoal(piboSessionId) {
|
|
202
|
+
const existing = this.requireSessionGoal(piboSessionId);
|
|
203
|
+
const status = currentGoalStatus(existing);
|
|
204
|
+
if (status === 'active' && existing.enabled)
|
|
205
|
+
return { operation: 'already-active', goal: existing };
|
|
206
|
+
if (status !== 'paused')
|
|
207
|
+
throw new Error(`Goal Loop cannot be resumed while its status is ${status}`);
|
|
208
|
+
const goal = this.store.updateJob(existing.id, { enabled: true }, this.now());
|
|
209
|
+
if (!goal)
|
|
210
|
+
throw new Error('Goal Loop not found');
|
|
211
|
+
this.armSoon();
|
|
212
|
+
return { operation: 'resumed', goal };
|
|
213
|
+
}
|
|
214
|
+
requireSessionGoal(piboSessionId) {
|
|
215
|
+
if (!this.options.context.getSession(piboSessionId))
|
|
216
|
+
throw new Error('Pibo Session not found');
|
|
217
|
+
const goal = this.store.getSessionGoalOwner(piboSessionId);
|
|
218
|
+
if (!goal)
|
|
219
|
+
throw new Error('This Pibo Session has no Goal Loop');
|
|
220
|
+
return goal;
|
|
221
|
+
}
|
|
222
|
+
sessionGoalTarget(value) {
|
|
223
|
+
if (typeof value !== 'string' || !value.trim())
|
|
224
|
+
return { kind: 'default-chat' };
|
|
225
|
+
const roomId = value.trim();
|
|
226
|
+
const room = this.roomService.getRoom(roomId);
|
|
227
|
+
if (!room)
|
|
228
|
+
throw new Error('The Pibo Session room no longer exists');
|
|
229
|
+
if (isPiboRoomArchived(room))
|
|
230
|
+
throw new Error('Archived rooms are read-only');
|
|
231
|
+
return { kind: 'room', roomId };
|
|
232
|
+
}
|
|
148
233
|
repairGoalSessionMetadata() {
|
|
149
234
|
for (const session of this.options.context.listSessions?.() ?? []) {
|
|
150
235
|
if (session.metadata?.loopMode === 'goal' && (session.metadata.loopJobId !== undefined || session.metadata.loopRunId !== undefined))
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { existsSync } from 'node:fs';
|
|
1
2
|
import { readFile, writeFile } from 'node:fs/promises';
|
|
2
3
|
import { ensureConfigExists, findConfigPath, getPreferredConfigPath, } from './config.js';
|
|
3
4
|
import { ErrorCode, formatCliError } from './errors.js';
|
|
@@ -155,9 +156,10 @@ export async function configCommand(options) {
|
|
|
155
156
|
return;
|
|
156
157
|
}
|
|
157
158
|
if (options.action === 'init') {
|
|
158
|
-
const
|
|
159
|
-
const
|
|
160
|
-
|
|
159
|
+
const preferredPath = getPreferredConfigPath(options.configPath);
|
|
160
|
+
const alreadyExists = existsSync(preferredPath);
|
|
161
|
+
const path = await ensureConfigExists(preferredPath);
|
|
162
|
+
console.log(alreadyExists ? `MCP config ready: ${path}` : `Created MCP config: ${path}`);
|
|
161
163
|
return;
|
|
162
164
|
}
|
|
163
165
|
if (options.action === 'describe') {
|
package/dist/plugins/builtin.js
CHANGED
|
@@ -4,6 +4,7 @@ import { createPiboGatewayToolProfiles } from "../gateway/tool.js";
|
|
|
4
4
|
import { InitialSessionContextBuilder } from "../core/profiles.js";
|
|
5
5
|
import { parsePiboThinkingLevel } from "../core/thinking.js";
|
|
6
6
|
import { createWebSearchToolProfile } from "../tools/web-search.js";
|
|
7
|
+
import { CODEX_BROWSER_TOOL_NAMES, createCodexBrowserToolProfiles } from "../tools/codex-browser.js";
|
|
7
8
|
import { createRuntimeToolProfile } from "../tools/runtime/tool.js";
|
|
8
9
|
import { completeLogin, getLoginStatus, removeLogin, setApiKey, startLogin } from "../auth/login-actions.js";
|
|
9
10
|
import { loadModelCatalog } from "../apps/chat/model-catalog.js";
|
|
@@ -166,6 +167,12 @@ export const piboCorePlugin = definePiboPlugin({
|
|
|
166
167
|
});
|
|
167
168
|
api.registerTool(createWebSearchToolProfile());
|
|
168
169
|
api.registerTool(createRuntimeToolProfile());
|
|
170
|
+
api.registerTools(createCodexBrowserToolProfiles());
|
|
171
|
+
api.registerCapabilityPackage({
|
|
172
|
+
name: "codex-browser-interface",
|
|
173
|
+
description: "Expose Browser Use and its persistent browser-bound Node REPL through a Codex-familiar structured tool surface.",
|
|
174
|
+
toolNames: [...CODEX_BROWSER_TOOL_NAMES],
|
|
175
|
+
});
|
|
169
176
|
registerPiboNativeTooling(api);
|
|
170
177
|
api.registerProfile({
|
|
171
178
|
name: DEFAULT_PIBO_PROFILE_NAME,
|