@pasko70/pibo 2.2.4 → 2.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 (50) hide show
  1. package/dist/agent-runtime/capabilities.js +9 -1
  2. package/dist/agent-runtimes/codex-native/adapter.js +5 -0
  3. package/dist/agent-runtimes/omp/adapter.js +5 -0
  4. package/dist/agent-runtimes/omp/turn.js +2 -0
  5. package/dist/agent-runtimes/pi/adapter.js +27 -6
  6. package/dist/agent-runtimes/pi/intent-tracing.js +120 -0
  7. package/dist/agent-runtimes/pi/routed-session.js +25 -8
  8. package/dist/agent-runtimes/pi/runtime.js +3 -0
  9. package/dist/apps/chat/chat-settings-routes.js +44 -3
  10. package/dist/apps/chat/chat-transcription.js +85 -0
  11. package/dist/apps/chat/data/chat-data-mappers.js +4 -4
  12. package/dist/apps/chat/stream.js +23 -9
  13. package/dist/apps/chat/trace-v2.js +1 -0
  14. package/dist/apps/chat/web-app.js +49 -0
  15. package/dist/apps/chat-ui/assets/{dist-CImWCF2M.js → dist-BCRR_a0Z.js} +1 -1
  16. package/dist/apps/chat-ui/assets/{dist-luJVFsmq.js → dist-BK7eaoLT.js} +1 -1
  17. package/dist/apps/chat-ui/assets/{dist-BFwTuvyi.js → dist-CTUT484B.js} +1 -1
  18. package/dist/apps/chat-ui/assets/{dist-ltfz1vFX.js → dist-fNgdnmyE.js} +1 -1
  19. package/dist/apps/chat-ui/assets/{dist-rf4HYdoa.js → dist-wq3P0LZj.js} +1 -1
  20. package/dist/apps/chat-ui/assets/{index-nZQXUpxE.css → index-BJ56TREg.css} +1 -1
  21. package/dist/apps/chat-ui/assets/index-DsFKL_EZ.js +228 -0
  22. package/dist/apps/chat-ui/index.html +2 -2
  23. package/dist/apps/chat-vscode-web/assets/index-R4FTxr78.js +43 -0
  24. package/dist/apps/chat-vscode-web/index.html +1 -1
  25. package/dist/apps/vscode-artifacts/latest.vsix +0 -0
  26. package/dist/apps/vscode-artifacts/pibo-vscode-ext-2.2.5.vsix +0 -0
  27. package/dist/core/gateway-resource-guard.js +35 -14
  28. package/dist/core/gateway-settings.js +64 -0
  29. package/dist/core/session-router.js +5 -1
  30. package/dist/core/user-settings.js +20 -0
  31. package/dist/data/ingest-service.js +2 -2
  32. package/dist/debug/index.js +7 -2
  33. package/dist/gateway/server.js +2 -0
  34. package/dist/index.js +5 -0
  35. package/dist/plugins/builtin.js +4 -2
  36. package/dist/plugins/openai-chatgpt-transcription.js +12 -0
  37. package/dist/plugins/openai-transcription.js +12 -0
  38. package/dist/plugins/registry.js +23 -0
  39. package/dist/session-ui/terminalRows.js +51 -1
  40. package/dist/shared/trace-event-projection.js +4 -0
  41. package/dist/shared/trace-live-reducer.js +4 -0
  42. package/dist/shared/trace-patch-nodes.js +1 -0
  43. package/dist/transcription/openai-chatgpt.js +148 -0
  44. package/dist/transcription/openai.js +72 -0
  45. package/dist/transcription/types.js +8 -0
  46. package/npm-shrinkwrap.json +2 -2
  47. package/package.json +1 -1
  48. package/dist/apps/chat-ui/assets/index-D2Maa2v1.js +0 -226
  49. package/dist/apps/chat-vscode-web/assets/index-BpurWVnX.js +0 -41
  50. package/dist/apps/vscode-artifacts/pibo-vscode-ext-2.2.4.vsix +0 -0
@@ -5,7 +5,7 @@
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
6
  <meta name="theme-color" content="#101d22" />
7
7
  <title>Pibo</title>
8
- <script type="module" crossorigin src="/apps/chat-vscode/assets/index-BpurWVnX.js"></script>
8
+ <script type="module" crossorigin src="/apps/chat-vscode/assets/index-R4FTxr78.js"></script>
9
9
  <link rel="stylesheet" crossorigin href="/apps/chat-vscode/assets/index-CF1-9PKU.css">
10
10
  </head>
11
11
  <body>
@@ -3,6 +3,7 @@ import { freemem, totalmem } from "node:os";
3
3
  import { promisify } from "node:util";
4
4
  import { getHeapStatistics } from "node:v8";
5
5
  import { collectYieldedRunHostResourceSnapshot } from "../runs/resource-isolation.js";
6
+ import { DEFAULT_GATEWAY_CONCURRENT_YIELDED_RUNS, DEFAULT_SESSION_CONCURRENT_YIELDED_RUNS, resolvePiboGatewaySettings, } from "./gateway-settings.js";
6
7
  const execFileAsync = promisify(execFile);
