@pasko70/pibo 3.2.3 → 3.2.5

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.
Files changed (70) hide show
  1. package/dist/agent-runtime/auth.js +3 -5
  2. package/dist/agent-runtime/portable-history.js +1 -1
  3. package/dist/agent-runtimes/codex-native/client.js +2 -5
  4. package/dist/agent-runtimes/codex-native/redaction.js +3 -27
  5. package/dist/agent-runtimes/omp/client.js +2 -4
  6. package/dist/agent-runtimes/pi/adapter.js +1 -0
  7. package/dist/agent-runtimes/pi/runtime.js +1 -1
  8. package/dist/apps/chat/agent-store.js +1 -1
  9. package/dist/apps/chat/chat-files.js +3 -1
  10. package/dist/apps/chat/chat-request-normalizers.js +1 -1
  11. package/dist/apps/chat/chat-user-skill-routes.js +7 -0
  12. package/dist/apps/chat/data/project-service.js +49 -1
  13. package/dist/apps/chat/data/session-query-service.js +46 -6
  14. package/dist/apps/chat/loop-api.js +10 -1
  15. package/dist/apps/chat/ralph-api.js +10 -1
  16. package/dist/apps/chat/web-app.js +22 -5
  17. package/dist/apps/chat-ui/assets/{dist-CTsyojIh.js → dist-CTC-_3l0.js} +1 -1
  18. package/dist/apps/chat-ui/assets/{dist-BHio-Mzx.js → dist-CftLEFd5.js} +1 -1
  19. package/dist/apps/chat-ui/assets/{dist-DJ6Bhcuk.js → dist-Dq27Wt2q.js} +1 -1
  20. package/dist/apps/chat-ui/assets/{dist-CPKEoSPK.js → dist-Y4fHV5-Z.js} +1 -1
  21. package/dist/apps/chat-ui/assets/{dist-DNHFRMCk.js → dist-dGF-PDGY.js} +1 -1
  22. package/dist/apps/chat-ui/assets/index-C_P0gXvJ.js +228 -0
  23. package/dist/apps/chat-ui/assets/{index-Dc-6Xupt.css → index-DUGVw259.css} +1 -1
  24. package/dist/apps/chat-ui/index.html +2 -2
  25. package/dist/apps/chat-vscode-web/assets/{index-B1TuQNY5.js → index-B5X0NaRo.js} +4 -4
  26. package/dist/apps/chat-vscode-web/index.html +1 -1
  27. package/dist/apps/cli-ui/InkSessionApp.js +38 -28
  28. package/dist/auth/cli.js +4 -6
  29. package/dist/auth/machine-keys.js +20 -3
  30. package/dist/cli-session/localSessionSource.js +2 -4
  31. package/dist/compute/cli.js +16 -13
  32. package/dist/compute/docker.js +96 -48
  33. package/dist/core/base-prompt.js +27 -5
  34. package/dist/core/context-build.js +5 -15
  35. package/dist/core/sensitive-data-redaction.js +2 -2
  36. package/dist/core/session-router.js +15 -4
  37. package/dist/cron/cli.js +42 -10
  38. package/dist/cron/store.js +1 -1
  39. package/dist/data/cli.js +15 -7
  40. package/dist/data/payload-store.js +55 -7
  41. package/dist/data/schema.js +65 -23
  42. package/dist/debug/index.js +5 -0
  43. package/dist/debug/pty.js +45 -10
  44. package/dist/gateway/cli.js +18 -2
  45. package/dist/gateway/server.js +1 -0
  46. package/dist/loops/service.js +32 -16
  47. package/dist/mcp/runtime-session.js +2 -1
  48. package/dist/pi-packages/cli.js +5 -0
  49. package/dist/previews/cli.js +2 -6
  50. package/dist/previews/config.js +10 -0
  51. package/dist/previews/manager.js +2 -9
  52. package/dist/ralph/service.js +21 -10
  53. package/dist/session-ui/statusViewModel.js +2 -4
  54. package/dist/sessions/pibo-data-store.js +18 -0
  55. package/dist/sessions/store.js +9 -0
  56. package/dist/setup/cli.js +14 -7
  57. package/dist/setup/installation-profiles.js +20 -7
  58. package/dist/shared/trace-event-projection.js +32 -1
  59. package/dist/subagents/tool.js +3 -3
  60. package/dist/tools/browser-use-leases.js +11 -3
  61. package/dist/tools/index.js +0 -1
  62. package/dist/tools/mcp-bridge.js +1 -1
  63. package/dist/tools/runtime/node-worker-source.js +39 -5
  64. package/dist/tools/runtime/python-backend.js +6 -2
  65. package/dist/tools/runtime/registry.js +38 -6
  66. package/dist/vscode/cli.js +1 -2
  67. package/dist/vscode/install.js +21 -14
  68. package/npm-shrinkwrap.json +2 -2
  69. package/package.json +3 -1
  70. package/dist/apps/chat-ui/assets/index-Y6jYzsaC.js +0 -228
