@pasko70/pibo 1.15.0 → 1.16.1
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/context/pibo-native-tooling.md +1 -1
- package/dist/apps/chat/model-catalog.js +2 -0
- package/dist/apps/chat/web-app.js +11 -0
- package/dist/apps/chat-ui/assets/{dist-Bi74WdBU.js → dist-BISHtc7t.js} +1 -1
- package/dist/apps/chat-ui/assets/{dist-Dq3i1LVZ.js → dist-CGlkj4C3.js} +1 -1
- package/dist/apps/chat-ui/assets/{dist-Dy5L1xOD.js → dist-CNZT1Z0L.js} +1 -1
- package/dist/apps/chat-ui/assets/{dist-BFwSuVfD.js → dist-CsgWBaSD.js} +1 -1
- package/dist/apps/chat-ui/assets/{dist-BYTi90un.js → dist-DDJJ8GK-.js} +1 -1
- package/dist/apps/chat-ui/assets/{dist-DS1ScAMf.js → dist-DXkRuRed.js} +1 -1
- package/dist/apps/chat-ui/assets/{dist-CuIwfDgF.js → dist-DltoBBze.js} +1 -1
- package/dist/apps/chat-ui/assets/{dist-DUgrMhHX.js → dist-DoMBxyQP.js} +1 -1
- package/dist/apps/chat-ui/assets/{dist-Zy3KnDp7.js → dist-I7cqk1W9.js} +1 -1
- package/dist/apps/chat-ui/assets/{dist-CYMM1_bS.js → dist-gWAQGdkD.js} +1 -1
- package/dist/apps/chat-ui/assets/index-CiKRTg5a.js +237 -0
- package/dist/apps/chat-ui/assets/index-E0RmuCkY.css +1 -0
- package/dist/apps/chat-ui/index.html +2 -2
- package/dist/apps/chat-vscode-web/assets/index-JHIrxu8c.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.16.1.vsix +0 -0
- package/dist/core/routed-session.js +17 -0
- package/dist/core/runtime.js +2 -0
- package/dist/core/session-router.js +20 -6
- package/dist/debug/web-streaming-benchmark-analysis.js +23 -0
- package/dist/debug/web-streaming-browser-library.js +0 -1
- package/dist/debug/web.js +4 -2
- package/dist/gateway/server.js +1 -0
- package/dist/plugins/builtin.js +4 -9
- package/dist/providers/openai-compat.js +6 -1
- package/dist/providers/qwen-token-plan.js +67 -0
- package/dist/shared/trace-event-projection.js +15 -15
- package/dist/shared/trace-live-reducer.js +1 -0
- package/package.json +1 -1
- package/dist/apps/chat-ui/assets/index-BZO4zpMi.js +0 -237
- package/dist/apps/chat-ui/assets/index-CoCl8FG8.css +0 -1
- package/dist/apps/chat-vscode-web/assets/index-V_pKPVAm.js +0 -41
- package/dist/apps/vscode-artifacts/pibo-vscode-ext-1.15.0.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-
|
|
8
|
+
<script type="module" crossorigin src="/apps/chat-vscode/assets/index-JHIrxu8c.js"></script>
|
|
9
9
|
<link rel="stylesheet" crossorigin href="/apps/chat-vscode/assets/index-Dupu1DzQ.css">
|
|
10
10
|
</head>
|
|
11
11
|
<body>
|
|
Binary file
|
|
Binary file
|
|
@@ -818,6 +818,22 @@ export class RoutedSession {
|
|
|
818
818
|
} : {}),
|
|
819
819
|
};
|
|
820
820
|
}
|
|
821
|
+
async getStatusSnapshot() {
|
|
822
|
+
const contextUsage = this.getContextUsage();
|
|
823
|
+
const providerUsage = await this.getProviderUsage();
|
|
824
|
+
return {
|
|
825
|
+
...this.getStatus(),
|
|
826
|
+
activeModel: this.getActiveModel(),
|
|
827
|
+
contextUsage: contextUsage
|
|
828
|
+
? {
|
|
829
|
+
tokens: contextUsage.tokens ?? undefined,
|
|
830
|
+
contextWindow: contextUsage.contextWindow ?? undefined,
|
|
831
|
+
percent: contextUsage.percent ?? undefined,
|
|
832
|
+
}
|
|
833
|
+
: contextUsage,
|
|
834
|
+
...(providerUsage ? { providerUsage } : {}),
|
|
835
|
+
};
|
|
836
|
+
}
|
|
821
837
|
getContextUsage() {
|
|
822
838
|
return this.runtime.session.getContextUsage();
|
|
823
839
|
}
|
|
@@ -1261,6 +1277,7 @@ export class RoutedSession {
|
|
|
1261
1277
|
return await gatewayAction.execute({
|
|
1262
1278
|
piboSessionId: this.piboSessionId,
|
|
1263
1279
|
getStatus: () => this.getStatus(),
|
|
1280
|
+
getStatusSnapshot: () => this.getStatusSnapshot(),
|
|
1264
1281
|
getContextUsage: () => this.getContextUsage(),
|
|
1265
1282
|
getActiveModel: () => this.getActiveModel(),
|
|
1266
1283
|
getProviderUsage: () => this.getProviderUsage(),
|
package/dist/core/runtime.js
CHANGED
|
@@ -22,6 +22,7 @@ import { DEFAULT_USER_TIMEZONE } from "./user-settings.js";
|
|
|
22
22
|
import { registerMiniMaxProvider } from "../providers/minimax.js";
|
|
23
23
|
import { registerGlmProvider } from "../providers/glm.js";
|
|
24
24
|
import { registerOpenAiGpt56Models } from "../providers/openai-gpt56.js";
|
|
25
|
+
import { registerQwenTokenPlanProvider } from "../providers/qwen-token-plan.js";
|
|
25
26
|
import { PIBO_APP_CONTEXT } from "../app-context.js";
|
|
26
27
|
import { createRuntimeToolDefinition } from "../tools/runtime/tool.js";
|
|
27
28
|
import { RuntimeSessionRegistry } from "../tools/runtime/registry.js";
|
|
@@ -291,6 +292,7 @@ export async function createPiboRuntime(options = {}) {
|
|
|
291
292
|
registerOpenAiGpt56Models(services.modelRegistry);
|
|
292
293
|
registerMiniMaxProvider(services.modelRegistry);
|
|
293
294
|
registerGlmProvider(services.modelRegistry);
|
|
295
|
+
registerQwenTokenPlanProvider(services.modelRegistry);
|
|
294
296
|
const ownsLocalRuntimeRegistry = options.runtimeToolController === undefined && profile.tools.some(isEnabledRuntimeTool);
|
|
295
297
|
const localRuntimeRegistry = ownsLocalRuntimeRegistry ? new RuntimeSessionRegistry({ cwd: runtimeCwd }) : undefined;
|
|
296
298
|
const runtimeToolController = options.runtimeToolController
|
|
@@ -23,6 +23,7 @@ import { PiboRuntimeTelemetryRecorder } from "./runtime-telemetry.js";
|
|
|
23
23
|
import { createPiboProviderTelemetryExtension } from "./provider-telemetry.js";
|
|
24
24
|
import { AsyncTelemetryWriter } from "../data/telemetry-writer.js";
|
|
25
25
|
const DEFAULT_SUBAGENT_REPLY_TIMEOUT_MS = 10 * 60 * 1000;
|
|
26
|
+
const DEFAULT_SUBAGENT_MAX_DEPTH = 3;
|
|
26
27
|
const DEFAULT_ROUTED_SESSION_IDLE_TIMEOUT_MS = 30 * 60 * 1000;
|
|
27
28
|
const DEFAULT_ROUTED_SESSION_DISPOSE_TIMEOUT_MS = 30 * 1000;
|
|
28
29
|
export const LOOP_RUNTIME_RETRY_DEFAULTS = {
|
|
@@ -43,7 +44,10 @@ export function resolvePiboSessionInitialFastMode(session) {
|
|
|
43
44
|
const value = session.metadata?.initialFastMode;
|
|
44
45
|
return typeof value === "boolean" ? value : undefined;
|
|
45
46
|
}
|
|
46
|
-
function
|
|
47
|
+
function hasReachedSubagentMaxDepth(subagent, depth) {
|
|
48
|
+
return depth >= (subagent.maxDepth ?? DEFAULT_SUBAGENT_MAX_DEPTH);
|
|
49
|
+
}
|
|
50
|
+
function profileForSession(baseProfile, piSessionId, parentPiSessionId, subagentDepth) {
|
|
47
51
|
const options = {
|
|
48
52
|
profileName: baseProfile.profileName,
|
|
49
53
|
sessionId: piSessionId,
|
|
@@ -59,7 +63,7 @@ function profileForSession(baseProfile, piSessionId, parentPiSessionId) {
|
|
|
59
63
|
subagentFast: baseProfile.subagentFast,
|
|
60
64
|
skills: baseProfile.skills,
|
|
61
65
|
tools: baseProfile.tools,
|
|
62
|
-
subagents: baseProfile.subagents,
|
|
66
|
+
subagents: baseProfile.subagents.filter((subagent) => !hasReachedSubagentMaxDepth(subagent, subagentDepth)),
|
|
63
67
|
mcpServers: baseProfile.mcpServers,
|
|
64
68
|
contextFiles: baseProfile.contextFiles,
|
|
65
69
|
piPackages: baseProfile.piPackages,
|
|
@@ -479,6 +483,15 @@ export class PiboSessionRouter {
|
|
|
479
483
|
getSessionRuntimeStatus(piboSessionId) {
|
|
480
484
|
return this.sessions.get(piboSessionId)?.getStatus();
|
|
481
485
|
}
|
|
486
|
+
async getSessionStatusSnapshot(piboSessionId) {
|
|
487
|
+
const session = await this.getOrCreateSession(piboSessionId);
|
|
488
|
+
try {
|
|
489
|
+
return await session.getStatusSnapshot();
|
|
490
|
+
}
|
|
491
|
+
finally {
|
|
492
|
+
this.scheduleIdleSessionEvictionIfIdle(piboSessionId);
|
|
493
|
+
}
|
|
494
|
+
}
|
|
482
495
|
async setLiveSessionActiveModel(piboSessionId, model) {
|
|
483
496
|
const session = this.sessions.get(piboSessionId);
|
|
484
497
|
if (!session)
|
|
@@ -700,6 +713,7 @@ export class PiboSessionRouter {
|
|
|
700
713
|
const modelDefaults = this.resolveModelDefaults();
|
|
701
714
|
const activeModel = this.ensureSessionActiveModel(piboSession, profile, parentPiSessionId, modelDefaults);
|
|
702
715
|
const initialThinkingLevel = resolvePiboSessionInitialThinkingLevel(piboSession);
|
|
716
|
+
const sessionProfile = profileForSession(profile, piboSession.piSessionId, parentPiSessionId, this.getSubagentDepth(piboSession.id));
|
|
703
717
|
const userSettings = loadPiboUserSettings();
|
|
704
718
|
const telemetryExtension = this.telemetryStore
|
|
705
719
|
? createPiboProviderTelemetryExtension({ store: this.telemetryStore, writer: this.telemetryWriter, session: piboSession, model: activeModel })
|
|
@@ -709,7 +723,7 @@ export class PiboSessionRouter {
|
|
|
709
723
|
persistSession: this.options.persistSession,
|
|
710
724
|
thinkingLevel: initialThinkingLevel ?? this.options.thinkingLevel,
|
|
711
725
|
retryDefaults: resolvePiboSessionRetryDefaults(piboSession.kind, this.options.retryDefaults),
|
|
712
|
-
profile:
|
|
726
|
+
profile: sessionProfile,
|
|
713
727
|
extensionFactories: [
|
|
714
728
|
...(telemetryExtension ? [telemetryExtension] : []),
|
|
715
729
|
...(this.options.extensionFactories ?? []),
|
|
@@ -726,7 +740,7 @@ export class PiboSessionRouter {
|
|
|
726
740
|
getActiveMessage: () => session?.getActiveMessage(),
|
|
727
741
|
},
|
|
728
742
|
});
|
|
729
|
-
const initialFastMode = resolvePiboSessionInitialFastMode(piboSession) ?? selectRequestedFastMode(
|
|
743
|
+
const initialFastMode = resolvePiboSessionInitialFastMode(piboSession) ?? selectRequestedFastMode(sessionProfile, modelDefaults) ?? false;
|
|
730
744
|
session = new RoutedSession(piboSession.id, runtime, this.emitOutput, this.pluginRegistry, this.options.forwardPiEvents ?? false, this.telemetryRecorder
|
|
731
745
|
? (id, event, context) => this.telemetryRecorder?.recordPiEvent(id, event, { session: this.sessionStore.get(id), status: context.status, activeEventId: context.activeEventId })
|
|
732
746
|
: undefined, initialFastMode, (result, event) => this.handleSessionOperation(result, event), (id, opts) => this.killChildSessions(id, opts), (state) => {
|
|
@@ -952,8 +966,8 @@ export class PiboSessionRouter {
|
|
|
952
966
|
};
|
|
953
967
|
}
|
|
954
968
|
assertSubagentDepth(parentPiboSessionId, subagent) {
|
|
955
|
-
const maxDepth = subagent.maxDepth ??
|
|
956
|
-
if (this.getSubagentDepth(parentPiboSessionId)
|
|
969
|
+
const maxDepth = subagent.maxDepth ?? DEFAULT_SUBAGENT_MAX_DEPTH;
|
|
970
|
+
if (hasReachedSubagentMaxDepth(subagent, this.getSubagentDepth(parentPiboSessionId))) {
|
|
957
971
|
throw new Error(`Subagent "${subagent.name}" exceeded max depth ${maxDepth} from Pibo session "${parentPiboSessionId}"`);
|
|
958
972
|
}
|
|
959
973
|
}
|
|
@@ -12,6 +12,29 @@ const URL_COMPARISON_MAX_FIRST_LIVE_LATENCY_DELTA_MS = 250;
|
|
|
12
12
|
const URL_COMPARISON_MAX_FIRST_VISIBLE_LATENCY_DELTA_MS = 300;
|
|
13
13
|
const PROVIDER_MIN_TEXT_PRESERVATION_RATIO = 0.95;
|
|
14
14
|
const PROVIDER_MIN_REASONING_PRESERVATION_RATIO = 0.95;
|
|
15
|
+
const X_ACCEL_BUFFERING_REGRESSION = "SSE X-Accel-Buffering header is not no";
|
|
16
|
+
export function evaluateStreamingSseHeaderRegressions(benchmark, url) {
|
|
17
|
+
if (!benchmark.sse?.requested)
|
|
18
|
+
return [];
|
|
19
|
+
const visibleValue = benchmark.sse.headers?.["x-accel-buffering"]?.trim().toLowerCase();
|
|
20
|
+
if (visibleValue)
|
|
21
|
+
return visibleValue === "no" ? [] : [X_ACCEL_BUFFERING_REGRESSION];
|
|
22
|
+
return isDirectStreamingBenchmarkUrl(url) ? [X_ACCEL_BUFFERING_REGRESSION] : [];
|
|
23
|
+
}
|
|
24
|
+
function isDirectStreamingBenchmarkUrl(value) {
|
|
25
|
+
try {
|
|
26
|
+
const hostname = new URL(value).hostname.toLowerCase();
|
|
27
|
+
return hostname === "localhost"
|
|
28
|
+
|| hostname.endsWith(".localhost")
|
|
29
|
+
|| hostname === "0.0.0.0"
|
|
30
|
+
|| hostname === "::1"
|
|
31
|
+
|| hostname === "[::1]"
|
|
32
|
+
|| /^127(?:\.\d{1,3}){3}$/.test(hostname);
|
|
33
|
+
}
|
|
34
|
+
catch {
|
|
35
|
+
return false;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
15
38
|
export function scoreStreamingBenchmark(benchmark) {
|
|
16
39
|
const debugDelta = benchmark.debug.delta ?? {};
|
|
17
40
|
const textDeltaCount = numberField(debugDelta, "textDeltaCount");
|
|
@@ -645,7 +645,6 @@ function streamingBenchmarkRegressions(result) {
|
|
|
645
645
|
if (result.sse && result.sse.requested) {
|
|
646
646
|
if (!result.sse.installed) failures.push('SSE fetch probe unavailable');
|
|
647
647
|
if (result.sse.status && result.sse.status !== 200) failures.push('SSE fetch status ' + result.sse.status);
|
|
648
|
-
if (result.sse.headers && String(result.sse.headers['x-accel-buffering'] || '').toLowerCase() !== 'no') failures.push('SSE X-Accel-Buffering header is not no');
|
|
649
648
|
if (result.sse.errors && result.sse.errors.length) failures.push('SSE fetch errors: ' + result.sse.errors.slice(0, 2).join('; '));
|
|
650
649
|
if (!traceCatchupRequested && expectedDeltas !== undefined && result.sse.textEventCount < expectedDeltas) failures.push('SSE text events ' + result.sse.textEventCount + ' < fixture deltas ' + expectedDeltas);
|
|
651
650
|
if (!traceCatchupRequested && expectedReasoningDeltas !== undefined && result.sse.reasoningEventCount < expectedReasoningDeltas) failures.push('SSE reasoning events ' + result.sse.reasoningEventCount + ' < fixture reasoning deltas ' + expectedReasoningDeltas);
|
package/dist/debug/web.js
CHANGED
|
@@ -3,7 +3,7 @@ import { listBrowserUseCdpTargets, selectBestChatTarget, formatBrowserUseTargets
|
|
|
3
3
|
import { CdpClient } from "../tools/cdp-client.js";
|
|
4
4
|
import { diffSnapshots, formatSnapshot, formatSnapshotDiff, formatWatch } from "./web-render-analysis.js";
|
|
5
5
|
import { formatStreamingBenchmarkAssertionError, formatStreamingBenchmarkCompactReport, formatStreamingBenchmarkResult, streamingBenchmarkReportRows, } from "./web-streaming-report.js";
|
|
6
|
-
import { applyExpectedStreamingRegressions, attachStreamingProviderTelemetryToBenchmarks, evaluateStreamingLivePipelineRegressions, evaluateStreamingProviderRegressions, readStreamingBenchmarkArtifact, readStreamingBenchmarkRuns, scoreStreamingBenchmark, streamingBenchmarkReportTarget, summarizeStreamingBenchmarkGroup, summarizeStreamingBenchmarkUrlComparison, summarizeStreamingCadence, summarizeStreamingLivePipeline, summarizeStreamingProviderPreservation, } from "./web-streaming-benchmark-analysis.js";
|
|
6
|
+
import { applyExpectedStreamingRegressions, attachStreamingProviderTelemetryToBenchmarks, evaluateStreamingLivePipelineRegressions, evaluateStreamingProviderRegressions, evaluateStreamingSseHeaderRegressions, readStreamingBenchmarkArtifact, readStreamingBenchmarkRuns, scoreStreamingBenchmark, streamingBenchmarkReportTarget, summarizeStreamingBenchmarkGroup, summarizeStreamingBenchmarkUrlComparison, summarizeStreamingCadence, summarizeStreamingLivePipeline, summarizeStreamingProviderPreservation, } from "./web-streaming-benchmark-analysis.js";
|
|
7
7
|
import { collectStreamingProviderTelemetry, collectStreamingProviderTelemetryFromSelectedBrowserSession, collectStreamingProviderTelemetryFromSession, collectStreamingProviderTelemetryFromTurn, } from "./web-streaming-provider-telemetry.js";
|
|
8
8
|
import { buildStreamingBenchmarkExpression, streamingBenchmarkEventSourceProbeScript, streamingBenchmarkFixtureHtml } from "./web-streaming-browser-scripts.js";
|
|
9
9
|
import { buildSnapshotExpression, buildWatchExpression } from "./web-snapshot-browser-scripts.js";
|
|
@@ -12,7 +12,7 @@ import { compactTarget, limitStdout, readBaselineSnapshot, writeArtifact, writeL
|
|
|
12
12
|
import { applyNegativeStreamingProfile, DEFAULT_DEPTH_LIMIT, DEFAULT_EVENT_LIMIT, DEFAULT_NODE_LIMIT, DEFAULT_TEXT_LIMIT, parseDuration, parseFixtureMix, parseFixturePreludeMessages, parseFixtureProfile, parseNegativeProfile, parseOptions, parseRuns, presetScope, resolveScope, resolveStreamingBenchmarkCompareUrl, resolveStreamingBenchmarkHostedCompareUrl } from "./web-options.js";
|
|
13
13
|
export { formatStreamingBenchmarkAssertionSummary, formatStreamingBenchmarkUrlComparison, summarizeStreamingSelectedLiveEventSource } from "./web-streaming-report.js";
|
|
14
14
|
export { resolveStreamingBenchmarkHostedCompareUrlFromValues } from "./web-options.js";
|
|
15
|
-
export { attachStreamingProviderTelemetryToBenchmark, evaluateStreamingBenchmarkAssertion, evaluateStreamingBenchmarkUrlComparisonRegressions, evaluateStreamingLivePipelineRegressions, evaluateStreamingProviderRegressions, summarizeStreamingBenchmarkUrlComparison, summarizeStreamingBenchmarks, summarizeStreamingLivePipeline, summarizeStreamingProviderPreservation } from "./web-streaming-benchmark-analysis.js";
|
|
15
|
+
export { attachStreamingProviderTelemetryToBenchmark, evaluateStreamingBenchmarkAssertion, evaluateStreamingBenchmarkUrlComparisonRegressions, evaluateStreamingLivePipelineRegressions, evaluateStreamingProviderRegressions, evaluateStreamingSseHeaderRegressions, summarizeStreamingBenchmarkUrlComparison, summarizeStreamingBenchmarks, summarizeStreamingLivePipeline, summarizeStreamingProviderPreservation } from "./web-streaming-benchmark-analysis.js";
|
|
16
16
|
export { collectStreamingProviderTelemetryFromSelectedBrowserSession, collectStreamingProviderTelemetryFromSession, collectStreamingProviderTelemetryFromTurn, summarizeStreamingProviderTelemetry } from "./web-streaming-provider-telemetry.js";
|
|
17
17
|
export { formatWatch, inferWatchFlickers } from "./web-render-analysis.js";
|
|
18
18
|
export { analyzeStreamingRenderOrderCapture } from "./web-render-order-analysis.js";
|
|
@@ -485,6 +485,7 @@ async function runStreamingBenchmarkSeries(client, runs, durationMs, options) {
|
|
|
485
485
|
}
|
|
486
486
|
async function runStreamingBenchmark(client, durationMs, options = {}) {
|
|
487
487
|
await client.send("Page.bringToFront").catch(() => undefined);
|
|
488
|
+
const targetUrl = await currentBrowserUrl(client);
|
|
488
489
|
const benchmarkTimeoutMs = durationMs + (options.startBackendFixture ? 20_000 : 10_000);
|
|
489
490
|
const benchmark = await client.evaluateJson(buildStreamingBenchmarkExpression(durationMs, options), benchmarkTimeoutMs);
|
|
490
491
|
const withRenderOrder = { ...benchmark, renderOrder: analyzeStreamingRenderOrderCapture(benchmark.renderOrder) };
|
|
@@ -496,6 +497,7 @@ async function runStreamingBenchmark(client, durationMs, options = {}) {
|
|
|
496
497
|
...withCadence,
|
|
497
498
|
regressions: [
|
|
498
499
|
...withCadence.regressions,
|
|
500
|
+
...evaluateStreamingSseHeaderRegressions(withCadence, targetUrl),
|
|
499
501
|
...(withCadence.renderOrder?.analysis?.regressions ?? []),
|
|
500
502
|
...evaluateStreamingLivePipelineRegressions(withCadence),
|
|
501
503
|
...evaluateStreamingProviderRegressions(withCadence),
|
package/dist/gateway/server.js
CHANGED
|
@@ -330,6 +330,7 @@ export class PiboGatewayServer {
|
|
|
330
330
|
findSessions: (input) => this.requireSessionStore().find(input),
|
|
331
331
|
listSessions: () => this.requireSessionStore().list?.() ?? [],
|
|
332
332
|
getSessionRuntimeStatus: (piboSessionId) => this.requireRouter().getSessionRuntimeStatus(piboSessionId),
|
|
333
|
+
getSessionStatusSnapshot: (piboSessionId) => this.requireRouter().getSessionStatusSnapshot(piboSessionId),
|
|
333
334
|
listSessionRuntimeStatuses: () => this.requireRouter().listSessionRuntimeStatuses(),
|
|
334
335
|
listRuns: (options) => this.requireRouter().listRuns(options),
|
|
335
336
|
snapshotSignalSession: (piboSessionId) => this.requireRouter().snapshotSignalSession(piboSessionId),
|
package/dist/plugins/builtin.js
CHANGED
|
@@ -22,6 +22,7 @@ const LOGIN_PROVIDERS = [
|
|
|
22
22
|
{ id: "openai-codex", name: "OpenAI (ChatGPT Plus/Pro)", authMethods: ["device_code"] },
|
|
23
23
|
{ id: "openai", name: "OpenAI API", authMethods: ["api_key"] },
|
|
24
24
|
{ id: "anthropic", name: "Anthropic", authMethods: ["api_key"] },
|
|
25
|
+
{ id: "qwen-token-plan", name: "Qwen Token Plan", authMethods: ["api_key"] },
|
|
25
26
|
{ id: "kimi-coding", name: "Kimi for Coding", authMethods: ["api_key"] },
|
|
26
27
|
{ id: "google", name: "Google Gemini", authMethods: ["api_key"] },
|
|
27
28
|
{ id: "groq", name: "Groq", authMethods: ["api_key"] },
|
|
@@ -188,14 +189,8 @@ export const piboCorePlugin = definePiboPlugin({
|
|
|
188
189
|
name: "status",
|
|
189
190
|
description: "Return current session status with context usage quota.",
|
|
190
191
|
slashCommands: ["status"],
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
return {
|
|
194
|
-
...context.getStatus(),
|
|
195
|
-
activeModel: context.getActiveModel(),
|
|
196
|
-
contextUsage: context.getContextUsage(),
|
|
197
|
-
...(providerUsage ? { providerUsage } : {}),
|
|
198
|
-
};
|
|
192
|
+
execute(context) {
|
|
193
|
+
return context.getStatusSnapshot();
|
|
199
194
|
},
|
|
200
195
|
});
|
|
201
196
|
api.registerGatewayAction({
|
|
@@ -368,7 +363,7 @@ export const piboCorePlugin = definePiboPlugin({
|
|
|
368
363
|
api.registerGatewayAction({
|
|
369
364
|
name: "model",
|
|
370
365
|
description: "Open the interactive model selector for authenticated providers.",
|
|
371
|
-
slashCommands: ["model"
|
|
366
|
+
slashCommands: ["model"],
|
|
372
367
|
async execute() {
|
|
373
368
|
const catalog = await loadModelCatalog(process.cwd());
|
|
374
369
|
return {
|
|
@@ -8,6 +8,8 @@ export function buildOpenAiCompatConfig(spec, baseModels = []) {
|
|
|
8
8
|
api: OPENAI_COMPLETIONS_API,
|
|
9
9
|
baseUrl: spec.baseUrl,
|
|
10
10
|
reasoning: Boolean(model.reasoning),
|
|
11
|
+
thinkingLevelMap: model.thinkingLevelMap ? { ...model.thinkingLevelMap } : undefined,
|
|
12
|
+
compat: model.compat ? { ...model.compat } : undefined,
|
|
11
13
|
input: [...model.input],
|
|
12
14
|
cost: { ...model.cost },
|
|
13
15
|
contextWindow: model.contextWindow,
|
|
@@ -19,6 +21,8 @@ export function buildOpenAiCompatConfig(spec, baseModels = []) {
|
|
|
19
21
|
api: OPENAI_COMPLETIONS_API,
|
|
20
22
|
baseUrl: spec.baseUrl,
|
|
21
23
|
reasoning: model.reasoning ?? false,
|
|
24
|
+
thinkingLevelMap: model.thinkingLevelMap ? { ...model.thinkingLevelMap } : undefined,
|
|
25
|
+
compat: model.compat ? { ...model.compat } : undefined,
|
|
22
26
|
input: [...model.input],
|
|
23
27
|
cost: { ...model.cost },
|
|
24
28
|
contextWindow: model.contextWindow,
|
|
@@ -30,9 +34,10 @@ export function buildOpenAiCompatConfig(spec, baseModels = []) {
|
|
|
30
34
|
for (const entry of customEntries)
|
|
31
35
|
byId.set(entry.id, entry);
|
|
32
36
|
return {
|
|
37
|
+
name: spec.name,
|
|
33
38
|
baseUrl: spec.baseUrl,
|
|
34
39
|
api: OPENAI_COMPLETIONS_API,
|
|
35
|
-
apiKey: spec.apiKeyEnv
|
|
40
|
+
apiKey: `$${spec.apiKeyEnv}`,
|
|
36
41
|
models: [...byId.values()],
|
|
37
42
|
};
|
|
38
43
|
}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { OPENAI_COMPLETIONS_API, registerOpenAiCompatProvider, resetOpenAiCompatProviderRegistration, unregisterOpenAiCompatProvider, } from "./openai-compat.js";
|
|
2
|
+
export const QWEN_TOKEN_PLAN_PROVIDER_ID = "qwen-token-plan";
|
|
3
|
+
export const QWEN_TOKEN_PLAN_PROVIDER_NAME = "Qwen Token Plan";
|
|
4
|
+
export const QWEN_TOKEN_PLAN_DEFAULT_BASE_URL = "https://token-plan.ap-southeast-1.maas.aliyuncs.com/compatible-mode/v1";
|
|
5
|
+
export const QWEN_TOKEN_PLAN_API_KEY_ENV = "QWEN_TOKEN_PLAN_API_KEY";
|
|
6
|
+
const QWEN_COMPAT = {
|
|
7
|
+
supportsStore: false,
|
|
8
|
+
supportsDeveloperRole: false,
|
|
9
|
+
thinkingFormat: "qwen",
|
|
10
|
+
maxTokensField: "max_tokens",
|
|
11
|
+
};
|
|
12
|
+
function qwenModel(id, name, input) {
|
|
13
|
+
return {
|
|
14
|
+
id,
|
|
15
|
+
name,
|
|
16
|
+
reasoning: true,
|
|
17
|
+
compat: QWEN_COMPAT,
|
|
18
|
+
contextWindow: 1_000_000,
|
|
19
|
+
maxTokens: 65_536,
|
|
20
|
+
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
|
|
21
|
+
input,
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
export const QWEN_TOKEN_PLAN_MODELS = [
|
|
25
|
+
qwenModel("qwen3.7-max", "Qwen3.7 Max", ["text"]),
|
|
26
|
+
qwenModel("qwen3.7-plus", "Qwen3.7 Plus", ["text", "image"]),
|
|
27
|
+
qwenModel("qwen3.6-plus", "Qwen3.6 Plus", ["text", "image"]),
|
|
28
|
+
qwenModel("qwen3.6-flash", "Qwen3.6 Flash", ["text", "image"]),
|
|
29
|
+
];
|
|
30
|
+
function resolveBaseUrl() {
|
|
31
|
+
const envOverride = process.env.PIBO_QWEN_TOKEN_PLAN_BASE_URL;
|
|
32
|
+
return envOverride && envOverride.length > 0
|
|
33
|
+
? envOverride
|
|
34
|
+
: QWEN_TOKEN_PLAN_DEFAULT_BASE_URL;
|
|
35
|
+
}
|
|
36
|
+
function buildQwenTokenPlanSpec() {
|
|
37
|
+
return {
|
|
38
|
+
id: QWEN_TOKEN_PLAN_PROVIDER_ID,
|
|
39
|
+
name: QWEN_TOKEN_PLAN_PROVIDER_NAME,
|
|
40
|
+
baseUrl: resolveBaseUrl(),
|
|
41
|
+
apiKeyEnv: QWEN_TOKEN_PLAN_API_KEY_ENV,
|
|
42
|
+
models: QWEN_TOKEN_PLAN_MODELS,
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
export function isQwenTokenPlanProvider(provider) {
|
|
46
|
+
return provider === QWEN_TOKEN_PLAN_PROVIDER_ID;
|
|
47
|
+
}
|
|
48
|
+
export function findQwenTokenPlanModel(modelRegistry, model) {
|
|
49
|
+
if (!model?.provider || !model.id)
|
|
50
|
+
return undefined;
|
|
51
|
+
if (!isQwenTokenPlanProvider(model.provider))
|
|
52
|
+
return undefined;
|
|
53
|
+
return modelRegistry.find(model.provider, model.id);
|
|
54
|
+
}
|
|
55
|
+
export function registerQwenTokenPlanProvider(modelRegistry) {
|
|
56
|
+
return registerOpenAiCompatProvider(modelRegistry, buildQwenTokenPlanSpec(), { baseModels: [] });
|
|
57
|
+
}
|
|
58
|
+
export function unregisterQwenTokenPlanProvider(modelRegistry) {
|
|
59
|
+
unregisterOpenAiCompatProvider(modelRegistry, QWEN_TOKEN_PLAN_PROVIDER_ID);
|
|
60
|
+
}
|
|
61
|
+
export function resetQwenTokenPlanProviderRegistration() {
|
|
62
|
+
resetOpenAiCompatProviderRegistration();
|
|
63
|
+
}
|
|
64
|
+
export function getDefaultQwenTokenPlanModels() {
|
|
65
|
+
return QWEN_TOKEN_PLAN_MODELS;
|
|
66
|
+
}
|
|
67
|
+
export { OPENAI_COMPLETIONS_API };
|
|
@@ -21,15 +21,15 @@ export function applySingleEventToNodes(nodes, byId, piboSessionId, storedEvent,
|
|
|
21
21
|
return;
|
|
22
22
|
}
|
|
23
23
|
if (payload.type === "assistant_delta") {
|
|
24
|
-
mergeAssistantDeltaEvent(nodes, byId, payload, sessionStatus, storedEvent.createdAt, storedEvent.eventSequence, storedEvent.streamId, storedEvent.streamFrameIndex);
|
|
24
|
+
mergeAssistantDeltaEvent(nodes, byId, payload, sessionStatus, storedEvent.createdAt, storedEvent.eventSequence, storedEvent.streamId, storedEvent.streamFrameIndex, storedEvent.traceSource);
|
|
25
25
|
return;
|
|
26
26
|
}
|
|
27
27
|
if (payload.type === "thinking_delta") {
|
|
28
|
-
mergeThinkingDeltaEvent(nodes, byId, payload, sessionStatus, storedEvent.createdAt, storedEvent.eventSequence, storedEvent.streamId, storedEvent.streamFrameIndex);
|
|
28
|
+
mergeThinkingDeltaEvent(nodes, byId, payload, sessionStatus, storedEvent.createdAt, storedEvent.eventSequence, storedEvent.streamId, storedEvent.streamFrameIndex, storedEvent.traceSource);
|
|
29
29
|
return;
|
|
30
30
|
}
|
|
31
31
|
if (payload.type === "assistant_message") {
|
|
32
|
-
const node = assistantMessageNodeFromEvent(piboSessionId, payload, storedEvent.createdAt, storedEvent.eventSequence, storedEvent.streamId, storedEvent.streamFrameIndex);
|
|
32
|
+
const node = assistantMessageNodeFromEvent(piboSessionId, payload, storedEvent.createdAt, storedEvent.eventSequence, storedEvent.streamId, storedEvent.streamFrameIndex, storedEvent.traceSource);
|
|
33
33
|
const existing = byId.get(node.id) ?? findMatchingContentNode(byId, node);
|
|
34
34
|
if (existing) {
|
|
35
35
|
mergeAssistantMessageEvent(existing, node);
|
|
@@ -39,7 +39,7 @@ export function applySingleEventToNodes(nodes, byId, piboSessionId, storedEvent,
|
|
|
39
39
|
byId.set(node.id, node);
|
|
40
40
|
return;
|
|
41
41
|
}
|
|
42
|
-
const node = traceNodeFromEvent(piboSessionId, payload, childByParent, linkedChildByToolCallId, sessionStatus, storedEvent.createdAt, storedEvent.eventSequence, storedEvent.streamId, storedEvent.streamFrameIndex);
|
|
42
|
+
const node = traceNodeFromEvent(piboSessionId, payload, childByParent, linkedChildByToolCallId, sessionStatus, storedEvent.createdAt, storedEvent.eventSequence, storedEvent.streamId, storedEvent.streamFrameIndex, storedEvent.traceSource);
|
|
43
43
|
if (!node)
|
|
44
44
|
return;
|
|
45
45
|
if (node.type === "user.message" &&
|
|
@@ -117,7 +117,7 @@ export function applySingleEventToNodes(nodes, byId, piboSessionId, storedEvent,
|
|
|
117
117
|
for (const indexed of flattenTraceNodes([node]))
|
|
118
118
|
byId.set(indexed.id, indexed);
|
|
119
119
|
}
|
|
120
|
-
function assistantMessageNodeFromEvent(piboSessionId, event, createdAt, eventSequence, streamId, streamFrameIndex) {
|
|
120
|
+
function assistantMessageNodeFromEvent(piboSessionId, event, createdAt, eventSequence, streamId, streamFrameIndex, traceSource) {
|
|
121
121
|
const eventId = typeof event.eventId === "string" ? event.eventId : undefined;
|
|
122
122
|
const assistantId = assistantEventNodeId(event);
|
|
123
123
|
const id = assistantId ? assistantMessageNodeId(assistantId) : `event:${event.type}:${cryptoSafeId(event)}`;
|
|
@@ -135,7 +135,7 @@ function assistantMessageNodeFromEvent(piboSessionId, event, createdAt, eventSeq
|
|
|
135
135
|
output: event.text,
|
|
136
136
|
source: "event-log",
|
|
137
137
|
stableKey: assistantId ? `assistant:${assistantId}` : eventStableKey(event),
|
|
138
|
-
orderKey: eventTraceNodeOrder(eventSequence, event.type, streamId, streamFrameIndex),
|
|
138
|
+
orderKey: eventTraceNodeOrder(eventSequence, event.type, streamId, streamFrameIndex, traceSource),
|
|
139
139
|
children: [],
|
|
140
140
|
};
|
|
141
141
|
}
|
|
@@ -356,7 +356,7 @@ export function latestTraceStreamId(events, initial) {
|
|
|
356
356
|
return latest;
|
|
357
357
|
}
|
|
358
358
|
// ── event → node helpers ─────────────────────────────────────────
|
|
359
|
-
function traceNodeFromEvent(piboSessionId, event, childByParent, linkedChildByToolCallId, sessionStatus, createdAt, eventSequence, streamId, streamFrameIndex) {
|
|
359
|
+
function traceNodeFromEvent(piboSessionId, event, childByParent, linkedChildByToolCallId, sessionStatus, createdAt, eventSequence, streamId, streamFrameIndex, traceSource) {
|
|
360
360
|
const eventId = "eventId" in event && typeof event.eventId === "string" ? event.eventId : undefined;
|
|
361
361
|
const id = `event:${event.type}:${eventId ?? cryptoSafeId(event)}`;
|
|
362
362
|
const turnParentId = eventId ? messageTurnNodeId(eventId) : undefined;
|
|
@@ -367,7 +367,7 @@ function traceNodeFromEvent(piboSessionId, event, childByParent, linkedChildByTo
|
|
|
367
367
|
startedAt: createdAt,
|
|
368
368
|
source: "event-log",
|
|
369
369
|
stableKey: eventStableKey(event),
|
|
370
|
-
orderKey: eventTraceNodeOrder(eventSequence, event.type, streamId, streamFrameIndex),
|
|
370
|
+
orderKey: eventTraceNodeOrder(eventSequence, event.type, streamId, streamFrameIndex, traceSource),
|
|
371
371
|
children: [],
|
|
372
372
|
};
|
|
373
373
|
switch (event.type) {
|
|
@@ -382,7 +382,7 @@ function traceNodeFromEvent(piboSessionId, event, childByParent, linkedChildByTo
|
|
|
382
382
|
startedAt: createdAt,
|
|
383
383
|
source: "event-log",
|
|
384
384
|
stableKey: eventId ? `run-notification:${eventId}` : id,
|
|
385
|
-
orderKey: eventTraceNodeOrder(eventSequence, event.type, streamId, streamFrameIndex),
|
|
385
|
+
orderKey: eventTraceNodeOrder(eventSequence, event.type, streamId, streamFrameIndex, traceSource),
|
|
386
386
|
notification,
|
|
387
387
|
});
|
|
388
388
|
}
|
|
@@ -555,7 +555,7 @@ function traceNodeFromEvent(piboSessionId, event, childByParent, linkedChildByTo
|
|
|
555
555
|
return undefined;
|
|
556
556
|
}
|
|
557
557
|
}
|
|
558
|
-
function mergeAssistantDeltaEvent(nodes, byId, event, sessionStatus, createdAt, eventSequence, streamId, streamFrameIndex) {
|
|
558
|
+
function mergeAssistantDeltaEvent(nodes, byId, event, sessionStatus, createdAt, eventSequence, streamId, streamFrameIndex, traceSource) {
|
|
559
559
|
if (typeof event.text !== "string" || event.text.length === 0)
|
|
560
560
|
return;
|
|
561
561
|
const assistantId = assistantEventNodeId(event);
|
|
@@ -581,7 +581,7 @@ function mergeAssistantDeltaEvent(nodes, byId, event, sessionStatus, createdAt,
|
|
|
581
581
|
output: event.text,
|
|
582
582
|
source: "event-log",
|
|
583
583
|
stableKey: assistantId ? `assistant:${assistantId}` : id,
|
|
584
|
-
orderKey: eventTraceNodeOrder(eventSequence, event.type, streamId, streamFrameIndex),
|
|
584
|
+
orderKey: eventTraceNodeOrder(eventSequence, event.type, streamId, streamFrameIndex, traceSource),
|
|
585
585
|
children: [],
|
|
586
586
|
};
|
|
587
587
|
nodes.push(node);
|
|
@@ -599,7 +599,7 @@ function mergeAssistantMessageEvent(target, update) {
|
|
|
599
599
|
target.error = update.error ?? target.error;
|
|
600
600
|
target.completedAt = update.completedAt ?? target.completedAt;
|
|
601
601
|
}
|
|
602
|
-
function mergeThinkingDeltaEvent(nodes, byId, event, sessionStatus, createdAt, eventSequence, streamId, streamFrameIndex) {
|
|
602
|
+
function mergeThinkingDeltaEvent(nodes, byId, event, sessionStatus, createdAt, eventSequence, streamId, streamFrameIndex, traceSource) {
|
|
603
603
|
if (typeof event.text !== "string" || event.text.length === 0)
|
|
604
604
|
return;
|
|
605
605
|
const thinkingId = thinkingEventNodeId(event);
|
|
@@ -626,7 +626,7 @@ function mergeThinkingDeltaEvent(nodes, byId, event, sessionStatus, createdAt, e
|
|
|
626
626
|
output: event.text,
|
|
627
627
|
source: "event-log",
|
|
628
628
|
stableKey,
|
|
629
|
-
orderKey: eventTraceNodeOrder(eventSequence, event.type, streamId, streamFrameIndex),
|
|
629
|
+
orderKey: eventTraceNodeOrder(eventSequence, event.type, streamId, streamFrameIndex, traceSource),
|
|
630
630
|
children: [],
|
|
631
631
|
};
|
|
632
632
|
nodes.push(node);
|
|
@@ -806,8 +806,8 @@ function isOpenTranscriptEvent(event) {
|
|
|
806
806
|
event.type === "thinking_delta" ||
|
|
807
807
|
event.type === "thinking_finished");
|
|
808
808
|
}
|
|
809
|
-
function eventTraceNodeOrder(eventSequence, type, streamId, streamFrameIndex) {
|
|
810
|
-
if (
|
|
809
|
+
function eventTraceNodeOrder(eventSequence, type, streamId, streamFrameIndex, traceSource) {
|
|
810
|
+
if (traceSource === "live") {
|
|
811
811
|
return liveTraceOrder(streamId, streamFrameIndex, eventNodeKind(type));
|
|
812
812
|
}
|
|
813
813
|
return eventTraceOrder(eventSequence, eventNodeKind(type));
|
|
@@ -148,6 +148,7 @@ function makeStored(streamEvent, piboSessionId, type, payload, nextSequence, now
|
|
|
148
148
|
eventSequence: sequence,
|
|
149
149
|
streamId: typeof streamEvent.streamId === "number" ? streamEvent.streamId : undefined,
|
|
150
150
|
streamFrameIndex,
|
|
151
|
+
traceSource: "live",
|
|
151
152
|
eventId: typeof payload.eventId === "string" ? payload.eventId : undefined,
|
|
152
153
|
type,
|
|
153
154
|
createdAt: streamEventCreatedAt(streamEvent) ?? now(),
|