@fonoster/common 0.27.0 → 0.31.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/{voice/PlayDtmf.d.ts → agents/index.d.ts} +3 -5
- package/dist/{assistants → agents}/index.js +2 -6
- package/dist/agents/sessionAgentSchema.d.ts +755 -0
- package/dist/agents/sessionAgentSchema.js +117 -0
- package/dist/{voice/Dial.d.ts → calls/index.d.ts} +16 -13
- package/dist/calls/index.js +44 -0
- package/dist/cellsecrets/index.d.ts +91 -0
- package/dist/cellsecrets/index.js +299 -0
- package/dist/config/cli/check.d.ts +6 -0
- package/dist/config/cli/check.js +202 -0
- package/dist/config/cli/envFile.d.ts +23 -0
- package/dist/config/cli/envFile.js +81 -0
- package/dist/config/cli/exposure.d.ts +10 -0
- package/dist/config/cli/exposure.js +93 -0
- package/dist/config/cli/index.d.ts +2 -0
- package/dist/{identity/tokenHasAccessKeyId.js → config/cli/index.js} +7 -8
- package/dist/config/cli/info.d.ts +6 -0
- package/dist/config/cli/info.js +62 -0
- package/dist/config/cli/init.d.ts +9 -0
- package/dist/config/cli/init.js +152 -0
- package/dist/config/cli/main.d.ts +11 -0
- package/dist/config/cli/main.js +155 -0
- package/dist/config/cli/render.d.ts +44 -0
- package/dist/config/cli/render.js +129 -0
- package/dist/config/cli/secrets.d.ts +21 -0
- package/dist/config/cli/secrets.js +117 -0
- package/dist/config/cli/types.d.ts +24 -0
- package/dist/config/cli/types.js +7 -0
- package/dist/{assistants/index.d.ts → config/configHints.d.ts} +8 -7
- package/dist/config/configHints.js +47 -0
- package/dist/{voice → config}/index.d.ts +11 -13
- package/dist/{voice → config}/index.js +11 -13
- package/dist/config/interpolateEnv.d.ts +34 -0
- package/dist/config/interpolateEnv.js +70 -0
- package/dist/config/loadServiceConfig.d.ts +28 -0
- package/dist/config/loadServiceConfig.js +112 -0
- package/dist/config/logsSchema.d.ts +76 -0
- package/dist/config/logsSchema.js +49 -0
- package/dist/config/natsConnection.d.ts +53 -0
- package/dist/config/natsConnection.js +58 -0
- package/dist/config/parseConfigFile.d.ts +7 -0
- package/dist/config/parseConfigFile.js +60 -0
- package/dist/config/resolveConfigFile.d.ts +17 -0
- package/dist/config/resolveConfigFile.js +54 -0
- package/dist/config/resolveSecretRefs.d.ts +35 -0
- package/dist/config/resolveSecretRefs.js +129 -0
- package/dist/{assistants/audioFiltersSchema.d.ts → config/strictDeep.d.ts} +9 -12
- package/dist/config/strictDeep.js +58 -0
- package/dist/config/telemetrySchema.d.ts +39 -0
- package/dist/config/telemetrySchema.js +44 -0
- package/dist/config/toJsonSchema.d.ts +30 -0
- package/dist/config/toJsonSchema.js +161 -0
- package/dist/constants.d.ts +1 -6
- package/dist/constants.js +4 -7
- package/dist/envs.d.ts +2 -1
- package/dist/envs.js +13 -11
- package/dist/errors/handleZodError.js +3 -1
- package/dist/filters/index.d.ts +70 -0
- package/dist/filters/index.js +101 -0
- package/dist/identity/createAuthInterceptor.d.ts +9 -2
- package/dist/identity/createAuthInterceptor.js +36 -30
- package/dist/identity/hasAccess.d.ts +9 -3
- package/dist/identity/hasAccess.js +32 -8
- package/dist/identity/index.d.ts +1 -0
- package/dist/identity/index.js +1 -0
- package/dist/identity/isValidToken.d.ts +12 -2
- package/dist/identity/isValidToken.js +25 -9
- package/dist/identity/roles.js +33 -7
- package/dist/identity/types.d.ts +6 -1
- package/dist/identity/types.js +1 -0
- package/dist/{assistants/LanguageModelProvider.js → identity/verifyAccessToken.d.ts} +10 -11
- package/dist/identity/verifyAccessToken.js +44 -0
- package/dist/index.d.ts +15 -2
- package/dist/index.js +18 -3
- package/dist/net/assertPublicDestination.d.ts +52 -0
- package/dist/net/assertPublicDestination.js +342 -0
- package/dist/{voice/StopSay.d.ts → net/index.d.ts} +1 -6
- package/dist/net/index.js +35 -0
- package/dist/notifications/createSendEmail.js +3 -1
- package/dist/protos/applications.proto +138 -3
- package/dist/protos/authz.proto +26 -4
- package/dist/protos/billing.proto +92 -0
- package/dist/protos/calls.proto +4 -0
- package/dist/protos/capabilities.proto +102 -0
- package/dist/protos/identity.proto +26 -1
- package/dist/protos/providers.proto +139 -0
- package/dist/protos/roomr.proto +146 -0
- package/dist/protos/session.proto +194 -0
- package/dist/protos/usage.proto +59 -0
- package/dist/protos/webhooks.proto +140 -0
- package/dist/{utils/types.d.ts → regions/hub/index.d.ts} +1 -5
- package/dist/regions/hub/index.js +35 -0
- package/dist/regions/hub/natsJwt.d.ts +63 -0
- package/dist/regions/hub/natsJwt.js +195 -0
- package/dist/registry/Registry.d.ts +87 -0
- package/dist/registry/Registry.js +432 -0
- package/dist/registry/cli.d.ts +20 -0
- package/dist/registry/cli.js +436 -0
- package/dist/registry/features.d.ts +31 -0
- package/dist/registry/features.js +38 -0
- package/dist/registry/index.d.ts +24 -0
- package/dist/registry/index.js +40 -0
- package/dist/registry/prisma.d.ts +67 -0
- package/dist/registry/prisma.js +399 -0
- package/dist/registry/stores.d.ts +21 -0
- package/dist/{assistants/languageModelConfigSchema.js → registry/stores.js} +55 -38
- package/dist/registry/types.d.ts +110 -0
- package/dist/{assistants/LanguageModelProvider.d.ts → registry/types.js} +6 -8
- package/dist/registry/workspaceKeys.d.ts +41 -0
- package/dist/registry/workspaceKeys.js +64 -0
- package/dist/roomr/health.d.ts +9 -0
- package/dist/{assistants/eventsHookSchema.js → roomr/health.js} +22 -18
- package/dist/roomr/index.d.ts +75 -0
- package/dist/roomr/index.js +146 -0
- package/dist/roomr/session.d.ts +133 -0
- package/dist/roomr/session.js +132 -0
- package/dist/session/index.d.ts +19 -0
- package/dist/session/index.js +35 -0
- package/dist/session/schema.d.ts +2140 -0
- package/dist/session/schema.js +448 -0
- package/dist/sessions/index.d.ts +96 -0
- package/dist/sessions/index.js +197 -0
- package/dist/telemetry.d.ts +76 -0
- package/dist/telemetry.js +360 -0
- package/dist/types.d.ts +3 -5
- package/dist/{voice/Gather.d.ts → usage/CallUsage.d.ts} +19 -18
- package/dist/usage/CallUsage.js +76 -0
- package/dist/usage/index.d.ts +22 -0
- package/dist/usage/index.js +38 -0
- package/dist/usage/meters.d.ts +113 -0
- package/dist/usage/meters.js +90 -0
- package/dist/usage/types.d.ts +159 -0
- package/dist/usage/types.js +84 -0
- package/dist/usage/usageId.d.ts +6 -0
- package/dist/usage/usageId.js +45 -0
- package/dist/utils/{findIntegrationsCredentials.js → WriteBehind.d.ts} +13 -10
- package/dist/utils/WriteBehind.js +64 -0
- package/dist/utils/index.d.ts +1 -3
- package/dist/utils/index.js +1 -3
- package/dist/utils/{createFetchSingleCallByCallId.d.ts → logUnhandledRejections.d.ts} +8 -4
- package/dist/{assistants/audioFiltersSchema.js → utils/logUnhandledRejections.js} +17 -12
- package/dist/utils/withErrorHandling.js +1 -1
- package/dist/validators/calls.d.ts +3 -0
- package/dist/validators/calls.js +12 -2
- package/dist/validators/identity.d.ts +37 -8
- package/dist/validators/identity.js +22 -3
- package/dist/validators/index.d.ts +1 -0
- package/dist/validators/index.js +1 -0
- package/dist/validators/sip.d.ts +40 -0
- package/dist/validators/sip.js +99 -0
- package/dist/validators/sipnet/credentials.d.ts +2 -2
- package/dist/validators/sipnet/domains.js +7 -7
- package/dist/validators/sipnet/trunks.d.ts +14 -14
- package/dist/validators/sipnet/trunks.js +4 -2
- package/dist/webhooks/Dispatcher.d.ts +87 -0
- package/dist/webhooks/Dispatcher.js +225 -0
- package/dist/webhooks/bus.d.ts +68 -0
- package/dist/webhooks/bus.js +178 -0
- package/dist/webhooks/events.d.ts +66 -0
- package/dist/webhooks/events.js +62 -0
- package/dist/webhooks/index.d.ts +23 -0
- package/dist/webhooks/index.js +39 -0
- package/dist/webhooks/prisma.d.ts +55 -0
- package/dist/webhooks/prisma.js +242 -0
- package/dist/webhooks/signing.d.ts +8 -0
- package/dist/webhooks/signing.js +53 -0
- package/package.json +25 -11
- package/schema/session.v1.json +871 -0
- package/dist/assistants/assistantSchema.d.ts +0 -739
- package/dist/assistants/assistantSchema.js +0 -37
- package/dist/assistants/conversationSettingsSchema.d.ts +0 -122
- package/dist/assistants/conversationSettingsSchema.js +0 -133
- package/dist/assistants/eventsHookSchema.d.ts +0 -38
- package/dist/assistants/languageModelConfigSchema.d.ts +0 -206
- package/dist/identity/tokenHasAccessKeyId.d.ts +0 -2
- package/dist/protos/voice.proto +0 -557
- package/dist/utils/createFetchSingleCallByCallId.js +0 -33
- package/dist/utils/findIntegrationsCredentials.d.ts +0 -23
- package/dist/utils/types.js +0 -2
- package/dist/voice/Dial.js +0 -20
- package/dist/voice/Gather.js +0 -9
- package/dist/voice/Mute.d.ts +0 -31
- package/dist/voice/Mute.js +0 -9
- package/dist/voice/Play.d.ts +0 -30
- package/dist/voice/Play.js +0 -2
- package/dist/voice/PlayDtmf.js +0 -2
- package/dist/voice/PlaybackControl.d.ts +0 -31
- package/dist/voice/PlaybackControl.js +0 -11
- package/dist/voice/Record.d.ts +0 -36
- package/dist/voice/Record.js +0 -7
- package/dist/voice/Say.d.ts +0 -28
- package/dist/voice/Say.js +0 -2
- package/dist/voice/StopSay.js +0 -2
- package/dist/voice/Stream.d.ts +0 -53
- package/dist/voice/Stream.js +0 -19
- package/dist/voice/StreamGather.d.ts +0 -34
- package/dist/voice/StreamGather.js +0 -9
- package/dist/voice/Verb.d.ts +0 -27
- package/dist/voice/Verb.js +0 -2
- package/dist/voice/voice.d.ts +0 -171
- package/dist/voice/voice.js +0 -65
- package/dist/{assistants → agents}/testCasesSchema.d.ts +4 -4
- /package/dist/{assistants → agents}/testCasesSchema.js +0 -0
- /package/dist/{assistants → agents}/tools/index.d.ts +0 -0
- /package/dist/{assistants → agents}/tools/index.js +0 -0
- /package/dist/{assistants → agents}/tools/propertySchema.d.ts +0 -0
- /package/dist/{assistants → agents}/tools/propertySchema.js +0 -0
- /package/dist/{assistants → agents}/tools/toolSchema.d.ts +0 -0
- /package/dist/{assistants → agents}/tools/toolSchema.js +0 -0
|
@@ -0,0 +1,399 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.PrismaUsageSource = exports.PrismaRegistryStore = void 0;
|
|
13
|
+
exports.openPrismaClient = openPrismaClient;
|
|
14
|
+
/**
|
|
15
|
+
* Copyright (C) 2025 by Fonoster Inc (https://fonoster.com)
|
|
16
|
+
* http://github.com/fonoster/fonoster
|
|
17
|
+
*
|
|
18
|
+
* This file is part of Fonoster
|
|
19
|
+
*
|
|
20
|
+
* Licensed under the MIT License (the "License");
|
|
21
|
+
* you may not use this file except in compliance with
|
|
22
|
+
* the License. You may obtain a copy of the License at
|
|
23
|
+
*
|
|
24
|
+
* https://opensource.org/licenses/MIT
|
|
25
|
+
*
|
|
26
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
27
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
28
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
29
|
+
* See the License for the specific language governing permissions and
|
|
30
|
+
* limitations under the License.
|
|
31
|
+
*/
|
|
32
|
+
const WriteBehind_1 = require("../utils/WriteBehind");
|
|
33
|
+
const stores_1 = require("./stores");
|
|
34
|
+
const toState = (s) => s.toUpperCase();
|
|
35
|
+
const fromState = (s) => s.toLowerCase();
|
|
36
|
+
const opt = (v) => (v === null ? undefined : v);
|
|
37
|
+
/** Drops undefined keys so loaded entries equal the ones the registry wrote. */
|
|
38
|
+
function clean(o) {
|
|
39
|
+
return Object.fromEntries(Object.entries(o).filter(([, v]) => v !== undefined));
|
|
40
|
+
}
|
|
41
|
+
class PrismaRegistryStore extends stores_1.MemoryRegistryStore {
|
|
42
|
+
constructor(prisma) {
|
|
43
|
+
super();
|
|
44
|
+
this.prisma = prisma;
|
|
45
|
+
this.writes = new WriteBehind_1.WriteBehind();
|
|
46
|
+
}
|
|
47
|
+
/** Opens the store with the current catalog and audit log loaded. */
|
|
48
|
+
static open(prisma) {
|
|
49
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
50
|
+
const store = new PrismaRegistryStore(prisma);
|
|
51
|
+
yield store.refresh();
|
|
52
|
+
return store;
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
/** Reloads the catalog (and audit log) from the database, after pending writes. */
|
|
56
|
+
refresh() {
|
|
57
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
58
|
+
yield this.writes.flush();
|
|
59
|
+
const [providers, models, voices, audit] = yield Promise.all([
|
|
60
|
+
this.prisma.registryProvider.findMany(),
|
|
61
|
+
this.prisma.registryModel.findMany(),
|
|
62
|
+
this.prisma.registryVoice.findMany({
|
|
63
|
+
include: { models: { orderBy: { position: "asc" } } }
|
|
64
|
+
}),
|
|
65
|
+
this.prisma.registryAudit.findMany({ orderBy: { seq: "asc" } })
|
|
66
|
+
]);
|
|
67
|
+
const entries = new Map();
|
|
68
|
+
for (const p of providers)
|
|
69
|
+
entries.set(p.id, clean({
|
|
70
|
+
kind: "provider",
|
|
71
|
+
id: p.id,
|
|
72
|
+
adapter: p.adapter,
|
|
73
|
+
capabilities: p.capabilities,
|
|
74
|
+
credentialRef: opt(p.credentialRef),
|
|
75
|
+
label: opt(p.label),
|
|
76
|
+
// Stored as {} when the provider names none.
|
|
77
|
+
endpoints: p.endpoints && Object.keys(p.endpoints).length
|
|
78
|
+
? p.endpoints
|
|
79
|
+
: undefined,
|
|
80
|
+
state: fromState(p.state),
|
|
81
|
+
replacement: opt(p.replacement),
|
|
82
|
+
retireOn: opt(p.retireOn)
|
|
83
|
+
}));
|
|
84
|
+
for (const m of models)
|
|
85
|
+
entries.set(m.id, clean({
|
|
86
|
+
kind: "model",
|
|
87
|
+
id: m.id,
|
|
88
|
+
label: opt(m.label),
|
|
89
|
+
type: m.type,
|
|
90
|
+
features: m.features,
|
|
91
|
+
languages: m.languages,
|
|
92
|
+
settings: m.settings,
|
|
93
|
+
state: fromState(m.state),
|
|
94
|
+
replacement: opt(m.replacement),
|
|
95
|
+
retireOn: opt(m.retireOn)
|
|
96
|
+
}));
|
|
97
|
+
for (const v of voices)
|
|
98
|
+
entries.set(v.id, clean({
|
|
99
|
+
kind: "voice",
|
|
100
|
+
id: v.id,
|
|
101
|
+
label: opt(v.label),
|
|
102
|
+
models: v.models.map((r) => r.modelId),
|
|
103
|
+
language: opt(v.language),
|
|
104
|
+
gender: opt(v.gender),
|
|
105
|
+
ownerWorkspace: opt(v.ownerWorkspace),
|
|
106
|
+
state: fromState(v.state),
|
|
107
|
+
replacement: opt(v.replacement),
|
|
108
|
+
retireOn: opt(v.retireOn)
|
|
109
|
+
}));
|
|
110
|
+
this.entries = entries;
|
|
111
|
+
this.log = audit.map((a) => clean({
|
|
112
|
+
at: a.at.toISOString(),
|
|
113
|
+
actor: a.actor,
|
|
114
|
+
action: a.action,
|
|
115
|
+
target: a.target,
|
|
116
|
+
details: opt(a.details)
|
|
117
|
+
}));
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
put(entry) {
|
|
121
|
+
var _a, _b, _c;
|
|
122
|
+
super.put(entry);
|
|
123
|
+
const e = JSON.parse(JSON.stringify(entry));
|
|
124
|
+
const common = {
|
|
125
|
+
label: (_a = e.label) !== null && _a !== void 0 ? _a : null,
|
|
126
|
+
state: toState(e.state),
|
|
127
|
+
replacement: (_b = e.replacement) !== null && _b !== void 0 ? _b : null,
|
|
128
|
+
retireOn: (_c = e.retireOn) !== null && _c !== void 0 ? _c : null
|
|
129
|
+
};
|
|
130
|
+
const provider = e.id.split("/")[0];
|
|
131
|
+
this.writes.push(() => __awaiter(this, void 0, void 0, function* () {
|
|
132
|
+
var _a, _b, _c, _d, _e;
|
|
133
|
+
if (e.kind === "provider") {
|
|
134
|
+
const data = Object.assign({ adapter: e.adapter, capabilities: e.capabilities, credentialRef: (_a = e.credentialRef) !== null && _a !== void 0 ? _a : null, endpoints: (_b = e.endpoints) !== null && _b !== void 0 ? _b : {} }, common);
|
|
135
|
+
yield this.prisma.registryProvider.upsert({
|
|
136
|
+
where: { id: e.id },
|
|
137
|
+
create: Object.assign({ id: e.id }, data),
|
|
138
|
+
update: data
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
else if (e.kind === "model") {
|
|
142
|
+
const data = Object.assign({ providerId: provider, type: e.type, features: e.features, languages: e.languages, settings: e.settings }, common);
|
|
143
|
+
yield this.prisma.registryModel.upsert({
|
|
144
|
+
where: { id: e.id },
|
|
145
|
+
create: Object.assign({ id: e.id }, data),
|
|
146
|
+
update: data
|
|
147
|
+
});
|
|
148
|
+
}
|
|
149
|
+
else {
|
|
150
|
+
const data = Object.assign({ providerId: provider, language: (_c = e.language) !== null && _c !== void 0 ? _c : null, gender: (_d = e.gender) !== null && _d !== void 0 ? _d : null, ownerWorkspace: (_e = e.ownerWorkspace) !== null && _e !== void 0 ? _e : null }, common);
|
|
151
|
+
yield this.prisma.$transaction([
|
|
152
|
+
this.prisma.registryVoice.upsert({
|
|
153
|
+
where: { id: e.id },
|
|
154
|
+
create: Object.assign({ id: e.id }, data),
|
|
155
|
+
update: data
|
|
156
|
+
}),
|
|
157
|
+
this.prisma.registryVoiceModel.deleteMany({
|
|
158
|
+
where: { voiceId: e.id }
|
|
159
|
+
}),
|
|
160
|
+
this.prisma.registryVoiceModel.createMany({
|
|
161
|
+
data: e.models.map((modelId, position) => ({
|
|
162
|
+
voiceId: e.id,
|
|
163
|
+
modelId,
|
|
164
|
+
position
|
|
165
|
+
}))
|
|
166
|
+
})
|
|
167
|
+
]);
|
|
168
|
+
}
|
|
169
|
+
}));
|
|
170
|
+
}
|
|
171
|
+
audit(entry) {
|
|
172
|
+
super.audit(entry);
|
|
173
|
+
this.writes.push(() => {
|
|
174
|
+
var _a;
|
|
175
|
+
return this.prisma.registryAudit.create({
|
|
176
|
+
data: {
|
|
177
|
+
at: new Date(entry.at),
|
|
178
|
+
actor: entry.actor,
|
|
179
|
+
action: entry.action,
|
|
180
|
+
target: entry.target,
|
|
181
|
+
details: (_a = entry.details) !== null && _a !== void 0 ? _a : undefined
|
|
182
|
+
}
|
|
183
|
+
});
|
|
184
|
+
});
|
|
185
|
+
}
|
|
186
|
+
/** Waits for every queued write; throws the first failure. */
|
|
187
|
+
flush() {
|
|
188
|
+
return this.writes.flush();
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
exports.PrismaRegistryStore = PrismaRegistryStore;
|
|
192
|
+
/**
|
|
193
|
+
* Usages of catalog ids in apps (speech defaults: voice, TTS and STT models) and agents (the
|
|
194
|
+
* Autopilot agent in an app's Intelligence config: `languageModel.model`, and
|
|
195
|
+
* `conversationSettings.voice`). Legacy rows with raw vendor names are not usages until migrated
|
|
196
|
+
* to catalog ids (task 5.1).
|
|
197
|
+
*/
|
|
198
|
+
class PrismaUsageSource {
|
|
199
|
+
constructor(prisma, options) {
|
|
200
|
+
this.prisma = prisma;
|
|
201
|
+
this.options = options;
|
|
202
|
+
this.rows = [];
|
|
203
|
+
this.origins = new WeakMap();
|
|
204
|
+
this.writes = new WriteBehind_1.WriteBehind();
|
|
205
|
+
/** Rewrites skipped because the config changed after it was read. */
|
|
206
|
+
this.conflicts = [];
|
|
207
|
+
}
|
|
208
|
+
static open(prisma_1) {
|
|
209
|
+
return __awaiter(this, arguments, void 0, function* (prisma, options = {}) {
|
|
210
|
+
const source = new PrismaUsageSource(prisma, options);
|
|
211
|
+
yield source.refresh();
|
|
212
|
+
return source;
|
|
213
|
+
});
|
|
214
|
+
}
|
|
215
|
+
refresh() {
|
|
216
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
217
|
+
yield this.writes.flush();
|
|
218
|
+
this.rows = yield this.prisma.application.findMany({
|
|
219
|
+
select: {
|
|
220
|
+
ref: true,
|
|
221
|
+
accessKeyId: true,
|
|
222
|
+
name: true,
|
|
223
|
+
speechVoice: true,
|
|
224
|
+
speechSttModel: true,
|
|
225
|
+
speechTtsModel: true,
|
|
226
|
+
speechSettings: true,
|
|
227
|
+
intelligence: { select: { config: true } }
|
|
228
|
+
},
|
|
229
|
+
orderBy: { ref: "asc" }
|
|
230
|
+
});
|
|
231
|
+
});
|
|
232
|
+
}
|
|
233
|
+
find(id) {
|
|
234
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j;
|
|
235
|
+
const out = [];
|
|
236
|
+
const add = (usage, origin) => {
|
|
237
|
+
this.origins.set(usage, origin);
|
|
238
|
+
out.push(usage);
|
|
239
|
+
};
|
|
240
|
+
for (const row of this.rows) {
|
|
241
|
+
const app = { kind: "app", ref: row.ref, name: row.name };
|
|
242
|
+
if (row.speechVoice === id || row.speechTtsModel === id) {
|
|
243
|
+
add({
|
|
244
|
+
workspace: row.accessKeyId,
|
|
245
|
+
config: app,
|
|
246
|
+
model: (_a = row.speechTtsModel) !== null && _a !== void 0 ? _a : undefined,
|
|
247
|
+
voice: (_b = row.speechVoice) !== null && _b !== void 0 ? _b : undefined,
|
|
248
|
+
settings: Object.keys((_c = row.speechSettings) !== null && _c !== void 0 ? _c : {}),
|
|
249
|
+
requires: ["streaming"]
|
|
250
|
+
}, { kind: "app-tts", row });
|
|
251
|
+
}
|
|
252
|
+
if (row.speechSttModel === id) {
|
|
253
|
+
add({
|
|
254
|
+
workspace: row.accessKeyId,
|
|
255
|
+
config: app,
|
|
256
|
+
model: id,
|
|
257
|
+
settings: [],
|
|
258
|
+
requires: ["streaming"]
|
|
259
|
+
}, { kind: "app-stt", row });
|
|
260
|
+
}
|
|
261
|
+
const agent = (_d = row.intelligence) === null || _d === void 0 ? void 0 : _d.config;
|
|
262
|
+
const llm = (_e = agent === null || agent === void 0 ? void 0 : agent.languageModel) === null || _e === void 0 ? void 0 : _e.model;
|
|
263
|
+
const config = {
|
|
264
|
+
kind: "agent",
|
|
265
|
+
ref: row.ref,
|
|
266
|
+
name: row.name
|
|
267
|
+
};
|
|
268
|
+
if (llm === id) {
|
|
269
|
+
add({
|
|
270
|
+
workspace: row.accessKeyId,
|
|
271
|
+
config,
|
|
272
|
+
model: llm,
|
|
273
|
+
settings: [],
|
|
274
|
+
requires: ((_g = (_f = agent === null || agent === void 0 ? void 0 : agent.languageModel) === null || _f === void 0 ? void 0 : _f.tools) === null || _g === void 0 ? void 0 : _g.length)
|
|
275
|
+
? ["streaming", "tool-calling"]
|
|
276
|
+
: ["streaming"]
|
|
277
|
+
}, { kind: "agent-llm", row, model: llm });
|
|
278
|
+
}
|
|
279
|
+
const voice = (_h = agent === null || agent === void 0 ? void 0 : agent.conversationSettings) === null || _h === void 0 ? void 0 : _h.voice;
|
|
280
|
+
if (voice === id) {
|
|
281
|
+
add({
|
|
282
|
+
workspace: row.accessKeyId,
|
|
283
|
+
config,
|
|
284
|
+
model: (_j = row.speechTtsModel) !== null && _j !== void 0 ? _j : undefined,
|
|
285
|
+
voice,
|
|
286
|
+
settings: [],
|
|
287
|
+
requires: ["streaming"]
|
|
288
|
+
}, { kind: "agent-voice", row, voice });
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
return out;
|
|
292
|
+
}
|
|
293
|
+
/**
|
|
294
|
+
* Queues the rewrite. The write only applies if the field still holds the value read; otherwise
|
|
295
|
+
* it is skipped, audited by the caller's flush report (`conflicts`), and the config keeps its id.
|
|
296
|
+
*/
|
|
297
|
+
rewrite(usage, change) {
|
|
298
|
+
var _a, _b;
|
|
299
|
+
const origin = this.origins.get(usage);
|
|
300
|
+
if (!origin)
|
|
301
|
+
return false;
|
|
302
|
+
const row = origin.row;
|
|
303
|
+
const conflict = (reason) => this.conflicts.push({ usage, reason });
|
|
304
|
+
if (origin.kind === "app-tts" || origin.kind === "app-stt") {
|
|
305
|
+
const where = { ref: row.ref };
|
|
306
|
+
const data = { updatedAt: new Date() };
|
|
307
|
+
if (origin.kind === "app-stt") {
|
|
308
|
+
where.speechSttModel = row.speechSttModel;
|
|
309
|
+
if (change.model)
|
|
310
|
+
data.speechSttModel = change.model;
|
|
311
|
+
}
|
|
312
|
+
else {
|
|
313
|
+
where.speechVoice = row.speechVoice;
|
|
314
|
+
where.speechTtsModel = row.speechTtsModel;
|
|
315
|
+
if (change.model)
|
|
316
|
+
data.speechTtsModel = change.model;
|
|
317
|
+
if (change.voice)
|
|
318
|
+
data.speechVoice = change.voice;
|
|
319
|
+
if (change.dropSettings.length && row.speechSettings) {
|
|
320
|
+
data.speechSettings = Object.fromEntries(Object.entries(row.speechSettings).filter(([k]) => !change.dropSettings.includes(k)));
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
this.writes.push(() => __awaiter(this, void 0, void 0, function* () {
|
|
324
|
+
const { count } = yield this.prisma.application.updateMany({
|
|
325
|
+
where,
|
|
326
|
+
data
|
|
327
|
+
});
|
|
328
|
+
if (count === 0)
|
|
329
|
+
conflict("app changed since it was read");
|
|
330
|
+
}));
|
|
331
|
+
return true;
|
|
332
|
+
}
|
|
333
|
+
const config = JSON.parse(JSON.stringify((_b = (_a = row.intelligence) === null || _a === void 0 ? void 0 : _a.config) !== null && _b !== void 0 ? _b : {}));
|
|
334
|
+
let path;
|
|
335
|
+
let expected;
|
|
336
|
+
if (origin.kind === "agent-llm") {
|
|
337
|
+
path = ["languageModel", "model"];
|
|
338
|
+
expected = origin.model;
|
|
339
|
+
if (change.model)
|
|
340
|
+
config.languageModel.model = change.model;
|
|
341
|
+
}
|
|
342
|
+
else {
|
|
343
|
+
path = ["conversationSettings", "voice"];
|
|
344
|
+
expected = origin.voice;
|
|
345
|
+
if (change.voice)
|
|
346
|
+
config.conversationSettings.voice = change.voice;
|
|
347
|
+
}
|
|
348
|
+
this.writes.push(() => __awaiter(this, void 0, void 0, function* () {
|
|
349
|
+
const { count } = yield this.prisma.intelligence.updateMany({
|
|
350
|
+
where: { applicationRef: row.ref, config: { path, equals: expected } },
|
|
351
|
+
data: { config }
|
|
352
|
+
});
|
|
353
|
+
if (count === 0)
|
|
354
|
+
conflict("agent changed since it was read");
|
|
355
|
+
else
|
|
356
|
+
yield this.prisma.application.update({
|
|
357
|
+
where: { ref: row.ref },
|
|
358
|
+
data: { updatedAt: new Date() }
|
|
359
|
+
});
|
|
360
|
+
}));
|
|
361
|
+
return true;
|
|
362
|
+
}
|
|
363
|
+
notify(workspace, notice) {
|
|
364
|
+
this.writes.push(() => __awaiter(this, void 0, void 0, function* () {
|
|
365
|
+
var _a, _b;
|
|
366
|
+
yield this.prisma.registryNotice.create({
|
|
367
|
+
data: {
|
|
368
|
+
accessKeyId: workspace,
|
|
369
|
+
type: String(notice.type),
|
|
370
|
+
data: notice
|
|
371
|
+
}
|
|
372
|
+
});
|
|
373
|
+
(_b = (_a = this.options).onNotice) === null || _b === void 0 ? void 0 : _b.call(_a, workspace, notice);
|
|
374
|
+
}));
|
|
375
|
+
}
|
|
376
|
+
/** Waits for every queued write; throws the first failure. */
|
|
377
|
+
flush() {
|
|
378
|
+
return this.writes.flush();
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
exports.PrismaUsageSource = PrismaUsageSource;
|
|
382
|
+
/**
|
|
383
|
+
* Opens a Prisma client generated from the apiserver's schema, with field encryption when a key
|
|
384
|
+
* is given. Loaded at run time so `@fonoster/common` does not depend on a generated client.
|
|
385
|
+
*/
|
|
386
|
+
function openPrismaClient(options) {
|
|
387
|
+
var _a, _b;
|
|
388
|
+
/* eslint-disable @typescript-eslint/no-var-requires */
|
|
389
|
+
const { PrismaClient, Prisma } = require((_b = (_a = options.clientModule) !== null && _a !== void 0 ? _a : process.env.FONOSTER_PRISMA_CLIENT) !== null && _b !== void 0 ? _b : "@prisma/client");
|
|
390
|
+
const client = new PrismaClient({ datasourceUrl: options.url });
|
|
391
|
+
if (!options.encryptionKey)
|
|
392
|
+
return client;
|
|
393
|
+
const { fieldEncryptionExtension } = require("prisma-field-encryption");
|
|
394
|
+
/* eslint-enable @typescript-eslint/no-var-requires */
|
|
395
|
+
return client.$extends(fieldEncryptionExtension({
|
|
396
|
+
encryptionKey: options.encryptionKey,
|
|
397
|
+
dmmf: Prisma === null || Prisma === void 0 ? void 0 : Prisma.dmmf
|
|
398
|
+
}));
|
|
399
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { AuditEntry, CatalogEntry, RegistryStore } from "./types";
|
|
2
|
+
export declare class MemoryRegistryStore implements RegistryStore {
|
|
3
|
+
protected entries: Map<string, CatalogEntry>;
|
|
4
|
+
protected log: AuditEntry[];
|
|
5
|
+
all(): CatalogEntry[];
|
|
6
|
+
get(id: string): CatalogEntry;
|
|
7
|
+
put(entry: CatalogEntry): void;
|
|
8
|
+
audit(entry: AuditEntry): void;
|
|
9
|
+
history(id?: string): AuditEntry[];
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* A JSON file store, for the operator utility until the registry tables exist (see build-log.md).
|
|
13
|
+
* Every write rewrites the file atomically.
|
|
14
|
+
*/
|
|
15
|
+
export declare class FileRegistryStore extends MemoryRegistryStore {
|
|
16
|
+
private readonly file;
|
|
17
|
+
constructor(file: string);
|
|
18
|
+
put(entry: CatalogEntry): void;
|
|
19
|
+
audit(entry: AuditEntry): void;
|
|
20
|
+
private save;
|
|
21
|
+
}
|
|
@@ -33,7 +33,7 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
33
33
|
};
|
|
34
34
|
})();
|
|
35
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
-
exports.
|
|
36
|
+
exports.FileRegistryStore = exports.MemoryRegistryStore = void 0;
|
|
37
37
|
/**
|
|
38
38
|
* Copyright (C) 2025 by Fonoster Inc (https://fonoster.com)
|
|
39
39
|
* http://github.com/fonoster/fonoster
|
|
@@ -52,40 +52,57 @@ exports.languageModelConfigSchema = void 0;
|
|
|
52
52
|
* See the License for the specific language governing permissions and
|
|
53
53
|
* limitations under the License.
|
|
54
54
|
*/
|
|
55
|
-
const
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
.
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
.
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
55
|
+
const fs = __importStar(require("fs"));
|
|
56
|
+
class MemoryRegistryStore {
|
|
57
|
+
constructor() {
|
|
58
|
+
this.entries = new Map();
|
|
59
|
+
this.log = [];
|
|
60
|
+
}
|
|
61
|
+
all() {
|
|
62
|
+
return [...this.entries.values()].sort((a, b) => a.id.localeCompare(b.id));
|
|
63
|
+
}
|
|
64
|
+
get(id) {
|
|
65
|
+
return this.entries.get(id);
|
|
66
|
+
}
|
|
67
|
+
put(entry) {
|
|
68
|
+
this.entries.set(entry.id, JSON.parse(JSON.stringify(entry)));
|
|
69
|
+
}
|
|
70
|
+
audit(entry) {
|
|
71
|
+
this.log.push(entry);
|
|
72
|
+
}
|
|
73
|
+
history(id) {
|
|
74
|
+
return id ? this.log.filter((e) => e.target === id) : [...this.log];
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
exports.MemoryRegistryStore = MemoryRegistryStore;
|
|
78
|
+
/**
|
|
79
|
+
* A JSON file store, for the operator utility until the registry tables exist (see build-log.md).
|
|
80
|
+
* Every write rewrites the file atomically.
|
|
81
|
+
*/
|
|
82
|
+
class FileRegistryStore extends MemoryRegistryStore {
|
|
83
|
+
constructor(file) {
|
|
84
|
+
var _a;
|
|
85
|
+
super();
|
|
86
|
+
this.file = file;
|
|
87
|
+
if (fs.existsSync(file)) {
|
|
88
|
+
const data = JSON.parse(fs.readFileSync(file, "utf8"));
|
|
89
|
+
for (const e of data.entries)
|
|
90
|
+
this.entries.set(e.id, e);
|
|
91
|
+
this.log = (_a = data.audit) !== null && _a !== void 0 ? _a : [];
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
put(entry) {
|
|
95
|
+
super.put(entry);
|
|
96
|
+
this.save();
|
|
97
|
+
}
|
|
98
|
+
audit(entry) {
|
|
99
|
+
super.audit(entry);
|
|
100
|
+
this.save();
|
|
101
|
+
}
|
|
102
|
+
save() {
|
|
103
|
+
const tmp = `${this.file}.tmp`;
|
|
104
|
+
fs.writeFileSync(tmp, JSON.stringify({ entries: this.all(), audit: this.log }, null, 2));
|
|
105
|
+
fs.renameSync(tmp, this.file);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
exports.FileRegistryStore = FileRegistryStore;
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (C) 2025 by Fonoster Inc (https://fonoster.com)
|
|
3
|
+
* http://github.com/fonoster/fonoster
|
|
4
|
+
*
|
|
5
|
+
* This file is part of Fonoster
|
|
6
|
+
*
|
|
7
|
+
* Licensed under the MIT License (the "License");
|
|
8
|
+
* you may not use this file except in compliance with
|
|
9
|
+
* the License. You may obtain a copy of the License at
|
|
10
|
+
*
|
|
11
|
+
* https://opensource.org/licenses/MIT
|
|
12
|
+
*
|
|
13
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
14
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
15
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
16
|
+
* See the License for the specific language governing permissions and
|
|
17
|
+
* limitations under the License.
|
|
18
|
+
*/
|
|
19
|
+
export type Lifecycle = "active" | "deprecated" | "retired";
|
|
20
|
+
/** What a provider or model serves: speech, language models, or noise cancelling (`nc`). */
|
|
21
|
+
export type Capability = "stt" | "tts" | "llm" | "nc";
|
|
22
|
+
export declare const CAPABILITIES: Capability[];
|
|
23
|
+
export type ItemKind = "provider" | "model" | "voice";
|
|
24
|
+
/** Where a provider serves each capability; services use these unless their config overrides. */
|
|
25
|
+
export type ProviderEndpoints = Partial<Record<Capability, string>>;
|
|
26
|
+
export type ProviderEntry = {
|
|
27
|
+
kind: "provider";
|
|
28
|
+
id: string;
|
|
29
|
+
/** A display name ("Deepgram"); the dashboard shows the id without one. */
|
|
30
|
+
label?: string;
|
|
31
|
+
adapter: string;
|
|
32
|
+
capabilities: Capability[];
|
|
33
|
+
/** The platform credential's name; omitted for a keyless provider (no key needed). */
|
|
34
|
+
credentialRef?: string;
|
|
35
|
+
endpoints?: ProviderEndpoints;
|
|
36
|
+
state: Lifecycle;
|
|
37
|
+
replacement?: string;
|
|
38
|
+
retireOn?: string;
|
|
39
|
+
};
|
|
40
|
+
export type ModelEntry = {
|
|
41
|
+
kind: "model";
|
|
42
|
+
id: string;
|
|
43
|
+
/** A display name ("Nova 3"); the dashboard shows the id without one. */
|
|
44
|
+
label?: string;
|
|
45
|
+
type: Capability;
|
|
46
|
+
features: string[];
|
|
47
|
+
languages: string[];
|
|
48
|
+
/** Settings the model accepts (for example "style", "stability"). */
|
|
49
|
+
settings: string[];
|
|
50
|
+
state: Lifecycle;
|
|
51
|
+
replacement?: string;
|
|
52
|
+
retireOn?: string;
|
|
53
|
+
};
|
|
54
|
+
export type VoiceEntry = {
|
|
55
|
+
kind: "voice";
|
|
56
|
+
id: string;
|
|
57
|
+
/** A display name ("Aura 2 Thalia"); the dashboard shows the id without one. */
|
|
58
|
+
label?: string;
|
|
59
|
+
models: string[];
|
|
60
|
+
language?: string;
|
|
61
|
+
gender?: string;
|
|
62
|
+
/** Set for a workspace's own (cloned) voice. */
|
|
63
|
+
ownerWorkspace?: string;
|
|
64
|
+
state: Lifecycle;
|
|
65
|
+
replacement?: string;
|
|
66
|
+
retireOn?: string;
|
|
67
|
+
};
|
|
68
|
+
export type CatalogEntry = ProviderEntry | ModelEntry | VoiceEntry;
|
|
69
|
+
export type AuditEntry = {
|
|
70
|
+
at: string;
|
|
71
|
+
actor: string;
|
|
72
|
+
action: string;
|
|
73
|
+
target: string;
|
|
74
|
+
details?: Record<string, unknown>;
|
|
75
|
+
};
|
|
76
|
+
/** One place a catalog id is used: an app's speech config or an agent's model config. */
|
|
77
|
+
export type Usage = {
|
|
78
|
+
workspace: string;
|
|
79
|
+
config: {
|
|
80
|
+
kind: "app" | "agent";
|
|
81
|
+
ref: string;
|
|
82
|
+
name: string;
|
|
83
|
+
};
|
|
84
|
+
model?: string;
|
|
85
|
+
voice?: string;
|
|
86
|
+
/** Settings the config sets on the model (dropped when the replacement does not accept them). */
|
|
87
|
+
settings: string[];
|
|
88
|
+
/** Hard features the config needs (derived from its content, e.g. tools need tool-calling). */
|
|
89
|
+
requires: string[];
|
|
90
|
+
};
|
|
91
|
+
/** Where usages come from (apps and agents in the control-plane database). */
|
|
92
|
+
export interface UsageSource {
|
|
93
|
+
find(id: string): Usage[];
|
|
94
|
+
/** Rewrites one config; returns false if it changed since it was read. */
|
|
95
|
+
rewrite(usage: Usage, change: {
|
|
96
|
+
model?: string;
|
|
97
|
+
voice?: string;
|
|
98
|
+
dropSettings: string[];
|
|
99
|
+
}): boolean;
|
|
100
|
+
/** Tells a workspace about a change (dashboard notice). */
|
|
101
|
+
notify(workspace: string, notice: Record<string, unknown>): void;
|
|
102
|
+
}
|
|
103
|
+
/** Where the catalog and the audit log are kept. */
|
|
104
|
+
export interface RegistryStore {
|
|
105
|
+
all(): CatalogEntry[];
|
|
106
|
+
get(id: string): CatalogEntry | undefined;
|
|
107
|
+
put(entry: CatalogEntry): void;
|
|
108
|
+
audit(entry: AuditEntry): void;
|
|
109
|
+
history(id?: string): AuditEntry[];
|
|
110
|
+
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
"use strict";
|
|
1
2
|
/**
|
|
2
3
|
* Copyright (C) 2025 by Fonoster Inc (https://fonoster.com)
|
|
3
4
|
* http://github.com/fonoster/fonoster
|
|
@@ -16,11 +17,8 @@
|
|
|
16
17
|
* See the License for the specific language governing permissions and
|
|
17
18
|
* limitations under the License.
|
|
18
19
|
*/
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
ANTHROPIC = "anthropic"
|
|
25
|
-
}
|
|
26
|
-
export { LanguageModelProvider };
|
|
20
|
+
// The provider registry (add-provider-registry): providers, models and voices by catalog id,
|
|
21
|
+
// with a manual lifecycle. The catalog never holds a secret: providers name a credentialRef.
|
|
22
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
23
|
+
exports.CAPABILITIES = void 0;
|
|
24
|
+
exports.CAPABILITIES = ["stt", "tts", "llm", "nc"];
|