@happyvertical/smrt-chat 0.55.9 → 0.55.11
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/AGENTS.md +25 -14
- package/README.md +12 -0
- package/agents/dev-workbench.md +69 -0
- package/agents/helper-preferences.md +65 -0
- package/agents/overview-tools.md +172 -0
- package/agents/token-streaming.md +3 -2
- package/dist/chunks/{ChatService-C9UxuJaw.js → ChatService-CFaaDHyU.js} +2 -2
- package/dist/chunks/{ChatService-C9UxuJaw.js.map → ChatService-CFaaDHyU.js.map} +1 -1
- package/dist/chunks/chat-stream-n-7AqsgF.js +2027 -0
- package/dist/chunks/chat-stream-n-7AqsgF.js.map +1 -0
- package/dist/dev-assistant-transport.d.ts +5 -0
- package/dist/dev-assistant-transport.d.ts.map +1 -0
- package/dist/dev-character-persistence-client.d.ts +24 -0
- package/dist/dev-character-persistence-client.d.ts.map +1 -0
- package/dist/dev-helper-client.d.ts +4 -0
- package/dist/dev-helper-client.d.ts.map +1 -0
- package/dist/dev-helper-server.d.ts +18 -0
- package/dist/dev-helper-server.d.ts.map +1 -0
- package/dist/helper-preferences-service.d.ts +22 -0
- package/dist/helper-preferences-service.d.ts.map +1 -0
- package/dist/helper-preferences.d.ts +84 -0
- package/dist/helper-preferences.d.ts.map +1 -0
- package/dist/helper-preferences.js +32 -0
- package/dist/helper-preferences.js.map +1 -0
- package/dist/helper-profile-store.d.ts +27 -0
- package/dist/helper-profile-store.d.ts.map +1 -0
- package/dist/index.d.ts +5 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +683 -5
- package/dist/index.js.map +1 -1
- package/dist/internal/agent-runtime.js +1 -1
- package/dist/manifest.json +122 -3
- package/dist/overview-tools.d.ts +221 -0
- package/dist/overview-tools.d.ts.map +1 -0
- package/dist/playground.d.ts +1 -1
- package/dist/playground.d.ts.map +1 -1
- package/dist/playground.js +99 -88
- package/dist/playground.js.map +1 -1
- package/dist/recipes.d.ts +81 -0
- package/dist/recipes.d.ts.map +1 -1
- package/dist/routes/api/dev-character-conversation/protocol.d.ts +33 -0
- package/dist/routes/api/dev-character-conversation/protocol.d.ts.map +1 -0
- package/dist/routes/api/dev-character-persistence/config.d.ts +24 -0
- package/dist/routes/api/dev-character-persistence/config.d.ts.map +1 -0
- package/dist/scripts/provision-dev-character-persistence.d.ts +3 -0
- package/dist/scripts/provision-dev-character-persistence.d.ts.map +1 -0
- package/dist/smrt-knowledge.json +144 -11
- package/dist/svelte/components/assistant/AssistantDock.svelte +58 -2
- package/dist/svelte/components/assistant/AssistantDock.svelte.d.ts +9 -0
- package/dist/svelte/components/assistant/AssistantDock.svelte.d.ts.map +1 -1
- package/dist/svelte/components/assistant/FloatingAssistant.svelte +309 -0
- package/dist/svelte/components/assistant/FloatingAssistant.svelte.d.ts +27 -0
- package/dist/svelte/components/assistant/FloatingAssistant.svelte.d.ts.map +1 -0
- package/dist/svelte/components/assistant/captions/CaptionOverlay.svelte +105 -0
- package/dist/svelte/components/assistant/captions/CaptionOverlay.svelte.d.ts +11 -0
- package/dist/svelte/components/assistant/captions/CaptionOverlay.svelte.d.ts.map +1 -0
- package/dist/svelte/components/assistant/captions/HeardCaptions.svelte +65 -0
- package/dist/svelte/components/assistant/captions/HeardCaptions.svelte.d.ts +19 -0
- package/dist/svelte/components/assistant/captions/HeardCaptions.svelte.d.ts.map +1 -0
- package/dist/svelte/components/assistant/captions/SpokenCaptions.svelte +65 -0
- package/dist/svelte/components/assistant/captions/SpokenCaptions.svelte.d.ts +21 -0
- package/dist/svelte/components/assistant/captions/SpokenCaptions.svelte.d.ts.map +1 -0
- package/dist/svelte/components/assistant/captions/caption-overlay-context.d.ts +3 -0
- package/dist/svelte/components/assistant/captions/caption-overlay-context.d.ts.map +1 -0
- package/dist/svelte/components/assistant/captions/caption-overlay-context.js +2 -0
- package/dist/svelte/components/assistant/captions/caption-state.svelte.d.ts +71 -0
- package/dist/svelte/components/assistant/captions/caption-state.svelte.d.ts.map +1 -0
- package/dist/svelte/components/assistant/captions/caption-state.svelte.js +225 -0
- package/dist/svelte/components/assistant/create-assistant-dock-controller.svelte.d.ts.map +1 -1
- package/dist/svelte/components/assistant/create-assistant-dock-controller.svelte.js +3 -1
- package/dist/svelte/components/helper/HelperControlPanel.svelte +401 -0
- package/dist/svelte/components/helper/HelperControlPanel.svelte.d.ts +23 -0
- package/dist/svelte/components/helper/HelperControlPanel.svelte.d.ts.map +1 -0
- package/dist/svelte/components/helper/registry.d.ts +53 -0
- package/dist/svelte/components/helper/registry.d.ts.map +1 -0
- package/dist/svelte/components/helper/registry.js +100 -0
- package/dist/svelte/i18n.d.ts +14 -0
- package/dist/svelte/i18n.d.ts.map +1 -1
- package/dist/svelte/i18n.js +17 -0
- package/dist/svelte/i18n.messages.d.ts +32 -0
- package/dist/svelte/i18n.messages.d.ts.map +1 -1
- package/dist/svelte/i18n.messages.js +33 -0
- package/dist/svelte/index.d.ts +7 -0
- package/dist/svelte/index.d.ts.map +1 -1
- package/dist/svelte/index.js +15 -5
- package/dist/svelte/playground.d.ts +94 -0
- package/dist/svelte/playground.d.ts.map +1 -1
- package/dist/svelte/playground.js +16 -5
- package/dist/sveltekit.js +2 -2
- package/package.json +27 -17
- package/dist/chunks/chat-stream-BBk_5_Ph.js +0 -2027
- package/dist/chunks/chat-stream-BBk_5_Ph.js.map +0 -1
package/dist/index.js
CHANGED
|
@@ -1,12 +1,14 @@
|
|
|
1
|
-
import { c as ChatThread, d as ChatParticipant, f as ChatMessage, i as clientRequestMessageId, l as ChatRoom, n as ChatService, o as VoiceSessionCollection, p as AgentSession, s as VoiceSession, t as ChatClientRequestConflictError, u as ChatReaction } from "./chunks/ChatService-
|
|
2
|
-
import { A as MAX_CLIENT_TOOLS, B as RUNTIME_REPORT_DEFINE_FUNCTION_NAME, C as SESSION_CONTINUATIONS_FIELD, D as runAssistantTurn, E as createSessionContinuationStore, F as classifyToolError, G as RUNTIME_REPORT_RUN_TOOL_SLUG, H as RUNTIME_REPORT_LIST_FUNCTION_NAME, I as invokeManifestTool, J as createRuntimeReportTools, K as RUNTIME_REPORT_SOURCES_FUNCTION_NAME, L as manifestToolToAITool, M as MAX_CLIENT_TOOL_SCHEMA_BYTES, N as appendClientToolResults, O as CLIENT_TOOL_RESULT_GUIDANCE, P as buildManifestToolCatalog, R as runToolLoop, S as DEFAULT_CONTINUATION_TTL_MS, T as createMemoryContinuationStore, U as RUNTIME_REPORT_LIST_TOOL_SLUG, V as RUNTIME_REPORT_DEFINE_TOOL_SLUG, W as RUNTIME_REPORT_RUN_FUNCTION_NAME, _ as runPersonaConversationTurn, a as MAX_CHAT_STREAM_CONTENT_LENGTH, b as CONTINUATION_CLAIM_TTL_MS, c as encodeChatStreamEvent, d as conversationPersonaFromAgentPersona, f as conversationPersonaFromResolved, g as resolveConversationInstructions, h as recallPersonaMemory, i as DEFAULT_CHAT_STREAM_HEARTBEAT_MS, j as MAX_CLIENT_TOOL_RESULT_CHARS, k as DEFAULT_MAX_STEPS, l as runChatConversationStream, m as principalBindingFor, n as ChatStreamError, o as MAX_CHAT_STREAM_MESSAGES, p as formatRecalledMemory, q as RUNTIME_REPORT_SOURCES_TOOL_SLUG, r as ChatStreamUnauthorizedError, s as createChatStreamHandler, t as ChatStreamBadRequestError, u as bindPersonaToSession, v as ASSISTANT_TURN_GENERIC_ERROR, w as createAssistantTurnResponse, x as DEFAULT_ASSISTANT_TURN_HEARTBEAT_MS, y as AssistantTurnUserError, z as sanitizeClientToolDeclarations } from "./chunks/chat-stream-
|
|
1
|
+
import { c as ChatThread, d as ChatParticipant, f as ChatMessage, i as clientRequestMessageId, l as ChatRoom, n as ChatService, o as VoiceSessionCollection, p as AgentSession, s as VoiceSession, t as ChatClientRequestConflictError, u as ChatReaction } from "./chunks/ChatService-CFaaDHyU.js";
|
|
2
|
+
import { A as MAX_CLIENT_TOOLS, B as RUNTIME_REPORT_DEFINE_FUNCTION_NAME, C as SESSION_CONTINUATIONS_FIELD, D as runAssistantTurn, E as createSessionContinuationStore, F as classifyToolError, G as RUNTIME_REPORT_RUN_TOOL_SLUG, H as RUNTIME_REPORT_LIST_FUNCTION_NAME, I as invokeManifestTool, J as createRuntimeReportTools, K as RUNTIME_REPORT_SOURCES_FUNCTION_NAME, L as manifestToolToAITool, M as MAX_CLIENT_TOOL_SCHEMA_BYTES, N as appendClientToolResults, O as CLIENT_TOOL_RESULT_GUIDANCE, P as buildManifestToolCatalog, R as runToolLoop, S as DEFAULT_CONTINUATION_TTL_MS, T as createMemoryContinuationStore, U as RUNTIME_REPORT_LIST_TOOL_SLUG, V as RUNTIME_REPORT_DEFINE_TOOL_SLUG, W as RUNTIME_REPORT_RUN_FUNCTION_NAME, _ as runPersonaConversationTurn, a as MAX_CHAT_STREAM_CONTENT_LENGTH, b as CONTINUATION_CLAIM_TTL_MS, c as encodeChatStreamEvent, d as conversationPersonaFromAgentPersona, f as conversationPersonaFromResolved, g as resolveConversationInstructions, h as recallPersonaMemory, i as DEFAULT_CHAT_STREAM_HEARTBEAT_MS, j as MAX_CLIENT_TOOL_RESULT_CHARS, k as DEFAULT_MAX_STEPS, l as runChatConversationStream, m as principalBindingFor, n as ChatStreamError, o as MAX_CHAT_STREAM_MESSAGES, p as formatRecalledMemory, q as RUNTIME_REPORT_SOURCES_TOOL_SLUG, r as ChatStreamUnauthorizedError, s as createChatStreamHandler, t as ChatStreamBadRequestError, u as bindPersonaToSession, v as ASSISTANT_TURN_GENERIC_ERROR, w as createAssistantTurnResponse, x as DEFAULT_ASSISTANT_TURN_HEARTBEAT_MS, y as AssistantTurnUserError, z as sanitizeClientToolDeclarations } from "./chunks/chat-stream-n-7AqsgF.js";
|
|
3
3
|
import { i as matchesToolAllowList, n as encodeAssistantTurnEvent, r as readAssistantTurnStream, t as AssistantTurnStreamError } from "./chunks/assistant-turn-events-BbZUf-Ju.js";
|
|
4
4
|
import { a as createServerDataSurfaceBridge, i as createDataSurfaceCommandBridge, n as DEFAULT_DATA_SURFACE_BRIDGE_TTL_MS, r as createDataSurfaceBridge, t as DATA_SURFACE_BRIDGE_VERSION } from "./chunks/data-surface-bridge-BJomMxjS.js";
|
|
5
|
+
import { HELPER_CLEARED_PREFERENCES, HELPER_PREFERENCES_VERSION, helperPreferenceFields, isHelperClearedPreferences, parseHelperPreferences } from "./helper-preferences.js";
|
|
5
6
|
import { CHAT_MODULE_META, CHAT_UI_SLOTS } from "./ui.js";
|
|
6
7
|
import { SmrtCollection, SmrtObject, SmrtRecipe, ValidationError, field, foreignKey, resolveDatabase, smrt } from "@happyvertical/smrt-core";
|
|
7
|
-
import { DATA_DISCOVER_FUNCTION_NAME, DATA_DISCOVER_TOOL_SLUG, DATA_INSPECT_FUNCTION_NAME, DATA_INSPECT_TOOL_SLUG, DATA_QUERY_FUNCTION_NAME, DATA_QUERY_TOOL_SLUG, DEFAULT_DATA_SURFACE_DEADLINE_MS, DataSurfaceDeadlineError, DataSurfaceDeniedError, DataSurfaceQueryError, DataSurfaceRequestError, DataSurfaceResultOrderError, MAX_DATA_SURFACE_DEADLINE_MS, createDataSurfaceQueryFingerprint, createDataSurfaceTools } from "@happyvertical/smrt-agents";
|
|
8
|
-
import { TenantScoped, tenantId } from "@happyvertical/smrt-tenancy";
|
|
8
|
+
import { DATA_DISCOVER_FUNCTION_NAME, DATA_DISCOVER_TOOL_SLUG, DATA_INSPECT_FUNCTION_NAME, DATA_INSPECT_TOOL_SLUG, DATA_QUERY_FUNCTION_NAME, DATA_QUERY_TOOL_SLUG, DEFAULT_DATA_SURFACE_DEADLINE_MS, DataSurfaceDeadlineError, DataSurfaceDeniedError, DataSurfaceDeniedError as DataSurfaceDeniedError$1, DataSurfaceQueryError, DataSurfaceRequestError, DataSurfaceResultOrderError, MAX_DATA_SURFACE_DEADLINE_MS, createDataSurfaceQueryFingerprint, createDataSurfaceTools } from "@happyvertical/smrt-agents";
|
|
9
|
+
import { TenantScoped, getCurrentTenant, isSuperAdminBypass, isSystemContext, isTenancyEnabled, tenantId, withTenant } from "@happyvertical/smrt-tenancy";
|
|
9
10
|
import { FeedbackCollection, feedbackSourceFor, personaLearningMemory, personaMemoryScope, reinforceFromFeedback } from "@happyvertical/smrt-personas";
|
|
11
|
+
import { ProfileCollection, ProfileMetadataCollection, ProfileMetafieldCollection } from "@happyvertical/smrt-profiles";
|
|
10
12
|
//#region src/chat-feedback.ts
|
|
11
13
|
async function captureChatFeedback(options) {
|
|
12
14
|
if (!options.persona.id) throw new Error("captureChatFeedback requires a persisted persona (missing id)");
|
|
@@ -85,6 +87,286 @@ function thumbsDown(options) {
|
|
|
85
87
|
});
|
|
86
88
|
}
|
|
87
89
|
//#endregion
|
|
90
|
+
//#region src/helper-preferences-service.ts
|
|
91
|
+
var HelperPreferencesAuthorizationError = class extends Error {
|
|
92
|
+
constructor() {
|
|
93
|
+
super("Helper preference access is not authorized.");
|
|
94
|
+
this.name = "HelperPreferencesAuthorizationError";
|
|
95
|
+
}
|
|
96
|
+
};
|
|
97
|
+
var HelperPreferencesValidationError = class extends Error {
|
|
98
|
+
constructor(message) {
|
|
99
|
+
super(message);
|
|
100
|
+
this.name = "HelperPreferencesValidationError";
|
|
101
|
+
}
|
|
102
|
+
};
|
|
103
|
+
var HelperPreferencesService = class {
|
|
104
|
+
#o;
|
|
105
|
+
constructor(options) {
|
|
106
|
+
this.#o = options;
|
|
107
|
+
}
|
|
108
|
+
async load(c) {
|
|
109
|
+
await this.#auth(c, "load");
|
|
110
|
+
return this.#resolve(c, await this.#o.store.load(c));
|
|
111
|
+
}
|
|
112
|
+
async save(c, value) {
|
|
113
|
+
await this.#auth(c, "save");
|
|
114
|
+
const p = await this.#visiblePolicy(c, await this.#policy(c));
|
|
115
|
+
if (p.selection === "owner-assigned") throw new HelperPreferencesAuthorizationError();
|
|
116
|
+
const next = parseHelperPreferences(value);
|
|
117
|
+
if (!next) throw new HelperPreferencesValidationError("Helper preferences are invalid.");
|
|
118
|
+
for (const f of this.#fields()) if (!p.customizable.includes(f) && next[f] !== p.defaultPreferences[f]) throw new HelperPreferencesValidationError(`The ${f} preference is not customizable.`);
|
|
119
|
+
await this.#validate(c, p, next);
|
|
120
|
+
await this.#o.store.save(c, next);
|
|
121
|
+
return this.#resolve(c, await this.#o.store.load(c));
|
|
122
|
+
}
|
|
123
|
+
async reset(c) {
|
|
124
|
+
await this.#auth(c, "reset");
|
|
125
|
+
if ((await this.#policy(c)).selection === "owner-assigned") throw new HelperPreferencesAuthorizationError();
|
|
126
|
+
await this.#o.store.clear(c);
|
|
127
|
+
return this.#resolve(c, await this.#o.store.load(c));
|
|
128
|
+
}
|
|
129
|
+
async #auth(c, op) {
|
|
130
|
+
if (!await this.#o.authorize(c, op)) throw new HelperPreferencesAuthorizationError();
|
|
131
|
+
}
|
|
132
|
+
async #policy(c) {
|
|
133
|
+
const p = await this.#o.resolvePolicy(c);
|
|
134
|
+
if (!parseHelperPreferences(p.defaultPreferences) || p.assignedPreferences !== void 0 && !parseHelperPreferences(p.assignedPreferences)) throw new HelperPreferencesValidationError("Helper policy preferences are invalid.");
|
|
135
|
+
return p;
|
|
136
|
+
}
|
|
137
|
+
async #resolve(c, raw) {
|
|
138
|
+
const p = await this.#visiblePolicy(c, await this.#policy(c));
|
|
139
|
+
const permissions = p.selection === "owner-assigned" ? {
|
|
140
|
+
editableFields: [],
|
|
141
|
+
canReset: false,
|
|
142
|
+
customStyleIds: []
|
|
143
|
+
} : {
|
|
144
|
+
editableFields: p.customizable,
|
|
145
|
+
canReset: raw !== null && !this.#cleared(raw),
|
|
146
|
+
customStyleIds: p.customStyleIds
|
|
147
|
+
};
|
|
148
|
+
const assigned = p.selection === "owner-assigned";
|
|
149
|
+
if (assigned && !p.assignedPreferences) return this.#snapshot(p, permissions, null, "unavailable", false, {
|
|
150
|
+
code: "invalid-preferences",
|
|
151
|
+
message: "The assigned helper preferences are unavailable."
|
|
152
|
+
});
|
|
153
|
+
const baseline = assigned ? p.assignedPreferences : p.defaultPreferences;
|
|
154
|
+
const persisted = !assigned && raw !== null && !this.#cleared(raw);
|
|
155
|
+
const parsed = assigned ? baseline : !persisted ? baseline : parseHelperPreferences(this.#decode(raw));
|
|
156
|
+
if (!parsed) try {
|
|
157
|
+
await this.#validate(c, p, baseline);
|
|
158
|
+
return this.#snapshot(p, permissions, baseline, "default", true, {
|
|
159
|
+
code: "invalid-preferences",
|
|
160
|
+
message: "Saved helper preferences are invalid. Reset to use current defaults."
|
|
161
|
+
});
|
|
162
|
+
} catch (error) {
|
|
163
|
+
if (error instanceof HelperPreferencesAuthorizationError) throw error;
|
|
164
|
+
return this.#snapshot(p, permissions, null, "unavailable", true, {
|
|
165
|
+
code: "invalid-preferences",
|
|
166
|
+
message: "The application default helper is unavailable."
|
|
167
|
+
});
|
|
168
|
+
}
|
|
169
|
+
try {
|
|
170
|
+
if (persisted) {
|
|
171
|
+
for (const f of this.#fields()) if (!p.customizable.includes(f) && parsed[f] !== baseline[f]) throw new HelperPreferencesValidationError("invalid-preferences");
|
|
172
|
+
}
|
|
173
|
+
await this.#validate(c, p, parsed);
|
|
174
|
+
return this.#snapshot(p, permissions, parsed, assigned ? "assigned" : persisted ? "personal" : "default", persisted, null);
|
|
175
|
+
} catch (error) {
|
|
176
|
+
if (error instanceof HelperPreferencesAuthorizationError) throw error;
|
|
177
|
+
if (assigned) return this.#snapshot(p, permissions, null, "unavailable", false, {
|
|
178
|
+
code: "invalid-preferences",
|
|
179
|
+
message: "The assigned helper preferences are unavailable."
|
|
180
|
+
});
|
|
181
|
+
try {
|
|
182
|
+
await this.#validate(c, p, baseline);
|
|
183
|
+
return this.#snapshot(p, permissions, baseline, "default", persisted, this.#recovery(error));
|
|
184
|
+
} catch (fallbackError) {
|
|
185
|
+
if (fallbackError instanceof HelperPreferencesAuthorizationError) throw fallbackError;
|
|
186
|
+
return this.#snapshot(p, permissions, null, "unavailable", persisted, {
|
|
187
|
+
code: "invalid-preferences",
|
|
188
|
+
message: "The application default helper is unavailable."
|
|
189
|
+
});
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
async #visiblePolicy(c, p) {
|
|
194
|
+
const offerings = [];
|
|
195
|
+
for (const offering of p.offerings) {
|
|
196
|
+
if (!this.#o.styleIds.includes(offering.styleId)) continue;
|
|
197
|
+
try {
|
|
198
|
+
await this.#o.validateOffering(c, offering);
|
|
199
|
+
offerings.push(offering);
|
|
200
|
+
} catch (error) {
|
|
201
|
+
if (error instanceof HelperPreferencesAuthorizationError) throw error;
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
return {
|
|
205
|
+
...p,
|
|
206
|
+
offerings
|
|
207
|
+
};
|
|
208
|
+
}
|
|
209
|
+
#decode(raw) {
|
|
210
|
+
if (typeof raw !== "string") return raw;
|
|
211
|
+
try {
|
|
212
|
+
return JSON.parse(raw);
|
|
213
|
+
} catch {
|
|
214
|
+
return;
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
#cleared(raw) {
|
|
218
|
+
return isHelperClearedPreferences(typeof raw === "string" ? this.#decode(raw) : raw);
|
|
219
|
+
}
|
|
220
|
+
async #validate(c, p, next) {
|
|
221
|
+
const offering = p.offerings.find((x) => x.id === next.offeringId);
|
|
222
|
+
if (!offering) throw new HelperPreferencesValidationError("unavailable-offering");
|
|
223
|
+
if (!this.#o.styleIds.includes(offering.styleId)) throw new HelperPreferencesValidationError("unavailable-style");
|
|
224
|
+
if (!p.voices.some((x) => x.id === next.voiceId)) throw new HelperPreferencesValidationError("unavailable-voice");
|
|
225
|
+
await this.#o.validateOffering(c, offering);
|
|
226
|
+
}
|
|
227
|
+
#recovery(error) {
|
|
228
|
+
return {
|
|
229
|
+
code: error instanceof HelperPreferencesValidationError && [
|
|
230
|
+
"unavailable-offering",
|
|
231
|
+
"unavailable-style",
|
|
232
|
+
"unavailable-voice"
|
|
233
|
+
].includes(error.message) ? error.message : "invalid-preferences",
|
|
234
|
+
message: "Saved helper preferences are no longer available. Reset to use current defaults."
|
|
235
|
+
};
|
|
236
|
+
}
|
|
237
|
+
#snapshot(p, permissions, prefs, source, hasOverride, recovery) {
|
|
238
|
+
return {
|
|
239
|
+
preferences: prefs,
|
|
240
|
+
recoveryDraft: prefs === null && p.selection !== "owner-assigned" ? this.#recoveryDraft(p, permissions) : null,
|
|
241
|
+
offering: prefs ? p.offerings.find((x) => x.id === prefs.offeringId) ?? null : null,
|
|
242
|
+
selection: p.selection,
|
|
243
|
+
source,
|
|
244
|
+
offerings: p.offerings,
|
|
245
|
+
voices: p.voices,
|
|
246
|
+
permissions,
|
|
247
|
+
hasOverride,
|
|
248
|
+
recovery
|
|
249
|
+
};
|
|
250
|
+
}
|
|
251
|
+
#recoveryDraft(p, permissions) {
|
|
252
|
+
const candidate = { ...p.defaultPreferences };
|
|
253
|
+
if (!p.offerings.find((item) => item.id === candidate.offeringId)) {
|
|
254
|
+
if (!permissions.editableFields.includes("offeringId") || !p.offerings[0]) return null;
|
|
255
|
+
candidate.offeringId = p.offerings[0].id;
|
|
256
|
+
}
|
|
257
|
+
if (!p.voices.some((voice) => voice.id === candidate.voiceId)) {
|
|
258
|
+
if (!permissions.editableFields.includes("voiceId") || !p.voices[0]) return null;
|
|
259
|
+
candidate.voiceId = p.voices[0].id;
|
|
260
|
+
}
|
|
261
|
+
return parseHelperPreferences(candidate);
|
|
262
|
+
}
|
|
263
|
+
#fields() {
|
|
264
|
+
return [
|
|
265
|
+
"offeringId",
|
|
266
|
+
"name",
|
|
267
|
+
"voiceId",
|
|
268
|
+
"placement",
|
|
269
|
+
"heardSubtitles",
|
|
270
|
+
"spokenSubtitles"
|
|
271
|
+
];
|
|
272
|
+
}
|
|
273
|
+
};
|
|
274
|
+
//#endregion
|
|
275
|
+
//#region src/helper-profile-store.ts
|
|
276
|
+
var HelperProfileStoreError = class extends Error {
|
|
277
|
+
constructor(message) {
|
|
278
|
+
super(message);
|
|
279
|
+
this.name = "HelperProfileStoreError";
|
|
280
|
+
}
|
|
281
|
+
};
|
|
282
|
+
var ProfileHelperPreferenceStore = class {
|
|
283
|
+
#db;
|
|
284
|
+
#metafieldSlug;
|
|
285
|
+
#applicationId;
|
|
286
|
+
constructor(options) {
|
|
287
|
+
this.#db = options.db;
|
|
288
|
+
this.#metafieldSlug = options.metafieldSlug;
|
|
289
|
+
this.#applicationId = options.applicationId;
|
|
290
|
+
}
|
|
291
|
+
async load(context) {
|
|
292
|
+
const { profile, metafield, metadata } = await this.#boundRecords(context);
|
|
293
|
+
const rows = await metadata.list({ where: {
|
|
294
|
+
profileId: profile.id,
|
|
295
|
+
metafieldId: metafield.id
|
|
296
|
+
} });
|
|
297
|
+
if (rows.length > 1) throw new HelperProfileStoreError("Duplicate helper preference metadata rows.");
|
|
298
|
+
const row = rows[0];
|
|
299
|
+
if (!row) return null;
|
|
300
|
+
if ((row.tenantId ?? null) !== (profile.tenantId ?? null)) throw new HelperProfileStoreError("Helper preference metadata tenant mismatch.");
|
|
301
|
+
return row.value;
|
|
302
|
+
}
|
|
303
|
+
async save(context, value) {
|
|
304
|
+
const { profile, metafield, metadata } = await this.#boundRecords(context);
|
|
305
|
+
const rows = await metadata.list({ where: {
|
|
306
|
+
profileId: profile.id,
|
|
307
|
+
metafieldId: metafield.id
|
|
308
|
+
} });
|
|
309
|
+
if (rows.length > 1) throw new HelperProfileStoreError("Duplicate helper preference metadata rows.");
|
|
310
|
+
const serialized = JSON.stringify(value);
|
|
311
|
+
const row = rows[0];
|
|
312
|
+
if (row) {
|
|
313
|
+
if ((row.tenantId ?? null) !== (profile.tenantId ?? null)) throw new HelperProfileStoreError("Helper preference metadata tenant mismatch.");
|
|
314
|
+
row.value = serialized;
|
|
315
|
+
await row.save();
|
|
316
|
+
return;
|
|
317
|
+
}
|
|
318
|
+
await (await metadata.create({
|
|
319
|
+
profileId: profile.id,
|
|
320
|
+
metafieldId: metafield.id,
|
|
321
|
+
value: serialized,
|
|
322
|
+
tenantId: profile.tenantId ?? null
|
|
323
|
+
})).save();
|
|
324
|
+
}
|
|
325
|
+
async clear(context) {
|
|
326
|
+
const { profile, metafield, metadata } = await this.#boundRecords(context);
|
|
327
|
+
const rows = await metadata.list({ where: {
|
|
328
|
+
profileId: profile.id,
|
|
329
|
+
metafieldId: metafield.id
|
|
330
|
+
} });
|
|
331
|
+
if (rows.length > 1) throw new HelperProfileStoreError("Duplicate helper preference metadata rows.");
|
|
332
|
+
const serialized = JSON.stringify({
|
|
333
|
+
version: 1,
|
|
334
|
+
cleared: true
|
|
335
|
+
});
|
|
336
|
+
const row = rows[0];
|
|
337
|
+
if (row) {
|
|
338
|
+
if ((row.tenantId ?? null) !== (profile.tenantId ?? null)) throw new HelperProfileStoreError("Helper preference metadata tenant mismatch.");
|
|
339
|
+
row.value = serialized;
|
|
340
|
+
await row.save();
|
|
341
|
+
return;
|
|
342
|
+
}
|
|
343
|
+
await (await metadata.create({
|
|
344
|
+
profileId: profile.id,
|
|
345
|
+
metafieldId: metafield.id,
|
|
346
|
+
value: serialized,
|
|
347
|
+
tenantId: profile.tenantId ?? null
|
|
348
|
+
})).save();
|
|
349
|
+
}
|
|
350
|
+
async #boundRecords(context) {
|
|
351
|
+
if (context.applicationId !== this.#applicationId) throw new HelperProfileStoreError("Helper preference application mismatch.");
|
|
352
|
+
const profile = await (await ProfileCollection.create({ db: this.#db })).get({ id: context.profileId });
|
|
353
|
+
if (!profile || (profile.tenantId ?? null) !== context.tenantId) throw new HelperProfileStoreError("Helper preference profile is unavailable.");
|
|
354
|
+
const candidates = await (await ProfileMetafieldCollection.create({ db: this.#db })).list({ where: { slug: this.#metafieldSlug } });
|
|
355
|
+
const matching = candidates.filter((field) => (field.tenantId ?? null) === (profile.tenantId ?? null));
|
|
356
|
+
const global = candidates.filter((field) => field.tenantId === null);
|
|
357
|
+
const chosen = matching[0] ?? global[0];
|
|
358
|
+
if (!chosen || matching.length > 1 || matching.length === 0 && global.length > 1) throw new HelperProfileStoreError("The pre-provisioned helper preference metafield is unavailable or ambiguous.");
|
|
359
|
+
return {
|
|
360
|
+
profile,
|
|
361
|
+
metafield: chosen,
|
|
362
|
+
metadata: await ProfileMetadataCollection.create({ db: this.#db })
|
|
363
|
+
};
|
|
364
|
+
}
|
|
365
|
+
};
|
|
366
|
+
function createHelperProfilePreferenceStore(options) {
|
|
367
|
+
return new ProfileHelperPreferenceStore(options);
|
|
368
|
+
}
|
|
369
|
+
//#endregion
|
|
88
370
|
//#region src/models/VoiceGatewayTurn.ts
|
|
89
371
|
var __defProp = Object.defineProperty;
|
|
90
372
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
@@ -150,6 +432,334 @@ VoiceGatewayTurn = __decorateClass([TenantScoped({ mode: "required" }), smrt({
|
|
|
150
432
|
cli: false
|
|
151
433
|
})], VoiceGatewayTurn);
|
|
152
434
|
//#endregion
|
|
435
|
+
//#region src/overview-tools.ts
|
|
436
|
+
var OVERVIEW_DESCRIBE_TOOL_SLUG = "overviews.describe";
|
|
437
|
+
var OVERVIEW_APPLY_TOOL_SLUG = "overviews.apply";
|
|
438
|
+
var OVERVIEW_UNDO_TOOL_SLUG = "overviews.undo";
|
|
439
|
+
var OVERVIEW_DESCRIBE_FUNCTION_NAME = "overviews-describe";
|
|
440
|
+
var OVERVIEW_APPLY_FUNCTION_NAME = "overviews-apply";
|
|
441
|
+
var OVERVIEW_UNDO_FUNCTION_NAME = "overviews-undo";
|
|
442
|
+
var OVERVIEW_TOOL_MAX_OPERATIONS = 20;
|
|
443
|
+
var PAGE_ID_PATTERN = /^[A-Za-z0-9][A-Za-z0-9_.:-]{0,95}$/;
|
|
444
|
+
var OverviewToolError = class extends Error {
|
|
445
|
+
status;
|
|
446
|
+
code;
|
|
447
|
+
publicMessage;
|
|
448
|
+
issues;
|
|
449
|
+
constructor(status, code, message, issues = []) {
|
|
450
|
+
super(message);
|
|
451
|
+
this.name = "OverviewToolError";
|
|
452
|
+
this.status = status;
|
|
453
|
+
this.code = code;
|
|
454
|
+
this.publicMessage = message;
|
|
455
|
+
this.issues = issues;
|
|
456
|
+
}
|
|
457
|
+
};
|
|
458
|
+
function createMemoryOverviewUndoStore(options = {}) {
|
|
459
|
+
const ttl = options.ttlMs ?? 30 * 6e4;
|
|
460
|
+
const max = options.maxEntries ?? 1e3;
|
|
461
|
+
const now = options.now ?? Date.now;
|
|
462
|
+
const entries = /* @__PURE__ */ new Map();
|
|
463
|
+
return {
|
|
464
|
+
get(key) {
|
|
465
|
+
const entry = entries.get(key);
|
|
466
|
+
if (entry && now() - entry.createdAt > ttl) {
|
|
467
|
+
entries.delete(key);
|
|
468
|
+
return;
|
|
469
|
+
}
|
|
470
|
+
return entry;
|
|
471
|
+
},
|
|
472
|
+
set(key, entry) {
|
|
473
|
+
const existing = entries.get(key);
|
|
474
|
+
if (existing && existing.createdAt > entry.createdAt) return;
|
|
475
|
+
entries.delete(key);
|
|
476
|
+
entries.set(key, entry);
|
|
477
|
+
while (entries.size > max) {
|
|
478
|
+
const oldest = entries.keys().next().value;
|
|
479
|
+
if (oldest === void 0) break;
|
|
480
|
+
entries.delete(oldest);
|
|
481
|
+
}
|
|
482
|
+
},
|
|
483
|
+
delete(key, token) {
|
|
484
|
+
if (entries.get(key)?.token === token) entries.delete(key);
|
|
485
|
+
}
|
|
486
|
+
};
|
|
487
|
+
}
|
|
488
|
+
var processUndoStore;
|
|
489
|
+
var lastUndoStamp = 0;
|
|
490
|
+
function nextUndoStamp() {
|
|
491
|
+
lastUndoStamp = Math.max(Date.now(), lastUndoStamp + 1);
|
|
492
|
+
return lastUndoStamp;
|
|
493
|
+
}
|
|
494
|
+
function defaultOverviewUndoStore() {
|
|
495
|
+
processUndoStore ??= createMemoryOverviewUndoStore();
|
|
496
|
+
return processUndoStore;
|
|
497
|
+
}
|
|
498
|
+
function principalFromRun(run) {
|
|
499
|
+
const userId = run.context.userId;
|
|
500
|
+
if (!userId) throw new DataSurfaceDeniedError$1();
|
|
501
|
+
return {
|
|
502
|
+
userId,
|
|
503
|
+
tenantId: run.context.tenantId
|
|
504
|
+
};
|
|
505
|
+
}
|
|
506
|
+
async function withPrincipalTenant(run, fn) {
|
|
507
|
+
if (!isTenancyEnabled()) return fn();
|
|
508
|
+
const tenantId = run.context.tenantId;
|
|
509
|
+
if (!tenantId) throw new OverviewToolError(403, "tenant_required", "A tenant is required to use overview tools.");
|
|
510
|
+
const active = getCurrentTenant();
|
|
511
|
+
if (active === void 0) return withTenant({ tenantId }, fn);
|
|
512
|
+
if (active.tenantId !== tenantId && !isSystemContext() && !isSuperAdminBypass()) throw new DataSurfaceDeniedError$1();
|
|
513
|
+
return fn();
|
|
514
|
+
}
|
|
515
|
+
function guarded(slug, body) {
|
|
516
|
+
return async (context) => {
|
|
517
|
+
context.run.assertToolAllowed(slug);
|
|
518
|
+
principalFromRun(context.run);
|
|
519
|
+
return withPrincipalTenant(context.run, () => body(context));
|
|
520
|
+
};
|
|
521
|
+
}
|
|
522
|
+
function aiTool(slug, name, description, parameters, execute) {
|
|
523
|
+
return {
|
|
524
|
+
slug,
|
|
525
|
+
aiTool: {
|
|
526
|
+
type: "function",
|
|
527
|
+
function: {
|
|
528
|
+
name,
|
|
529
|
+
description,
|
|
530
|
+
parameters
|
|
531
|
+
}
|
|
532
|
+
},
|
|
533
|
+
execute
|
|
534
|
+
};
|
|
535
|
+
}
|
|
536
|
+
function persistFailure(result, conflict) {
|
|
537
|
+
if (result.reason === "conflict") return new OverviewToolError(409, conflict.code, conflict.message);
|
|
538
|
+
if (result.reason === "not_allowed") return new OverviewToolError(403, "not_allowed", "You may not change this overview.");
|
|
539
|
+
const issues = result.issues ?? [];
|
|
540
|
+
return new OverviewToolError(422, "invalid_operations", `The overview rejected the change and nothing changed. ${formatOverviewIssues(issues)}`, issues);
|
|
541
|
+
}
|
|
542
|
+
function sameJson(a, b) {
|
|
543
|
+
return JSON.stringify(a ?? null) === JSON.stringify(b ?? null);
|
|
544
|
+
}
|
|
545
|
+
function formatOverviewIssues(issues) {
|
|
546
|
+
return issues.slice(0, 10).map((issue) => {
|
|
547
|
+
const record = issue && typeof issue === "object" ? issue : {};
|
|
548
|
+
return `${typeof record.index === "number" ? `#${record.index + 1}` : "batch"}${typeof record.op === "string" ? ` ${record.op}` : ""}: ${typeof record.message === "string" ? record.message : typeof record.code === "string" ? record.code : "invalid"}`;
|
|
549
|
+
}).join("; ");
|
|
550
|
+
}
|
|
551
|
+
var OPERATION_PARAMETERS = {
|
|
552
|
+
type: "object",
|
|
553
|
+
required: ["op"],
|
|
554
|
+
additionalProperties: false,
|
|
555
|
+
properties: {
|
|
556
|
+
op: {
|
|
557
|
+
type: "string",
|
|
558
|
+
enum: [
|
|
559
|
+
"add",
|
|
560
|
+
"configure",
|
|
561
|
+
"move",
|
|
562
|
+
"resize",
|
|
563
|
+
"remove"
|
|
564
|
+
]
|
|
565
|
+
},
|
|
566
|
+
type: {
|
|
567
|
+
type: "string",
|
|
568
|
+
description: "add: a widget type overviews-describe lists."
|
|
569
|
+
},
|
|
570
|
+
id: {
|
|
571
|
+
type: "string",
|
|
572
|
+
description: "configure/move/resize/remove: an existing widget id."
|
|
573
|
+
},
|
|
574
|
+
span: {
|
|
575
|
+
type: "integer",
|
|
576
|
+
minimum: 1,
|
|
577
|
+
maximum: 4,
|
|
578
|
+
description: "add/resize: columns, within the type's span range."
|
|
579
|
+
},
|
|
580
|
+
index: {
|
|
581
|
+
type: "integer",
|
|
582
|
+
minimum: 0,
|
|
583
|
+
description: "add/move: zero-based position."
|
|
584
|
+
},
|
|
585
|
+
options: {
|
|
586
|
+
type: "object",
|
|
587
|
+
description: "add: the options; configure: keys to change (null resets a key). Only the option fields overviews-describe lists, with their allowed values.",
|
|
588
|
+
additionalProperties: { type: [
|
|
589
|
+
"string",
|
|
590
|
+
"number",
|
|
591
|
+
"boolean",
|
|
592
|
+
"null"
|
|
593
|
+
] }
|
|
594
|
+
}
|
|
595
|
+
}
|
|
596
|
+
};
|
|
597
|
+
function createOverviewTools(options) {
|
|
598
|
+
const { host } = options;
|
|
599
|
+
const undoStore = options.undoStore ?? defaultOverviewUndoStore();
|
|
600
|
+
const maxOperations = options.maxOperations ?? 20;
|
|
601
|
+
const createToken = options.createToken ?? (() => crypto.randomUUID());
|
|
602
|
+
const onError = options.onError ?? ((error, context) => {
|
|
603
|
+
console.warn(`[smrt-chat] ${context}`, error);
|
|
604
|
+
});
|
|
605
|
+
const undoKey = (run, pageId) => {
|
|
606
|
+
const { userId, tenantId } = principalFromRun(run);
|
|
607
|
+
return JSON.stringify([
|
|
608
|
+
tenantId,
|
|
609
|
+
userId,
|
|
610
|
+
pageId
|
|
611
|
+
]);
|
|
612
|
+
};
|
|
613
|
+
const pageArg = (value) => {
|
|
614
|
+
if (typeof value !== "string" || !PAGE_ID_PATTERN.test(value)) throw new OverviewToolError(422, "invalid_page", "page must be an overview page id from overviews-describe");
|
|
615
|
+
return value;
|
|
616
|
+
};
|
|
617
|
+
const open = async (run, pageId) => {
|
|
618
|
+
const surface = await host.open(run, pageId);
|
|
619
|
+
if (!surface || surface.pageId !== pageId) throw new OverviewToolError(404, "unknown_page", `no overview page "${pageId}" is available`);
|
|
620
|
+
return surface;
|
|
621
|
+
};
|
|
622
|
+
const requireCustomize = (surface) => {
|
|
623
|
+
if (!surface.canCustomize) throw new OverviewToolError(403, "not_allowed", "You may not change this overview.");
|
|
624
|
+
};
|
|
625
|
+
const audit = async (run, entry) => {
|
|
626
|
+
try {
|
|
627
|
+
await options.audit?.({
|
|
628
|
+
...entry,
|
|
629
|
+
...principalFromRun(run)
|
|
630
|
+
});
|
|
631
|
+
} catch (error) {
|
|
632
|
+
onError(error, `overview tool audit failed (${entry.action})`);
|
|
633
|
+
}
|
|
634
|
+
};
|
|
635
|
+
return [
|
|
636
|
+
aiTool(OVERVIEW_DESCRIBE_TOOL_SLUG, OVERVIEW_DESCRIBE_FUNCTION_NAME, "Describe an overview page: the widget types it allows (with their option fields, allowed values and span range) and the widgets it shows now, in order, plus whether you may change it. Without a page, lists the overview pages available. Call before changing an overview; never invent types, option keys or models.", {
|
|
637
|
+
type: "object",
|
|
638
|
+
additionalProperties: false,
|
|
639
|
+
properties: { page: {
|
|
640
|
+
type: "string",
|
|
641
|
+
description: "Overview page id."
|
|
642
|
+
} }
|
|
643
|
+
}, guarded(OVERVIEW_DESCRIBE_TOOL_SLUG, async ({ run, args }) => {
|
|
644
|
+
if (args.page === void 0) return { pages: host.pages ? await host.pages(run) : [] };
|
|
645
|
+
const surface = await open(run, pageArg(args.page));
|
|
646
|
+
return {
|
|
647
|
+
page: surface.pageId,
|
|
648
|
+
overview: surface.describe()
|
|
649
|
+
};
|
|
650
|
+
})),
|
|
651
|
+
aiTool(OVERVIEW_APPLY_TOOL_SLUG, OVERVIEW_APPLY_FUNCTION_NAME, "Change an overview page with a batch of structured operations: add {type, span?, options, index?}, configure {id, options}, move {id, index}, resize {id, span}, remove {id}. The batch is all-or-nothing: if any operation is invalid nothing changes and the issues are returned to fix. Returns an undoToken; the person can undo the batch.", {
|
|
652
|
+
type: "object",
|
|
653
|
+
required: ["page", "operations"],
|
|
654
|
+
additionalProperties: false,
|
|
655
|
+
properties: {
|
|
656
|
+
page: {
|
|
657
|
+
type: "string",
|
|
658
|
+
description: "Overview page id."
|
|
659
|
+
},
|
|
660
|
+
operations: {
|
|
661
|
+
type: "array",
|
|
662
|
+
minItems: 1,
|
|
663
|
+
maxItems: maxOperations,
|
|
664
|
+
items: OPERATION_PARAMETERS
|
|
665
|
+
}
|
|
666
|
+
}
|
|
667
|
+
}, guarded(OVERVIEW_APPLY_TOOL_SLUG, async ({ run, args }) => {
|
|
668
|
+
const pageId = pageArg(args.page);
|
|
669
|
+
const operations = args.operations;
|
|
670
|
+
if (!Array.isArray(operations) || operations.length === 0 || operations.length > maxOperations) throw new OverviewToolError(422, "invalid_operations", `operations must be an array of 1 to ${maxOperations} operations`);
|
|
671
|
+
const surface = await open(run, pageId);
|
|
672
|
+
requireCustomize(surface);
|
|
673
|
+
const before = surface.current();
|
|
674
|
+
const plan = surface.plan(operations);
|
|
675
|
+
if (!plan.ok) throw new OverviewToolError(422, "invalid_operations", `The batch was rejected and nothing changed. ${formatOverviewIssues(plan.issues)}`, plan.issues);
|
|
676
|
+
if (!!(plan.unchanged ?? sameJson(plan.override, before))) return {
|
|
677
|
+
page: pageId,
|
|
678
|
+
changed: false,
|
|
679
|
+
applied: plan.results,
|
|
680
|
+
undoToken: null
|
|
681
|
+
};
|
|
682
|
+
const written = await surface.persist(plan.override);
|
|
683
|
+
if (!written.ok) throw persistFailure(written, {
|
|
684
|
+
code: "conflict",
|
|
685
|
+
message: "The overview changed while the batch was being applied, so nothing changed. Call overviews-describe again and rebuild the batch."
|
|
686
|
+
});
|
|
687
|
+
let token = createToken();
|
|
688
|
+
try {
|
|
689
|
+
await undoStore.set(undoKey(run, pageId), {
|
|
690
|
+
token,
|
|
691
|
+
before,
|
|
692
|
+
after: plan.override,
|
|
693
|
+
createdAt: nextUndoStamp()
|
|
694
|
+
});
|
|
695
|
+
} catch (error) {
|
|
696
|
+
onError(error, "overview undo entry was not stored");
|
|
697
|
+
token = null;
|
|
698
|
+
}
|
|
699
|
+
await audit(run, {
|
|
700
|
+
action: "apply",
|
|
701
|
+
pageId,
|
|
702
|
+
operations: operations.length
|
|
703
|
+
});
|
|
704
|
+
return {
|
|
705
|
+
page: pageId,
|
|
706
|
+
changed: true,
|
|
707
|
+
applied: plan.results,
|
|
708
|
+
undoToken: token,
|
|
709
|
+
...token === null ? { note: "The change was applied but cannot be undone with overviews-undo. Do not apply it again." } : {},
|
|
710
|
+
overview: surface.describe()
|
|
711
|
+
};
|
|
712
|
+
})),
|
|
713
|
+
aiTool(OVERVIEW_UNDO_TOOL_SLUG, OVERVIEW_UNDO_FUNCTION_NAME, "Undo the last batch applied to an overview page (pass the undoToken overviews-apply returned). Single step: only the latest batch can be undone, and not once the page changed since.", {
|
|
714
|
+
type: "object",
|
|
715
|
+
required: ["page", "undoToken"],
|
|
716
|
+
additionalProperties: false,
|
|
717
|
+
properties: {
|
|
718
|
+
page: {
|
|
719
|
+
type: "string",
|
|
720
|
+
description: "Overview page id."
|
|
721
|
+
},
|
|
722
|
+
undoToken: { type: "string" }
|
|
723
|
+
}
|
|
724
|
+
}, guarded(OVERVIEW_UNDO_TOOL_SLUG, async ({ run, args }) => {
|
|
725
|
+
const pageId = pageArg(args.page);
|
|
726
|
+
const key = undoKey(run, pageId);
|
|
727
|
+
const entry = await undoStore.get(key);
|
|
728
|
+
if (!entry || typeof args.undoToken !== "string" || entry.token !== args.undoToken) throw new OverviewToolError(409, "nothing_to_undo", "There is no assistant change with that undoToken to undo on this page; only the latest batch can be undone.");
|
|
729
|
+
const surface = await open(run, pageId);
|
|
730
|
+
requireCustomize(surface);
|
|
731
|
+
if (!sameJson(surface.current(), entry.after)) {
|
|
732
|
+
await undoStore.delete(key, entry.token);
|
|
733
|
+
throw new OverviewToolError(409, "changed_since", "The overview changed after that batch, so it was not undone.");
|
|
734
|
+
}
|
|
735
|
+
const checked = surface.check(entry.before);
|
|
736
|
+
if (!checked.ok) {
|
|
737
|
+
await undoStore.delete(key, entry.token);
|
|
738
|
+
throw new OverviewToolError(409, "cannot_restore", `The earlier arrangement is no longer valid on this page. ${formatOverviewIssues(checked.issues)}`, checked.issues);
|
|
739
|
+
}
|
|
740
|
+
const written = await surface.persist(checked.override);
|
|
741
|
+
if (!written.ok) throw persistFailure(written, {
|
|
742
|
+
code: "changed_since",
|
|
743
|
+
message: "The overview changed after that batch, so it was not undone."
|
|
744
|
+
});
|
|
745
|
+
try {
|
|
746
|
+
await undoStore.delete(key, entry.token);
|
|
747
|
+
} catch (error) {
|
|
748
|
+
onError(error, "overview undo entry was not removed");
|
|
749
|
+
}
|
|
750
|
+
await audit(run, {
|
|
751
|
+
action: "undo",
|
|
752
|
+
pageId
|
|
753
|
+
});
|
|
754
|
+
return {
|
|
755
|
+
page: pageId,
|
|
756
|
+
undone: true,
|
|
757
|
+
overview: surface.describe()
|
|
758
|
+
};
|
|
759
|
+
}))
|
|
760
|
+
];
|
|
761
|
+
}
|
|
762
|
+
//#endregion
|
|
153
763
|
//#region src/recipes.ts
|
|
154
764
|
var AssistantRecipe = class extends SmrtRecipe {
|
|
155
765
|
static id = "chat.assistant";
|
|
@@ -198,6 +808,74 @@ var AssistantRecipe = class extends SmrtRecipe {
|
|
|
198
808
|
browserOptions: ["webllm", "bitgpu"]
|
|
199
809
|
}];
|
|
200
810
|
};
|
|
811
|
+
var ChatRoomsRecipe = class extends SmrtRecipe {
|
|
812
|
+
static id = "chat.rooms";
|
|
813
|
+
static help = "./chat-rooms.recipe.md";
|
|
814
|
+
static label = "Team Chat";
|
|
815
|
+
static summary = "Organize team conversations in rooms with threads and reactions.";
|
|
816
|
+
static synonyms = [
|
|
817
|
+
"team chat",
|
|
818
|
+
"channels",
|
|
819
|
+
"group chat",
|
|
820
|
+
"conversations"
|
|
821
|
+
];
|
|
822
|
+
static models = [
|
|
823
|
+
ChatRoom,
|
|
824
|
+
ChatMessage,
|
|
825
|
+
ChatParticipant,
|
|
826
|
+
ChatThread,
|
|
827
|
+
ChatReaction
|
|
828
|
+
];
|
|
829
|
+
static group = {
|
|
830
|
+
id: "team-collaboration",
|
|
831
|
+
label: "Team collaboration",
|
|
832
|
+
summary: "Keep conversations and shared work in one place."
|
|
833
|
+
};
|
|
834
|
+
static section = {
|
|
835
|
+
id: "team",
|
|
836
|
+
label: "Team",
|
|
837
|
+
icon: "users",
|
|
838
|
+
description: "People and the conversations that keep them aligned."
|
|
839
|
+
};
|
|
840
|
+
static nav = [{
|
|
841
|
+
label: "Chat Rooms",
|
|
842
|
+
model: ChatRoom,
|
|
843
|
+
icon: "users",
|
|
844
|
+
description: "Team conversations organized by topic or audience.",
|
|
845
|
+
noun: "chat room"
|
|
846
|
+
}];
|
|
847
|
+
static runtime = "both";
|
|
848
|
+
static surfaces = [{
|
|
849
|
+
kind: "route",
|
|
850
|
+
path: "/chat/rooms",
|
|
851
|
+
export: "@happyvertical/smrt-chat/svelte#ChatLayout",
|
|
852
|
+
label: "Team chat"
|
|
853
|
+
}, {
|
|
854
|
+
kind: "playground",
|
|
855
|
+
export: "@happyvertical/smrt-chat/playground#default",
|
|
856
|
+
label: "Static chat fixtures"
|
|
857
|
+
}];
|
|
858
|
+
static demoSeed = { export: "@happyvertical/smrt-chat/playground#chatRoomsFixture" };
|
|
859
|
+
static options = {
|
|
860
|
+
ChatRoom: { fields: {
|
|
861
|
+
metadata: { visibility: "hidden" },
|
|
862
|
+
createdByProfileId: { visibility: "hidden" },
|
|
863
|
+
lastMessageAt: {
|
|
864
|
+
label: "Last message",
|
|
865
|
+
order: 1
|
|
866
|
+
}
|
|
867
|
+
} },
|
|
868
|
+
ChatMessage: { fields: {
|
|
869
|
+
metadata: { visibility: "hidden" },
|
|
870
|
+
toolCallData: { visibility: "hidden" },
|
|
871
|
+
attachments: { visibility: "advanced" }
|
|
872
|
+
} },
|
|
873
|
+
ChatParticipant: { fields: {
|
|
874
|
+
lastReadMessageId: { visibility: "hidden" },
|
|
875
|
+
lastSeenAt: { visibility: "advanced" }
|
|
876
|
+
} }
|
|
877
|
+
};
|
|
878
|
+
};
|
|
201
879
|
//#endregion
|
|
202
880
|
//#region src/collections/VoiceGatewayTurnCollection.ts
|
|
203
881
|
var VoiceGatewayTurnCollection = class extends SmrtCollection {
|
|
@@ -617,6 +1295,6 @@ function jsonResponse(body, status) {
|
|
|
617
1295
|
});
|
|
618
1296
|
}
|
|
619
1297
|
//#endregion
|
|
620
|
-
export { ASSISTANT_TURN_GENERIC_ERROR, AgentSession, AssistantRecipe, AssistantTurnStreamError, AssistantTurnUserError, CHAT_MODULE_META, CHAT_UI_SLOTS, CLIENT_TOOL_RESULT_GUIDANCE, CONTINUATION_CLAIM_TTL_MS, ChatClientRequestConflictError, ChatMessage, ChatParticipant, ChatReaction, ChatRoom, ChatService, ChatStreamBadRequestError, ChatStreamError, ChatStreamUnauthorizedError, ChatThread, DATA_DISCOVER_FUNCTION_NAME, DATA_DISCOVER_TOOL_SLUG, DATA_INSPECT_FUNCTION_NAME, DATA_INSPECT_TOOL_SLUG, DATA_QUERY_FUNCTION_NAME, DATA_QUERY_TOOL_SLUG, DATA_SURFACE_BRIDGE_VERSION, DEFAULT_ASSISTANT_TURN_HEARTBEAT_MS, DEFAULT_CHAT_STREAM_HEARTBEAT_MS, DEFAULT_CONTINUATION_TTL_MS, DEFAULT_DATA_SURFACE_BRIDGE_TTL_MS, DEFAULT_DATA_SURFACE_DEADLINE_MS, DEFAULT_MAX_STEPS, DataSurfaceDeadlineError, DataSurfaceDeniedError, DataSurfaceQueryError, DataSurfaceRequestError, DataSurfaceResultOrderError, MAX_CHAT_STREAM_CONTENT_LENGTH, MAX_CHAT_STREAM_MESSAGES, MAX_CLIENT_TOOLS, MAX_CLIENT_TOOL_RESULT_CHARS, MAX_CLIENT_TOOL_SCHEMA_BYTES, MAX_DATA_SURFACE_DEADLINE_MS, MAX_VOICE_GATEWAY_TEXT_LENGTH, RUNTIME_REPORT_DEFINE_FUNCTION_NAME, RUNTIME_REPORT_DEFINE_TOOL_SLUG, RUNTIME_REPORT_LIST_FUNCTION_NAME, RUNTIME_REPORT_LIST_TOOL_SLUG, RUNTIME_REPORT_RUN_FUNCTION_NAME, RUNTIME_REPORT_RUN_TOOL_SLUG, RUNTIME_REPORT_SOURCES_FUNCTION_NAME, RUNTIME_REPORT_SOURCES_TOOL_SLUG, SESSION_CONTINUATIONS_FIELD, SMRT_CHAT_VOICE_TARGET, VoiceGatewayBadRequestError, VoiceGatewayError, VoiceGatewayReplayError, VoiceGatewayTurn, VoiceGatewayUnauthorizedError, VoiceSession, VoiceSessionExpiredError, VoiceSessionRejectedError, acceptAppliedChange, appendClientToolResults, assertVoiceGatewayBearer, bindPersonaToSession, buildManifestToolCatalog, captureChatFeedback, classifyToolError, clientRequestMessageId, conversationPersonaFromAgentPersona, conversationPersonaFromResolved, correctResponse, createAssistantTurnResponse, createChatStreamHandler, createDataSurfaceBridge, createDataSurfaceCommandBridge, createDataSurfaceQueryFingerprint, createDataSurfaceTools, createMemoryContinuationStore, createRuntimeReportTools, createServerDataSurfaceBridge, createSessionContinuationStore, createVoiceChatSession, createVoiceGatewayTurnHandler, encodeAssistantTurnEvent, encodeChatStreamEvent, formatRecalledMemory, handleVoiceGatewayTurn, invokeManifestTool, manifestToolToAITool, matchesToolAllowList, principalBindingFor, rateResponse, readAssistantTurnStream, recallPersonaMemory, rejectAppliedChange, resolveConversationInstructions, runAssistantTurn, runChatConversationStream, runPersonaConversationTurn, runToolLoop, sanitizeClientToolDeclarations, thumbsDown, thumbsUp };
|
|
1298
|
+
export { ASSISTANT_TURN_GENERIC_ERROR, AgentSession, AssistantRecipe, AssistantTurnStreamError, AssistantTurnUserError, CHAT_MODULE_META, CHAT_UI_SLOTS, CLIENT_TOOL_RESULT_GUIDANCE, CONTINUATION_CLAIM_TTL_MS, ChatClientRequestConflictError, ChatMessage, ChatParticipant, ChatReaction, ChatRoom, ChatRoomsRecipe, ChatService, ChatStreamBadRequestError, ChatStreamError, ChatStreamUnauthorizedError, ChatThread, DATA_DISCOVER_FUNCTION_NAME, DATA_DISCOVER_TOOL_SLUG, DATA_INSPECT_FUNCTION_NAME, DATA_INSPECT_TOOL_SLUG, DATA_QUERY_FUNCTION_NAME, DATA_QUERY_TOOL_SLUG, DATA_SURFACE_BRIDGE_VERSION, DEFAULT_ASSISTANT_TURN_HEARTBEAT_MS, DEFAULT_CHAT_STREAM_HEARTBEAT_MS, DEFAULT_CONTINUATION_TTL_MS, DEFAULT_DATA_SURFACE_BRIDGE_TTL_MS, DEFAULT_DATA_SURFACE_DEADLINE_MS, DEFAULT_MAX_STEPS, DataSurfaceDeadlineError, DataSurfaceDeniedError, DataSurfaceQueryError, DataSurfaceRequestError, DataSurfaceResultOrderError, HELPER_CLEARED_PREFERENCES, HELPER_PREFERENCES_VERSION, HelperPreferencesAuthorizationError, HelperPreferencesService, HelperPreferencesValidationError, HelperProfileStoreError, MAX_CHAT_STREAM_CONTENT_LENGTH, MAX_CHAT_STREAM_MESSAGES, MAX_CLIENT_TOOLS, MAX_CLIENT_TOOL_RESULT_CHARS, MAX_CLIENT_TOOL_SCHEMA_BYTES, MAX_DATA_SURFACE_DEADLINE_MS, MAX_VOICE_GATEWAY_TEXT_LENGTH, OVERVIEW_APPLY_FUNCTION_NAME, OVERVIEW_APPLY_TOOL_SLUG, OVERVIEW_DESCRIBE_FUNCTION_NAME, OVERVIEW_DESCRIBE_TOOL_SLUG, OVERVIEW_TOOL_MAX_OPERATIONS, OVERVIEW_UNDO_FUNCTION_NAME, OVERVIEW_UNDO_TOOL_SLUG, OverviewToolError, ProfileHelperPreferenceStore, RUNTIME_REPORT_DEFINE_FUNCTION_NAME, RUNTIME_REPORT_DEFINE_TOOL_SLUG, RUNTIME_REPORT_LIST_FUNCTION_NAME, RUNTIME_REPORT_LIST_TOOL_SLUG, RUNTIME_REPORT_RUN_FUNCTION_NAME, RUNTIME_REPORT_RUN_TOOL_SLUG, RUNTIME_REPORT_SOURCES_FUNCTION_NAME, RUNTIME_REPORT_SOURCES_TOOL_SLUG, SESSION_CONTINUATIONS_FIELD, SMRT_CHAT_VOICE_TARGET, VoiceGatewayBadRequestError, VoiceGatewayError, VoiceGatewayReplayError, VoiceGatewayTurn, VoiceGatewayUnauthorizedError, VoiceSession, VoiceSessionExpiredError, VoiceSessionRejectedError, acceptAppliedChange, appendClientToolResults, assertVoiceGatewayBearer, bindPersonaToSession, buildManifestToolCatalog, captureChatFeedback, classifyToolError, clientRequestMessageId, conversationPersonaFromAgentPersona, conversationPersonaFromResolved, correctResponse, createAssistantTurnResponse, createChatStreamHandler, createDataSurfaceBridge, createDataSurfaceCommandBridge, createDataSurfaceQueryFingerprint, createDataSurfaceTools, createHelperProfilePreferenceStore, createMemoryContinuationStore, createMemoryOverviewUndoStore, createOverviewTools, createRuntimeReportTools, createServerDataSurfaceBridge, createSessionContinuationStore, createVoiceChatSession, createVoiceGatewayTurnHandler, defaultOverviewUndoStore, encodeAssistantTurnEvent, encodeChatStreamEvent, formatOverviewIssues, formatRecalledMemory, handleVoiceGatewayTurn, helperPreferenceFields, invokeManifestTool, isHelperClearedPreferences, manifestToolToAITool, matchesToolAllowList, parseHelperPreferences, principalBindingFor, rateResponse, readAssistantTurnStream, recallPersonaMemory, rejectAppliedChange, resolveConversationInstructions, runAssistantTurn, runChatConversationStream, runPersonaConversationTurn, runToolLoop, sanitizeClientToolDeclarations, thumbsDown, thumbsUp };
|
|
621
1299
|
|
|
622
1300
|
//# sourceMappingURL=index.js.map
|