@pasko70/pibo 2.2.4 → 2.3.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/agent-runtime/capabilities.js +9 -1
- package/dist/agent-runtime/context-build.js +5 -2
- package/dist/agent-runtimes/codex-native/adapter.js +5 -0
- package/dist/agent-runtimes/omp/adapter.js +5 -0
- package/dist/agent-runtimes/omp/turn.js +2 -0
- package/dist/agent-runtimes/pi/adapter.js +28 -7
- package/dist/agent-runtimes/pi/intent-tracing.js +120 -0
- package/dist/agent-runtimes/pi/routed-session.js +25 -8
- package/dist/agent-runtimes/pi/runtime.js +28 -16
- package/dist/apps/chat/chat-settings-routes.js +44 -3
- package/dist/apps/chat/chat-transcription.js +85 -0
- package/dist/apps/chat/data/chat-data-mappers.js +4 -4
- package/dist/apps/chat/stream.js +23 -9
- package/dist/apps/chat/trace-v2.js +1 -0
- package/dist/apps/chat/web-app.js +49 -0
- package/dist/apps/chat-ui/assets/{dist-luJVFsmq.js → dist-Byygd1lH.js} +1 -1
- package/dist/apps/chat-ui/assets/{dist-ltfz1vFX.js → dist-C9BrS7sL.js} +1 -1
- package/dist/apps/chat-ui/assets/{dist-rf4HYdoa.js → dist-CUcAofmV.js} +1 -1
- package/dist/apps/chat-ui/assets/{dist-CImWCF2M.js → dist-D4RU6xu3.js} +1 -1
- package/dist/apps/chat-ui/assets/{dist-BFwTuvyi.js → dist-DusFwy0L.js} +1 -1
- package/dist/apps/chat-ui/assets/{index-nZQXUpxE.css → index-BJ56TREg.css} +1 -1
- package/dist/apps/chat-ui/assets/index-Bifi_kjN.js +228 -0
- package/dist/apps/chat-ui/index.html +2 -2
- package/dist/apps/chat-vscode-web/assets/index-WsLm1mo3.js +43 -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-2.3.0.vsix +0 -0
- package/dist/core/codex-compat.js +1 -3
- package/dist/core/context-build.js +16 -7
- package/dist/core/gateway-resource-guard.js +35 -14
- package/dist/core/gateway-settings.js +64 -0
- package/dist/core/session-router.js +226 -46
- package/dist/core/user-settings.js +20 -0
- package/dist/data/ingest-service.js +14 -2
- package/dist/debug/agents.js +391 -0
- package/dist/debug/index.js +14 -2
- package/dist/gateway/server.js +2 -0
- package/dist/index.js +6 -1
- package/dist/plugins/builtin.js +4 -2
- package/dist/plugins/openai-chatgpt-transcription.js +12 -0
- package/dist/plugins/openai-transcription.js +12 -0
- package/dist/plugins/registry.js +23 -0
- package/dist/session-ui/delegation.js +4 -2
- package/dist/session-ui/terminalRows.js +51 -1
- package/dist/shared/trace-async-agent-runs.js +4 -2
- package/dist/shared/trace-event-projection.js +12 -2
- package/dist/shared/trace-live-reducer.js +4 -0
- package/dist/shared/trace-patch-nodes.js +1 -0
- package/dist/shared/trace-subagent-links.js +19 -6
- package/dist/subagents/observations.js +149 -0
- package/dist/subagents/tool.js +177 -46
- package/dist/tools/session-service.js +1 -0
- package/dist/tools/session-tool-set.js +9 -5
- package/dist/transcription/openai-chatgpt.js +148 -0
- package/dist/transcription/openai.js +72 -0
- package/dist/transcription/types.js +8 -0
- package/npm-shrinkwrap.json +2 -2
- package/package.json +1 -1
- package/dist/apps/chat-ui/assets/index-D2Maa2v1.js +0 -226
- package/dist/apps/chat-vscode-web/assets/index-BpurWVnX.js +0 -41
- package/dist/apps/vscode-artifacts/pibo-vscode-ext-2.2.4.vsix +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { createPiboGoalToolDefinitions, PIBO_GOAL_TOOL_NAMES } from "../loops/tools.js";
|
|
2
2
|
import { createRunToolDefinitions } from "../runs/tools.js";
|
|
3
|
-
import {
|
|
3
|
+
import { createAgentToolDefinitions } from "../subagents/tool.js";
|
|
4
4
|
import { CODEX_BROWSER_TOOL_NAMES, createCodexBrowserToolDefinitions, } from "./codex-browser.js";
|
|
5
5
|
import { createCodexCompatToolDefinitions } from "./codex-compat.js";
|
|
6
6
|
import { createRuntimeToolDefinition } from "./runtime/tool.js";
|
|
@@ -18,6 +18,7 @@ export function isEnabledCodexBrowserToolProfile(tool) {
|
|
|
18
18
|
}
|
|
19
19
|
export function isGeneratedPiboTool(name) {
|
|
20
20
|
return name === "runtime"
|
|
21
|
+
|| name.startsWith("pibo_agents_")
|
|
21
22
|
|| name.startsWith("pibo_subagent_")
|
|
22
23
|
|| name.startsWith("pibo_run_")
|
|
23
24
|
|| PIBO_GOAL_TOOL_NAMES.includes(name);
|
|
@@ -33,6 +34,9 @@ function getToolDefinition(tool, context = {}) {
|
|
|
33
34
|
/** Assemble the selected Pibo-managed tool set without importing any harness package. */
|
|
34
35
|
export function createPiboSessionToolDefinitions(options) {
|
|
35
36
|
const { profile } = options;
|
|
37
|
+
if (profile.subagents.some((subagent) => subagent.enabled !== false) && options.subagentRunner && !options.agentsController) {
|
|
38
|
+
throw new Error("CreatePiboSessionToolDefinitionsOptions.subagentRunner is retired. Provide agentsController so the session can expose the four pibo_agents_* management tools.");
|
|
39
|
+
}
|
|
36
40
|
const runtimeProfileTool = profile.tools.find(isEnabledRuntimeToolProfile);
|
|
37
41
|
const runtimeTool = runtimeProfileTool && options.runtimeToolController
|
|
38
42
|
? createRuntimeToolDefinition(options.runtimeToolController)
|
|
@@ -53,8 +57,8 @@ export function createPiboSessionToolDefinitions(options) {
|
|
|
53
57
|
const goalTools = profile.toolPackages.goalControl !== false
|
|
54
58
|
? createPiboGoalToolDefinitions(options.toolContext ?? {})
|
|
55
59
|
: [];
|
|
56
|
-
const
|
|
57
|
-
?
|
|
60
|
+
const agentTools = options.agentsController
|
|
61
|
+
? createAgentToolDefinitions(profile.subagents, options.agentsController)
|
|
58
62
|
: [];
|
|
59
63
|
const nativeYieldableTools = [...(options.nativeYieldableTools ?? [])];
|
|
60
64
|
const yieldableTools = [
|
|
@@ -64,7 +68,7 @@ export function createPiboSessionToolDefinitions(options) {
|
|
|
64
68
|
.map((tool) => getToolDefinition(tool, options.toolContext)),
|
|
65
69
|
...(runtimeTool && runtimeProfileTool?.yieldable !== false ? [runtimeTool] : []),
|
|
66
70
|
...codexBrowserTools.filter((definition) => profile.tools.find((tool) => tool.name === definition.name)?.yieldable !== false),
|
|
67
|
-
...
|
|
71
|
+
...agentTools,
|
|
68
72
|
...codexCompatTools,
|
|
69
73
|
];
|
|
70
74
|
const runTools = profile.toolPackages.runControl === true
|
|
@@ -77,7 +81,7 @@ export function createPiboSessionToolDefinitions(options) {
|
|
|
77
81
|
...profileToolDefinitions,
|
|
78
82
|
...(runtimeTool ? [runtimeTool] : []),
|
|
79
83
|
...codexBrowserTools,
|
|
80
|
-
...
|
|
84
|
+
...agentTools,
|
|
81
85
|
...codexCompatTools,
|
|
82
86
|
...goalTools,
|
|
83
87
|
...runTools,
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
import { readPiCredential, resolvePiProviderAuth, } from "../agent-runtimes/pi/credentials.js";
|
|
2
|
+
import { PiboTranscriptionError, } from "./types.js";
|
|
3
|
+
export const OPENAI_CHATGPT_TRANSCRIPTION_PROVIDER_ID = "openai-chatgpt";
|
|
4
|
+
export const OPENAI_CODEX_AUTH_PROVIDER_ID = "openai-codex";
|
|
5
|
+
export const DEFAULT_OPENAI_CHATGPT_TRANSCRIPTION_URL = "https://chatgpt.com/backend-api/transcribe";
|
|
6
|
+
export const DEFAULT_OPENAI_CHATGPT_USER_AGENT = "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/148.0.0.0 Safari/537.36";
|
|
7
|
+
export function createOpenAiChatGptTranscriptionProvider(options = {}) {
|
|
8
|
+
const url = options.url ?? DEFAULT_OPENAI_CHATGPT_TRANSCRIPTION_URL;
|
|
9
|
+
const fetchImpl = options.fetch ?? fetch;
|
|
10
|
+
const getAuth = options.getAuth ?? resolveOpenAiChatGptTranscriptionAuth;
|
|
11
|
+
const isConfigured = options.isConfigured ?? hasOpenAiCodexOAuthCredential;
|
|
12
|
+
return {
|
|
13
|
+
id: OPENAI_CHATGPT_TRANSCRIPTION_PROVIDER_ID,
|
|
14
|
+
name: "ChatGPT Subscription",
|
|
15
|
+
description: "Uses the existing OpenAI Codex OAuth login and ChatGPT subscription through Codex's transcription path.",
|
|
16
|
+
isConfigured,
|
|
17
|
+
async transcribe(input) {
|
|
18
|
+
if (input.audio.bytes.byteLength === 0) {
|
|
19
|
+
throw new PiboTranscriptionError("The audio recording is empty.", "invalid_audio");
|
|
20
|
+
}
|
|
21
|
+
let auth;
|
|
22
|
+
try {
|
|
23
|
+
auth = await getAuth();
|
|
24
|
+
}
|
|
25
|
+
catch (error) {
|
|
26
|
+
throw new PiboTranscriptionError("ChatGPT Subscription authentication could not be loaded. Sign in again under Settings → Providers.", "not_configured", { cause: error });
|
|
27
|
+
}
|
|
28
|
+
if (!auth?.accessToken) {
|
|
29
|
+
throw new PiboTranscriptionError("ChatGPT Subscription authentication is not configured. Sign in to OpenAI (ChatGPT Plus/Pro) under Settings → Providers.", "not_configured");
|
|
30
|
+
}
|
|
31
|
+
const form = new FormData();
|
|
32
|
+
const audioBytes = input.audio.bytes.slice().buffer;
|
|
33
|
+
const audio = new Blob([audioBytes], { type: input.audio.mimeType || "application/octet-stream" });
|
|
34
|
+
form.append("file", audio, input.audio.filename);
|
|
35
|
+
const headers = {
|
|
36
|
+
Authorization: `Bearer ${auth.accessToken}`,
|
|
37
|
+
Origin: "https://chatgpt.com",
|
|
38
|
+
Referer: "https://chatgpt.com/",
|
|
39
|
+
"User-Agent": chatGptUserAgent(input.clientUserAgent),
|
|
40
|
+
};
|
|
41
|
+
if (auth.accountId)
|
|
42
|
+
headers["ChatGPT-Account-Id"] = auth.accountId;
|
|
43
|
+
let response;
|
|
44
|
+
try {
|
|
45
|
+
response = await fetchImpl(url, {
|
|
46
|
+
method: "POST",
|
|
47
|
+
headers,
|
|
48
|
+
body: form,
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
catch (error) {
|
|
52
|
+
throw new PiboTranscriptionError("ChatGPT subscription transcription request failed.", "provider_error", { cause: error });
|
|
53
|
+
}
|
|
54
|
+
const responseText = await response.text().catch(() => "");
|
|
55
|
+
const payload = parseJsonObject(responseText);
|
|
56
|
+
if (!response.ok) {
|
|
57
|
+
const detail = transcriptionErrorMessage(payload, responseText);
|
|
58
|
+
const loginGuidance = response.status === 401
|
|
59
|
+
? " Sign in again under Settings → Providers."
|
|
60
|
+
: "";
|
|
61
|
+
throw new PiboTranscriptionError(`ChatGPT subscription transcription request failed (${response.status})${detail ? `: ${detail}` : "."}${loginGuidance}`, "provider_error");
|
|
62
|
+
}
|
|
63
|
+
const text = transcriptionText(payload);
|
|
64
|
+
if (!text) {
|
|
65
|
+
throw new PiboTranscriptionError("ChatGPT returned an empty transcription.", "provider_error");
|
|
66
|
+
}
|
|
67
|
+
return { text };
|
|
68
|
+
},
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
async function hasOpenAiCodexOAuthCredential() {
|
|
72
|
+
return (await readPiCredential(OPENAI_CODEX_AUTH_PROVIDER_ID))?.type === "oauth";
|
|
73
|
+
}
|
|
74
|
+
async function resolveOpenAiChatGptTranscriptionAuth() {
|
|
75
|
+
const credential = await readPiCredential(OPENAI_CODEX_AUTH_PROVIDER_ID);
|
|
76
|
+
if (credential?.type !== "oauth")
|
|
77
|
+
return undefined;
|
|
78
|
+
const resolvedAuth = await resolvePiProviderAuth(OPENAI_CODEX_AUTH_PROVIDER_ID);
|
|
79
|
+
const accessToken = resolvedAuth?.auth.apiKey;
|
|
80
|
+
if (!accessToken)
|
|
81
|
+
return undefined;
|
|
82
|
+
return {
|
|
83
|
+
accessToken,
|
|
84
|
+
accountId: getOpenAiAccountId(accessToken, credential.accountId),
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
function chatGptUserAgent(value) {
|
|
88
|
+
const userAgent = value?.replace(/[\u0000-\u001f\u007f]/g, "").trim();
|
|
89
|
+
return userAgent && userAgent.length <= 512 && /\bMozilla\/5\.0\b/.test(userAgent)
|
|
90
|
+
? userAgent
|
|
91
|
+
: DEFAULT_OPENAI_CHATGPT_USER_AGENT;
|
|
92
|
+
}
|
|
93
|
+
function getOpenAiAccountId(accessToken, storedAccountId) {
|
|
94
|
+
if (typeof storedAccountId === "string" && storedAccountId.trim())
|
|
95
|
+
return storedAccountId.trim();
|
|
96
|
+
const payload = decodeJwtPayload(accessToken);
|
|
97
|
+
const auth = payload?.["https://api.openai.com/auth"];
|
|
98
|
+
if (!auth || typeof auth !== "object" || Array.isArray(auth))
|
|
99
|
+
return undefined;
|
|
100
|
+
const accountId = auth.chatgpt_account_id;
|
|
101
|
+
return typeof accountId === "string" && accountId.trim() ? accountId.trim() : undefined;
|
|
102
|
+
}
|
|
103
|
+
function decodeJwtPayload(token) {
|
|
104
|
+
try {
|
|
105
|
+
const payload = token.split(".")[1];
|
|
106
|
+
if (!payload)
|
|
107
|
+
return undefined;
|
|
108
|
+
const normalized = payload.replace(/-/g, "+").replace(/_/g, "/");
|
|
109
|
+
const padded = normalized.padEnd(Math.ceil(normalized.length / 4) * 4, "=");
|
|
110
|
+
const parsed = JSON.parse(Buffer.from(padded, "base64").toString("utf8"));
|
|
111
|
+
return parsed && typeof parsed === "object" && !Array.isArray(parsed)
|
|
112
|
+
? parsed
|
|
113
|
+
: undefined;
|
|
114
|
+
}
|
|
115
|
+
catch {
|
|
116
|
+
return undefined;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
function parseJsonObject(value) {
|
|
120
|
+
try {
|
|
121
|
+
const parsed = JSON.parse(value);
|
|
122
|
+
return parsed && typeof parsed === "object" && !Array.isArray(parsed)
|
|
123
|
+
? parsed
|
|
124
|
+
: undefined;
|
|
125
|
+
}
|
|
126
|
+
catch {
|
|
127
|
+
return undefined;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
function transcriptionText(payload) {
|
|
131
|
+
const text = payload?.text;
|
|
132
|
+
return typeof text === "string" && text.trim() ? text.trim() : undefined;
|
|
133
|
+
}
|
|
134
|
+
function transcriptionErrorMessage(payload, responseText) {
|
|
135
|
+
const error = payload?.error;
|
|
136
|
+
const message = error && typeof error === "object" && !Array.isArray(error)
|
|
137
|
+
? error.message
|
|
138
|
+
: undefined;
|
|
139
|
+
const candidate = typeof message === "string"
|
|
140
|
+
? message
|
|
141
|
+
: typeof payload?.detail === "string"
|
|
142
|
+
? payload.detail
|
|
143
|
+
: responseText.trimStart().startsWith("<")
|
|
144
|
+
? "ChatGPT rejected the request at its web boundary."
|
|
145
|
+
: responseText;
|
|
146
|
+
const normalized = candidate.replace(/\s+/g, " ").trim();
|
|
147
|
+
return normalized ? normalized.slice(0, 300) : undefined;
|
|
148
|
+
}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { getPiProviderAuthStatus, resolvePiProviderAuth } from "../agent-runtimes/pi/credentials.js";
|
|
2
|
+
import { PiboTranscriptionError, } from "./types.js";
|
|
3
|
+
export const OPENAI_TRANSCRIPTION_PROVIDER_ID = "openai-api";
|
|
4
|
+
export const OPENAI_API_CREDENTIAL_PROVIDER_ID = "openai";
|
|
5
|
+
export const DEFAULT_OPENAI_TRANSCRIPTION_MODEL = "gpt-4o-mini-transcribe";
|
|
6
|
+
export const DEFAULT_OPENAI_TRANSCRIPTION_URL = "https://api.openai.com/v1/audio/transcriptions";
|
|
7
|
+
export function createOpenAiTranscriptionProvider(options = {}) {
|
|
8
|
+
const model = options.model ?? DEFAULT_OPENAI_TRANSCRIPTION_MODEL;
|
|
9
|
+
const url = options.url ?? DEFAULT_OPENAI_TRANSCRIPTION_URL;
|
|
10
|
+
const fetchImpl = options.fetch ?? fetch;
|
|
11
|
+
const getApiKey = options.getApiKey ?? (async () => (await resolvePiProviderAuth(OPENAI_API_CREDENTIAL_PROVIDER_ID))?.auth.apiKey);
|
|
12
|
+
const isConfigured = options.isConfigured ?? (async () => (await getPiProviderAuthStatus(OPENAI_API_CREDENTIAL_PROVIDER_ID)).configured);
|
|
13
|
+
return {
|
|
14
|
+
id: OPENAI_TRANSCRIPTION_PROVIDER_ID,
|
|
15
|
+
name: "OpenAI API",
|
|
16
|
+
description: `Official OpenAI Audio Transcriptions API using ${model}.`,
|
|
17
|
+
isConfigured,
|
|
18
|
+
async transcribe(input) {
|
|
19
|
+
if (input.audio.bytes.byteLength === 0) {
|
|
20
|
+
throw new PiboTranscriptionError("The audio recording is empty.", "invalid_audio");
|
|
21
|
+
}
|
|
22
|
+
const apiKey = await getApiKey();
|
|
23
|
+
if (!apiKey) {
|
|
24
|
+
throw new PiboTranscriptionError("OpenAI API authentication is not configured. Add an OpenAI API key in Settings → Providers.", "not_configured");
|
|
25
|
+
}
|
|
26
|
+
const form = new FormData();
|
|
27
|
+
const audioBytes = input.audio.bytes.slice().buffer;
|
|
28
|
+
const audio = new Blob([audioBytes], { type: input.audio.mimeType || "application/octet-stream" });
|
|
29
|
+
form.append("file", audio, input.audio.filename);
|
|
30
|
+
form.append("model", model);
|
|
31
|
+
let response;
|
|
32
|
+
try {
|
|
33
|
+
response = await fetchImpl(url, {
|
|
34
|
+
method: "POST",
|
|
35
|
+
headers: { Authorization: `Bearer ${apiKey}` },
|
|
36
|
+
body: form,
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
catch (error) {
|
|
40
|
+
throw new PiboTranscriptionError("OpenAI transcription request failed.", "provider_error", { cause: error });
|
|
41
|
+
}
|
|
42
|
+
const payload = await response.json().catch(() => undefined);
|
|
43
|
+
if (!response.ok) {
|
|
44
|
+
const detail = transcriptionErrorMessage(payload);
|
|
45
|
+
throw new PiboTranscriptionError(`OpenAI transcription request failed (${response.status})${detail ? `: ${detail}` : "."}`, "provider_error");
|
|
46
|
+
}
|
|
47
|
+
const text = transcriptionText(payload);
|
|
48
|
+
if (!text) {
|
|
49
|
+
throw new PiboTranscriptionError("OpenAI returned an empty transcription.", "provider_error");
|
|
50
|
+
}
|
|
51
|
+
return { text, model };
|
|
52
|
+
},
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
function transcriptionText(payload) {
|
|
56
|
+
if (!payload || typeof payload !== "object" || Array.isArray(payload))
|
|
57
|
+
return undefined;
|
|
58
|
+
const text = payload.text;
|
|
59
|
+
return typeof text === "string" && text.trim() ? text.trim() : undefined;
|
|
60
|
+
}
|
|
61
|
+
function transcriptionErrorMessage(payload) {
|
|
62
|
+
if (!payload || typeof payload !== "object" || Array.isArray(payload))
|
|
63
|
+
return undefined;
|
|
64
|
+
const error = payload.error;
|
|
65
|
+
const message = error && typeof error === "object" && !Array.isArray(error)
|
|
66
|
+
? error.message
|
|
67
|
+
: undefined;
|
|
68
|
+
if (typeof message !== "string")
|
|
69
|
+
return undefined;
|
|
70
|
+
const normalized = message.replace(/\s+/g, " ").trim();
|
|
71
|
+
return normalized ? normalized.slice(0, 300) : undefined;
|
|
72
|
+
}
|
package/npm-shrinkwrap.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pasko70/pibo",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.3.0",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "@pasko70/pibo",
|
|
9
|
-
"version": "2.
|
|
9
|
+
"version": "2.3.0",
|
|
10
10
|
"workspaces": [
|
|
11
11
|
"packages/workflows"
|
|
12
12
|
],
|