@@ -1,5 +1,6 @@
1
1
  export const NODE_RUNTIME_WORKER_SOURCE = String.raw `
2
2
  const vm = require("node:vm");
3
+ const inspector = require("node:inspector");
3
4
  const util = require("node:util");
4
5
  const fs = require("node:fs");
5
6
  const childProcess = require("node:child_process");
@@ -153,6 +154,7 @@ const consoleProxy = {
153
154
  dir: (value, options) => appendStdout(util.inspect(value, options) + "\n"),
154
155
  };
155
156
 
157
+ const runtimeContextName = "pibo-runtime-" + process.pid;
156
158
  const context = vm.createContext({
157
159
  console: consoleProxy,
158
160
  require: runtimeRequire,
@@ -169,10 +171,24 @@ const context = vm.createContext({
169
171
  setImmediate,
170
172
  clearImmediate,
171
173
  queueMicrotask,
172
- });
174
+ }, { name: runtimeContextName });
173
175
  context.global = context;
174
176
  context.globalThis = context;
175
177
 
178
+ const inspectorSession = new inspector.Session();
179
+ let runtimeContextId;
180
+ inspectorSession.on("Runtime.executionContextCreated", ({ params }) => {
181
+ if (params.context.name === runtimeContextName) runtimeContextId = params.context.id;
182
+ });
183
+ inspectorSession.connect();
184
+ const inspectorReady = inspectorPost("Runtime.enable");
185
+
186
+ function inspectorPost(method, params = {}) {
187
+ return new Promise((resolve, reject) => {
188
+ inspectorSession.post(method, params, (error, result) => error ? reject(error) : resolve(result));
189
+ });
190
+ }
191
+
176
192
  async function execute(req) {
177
193
  const mode = req.mode || "exec";
178
194
  const code = req.code || "";
@@ -230,16 +246,31 @@ async function inspectValue(req) {
230
246
  }
231
247
  }
232
248
 
233
- function listVars(req) {
249
+ async function listVars(req) {
234
250
  const includePrivate = Boolean(req.includePrivate);
235
251
  const maxItems = Number(req.maxItems || 100);
236
252
  const maxBytes = Number(req.maxBytes || 4096);
237
253
  const hidden = new Set(["console", "require", "process", "Buffer", "URL", "URLSearchParams", "TextEncoder", "TextDecoder", "global", "globalThis"]);
254
+ const lexicalNames = new Set();
255
+ try {
256
+ await inspectorReady;
257
+ if (runtimeContextId !== undefined) {
258
+ const result = await inspectorPost("Runtime.globalLexicalScopeNames", { executionContextId: runtimeContextId });
259
+ for (const name of result.names || []) lexicalNames.add(name);
260
+ }
261
+ } catch {}
262
+ const names = new Set([...Object.keys(context), ...lexicalNames]);
238
263
  const variables = [];
239
- for (const name of Object.keys(context).sort()) {
264
+ for (const name of [...names].sort()) {
240
265
  if (hidden.has(name)) continue;
241
266
  if (!includePrivate && name.startsWith("_")) continue;
242
- variables.push({ name, summary: summarize(context[name], maxBytes) });
267
+ let value;
268
+ try {
269
+ value = lexicalNames.has(name) ? vm.runInContext(name, context, { filename: "<pibo-runtime>", timeout: 15000 }) : context[name];
270
+ } catch {
271
+ continue;
272
+ }
273
+ variables.push({ name, summary: summarize(value, maxBytes) });
243
274
  if (variables.length >= maxItems) break;
244
275
  }
245
276
  return { id: req.id, status: "ok", variables, truncated: variables.length >= maxItems };
@@ -253,7 +284,10 @@ async function handle(req) {
253
284
  if (req.type === "exec") return await execute(req);
254
285
  if (req.type === "inspect") return await inspectValue(req);
255
286
  if (req.type === "vars") return listVars(req);
256
- if (req.type === "shutdown") return { id: req.id, status: "ok", shutdown: true };
287
+ if (req.type === "shutdown") {
288
+ inspectorSession.disconnect();
289
+ return { id: req.id, status: "ok", shutdown: true };
290
+ }
257
291
  return { id: req.id, status: "error", error: { name: "RuntimeProtocolError", message: "unknown request type " + req.type } };
258
292
  }
259
293
 
@@ -90,6 +90,9 @@ export class PythonRuntimeBackend {
90
90
  isAlive() {
91
91
  return this.alive;
92
92
  }
93
+ isBusy() {
94
+ return [...this.pending.values()].some((pending) => pending.requestType === "exec");
95
+ }
93
96
  getRecord() {
94
97
  return { pid: this.child.pid, cwd: this.cwd, executable: this.executable };
95
98
  }
@@ -194,10 +197,11 @@ export class PythonRuntimeBackend {
194
197
  const id = `req_${++this.requestCounter}`;
195
198
  return new Promise((resolveRequest, rejectRequest) => {
196
199
  const timer = setTimeout(() => {
197
- this.pending.delete(id);
200
+ if (!this.pending.has(id))
201
+ return;
198
202
  rejectRequest(new TimeoutError(`Runtime request ${type} timed out after ${timeoutMs}ms`));
199
203
  }, timeoutMs);
200
- this.pending.set(id, { resolve: resolveRequest, reject: rejectRequest, timer });
204
+ this.pending.set(id, { requestType: type, resolve: resolveRequest, reject: rejectRequest, timer });
201
205
  this.child.stdin.write(`${JSON.stringify({ id, type, ...payload })}\n`);
202
206
  });
203
207
  }
@@ -30,6 +30,7 @@ function notFoundVars(sessionId = "auto") {
30
30
  export class RuntimeSessionRegistry {
31
31
  options;
32
32
  sessions = new Map();
33
+ defaultStarts = new Map();
33
34
  maxHistoryEntries;
34
35
  constructor(options) {
35
36
  this.options = options;
@@ -79,9 +80,23 @@ export class RuntimeSessionRegistry {
79
80
  }
80
81
  }
81
82
  async exec(controllerPiboSessionId, input) {
82
- const session = input.sessionId
83
+ let session = input.sessionId
83
84
  ? this.getSessionForController(controllerPiboSessionId, input.sessionId)
84
- : await this.getOrStartDefault(controllerPiboSessionId, input);
85
+ : this.getDefault(controllerPiboSessionId, input.runtime ?? "python");
86
+ if (!input.sessionId && !session) {
87
+ const runtime = input.runtime ?? "python";
88
+ const started = await this.getOrStartDefault(controllerPiboSessionId, input);
89
+ if (started.status !== "ok" || !started.sessionId) {
90
+ return {
91
+ status: started.status === "ok" ? "failed" : started.status,
92
+ sessionId: started.sessionId ?? "auto",
93
+ runtime: started.runtime ?? runtime,
94
+ durationMs: 0,
95
+ error: started.error ?? { name: "RuntimeStartError", message: "Runtime session failed to start." },
96
+ };
97
+ }
98
+ session = this.getSessionForController(controllerPiboSessionId, started.sessionId);
99
+ }
85
100
  const sessionId = input.sessionId ?? session?.sessionId ?? "auto";
86
101
  if (!session)
87
102
  return notFoundExec(sessionId);
@@ -106,7 +121,9 @@ export class RuntimeSessionRegistry {
106
121
  result.executionCount = session.executionCount;
107
122
  session.lastExecAt = startedAt;
108
123
  session.updatedAt = nowIso();
109
- session.status = session.backend.isAlive() ? "idle" : "failed";
124
+ session.status = session.backend.isAlive()
125
+ ? session.backend.isBusy?.() === true ? "busy" : "idle"
126
+ : "failed";
110
127
  this.appendHistory(session, {
111
128
  id: randomUUID(),
112
129
  startedAt,
@@ -223,14 +240,25 @@ export class RuntimeSessionRegistry {
223
240
  const runtime = input.runtime ?? "python";
224
241
  const existing = this.getDefault(controllerPiboSessionId, runtime);
225
242
  if (existing)
226
- return existing;
227
- const started = await this.start(controllerPiboSessionId, {
243
+ return { status: "ok", sessionId: existing.sessionId, runtime: existing.runtime };
244
+ const key = `${controllerPiboSessionId}\0${runtime}`;
245
+ const pending = this.defaultStarts.get(key);
246
+ if (pending)
247
+ return pending;
248
+ const start = this.start(controllerPiboSessionId, {
228
249
  runtime,
229
250
  name: input.name,
230
251
  target: input.target,
231
252
  timeoutMs: input.timeoutMs,
232
253
  });
233
- return started.sessionId ? this.getSessionForController(controllerPiboSessionId, started.sessionId) : undefined;
254
+ this.defaultStarts.set(key, start);
255
+ try {
256
+ return await start;
257
+ }
258
+ finally {
259
+ if (this.defaultStarts.get(key) === start)
260
+ this.defaultStarts.delete(key);
261
+ }
234
262
  }
235
263
  getSessionForController(controllerPiboSessionId, sessionId) {
236
264
  const session = this.sessions.get(sessionId);
@@ -243,6 +271,10 @@ export class RuntimeSessionRegistry {
243
271
  session.status = "failed";
244
272
  session.updatedAt = nowIso();
245
273
  }
274
+ else if (session.status === "busy" && session.backend.isBusy?.() === false) {
275
+ session.status = "idle";
276
+ session.updatedAt = nowIso();
277
+ }
246
278
  return session;
247
279
  }
248
280
  appendHistory(session, entry) {
@@ -50,9 +50,8 @@ export async function runVscodeCli(argv = process.argv) {
50
50
  else if (result.status === "installed") {
51
51
  console.log(`installed\t${result.tagName}\t${result.vsixPath}`);
52
52
  }
53
- else {
53
+ if (result.status === "failed")
54
54
  process.exitCode = 1;
55
- }
56
55
  });
57
56
  program
58
57
  .command("uninstall")
@@ -11,13 +11,13 @@
11
11
  * The resolved VSIX is cached under `~/.pibo/vscode/cache/<tagName>/` so
12
12
  * repeated installs do not re-download.
13
13
  */
14
+ import { createHash } from "node:crypto";
14
15
  import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
15
16
  import { homedir } from "node:os";
16
17
  import { join, resolve } from "node:path";
17
18
  import { detectCodeBinary, listInstalledExtensions, runCodeCommand } from "./code-cli.js";
18
19
  import { downloadVsixAsset, fetchLatestVsix, isVsixAsset } from "./vsix-fetcher.js";
19
20
  import { DEFAULT_GITHUB_OWNER, DEFAULT_GITHUB_REPO, PIBO_VSCODE_CACHE_DIR, PIBO_VSCODE_EXTENSION_ID, } from "./types.js";
20
- import { findVsixAsset, fetchRelease } from "./vsix-fetcher.js";
21
21
  const DEFAULT_LOG = (message) => {
22
22
  console.log(message);
23
23
  };
@@ -33,6 +33,9 @@ function getCacheDir(options) {
33
33
  function cacheKeyForVersion(tagName) {
34
34
  return tagName.replace(/[^A-Za-z0-9._-]/g, "_");
35
35
  }
36
+ function cacheTagForUrl(url) {
37
+ return `url-${createHash("sha256").update(url).digest("hex").slice(0, 16)}`;
38
+ }
36
39
  function readCachedVsix(cacheDir, tagName) {
37
40
  const dir = join(cacheDir, cacheKeyForVersion(tagName));
38
41
  const path = join(dir, "pibo.vsix");
@@ -73,19 +76,23 @@ export async function resolveVsixArtifact(options) {
73
76
  }
74
77
  return { tagName: "local", vsixPath: absolute };
75
78
  }
79
+ if (options.fromUrl) {
80
+ const tagName = cacheTagForUrl(options.fromUrl);
81
+ if (!options.skipCache) {
82
+ const cached = readCachedVsix(options.cacheDir, tagName);
83
+ if (cached)
84
+ return { tagName, vsixPath: cached };
85
+ }
86
+ const bytes = await downloadVsixAsset({ url: options.fromUrl, fetchImpl: options.fetchImpl });
87
+ const cachedPath = writeCachedVsix(options.cacheDir, tagName, bytes);
88
+ return { tagName, vsixPath: cachedPath, bytes };
89
+ }
76
90
  if (!options.skipCache && !options.version) {
77
91
  const cachedTag = readCachedTagManifest(options.cacheDir);
78
92
  if (cachedTag?.tagName && cachedTag.vsixPath && existsSync(cachedTag.vsixPath)) {
79
93
  return { tagName: cachedTag.tagName, vsixPath: cachedTag.vsixPath };
80
94
  }
81
95
  }
82
- if (options.fromUrl) {
83
- const release = await fetchRelease({ owner: options.owner, repo: options.repo, fetchImpl: options.fetchImpl });
84
- const asset = findVsixAsset(release) ?? { name: "remote.vsix", browserDownloadUrl: options.fromUrl, size: 0, contentType: "application/octet-stream" };
85
- const bytes = await downloadVsixAsset({ url: options.fromUrl, fetchImpl: options.fetchImpl });
86
- const cachedPath = writeCachedVsix(options.cacheDir, release.tagName, bytes);
87
- return { tagName: release.tagName, vsixPath: cachedPath, bytes };
88
- }
89
96
  const result = await fetchLatestVsix({
90
97
  owner: options.owner,
91
98
  repo: options.repo,
@@ -151,7 +158,6 @@ export async function runInstall(options) {
151
158
  errorLog(reason);
152
159
  return { status: "failed", reason, codeBinary: detected.path, tagName: artifact.tagName };
153
160
  }
154
- writeCachedTagManifest(cacheDir, artifact.tagName, artifact.vsixPath);
155
161
  try {
156
162
  const installed = await listInstalledExtensions({
157
163
  binary: detected.path,
@@ -159,18 +165,19 @@ export async function runInstall(options) {
159
165
  env: options.env,
160
166
  });
161
167
  const ours = installed.find((entry) => entry.id === PIBO_VSCODE_EXTENSION_ID);
162
- if (ours) {
163
- log(`Installed ${ours.id}@${ours.version ?? "?"} via ${detected.path}`);
164
- }
165
- else {
166
- log(`code --install-extension reported success but ${PIBO_VSCODE_EXTENSION_ID} is not in the installed list.`);
168
+ if (!ours) {
169
+ const reason = `code --install-extension reported success but ${PIBO_VSCODE_EXTENSION_ID} is not in the installed list.`;
170
+ errorLog(reason);
171
+ return { status: "failed", reason, codeBinary: detected.path, tagName: artifact.tagName };
167
172
  }
173
+ log(`Installed ${ours.id}@${ours.version ?? "?"} via ${detected.path}`);
168
174
  }
169
175
  catch (listError) {
170
176
  // Listing the installed extensions is a best-effort check; do not fail the install on a listing error.
171
177
  const reason = listError instanceof Error ? listError.message : String(listError);
172
178
  log(`Install completed; failed to verify via --list-extensions: ${reason}`);
173
179
  }
180
+ writeCachedTagManifest(cacheDir, artifact.tagName, artifact.vsixPath);
174
181
  return { status: "installed", tagName: artifact.tagName, vsixPath: artifact.vsixPath, codeBinary: detected.path };
175
182
  }
176
183
  // Re-export for symmetry with code-cli.ts consumers.
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "@pasko70/pibo",
3
- "version": "3.2.3",
3
+ "version": "3.2.5",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "@pasko70/pibo",
9
- "version": "3.2.3",
9
+ "version": "3.2.5",
10
10
  "workspaces": [
11
11
  "packages/workflows"
12
12
  ],
package/package.json CHANGED
@@ -1,7 +1,9 @@
1
1
  {
2
2
  "name": "@pasko70/pibo",
3
- "version": "3.2.3",
3
+ "version": "3.2.5",
4
4
  "type": "module",
5
+ "main": "./dist/index.js",
6
+ "types": "./dist/index.d.ts",
5
7
  "workspaces": [
6
8
  "packages/workflows"
7
9
  ],