@pasko70/pibo 1.7.7 → 1.7.9
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/chat-user-skill-routes.js +51 -19
- package/dist/apps/chat/model-catalog.js +2 -0
- package/dist/apps/chat/web-app.js +2 -2
- package/dist/apps/chat-ui/assets/{dist-BhCflw5L.js → dist-BLQTYmgi.js} +1 -1
- package/dist/apps/chat-ui/assets/{dist-C2wdpulS.js → dist-BLYDOjGT.js} +1 -1
- package/dist/apps/chat-ui/assets/{dist-BUfawaFa.js → dist-Bg2k47fY.js} +1 -1
- package/dist/apps/chat-ui/assets/{dist-iblHo9vw.js → dist-Bv912fTl.js} +1 -1
- package/dist/apps/chat-ui/assets/{dist-NDLYTRqO.js → dist-CCOZbHCt.js} +1 -1
- package/dist/apps/chat-ui/assets/{dist-ChMCJ0Xh.js → dist-D6ImmtZ3.js} +1 -1
- package/dist/apps/chat-ui/assets/{dist-C5S2MWeq.js → dist-DDQWCHTh.js} +1 -1
- package/dist/apps/chat-ui/assets/{dist-XR2wwVeo.js → dist-DTJJ5-iA.js} +1 -1
- package/dist/apps/chat-ui/assets/{dist-COMZszUx.js → dist-Daom6uMW.js} +1 -1
- package/dist/apps/chat-ui/assets/{dist-CqZsX_X9.js → dist-Dgs6LwMW.js} +1 -1
- package/dist/apps/chat-ui/assets/{dist-CJOnkhP1.js → dist-LRUZKp77.js} +1 -1
- package/dist/apps/chat-ui/assets/index-BnZ0V5cJ.js +173 -0
- package/dist/apps/chat-ui/assets/index-DbRZGRDd.css +1 -0
- package/dist/apps/chat-ui/index.html +2 -2
- package/dist/apps/chat-vscode-web/assets/index-CiQZTRZH.js +41 -0
- package/dist/apps/chat-vscode-web/index.html +1 -1
- package/dist/apps/vscode-artifacts/latest.vsix +0 -0
- package/dist/apps/vscode-artifacts/pibo-vscode-ext-1.7.9.vsix +0 -0
- package/dist/cli.js +12 -3
- package/dist/core/context-guard.js +126 -0
- package/dist/core/gateway-resource-guard.js +215 -0
- package/dist/core/routed-session.js +76 -1
- package/dist/core/runtime.js +40 -2
- package/dist/core/session-router.js +2 -0
- package/dist/debug/index.js +40 -0
- package/dist/mcp/output.js +19 -4
- package/dist/providers/openai-gpt56.js +153 -0
- package/dist/ralph/cli.js +49 -5
- package/dist/session-ui/terminalRows.js +59 -0
- package/dist/skills/cli.js +33 -23
- package/dist/tools/guides.js +17 -0
- package/dist/user-skills/manager.js +106 -8
- package/package.json +1 -1
- package/dist/apps/chat-ui/assets/index-BStUapSa.css +0 -1
- package/dist/apps/chat-ui/assets/index-BYqOi32B.js +0 -173
- package/dist/apps/chat-vscode-web/assets/index-B4Jk2P5o.js +0 -41
package/dist/debug/index.js
CHANGED
|
@@ -52,6 +52,10 @@ export async function runDebugCli(argv = process.argv) {
|
|
|
52
52
|
await runDebugRuns(args.slice(1));
|
|
53
53
|
return;
|
|
54
54
|
}
|
|
55
|
+
if (args[0] === "resources") {
|
|
56
|
+
await runDebugResources(args.slice(1));
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
55
59
|
if (args[0] === "signals") {
|
|
56
60
|
await runDebugSignals(args.slice(1));
|
|
57
61
|
return;
|
|
@@ -77,6 +81,19 @@ export async function runDebugCli(argv = process.argv) {
|
|
|
77
81
|
process.exitCode = 1;
|
|
78
82
|
}
|
|
79
83
|
}
|
|
84
|
+
async function runDebugResources(args) {
|
|
85
|
+
if (args[0] === "--help" || args[0] === "-h") {
|
|
86
|
+
printDebugResourcesDiscovery();
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
const options = parseOptions(args);
|
|
90
|
+
const { collectGatewayResourceSnapshot, renderGatewayResourceSnapshotText } = await import("../core/gateway-resource-guard.js");
|
|
91
|
+
const snapshot = await collectGatewayResourceSnapshot();
|
|
92
|
+
if (options.json)
|
|
93
|
+
console.log(JSON.stringify(snapshot, null, 2));
|
|
94
|
+
else
|
|
95
|
+
console.log(renderGatewayResourceSnapshotText(snapshot));
|
|
96
|
+
}
|
|
80
97
|
async function runDebugDb(args) {
|
|
81
98
|
if (args.length === 0 || args[0] === "--help" || args[0] === "-h") {
|
|
82
99
|
printDebugDbDiscovery();
|
|
@@ -1007,6 +1024,7 @@ Commands:
|
|
|
1007
1024
|
failures List failed tool calls and trace/session errors
|
|
1008
1025
|
jobs Inspect durable Pibo jobs and DLQ
|
|
1009
1026
|
runs Inspect durable yielded runs
|
|
1027
|
+
resources Show gateway memory reserve, related child processes, and heavy daemons
|
|
1010
1028
|
signals Inspect live session signal snapshots through Chat Web APIs
|
|
1011
1029
|
telemetry Inspect runtime observability telemetry
|
|
1012
1030
|
web Inspect browser render state via CDP
|
|
@@ -1019,12 +1037,34 @@ Next:
|
|
|
1019
1037
|
pibo debug messages <pibo-session-id> list
|
|
1020
1038
|
pibo debug trace <pibo-session-id> --running-only
|
|
1021
1039
|
pibo debug events stream --topic pibo.output
|
|
1040
|
+
pibo debug resources --json
|
|
1022
1041
|
pibo debug signals tree ps_...
|
|
1023
1042
|
pibo debug telemetry sessions --active
|
|
1024
1043
|
pibo debug web targets
|
|
1025
1044
|
pibo debug pty run -- pibo tui:sessions --demo
|
|
1026
1045
|
`);
|
|
1027
1046
|
}
|
|
1047
|
+
function printDebugResourcesDiscovery() {
|
|
1048
|
+
console.log(`pibo debug resources - inspect gateway resource guard state
|
|
1049
|
+
|
|
1050
|
+
Usage:
|
|
1051
|
+
pibo debug resources [--json]
|
|
1052
|
+
|
|
1053
|
+
Reports:
|
|
1054
|
+
Gateway RSS/heap headroom, host free-memory reserve, direct child processes, and known heavy local daemons such as ComfyUI or Unity when process listing is available.
|
|
1055
|
+
|
|
1056
|
+
Environment:
|
|
1057
|
+
PIBO_GATEWAY_RESOURCE_GUARD=warn|block|off
|
|
1058
|
+
PIBO_GATEWAY_MIN_FREE_MEMORY_BYTES=<bytes>
|
|
1059
|
+
PIBO_GATEWAY_MIN_HEAP_AVAILABLE_BYTES=<bytes>
|
|
1060
|
+
PIBO_GATEWAY_MAX_RSS_BYTES=<bytes>
|
|
1061
|
+
PIBO_GATEWAY_KNOWN_DAEMON_WARNING_RSS_BYTES=<bytes>
|
|
1062
|
+
|
|
1063
|
+
Next:
|
|
1064
|
+
pibo debug resources --json
|
|
1065
|
+
pibo compute health --json
|
|
1066
|
+
`);
|
|
1067
|
+
}
|
|
1028
1068
|
function printDebugSignalsDiscovery() {
|
|
1029
1069
|
console.log(`pibo debug signals - inspect live Session Signal snapshots
|
|
1030
1070
|
|
package/dist/mcp/output.js
CHANGED
|
@@ -50,6 +50,17 @@ export function truncateToolDescription(description, maxLength = TOOL_DESCRIPTIO
|
|
|
50
50
|
return normalized;
|
|
51
51
|
return `${normalized.slice(0, Math.max(0, maxLength - 1)).trimEnd()}…`;
|
|
52
52
|
}
|
|
53
|
+
/**
|
|
54
|
+
* Return an info-view summary without generated OpenAPI error-response noise.
|
|
55
|
+
*/
|
|
56
|
+
export function summarizeToolDescriptionForInfo(description) {
|
|
57
|
+
if (!description)
|
|
58
|
+
return undefined;
|
|
59
|
+
const withoutErrorResponses = description
|
|
60
|
+
.replace(/\s*Error Responses:\s*[\s\S]*$/i, '')
|
|
61
|
+
.trim();
|
|
62
|
+
return truncateToolDescription(withoutErrorResponses);
|
|
63
|
+
}
|
|
53
64
|
/**
|
|
54
65
|
* Format server list for display
|
|
55
66
|
*/
|
|
@@ -140,15 +151,19 @@ export function formatServerDetails(serverName, config, tools, withDescriptions
|
|
|
140
151
|
lines.push(` ${color(tool.name, colors.green)}`);
|
|
141
152
|
const toolSummary = withDescriptions
|
|
142
153
|
? tool.description
|
|
143
|
-
:
|
|
154
|
+
: summarizeToolDescriptionForInfo(tool.description);
|
|
144
155
|
if (toolSummary) {
|
|
145
156
|
lines.push(` ${color(toolSummary, colors.dim)}`);
|
|
146
157
|
}
|
|
147
158
|
// Show parameters from schema
|
|
148
159
|
const schema = tool.inputSchema;
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
160
|
+
const parameters = Object.entries(schema.properties ?? {});
|
|
161
|
+
lines.push(` ${color('Parameters:', colors.yellow)}`);
|
|
162
|
+
if (parameters.length === 0) {
|
|
163
|
+
lines.push(` ${color('No parameters', colors.dim)}`);
|
|
164
|
+
}
|
|
165
|
+
else {
|
|
166
|
+
for (const [name, prop] of parameters) {
|
|
152
167
|
const required = schema.required?.includes(name)
|
|
153
168
|
? 'required'
|
|
154
169
|
: 'optional';
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
import { getModels } from "@mariozechner/pi-ai";
|
|
2
|
+
import { getOAuthProvider } from "@mariozechner/pi-ai/oauth";
|
|
3
|
+
export const OPENAI_PROVIDER_ID = "openai";
|
|
4
|
+
export const OPENAI_RESPONSES_API = "openai-responses";
|
|
5
|
+
export const OPENAI_BASE_URL = "https://api.openai.com/v1";
|
|
6
|
+
export const OPENAI_API_KEY_ENV = "OPENAI_API_KEY";
|
|
7
|
+
export const OPENAI_CODEX_PROVIDER_ID = "openai-codex";
|
|
8
|
+
export const OPENAI_CODEX_RESPONSES_API = "openai-codex-responses";
|
|
9
|
+
export const OPENAI_CODEX_BASE_URL = "https://chatgpt.com/backend-api";
|
|
10
|
+
const OPENAI_GPT_56_CONTEXT_WINDOW = 1_050_000;
|
|
11
|
+
const OPENAI_CODEX_GPT_56_CONTEXT_WINDOW = 272_000;
|
|
12
|
+
const GPT_56_MAX_TOKENS = 128_000;
|
|
13
|
+
export const OPENAI_GPT_56_MODELS = [
|
|
14
|
+
{
|
|
15
|
+
id: "gpt-5.6",
|
|
16
|
+
name: "GPT-5.6 (Sol alias)",
|
|
17
|
+
cost: { input: 5, output: 30, cacheRead: 0.5, cacheWrite: 6.25 },
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
id: "gpt-5.6-sol",
|
|
21
|
+
name: "GPT-5.6 Sol",
|
|
22
|
+
cost: { input: 5, output: 30, cacheRead: 0.5, cacheWrite: 6.25 },
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
id: "gpt-5.6-terra",
|
|
26
|
+
name: "GPT-5.6 Terra",
|
|
27
|
+
cost: { input: 2.5, output: 15, cacheRead: 0.25, cacheWrite: 3.125 },
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
id: "gpt-5.6-luna",
|
|
31
|
+
name: "GPT-5.6 Luna",
|
|
32
|
+
cost: { input: 1, output: 6, cacheRead: 0.1, cacheWrite: 1.25 },
|
|
33
|
+
},
|
|
34
|
+
];
|
|
35
|
+
const OPENAI_GPT_56_MODEL_IDS = new Set(OPENAI_GPT_56_MODELS.map((model) => model.id));
|
|
36
|
+
export function getBuiltInOpenAiModels() {
|
|
37
|
+
return getBuiltInProviderModels(OPENAI_PROVIDER_ID);
|
|
38
|
+
}
|
|
39
|
+
export function getBuiltInOpenAiCodexModels() {
|
|
40
|
+
return getBuiltInProviderModels(OPENAI_CODEX_PROVIDER_ID);
|
|
41
|
+
}
|
|
42
|
+
export function buildOpenAiGpt56Models(baseModels = getBuiltInOpenAiModels()) {
|
|
43
|
+
return buildProviderGpt56Models({
|
|
44
|
+
providerId: OPENAI_PROVIDER_ID,
|
|
45
|
+
api: OPENAI_RESPONSES_API,
|
|
46
|
+
baseUrl: OPENAI_BASE_URL,
|
|
47
|
+
contextWindow: OPENAI_GPT_56_CONTEXT_WINDOW,
|
|
48
|
+
thinkingLevelMap: { off: null, xhigh: "xhigh" },
|
|
49
|
+
baseModels,
|
|
50
|
+
modelCost: (model) => model.cost,
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
export function buildOpenAiCodexGpt56Models(baseModels = getBuiltInOpenAiCodexModels()) {
|
|
54
|
+
return buildProviderGpt56Models({
|
|
55
|
+
providerId: OPENAI_CODEX_PROVIDER_ID,
|
|
56
|
+
api: OPENAI_CODEX_RESPONSES_API,
|
|
57
|
+
baseUrl: OPENAI_CODEX_BASE_URL,
|
|
58
|
+
contextWindow: OPENAI_CODEX_GPT_56_CONTEXT_WINDOW,
|
|
59
|
+
thinkingLevelMap: { xhigh: "xhigh", minimal: "low" },
|
|
60
|
+
baseModels,
|
|
61
|
+
modelCost: (model) => ({ ...model.cost, cacheWrite: 0 }),
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
export function registerOpenAiGpt56Models(modelRegistry, options = {}) {
|
|
65
|
+
const baseOpenAiModels = options.baseOpenAiModels ?? getBuiltInOpenAiModels();
|
|
66
|
+
const openAiModels = buildOpenAiGpt56Models(baseOpenAiModels);
|
|
67
|
+
const openAiAdded = countMissingGpt56Models(baseOpenAiModels, OPENAI_PROVIDER_ID);
|
|
68
|
+
modelRegistry.registerProvider(OPENAI_PROVIDER_ID, {
|
|
69
|
+
baseUrl: OPENAI_BASE_URL,
|
|
70
|
+
api: OPENAI_RESPONSES_API,
|
|
71
|
+
apiKey: OPENAI_API_KEY_ENV,
|
|
72
|
+
models: openAiModels,
|
|
73
|
+
});
|
|
74
|
+
const baseOpenAiCodexModels = options.baseOpenAiCodexModels ?? getBuiltInOpenAiCodexModels();
|
|
75
|
+
const openAiCodexModels = buildOpenAiCodexGpt56Models(baseOpenAiCodexModels);
|
|
76
|
+
const openAiCodexAdded = countMissingGpt56Models(baseOpenAiCodexModels, OPENAI_CODEX_PROVIDER_ID);
|
|
77
|
+
const openAiCodexOAuth = getOpenAiCodexOAuthConfig();
|
|
78
|
+
modelRegistry.registerProvider(OPENAI_CODEX_PROVIDER_ID, {
|
|
79
|
+
name: openAiCodexOAuth.name,
|
|
80
|
+
baseUrl: OPENAI_CODEX_BASE_URL,
|
|
81
|
+
api: OPENAI_CODEX_RESPONSES_API,
|
|
82
|
+
oauth: openAiCodexOAuth,
|
|
83
|
+
models: openAiCodexModels,
|
|
84
|
+
});
|
|
85
|
+
return {
|
|
86
|
+
registered: true,
|
|
87
|
+
providers: 2,
|
|
88
|
+
models: openAiModels.length + openAiCodexModels.length,
|
|
89
|
+
added: openAiAdded + openAiCodexAdded,
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
export function findOpenAiGpt56Model(modelRegistry, model) {
|
|
93
|
+
if (!model?.provider || !model.id)
|
|
94
|
+
return undefined;
|
|
95
|
+
if (model.provider !== OPENAI_PROVIDER_ID && model.provider !== OPENAI_CODEX_PROVIDER_ID)
|
|
96
|
+
return undefined;
|
|
97
|
+
if (!OPENAI_GPT_56_MODEL_IDS.has(model.id))
|
|
98
|
+
return undefined;
|
|
99
|
+
return modelRegistry.find(model.provider, model.id);
|
|
100
|
+
}
|
|
101
|
+
function getBuiltInProviderModels(providerId) {
|
|
102
|
+
try {
|
|
103
|
+
return getModels(providerId);
|
|
104
|
+
}
|
|
105
|
+
catch {
|
|
106
|
+
return [];
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
function buildProviderGpt56Models(options) {
|
|
110
|
+
const providerBaseModels = options.baseModels
|
|
111
|
+
.filter((model) => model.provider === options.providerId)
|
|
112
|
+
.map(cloneModel);
|
|
113
|
+
const existingIds = new Set(providerBaseModels.map((model) => model.id));
|
|
114
|
+
const additions = OPENAI_GPT_56_MODELS
|
|
115
|
+
.filter((model) => !existingIds.has(model.id))
|
|
116
|
+
.map((model) => openAiGpt56ModelToRegistryModel(model, options));
|
|
117
|
+
return [...providerBaseModels, ...additions];
|
|
118
|
+
}
|
|
119
|
+
function countMissingGpt56Models(baseModels, providerId) {
|
|
120
|
+
const existingIds = new Set(baseModels.filter((model) => model.provider === providerId).map((model) => model.id));
|
|
121
|
+
return OPENAI_GPT_56_MODELS.filter((model) => !existingIds.has(model.id)).length;
|
|
122
|
+
}
|
|
123
|
+
function cloneModel(model) {
|
|
124
|
+
return {
|
|
125
|
+
...model,
|
|
126
|
+
input: [...model.input],
|
|
127
|
+
cost: { ...model.cost },
|
|
128
|
+
headers: model.headers ? { ...model.headers } : undefined,
|
|
129
|
+
compat: model.compat ? { ...model.compat } : undefined,
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
function openAiGpt56ModelToRegistryModel(model, options) {
|
|
133
|
+
return {
|
|
134
|
+
id: model.id,
|
|
135
|
+
name: model.name,
|
|
136
|
+
api: options.api,
|
|
137
|
+
provider: options.providerId,
|
|
138
|
+
baseUrl: options.baseUrl,
|
|
139
|
+
reasoning: true,
|
|
140
|
+
thinkingLevelMap: options.thinkingLevelMap,
|
|
141
|
+
input: ["text", "image"],
|
|
142
|
+
cost: options.modelCost(model),
|
|
143
|
+
contextWindow: options.contextWindow,
|
|
144
|
+
maxTokens: GPT_56_MAX_TOKENS,
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
function getOpenAiCodexOAuthConfig() {
|
|
148
|
+
const provider = getOAuthProvider(OPENAI_CODEX_PROVIDER_ID);
|
|
149
|
+
if (!provider)
|
|
150
|
+
throw new Error("OpenAI Codex OAuth provider is unavailable.");
|
|
151
|
+
const { id: _id, ...oauth } = provider;
|
|
152
|
+
return oauth;
|
|
153
|
+
}
|
package/dist/ralph/cli.js
CHANGED
|
@@ -4,6 +4,7 @@ import { createDefaultPiboRalphStore } from './store.js';
|
|
|
4
4
|
import { createBuiltInRalphStopConditions } from './stopping.js';
|
|
5
5
|
import { DEFAULT_PIBO_PROFILE_NAME } from '../plugins/builtin.js';
|
|
6
6
|
import { getRalphJobTemplate, listRalphJobTemplates } from './templates.js';
|
|
7
|
+
import { parsePiboThinkingLevel } from '../core/thinking.js';
|
|
7
8
|
function printDiscovery() {
|
|
8
9
|
console.log(`pibo ralph
|
|
9
10
|
|
|
@@ -34,6 +35,49 @@ function printJson(value) { console.log(JSON.stringify(value, null, 2)); }
|
|
|
34
35
|
function maxIterations(value) { if (value === undefined)
|
|
35
36
|
return undefined; const parsed = Number(value); if (!Number.isInteger(parsed) || parsed < 1)
|
|
36
37
|
throw new Error('--max-iterations must be a positive integer'); return parsed; }
|
|
38
|
+
function parseModelOverride(value) {
|
|
39
|
+
if (value === undefined)
|
|
40
|
+
return undefined;
|
|
41
|
+
const slash = value.indexOf('/');
|
|
42
|
+
if (slash <= 0 || slash === value.length - 1)
|
|
43
|
+
throw new Error('--model must use provider/model syntax, for example openai/gpt-5');
|
|
44
|
+
const provider = value.slice(0, slash).trim();
|
|
45
|
+
const id = value.slice(slash + 1).trim();
|
|
46
|
+
if (!provider || !id)
|
|
47
|
+
throw new Error('--model must use provider/model syntax, for example openai/gpt-5');
|
|
48
|
+
return { provider, id };
|
|
49
|
+
}
|
|
50
|
+
function parseThinkingOverride(value) { return value === undefined ? undefined : parsePiboThinkingLevel(value); }
|
|
51
|
+
function applyRuntimeCreateOptions(input, options) {
|
|
52
|
+
const modelOverride = parseModelOverride(options.model);
|
|
53
|
+
const thinkingLevel = parseThinkingOverride(options.thinking);
|
|
54
|
+
if (modelOverride)
|
|
55
|
+
input.modelOverride = modelOverride;
|
|
56
|
+
if (thinkingLevel)
|
|
57
|
+
input.thinkingLevel = thinkingLevel;
|
|
58
|
+
if (options.fast !== undefined)
|
|
59
|
+
input.fastMode = options.fast;
|
|
60
|
+
}
|
|
61
|
+
function applyRuntimePatchOptions(patch, options) {
|
|
62
|
+
if (options.model !== undefined && options.clearModel)
|
|
63
|
+
throw new Error('Choose either --model or --clear-model, not both');
|
|
64
|
+
if (options.thinking !== undefined && options.clearThinking)
|
|
65
|
+
throw new Error('Choose either --thinking or --clear-thinking, not both');
|
|
66
|
+
if (options.fast !== undefined && options.clearFast)
|
|
67
|
+
throw new Error('Choose either --fast/--no-fast or --clear-fast, not both');
|
|
68
|
+
if (options.clearModel)
|
|
69
|
+
patch.modelOverride = null;
|
|
70
|
+
else if (options.model !== undefined)
|
|
71
|
+
patch.modelOverride = parseModelOverride(options.model);
|
|
72
|
+
if (options.clearThinking)
|
|
73
|
+
patch.thinkingLevel = null;
|
|
74
|
+
else if (options.thinking !== undefined)
|
|
75
|
+
patch.thinkingLevel = parseThinkingOverride(options.thinking);
|
|
76
|
+
if (options.clearFast)
|
|
77
|
+
patch.fastMode = null;
|
|
78
|
+
else if (options.fast !== undefined)
|
|
79
|
+
patch.fastMode = options.fast;
|
|
80
|
+
}
|
|
37
81
|
function templatePatch(id) {
|
|
38
82
|
if (!id)
|
|
39
83
|
return {};
|
|
@@ -77,18 +121,18 @@ export async function runRalphCli(argv = process.argv) {
|
|
|
77
121
|
else
|
|
78
122
|
for (const job of jobs)
|
|
79
123
|
console.log(formatRalphJobLine(job)); store.close(); });
|
|
80
|
-
program.command('add').description('Create a Ralph job').option('--template <id>', 'Built-in job template id').option('--prompt <text>', 'Task prompt').option('--name <name>', 'Job name').option('--description <text>', 'Job description').option('--profile <profile>', 'Agent profile', DEFAULT_PIBO_PROFILE_NAME).option('--room <room-id>', 'Target room id').option('--default-chat', 'Target the shared default chat').option('--max-iterations <n>', 'Stop after n completed run attempts')
|
|
124
|
+
program.command('add').description('Create a Ralph job').option('--template <id>', 'Built-in job template id').option('--prompt <text>', 'Task prompt').option('--name <name>', 'Job name').option('--description <text>', 'Job description').option('--profile <profile>', 'Agent profile', DEFAULT_PIBO_PROFILE_NAME).option('--room <room-id>', 'Target room id').option('--default-chat', 'Target the shared default chat').option('--max-iterations <n>', 'Stop after n completed run attempts').option('--model <provider/model>', 'Runtime model override, for example openai/gpt-5').option('--thinking <level>', 'Runtime thinking level override: off, minimal, low, medium, high, xhigh').option('--fast', 'Enable runtime fast mode').option('--no-fast', 'Disable runtime fast mode')
|
|
81
125
|
.option('--start', 'Start immediately').option('--json', 'Print JSON').action((options) => { const base = templatePatch(options.template); const prompt = options.prompt ?? base.prompt; if (typeof prompt !== 'string' || !prompt.trim())
|
|
82
|
-
throw new Error('Choose --template <id> or provide --prompt <text>'); const
|
|
126
|
+
throw new Error('Choose --template <id> or provide --prompt <text>'); const input = { name: options.name ?? base.name, description: options.description ?? base.description, enabled: options.start === true, target: targetFromOptions(options), profile: options.profile, prompt, maxIterations: options.maxIterations !== undefined ? maxIterations(options.maxIterations) : typeof base.maxIterations === 'number' ? base.maxIterations : undefined, stopPolicy: base.stopPolicy ?? undefined }; applyRuntimeCreateOptions(input, options); const store = createDefaultPiboRalphStore({ path: program.opts().store }); const job = store.createJob(input); if (options.json)
|
|
83
127
|
printJson(job);
|
|
84
128
|
else
|
|
85
129
|
console.log(`${job.id}\t${job.enabled ? 'running' : 'stopped'}\t${job.name}`); store.close(); });
|
|
86
|
-
program.command('edit').argument('<id>', 'Ralph job id').description('Update a Ralph job').option('--template <id>', 'Apply a built-in job template before explicit overrides').option('--prompt <text>', 'Task prompt').option('--name <name>', 'Job name').option('--description <text>', 'Job description').option('--profile <profile>', 'Agent profile').option('--room <room-id>', 'Target room id').option('--default-chat', 'Target the shared default chat').option('--max-iterations <n>', 'Stop after n completed run attempts').option('--json', 'Print JSON').action((id, options) => { const store = createDefaultPiboRalphStore({ path: program.opts().store }); const patch = { ...templatePatch(options.template) }; if (options.name !== undefined)
|
|
130
|
+
program.command('edit').argument('<id>', 'Ralph job id').description('Update a Ralph job').option('--template <id>', 'Apply a built-in job template before explicit overrides').option('--prompt <text>', 'Task prompt').option('--name <name>', 'Job name').option('--description <text>', 'Job description').option('--profile <profile>', 'Agent profile').option('--room <room-id>', 'Target room id').option('--default-chat', 'Target the shared default chat').option('--max-iterations <n>', 'Stop after n completed run attempts').option('--model <provider/model>', 'Set runtime model override, for example openai/gpt-5').option('--clear-model', 'Clear runtime model override').option('--thinking <level>', 'Set runtime thinking level override: off, minimal, low, medium, high, xhigh').option('--clear-thinking', 'Clear runtime thinking level override').option('--fast', 'Enable runtime fast mode').option('--no-fast', 'Disable runtime fast mode').option('--clear-fast', 'Clear runtime fast mode override').option('--json', 'Print JSON').action((id, options) => { const store = createDefaultPiboRalphStore({ path: program.opts().store }); const patch = { ...templatePatch(options.template) }; if (options.name !== undefined)
|
|
87
131
|
patch.name = options.name; if (options.description !== undefined)
|
|
88
132
|
patch.description = options.description; if (options.profile !== undefined)
|
|
89
133
|
patch.profile = options.profile; if (options.prompt !== undefined)
|
|
90
134
|
patch.prompt = options.prompt; if (options.maxIterations !== undefined)
|
|
91
|
-
patch.maxIterations = maxIterations(options.maxIterations); const target = maybeTargetFromOptions(options); if (target)
|
|
135
|
+
patch.maxIterations = maxIterations(options.maxIterations); applyRuntimePatchOptions(patch, options); const target = maybeTargetFromOptions(options); if (target)
|
|
92
136
|
patch.target = target; if (Object.keys(patch).length === 0)
|
|
93
137
|
throw new Error('No Ralph job update fields provided'); const job = store.updateJob(id, patch); if (!job)
|
|
94
138
|
throw new Error('Ralph job not found'); if (options.json)
|
|
@@ -145,7 +189,7 @@ export async function runRalphCli(argv = process.argv) {
|
|
|
145
189
|
else
|
|
146
190
|
for (const run of runs)
|
|
147
191
|
console.log(formatRalphRunLine(run)); store.close(); });
|
|
148
|
-
if (argv.length <= 2 || argv.
|
|
192
|
+
if (argv.length <= 2 || (argv.length === 3 && (argv[2] === '--help' || argv[2] === '-h'))) {
|
|
149
193
|
printDiscovery();
|
|
150
194
|
return;
|
|
151
195
|
}
|
|
@@ -129,6 +129,9 @@ function createToolRowCandidate(node, turnId) {
|
|
|
129
129
|
const row = createCommandToolRow(node, command);
|
|
130
130
|
return { row, turnId, exploring: undefined };
|
|
131
131
|
}
|
|
132
|
+
if (isWebSearchToolName(node.title)) {
|
|
133
|
+
return { row: createWebSearchToolRow(node), turnId };
|
|
134
|
+
}
|
|
132
135
|
const image = classifyImageTool(node);
|
|
133
136
|
if (image) {
|
|
134
137
|
const row = createImageToolRow(node, image);
|
|
@@ -161,6 +164,38 @@ function createToolRowCandidate(node, turnId) {
|
|
|
161
164
|
const exploring = classifyExploringTool(node);
|
|
162
165
|
return { row, turnId, exploring };
|
|
163
166
|
}
|
|
167
|
+
function createWebSearchToolRow(node) {
|
|
168
|
+
const status = mapStatus(node.status);
|
|
169
|
+
const query = webSearchQuery(node);
|
|
170
|
+
const sourceCount = webSearchSourceCount(node.output);
|
|
171
|
+
const lines = [
|
|
172
|
+
{
|
|
173
|
+
prefix: "bullet",
|
|
174
|
+
tokens: [token(webSearchVerb(node.status), toneForStatus(node.status), node.status === "error" ? "bold" : "semibold")],
|
|
175
|
+
},
|
|
176
|
+
];
|
|
177
|
+
if (query) {
|
|
178
|
+
lines.push({ prefix: "detail", tokens: [token(`query: ${JSON.stringify(query)}`, "cyan")] });
|
|
179
|
+
}
|
|
180
|
+
if (node.status === "done" && sourceCount !== undefined) {
|
|
181
|
+
lines.push({ prefix: "detail", tokens: [token(`sources: ${sourceCount}`, "dim")] });
|
|
182
|
+
}
|
|
183
|
+
if (node.status === "error" && node.error) {
|
|
184
|
+
lines.push({ prefix: "detail", tokens: [token(node.error, "red")] });
|
|
185
|
+
}
|
|
186
|
+
return {
|
|
187
|
+
id: node.id,
|
|
188
|
+
kind: "tool.call",
|
|
189
|
+
status,
|
|
190
|
+
errorKind: node.status === "error" ? "tool" : undefined,
|
|
191
|
+
lines,
|
|
192
|
+
sourceNodeIds: [node.id],
|
|
193
|
+
input: node.input,
|
|
194
|
+
output: node.output,
|
|
195
|
+
error: node.error,
|
|
196
|
+
expandable: node.input !== undefined || node.output !== undefined || Boolean(node.error),
|
|
197
|
+
};
|
|
198
|
+
}
|
|
164
199
|
function createImageToolRow(node, image) {
|
|
165
200
|
const status = mapStatus(node.status);
|
|
166
201
|
const detailLabel = image.path ? `Path: ${image.path}` : image.artifactId ? `Artifact: ${image.artifactId}` : image.query ? `Query: ${image.query}` : image.mimeType ? `Type: ${image.mimeType}` : "Image content returned";
|
|
@@ -962,6 +997,30 @@ function isShellToolName(name) {
|
|
|
962
997
|
normalized === "bash" ||
|
|
963
998
|
normalized === "terminal");
|
|
964
999
|
}
|
|
1000
|
+
function isWebSearchToolName(name) {
|
|
1001
|
+
return (name ?? "").trim().toLowerCase() === "web_search";
|
|
1002
|
+
}
|
|
1003
|
+
function webSearchVerb(status) {
|
|
1004
|
+
if (status === "running")
|
|
1005
|
+
return "Searching web";
|
|
1006
|
+
if (status === "error")
|
|
1007
|
+
return "Web search failed";
|
|
1008
|
+
return "Searched web";
|
|
1009
|
+
}
|
|
1010
|
+
function webSearchQuery(node) {
|
|
1011
|
+
const input = isRecord(node.input) ? node.input : undefined;
|
|
1012
|
+
const output = isRecord(node.output) ? node.output : undefined;
|
|
1013
|
+
return stringValue(input?.query) ?? stringValue(output?.query) ?? stringValue(node.summary);
|
|
1014
|
+
}
|
|
1015
|
+
function webSearchSourceCount(output) {
|
|
1016
|
+
if (!isRecord(output))
|
|
1017
|
+
return undefined;
|
|
1018
|
+
const explicit = output.sourceCount ?? output.sourcesCount;
|
|
1019
|
+
if (typeof explicit === "number" && Number.isFinite(explicit))
|
|
1020
|
+
return explicit;
|
|
1021
|
+
const sources = output.sources ?? output.citations ?? output.results;
|
|
1022
|
+
return Array.isArray(sources) ? sources.length : undefined;
|
|
1023
|
+
}
|
|
965
1024
|
function shellCommandValue(value) {
|
|
966
1025
|
if (!isRecord(value))
|
|
967
1026
|
return undefined;
|
package/dist/skills/cli.js
CHANGED
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
import { Command } from "commander";
|
|
2
2
|
import { createDefaultPiboPluginRegistry } from "../plugins/builtin.js";
|
|
3
|
-
import {
|
|
3
|
+
import { ScopedUserSkillManager, normalizeUserSkillScope, normalizeWritableUserSkillScope, } from "../user-skills/manager.js";
|
|
4
4
|
import { readFileSync } from "node:fs";
|
|
5
5
|
import { resolve } from "node:path";
|
|
6
|
-
import os from "node:os";
|
|
7
6
|
function printJson(value) {
|
|
8
7
|
console.log(JSON.stringify(value, null, 2));
|
|
9
8
|
}
|
|
10
9
|
export async function runSkillsCli(argv) {
|
|
11
|
-
const manager = new
|
|
10
|
+
const manager = new ScopedUserSkillManager();
|
|
12
11
|
const program = new Command();
|
|
13
12
|
program
|
|
14
13
|
.name("pibo skills")
|
|
@@ -37,9 +36,10 @@ export async function runSkillsCli(argv) {
|
|
|
37
36
|
program
|
|
38
37
|
.command("list")
|
|
39
38
|
.description("List user skills managed by this CLI")
|
|
39
|
+
.option("--scope <scope>", "Skill scope: global, workspace, or all", "all")
|
|
40
40
|
.option("--json", "Print JSON")
|
|
41
41
|
.action((options) => {
|
|
42
|
-
const skills = manager.list();
|
|
42
|
+
const skills = manager.list(normalizeUserSkillScope(options.scope));
|
|
43
43
|
if (options.json) {
|
|
44
44
|
printJson(skills);
|
|
45
45
|
return;
|
|
@@ -48,24 +48,26 @@ export async function runSkillsCli(argv) {
|
|
|
48
48
|
console.log("No user skills registered.");
|
|
49
49
|
return;
|
|
50
50
|
}
|
|
51
|
-
console.log("NAME\t\tENABLED\tSOURCE\t\tDESCRIPTION");
|
|
51
|
+
console.log("NAME\t\tSCOPE\t\tENABLED\tSOURCE\t\tDESCRIPTION");
|
|
52
52
|
for (const s of skills) {
|
|
53
53
|
const enabled = s.enabled ? "yes" : "no";
|
|
54
|
-
console.log(`${s.name}\t${enabled}\t\t${s.source}\t${s.description}`);
|
|
54
|
+
console.log(`${s.name}\t${s.scope ?? "global"}\t${enabled}\t\t${s.source}\t${s.description}`);
|
|
55
55
|
}
|
|
56
56
|
});
|
|
57
57
|
program
|
|
58
58
|
.command("show")
|
|
59
59
|
.description("Show a skill's markdown content")
|
|
60
60
|
.argument("<name>", "Skill name")
|
|
61
|
-
.
|
|
62
|
-
|
|
61
|
+
.option("--scope <scope>", "Skill scope: global, workspace, or all", "all")
|
|
62
|
+
.action((name, options) => {
|
|
63
|
+
const scope = normalizeUserSkillScope(options.scope);
|
|
64
|
+
const skill = manager.get(name, scope);
|
|
63
65
|
if (!skill) {
|
|
64
66
|
console.error(`Skill "${name}" not found.`);
|
|
65
67
|
process.exitCode = 1;
|
|
66
68
|
return;
|
|
67
69
|
}
|
|
68
|
-
console.log(manager.getSkillMarkdown(skill.id));
|
|
70
|
+
console.log(manager.getSkillMarkdown(skill.id, scope));
|
|
69
71
|
});
|
|
70
72
|
program
|
|
71
73
|
.command("add")
|
|
@@ -73,6 +75,7 @@ export async function runSkillsCli(argv) {
|
|
|
73
75
|
.argument("<name>", "Skill name (kebab-case)")
|
|
74
76
|
.requiredOption("--file <path>", "Path to markdown file")
|
|
75
77
|
.option("--description <text>", "Short description")
|
|
78
|
+
.option("--scope <scope>", "Skill scope: global or workspace", "global")
|
|
76
79
|
.action((name, options) => {
|
|
77
80
|
const filePath = resolve(options.file);
|
|
78
81
|
const markdown = readFileSync(filePath, "utf-8");
|
|
@@ -80,58 +83,65 @@ export async function runSkillsCli(argv) {
|
|
|
80
83
|
name,
|
|
81
84
|
description: options.description ?? "",
|
|
82
85
|
markdown,
|
|
83
|
-
});
|
|
84
|
-
printJson({ id: skill.id, name: skill.name, enabled: skill.enabled });
|
|
86
|
+
}, normalizeWritableUserSkillScope(options.scope));
|
|
87
|
+
printJson({ id: skill.id, name: skill.name, scope: skill.scope, enabled: skill.enabled });
|
|
85
88
|
});
|
|
86
89
|
program
|
|
87
90
|
.command("remove")
|
|
88
91
|
.description("Remove a user skill")
|
|
89
92
|
.argument("<name>", "Skill name")
|
|
90
|
-
.
|
|
91
|
-
|
|
93
|
+
.option("--scope <scope>", "Skill scope: global, workspace, or all", "all")
|
|
94
|
+
.action((name, options) => {
|
|
95
|
+
const scope = normalizeUserSkillScope(options.scope);
|
|
96
|
+
const skill = manager.get(name, scope);
|
|
92
97
|
if (!skill) {
|
|
93
98
|
console.error(`Skill "${name}" not found.`);
|
|
94
99
|
process.exitCode = 1;
|
|
95
100
|
return;
|
|
96
101
|
}
|
|
97
|
-
manager.remove(skill.id);
|
|
102
|
+
manager.remove(skill.id, scope);
|
|
98
103
|
console.log(`Removed skill "${skill.name}".`);
|
|
99
104
|
});
|
|
100
105
|
program
|
|
101
106
|
.command("enable")
|
|
102
107
|
.description("Enable a user skill")
|
|
103
108
|
.argument("<name>", "Skill name")
|
|
104
|
-
.
|
|
105
|
-
|
|
109
|
+
.option("--scope <scope>", "Skill scope: global, workspace, or all", "all")
|
|
110
|
+
.action((name, options) => {
|
|
111
|
+
const scope = normalizeUserSkillScope(options.scope);
|
|
112
|
+
const skill = manager.get(name, scope);
|
|
106
113
|
if (!skill) {
|
|
107
114
|
console.error(`Skill "${name}" not found.`);
|
|
108
115
|
process.exitCode = 1;
|
|
109
116
|
return;
|
|
110
117
|
}
|
|
111
|
-
manager.setEnabled(skill.id, true);
|
|
118
|
+
manager.setEnabled(skill.id, true, scope);
|
|
112
119
|
console.log(`Enabled skill "${skill.name}".`);
|
|
113
120
|
});
|
|
114
121
|
program
|
|
115
122
|
.command("disable")
|
|
116
123
|
.description("Disable a user skill")
|
|
117
124
|
.argument("<name>", "Skill name")
|
|
118
|
-
.
|
|
119
|
-
|
|
125
|
+
.option("--scope <scope>", "Skill scope: global, workspace, or all", "all")
|
|
126
|
+
.action((name, options) => {
|
|
127
|
+
const scope = normalizeUserSkillScope(options.scope);
|
|
128
|
+
const skill = manager.get(name, scope);
|
|
120
129
|
if (!skill) {
|
|
121
130
|
console.error(`Skill "${name}" not found.`);
|
|
122
131
|
process.exitCode = 1;
|
|
123
132
|
return;
|
|
124
133
|
}
|
|
125
|
-
manager.setEnabled(skill.id, false);
|
|
134
|
+
manager.setEnabled(skill.id, false, scope);
|
|
126
135
|
console.log(`Disabled skill "${skill.name}".`);
|
|
127
136
|
});
|
|
128
137
|
program
|
|
129
138
|
.command("install")
|
|
130
139
|
.description("Install a skill from a URL (GitHub or skills.sh)")
|
|
131
140
|
.argument("<url>", "Skill URL")
|
|
132
|
-
.
|
|
133
|
-
|
|
134
|
-
|
|
141
|
+
.option("--scope <scope>", "Skill scope: global or workspace", "global")
|
|
142
|
+
.action(async (url, options) => {
|
|
143
|
+
const skill = await manager.installFromUrl(url, normalizeWritableUserSkillScope(options.scope));
|
|
144
|
+
printJson({ id: skill.id, name: skill.name, scope: skill.scope, source: skill.source });
|
|
135
145
|
});
|
|
136
146
|
if (argv.length <= 2) {
|
|
137
147
|
program.outputHelp();
|
package/dist/tools/guides.js
CHANGED
|
@@ -63,6 +63,23 @@ pibo ralph add \\
|
|
|
63
63
|
|
|
64
64
|
Explicit options override template fields.
|
|
65
65
|
|
|
66
|
+
Runtime overrides are optional and apply to sessions created by the job:
|
|
67
|
+
|
|
68
|
+
\`\`\`bash
|
|
69
|
+
pibo ralph add \\
|
|
70
|
+
--room "<room-id>" \\
|
|
71
|
+
--prompt "Use a specific runtime." \\
|
|
72
|
+
--model openai/gpt-5 \\
|
|
73
|
+
--thinking high \\
|
|
74
|
+
--fast \\
|
|
75
|
+
--json
|
|
76
|
+
|
|
77
|
+
pibo ralph edit <job-id> --model openai/gpt-5 --thinking medium --no-fast --json
|
|
78
|
+
pibo ralph edit <job-id> --clear-model --clear-thinking --clear-fast --json
|
|
79
|
+
\`\`\`
|
|
80
|
+
|
|
81
|
+
Use \`--model <provider/model>\`, \`--thinking off|minimal|low|medium|high|xhigh\`, and \`--fast\`/\`--no-fast\` to set runtime options. Use the \`--clear-*\` flags on \`edit\` to return to profile/default runtime behavior.
|
|
82
|
+
|
|
66
83
|
## Inspect and Debug
|
|
67
84
|
|
|
68
85
|
\`\`\`bash
|