@pasko70/pibo 1.16.5 → 2.0.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/auth.js +28 -0
- package/dist/agent-runtime/capabilities.js +221 -0
- package/dist/agent-runtime/context-build.js +313 -0
- package/dist/agent-runtime/contract.js +45 -0
- package/dist/agent-runtime/errors.js +57 -0
- package/dist/agent-runtime/events.js +1 -0
- package/dist/agent-runtime/history.js +1 -0
- package/dist/agent-runtime/profile-validation.js +109 -0
- package/dist/agent-runtime/registry.js +608 -0
- package/dist/agent-runtime/resource-files.js +87 -0
- package/dist/agent-runtime/resource-service.js +635 -0
- package/dist/agent-runtime/resources.js +1 -0
- package/dist/agent-runtime/routed-session.js +931 -0
- package/dist/agent-runtime/testing/contract.js +51 -0
- package/dist/agent-runtime/testing/fake-adapter.js +192 -0
- package/dist/agent-runtime/types.js +3 -0
- package/dist/agent-runtimes/codex-native/adapter.js +905 -0
- package/dist/agent-runtimes/codex-native/auth.js +476 -0
- package/dist/agent-runtimes/codex-native/client.js +734 -0
- package/dist/agent-runtimes/codex-native/config.js +152 -0
- package/dist/agent-runtimes/codex-native/history.js +283 -0
- package/dist/agent-runtimes/codex-native/mcp-stdio-launcher.js +89 -0
- package/dist/agent-runtimes/codex-native/models.js +581 -0
- package/dist/agent-runtimes/codex-native/process.js +459 -0
- package/dist/agent-runtimes/codex-native/protocol-types.js +1 -0
- package/dist/agent-runtimes/codex-native/protocol-version.js +7 -0
- package/dist/agent-runtimes/codex-native/redaction.js +31 -0
- package/dist/agent-runtimes/codex-native/requests.js +378 -0
- package/dist/agent-runtimes/codex-native/resource-delivery.js +445 -0
- package/dist/agent-runtimes/codex-native/thread.js +388 -0
- package/dist/agent-runtimes/codex-native/turn.js +849 -0
- package/dist/agent-runtimes/pi/adapter.js +653 -0
- package/dist/agent-runtimes/pi/auth.js +455 -0
- package/dist/agent-runtimes/pi/history.js +640 -0
- package/dist/agent-runtimes/pi/model-catalog.js +87 -0
- package/dist/agent-runtimes/pi/routed-session.js +1464 -0
- package/dist/agent-runtimes/pi/runtime.js +534 -0
- package/dist/agent-runtimes/pi/tool-compiler.js +69 -0
- package/dist/apps/chat/agent-profiles.js +40 -23
- package/dist/apps/chat/agent-store.js +111 -64
- package/dist/apps/chat/chat-api-routes.js +1 -1
- package/dist/apps/chat/chat-request-normalizers.js +47 -0
- package/dist/apps/chat/data/chat-data-mappers.js +25 -9
- package/dist/apps/chat/data/history-query-service.js +108 -0
- package/dist/apps/chat/data/session-query-service.js +24 -3
- package/dist/apps/chat/data/timeline-query-service.js +3 -3
- package/dist/apps/chat/model-catalog.js +1 -55
- package/dist/apps/chat/provider-auth-actions.js +171 -23
- package/dist/apps/chat/stream.js +12 -0
- package/dist/apps/chat/trace-v2.js +1 -0
- package/dist/apps/chat/trace.js +126 -415
- package/dist/apps/chat/web-app.js +582 -157
- package/dist/apps/chat-ui/assets/{dist-QXwINWYY.js → dist-9v2ZXT6V.js} +1 -1
- package/dist/apps/chat-ui/assets/{dist-CvZNkkOi.js → dist-B1LVAytl.js} +1 -1
- package/dist/apps/chat-ui/assets/{dist-_SP-MjLq.js → dist-C6LPDFXU.js} +1 -1
- package/dist/apps/chat-ui/assets/{dist-Bad4Yz4P.js → dist-DVtXxfHc.js} +1 -1
- package/dist/apps/chat-ui/assets/{dist-xy-zomwl.js → dist-DW4Qrfbd.js} +1 -1
- package/dist/apps/chat-ui/assets/{dist-DI4i80O2.js → dist-DmbsHdMC.js} +1 -1
- package/dist/apps/chat-ui/assets/{dist-D17yAUqp.js → dist-DyvwuSFO.js} +1 -1
- package/dist/apps/chat-ui/assets/{dist-Bc3Vbgjh.js → dist-I26VB0QO.js} +1 -1
- package/dist/apps/chat-ui/assets/{dist-BzqH7w58.js → dist-RtHbJRPV.js} +1 -1
- package/dist/apps/chat-ui/assets/{dist-CMDJ-WZm.js → dist-sZgJkWZb.js} +1 -1
- package/dist/apps/chat-ui/assets/index-BPbNvcZe.css +1 -0
- package/dist/apps/chat-ui/assets/index-CIOf2uL2.js +237 -0
- package/dist/apps/chat-ui/index.html +2 -2
- package/dist/apps/chat-vscode-web/assets/index-1ivRyjFs.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-2.0.0.vsix +0 -0
- package/dist/auth/login-actions.js +5 -251
- package/dist/cli-session/localSessionSource.js +8 -1
- package/dist/core/context-build.js +124 -20
- package/dist/core/default-profile.js +8 -0
- package/dist/core/profiles.js +30 -3
- package/dist/core/routed-session.js +5 -1446
- package/dist/core/runtime.js +5 -561
- package/dist/core/session-router.js +637 -83
- package/dist/data/cli.js +20 -3
- package/dist/data/schema.js +104 -1
- package/dist/data/session-store.js +24 -1
- package/dist/debug/events.js +25 -10
- package/dist/debug/failures.js +23 -3
- package/dist/debug/index.js +24 -6
- package/dist/debug/messages.js +87 -7
- package/dist/debug/persisted-payloads.js +31 -0
- package/dist/debug/pty.js +7 -6
- package/dist/debug/runtime-binding.js +29 -0
- package/dist/debug/session.js +137 -0
- package/dist/debug/summary.js +12 -0
- package/dist/debug/telemetry.js +28 -0
- package/dist/debug/tools.js +12 -2
- package/dist/debug/trace.js +154 -76
- package/dist/gateway/server.js +87 -2
- package/dist/gateway/tool.js +5 -5
- package/dist/index.js +21 -2
- package/dist/loops/tools.js +13 -12
- package/dist/mcp/agent-context.js +13 -4
- package/dist/mcp/client.js +10 -6
- package/dist/mcp/config.js +5 -2
- package/dist/mcp/runtime-session.js +166 -0
- package/dist/plugins/builtin.js +191 -53
- package/dist/plugins/codex-native.js +29 -0
- package/dist/plugins/registry.js +66 -2
- package/dist/runs/tools.js +26 -25
- package/dist/session-ui/terminalRows.js +2 -2
- package/dist/sessions/pibo-data-store.js +125 -16
- package/dist/sessions/runtime-binding.js +107 -0
- package/dist/sessions/sqlite-store.js +239 -18
- package/dist/sessions/store.js +86 -7
- package/dist/shared/trace-engine.js +18 -9
- package/dist/shared/trace-event-projection.js +29 -11
- package/dist/shared/{trace-transcript.js → trace-history.js} +193 -195
- package/dist/shared/trace-order.js +9 -4
- package/dist/shared/trace-page-merge.js +1 -1
- package/dist/signals/projector.js +20 -2
- package/dist/signals/registry.js +11 -0
- package/dist/subagents/tool.js +8 -6
- package/dist/tools/codex-browser.js +20 -19
- package/dist/tools/codex-compat.js +10 -9
- package/dist/tools/codex-image-generation.js +8 -6
- package/dist/tools/contract.js +45 -0
- package/dist/tools/credential-registry.js +182 -0
- package/dist/tools/mcp-bridge.js +511 -0
- package/dist/tools/payload-writer.js +17 -0
- package/dist/tools/runtime/tool.js +10 -9
- package/dist/tools/schema.js +9 -0
- package/dist/tools/session-service.js +193 -0
- package/dist/tools/session-tool-set.js +85 -0
- package/dist/web-annotations/tools.js +17 -16
- package/docs/README.md +11 -0
- package/package.json +3 -2
- package/skills/builtin/pibo-agent-runtime-adapter/SKILL.md +183 -0
- package/skills/builtin/pibo-agent-runtime-adapter/evals/README.md +10 -0
- package/skills/builtin/pibo-agent-runtime-adapter/evals/evals.json +45 -0
- package/skills/builtin/pibo-agent-runtime-adapter/evals/fixtures/orion-full-harness.md +60 -0
- package/skills/builtin/pibo-agent-runtime-adapter/evals/fixtures/relay-partial-harness.md +52 -0
- package/skills/builtin/pibo-agent-runtime-adapter/references/capabilities-and-designer.md +194 -0
- package/skills/builtin/pibo-agent-runtime-adapter/references/history-debug-and-security.md +213 -0
- package/skills/builtin/pibo-agent-runtime-adapter/references/interfaces-and-registration.md +214 -0
- package/skills/builtin/pibo-agent-runtime-adapter/references/lifecycle-bindings-and-events.md +193 -0
- package/skills/builtin/pibo-agent-runtime-adapter/references/portable-delivery-and-native-behavior.md +226 -0
- package/skills/builtin/pibo-agent-runtime-adapter/references/testing-migration-and-validation.md +256 -0
- package/dist/apps/chat-ui/assets/index-C45B0rw7.js +0 -237
- package/dist/apps/chat-ui/assets/index-E0RmuCkY.css +0 -1
- package/dist/apps/chat-vscode-web/assets/index-D-tSsXLG.js +0 -41
- package/dist/apps/vscode-artifacts/pibo-vscode-ext-1.16.5.vsix +0 -0
|
@@ -3,10 +3,75 @@ import { mkdirSync } from "node:fs";
|
|
|
3
3
|
import { dirname, resolve } from "node:path";
|
|
4
4
|
import { piboHomePath } from "../../core/pibo-home.js";
|
|
5
5
|
import { DatabaseSync } from "node:sqlite";
|
|
6
|
-
import { DEFAULT_BUILTIN_TOOL_NAMES } from "../../core/profiles.js";
|
|
6
|
+
import { DEFAULT_AGENT_RUNTIME_INSTANCE_ID, DEFAULT_BUILTIN_TOOL_NAMES } from "../../core/profiles.js";
|
|
7
7
|
import { isPiboThinkingLevel } from "../../core/thinking.js";
|
|
8
8
|
import { findPiPackage } from "../../pi-packages/store.js";
|
|
9
9
|
const CUSTOM_AGENT_NAME_PATTERN = /^[a-z][a-z0-9]*(?:-[a-z0-9]+)*$/;
|
|
10
|
+
export function previewCustomAgentCreate(input, options = {}) {
|
|
11
|
+
const now = options.now ?? new Date().toISOString();
|
|
12
|
+
const id = options.id ?? `agent_${randomUUID()}`;
|
|
13
|
+
return {
|
|
14
|
+
id,
|
|
15
|
+
profileName: input.displayName,
|
|
16
|
+
displayName: input.displayName,
|
|
17
|
+
profileAliases: [],
|
|
18
|
+
description: input.description,
|
|
19
|
+
runtimeInstanceId: sanitizeRuntimeInstanceId(input.runtimeInstanceId),
|
|
20
|
+
runtimeOptions: cloneRuntimeOptions(input.runtimeOptions),
|
|
21
|
+
nativeTools: [...(input.nativeTools ?? [])],
|
|
22
|
+
skills: [...(input.skills ?? [])],
|
|
23
|
+
contextFiles: [...(input.contextFiles ?? [])],
|
|
24
|
+
subagents: sanitizeSubagents(input.subagents ?? []),
|
|
25
|
+
mcpServers: uniqueStrings(input.mcpServers ?? []),
|
|
26
|
+
piPackages: sanitizePiPackages(input.piPackages ?? []),
|
|
27
|
+
mainModel: sanitizeModelProfile(input.mainModel),
|
|
28
|
+
subagentModel: sanitizeModelProfile(input.subagentModel),
|
|
29
|
+
thinkingLevel: sanitizeThinkingLevel(input.thinkingLevel),
|
|
30
|
+
mainThinkingLevel: sanitizeThinkingLevel(input.mainThinkingLevel),
|
|
31
|
+
subagentThinkingLevel: sanitizeThinkingLevel(input.subagentThinkingLevel),
|
|
32
|
+
fast: sanitizeBoolean(input.fast),
|
|
33
|
+
mainFast: sanitizeBoolean(input.mainFast),
|
|
34
|
+
subagentFast: sanitizeBoolean(input.subagentFast),
|
|
35
|
+
builtinTools: input.builtinTools ?? "default",
|
|
36
|
+
builtinToolNames: sanitizeBuiltinToolNames(input.builtinToolNames),
|
|
37
|
+
autoContextFiles: input.autoContextFiles ?? true,
|
|
38
|
+
runControl: input.runControl ?? false,
|
|
39
|
+
goalControl: input.goalControl ?? true,
|
|
40
|
+
createdAt: now,
|
|
41
|
+
updatedAt: now,
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
export function previewCustomAgentUpdate(existing, input, options = {}) {
|
|
45
|
+
const profileName = input.displayName ?? existing.displayName;
|
|
46
|
+
return {
|
|
47
|
+
...existing,
|
|
48
|
+
profileName,
|
|
49
|
+
displayName: input.displayName ?? existing.displayName,
|
|
50
|
+
description: input.description === undefined ? existing.description : input.description,
|
|
51
|
+
runtimeInstanceId: input.runtimeInstanceId === undefined ? existing.runtimeInstanceId : sanitizeRuntimeInstanceId(input.runtimeInstanceId),
|
|
52
|
+
runtimeOptions: input.runtimeOptions === undefined ? existing.runtimeOptions : cloneRuntimeOptions(input.runtimeOptions),
|
|
53
|
+
nativeTools: input.nativeTools ? [...input.nativeTools] : existing.nativeTools,
|
|
54
|
+
skills: input.skills ? [...input.skills] : existing.skills,
|
|
55
|
+
contextFiles: input.contextFiles ? [...input.contextFiles] : existing.contextFiles,
|
|
56
|
+
subagents: input.subagents ? sanitizeSubagents(input.subagents) : existing.subagents,
|
|
57
|
+
mcpServers: input.mcpServers ? uniqueStrings(input.mcpServers) : existing.mcpServers,
|
|
58
|
+
piPackages: input.piPackages ? sanitizePiPackages(input.piPackages) : existing.piPackages,
|
|
59
|
+
mainModel: input.mainModel === undefined ? existing.mainModel : sanitizeModelProfile(input.mainModel),
|
|
60
|
+
subagentModel: input.subagentModel === undefined ? existing.subagentModel : sanitizeModelProfile(input.subagentModel),
|
|
61
|
+
thinkingLevel: input.thinkingLevel === undefined ? existing.thinkingLevel : sanitizeThinkingLevel(input.thinkingLevel),
|
|
62
|
+
mainThinkingLevel: input.mainThinkingLevel === undefined ? existing.mainThinkingLevel : sanitizeThinkingLevel(input.mainThinkingLevel),
|
|
63
|
+
subagentThinkingLevel: input.subagentThinkingLevel === undefined ? existing.subagentThinkingLevel : sanitizeThinkingLevel(input.subagentThinkingLevel),
|
|
64
|
+
fast: input.fast === undefined ? existing.fast : sanitizeBoolean(input.fast),
|
|
65
|
+
mainFast: input.mainFast === undefined ? existing.mainFast : sanitizeBoolean(input.mainFast),
|
|
66
|
+
subagentFast: input.subagentFast === undefined ? existing.subagentFast : sanitizeBoolean(input.subagentFast),
|
|
67
|
+
builtinTools: input.builtinTools ?? existing.builtinTools,
|
|
68
|
+
builtinToolNames: input.builtinToolNames ? sanitizeBuiltinToolNames(input.builtinToolNames) : existing.builtinToolNames,
|
|
69
|
+
autoContextFiles: input.autoContextFiles ?? existing.autoContextFiles,
|
|
70
|
+
runControl: input.runControl ?? existing.runControl,
|
|
71
|
+
goalControl: input.goalControl ?? existing.goalControl,
|
|
72
|
+
updatedAt: options.now ?? new Date().toISOString(),
|
|
73
|
+
};
|
|
74
|
+
}
|
|
10
75
|
export class CustomAgentStore {
|
|
11
76
|
db;
|
|
12
77
|
constructor(path) {
|
|
@@ -24,6 +89,8 @@ export class CustomAgentStore {
|
|
|
24
89
|
profile_name TEXT NOT NULL UNIQUE,
|
|
25
90
|
display_name TEXT NOT NULL,
|
|
26
91
|
description TEXT,
|
|
92
|
+
runtime_instance_id TEXT NOT NULL DEFAULT 'pi',
|
|
93
|
+
runtime_options_json TEXT NOT NULL DEFAULT '{}',
|
|
27
94
|
native_tools_json TEXT NOT NULL,
|
|
28
95
|
skills_json TEXT NOT NULL,
|
|
29
96
|
context_files_json TEXT NOT NULL,
|
|
@@ -53,6 +120,7 @@ export class CustomAgentStore {
|
|
|
53
120
|
this.migrateArchivedAtColumn();
|
|
54
121
|
this.migrateAutoContextFilesColumn();
|
|
55
122
|
this.migrateMcpServersColumn();
|
|
123
|
+
this.migrateRuntimeColumns();
|
|
56
124
|
this.migratePiPackagesColumn();
|
|
57
125
|
this.migrateModelColumns();
|
|
58
126
|
this.migrateThinkingLevelColumn();
|
|
@@ -78,42 +146,12 @@ export class CustomAgentStore {
|
|
|
78
146
|
}
|
|
79
147
|
create(input) {
|
|
80
148
|
this.migrateLegacyProfileNames();
|
|
81
|
-
|
|
82
|
-
const
|
|
83
|
-
const profileName = input.displayName;
|
|
84
|
-
this.requireProfileNameAvailable(profileName);
|
|
85
|
-
const agent = {
|
|
86
|
-
id,
|
|
87
|
-
profileName,
|
|
88
|
-
displayName: input.displayName,
|
|
89
|
-
profileAliases: [],
|
|
90
|
-
description: input.description,
|
|
91
|
-
nativeTools: [...(input.nativeTools ?? [])],
|
|
92
|
-
skills: [...(input.skills ?? [])],
|
|
93
|
-
contextFiles: [...(input.contextFiles ?? [])],
|
|
94
|
-
subagents: sanitizeSubagents(input.subagents ?? []),
|
|
95
|
-
mcpServers: uniqueStrings(input.mcpServers ?? []),
|
|
96
|
-
piPackages: sanitizePiPackages(input.piPackages ?? []),
|
|
97
|
-
mainModel: sanitizeModelProfile(input.mainModel),
|
|
98
|
-
subagentModel: sanitizeModelProfile(input.subagentModel),
|
|
99
|
-
thinkingLevel: sanitizeThinkingLevel(input.thinkingLevel),
|
|
100
|
-
mainThinkingLevel: sanitizeThinkingLevel(input.mainThinkingLevel),
|
|
101
|
-
subagentThinkingLevel: sanitizeThinkingLevel(input.subagentThinkingLevel),
|
|
102
|
-
fast: sanitizeBoolean(input.fast),
|
|
103
|
-
mainFast: sanitizeBoolean(input.mainFast),
|
|
104
|
-
subagentFast: sanitizeBoolean(input.subagentFast),
|
|
105
|
-
builtinTools: input.builtinTools ?? "default",
|
|
106
|
-
builtinToolNames: sanitizeBuiltinToolNames(input.builtinToolNames),
|
|
107
|
-
autoContextFiles: input.autoContextFiles ?? true,
|
|
108
|
-
runControl: input.runControl ?? false,
|
|
109
|
-
goalControl: input.goalControl ?? true,
|
|
110
|
-
createdAt: now,
|
|
111
|
-
updatedAt: now,
|
|
112
|
-
};
|
|
149
|
+
this.requireProfileNameAvailable(input.displayName);
|
|
150
|
+
const agent = previewCustomAgentCreate(input);
|
|
113
151
|
this.insert(agent);
|
|
114
|
-
const created = this.get(id);
|
|
152
|
+
const created = this.get(agent.id);
|
|
115
153
|
if (!created)
|
|
116
|
-
throw new Error(`Failed to create custom agent "${id}"`);
|
|
154
|
+
throw new Error(`Failed to create custom agent "${agent.id}"`);
|
|
117
155
|
return created;
|
|
118
156
|
}
|
|
119
157
|
update(id, input) {
|
|
@@ -123,38 +161,15 @@ export class CustomAgentStore {
|
|
|
123
161
|
return undefined;
|
|
124
162
|
const profileName = input.displayName ?? existing.displayName;
|
|
125
163
|
this.requireProfileNameAvailable(profileName, id);
|
|
126
|
-
const updated =
|
|
127
|
-
...existing,
|
|
128
|
-
profileName,
|
|
129
|
-
displayName: input.displayName ?? existing.displayName,
|
|
130
|
-
description: input.description === undefined ? existing.description : input.description,
|
|
131
|
-
nativeTools: input.nativeTools ? [...input.nativeTools] : existing.nativeTools,
|
|
132
|
-
skills: input.skills ? [...input.skills] : existing.skills,
|
|
133
|
-
contextFiles: input.contextFiles ? [...input.contextFiles] : existing.contextFiles,
|
|
134
|
-
subagents: input.subagents ? sanitizeSubagents(input.subagents) : existing.subagents,
|
|
135
|
-
mcpServers: input.mcpServers ? uniqueStrings(input.mcpServers) : existing.mcpServers,
|
|
136
|
-
piPackages: input.piPackages ? sanitizePiPackages(input.piPackages) : existing.piPackages,
|
|
137
|
-
mainModel: input.mainModel === undefined ? existing.mainModel : sanitizeModelProfile(input.mainModel),
|
|
138
|
-
subagentModel: input.subagentModel === undefined ? existing.subagentModel : sanitizeModelProfile(input.subagentModel),
|
|
139
|
-
thinkingLevel: input.thinkingLevel === undefined ? existing.thinkingLevel : sanitizeThinkingLevel(input.thinkingLevel),
|
|
140
|
-
mainThinkingLevel: input.mainThinkingLevel === undefined ? existing.mainThinkingLevel : sanitizeThinkingLevel(input.mainThinkingLevel),
|
|
141
|
-
subagentThinkingLevel: input.subagentThinkingLevel === undefined ? existing.subagentThinkingLevel : sanitizeThinkingLevel(input.subagentThinkingLevel),
|
|
142
|
-
fast: input.fast === undefined ? existing.fast : sanitizeBoolean(input.fast),
|
|
143
|
-
mainFast: input.mainFast === undefined ? existing.mainFast : sanitizeBoolean(input.mainFast),
|
|
144
|
-
subagentFast: input.subagentFast === undefined ? existing.subagentFast : sanitizeBoolean(input.subagentFast),
|
|
145
|
-
builtinTools: input.builtinTools ?? existing.builtinTools,
|
|
146
|
-
builtinToolNames: input.builtinToolNames ? sanitizeBuiltinToolNames(input.builtinToolNames) : existing.builtinToolNames,
|
|
147
|
-
autoContextFiles: input.autoContextFiles ?? existing.autoContextFiles,
|
|
148
|
-
runControl: input.runControl ?? existing.runControl,
|
|
149
|
-
goalControl: input.goalControl ?? existing.goalControl,
|
|
150
|
-
updatedAt: new Date().toISOString(),
|
|
151
|
-
};
|
|
164
|
+
const updated = previewCustomAgentUpdate(existing, input);
|
|
152
165
|
this.db
|
|
153
166
|
.prepare(`
|
|
154
167
|
UPDATE chat_agents SET
|
|
155
168
|
profile_name = ?,
|
|
156
169
|
display_name = ?,
|
|
157
170
|
description = ?,
|
|
171
|
+
runtime_instance_id = ?,
|
|
172
|
+
runtime_options_json = ?,
|
|
158
173
|
native_tools_json = ?,
|
|
159
174
|
skills_json = ?,
|
|
160
175
|
context_files_json = ?,
|
|
@@ -177,7 +192,7 @@ export class CustomAgentStore {
|
|
|
177
192
|
updated_at = ?
|
|
178
193
|
WHERE id = ?
|
|
179
194
|
`)
|
|
180
|
-
.run(updated.profileName, updated.displayName, updated.description ?? null, JSON.stringify(updated.nativeTools), JSON.stringify(updated.skills), JSON.stringify(updated.contextFiles), JSON.stringify(sanitizeSubagents(updated.subagents)), JSON.stringify(updated.mcpServers), JSON.stringify(updated.piPackages), updated.mainModel ? JSON.stringify(updated.mainModel) : null, updated.subagentModel ? JSON.stringify(updated.subagentModel) : null, updated.thinkingLevel ?? null, updated.mainThinkingLevel ?? null, updated.subagentThinkingLevel ?? null, serializeBoolean(updated.fast), serializeBoolean(updated.mainFast), serializeBoolean(updated.subagentFast), updated.builtinTools, JSON.stringify(updated.builtinToolNames), updated.autoContextFiles ? 1 : 0, updated.runControl ? 1 : 0, updated.goalControl ? 1 : 0, updated.updatedAt, id);
|
|
195
|
+
.run(updated.profileName, updated.displayName, updated.description ?? null, updated.runtimeInstanceId, JSON.stringify(updated.runtimeOptions), JSON.stringify(updated.nativeTools), JSON.stringify(updated.skills), JSON.stringify(updated.contextFiles), JSON.stringify(sanitizeSubagents(updated.subagents)), JSON.stringify(updated.mcpServers), JSON.stringify(updated.piPackages), updated.mainModel ? JSON.stringify(updated.mainModel) : null, updated.subagentModel ? JSON.stringify(updated.subagentModel) : null, updated.thinkingLevel ?? null, updated.mainThinkingLevel ?? null, updated.subagentThinkingLevel ?? null, serializeBoolean(updated.fast), serializeBoolean(updated.mainFast), serializeBoolean(updated.subagentFast), updated.builtinTools, JSON.stringify(updated.builtinToolNames), updated.autoContextFiles ? 1 : 0, updated.runControl ? 1 : 0, updated.goalControl ? 1 : 0, updated.updatedAt, id);
|
|
181
196
|
return this.get(id);
|
|
182
197
|
}
|
|
183
198
|
setArchived(id, archived) {
|
|
@@ -207,6 +222,8 @@ export class CustomAgentStore {
|
|
|
207
222
|
profile_name,
|
|
208
223
|
display_name,
|
|
209
224
|
description,
|
|
225
|
+
runtime_instance_id,
|
|
226
|
+
runtime_options_json,
|
|
210
227
|
native_tools_json,
|
|
211
228
|
skills_json,
|
|
212
229
|
context_files_json,
|
|
@@ -229,9 +246,9 @@ export class CustomAgentStore {
|
|
|
229
246
|
created_at,
|
|
230
247
|
updated_at,
|
|
231
248
|
archived_at
|
|
232
|
-
) VALUES (${Array.from({ length:
|
|
249
|
+
) VALUES (${Array.from({ length: 28 }, () => "?").join(", ")})
|
|
233
250
|
`)
|
|
234
|
-
.run(agent.id, agent.profileName, agent.displayName, agent.description ?? null, JSON.stringify(agent.nativeTools), JSON.stringify(agent.skills), JSON.stringify(agent.contextFiles), JSON.stringify(sanitizeSubagents(agent.subagents)), JSON.stringify(agent.mcpServers), JSON.stringify(agent.piPackages), agent.mainModel ? JSON.stringify(agent.mainModel) : null, agent.subagentModel ? JSON.stringify(agent.subagentModel) : null, agent.thinkingLevel ?? null, agent.mainThinkingLevel ?? null, agent.subagentThinkingLevel ?? null, serializeBoolean(agent.fast), serializeBoolean(agent.mainFast), serializeBoolean(agent.subagentFast), agent.builtinTools, JSON.stringify(agent.builtinToolNames), agent.autoContextFiles ? 1 : 0, agent.runControl ? 1 : 0, agent.goalControl ? 1 : 0, agent.createdAt, agent.updatedAt, agent.archivedAt ?? null);
|
|
251
|
+
.run(agent.id, agent.profileName, agent.displayName, agent.description ?? null, agent.runtimeInstanceId, JSON.stringify(agent.runtimeOptions), JSON.stringify(agent.nativeTools), JSON.stringify(agent.skills), JSON.stringify(agent.contextFiles), JSON.stringify(sanitizeSubagents(agent.subagents)), JSON.stringify(agent.mcpServers), JSON.stringify(agent.piPackages), agent.mainModel ? JSON.stringify(agent.mainModel) : null, agent.subagentModel ? JSON.stringify(agent.subagentModel) : null, agent.thinkingLevel ?? null, agent.mainThinkingLevel ?? null, agent.subagentThinkingLevel ?? null, serializeBoolean(agent.fast), serializeBoolean(agent.mainFast), serializeBoolean(agent.subagentFast), agent.builtinTools, JSON.stringify(agent.builtinToolNames), agent.autoContextFiles ? 1 : 0, agent.runControl ? 1 : 0, agent.goalControl ? 1 : 0, agent.createdAt, agent.updatedAt, agent.archivedAt ?? null);
|
|
235
252
|
}
|
|
236
253
|
requireProfileNameAvailable(profileName, currentId) {
|
|
237
254
|
const row = this.db.prepare("SELECT id FROM chat_agents WHERE profile_name = ?").get(profileName);
|
|
@@ -341,6 +358,15 @@ export class CustomAgentStore {
|
|
|
341
358
|
this.db.prepare("ALTER TABLE chat_agents ADD COLUMN mcp_servers_json TEXT NOT NULL DEFAULT '[]'").run();
|
|
342
359
|
}
|
|
343
360
|
}
|
|
361
|
+
migrateRuntimeColumns() {
|
|
362
|
+
const columns = this.tableColumns();
|
|
363
|
+
if (!columns.has("runtime_instance_id")) {
|
|
364
|
+
this.db.prepare(`ALTER TABLE chat_agents ADD COLUMN runtime_instance_id TEXT NOT NULL DEFAULT '${DEFAULT_AGENT_RUNTIME_INSTANCE_ID}'`).run();
|
|
365
|
+
}
|
|
366
|
+
if (!columns.has("runtime_options_json")) {
|
|
367
|
+
this.db.prepare("ALTER TABLE chat_agents ADD COLUMN runtime_options_json TEXT NOT NULL DEFAULT '{}'").run();
|
|
368
|
+
}
|
|
369
|
+
}
|
|
344
370
|
migratePiPackagesColumn() {
|
|
345
371
|
const columns = new Set(this.db.prepare("PRAGMA table_info(chat_agents)").all().map((column) => column.name));
|
|
346
372
|
if (!columns.has("pi_packages_json")) {
|
|
@@ -536,6 +562,8 @@ function agentFromRow(row, profileAliases) {
|
|
|
536
562
|
displayName: row.display_name,
|
|
537
563
|
profileAliases: profileAliases.filter((alias) => alias !== row.profile_name),
|
|
538
564
|
description: row.description ?? undefined,
|
|
565
|
+
runtimeInstanceId: sanitizeRuntimeInstanceId(row.runtime_instance_id),
|
|
566
|
+
runtimeOptions: parseRuntimeOptions(row.runtime_options_json),
|
|
539
567
|
nativeTools: parseStringArray(row.native_tools_json),
|
|
540
568
|
skills: parseStringArray(row.skills_json),
|
|
541
569
|
contextFiles: parseStringArray(row.context_files_json),
|
|
@@ -572,6 +600,25 @@ function parseStringArray(value) {
|
|
|
572
600
|
function uniqueStrings(value) {
|
|
573
601
|
return [...new Set(value.filter((item) => typeof item === "string" && item.trim()).map((item) => item.trim()))];
|
|
574
602
|
}
|
|
603
|
+
function sanitizeRuntimeInstanceId(value) {
|
|
604
|
+
if (typeof value !== "string" || !value.trim())
|
|
605
|
+
return DEFAULT_AGENT_RUNTIME_INSTANCE_ID;
|
|
606
|
+
return value.trim();
|
|
607
|
+
}
|
|
608
|
+
function cloneRuntimeOptions(value) {
|
|
609
|
+
return structuredClone(value ?? {});
|
|
610
|
+
}
|
|
611
|
+
function parseRuntimeOptions(value) {
|
|
612
|
+
try {
|
|
613
|
+
const parsed = JSON.parse(value);
|
|
614
|
+
return parsed && typeof parsed === "object" && !Array.isArray(parsed)
|
|
615
|
+
? structuredClone(parsed)
|
|
616
|
+
: {};
|
|
617
|
+
}
|
|
618
|
+
catch {
|
|
619
|
+
return {};
|
|
620
|
+
}
|
|
621
|
+
}
|
|
575
622
|
function sanitizePiPackages(value) {
|
|
576
623
|
const packages = uniqueStrings(value);
|
|
577
624
|
for (const pkg of packages) {
|
|
@@ -300,7 +300,7 @@ export function sessionActionResource(pathname) {
|
|
|
300
300
|
if (parts.length !== 2 || !parts[0])
|
|
301
301
|
return undefined;
|
|
302
302
|
const action = parts[1];
|
|
303
|
-
if (action !== "read" && action !== "kill" && action !== "kill-all")
|
|
303
|
+
if (action !== "read" && action !== "kill" && action !== "kill-all" && action !== "runtime-binding")
|
|
304
304
|
return undefined;
|
|
305
305
|
try {
|
|
306
306
|
return { piboSessionId: decodeURIComponent(parts[0]), action };
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { existsSync, statSync } from "node:fs";
|
|
2
2
|
import { isAbsolute, resolve } from "node:path";
|
|
3
3
|
import { savePiboModelDefaults } from "../../core/model-defaults.js";
|
|
4
|
+
import { DEFAULT_AGENT_RUNTIME_INSTANCE_ID } from "../../core/profiles.js";
|
|
4
5
|
import { isPiboThinkingLevel } from "../../core/thinking.js";
|
|
5
6
|
import { PiboWebHttpError } from "../../web/http.js";
|
|
6
7
|
import { listPiPackages } from "../../pi-packages/store.js";
|
|
@@ -127,6 +128,46 @@ export function normalizeAgentDescription(value) {
|
|
|
127
128
|
throw new PiboWebHttpError("Agent description is too long", 400);
|
|
128
129
|
return description;
|
|
129
130
|
}
|
|
131
|
+
export function normalizeAgentRuntimeInstanceId(value) {
|
|
132
|
+
if (value === undefined)
|
|
133
|
+
return DEFAULT_AGENT_RUNTIME_INSTANCE_ID;
|
|
134
|
+
if (typeof value !== "string" || !value.trim()) {
|
|
135
|
+
throw new PiboWebHttpError("runtimeInstanceId must be a non-empty string", 400);
|
|
136
|
+
}
|
|
137
|
+
const instanceId = value.trim();
|
|
138
|
+
if (!/^[a-z][a-z0-9]*(?:[._-][a-z0-9]+)*$/.test(instanceId)) {
|
|
139
|
+
throw new PiboWebHttpError("runtimeInstanceId is invalid", 400);
|
|
140
|
+
}
|
|
141
|
+
return instanceId;
|
|
142
|
+
}
|
|
143
|
+
export function normalizeAgentRuntimeOptions(value) {
|
|
144
|
+
if (value === undefined || value === null)
|
|
145
|
+
return {};
|
|
146
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
147
|
+
throw new PiboWebHttpError("runtimeOptions must be a JSON object", 400);
|
|
148
|
+
}
|
|
149
|
+
return normalizeAgentRuntimeJsonObject(value, "runtimeOptions", 0);
|
|
150
|
+
}
|
|
151
|
+
function normalizeAgentRuntimeJsonObject(value, path, depth) {
|
|
152
|
+
if (depth > 20)
|
|
153
|
+
throw new PiboWebHttpError(`${path} exceeds the maximum nesting depth`, 400);
|
|
154
|
+
const normalized = {};
|
|
155
|
+
for (const [key, item] of Object.entries(value)) {
|
|
156
|
+
normalized[key] = normalizeAgentRuntimeJsonValue(item, `${path}.${key}`, depth + 1);
|
|
157
|
+
}
|
|
158
|
+
return normalized;
|
|
159
|
+
}
|
|
160
|
+
function normalizeAgentRuntimeJsonValue(value, path, depth) {
|
|
161
|
+
if (value === null || typeof value === "string" || typeof value === "boolean")
|
|
162
|
+
return value;
|
|
163
|
+
if (typeof value === "number" && Number.isFinite(value))
|
|
164
|
+
return value;
|
|
165
|
+
if (Array.isArray(value))
|
|
166
|
+
return value.map((item, index) => normalizeAgentRuntimeJsonValue(item, `${path}[${index}]`, depth + 1));
|
|
167
|
+
if (value && typeof value === "object")
|
|
168
|
+
return normalizeAgentRuntimeJsonObject(value, path, depth + 1);
|
|
169
|
+
throw new PiboWebHttpError(`${path} must contain JSON values only`, 400);
|
|
170
|
+
}
|
|
130
171
|
export function normalizeNameArray(value, label) {
|
|
131
172
|
if (value === undefined)
|
|
132
173
|
return [];
|
|
@@ -607,6 +648,8 @@ export function createAgentInput(body) {
|
|
|
607
648
|
return {
|
|
608
649
|
displayName: normalizeAgentDisplayName(body.displayName),
|
|
609
650
|
description: normalizeAgentDescription(body.description),
|
|
651
|
+
runtimeInstanceId: normalizeAgentRuntimeInstanceId(body.runtimeInstanceId),
|
|
652
|
+
runtimeOptions: normalizeAgentRuntimeOptions(body.runtimeOptions),
|
|
610
653
|
nativeTools: normalizeNameArray(body.nativeTools, "nativeTools"),
|
|
611
654
|
skills: normalizeNameArray(body.skills, "skills"),
|
|
612
655
|
contextFiles: normalizeNameArray(body.contextFiles, "contextFiles"),
|
|
@@ -634,6 +677,10 @@ export function createAgentUpdate(body) {
|
|
|
634
677
|
update.displayName = normalizeAgentDisplayName(body.displayName);
|
|
635
678
|
if (body.description !== undefined)
|
|
636
679
|
update.description = normalizeAgentDescription(body.description);
|
|
680
|
+
if (body.runtimeInstanceId !== undefined)
|
|
681
|
+
update.runtimeInstanceId = normalizeAgentRuntimeInstanceId(body.runtimeInstanceId);
|
|
682
|
+
if (body.runtimeOptions !== undefined)
|
|
683
|
+
update.runtimeOptions = normalizeAgentRuntimeOptions(body.runtimeOptions);
|
|
637
684
|
if (body.nativeTools !== undefined)
|
|
638
685
|
update.nativeTools = normalizeNameArray(body.nativeTools, "nativeTools");
|
|
639
686
|
if (body.skills !== undefined)
|
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
import { normalizeSessionErrorDetails } from "../../../core/session-errors.js";
|
|
2
2
|
import { roomWorkspaceFromMetadata } from "../types/rooms.js";
|
|
3
|
-
export function storedPiboEventFromV2Row(row) {
|
|
3
|
+
export function storedPiboEventFromV2Row(row, payloadStore) {
|
|
4
4
|
const attributes = parseJsonObject(row.attributes_json);
|
|
5
|
-
const payload = outputPayloadFromV2Row(row, attributes);
|
|
5
|
+
const payload = outputPayloadFromV2Row(row, attributes, readPersistedPayload(row, payloadStore));
|
|
6
6
|
if (!payload)
|
|
7
7
|
return undefined;
|
|
8
8
|
return { id: String(row.stream_id), piboSessionId: row.session_id ?? undefined, eventSequence: row.session_sequence ?? undefined, eventId: row.event_id ?? undefined, streamId: row.stream_id, type: row.type, createdAt: row.created_at, payload };
|
|
9
9
|
}
|
|
10
|
-
export function storedChatEventFromV2Row(row) {
|
|
10
|
+
export function storedChatEventFromV2Row(row, payloadStore) {
|
|
11
11
|
const attributes = parseJsonObject(row.attributes_json);
|
|
12
|
-
return { streamId: row.stream_id, roomId: row.room_id ?? undefined, piboSessionId: row.session_id ?? undefined, eventId: row.event_id ?? `evt_${row.stream_id}`, eventType: row.type, actorType: actorTypeValue(row.actor_type), actorId: row.actor_id ?? undefined, clientTxnId: typeof attributes.clientTxnId === "string" ? attributes.clientTxnId : undefined, createdAt: row.created_at, retentionClass: retentionClassValue(row.retention_class), payload: (outputPayloadFromV2Row(row, attributes) ?? null) };
|
|
12
|
+
return { streamId: row.stream_id, roomId: row.room_id ?? undefined, piboSessionId: row.session_id ?? undefined, eventId: row.event_id ?? `evt_${row.stream_id}`, eventType: row.type, actorType: actorTypeValue(row.actor_type), actorId: row.actor_id ?? undefined, clientTxnId: typeof attributes.clientTxnId === "string" ? attributes.clientTxnId : undefined, createdAt: row.created_at, retentionClass: retentionClassValue(row.retention_class), payload: (outputPayloadFromV2Row(row, attributes, readPersistedPayload(row, payloadStore)) ?? null) };
|
|
13
13
|
}
|
|
14
|
-
function outputPayloadFromV2Row(row, attributes) {
|
|
15
|
-
const inlinePayload = attributes.inlinePayload;
|
|
14
|
+
function outputPayloadFromV2Row(row, attributes, persistedPayload) {
|
|
15
|
+
const inlinePayload = attributes.inlinePayload ?? persistedPayload;
|
|
16
16
|
if (inlinePayload && typeof inlinePayload === "object" && !Array.isArray(inlinePayload) && typeof inlinePayload.type === "string")
|
|
17
17
|
return inlinePayload;
|
|
18
18
|
const piboSessionId = row.session_id;
|
|
@@ -25,7 +25,7 @@ function outputPayloadFromV2Row(row, attributes) {
|
|
|
25
25
|
type: row.type,
|
|
26
26
|
assistantIndex: numberAttribute(attributes, "assistantIndex"),
|
|
27
27
|
contentIndex: numberAttribute(attributes, "contentIndex"),
|
|
28
|
-
text: row.preview_text ?? "",
|
|
28
|
+
text: typeof inlinePayload === "string" ? inlinePayload : row.preview_text ?? "",
|
|
29
29
|
});
|
|
30
30
|
}
|
|
31
31
|
if (row.type === "message_queued")
|
|
@@ -42,7 +42,7 @@ function outputPayloadFromV2Row(row, attributes) {
|
|
|
42
42
|
type: row.type,
|
|
43
43
|
thinkingIndex: numberAttribute(attributes, "thinkingIndex"),
|
|
44
44
|
contentIndex: numberAttribute(attributes, "contentIndex"),
|
|
45
|
-
...(row.type === "thinking_started" ? {} : { text: row.preview_text ?? "" }),
|
|
45
|
+
...(row.type === "thinking_started" ? {} : { text: typeof inlinePayload === "string" ? inlinePayload : row.preview_text ?? "" }),
|
|
46
46
|
});
|
|
47
47
|
}
|
|
48
48
|
if (row.type === "tool_call")
|
|
@@ -71,7 +71,22 @@ function outputPayloadFromV2Row(row, attributes) {
|
|
|
71
71
|
return { type: "user.message.accepted", piboSessionId, roomId: row.room_id ?? undefined, text: stringAttribute(attributes, "inlineText") ?? row.preview_text ?? "", clientTxnId: stringAttribute(attributes, "clientTxnId") };
|
|
72
72
|
return { ...base, type: row.type };
|
|
73
73
|
}
|
|
74
|
-
|
|
74
|
+
function readPersistedPayload(row, payloadStore) {
|
|
75
|
+
if (!row.payload_ref || !payloadStore)
|
|
76
|
+
return undefined;
|
|
77
|
+
try {
|
|
78
|
+
const metadata = payloadStore.getPayload(row.payload_ref);
|
|
79
|
+
if (!metadata)
|
|
80
|
+
return undefined;
|
|
81
|
+
return metadata.contentType.includes("json")
|
|
82
|
+
? payloadStore.readPayloadJson(row.payload_ref)
|
|
83
|
+
: payloadStore.readPayloadText(row.payload_ref);
|
|
84
|
+
}
|
|
85
|
+
catch {
|
|
86
|
+
return undefined;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
export function sessionFromRow(row) { return { piboSessionId: row.id, piSessionId: row.pi_session_id ?? "", runtimeInstanceId: row.runtime_instance_id ?? undefined, runtimeAdapterId: row.runtime_adapter_id ?? undefined, runtimeBindingState: isRuntimeBindingState(row.binding_state) ? row.binding_state : undefined, nativeSessionId: row.native_session_id ?? undefined, parentId: row.parent_id ?? undefined, profile: row.profile, channel: row.channel, kind: row.kind, createdAt: row.created_at, updatedAt: row.updated_at, lastActivityAt: row.last_activity_at, status: row.status === "running" || row.status === "error" ? row.status : "idle" }; }
|
|
75
90
|
export function roomFromRow(row) { const metadata = parseJsonObject(row.metadata_json); return { id: row.id, name: row.name, topic: row.topic ?? undefined, workspace: row.workspace ?? roomWorkspaceFromMetadata(metadata), type: row.type, parentRoomId: row.parent_room_id ?? undefined, createdAt: row.created_at, updatedAt: row.updated_at, retentionPolicyId: row.retention_policy_id ?? undefined, metadata }; }
|
|
76
91
|
export function parseJsonObject(value) { try {
|
|
77
92
|
const parsed = JSON.parse(value);
|
|
@@ -92,5 +107,6 @@ export function previewForPayload(payload) { if (typeof payload === "object" &&
|
|
|
92
107
|
export function statusFromOutputEvent(event) { if (event.type === "session_error")
|
|
93
108
|
return "error"; if (event.type === "message_finished")
|
|
94
109
|
return "idle"; return "running"; }
|
|
110
|
+
function isRuntimeBindingState(value) { return value === "unbound" || value === "bound" || value === "missing" || value === "error"; }
|
|
95
111
|
function actorTypeValue(value) { return value === "user" || value === "assistant" || value === "system" || value === "agent" ? value : undefined; }
|
|
96
112
|
function retentionClassValue(value) { return value === "live_delta" || value === "chat_message" || value === "audit_event" ? value : "trace_event"; }
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
export class ChatHistoryQueryService {
|
|
2
|
+
store;
|
|
3
|
+
constructor(store) {
|
|
4
|
+
this.store = store;
|
|
5
|
+
}
|
|
6
|
+
listProductHistoryEntries(input) {
|
|
7
|
+
const limit = Math.max(1, Math.min(input.limit ?? 200, 1000));
|
|
8
|
+
const clauses = ["m.session_id = ?", "m.role IN ('user', 'assistant', 'system')"];
|
|
9
|
+
const values = [input.piboSessionId];
|
|
10
|
+
if (input.beforeSequence !== undefined) {
|
|
11
|
+
clauses.push("COALESCE(e.session_sequence, m.sequence) < ?");
|
|
12
|
+
values.push(input.beforeSequence);
|
|
13
|
+
}
|
|
14
|
+
const rows = this.store.db.prepare(`
|
|
15
|
+
SELECT m.*, e.session_sequence AS event_sequence
|
|
16
|
+
FROM chat_messages m
|
|
17
|
+
LEFT JOIN event_log e ON e.stream_id = m.source_stream_id
|
|
18
|
+
WHERE ${clauses.join(" AND ")}
|
|
19
|
+
ORDER BY m.sequence DESC
|
|
20
|
+
LIMIT ?
|
|
21
|
+
`).all(...values, limit);
|
|
22
|
+
return rows.reverse().flatMap((row) => {
|
|
23
|
+
const role = historyRole(row.role);
|
|
24
|
+
if (!role)
|
|
25
|
+
return [];
|
|
26
|
+
const attributes = parseObject(row.attributes_json);
|
|
27
|
+
const text = this.readMessageText(row, attributes);
|
|
28
|
+
return [{
|
|
29
|
+
id: `product:${row.id}`,
|
|
30
|
+
type: "message",
|
|
31
|
+
source: "product",
|
|
32
|
+
createdAt: row.created_at,
|
|
33
|
+
sequence: row.event_sequence ?? row.sequence,
|
|
34
|
+
turnId: row.turn_id ?? undefined,
|
|
35
|
+
role,
|
|
36
|
+
content: text,
|
|
37
|
+
assistantIndex: numberValue(attributes.assistantIndex),
|
|
38
|
+
contentIndex: numberValue(attributes.contentIndex),
|
|
39
|
+
status: historyStatus(row.status),
|
|
40
|
+
metadata: compactObject({
|
|
41
|
+
messageId: row.id,
|
|
42
|
+
sourceStreamId: row.source_stream_id ?? undefined,
|
|
43
|
+
completedAt: row.completed_at ?? undefined,
|
|
44
|
+
payloadRef: row.content_payload_ref ?? undefined,
|
|
45
|
+
}),
|
|
46
|
+
}];
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
getProductHistoryCoverage(piboSessionId) {
|
|
50
|
+
const row = this.store.db.prepare(`
|
|
51
|
+
SELECT
|
|
52
|
+
COUNT(*) AS message_count,
|
|
53
|
+
MIN(e.session_sequence) AS first_event_sequence,
|
|
54
|
+
MAX(e.session_sequence) AS last_event_sequence,
|
|
55
|
+
MIN(m.created_at) AS first_created_at,
|
|
56
|
+
MAX(m.created_at) AS last_created_at
|
|
57
|
+
FROM chat_messages m
|
|
58
|
+
LEFT JOIN event_log e ON e.stream_id = m.source_stream_id
|
|
59
|
+
WHERE m.session_id = ?
|
|
60
|
+
`).get(piboSessionId);
|
|
61
|
+
return {
|
|
62
|
+
messageCount: Number(row.message_count ?? 0),
|
|
63
|
+
firstEventSequence: row.first_event_sequence ?? undefined,
|
|
64
|
+
lastEventSequence: row.last_event_sequence ?? undefined,
|
|
65
|
+
firstCreatedAt: row.first_created_at ?? undefined,
|
|
66
|
+
lastCreatedAt: row.last_created_at ?? undefined,
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
readMessageText(row, attributes) {
|
|
70
|
+
if (row.content_payload_ref) {
|
|
71
|
+
try {
|
|
72
|
+
return this.store.payloads.readPayloadText(row.content_payload_ref);
|
|
73
|
+
}
|
|
74
|
+
catch {
|
|
75
|
+
// Retain the durable preview if the external payload was removed or corrupted.
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
if (typeof attributes.inlineText === "string")
|
|
79
|
+
return attributes.inlineText;
|
|
80
|
+
return row.content_preview ?? "";
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
function historyRole(role) {
|
|
84
|
+
return role === "user" || role === "assistant" || role === "system" ? role : undefined;
|
|
85
|
+
}
|
|
86
|
+
function historyStatus(status) {
|
|
87
|
+
if (status === "running" || status === "streaming" || status === "in_progress")
|
|
88
|
+
return "running";
|
|
89
|
+
if (status === "error" || status === "failed")
|
|
90
|
+
return "error";
|
|
91
|
+
return "complete";
|
|
92
|
+
}
|
|
93
|
+
function parseObject(value) {
|
|
94
|
+
try {
|
|
95
|
+
const parsed = JSON.parse(value);
|
|
96
|
+
return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : {};
|
|
97
|
+
}
|
|
98
|
+
catch {
|
|
99
|
+
return {};
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
function numberValue(value) {
|
|
103
|
+
return typeof value === "number" && Number.isFinite(value) ? value : undefined;
|
|
104
|
+
}
|
|
105
|
+
function compactObject(value) {
|
|
106
|
+
const compact = Object.fromEntries(Object.entries(value).filter(([, item]) => item !== undefined));
|
|
107
|
+
return Object.keys(compact).length ? compact : undefined;
|
|
108
|
+
}
|
|
@@ -30,11 +30,22 @@ export class ChatSessionQueryService {
|
|
|
30
30
|
return undefined;
|
|
31
31
|
}
|
|
32
32
|
listSessions() {
|
|
33
|
-
const rows = this.store.db.prepare(
|
|
33
|
+
const rows = this.store.db.prepare(`
|
|
34
|
+
SELECT s.*, b.runtime_instance_id, b.runtime_adapter_id, b.native_session_id, b.binding_state
|
|
35
|
+
FROM sessions s
|
|
36
|
+
LEFT JOIN session_runtime_bindings b ON b.pibo_session_id = s.id
|
|
37
|
+
WHERE s.deleted_at IS NULL
|
|
38
|
+
ORDER BY s.last_activity_at DESC, s.created_at DESC
|
|
39
|
+
`).all();
|
|
34
40
|
return rows.map(sessionFromRow);
|
|
35
41
|
}
|
|
36
42
|
getSession(piboSessionId) {
|
|
37
|
-
const row = this.store.db.prepare(
|
|
43
|
+
const row = this.store.db.prepare(`
|
|
44
|
+
SELECT s.*, b.runtime_instance_id, b.runtime_adapter_id, b.native_session_id, b.binding_state
|
|
45
|
+
FROM sessions s
|
|
46
|
+
LEFT JOIN session_runtime_bindings b ON b.pibo_session_id = s.id
|
|
47
|
+
WHERE s.id = ? AND s.deleted_at IS NULL
|
|
48
|
+
`).get(piboSessionId);
|
|
38
49
|
return row ? sessionFromRow(row) : undefined;
|
|
39
50
|
}
|
|
40
51
|
hasSessionActivity(piboSessionId) {
|
|
@@ -76,17 +87,27 @@ export class ChatSessionQueryService {
|
|
|
76
87
|
s.created_at,
|
|
77
88
|
s.updated_at,
|
|
78
89
|
s.last_activity_at,
|
|
90
|
+
b.runtime_instance_id,
|
|
91
|
+
b.runtime_adapter_id,
|
|
92
|
+
b.native_session_id,
|
|
93
|
+
b.binding_state,
|
|
79
94
|
n.status AS navigation_status,
|
|
80
95
|
n.title AS navigation_title,
|
|
81
96
|
n.sort_key AS navigation_sort_key,
|
|
82
97
|
n.updated_at AS navigation_updated_at
|
|
83
98
|
FROM sessions s
|
|
99
|
+
LEFT JOIN session_runtime_bindings b ON b.pibo_session_id = s.id
|
|
84
100
|
LEFT JOIN session_navigation n ON n.session_id = s.id
|
|
85
101
|
WHERE s.id = ? AND s.deleted_at IS NULL
|
|
86
102
|
`).get(session.id);
|
|
87
103
|
if (!row)
|
|
88
104
|
return false;
|
|
89
|
-
|
|
105
|
+
const binding = session.runtimeBinding;
|
|
106
|
+
return row.pi_session_id === (session.piSessionId || null)
|
|
107
|
+
&& row.runtime_instance_id === (binding?.runtimeInstanceId ?? "pi")
|
|
108
|
+
&& row.runtime_adapter_id === (binding?.adapterId ?? "pi")
|
|
109
|
+
&& row.native_session_id === (binding?.nativeSessionId ?? (session.piSessionId || null))
|
|
110
|
+
&& row.binding_state === (binding?.state ?? (session.piSessionId ? "bound" : "unbound"))
|
|
90
111
|
&& row.room_id === roomId
|
|
91
112
|
&& row.root_session_id === rootSessionId(session)
|
|
92
113
|
&& row.parent_id === (session.parentId ?? null)
|
|
@@ -23,7 +23,7 @@ export class ChatTimelineQueryService {
|
|
|
23
23
|
const where = clauses.length ? `WHERE ${clauses.join(" AND ")}` : "";
|
|
24
24
|
const limit = Math.max(1, Math.min(input.limit ?? 1000, 5000));
|
|
25
25
|
const rows = this.store.db.prepare(`SELECT * FROM event_log ${where} ORDER BY stream_id ASC LIMIT ?`).all(...values, limit);
|
|
26
|
-
return rows.map(storedChatEventFromV2Row);
|
|
26
|
+
return rows.map((row) => storedChatEventFromV2Row(row, this.store.payloads));
|
|
27
27
|
}
|
|
28
28
|
listSessionEvents(piboSessionId, limit = 1000) {
|
|
29
29
|
return this.listTraceEvents({ piboSessionId, limit, includeLive: true });
|
|
@@ -38,7 +38,7 @@ export class ChatTimelineQueryService {
|
|
|
38
38
|
AND type IN ('message_queued', 'message_steered', 'message_started', 'message_finished', 'session_error', 'thinking_finished', 'assistant_message')
|
|
39
39
|
ORDER BY session_sequence ASC, stream_id ASC
|
|
40
40
|
`).all(piboSessionId);
|
|
41
|
-
const events = rows.map(storedPiboEventFromV2Row).filter((event) => event !== undefined);
|
|
41
|
+
const events = rows.map((row) => storedPiboEventFromV2Row(row, this.store.payloads)).filter((event) => event !== undefined);
|
|
42
42
|
return messageTurnTimingsFromEvents(events);
|
|
43
43
|
}
|
|
44
44
|
listTraceEvents(input) {
|
|
@@ -68,7 +68,7 @@ export class ChatTimelineQueryService {
|
|
|
68
68
|
)
|
|
69
69
|
ORDER BY session_sequence ASC, stream_id ASC
|
|
70
70
|
`).all(...values, limit);
|
|
71
|
-
return rows.map(storedPiboEventFromV2Row).filter((event) => event !== undefined);
|
|
71
|
+
return rows.map((row) => storedPiboEventFromV2Row(row, this.store.payloads)).filter((event) => event !== undefined);
|
|
72
72
|
}
|
|
73
73
|
countEventsByType(input = {}) {
|
|
74
74
|
const clauses = [];
|