7
8
  const DEFAULT_POLICY = Object.freeze({
8
9
  mode: "block",
@@ -10,17 +11,19 @@ const DEFAULT_POLICY = Object.freeze({
10
11
  minHeapAvailableBytes: 64 * 1024 * 1024,
11
12
  maxRssBytes: 1536 * 1024 * 1024,
12
13
  knownDaemonWarningRssBytes: 2 * 1024 * 1024 * 1024,
13
- maxConcurrentYieldedRuns: 1,
14
+ maxConcurrentYieldedRuns: DEFAULT_GATEWAY_CONCURRENT_YIELDED_RUNS,
15
+ sessionConcurrentYieldedRuns: DEFAULT_SESSION_CONCURRENT_YIELDED_RUNS,
14
16
  yieldedRunMemoryReservationBytes: 2 * 1024 * 1024 * 1024,
15
17
  });
16
- export function resolveGatewayResourceGuardPolicy(env = process.env) {
18
+ export function resolveGatewayResourceGuardPolicy(env = process.env, gatewaySettings = resolvePiboGatewaySettings(env)) {
17
19
  return {
18
20
  mode: parseMode(env.PIBO_GATEWAY_RESOURCE_GUARD, DEFAULT_POLICY.mode),
19
21
  minFreeMemoryBytes: parseByteThreshold(env.PIBO_GATEWAY_MIN_FREE_MEMORY_BYTES, DEFAULT_POLICY.minFreeMemoryBytes),
20
22
  minHeapAvailableBytes: parseByteThreshold(env.PIBO_GATEWAY_MIN_HEAP_AVAILABLE_BYTES, DEFAULT_POLICY.minHeapAvailableBytes),
21
23
  maxRssBytes: parseByteThreshold(env.PIBO_GATEWAY_MAX_RSS_BYTES, DEFAULT_POLICY.maxRssBytes),
22
24
  knownDaemonWarningRssBytes: parseByteThreshold(env.PIBO_GATEWAY_KNOWN_DAEMON_WARNING_RSS_BYTES, DEFAULT_POLICY.knownDaemonWarningRssBytes),
23
- maxConcurrentYieldedRuns: parsePositiveInteger(env.PIBO_GATEWAY_MAX_CONCURRENT_YIELDED_RUNS, DEFAULT_POLICY.maxConcurrentYieldedRuns),
25
+ maxConcurrentYieldedRuns: gatewaySettings.maxConcurrentYieldedRuns,
26
+ sessionConcurrentYieldedRuns: gatewaySettings.sessionConcurrentYieldedRuns,
24
27
  yieldedRunMemoryReservationBytes: parseByteThreshold(env.PIBO_GATEWAY_YIELDED_RUN_MEMORY_RESERVATION_BYTES, DEFAULT_POLICY.yieldedRunMemoryReservationBytes),
25
28
  };
26
29
  }
@@ -39,7 +42,7 @@ export function collectGatewayProcessMemory() {
39
42
  };
40
43
  }
41
44
  export function buildGatewayResourceSnapshot(options = {}) {
42
- const policy = resolveGatewayResourceGuardPolicy(options.env);
45
+ const policy = resolveGatewayResourceGuardPolicy(options.env, options.gatewaySettings);
43
46
  const gateway = collectGatewayProcessMemory();
44
47
  const hostResources = options.hostResourceSnapshot ?? collectYieldedRunHostResourceSnapshot({ now: options.now });
45
48
  const host = { freeBytes: hostResources.memoryFreeBytes || freemem(), availableBytes: hostResources.memoryAvailableBytes || freemem(), totalBytes: totalmem() };
@@ -91,15 +94,30 @@ export function assertGatewayResourceAvailableForWork(workLabel, env = process.e
91
94
  }
92
95
  export class GatewayWorkAdmissionController {
93
96
  activeReservations = new Set();
94
- reserve(workLabel, env = process.env) {
95
- const snapshot = buildGatewayResourceSnapshot({ env, includeProcesses: false });
97
+ activeSessionReservations = new Map();
98
+ reserve(workLabel, options = {}) {
99
+ const snapshot = buildGatewayResourceSnapshot({
100
+ env: options.env,
101
+ gatewaySettings: options.gatewaySettings,
102
+ includeProcesses: false,
103
+ });
96
104
  const policy = snapshot.policy;
97
105
  if (snapshot.guardAction === "block") {
98
106
  throwGatewayResourceBlock(workLabel, snapshot.checks.filter((check) => check.severity === "critical").map((check) => check.message));
99
107
  }
100
108
  if (policy.mode === "block" && this.activeReservations.size >= policy.maxConcurrentYieldedRuns) {
101
109
  throwGatewayResourceBlock(workLabel, [
102
- `Active yielded runs ${this.activeReservations.size} reached the configured limit ${policy.maxConcurrentYieldedRuns}. Wait for an active run to settle or raise PIBO_GATEWAY_MAX_CONCURRENT_YIELDED_RUNS explicitly.`,
110
+ `Active yielded runs ${this.activeReservations.size} reached the configured gateway limit ${policy.maxConcurrentYieldedRuns}. Wait for an active run to settle or raise PIBO_GATEWAY_MAX_CONCURRENT_YIELDED_RUNS in Settings or the gateway environment.`,
111
+ ]);
112
+ }
113
+ const activeForSession = options.sessionId
114
+ ? this.activeSessionReservations.get(options.sessionId) ?? 0
115
+ : 0;
116
+ if (policy.mode === "block"
117
+ && options.sessionId
118
+ && activeForSession >= policy.sessionConcurrentYieldedRuns) {
119
+ throwGatewayResourceBlock(workLabel, [
120
+ `Session ${options.sessionId} has ${activeForSession} active yielded runs and reached the configured session limit ${policy.sessionConcurrentYieldedRuns}. Wait for an active run to settle or raise PIBO_SESSION_CONCURRENT_YIELDED_RUNS in Settings or the gateway environment.`,
103
121
  ]);
104
122
  }
105
123
  if (policy.mode === "block" &&
@@ -110,6 +128,8 @@ export class GatewayWorkAdmissionController {
110
128
  }
111
129
  const reservation = Symbol(workLabel);
112
130
  this.activeReservations.add(reservation);
131
+ if (options.sessionId)
132
+ this.activeSessionReservations.set(options.sessionId, activeForSession + 1);
113
133
  let released = false;
114
134
  return {
115
135
  admission: collectYieldedRunHostResourceSnapshot(),
@@ -118,6 +138,13 @@ export class GatewayWorkAdmissionController {
118
138
  return;
119
139
  released = true;
120
140
  this.activeReservations.delete(reservation);
141
+ if (!options.sessionId)
142
+ return;
143
+ const nextSessionCount = (this.activeSessionReservations.get(options.sessionId) ?? 1) - 1;
144
+ if (nextSessionCount > 0)
145
+ this.activeSessionReservations.set(options.sessionId, nextSessionCount);
146
+ else
147
+ this.activeSessionReservations.delete(options.sessionId);
121
148
  },
122
149
  };
123
150
  }
@@ -157,7 +184,7 @@ export function renderGatewayResourceSnapshotText(snapshot) {
157
184
  lines.push(`Gateway PID: ${snapshot.gateway.pid}`);
158
185
  lines.push(`Gateway memory: rss=${snapshot.gateway.rssBytes} heapUsed=${snapshot.gateway.heapUsedBytes} heapAvailable=${snapshot.gateway.heapAvailableBytes} heapLimit=${snapshot.gateway.heapLimitBytes}`);
159
186
  lines.push(`Host memory: free=${snapshot.host.freeBytes} available=${snapshot.host.availableBytes} total=${snapshot.host.totalBytes}`);
160
- lines.push(`Thresholds: minFree=${snapshot.policy.minFreeMemoryBytes} minHeapAvailable=${snapshot.policy.minHeapAvailableBytes} maxRss=${snapshot.policy.maxRssBytes} daemonWarnRss=${snapshot.policy.knownDaemonWarningRssBytes} maxYieldedRuns=${snapshot.policy.maxConcurrentYieldedRuns} yieldedRunReservation=${snapshot.policy.yieldedRunMemoryReservationBytes}`);
187
+ lines.push(`Thresholds: minFree=${snapshot.policy.minFreeMemoryBytes} minHeapAvailable=${snapshot.policy.minHeapAvailableBytes} maxRss=${snapshot.policy.maxRssBytes} daemonWarnRss=${snapshot.policy.knownDaemonWarningRssBytes} maxYieldedRuns=${snapshot.policy.maxConcurrentYieldedRuns} sessionYieldedRuns=${snapshot.policy.sessionConcurrentYieldedRuns} yieldedRunReservation=${snapshot.policy.yieldedRunMemoryReservationBytes}`);
161
188
  lines.push(`Related processes: children=${snapshot.processes.children.length} knownDaemons=${snapshot.processes.knownDaemons.length} processList=${snapshot.processes.available ? "available" : "unavailable"}`);
162
189
  lines.push(`Yielded-run cgroups: units=${snapshot.yieldedRunUnits.units.length} systemdList=${snapshot.yieldedRunUnits.available ? "available" : "unavailable"}`);
163
190
  if (snapshot.processes.error)
@@ -242,12 +269,6 @@ function parseByteThreshold(value, fallback) {
242
269
  const parsed = Number(value);
243
270
  return Number.isFinite(parsed) && parsed >= 0 ? Math.floor(parsed) : fallback;
244
271
  }
245
- function parsePositiveInteger(value, fallback) {
246
- if (value === undefined || value.trim() === "")
247
- return fallback;
248
- const parsed = Number(value);
249
- return Number.isInteger(parsed) && parsed > 0 ? parsed : fallback;
250
- }
251
272
  function throwGatewayResourceBlock(workLabel, reasons) {
252
273
  throw new Error(`Gateway resource guard blocked ${workLabel} before starting: ${reasons.join("; ")}`);
253
274
  }
@@ -0,0 +1,64 @@
1
+ import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
2
+ import { dirname } from "node:path";
3
+ import { piboHomePath } from "./pibo-home.js";
4
+ export const DEFAULT_GATEWAY_CONCURRENT_YIELDED_RUNS = 50;
5
+ export const DEFAULT_SESSION_CONCURRENT_YIELDED_RUNS = 10;
6
+ export const DEFAULT_PIBO_GATEWAY_SETTINGS_PATH = "gateway-settings.json";
7
+ export function loadPiboGatewaySettings(env = process.env) {
8
+ return sanitizePiboGatewaySettings(readState().settings, env);
9
+ }
10
+ export function updatePiboGatewaySettings(patch, env = process.env) {
11
+ const state = readState();
12
+ const current = sanitizePiboGatewaySettings(state.settings, env);
13
+ const next = sanitizePiboGatewaySettings({ ...current, ...patch }, env);
14
+ state.settings = next;
15
+ writeState(state);
16
+ return next;
17
+ }
18
+ export function resolvePiboGatewaySettings(env = process.env) {
19
+ return {
20
+ maxConcurrentYieldedRuns: parsePositiveInteger(env.PIBO_GATEWAY_MAX_CONCURRENT_YIELDED_RUNS, DEFAULT_GATEWAY_CONCURRENT_YIELDED_RUNS),
21
+ sessionConcurrentYieldedRuns: parsePositiveInteger(env.PIBO_SESSION_CONCURRENT_YIELDED_RUNS, DEFAULT_SESSION_CONCURRENT_YIELDED_RUNS),
22
+ };
23
+ }
24
+ export function sanitizePiboGatewaySettings(value, env = process.env) {
25
+ const raw = value && typeof value === "object" && !Array.isArray(value)
26
+ ? value
27
+ : {};
28
+ const defaults = resolvePiboGatewaySettings(env);
29
+ return {
30
+ maxConcurrentYieldedRuns: sanitizeConcurrentYieldedRuns(raw.maxConcurrentYieldedRuns)
31
+ ?? defaults.maxConcurrentYieldedRuns,
32
+ sessionConcurrentYieldedRuns: sanitizeConcurrentYieldedRuns(raw.sessionConcurrentYieldedRuns)
33
+ ?? defaults.sessionConcurrentYieldedRuns,
34
+ };
35
+ }
36
+ export function sanitizeConcurrentYieldedRuns(value) {
37
+ if (typeof value !== "number" && typeof value !== "string")
38
+ return undefined;
39
+ const parsed = typeof value === "number" ? value : Number(value.trim());
40
+ return Number.isSafeInteger(parsed) && parsed > 0 ? parsed : undefined;
41
+ }
42
+ function parsePositiveInteger(value, fallback) {
43
+ return sanitizeConcurrentYieldedRuns(value) ?? fallback;
44
+ }
45
+ function readState() {
46
+ const path = piboHomePath(DEFAULT_PIBO_GATEWAY_SETTINGS_PATH);
47
+ if (!existsSync(path))
48
+ return {};
49
+ try {
50
+ const parsed = JSON.parse(readFileSync(path, "utf-8"));
51
+ const raw = parsed && typeof parsed === "object" && !Array.isArray(parsed)
52
+ ? parsed
53
+ : {};
54
+ return { settings: raw.settings };
55
+ }
56
+ catch {
57
+ return {};
58
+ }
59
+ }
60
+ function writeState(state) {
61
+ const path = piboHomePath(DEFAULT_PIBO_GATEWAY_SETTINGS_PATH);
62
+ mkdirSync(dirname(path), { recursive: true });
63
+ writeFileSync(path, `${JSON.stringify(state, null, 2)}\n`);
64
+ }
@@ -15,6 +15,7 @@ import { AgentRuntimeBindingMissingError, AgentRuntimeUnavailableError } from ".
15
15
  import { validateAgentRuntimeProfileCapabilities } from "../agent-runtime/profile-validation.js";
16
16
  import { getDefaultPiboWorkspace } from "./workspace.js";
17
17
  import { loadPiboModelDefaults, selectRequestedFastMode } from "./model-defaults.js";
18
+ import { loadPiboGatewaySettings } from "./gateway-settings.js";
18
19
  import { loadPiboUserSettings } from "./user-settings.js";
19
20
  import { resolvePiboSessionActiveModel } from "./session-model.js";
20
21
  import { isPiboThinkingLevel } from "./thinking.js";
@@ -1630,7 +1631,10 @@ export class PiboSessionRouter {
1630
1631
  createRunToolController(parentPiboSessionId) {
1631
1632
  return {
1632
1633
  startToolRun: ({ toolName, params, completionPolicy, retryable, maxAttempts, timeoutMs, serviceWarning, resources, execute, cancel }) => {
1633
- const admission = this.gatewayWorkAdmission.reserve(`yielded run ${toolName}`);
1634
+ const admission = this.gatewayWorkAdmission.reserve(`yielded run ${toolName}`, {
1635
+ sessionId: parentPiboSessionId,
1636
+ gatewaySettings: loadPiboGatewaySettings(),
1637
+ });
1634
1638
  if (resources)
1635
1639
  resources.admission = admission.admission;
1636
1640
  const reminderGeneration = this.runReminderGeneration(parentPiboSessionId);
@@ -5,6 +5,8 @@ import { sanitizeTelemetryRetentionSettings } from "./telemetry-retention-settin
5
5
  import { sanitizeTelemetryStaleThresholdSettings } from "./telemetry-staleness.js";
6
6
  export const DEFAULT_USER_TIMEZONE = "UTC";
7
7
  export const DEFAULT_WEB_ANNOTATIONS_TOGGLE_SHORTCUT = "Alt+Shift+A";
8
+ export const DEFAULT_TRANSCRIPTION_PROVIDER_ID = "openai-chatgpt";
9
+ const LEGACY_OPENAI_TRANSCRIPTION_PROVIDER_ID = "openai";
8
10
  export const DEFAULT_PIBO_USER_SETTINGS_PATH = "user-settings.json";
9
11
  export function loadPiboUserSettings() {
10
12
  return sanitizeUserSettings(readState().settings);
@@ -37,6 +39,23 @@ export function sanitizeShortcut(value) {
37
39
  const shortcut = value.replace(/[\u0000-\u001f\u007f]/g, "").trim();
38
40
  return shortcut && shortcut.length <= 80 ? shortcut : undefined;
39
41
  }
42
+ export function sanitizeTranscriptionProviderId(value) {
43
+ if (typeof value !== "string")
44
+ return undefined;
45
+ const providerId = value.trim();
46
+ return /^[a-z0-9][a-z0-9._-]{0,79}$/i.test(providerId) ? providerId : undefined;
47
+ }
48
+ export function sanitizeTranscriptionSettings(value) {
49
+ const raw = value && typeof value === "object" && !Array.isArray(value)
50
+ ? value
51
+ : {};
52
+ const providerId = sanitizeTranscriptionProviderId(raw.providerId);
53
+ return {
54
+ providerId: providerId === LEGACY_OPENAI_TRANSCRIPTION_PROVIDER_ID
55
+ ? DEFAULT_TRANSCRIPTION_PROVIDER_ID
56
+ : providerId ?? DEFAULT_TRANSCRIPTION_PROVIDER_ID,
57
+ };
58
+ }
40
59
  export function sanitizeTimezone(value) {
41
60
  if (typeof value !== "string")
42
61
  return undefined;
@@ -58,6 +77,7 @@ function sanitizeUserSettings(value) {
58
77
  return {
59
78
  timezone: sanitizeTimezone(raw.timezone) ?? DEFAULT_USER_TIMEZONE,
60
79
  shortcuts: sanitizeShortcutSettings(raw.shortcuts),
80
+ transcription: sanitizeTranscriptionSettings(raw.transcription),
61
81
  telemetryStaleThresholds: sanitizeTelemetryStaleThresholdSettings(raw.telemetryStaleThresholds),
62
82
  telemetryRetention: sanitizeTelemetryRetentionSettings(raw.telemetryRetention),
63
83
  };
@@ -327,9 +327,9 @@ function attributesForOutputEvent(event) {
327
327
  if (event.type === "thinking_started" || event.type === "thinking_delta" || event.type === "thinking_finished")
328
328
  return { thinkingIndex: event.thinkingIndex, contentIndex: event.contentIndex };
329
329
  if (event.type === "tool_call")
330
- return { toolCallId: event.toolCallId, toolName: event.toolName, argsComplete: event.argsComplete };
330
+ return { toolCallId: event.toolCallId, toolName: event.toolName, argsComplete: event.argsComplete, intent: event.intent };
331
331
  if (event.type === "tool_execution_started" || event.type === "tool_execution_updated" || event.type === "tool_execution_finished")
332
- return { toolCallId: event.toolCallId, toolName: event.toolName, isError: "isError" in event ? event.isError : undefined };
332
+ return { toolCallId: event.toolCallId, toolName: event.toolName, isError: "isError" in event ? event.isError : undefined, intent: event.intent };
333
333
  if (event.type === "subagent_session")
334
334
  return { toolCallId: event.toolCallId, toolName: event.toolName, subagentName: event.subagentName, childPiboSessionId: event.childPiboSessionId, threadKey: event.threadKey };
335
335
  if (event.type === "execution_result")
@@ -88,7 +88,8 @@ async function runDebugResources(args) {
88
88
  }
89
89
  const options = parseOptions(args);
90
90
  const { collectGatewayResourceSnapshot, renderGatewayResourceSnapshotText } = await import("../core/gateway-resource-guard.js");
91
- const snapshot = await collectGatewayResourceSnapshot();
91
+ const { loadPiboGatewaySettings } = await import("../core/gateway-settings.js");
92
+ const snapshot = await collectGatewayResourceSnapshot({ gatewaySettings: loadPiboGatewaySettings() });
92
93
  if (options.json)
93
94
  console.log(JSON.stringify(snapshot, null, 2));
94
95
  else
@@ -1088,9 +1089,13 @@ Environment:
1088
1089
  PIBO_GATEWAY_MIN_HEAP_AVAILABLE_BYTES=<bytes>
1089
1090
  PIBO_GATEWAY_MAX_RSS_BYTES=<bytes>
1090
1091
  PIBO_GATEWAY_KNOWN_DAEMON_WARNING_RSS_BYTES=<bytes>
1091
- PIBO_GATEWAY_MAX_CONCURRENT_YIELDED_RUNS=<count> (default: 1)
1092
+ PIBO_GATEWAY_MAX_CONCURRENT_YIELDED_RUNS=<count> (default: 50)
1093
+ PIBO_SESSION_CONCURRENT_YIELDED_RUNS=<count> (default: 10)
1092
1094
  PIBO_GATEWAY_YIELDED_RUN_MEMORY_RESERVATION_BYTES=<bytes> (default: 2147483648)
1093
1095
 
1096
+ Web settings:
1097
+ Settings -> Concurrency persists overrides that apply to new yielded runs immediately.
1098
+
1094
1099
  Next:
1095
1100
  pibo debug resources --json
1096
1101
  pibo compute health --json
@@ -429,6 +429,8 @@ export class PiboGatewayServer {
429
429
  getProfiles: () => this.pluginRegistry.getProfileInfos(),
430
430
  createProfile: (name) => this.pluginRegistry.createProfile(name),
431
431
  getCapabilityCatalog: () => this.pluginRegistry.getCapabilityCatalog(),
432
+ getTranscriptionProviderInfos: () => this.pluginRegistry.getTranscriptionProviderInfos(),
433
+ transcribe: (providerId, input) => this.pluginRegistry.transcribe(providerId, input),
432
434
  inspectAgentRuntimeInstances: () => this.pluginRegistry.inspectAgentRuntimeInstances(),
433
435
  getAgentRuntimeAuthStatus: (runtimeInstanceId) => this.requireRouter().getAgentRuntimeAuthStatus(runtimeInstanceId),
434
436
  startAgentRuntimeAuth: (runtimeInstanceId, input) => this.requireRouter().startAgentRuntimeAuth(runtimeInstanceId, input),
package/dist/index.js CHANGED
@@ -1,10 +1,15 @@
1
1
  export { createDefaultPiboProfile, createDefaultPiboPluginRegistry, createDefaultPiboPlugins, createGatewayProducerPiboPluginRegistry, createGatewayProducerPiboProfile, CODEX_NATIVE_PROFILE_NAME, CODEX_NATIVE_RUNTIME_INSTANCE_ID, piboCodexNativePlugin, OMP_PROFILE_NAME, OMP_RUNTIME_INSTANCE_ID, piboOmpPlugin, piboCorePlugin, piboGatewayProducerPlugin, } from "./plugins/builtin.js";
2
2
  export { createPiboBetterAuthPlugin } from "./plugins/better-auth.js";
3
3
  export { createPiboChatWebPlugin } from "./plugins/chat-web.js";
4
+ export { createPiboOpenAiChatGptTranscriptionPlugin, piboOpenAiChatGptTranscriptionPlugin } from "./plugins/openai-chatgpt-transcription.js";
5
+ export { createPiboOpenAiTranscriptionPlugin, piboOpenAiTranscriptionPlugin } from "./plugins/openai-transcription.js";
4
6
  export { createPiboContextFilesPlugin } from "./plugins/context-files.js";
5
7
  export { createPiboWebHostPlugin } from "./plugins/web.js";
6
8
  export { createChatWebApp } from "./apps/chat/web-app.js";
7
9
  export { createBetterAuthService } from "./auth/better-auth.js";
10
+ export { DEFAULT_OPENAI_CHATGPT_TRANSCRIPTION_URL, DEFAULT_OPENAI_CHATGPT_USER_AGENT, OPENAI_CHATGPT_TRANSCRIPTION_PROVIDER_ID, OPENAI_CODEX_AUTH_PROVIDER_ID, createOpenAiChatGptTranscriptionProvider, } from "./transcription/openai-chatgpt.js";
11
+ export { DEFAULT_OPENAI_TRANSCRIPTION_MODEL, DEFAULT_OPENAI_TRANSCRIPTION_URL, OPENAI_API_CREDENTIAL_PROVIDER_ID, OPENAI_TRANSCRIPTION_PROVIDER_ID, createOpenAiTranscriptionProvider, } from "./transcription/openai.js";
12
+ export { PiboTranscriptionError } from "./transcription/types.js";
8
13
  export { DEFAULT_AGENT_RUNTIME_INSTANCE_ID, InitialSessionContext, InitialSessionContextBuilder, normalizeToolProfile, } from "./core/profiles.js";
9
14
  export { AgentRuntimeAdapterRegistry } from "./agent-runtime/registry.js";
10
15
  export { validateAgentRuntimeProfileCapabilities } from "./agent-runtime/profile-validation.js";
@@ -13,6 +13,8 @@ import { piboCodexNativePlugin } from "./codex-native.js";
13
13
  import { addPiboNativeToolingContext, registerPiboNativeTooling } from "./native-tooling.js";
14
14
  import { piboWebAnnotationsPlugin } from "./web-annotations.js";
15
15
  import { piboOmpPlugin } from "./omp.js";
16
+ import { piboOpenAiChatGptTranscriptionPlugin } from "./openai-chatgpt-transcription.js";
17
+ import { piboOpenAiTranscriptionPlugin } from "./openai-transcription.js";
16
18
  import { definePiboPlugin, PiboPluginRegistry } from "./registry.js";
17
19
  import { PI_AGENT_RUNTIME_DRIVER } from "../agent-runtimes/pi/adapter.js";
18
20
  export { createDefaultPiboProfile, DEFAULT_PIBO_PROFILE_NAME } from "../core/default-profile.js";
@@ -589,11 +591,11 @@ export const piboGatewayProducerPlugin = definePiboPlugin({
589
591
  },
590
592
  });
591
593
  export function createDefaultPiboPlugins() {
592
- return [piboCorePlugin, piboCodexNativePlugin, piboCodexCompatPlugin, piboWebAnnotationsPlugin, piboOmpPlugin];
594
+ return [piboCorePlugin, piboCodexNativePlugin, piboCodexCompatPlugin, piboWebAnnotationsPlugin, piboOmpPlugin, piboOpenAiChatGptTranscriptionPlugin, piboOpenAiTranscriptionPlugin];
593
595
  }
594
596
  export function createGatewayProducerPiboPluginRegistry() {
595
597
  return PiboPluginRegistry.create({
596
- plugins: [piboCorePlugin, piboCodexNativePlugin, piboGatewayProducerPlugin, piboCodexCompatPlugin, piboWebAnnotationsPlugin, piboOmpPlugin],
598
+ plugins: [piboCorePlugin, piboCodexNativePlugin, piboGatewayProducerPlugin, piboCodexCompatPlugin, piboWebAnnotationsPlugin, piboOmpPlugin, piboOpenAiChatGptTranscriptionPlugin, piboOpenAiTranscriptionPlugin],
597
599
  });
598
600
  }
599
601
  export function createDefaultPiboPluginRegistry() {
@@ -0,0 +1,12 @@
1
+ import { createOpenAiChatGptTranscriptionProvider, } from "../transcription/openai-chatgpt.js";
2
+ import { definePiboPlugin } from "./registry.js";
3
+ export function createPiboOpenAiChatGptTranscriptionPlugin(options = {}) {
4
+ return definePiboPlugin({
5
+ id: "pibo.transcription.openai-chatgpt",
6
+ name: "ChatGPT Subscription Transcription",
7
+ register(api) {
8
+ api.registerTranscriptionProvider(createOpenAiChatGptTranscriptionProvider(options));
9
+ },
10
+ });
11
+ }
12
+ export const piboOpenAiChatGptTranscriptionPlugin = createPiboOpenAiChatGptTranscriptionPlugin();
@@ -0,0 +1,12 @@
1
+ import { createOpenAiTranscriptionProvider, } from "../transcription/openai.js";
2
+ import { definePiboPlugin } from "./registry.js";
3
+ export function createPiboOpenAiTranscriptionPlugin(options = {}) {
4
+ return definePiboPlugin({
5
+ id: "pibo.transcription.openai",
6
+ name: "OpenAI Transcription",
7
+ register(api) {
8
+ api.registerTranscriptionProvider(createOpenAiTranscriptionProvider(options));
9
+ },
10
+ });
11
+ }
12
+ export const piboOpenAiTranscriptionPlugin = createPiboOpenAiTranscriptionPlugin();
@@ -44,6 +44,7 @@ export class PiboPluginRegistry {
44
44
  gatewaySlashCommands = new Map();
45
45
  channels = new Map();
46
46
  authService;
47
+ transcriptionProviders = new Map();
47
48
  webApps = new Map();
48
49
  capabilityPackages = new Map();
49
50
  eventListeners = new Set();
@@ -181,6 +182,23 @@ export class PiboPluginRegistry {
181
182
  }
182
183
  this.authService = service;
183
184
  }
185
+ registerTranscriptionProvider(provider) {
186
+ this.addUnique(this.transcriptionProviders, provider.id, provider, "transcription provider");
187
+ }
188
+ async getTranscriptionProviderInfos() {
189
+ return await Promise.all([...this.transcriptionProviders.values()].map(async (provider) => ({
190
+ id: provider.id,
191
+ name: provider.name,
192
+ description: provider.description,
193
+ configured: provider.isConfigured ? await Promise.resolve(provider.isConfigured()).catch(() => false) : true,
194
+ pluginId: provider.pluginId,
195
+ pluginName: provider.pluginId ? this.pluginNames.get(provider.pluginId) : undefined,
196
+ })));
197
+ }
198
+ async transcribe(providerId, input) {
199
+ const provider = this.getRequired(this.transcriptionProviders, providerId, "transcription provider");
200
+ return { providerId, ...await provider.transcribe(input) };
201
+ }
184
202
  registerWebApp(app) {
185
203
  if (this.webApps.has(app.name)) {
186
204
  throw new Error(`Duplicate web app "${app.name}"`);
@@ -414,6 +432,10 @@ export class PiboPluginRegistry {
414
432
  toolNames: [...pkg.toolNames],
415
433
  pluginId: pkg.pluginId ?? pluginId,
416
434
  });
435
+ const withPluginTranscriptionProviderContext = (provider) => ({
436
+ ...provider,
437
+ pluginId: provider.pluginId ?? pluginId,
438
+ });
417
439
  return {
418
440
  registerAgentRuntimeDriver: (driver) => this.registerAgentRuntimeDriver(driver),
419
441
  registerAgentRuntimeInstance: (instance) => this.registerAgentRuntimeInstance(instance),
@@ -430,6 +452,7 @@ export class PiboPluginRegistry {
430
452
  registerGatewayAction: (action) => this.registerGatewayAction(action),
431
453
  registerChannel: (channel) => this.registerChannel(channel),
432
454
  registerAuthService: (service) => this.registerAuthService(service),
455
+ registerTranscriptionProvider: (provider) => this.registerTranscriptionProvider(withPluginTranscriptionProviderContext(provider)),
433
456
  registerWebApp: (app) => this.registerWebApp(app),
434
457
  registerCapabilityPackage: (pkg) => this.registerCapabilityPackage(withPluginPackageContext(pkg)),
435
458
  registerLoopStopCondition: (condition) => this.registerLoopStopCondition(condition, pluginId),
@@ -18,7 +18,55 @@ export function buildCompactTerminalRows(traceView, options) {
18
18
  .filter((item) => item.node.type !== "agent.turn" && (options.showThinking || item.node.type !== "model.reasoning"));
19
19
  const candidates = syncThinkingToolRows(flatNodes.map((item) => createRowCandidate(item.node, item.turnId)));
20
20
  applyCompletedTurnTiming(candidates, turnById);
21
- return groupRelatedToolCandidates(reconcileConceptualRowCandidates(candidates)).map((candidate) => candidate.row);
21
+ const reconciled = reconcileConceptualRowCandidates(candidates);
22
+ const rows = (options.toolDisplayMode ?? "default") === "default"
23
+ ? groupRelatedToolCandidates(reconciled).map((candidate) => candidate.row)
24
+ : reconciled.map((candidate) => candidate.row);
25
+ return applyToolDisplayMode(rows, options.toolDisplayMode ?? "default");
26
+ }
27
+ function applyToolDisplayMode(rows, mode) {
28
+ if (mode === "default")
29
+ return rows;
30
+ if (mode === "hide")
31
+ return rows.filter((row) => !isToolDisplayRow(row));
32
+ return rows.flatMap((row) => {
33
+ if (!isToolDisplayRow(row))
34
+ return [row];
35
+ const intent = row.intent?.trim();
36
+ if (mode === "intent" && !intent)
37
+ return [];
38
+ const slimRow = {
39
+ ...row,
40
+ lines: row.lines.slice(0, 1),
41
+ input: undefined,
42
+ output: undefined,
43
+ error: undefined,
44
+ markdown: undefined,
45
+ expandable: false,
46
+ singleLine: true,
47
+ previewOmission: undefined,
48
+ detailItems: undefined,
49
+ };
50
+ if (mode !== "intent")
51
+ return [slimRow];
52
+ return [{
53
+ ...slimRow,
54
+ title: undefined,
55
+ summary: undefined,
56
+ lines: [{
57
+ prefix: "bullet",
58
+ tokens: [token(intent, row.status === "error" ? "red" : row.status === "done" ? "green" : "cyan", "semibold")],
59
+ }],
60
+ }];
61
+ });
62
+ }
63
+ function isToolDisplayRow(row) {
64
+ return row.id.startsWith("terminal:tool:")
65
+ || row.kind === "tool.call"
66
+ || row.kind === "tool.image"
67
+ || row.kind === "tool.group.exploring"
68
+ || row.kind === "tool.group.images"
69
+ || row.kind === "agent.delegation";
22
70
  }
23
71
  export function findActiveTurnStartedAt(traceView) {
24
72
  if (!traceView)
@@ -112,6 +160,7 @@ function createRowCandidate(node, turnId) {
112
160
  row: {
113
161
  ...candidate.row,
114
162
  id: compactTerminalRowIdentity(node),
163
+ intent: node.intent,
115
164
  ...debugFields(node),
116
165
  },
117
166
  };
@@ -164,6 +213,7 @@ function reconcileConceptualRowCandidates(candidates) {
164
213
  ...existing.row,
165
214
  ...candidate.row,
166
215
  sourceNodeIds: [...new Set([...existing.row.sourceNodeIds, ...candidate.row.sourceNodeIds])],
216
+ intent: candidate.row.intent ?? existing.row.intent,
167
217
  input: candidate.row.input ?? existing.row.input,
168
218
  output: candidate.row.output ?? existing.row.output,
169
219
  error: candidate.row.error ?? existing.row.error,
@@ -465,6 +465,7 @@ function traceNodeFromEvent(piboSessionId, event, childByParent, linkedChildByTo
465
465
  id: `tool:${event.toolCallId}`,
466
466
  parentId: turnParentId,
467
467
  toolCallId: event.toolCallId,
468
+ intent: event.intent,
468
469
  type: subagentTool ? "agent.delegation" : "tool.call",
469
470
  title: event.toolName,
470
471
  status: event.type === "tool_execution_finished"
@@ -685,6 +686,8 @@ function isNativeHistoryToolEchoEvent(event, coverage, sessionStatus) {
685
686
  event.type !== "tool_execution_updated" &&
686
687
  event.type !== "tool_execution_finished")
687
688
  return false;
689
+ if (typeof event.intent === "string" && event.intent.trim())
690
+ return false;
688
691
  return coverage.toolCallIds.has(event.toolCallId) || historyCoversEvent(event, coverage);
689
692
  }
690
693
  export function mergeMessageTurnTimings(...groups) {
@@ -917,6 +920,7 @@ function thinkingEventNodeId(event) {
917
920
  }
918
921
  function mergeToolEvent(target, update) {
919
922
  target.status = update.status;
923
+ target.intent = update.intent ?? target.intent;
920
924
  target.summary = update.summary ?? target.summary;
921
925
  target.input = mergeDelegationInput(target, update);
922
926
  target.output = update.output ?? target.output;
@@ -80,6 +80,7 @@ function storedEventFromStreamEvent(event, piboSessionId, nextSequence, now) {
80
80
  toolCallId: event.toolCallId,
81
81
  toolName: event.toolName,
82
82
  args: event.args,
83
+ ...(event.intent ? { intent: event.intent } : {}),
83
84
  };
84
85
  return makeStored(event, piboSessionId, "tool_execution_started", payload, nextSequence, now);
85
86
  }
@@ -95,6 +96,7 @@ function storedEventFromStreamEvent(event, piboSessionId, nextSequence, now) {
95
96
  toolName: event.toolName,
96
97
  args: event.args,
97
98
  partialResult: event.partialResult,
99
+ ...(event.intent ? { intent: event.intent } : {}),
98
100
  }
99
101
  : {
100
102
  type: "tool_call",
@@ -104,6 +106,7 @@ function storedEventFromStreamEvent(event, piboSessionId, nextSequence, now) {
104
106
  toolName: event.toolName,
105
107
  args: event.args,
106
108
  argsComplete: Boolean(event.argsComplete),
109
+ ...(event.intent ? { intent: event.intent } : {}),
107
110
  };
108
111
  return makeStored(event, piboSessionId, sourceEventType, payload, nextSequence, now);
109
112
  }
@@ -116,6 +119,7 @@ function storedEventFromStreamEvent(event, piboSessionId, nextSequence, now) {
116
119
  toolName: event.toolName,
117
120
  result: event.result,
118
121
  isError: Boolean(event.isError),
122
+ ...(event.intent ? { intent: event.intent } : {}),
119
123
  };
120
124
  return makeStored(event, piboSessionId, "tool_execution_finished", payload, nextSequence, now);
121
125
  }
@@ -52,6 +52,7 @@ function traceNodeShallowEqual(left, right) {
52
52
  left.eventId === right.eventId &&
53
53
  left.toolCallId === right.toolCallId &&
54
54
  left.runId === right.runId &&
55
+ left.intent === right.intent &&
55
56
  left.type === right.type &&
56
57
  left.title === right.title &&
57
58
  left.status === right.status &&