@uncensoredcode/openbridge 0.1.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/README.md +117 -0
- package/bin/openbridge.js +10 -0
- package/package.json +85 -0
- package/packages/cli/dist/args.d.ts +30 -0
- package/packages/cli/dist/args.js +160 -0
- package/packages/cli/dist/cli.d.ts +2 -0
- package/packages/cli/dist/cli.js +9 -0
- package/packages/cli/dist/index.d.ts +26 -0
- package/packages/cli/dist/index.js +76 -0
- package/packages/runtime/dist/assistant-protocol.d.ts +34 -0
- package/packages/runtime/dist/assistant-protocol.js +121 -0
- package/packages/runtime/dist/execution/in-process.d.ts +14 -0
- package/packages/runtime/dist/execution/in-process.js +45 -0
- package/packages/runtime/dist/execution/types.d.ts +49 -0
- package/packages/runtime/dist/execution/types.js +20 -0
- package/packages/runtime/dist/index.d.ts +86 -0
- package/packages/runtime/dist/index.js +60 -0
- package/packages/runtime/dist/normalizers/index.d.ts +6 -0
- package/packages/runtime/dist/normalizers/index.js +12 -0
- package/packages/runtime/dist/normalizers/legacy-packet.d.ts +6 -0
- package/packages/runtime/dist/normalizers/legacy-packet.js +131 -0
- package/packages/runtime/dist/output-sanitizer.d.ts +23 -0
- package/packages/runtime/dist/output-sanitizer.js +78 -0
- package/packages/runtime/dist/packet-extractor.d.ts +17 -0
- package/packages/runtime/dist/packet-extractor.js +43 -0
- package/packages/runtime/dist/packet-normalizer.d.ts +21 -0
- package/packages/runtime/dist/packet-normalizer.js +47 -0
- package/packages/runtime/dist/prompt-compiler.d.ts +28 -0
- package/packages/runtime/dist/prompt-compiler.js +301 -0
- package/packages/runtime/dist/protocol.d.ts +44 -0
- package/packages/runtime/dist/protocol.js +165 -0
- package/packages/runtime/dist/provider-failure.d.ts +52 -0
- package/packages/runtime/dist/provider-failure.js +236 -0
- package/packages/runtime/dist/provider.d.ts +40 -0
- package/packages/runtime/dist/provider.js +1 -0
- package/packages/runtime/dist/runtime.d.ts +86 -0
- package/packages/runtime/dist/runtime.js +462 -0
- package/packages/runtime/dist/session-bound-provider.d.ts +52 -0
- package/packages/runtime/dist/session-bound-provider.js +366 -0
- package/packages/runtime/dist/tool-name-aliases.d.ts +5 -0
- package/packages/runtime/dist/tool-name-aliases.js +13 -0
- package/packages/runtime/dist/tools/bash.d.ts +9 -0
- package/packages/runtime/dist/tools/bash.js +157 -0
- package/packages/runtime/dist/tools/edit.d.ts +9 -0
- package/packages/runtime/dist/tools/edit.js +94 -0
- package/packages/runtime/dist/tools/index.d.ts +39 -0
- package/packages/runtime/dist/tools/index.js +27 -0
- package/packages/runtime/dist/tools/list-dir.d.ts +9 -0
- package/packages/runtime/dist/tools/list-dir.js +127 -0
- package/packages/runtime/dist/tools/read.d.ts +9 -0
- package/packages/runtime/dist/tools/read.js +56 -0
- package/packages/runtime/dist/tools/registry.d.ts +15 -0
- package/packages/runtime/dist/tools/registry.js +38 -0
- package/packages/runtime/dist/tools/runtime-path.d.ts +7 -0
- package/packages/runtime/dist/tools/runtime-path.js +22 -0
- package/packages/runtime/dist/tools/search-files.d.ts +9 -0
- package/packages/runtime/dist/tools/search-files.js +149 -0
- package/packages/runtime/dist/tools/text-file.d.ts +32 -0
- package/packages/runtime/dist/tools/text-file.js +101 -0
- package/packages/runtime/dist/tools/workspace-path.d.ts +17 -0
- package/packages/runtime/dist/tools/workspace-path.js +70 -0
- package/packages/runtime/dist/tools/write.d.ts +9 -0
- package/packages/runtime/dist/tools/write.js +59 -0
- package/packages/server/dist/bridge/bridge-model-catalog.d.ts +56 -0
- package/packages/server/dist/bridge/bridge-model-catalog.js +100 -0
- package/packages/server/dist/bridge/bridge-runtime-service.d.ts +61 -0
- package/packages/server/dist/bridge/bridge-runtime-service.js +1386 -0
- package/packages/server/dist/bridge/chat-completions/chat-completion-service.d.ts +127 -0
- package/packages/server/dist/bridge/chat-completions/chat-completion-service.js +1026 -0
- package/packages/server/dist/bridge/index.d.ts +335 -0
- package/packages/server/dist/bridge/index.js +45 -0
- package/packages/server/dist/bridge/live-provider-extraction-canary.d.ts +69 -0
- package/packages/server/dist/bridge/live-provider-extraction-canary.js +186 -0
- package/packages/server/dist/bridge/providers/generic-provider-transport.d.ts +53 -0
- package/packages/server/dist/bridge/providers/generic-provider-transport.js +973 -0
- package/packages/server/dist/bridge/providers/provider-session-resolver.d.ts +17 -0
- package/packages/server/dist/bridge/providers/provider-session-resolver.js +95 -0
- package/packages/server/dist/bridge/providers/provider-streams.d.ts +80 -0
- package/packages/server/dist/bridge/providers/provider-streams.js +844 -0
- package/packages/server/dist/bridge/providers/provider-transport-profile.d.ts +194 -0
- package/packages/server/dist/bridge/providers/provider-transport-profile.js +198 -0
- package/packages/server/dist/bridge/providers/web-provider-transport.d.ts +30 -0
- package/packages/server/dist/bridge/providers/web-provider-transport.js +151 -0
- package/packages/server/dist/bridge/state/file-bridge-state-store.d.ts +36 -0
- package/packages/server/dist/bridge/state/file-bridge-state-store.js +164 -0
- package/packages/server/dist/bridge/stores/local-session-package-store.d.ts +23 -0
- package/packages/server/dist/bridge/stores/local-session-package-store.js +548 -0
- package/packages/server/dist/bridge/stores/provider-store.d.ts +94 -0
- package/packages/server/dist/bridge/stores/provider-store.js +143 -0
- package/packages/server/dist/bridge/stores/session-backed-provider-store.d.ts +7 -0
- package/packages/server/dist/bridge/stores/session-backed-provider-store.js +26 -0
- package/packages/server/dist/bridge/stores/session-package-store.d.ts +286 -0
- package/packages/server/dist/bridge/stores/session-package-store.js +1527 -0
- package/packages/server/dist/bridge/stores/session-store.d.ts +120 -0
- package/packages/server/dist/bridge/stores/session-store.js +139 -0
- package/packages/server/dist/cli/index.d.ts +9 -0
- package/packages/server/dist/cli/index.js +6 -0
- package/packages/server/dist/cli/main.d.ts +2 -0
- package/packages/server/dist/cli/main.js +9 -0
- package/packages/server/dist/cli/run-bridge-server-cli.d.ts +54 -0
- package/packages/server/dist/cli/run-bridge-server-cli.js +371 -0
- package/packages/server/dist/client/bridge-api-client.d.ts +61 -0
- package/packages/server/dist/client/bridge-api-client.js +267 -0
- package/packages/server/dist/client/index.d.ts +11 -0
- package/packages/server/dist/client/index.js +11 -0
- package/packages/server/dist/config/bridge-server-config.d.ts +52 -0
- package/packages/server/dist/config/bridge-server-config.js +118 -0
- package/packages/server/dist/config/index.d.ts +20 -0
- package/packages/server/dist/config/index.js +8 -0
- package/packages/server/dist/http/bridge-api-route-context.d.ts +14 -0
- package/packages/server/dist/http/bridge-api-route-context.js +1 -0
- package/packages/server/dist/http/create-bridge-api-server.d.ts +72 -0
- package/packages/server/dist/http/create-bridge-api-server.js +225 -0
- package/packages/server/dist/http/index.d.ts +5 -0
- package/packages/server/dist/http/index.js +5 -0
- package/packages/server/dist/http/parse-request.d.ts +6 -0
- package/packages/server/dist/http/parse-request.js +27 -0
- package/packages/server/dist/http/register-bridge-api-routes.d.ts +7 -0
- package/packages/server/dist/http/register-bridge-api-routes.js +17 -0
- package/packages/server/dist/http/routes/admin-routes.d.ts +7 -0
- package/packages/server/dist/http/routes/admin-routes.js +135 -0
- package/packages/server/dist/http/routes/chat-completions-route.d.ts +7 -0
- package/packages/server/dist/http/routes/chat-completions-route.js +49 -0
- package/packages/server/dist/http/routes/health-routes.d.ts +6 -0
- package/packages/server/dist/http/routes/health-routes.js +7 -0
- package/packages/server/dist/http/routes/message-routes.d.ts +7 -0
- package/packages/server/dist/http/routes/message-routes.js +7 -0
- package/packages/server/dist/index.d.ts +85 -0
- package/packages/server/dist/index.js +28 -0
- package/packages/server/dist/security/bridge-auth.d.ts +9 -0
- package/packages/server/dist/security/bridge-auth.js +41 -0
- package/packages/server/dist/security/cors-policy.d.ts +5 -0
- package/packages/server/dist/security/cors-policy.js +34 -0
- package/packages/server/dist/security/index.d.ts +16 -0
- package/packages/server/dist/security/index.js +12 -0
- package/packages/server/dist/security/redact-sensitive-values.d.ts +19 -0
- package/packages/server/dist/security/redact-sensitive-values.js +67 -0
- package/packages/server/dist/shared/api-schema.d.ts +133 -0
- package/packages/server/dist/shared/api-schema.js +1 -0
- package/packages/server/dist/shared/bridge-api-error.d.ts +17 -0
- package/packages/server/dist/shared/bridge-api-error.js +19 -0
- package/packages/server/dist/shared/index.d.ts +7 -0
- package/packages/server/dist/shared/index.js +7 -0
- package/packages/server/dist/shared/output.d.ts +5 -0
- package/packages/server/dist/shared/output.js +14 -0
|
@@ -0,0 +1,1527 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { bridgeApiErrorModule } from "../../shared/bridge-api-error.js";
|
|
3
|
+
import { providerStoreModule } from "./provider-store.js";
|
|
4
|
+
const { createProviderRequestSchema, providerDeleteResponseSchema, providerSchema } = providerStoreModule;
|
|
5
|
+
const { BridgeApiError } = bridgeApiErrorModule;
|
|
6
|
+
const nonEmptyString = (field) => z.string().trim().min(1, `${field} is required.`);
|
|
7
|
+
const looseObjectSchema = z.object({}).catchall(z.unknown());
|
|
8
|
+
const sessionPackageLifecycleStatusSchema = z.enum(["active", "expired", "revoked", "invalid"]);
|
|
9
|
+
const transportFamilySchema = z.enum(["http-sse", "http-json", "http-connect"]);
|
|
10
|
+
const transportPackageSchema = z
|
|
11
|
+
.object({
|
|
12
|
+
family: transportFamilySchema,
|
|
13
|
+
prompt: looseObjectSchema.optional(),
|
|
14
|
+
binding: looseObjectSchema.optional(),
|
|
15
|
+
session: looseObjectSchema.optional(),
|
|
16
|
+
request: looseObjectSchema.optional(),
|
|
17
|
+
response: looseObjectSchema.optional(),
|
|
18
|
+
seedBinding: looseObjectSchema.optional(),
|
|
19
|
+
bootstrap: looseObjectSchema.optional(),
|
|
20
|
+
preflight: looseObjectSchema.optional()
|
|
21
|
+
})
|
|
22
|
+
.strict();
|
|
23
|
+
const integrationPackageSchema = z
|
|
24
|
+
.object({
|
|
25
|
+
label: nonEmptyString("label").optional(),
|
|
26
|
+
enabled: z.boolean().optional(),
|
|
27
|
+
models: z.array(nonEmptyString("model")).optional(),
|
|
28
|
+
defaultModel: nonEmptyString("defaultModel").optional()
|
|
29
|
+
})
|
|
30
|
+
.strict();
|
|
31
|
+
const sessionPackageSchema = z
|
|
32
|
+
.object({
|
|
33
|
+
schemaVersion: z.number().int().min(1).optional(),
|
|
34
|
+
source: nonEmptyString("source"),
|
|
35
|
+
capturedAt: z.string().datetime({ offset: true }),
|
|
36
|
+
origin: z.string().url(),
|
|
37
|
+
cookies: z.array(looseObjectSchema).default([]),
|
|
38
|
+
localStorage: looseObjectSchema.default({}),
|
|
39
|
+
sessionStorage: looseObjectSchema.default({}),
|
|
40
|
+
headers: looseObjectSchema.default({}),
|
|
41
|
+
metadata: looseObjectSchema.default({}),
|
|
42
|
+
integration: integrationPackageSchema.optional(),
|
|
43
|
+
transport: transportPackageSchema.optional()
|
|
44
|
+
})
|
|
45
|
+
.strict();
|
|
46
|
+
const sessionPackageStatusResponseSchema = z
|
|
47
|
+
.object({
|
|
48
|
+
ok: z.literal(true),
|
|
49
|
+
providerId: nonEmptyString("providerId"),
|
|
50
|
+
hasSessionPackage: z.boolean(),
|
|
51
|
+
source: nonEmptyString("source").optional(),
|
|
52
|
+
capturedAt: z.string().datetime({ offset: true }).optional(),
|
|
53
|
+
origin: z.string().url().optional()
|
|
54
|
+
})
|
|
55
|
+
.strict();
|
|
56
|
+
const sessionPackageDeleteResponseSchema = z
|
|
57
|
+
.object({
|
|
58
|
+
ok: z.literal(true),
|
|
59
|
+
providerId: nonEmptyString("providerId")
|
|
60
|
+
})
|
|
61
|
+
.strict();
|
|
62
|
+
const sessionPackageMetadataSchema = z
|
|
63
|
+
.object({
|
|
64
|
+
handle: nonEmptyString("handle"),
|
|
65
|
+
providerId: nonEmptyString("providerId"),
|
|
66
|
+
source: nonEmptyString("source").optional(),
|
|
67
|
+
capturedAt: z.string().datetime({ offset: true }).optional(),
|
|
68
|
+
origin: z.string().url().optional(),
|
|
69
|
+
hasSessionPackage: z.boolean(),
|
|
70
|
+
createdAt: z.string().datetime({ offset: true }),
|
|
71
|
+
lastUsedAt: z.string().datetime({ offset: true }).optional(),
|
|
72
|
+
lastVerifiedAt: z.string().datetime({ offset: true }).optional(),
|
|
73
|
+
idleExpiresAt: z.string().datetime({ offset: true }).optional(),
|
|
74
|
+
absoluteExpiresAt: z.string().datetime({ offset: true }).optional(),
|
|
75
|
+
status: sessionPackageLifecycleStatusSchema,
|
|
76
|
+
version: z.number().int().min(1)
|
|
77
|
+
})
|
|
78
|
+
.strict();
|
|
79
|
+
const installedProviderPackageSchema = z
|
|
80
|
+
.object({
|
|
81
|
+
provider: providerSchema,
|
|
82
|
+
session: sessionPackageSchema.nullable()
|
|
83
|
+
})
|
|
84
|
+
.strict();
|
|
85
|
+
function createInMemorySessionPackageStore() {
|
|
86
|
+
const packages = new Map();
|
|
87
|
+
const metadata = new Map();
|
|
88
|
+
const store = {
|
|
89
|
+
listProviders() {
|
|
90
|
+
return [...packages.values()]
|
|
91
|
+
.map((entry) => cloneProvider(entry.provider))
|
|
92
|
+
.sort((left, right) => left.id.localeCompare(right.id));
|
|
93
|
+
},
|
|
94
|
+
getProvider(providerId) {
|
|
95
|
+
const stored = packages.get(providerId);
|
|
96
|
+
return stored ? cloneProvider(stored.provider) : null;
|
|
97
|
+
},
|
|
98
|
+
createProvider(input) {
|
|
99
|
+
if (packages.has(input.id)) {
|
|
100
|
+
throw new BridgeApiError({
|
|
101
|
+
statusCode: 409,
|
|
102
|
+
code: "provider_exists",
|
|
103
|
+
message: `Provider '${input.id}' already exists.`
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
const timestamp = createTimestamp();
|
|
107
|
+
const provider = providerSchema.parse({
|
|
108
|
+
...createProviderRequestSchema.parse(input),
|
|
109
|
+
createdAt: timestamp,
|
|
110
|
+
updatedAt: timestamp
|
|
111
|
+
});
|
|
112
|
+
packages.set(provider.id, installedProviderPackageSchema.parse({
|
|
113
|
+
provider,
|
|
114
|
+
session: null
|
|
115
|
+
}));
|
|
116
|
+
metadata.set(provider.id, buildSessionPackageMetadata(provider.id, null, {
|
|
117
|
+
existing: metadata.get(provider.id) ?? null,
|
|
118
|
+
now: timestamp
|
|
119
|
+
}));
|
|
120
|
+
return cloneProvider(provider);
|
|
121
|
+
},
|
|
122
|
+
updateProvider(providerId, patch) {
|
|
123
|
+
const stored = packages.get(providerId);
|
|
124
|
+
if (!stored) {
|
|
125
|
+
throw missingProviderError(providerId);
|
|
126
|
+
}
|
|
127
|
+
const nextProvider = providerSchema.parse({
|
|
128
|
+
...stored.provider,
|
|
129
|
+
...patch,
|
|
130
|
+
config: patch.config === undefined ? stored.provider.config : cloneConfig(patch.config),
|
|
131
|
+
updatedAt: createTimestamp(stored.provider.updatedAt)
|
|
132
|
+
});
|
|
133
|
+
const nextPackage = installedProviderPackageSchema.parse({
|
|
134
|
+
provider: nextProvider,
|
|
135
|
+
session: stored.session ? cloneSessionPackage(stored.session) : null
|
|
136
|
+
});
|
|
137
|
+
packages.set(providerId, nextPackage);
|
|
138
|
+
metadata.set(providerId, buildSessionPackageMetadata(providerId, nextPackage.session, {
|
|
139
|
+
existing: metadata.get(providerId) ?? null,
|
|
140
|
+
now: nextProvider.updatedAt
|
|
141
|
+
}));
|
|
142
|
+
return cloneProvider(nextProvider);
|
|
143
|
+
},
|
|
144
|
+
get(providerId) {
|
|
145
|
+
const stored = packages.get(providerId)?.session;
|
|
146
|
+
return stored ? cloneSessionPackage(stored) : null;
|
|
147
|
+
},
|
|
148
|
+
getStatus(providerId) {
|
|
149
|
+
const stored = metadata.get(providerId);
|
|
150
|
+
return stored ? cloneSessionPackageMetadata(stored) : null;
|
|
151
|
+
},
|
|
152
|
+
put(providerId, value) {
|
|
153
|
+
const normalized = cloneSessionPackage(value);
|
|
154
|
+
const existing = packages.get(providerId);
|
|
155
|
+
const now = createTimestamp(existing?.provider.updatedAt);
|
|
156
|
+
const provider = inferProviderFromSessionPackage({
|
|
157
|
+
providerId,
|
|
158
|
+
value: normalized,
|
|
159
|
+
existing: existing?.provider ?? null,
|
|
160
|
+
now
|
|
161
|
+
});
|
|
162
|
+
packages.set(providerId, installedProviderPackageSchema.parse({
|
|
163
|
+
provider,
|
|
164
|
+
session: normalized
|
|
165
|
+
}));
|
|
166
|
+
const nextMetadata = buildSessionPackageMetadata(providerId, normalized, {
|
|
167
|
+
existing: metadata.get(providerId) ?? null,
|
|
168
|
+
now
|
|
169
|
+
});
|
|
170
|
+
metadata.set(providerId, nextMetadata);
|
|
171
|
+
return cloneSessionPackageMetadata(nextMetadata);
|
|
172
|
+
},
|
|
173
|
+
delete(providerId) {
|
|
174
|
+
if (!packages.delete(providerId)) {
|
|
175
|
+
throw missingProviderError(providerId);
|
|
176
|
+
}
|
|
177
|
+
metadata.delete(providerId);
|
|
178
|
+
return sessionPackageDeleteResponseSchema.parse({
|
|
179
|
+
ok: true,
|
|
180
|
+
providerId
|
|
181
|
+
});
|
|
182
|
+
},
|
|
183
|
+
deleteSession(providerId) {
|
|
184
|
+
const stored = packages.get(providerId);
|
|
185
|
+
if (!stored) {
|
|
186
|
+
throw missingProviderError(providerId);
|
|
187
|
+
}
|
|
188
|
+
packages.set(providerId, installedProviderPackageSchema.parse({
|
|
189
|
+
provider: cloneProvider(stored.provider),
|
|
190
|
+
session: null
|
|
191
|
+
}));
|
|
192
|
+
const now = createTimestamp(stored.provider.updatedAt);
|
|
193
|
+
metadata.set(providerId, buildSessionPackageMetadata(providerId, null, {
|
|
194
|
+
existing: metadata.get(providerId) ?? null,
|
|
195
|
+
now
|
|
196
|
+
}));
|
|
197
|
+
return sessionPackageDeleteResponseSchema.parse({
|
|
198
|
+
ok: true,
|
|
199
|
+
providerId
|
|
200
|
+
});
|
|
201
|
+
},
|
|
202
|
+
listPackages() {
|
|
203
|
+
return [...packages.values()]
|
|
204
|
+
.map(cloneInstalledProviderPackage)
|
|
205
|
+
.sort((left, right) => left.provider.id.localeCompare(right.provider.id));
|
|
206
|
+
},
|
|
207
|
+
getPackage(providerId) {
|
|
208
|
+
const stored = packages.get(providerId);
|
|
209
|
+
return stored ? cloneInstalledProviderPackage(stored) : null;
|
|
210
|
+
}
|
|
211
|
+
};
|
|
212
|
+
return store;
|
|
213
|
+
}
|
|
214
|
+
function buildSessionPackageStatus(providerId, stored) {
|
|
215
|
+
return sessionPackageStatusResponseSchema.parse({
|
|
216
|
+
ok: true,
|
|
217
|
+
providerId,
|
|
218
|
+
hasSessionPackage: Boolean(stored?.hasSessionPackage),
|
|
219
|
+
...(stored?.hasSessionPackage
|
|
220
|
+
? {
|
|
221
|
+
source: stored.source,
|
|
222
|
+
capturedAt: stored.capturedAt,
|
|
223
|
+
origin: stored.origin
|
|
224
|
+
}
|
|
225
|
+
: {})
|
|
226
|
+
});
|
|
227
|
+
}
|
|
228
|
+
function cloneProvider(provider) {
|
|
229
|
+
return providerSchema.parse({
|
|
230
|
+
...provider,
|
|
231
|
+
config: cloneConfig(provider.config)
|
|
232
|
+
});
|
|
233
|
+
}
|
|
234
|
+
function cloneConfig(config) {
|
|
235
|
+
return structuredClone(config);
|
|
236
|
+
}
|
|
237
|
+
function cloneSessionPackage(value) {
|
|
238
|
+
return sessionPackageSchema.parse(structuredClone(value));
|
|
239
|
+
}
|
|
240
|
+
function cloneSessionPackageMetadata(value) {
|
|
241
|
+
return sessionPackageMetadataSchema.parse(structuredClone(value));
|
|
242
|
+
}
|
|
243
|
+
function cloneInstalledProviderPackage(value) {
|
|
244
|
+
return installedProviderPackageSchema.parse(structuredClone(value));
|
|
245
|
+
}
|
|
246
|
+
function buildSessionPackageMetadata(providerId, session, input) {
|
|
247
|
+
return sessionPackageMetadataSchema.parse({
|
|
248
|
+
handle: input.existing?.handle ?? input.handle ?? `memory:${providerId}`,
|
|
249
|
+
providerId,
|
|
250
|
+
source: session?.source,
|
|
251
|
+
capturedAt: session?.capturedAt,
|
|
252
|
+
origin: session?.origin,
|
|
253
|
+
hasSessionPackage: Boolean(session),
|
|
254
|
+
createdAt: input.existing?.createdAt ?? input.now,
|
|
255
|
+
lastUsedAt: session ? input.now : input.existing?.lastUsedAt,
|
|
256
|
+
lastVerifiedAt: readLifecycleIsoString(session?.metadata, "lastVerifiedAt") ?? input.existing?.lastVerifiedAt,
|
|
257
|
+
idleExpiresAt: readLifecycleIsoString(session?.metadata, "idleExpiresAt"),
|
|
258
|
+
absoluteExpiresAt: readLifecycleIsoString(session?.metadata, "absoluteExpiresAt"),
|
|
259
|
+
status: "active",
|
|
260
|
+
version: 1
|
|
261
|
+
});
|
|
262
|
+
}
|
|
263
|
+
function inferProviderFromSessionPackage(input) {
|
|
264
|
+
const embeddedTransport = readEmbeddedTransport(input.value);
|
|
265
|
+
const capturedTransport = inferTransportFromRequestCapture(input.value);
|
|
266
|
+
const inferredTransport = embeddedTransport ??
|
|
267
|
+
(shouldRefreshTransportFromCapture(input.existing, capturedTransport)
|
|
268
|
+
? capturedTransport
|
|
269
|
+
: null);
|
|
270
|
+
const explicitModels = readExplicitModelIds(input.value);
|
|
271
|
+
const inferredModels = inferModelIdsFromCapture(input.value);
|
|
272
|
+
const existingModels = readConfiguredModelIds(input.existing?.config);
|
|
273
|
+
const nextModels = explicitModels ?? mergeModelIds(existingModels, inferredModels);
|
|
274
|
+
return providerSchema.parse({
|
|
275
|
+
id: input.providerId,
|
|
276
|
+
kind: inferredTransport?.family ?? input.existing?.kind ?? "http-json",
|
|
277
|
+
label: readLabel(input.value, input.providerId) ?? input.existing?.label ?? input.providerId,
|
|
278
|
+
enabled: input.value.integration?.enabled ?? input.existing?.enabled ?? true,
|
|
279
|
+
config: {
|
|
280
|
+
...(input.existing?.config ?? {}),
|
|
281
|
+
...(inferredTransport ? { transport: inferredTransport.config } : {}),
|
|
282
|
+
models: nextModels
|
|
283
|
+
},
|
|
284
|
+
createdAt: input.existing?.createdAt ?? input.now,
|
|
285
|
+
updatedAt: input.now
|
|
286
|
+
});
|
|
287
|
+
}
|
|
288
|
+
function shouldRefreshTransportFromCapture(existing, capturedTransport) {
|
|
289
|
+
if (!capturedTransport) {
|
|
290
|
+
return false;
|
|
291
|
+
}
|
|
292
|
+
if (!existing) {
|
|
293
|
+
return true;
|
|
294
|
+
}
|
|
295
|
+
const existingTransport = readConfiguredTransport(existing.config);
|
|
296
|
+
if (!existingTransport) {
|
|
297
|
+
return true;
|
|
298
|
+
}
|
|
299
|
+
const existingRequest = typeof existingTransport.request === "object" && existingTransport.request !== null
|
|
300
|
+
? existingTransport.request
|
|
301
|
+
: null;
|
|
302
|
+
const capturedRequest = typeof capturedTransport.config.request === "object" &&
|
|
303
|
+
capturedTransport.config.request !== null
|
|
304
|
+
? capturedTransport.config.request
|
|
305
|
+
: null;
|
|
306
|
+
const existingUrl = typeof existingRequest?.url === "string" ? existingRequest.url.trim() : "";
|
|
307
|
+
const capturedUrl = typeof capturedRequest?.url === "string" ? capturedRequest.url.trim() : "";
|
|
308
|
+
if (existing.kind !== capturedTransport.family) {
|
|
309
|
+
return true;
|
|
310
|
+
}
|
|
311
|
+
if (existingUrl && capturedUrl && existingUrl === capturedUrl) {
|
|
312
|
+
return true;
|
|
313
|
+
}
|
|
314
|
+
return false;
|
|
315
|
+
}
|
|
316
|
+
function readEmbeddedTransport(value) {
|
|
317
|
+
if (!value.transport) {
|
|
318
|
+
return null;
|
|
319
|
+
}
|
|
320
|
+
const parsed = transportPackageSchema.safeParse(value.transport);
|
|
321
|
+
if (!parsed.success) {
|
|
322
|
+
return null;
|
|
323
|
+
}
|
|
324
|
+
const { family, ...config } = parsed.data;
|
|
325
|
+
return {
|
|
326
|
+
family,
|
|
327
|
+
config
|
|
328
|
+
};
|
|
329
|
+
}
|
|
330
|
+
function inferTransportFromRequestCapture(value) {
|
|
331
|
+
const selectedRequest = readSelectedRequest(value.metadata);
|
|
332
|
+
if (!selectedRequest?.url || !selectedRequest?.method) {
|
|
333
|
+
return null;
|
|
334
|
+
}
|
|
335
|
+
const zaiConversationTransport = inferZaiConversationTransport(selectedRequest, value);
|
|
336
|
+
if (zaiConversationTransport) {
|
|
337
|
+
return zaiConversationTransport;
|
|
338
|
+
}
|
|
339
|
+
const qwenConversationTransport = inferQwenConversationTransport(selectedRequest, value);
|
|
340
|
+
if (qwenConversationTransport) {
|
|
341
|
+
return qwenConversationTransport;
|
|
342
|
+
}
|
|
343
|
+
const deepSeekConversationTransport = inferDeepSeekConversationTransport(selectedRequest, value);
|
|
344
|
+
if (deepSeekConversationTransport) {
|
|
345
|
+
return deepSeekConversationTransport;
|
|
346
|
+
}
|
|
347
|
+
const openAiConversationTransport = inferOpenAiConversationTransport(selectedRequest, value);
|
|
348
|
+
if (openAiConversationTransport) {
|
|
349
|
+
return openAiConversationTransport;
|
|
350
|
+
}
|
|
351
|
+
const family = readTransportFamily(selectedRequest);
|
|
352
|
+
const requestBody = readTemplateRequestBody(selectedRequest);
|
|
353
|
+
return {
|
|
354
|
+
family,
|
|
355
|
+
config: {
|
|
356
|
+
prompt: {
|
|
357
|
+
mode: "flatten"
|
|
358
|
+
},
|
|
359
|
+
binding: {
|
|
360
|
+
firstTurn: "empty"
|
|
361
|
+
},
|
|
362
|
+
session: {
|
|
363
|
+
requireCookie: Array.isArray(value.cookies) && value.cookies.length > 0,
|
|
364
|
+
requireBearerToken: hasBearerAuthorization(value.headers),
|
|
365
|
+
requireUserAgent: hasHeader(value.headers, "user-agent"),
|
|
366
|
+
includeExtraHeaders: true
|
|
367
|
+
},
|
|
368
|
+
request: {
|
|
369
|
+
method: String(selectedRequest.method).toUpperCase(),
|
|
370
|
+
url: String(selectedRequest.url),
|
|
371
|
+
headers: {},
|
|
372
|
+
...(requestBody === undefined ? {} : { body: requestBody })
|
|
373
|
+
},
|
|
374
|
+
response: {
|
|
375
|
+
contentPaths: family === "http-sse"
|
|
376
|
+
? DEFAULT_SSE_CONTENT_PATHS
|
|
377
|
+
: family === "http-connect"
|
|
378
|
+
? DEFAULT_CONNECT_CONTENT_PATHS
|
|
379
|
+
: DEFAULT_JSON_CONTENT_PATHS,
|
|
380
|
+
responseIdPaths: DEFAULT_RESPONSE_ID_PATHS,
|
|
381
|
+
conversationIdPaths: DEFAULT_CONVERSATION_ID_PATHS,
|
|
382
|
+
trimLeadingAssistantBlock: true
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
};
|
|
386
|
+
}
|
|
387
|
+
function inferQwenConversationTransport(selectedRequest, value) {
|
|
388
|
+
const requestUrl = typeof selectedRequest.url === "string" ? selectedRequest.url.trim() : "";
|
|
389
|
+
if (!isQwenConversationRequestUrl(requestUrl)) {
|
|
390
|
+
return null;
|
|
391
|
+
}
|
|
392
|
+
const requestBody = readTemplateRequestBody(selectedRequest);
|
|
393
|
+
const capturedBootstrapHeaders = readCapturedRequestHeaders(value.metadata, isQwenBootstrapRequestUrl);
|
|
394
|
+
const bootstrapHeaders = mergeHeaderRecords({
|
|
395
|
+
Accept: "application/json",
|
|
396
|
+
"Content-Type": "application/json",
|
|
397
|
+
Origin: "https://chat.qwen.ai",
|
|
398
|
+
Referer: "https://chat.qwen.ai/"
|
|
399
|
+
}, capturedBootstrapHeaders);
|
|
400
|
+
return {
|
|
401
|
+
family: "http-sse",
|
|
402
|
+
config: {
|
|
403
|
+
prompt: {
|
|
404
|
+
mode: "flatten"
|
|
405
|
+
},
|
|
406
|
+
binding: {
|
|
407
|
+
firstTurn: "seed"
|
|
408
|
+
},
|
|
409
|
+
session: {
|
|
410
|
+
requireCookie: Array.isArray(value.cookies) && value.cookies.length > 0,
|
|
411
|
+
requireBearerToken: hasBearerAuthorization(value.headers),
|
|
412
|
+
requireUserAgent: hasHeader(value.headers, "user-agent"),
|
|
413
|
+
includeExtraHeaders: true
|
|
414
|
+
},
|
|
415
|
+
request: {
|
|
416
|
+
method: String(selectedRequest.method).toUpperCase(),
|
|
417
|
+
url: "https://chat.qwen.ai/api/v2/chat/completions?chat_id={{conversationId}}",
|
|
418
|
+
headers: {},
|
|
419
|
+
...(requestBody === undefined ? {} : { body: requestBody })
|
|
420
|
+
},
|
|
421
|
+
response: {
|
|
422
|
+
contentPaths: DEFAULT_SSE_CONTENT_PATHS,
|
|
423
|
+
responseIdPaths: DEFAULT_RESPONSE_ID_PATHS,
|
|
424
|
+
conversationIdPaths: ["response.created.chat_id", ...DEFAULT_CONVERSATION_ID_PATHS],
|
|
425
|
+
eventFilters: [
|
|
426
|
+
{
|
|
427
|
+
path: "choices.0.delta.phase",
|
|
428
|
+
equals: "answer"
|
|
429
|
+
}
|
|
430
|
+
],
|
|
431
|
+
trimLeadingAssistantBlock: true
|
|
432
|
+
},
|
|
433
|
+
bootstrap: {
|
|
434
|
+
request: {
|
|
435
|
+
method: "POST",
|
|
436
|
+
url: "https://chat.qwen.ai/api/v2/chats/new",
|
|
437
|
+
headers: bootstrapHeaders,
|
|
438
|
+
body: buildQwenBootstrapRequestBody(selectedRequest)
|
|
439
|
+
},
|
|
440
|
+
conversationIdPath: "data.id"
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
};
|
|
444
|
+
}
|
|
445
|
+
function inferDeepSeekConversationTransport(selectedRequest, value) {
|
|
446
|
+
const requestUrl = typeof selectedRequest.url === "string" ? selectedRequest.url.trim() : "";
|
|
447
|
+
if (!isDeepSeekConversationRequestUrl(requestUrl)) {
|
|
448
|
+
return null;
|
|
449
|
+
}
|
|
450
|
+
const requestBody = readTemplateRequestBody(selectedRequest);
|
|
451
|
+
const capturedCompletionHeaders = omitHeaders(filterCapturedRequestHeaders(readSelectedRequestHeaders(selectedRequest)), ["x-ds-pow-response"]);
|
|
452
|
+
const capturedBootstrapHeaders = omitHeaders(readCapturedRequestHeaders(value.metadata, isDeepSeekBootstrapRequestUrl), ["x-ds-pow-response"]);
|
|
453
|
+
const capturedPreflightHeaders = omitHeaders(readCapturedRequestHeaders(value.metadata, isDeepSeekPowChallengeRequestUrl), ["x-ds-pow-response"]);
|
|
454
|
+
const requestHeaders = mergeHeaderRecords({
|
|
455
|
+
Accept: "*/*",
|
|
456
|
+
"Content-Type": "application/json",
|
|
457
|
+
Origin: "https://chat.deepseek.com",
|
|
458
|
+
Referer: "https://chat.deepseek.com/"
|
|
459
|
+
}, capturedCompletionHeaders);
|
|
460
|
+
const bootstrapHeaders = mergeHeaderRecords({
|
|
461
|
+
Accept: "*/*",
|
|
462
|
+
"Content-Type": "application/json",
|
|
463
|
+
Origin: "https://chat.deepseek.com",
|
|
464
|
+
Referer: "https://chat.deepseek.com/"
|
|
465
|
+
}, capturedBootstrapHeaders);
|
|
466
|
+
const preflightHeaders = mergeHeaderRecords({
|
|
467
|
+
Accept: "*/*",
|
|
468
|
+
"Content-Type": "application/json",
|
|
469
|
+
Origin: "https://chat.deepseek.com",
|
|
470
|
+
Referer: "https://chat.deepseek.com/"
|
|
471
|
+
}, capturedPreflightHeaders);
|
|
472
|
+
return {
|
|
473
|
+
family: "http-sse",
|
|
474
|
+
config: {
|
|
475
|
+
prompt: {
|
|
476
|
+
mode: "flatten"
|
|
477
|
+
},
|
|
478
|
+
binding: {
|
|
479
|
+
firstTurn: "empty"
|
|
480
|
+
},
|
|
481
|
+
session: {
|
|
482
|
+
requireCookie: Array.isArray(value.cookies) && value.cookies.length > 0,
|
|
483
|
+
requireBearerToken: hasBearerAuthorization(value.headers),
|
|
484
|
+
requireUserAgent: hasHeader(value.headers, "user-agent"),
|
|
485
|
+
includeExtraHeaders: false
|
|
486
|
+
},
|
|
487
|
+
request: {
|
|
488
|
+
method: "POST",
|
|
489
|
+
url: "https://chat.deepseek.com/api/v0/chat/completion",
|
|
490
|
+
headers: requestHeaders,
|
|
491
|
+
...(requestBody === undefined ? {} : { body: requestBody })
|
|
492
|
+
},
|
|
493
|
+
response: {
|
|
494
|
+
contentPaths: ["__bridge__.deepseek.response"],
|
|
495
|
+
responseIdPaths: [
|
|
496
|
+
"response_message_id",
|
|
497
|
+
"chat_message.message_id",
|
|
498
|
+
"data.biz_data.message_id",
|
|
499
|
+
...DEFAULT_RESPONSE_ID_PATHS
|
|
500
|
+
],
|
|
501
|
+
conversationIdPaths: [
|
|
502
|
+
"chat_message.chat_session_id",
|
|
503
|
+
"data.biz_data.chat_session.id",
|
|
504
|
+
"data.biz_data.chat_session_id",
|
|
505
|
+
...DEFAULT_CONVERSATION_ID_PATHS
|
|
506
|
+
],
|
|
507
|
+
trimLeadingAssistantBlock: true
|
|
508
|
+
},
|
|
509
|
+
bootstrap: {
|
|
510
|
+
request: {
|
|
511
|
+
method: "POST",
|
|
512
|
+
url: "https://chat.deepseek.com/api/v0/chat_session/create",
|
|
513
|
+
headers: bootstrapHeaders,
|
|
514
|
+
body: {}
|
|
515
|
+
},
|
|
516
|
+
conversationIdPath: "data.biz_data.chat_session.id"
|
|
517
|
+
},
|
|
518
|
+
preflight: {
|
|
519
|
+
request: {
|
|
520
|
+
method: "POST",
|
|
521
|
+
url: "https://chat.deepseek.com/api/v0/chat/create_pow_challenge",
|
|
522
|
+
headers: preflightHeaders,
|
|
523
|
+
body: {
|
|
524
|
+
target_path: "/api/v0/chat/completion"
|
|
525
|
+
}
|
|
526
|
+
},
|
|
527
|
+
proofOfWork: {
|
|
528
|
+
kind: "sha3-wasm-salt-expiry",
|
|
529
|
+
headerName: "x-ds-pow-response",
|
|
530
|
+
wasmUrl: "https://fe-static.deepseek.com/chat/static/sha3_wasm_bg.7b9ca65ddd.wasm",
|
|
531
|
+
algorithmPath: "data.biz_data.challenge.algorithm",
|
|
532
|
+
challengePath: "data.biz_data.challenge.challenge",
|
|
533
|
+
saltPath: "data.biz_data.challenge.salt",
|
|
534
|
+
signaturePath: "data.biz_data.challenge.signature",
|
|
535
|
+
difficultyPath: "data.biz_data.challenge.difficulty",
|
|
536
|
+
expireAtPath: "data.biz_data.challenge.expire_at",
|
|
537
|
+
targetPathPath: "data.biz_data.challenge.target_path"
|
|
538
|
+
}
|
|
539
|
+
}
|
|
540
|
+
}
|
|
541
|
+
};
|
|
542
|
+
}
|
|
543
|
+
function inferZaiConversationTransport(selectedRequest, value) {
|
|
544
|
+
const requestUrl = typeof selectedRequest.url === "string" ? selectedRequest.url.trim() : "";
|
|
545
|
+
if (!isZaiConversationRequestUrl(requestUrl)) {
|
|
546
|
+
return null;
|
|
547
|
+
}
|
|
548
|
+
const capturedBootstrapHeaders = readCapturedRequestHeaders(value.metadata, isZaiBootstrapRequestUrl);
|
|
549
|
+
const bootstrapHeaders = mergeHeaderRecords({
|
|
550
|
+
Accept: "application/json",
|
|
551
|
+
"Accept-Language": "en-US",
|
|
552
|
+
Connection: "keep-alive",
|
|
553
|
+
"Content-Type": "application/json",
|
|
554
|
+
Origin: "https://chat.z.ai",
|
|
555
|
+
"Sec-Fetch-Dest": "empty",
|
|
556
|
+
"Sec-Fetch-Mode": "cors",
|
|
557
|
+
"Sec-Fetch-Site": "same-origin"
|
|
558
|
+
}, capturedBootstrapHeaders);
|
|
559
|
+
return {
|
|
560
|
+
family: "http-sse",
|
|
561
|
+
config: {
|
|
562
|
+
prompt: {
|
|
563
|
+
mode: "latest_user"
|
|
564
|
+
},
|
|
565
|
+
binding: {
|
|
566
|
+
firstTurn: "seed"
|
|
567
|
+
},
|
|
568
|
+
session: {
|
|
569
|
+
requireCookie: Array.isArray(value.cookies) && value.cookies.length > 0,
|
|
570
|
+
requireBearerToken: hasBearerAuthorization(value.headers),
|
|
571
|
+
requireUserAgent: hasHeader(value.headers, "user-agent"),
|
|
572
|
+
includeExtraHeaders: true
|
|
573
|
+
},
|
|
574
|
+
request: {
|
|
575
|
+
method: "POST",
|
|
576
|
+
url: "https://chat.z.ai/api/v2/chat/completions",
|
|
577
|
+
headers: {
|
|
578
|
+
Accept: "*/*",
|
|
579
|
+
"Accept-Language": "en-US",
|
|
580
|
+
Connection: "keep-alive",
|
|
581
|
+
"Content-Type": "application/json",
|
|
582
|
+
Origin: "https://chat.z.ai",
|
|
583
|
+
"Sec-Fetch-Dest": "empty",
|
|
584
|
+
"Sec-Fetch-Mode": "cors",
|
|
585
|
+
"Sec-Fetch-Site": "same-origin",
|
|
586
|
+
"X-FE-Version": "prod-fe-1.1.2"
|
|
587
|
+
},
|
|
588
|
+
signing: {
|
|
589
|
+
kind: "z-ai-v1"
|
|
590
|
+
},
|
|
591
|
+
body: {
|
|
592
|
+
stream: true,
|
|
593
|
+
model: "{{modelId}}",
|
|
594
|
+
messages: [
|
|
595
|
+
{
|
|
596
|
+
role: "user",
|
|
597
|
+
content: "{{prompt}}"
|
|
598
|
+
}
|
|
599
|
+
],
|
|
600
|
+
signature_prompt: "{{prompt}}",
|
|
601
|
+
params: {},
|
|
602
|
+
extra: {},
|
|
603
|
+
features: {
|
|
604
|
+
image_generation: false,
|
|
605
|
+
web_search: false,
|
|
606
|
+
auto_web_search: false,
|
|
607
|
+
preview_mode: true,
|
|
608
|
+
flags: [],
|
|
609
|
+
vlm_tools_enable: false,
|
|
610
|
+
vlm_web_search_enable: false,
|
|
611
|
+
vlm_website_mode: false,
|
|
612
|
+
enable_thinking: "{{thinkingEnabledOrTrue}}"
|
|
613
|
+
},
|
|
614
|
+
variables: {
|
|
615
|
+
"{{USER_NAME}}": "{{userName}}",
|
|
616
|
+
"{{USER_LOCATION}}": "Unknown",
|
|
617
|
+
"{{CURRENT_DATETIME}}": "{{currentDateTime}}",
|
|
618
|
+
"{{CURRENT_DATE}}": "{{currentDate}}",
|
|
619
|
+
"{{CURRENT_TIME}}": "{{currentTime}}",
|
|
620
|
+
"{{CURRENT_WEEKDAY}}": "{{currentWeekday}}",
|
|
621
|
+
"{{CURRENT_TIMEZONE}}": "{{currentTimezone}}",
|
|
622
|
+
"{{USER_LANGUAGE}}": "{{userLanguage}}"
|
|
623
|
+
},
|
|
624
|
+
chat_id: "{{conversationId}}",
|
|
625
|
+
id: "{{assistantMessageId}}",
|
|
626
|
+
current_user_message_id: "{{userMessageId}}",
|
|
627
|
+
current_user_message_parent_id: "{{parentIdOrNull}}",
|
|
628
|
+
background_tasks: {
|
|
629
|
+
title_generation: true,
|
|
630
|
+
tags_generation: true
|
|
631
|
+
}
|
|
632
|
+
}
|
|
633
|
+
},
|
|
634
|
+
response: {
|
|
635
|
+
contentPaths: ["data.delta_content"],
|
|
636
|
+
eventFilters: [
|
|
637
|
+
{
|
|
638
|
+
path: "data.phase",
|
|
639
|
+
equals: "answer"
|
|
640
|
+
}
|
|
641
|
+
],
|
|
642
|
+
fallbackResponseId: "assistantMessageId",
|
|
643
|
+
trimLeadingAssistantBlock: false
|
|
644
|
+
},
|
|
645
|
+
bootstrap: {
|
|
646
|
+
request: {
|
|
647
|
+
method: "POST",
|
|
648
|
+
url: "https://chat.z.ai/api/v1/chats/new",
|
|
649
|
+
headers: bootstrapHeaders,
|
|
650
|
+
body: {
|
|
651
|
+
chat: {
|
|
652
|
+
id: "",
|
|
653
|
+
title: "New Chat",
|
|
654
|
+
models: ["{{modelId}}"],
|
|
655
|
+
params: {},
|
|
656
|
+
history: {
|
|
657
|
+
messages: {
|
|
658
|
+
"bootstrap-user": {
|
|
659
|
+
id: "bootstrap-user",
|
|
660
|
+
parentId: null,
|
|
661
|
+
childrenIds: [],
|
|
662
|
+
role: "user",
|
|
663
|
+
content: "{{prompt}}",
|
|
664
|
+
timestamp: "{{unixTimestampSec}}",
|
|
665
|
+
models: ["{{modelId}}"]
|
|
666
|
+
}
|
|
667
|
+
},
|
|
668
|
+
currentId: "bootstrap-user"
|
|
669
|
+
},
|
|
670
|
+
tags: [],
|
|
671
|
+
flags: [],
|
|
672
|
+
features: [
|
|
673
|
+
{ type: "mcp", server: "vibe-coding", status: "hidden" },
|
|
674
|
+
{ type: "mcp", server: "ppt-maker", status: "hidden" },
|
|
675
|
+
{ type: "mcp", server: "image-search", status: "hidden" },
|
|
676
|
+
{ type: "mcp", server: "deep-research", status: "hidden" },
|
|
677
|
+
{ type: "tool_selector", server: "tool_selector", status: "hidden" }
|
|
678
|
+
],
|
|
679
|
+
mcp_servers: [],
|
|
680
|
+
enable_thinking: "{{thinkingEnabledOrTrue}}",
|
|
681
|
+
auto_web_search: false,
|
|
682
|
+
message_version: 1,
|
|
683
|
+
extra: {},
|
|
684
|
+
timestamp: "{{unixTimestampMs}}",
|
|
685
|
+
type: "default"
|
|
686
|
+
}
|
|
687
|
+
}
|
|
688
|
+
},
|
|
689
|
+
conversationIdPath: "id"
|
|
690
|
+
}
|
|
691
|
+
}
|
|
692
|
+
};
|
|
693
|
+
}
|
|
694
|
+
function inferOpenAiConversationTransport(selectedRequest, value) {
|
|
695
|
+
const requestUrl = typeof selectedRequest.url === "string" ? selectedRequest.url.trim() : "";
|
|
696
|
+
if (!isOpenAiConversationRequestUrl(requestUrl)) {
|
|
697
|
+
return null;
|
|
698
|
+
}
|
|
699
|
+
return {
|
|
700
|
+
family: "http-sse",
|
|
701
|
+
config: {
|
|
702
|
+
prompt: {
|
|
703
|
+
mode: "auto_join"
|
|
704
|
+
},
|
|
705
|
+
binding: {
|
|
706
|
+
firstTurn: "empty"
|
|
707
|
+
},
|
|
708
|
+
session: {
|
|
709
|
+
requireCookie: Array.isArray(value.cookies) && value.cookies.length > 0,
|
|
710
|
+
requireBearerToken: hasBearerAuthorization(value.headers),
|
|
711
|
+
requireUserAgent: hasHeader(value.headers, "user-agent"),
|
|
712
|
+
includeExtraHeaders: true
|
|
713
|
+
},
|
|
714
|
+
request: {
|
|
715
|
+
method: String(selectedRequest.method).toUpperCase(),
|
|
716
|
+
url: requestUrl,
|
|
717
|
+
headers: {},
|
|
718
|
+
body: buildOpenAiConversationRequestBody(readRequestBodyObject(selectedRequest))
|
|
719
|
+
},
|
|
720
|
+
response: {
|
|
721
|
+
contentPaths: ["v.message.content.parts.*", "message.content.parts.*"],
|
|
722
|
+
responseIdPaths: ["v.message.id", "message.id"],
|
|
723
|
+
conversationIdPaths: ["conversation_id", "v.conversation_id"],
|
|
724
|
+
allowVisibleTextFinal: true,
|
|
725
|
+
trimLeadingAssistantBlock: false
|
|
726
|
+
}
|
|
727
|
+
}
|
|
728
|
+
};
|
|
729
|
+
}
|
|
730
|
+
function readCapturedRequestHeaders(metadata, matcher) {
|
|
731
|
+
const requests = readCapturedRequests(metadata);
|
|
732
|
+
for (let index = requests.length - 1; index >= 0; index -= 1) {
|
|
733
|
+
const request = requests[index];
|
|
734
|
+
const url = typeof request.url === "string" ? request.url.trim() : "";
|
|
735
|
+
if (!url || !matcher(url)) {
|
|
736
|
+
continue;
|
|
737
|
+
}
|
|
738
|
+
return filterCapturedRequestHeaders(readSelectedRequestHeaders(request));
|
|
739
|
+
}
|
|
740
|
+
return {};
|
|
741
|
+
}
|
|
742
|
+
function omitHeaders(source, names) {
|
|
743
|
+
if (Object.keys(source).length === 0 || names.length === 0) {
|
|
744
|
+
return source;
|
|
745
|
+
}
|
|
746
|
+
const excluded = new Set(names.map((name) => name.toLowerCase()));
|
|
747
|
+
return Object.fromEntries(Object.entries(source).filter(([key]) => !excluded.has(key.toLowerCase())));
|
|
748
|
+
}
|
|
749
|
+
function readCapturedRequests(metadata) {
|
|
750
|
+
const capture = metadata.requestCapture;
|
|
751
|
+
if (!capture || typeof capture !== "object" || Array.isArray(capture)) {
|
|
752
|
+
return [];
|
|
753
|
+
}
|
|
754
|
+
const requests = capture.requests;
|
|
755
|
+
return Array.isArray(requests)
|
|
756
|
+
? requests.filter((entry) => typeof entry === "object" && entry !== null && !Array.isArray(entry))
|
|
757
|
+
: [];
|
|
758
|
+
}
|
|
759
|
+
function filterCapturedRequestHeaders(headers) {
|
|
760
|
+
if (!headers) {
|
|
761
|
+
return {};
|
|
762
|
+
}
|
|
763
|
+
return Object.fromEntries(Object.entries(headers).flatMap(([key, value]) => {
|
|
764
|
+
if (typeof value !== "string" || !value.trim()) {
|
|
765
|
+
return [];
|
|
766
|
+
}
|
|
767
|
+
const normalized = key.toLowerCase();
|
|
768
|
+
if (normalized === "cookie" ||
|
|
769
|
+
normalized === "authorization" ||
|
|
770
|
+
normalized === "user-agent" ||
|
|
771
|
+
normalized === "content-length") {
|
|
772
|
+
return [];
|
|
773
|
+
}
|
|
774
|
+
return [[key, value.trim()]];
|
|
775
|
+
}));
|
|
776
|
+
}
|
|
777
|
+
function mergeHeaderRecords(...sources) {
|
|
778
|
+
const merged = {};
|
|
779
|
+
const canonicalKeys = new Map();
|
|
780
|
+
for (const source of sources) {
|
|
781
|
+
for (const [key, value] of Object.entries(source)) {
|
|
782
|
+
if (typeof value !== "string" || !value.trim()) {
|
|
783
|
+
continue;
|
|
784
|
+
}
|
|
785
|
+
const normalized = key.toLowerCase();
|
|
786
|
+
const existingKey = canonicalKeys.get(normalized);
|
|
787
|
+
if (existingKey && existingKey !== key) {
|
|
788
|
+
delete merged[existingKey];
|
|
789
|
+
}
|
|
790
|
+
canonicalKeys.set(normalized, key);
|
|
791
|
+
merged[key] = value.trim();
|
|
792
|
+
}
|
|
793
|
+
}
|
|
794
|
+
return merged;
|
|
795
|
+
}
|
|
796
|
+
function isZaiConversationRequestUrl(requestUrl) {
|
|
797
|
+
if (!requestUrl) {
|
|
798
|
+
return false;
|
|
799
|
+
}
|
|
800
|
+
try {
|
|
801
|
+
const url = new URL(requestUrl);
|
|
802
|
+
return (url.hostname.toLowerCase() === "chat.z.ai" &&
|
|
803
|
+
/^\/api\/v2\/chat\/completions\/?$/i.test(url.pathname));
|
|
804
|
+
}
|
|
805
|
+
catch {
|
|
806
|
+
return false;
|
|
807
|
+
}
|
|
808
|
+
}
|
|
809
|
+
function isOpenAiConversationRequestUrl(requestUrl) {
|
|
810
|
+
if (!requestUrl) {
|
|
811
|
+
return false;
|
|
812
|
+
}
|
|
813
|
+
try {
|
|
814
|
+
const url = new URL(requestUrl);
|
|
815
|
+
const normalizedHost = url.hostname.toLowerCase();
|
|
816
|
+
const normalizedPath = url.pathname.toLowerCase();
|
|
817
|
+
return ((normalizedHost === "chatgpt.com" || normalizedHost.endsWith(".chatgpt.com")) &&
|
|
818
|
+
/^\/backend-api(?:\/f)?\/conversation\/?$/.test(normalizedPath));
|
|
819
|
+
}
|
|
820
|
+
catch {
|
|
821
|
+
return false;
|
|
822
|
+
}
|
|
823
|
+
}
|
|
824
|
+
function isQwenConversationRequestUrl(requestUrl) {
|
|
825
|
+
if (!requestUrl) {
|
|
826
|
+
return false;
|
|
827
|
+
}
|
|
828
|
+
try {
|
|
829
|
+
const url = new URL(requestUrl);
|
|
830
|
+
const normalizedHost = url.hostname.toLowerCase();
|
|
831
|
+
const normalizedPath = url.pathname.toLowerCase();
|
|
832
|
+
return ((normalizedHost === "chat.qwen.ai" || normalizedHost.endsWith(".chat.qwen.ai")) &&
|
|
833
|
+
normalizedPath === "/api/v2/chat/completions");
|
|
834
|
+
}
|
|
835
|
+
catch {
|
|
836
|
+
return false;
|
|
837
|
+
}
|
|
838
|
+
}
|
|
839
|
+
function isQwenBootstrapRequestUrl(requestUrl) {
|
|
840
|
+
if (!requestUrl) {
|
|
841
|
+
return false;
|
|
842
|
+
}
|
|
843
|
+
try {
|
|
844
|
+
const url = new URL(requestUrl);
|
|
845
|
+
const normalizedHost = url.hostname.toLowerCase();
|
|
846
|
+
const normalizedPath = url.pathname.toLowerCase();
|
|
847
|
+
return ((normalizedHost === "chat.qwen.ai" || normalizedHost.endsWith(".chat.qwen.ai")) &&
|
|
848
|
+
normalizedPath === "/api/v2/chats/new");
|
|
849
|
+
}
|
|
850
|
+
catch {
|
|
851
|
+
return false;
|
|
852
|
+
}
|
|
853
|
+
}
|
|
854
|
+
function isDeepSeekConversationRequestUrl(requestUrl) {
|
|
855
|
+
if (!requestUrl) {
|
|
856
|
+
return false;
|
|
857
|
+
}
|
|
858
|
+
try {
|
|
859
|
+
const url = new URL(requestUrl);
|
|
860
|
+
const normalizedHost = url.hostname.toLowerCase();
|
|
861
|
+
const normalizedPath = url.pathname.toLowerCase();
|
|
862
|
+
return ((normalizedHost === "chat.deepseek.com" || normalizedHost.endsWith(".chat.deepseek.com")) &&
|
|
863
|
+
normalizedPath === "/api/v0/chat/completion");
|
|
864
|
+
}
|
|
865
|
+
catch {
|
|
866
|
+
return false;
|
|
867
|
+
}
|
|
868
|
+
}
|
|
869
|
+
function isDeepSeekBootstrapRequestUrl(requestUrl) {
|
|
870
|
+
if (!requestUrl) {
|
|
871
|
+
return false;
|
|
872
|
+
}
|
|
873
|
+
try {
|
|
874
|
+
const url = new URL(requestUrl);
|
|
875
|
+
const normalizedHost = url.hostname.toLowerCase();
|
|
876
|
+
const normalizedPath = url.pathname.toLowerCase();
|
|
877
|
+
return ((normalizedHost === "chat.deepseek.com" || normalizedHost.endsWith(".chat.deepseek.com")) &&
|
|
878
|
+
normalizedPath === "/api/v0/chat_session/create");
|
|
879
|
+
}
|
|
880
|
+
catch {
|
|
881
|
+
return false;
|
|
882
|
+
}
|
|
883
|
+
}
|
|
884
|
+
function isDeepSeekPowChallengeRequestUrl(requestUrl) {
|
|
885
|
+
if (!requestUrl) {
|
|
886
|
+
return false;
|
|
887
|
+
}
|
|
888
|
+
try {
|
|
889
|
+
const url = new URL(requestUrl);
|
|
890
|
+
const normalizedHost = url.hostname.toLowerCase();
|
|
891
|
+
const normalizedPath = url.pathname.toLowerCase();
|
|
892
|
+
return ((normalizedHost === "chat.deepseek.com" || normalizedHost.endsWith(".chat.deepseek.com")) &&
|
|
893
|
+
normalizedPath === "/api/v0/chat/create_pow_challenge");
|
|
894
|
+
}
|
|
895
|
+
catch {
|
|
896
|
+
return false;
|
|
897
|
+
}
|
|
898
|
+
}
|
|
899
|
+
function buildQwenBootstrapRequestBody(selectedRequest) {
|
|
900
|
+
const requestBody = readRequestBodyObject(selectedRequest);
|
|
901
|
+
const topLevelChatType = typeof requestBody?.chat_type === "string" && requestBody.chat_type.trim()
|
|
902
|
+
? requestBody.chat_type.trim()
|
|
903
|
+
: "";
|
|
904
|
+
const topLevelChatMode = typeof requestBody?.chat_mode === "string" && requestBody.chat_mode.trim()
|
|
905
|
+
? requestBody.chat_mode.trim()
|
|
906
|
+
: "";
|
|
907
|
+
const projectId = typeof requestBody?.project_id === "string" ? requestBody.project_id : "";
|
|
908
|
+
const firstMessage = Array.isArray(requestBody?.messages) &&
|
|
909
|
+
requestBody.messages.length > 0 &&
|
|
910
|
+
typeof requestBody.messages[0] === "object" &&
|
|
911
|
+
requestBody.messages[0] !== null
|
|
912
|
+
? requestBody.messages[0]
|
|
913
|
+
: null;
|
|
914
|
+
const messageChatType = typeof firstMessage?.chat_type === "string" && firstMessage.chat_type.trim()
|
|
915
|
+
? firstMessage.chat_type.trim()
|
|
916
|
+
: "";
|
|
917
|
+
const messageSubChatType = typeof firstMessage?.sub_chat_type === "string" && firstMessage.sub_chat_type.trim()
|
|
918
|
+
? firstMessage.sub_chat_type.trim()
|
|
919
|
+
: "";
|
|
920
|
+
return {
|
|
921
|
+
title: "New Chat",
|
|
922
|
+
models: ["{{modelId}}"],
|
|
923
|
+
chat_mode: topLevelChatMode || "normal",
|
|
924
|
+
chat_type: topLevelChatType || messageChatType || messageSubChatType || "t2t",
|
|
925
|
+
timestamp: "{{unixTimestampMs}}",
|
|
926
|
+
project_id: projectId
|
|
927
|
+
};
|
|
928
|
+
}
|
|
929
|
+
function buildOpenAiConversationRequestBody(requestBody) {
|
|
930
|
+
const base = requestBody ? structuredClone(requestBody) : {};
|
|
931
|
+
const capturedMessage = Array.isArray(requestBody?.messages) &&
|
|
932
|
+
requestBody.messages.length > 0 &&
|
|
933
|
+
typeof requestBody.messages[0] === "object" &&
|
|
934
|
+
requestBody.messages[0] !== null
|
|
935
|
+
? requestBody.messages[0]
|
|
936
|
+
: null;
|
|
937
|
+
const nextBody = {
|
|
938
|
+
...base,
|
|
939
|
+
action: typeof requestBody?.action === "string" && requestBody.action.trim()
|
|
940
|
+
? requestBody.action
|
|
941
|
+
: "next",
|
|
942
|
+
messages: [buildOpenAiConversationUserMessage(capturedMessage)],
|
|
943
|
+
parent_message_id: "{{parentIdOrClientCreatedRoot}}",
|
|
944
|
+
model: "{{modelId}}"
|
|
945
|
+
};
|
|
946
|
+
delete nextBody.conversation_id;
|
|
947
|
+
delete nextBody.conversationId;
|
|
948
|
+
return nextBody;
|
|
949
|
+
}
|
|
950
|
+
function buildOpenAiConversationUserMessage(capturedMessage) {
|
|
951
|
+
const base = capturedMessage ? structuredClone(capturedMessage) : {};
|
|
952
|
+
const author = capturedMessage?.author &&
|
|
953
|
+
typeof capturedMessage.author === "object" &&
|
|
954
|
+
!Array.isArray(capturedMessage.author)
|
|
955
|
+
? structuredClone(capturedMessage.author)
|
|
956
|
+
: {};
|
|
957
|
+
const content = capturedMessage?.content &&
|
|
958
|
+
typeof capturedMessage.content === "object" &&
|
|
959
|
+
!Array.isArray(capturedMessage.content)
|
|
960
|
+
? structuredClone(capturedMessage.content)
|
|
961
|
+
: {};
|
|
962
|
+
return {
|
|
963
|
+
...base,
|
|
964
|
+
id: "{{messageId}}",
|
|
965
|
+
author: {
|
|
966
|
+
...author,
|
|
967
|
+
role: "user"
|
|
968
|
+
},
|
|
969
|
+
create_time: "{{unixTimestampSec}}",
|
|
970
|
+
content: {
|
|
971
|
+
...content,
|
|
972
|
+
content_type: typeof content.content_type === "string" && content.content_type.trim()
|
|
973
|
+
? content.content_type
|
|
974
|
+
: "text",
|
|
975
|
+
parts: ["{{prompt}}"]
|
|
976
|
+
}
|
|
977
|
+
};
|
|
978
|
+
}
|
|
979
|
+
function readTemplateRequestBody(selectedRequest) {
|
|
980
|
+
const requestBodyJson = selectedRequest.requestBodyJson;
|
|
981
|
+
if (requestBodyJson && typeof requestBodyJson === "object" && !Array.isArray(requestBodyJson)) {
|
|
982
|
+
return templateRequestValue(requestBodyJson, {
|
|
983
|
+
parentKey: "",
|
|
984
|
+
parentRole: ""
|
|
985
|
+
});
|
|
986
|
+
}
|
|
987
|
+
const requestBodyText = typeof selectedRequest.requestBodyText === "string"
|
|
988
|
+
? selectedRequest.requestBodyText.trim()
|
|
989
|
+
: "";
|
|
990
|
+
if (!requestBodyText) {
|
|
991
|
+
return undefined;
|
|
992
|
+
}
|
|
993
|
+
const contentType = readSelectedRequestContentType(selectedRequest);
|
|
994
|
+
if (isConnectJsonContentType(contentType)) {
|
|
995
|
+
const connectJson = decodeConnectJsonBody(requestBodyText);
|
|
996
|
+
if (connectJson && typeof connectJson === "object" && !Array.isArray(connectJson)) {
|
|
997
|
+
return templateRequestValue(connectJson, {
|
|
998
|
+
parentKey: "",
|
|
999
|
+
parentRole: ""
|
|
1000
|
+
});
|
|
1001
|
+
}
|
|
1002
|
+
}
|
|
1003
|
+
try {
|
|
1004
|
+
return templateRequestValue(JSON.parse(requestBodyText), {
|
|
1005
|
+
parentKey: "",
|
|
1006
|
+
parentRole: ""
|
|
1007
|
+
});
|
|
1008
|
+
}
|
|
1009
|
+
catch {
|
|
1010
|
+
return requestBodyText;
|
|
1011
|
+
}
|
|
1012
|
+
}
|
|
1013
|
+
function readSeedBinding(selectedRequest) {
|
|
1014
|
+
const requestBodyJson = readRequestBodyObject(selectedRequest);
|
|
1015
|
+
const requestUrl = typeof selectedRequest.url === "string" ? selectedRequest.url : "";
|
|
1016
|
+
const conversationId = readConversationIdFromUrl(requestUrl) ||
|
|
1017
|
+
readFirstNestedStringByKeys(requestBodyJson, [
|
|
1018
|
+
"chat_id",
|
|
1019
|
+
"chat_session_id",
|
|
1020
|
+
"chatSessionId",
|
|
1021
|
+
"conversation_id",
|
|
1022
|
+
"conversationId",
|
|
1023
|
+
"thread_id",
|
|
1024
|
+
"threadId",
|
|
1025
|
+
"session_id",
|
|
1026
|
+
"sessionId"
|
|
1027
|
+
]);
|
|
1028
|
+
const parentId = readFirstNestedStringByKeys(requestBodyJson, [
|
|
1029
|
+
"parent_id",
|
|
1030
|
+
"parentId",
|
|
1031
|
+
"parent_message_id",
|
|
1032
|
+
"parentMessageId",
|
|
1033
|
+
"message_id",
|
|
1034
|
+
"messageId"
|
|
1035
|
+
]);
|
|
1036
|
+
return conversationId
|
|
1037
|
+
? {
|
|
1038
|
+
seedBinding: {
|
|
1039
|
+
conversationId,
|
|
1040
|
+
...(parentId ? { parentId } : {})
|
|
1041
|
+
}
|
|
1042
|
+
}
|
|
1043
|
+
: {};
|
|
1044
|
+
}
|
|
1045
|
+
function readConversationIdFromUrl(requestUrl) {
|
|
1046
|
+
if (!requestUrl) {
|
|
1047
|
+
return "";
|
|
1048
|
+
}
|
|
1049
|
+
try {
|
|
1050
|
+
const url = new URL(requestUrl);
|
|
1051
|
+
for (const key of [
|
|
1052
|
+
"chat_id",
|
|
1053
|
+
"chat_session_id",
|
|
1054
|
+
"chatSessionId",
|
|
1055
|
+
"conversation_id",
|
|
1056
|
+
"conversationId",
|
|
1057
|
+
"thread_id",
|
|
1058
|
+
"threadId",
|
|
1059
|
+
"session_id",
|
|
1060
|
+
"sessionId"
|
|
1061
|
+
]) {
|
|
1062
|
+
const value = url.searchParams.get(key);
|
|
1063
|
+
if (value?.trim()) {
|
|
1064
|
+
return value.trim();
|
|
1065
|
+
}
|
|
1066
|
+
}
|
|
1067
|
+
}
|
|
1068
|
+
catch {
|
|
1069
|
+
return "";
|
|
1070
|
+
}
|
|
1071
|
+
return "";
|
|
1072
|
+
}
|
|
1073
|
+
function readFirstStringByKeys(value, keys) {
|
|
1074
|
+
if (!value) {
|
|
1075
|
+
return "";
|
|
1076
|
+
}
|
|
1077
|
+
for (const key of keys) {
|
|
1078
|
+
const entry = value[key];
|
|
1079
|
+
if (typeof entry === "string" && entry.trim()) {
|
|
1080
|
+
return entry.trim();
|
|
1081
|
+
}
|
|
1082
|
+
if (typeof entry === "number" && Number.isFinite(entry)) {
|
|
1083
|
+
return String(entry);
|
|
1084
|
+
}
|
|
1085
|
+
}
|
|
1086
|
+
return "";
|
|
1087
|
+
}
|
|
1088
|
+
function readFirstNestedStringByKeys(value, keys) {
|
|
1089
|
+
if (!value) {
|
|
1090
|
+
return "";
|
|
1091
|
+
}
|
|
1092
|
+
const direct = readFirstStringByKeys(value, keys);
|
|
1093
|
+
if (direct) {
|
|
1094
|
+
return direct;
|
|
1095
|
+
}
|
|
1096
|
+
for (const entry of Object.values(value)) {
|
|
1097
|
+
if (Array.isArray(entry)) {
|
|
1098
|
+
for (const item of entry) {
|
|
1099
|
+
if (typeof item !== "object" || item === null || Array.isArray(item)) {
|
|
1100
|
+
continue;
|
|
1101
|
+
}
|
|
1102
|
+
const nested = readFirstNestedStringByKeys(item, keys);
|
|
1103
|
+
if (nested) {
|
|
1104
|
+
return nested;
|
|
1105
|
+
}
|
|
1106
|
+
}
|
|
1107
|
+
continue;
|
|
1108
|
+
}
|
|
1109
|
+
if (typeof entry !== "object" || entry === null) {
|
|
1110
|
+
continue;
|
|
1111
|
+
}
|
|
1112
|
+
const nested = readFirstNestedStringByKeys(entry, keys);
|
|
1113
|
+
if (nested) {
|
|
1114
|
+
return nested;
|
|
1115
|
+
}
|
|
1116
|
+
}
|
|
1117
|
+
return "";
|
|
1118
|
+
}
|
|
1119
|
+
function templateRequestValue(value, context) {
|
|
1120
|
+
if (Array.isArray(value)) {
|
|
1121
|
+
if (/^children(ids|_ids)?$/i.test(context.parentKey)) {
|
|
1122
|
+
return [];
|
|
1123
|
+
}
|
|
1124
|
+
return value.map((entry) => templateRequestValue(entry, context));
|
|
1125
|
+
}
|
|
1126
|
+
if (typeof value === "object" && value !== null) {
|
|
1127
|
+
const record = value;
|
|
1128
|
+
const nextRole = typeof record.role === "string" ? record.role.toLowerCase() : context.parentRole;
|
|
1129
|
+
return Object.fromEntries(Object.entries(record).map(([key, entry]) => [
|
|
1130
|
+
key,
|
|
1131
|
+
templateRequestValue(entry, {
|
|
1132
|
+
parentKey: key,
|
|
1133
|
+
parentRole: nextRole
|
|
1134
|
+
})
|
|
1135
|
+
]));
|
|
1136
|
+
}
|
|
1137
|
+
if (typeof value === "number" && Number.isFinite(value)) {
|
|
1138
|
+
const key = context.parentKey.toLowerCase();
|
|
1139
|
+
if (/(^|_)(parent|parentid|parent_id|messageid|message_id)$/.test(key)) {
|
|
1140
|
+
return "{{parentIdNumberOrOmit}}";
|
|
1141
|
+
}
|
|
1142
|
+
if (/(^|_)(timestamp|time|ts)$/.test(key)) {
|
|
1143
|
+
return value >= 1000000000000 ? "{{unixTimestampMs}}" : "{{unixTimestampSec}}";
|
|
1144
|
+
}
|
|
1145
|
+
return value;
|
|
1146
|
+
}
|
|
1147
|
+
if (typeof value === "boolean") {
|
|
1148
|
+
const key = context.parentKey.toLowerCase();
|
|
1149
|
+
if (key === "thinking") {
|
|
1150
|
+
return value ? "{{thinkingEnabledOrTrue}}" : "{{thinkingEnabledOrFalse}}";
|
|
1151
|
+
}
|
|
1152
|
+
return value;
|
|
1153
|
+
}
|
|
1154
|
+
if (typeof value !== "string") {
|
|
1155
|
+
return value;
|
|
1156
|
+
}
|
|
1157
|
+
const key = context.parentKey.toLowerCase();
|
|
1158
|
+
const role = context.parentRole.toLowerCase();
|
|
1159
|
+
if (key === "fid") {
|
|
1160
|
+
return "{{messageId}}";
|
|
1161
|
+
}
|
|
1162
|
+
if ((key === "message_id" || key === "messageid") && value.trim() === "") {
|
|
1163
|
+
return value;
|
|
1164
|
+
}
|
|
1165
|
+
if (/(^|_)(parent|parentid|parent_id|messageid|message_id)$/.test(key) &&
|
|
1166
|
+
/^-?(?:0|[1-9]\d*)$/.test(value.trim())) {
|
|
1167
|
+
return "{{parentIdNumberOrOmit}}";
|
|
1168
|
+
}
|
|
1169
|
+
if (/(^|_)(model|modelid|model_id|models)$/.test(key)) {
|
|
1170
|
+
return "{{modelId}}";
|
|
1171
|
+
}
|
|
1172
|
+
if (/(^|_)(trace|request|requestid|request_id)$/.test(key)) {
|
|
1173
|
+
return "{{requestUuid}}";
|
|
1174
|
+
}
|
|
1175
|
+
if (/(^|_)(conversation|chat|session|thread)(id|_id)?$/.test(key)) {
|
|
1176
|
+
return "{{conversationIdOrOmit}}";
|
|
1177
|
+
}
|
|
1178
|
+
if (/(^|_)(parent|parentid|parent_id|messageid|message_id)$/.test(key)) {
|
|
1179
|
+
return "{{parentIdOrOmit}}";
|
|
1180
|
+
}
|
|
1181
|
+
if (/(^|_)(prompt|input|query|text|message)$/.test(key)) {
|
|
1182
|
+
return "{{prompt}}";
|
|
1183
|
+
}
|
|
1184
|
+
if (key === "content" && (!role || role === "user")) {
|
|
1185
|
+
return "{{prompt}}";
|
|
1186
|
+
}
|
|
1187
|
+
return value;
|
|
1188
|
+
}
|
|
1189
|
+
function readExplicitModelIds(value) {
|
|
1190
|
+
const integrationModels = value.integration?.models?.map((entry) => entry.trim()).filter(Boolean) ?? [];
|
|
1191
|
+
if (integrationModels.length > 0) {
|
|
1192
|
+
return [...new Set(integrationModels)].sort((left, right) => left.localeCompare(right));
|
|
1193
|
+
}
|
|
1194
|
+
const metadataModels = readMetadataModelCatalog(value.metadata);
|
|
1195
|
+
if (metadataModels.length > 0) {
|
|
1196
|
+
return metadataModels;
|
|
1197
|
+
}
|
|
1198
|
+
return null;
|
|
1199
|
+
}
|
|
1200
|
+
function inferModelIdsFromCapture(value) {
|
|
1201
|
+
const selectedRequest = readSelectedRequest(value.metadata);
|
|
1202
|
+
const topLevelModelHints = Array.isArray(selectedRequest?.modelHints)
|
|
1203
|
+
? selectedRequest.modelHints
|
|
1204
|
+
: [];
|
|
1205
|
+
const inferred = typeof selectedRequest?.inferred === "object" && selectedRequest.inferred !== null
|
|
1206
|
+
? selectedRequest.inferred
|
|
1207
|
+
: null;
|
|
1208
|
+
const inferredModelHints = Array.isArray(inferred?.modelHints) ? inferred.modelHints : [];
|
|
1209
|
+
const mirroredSelectedRequest = typeof value.metadata.selectedRequest === "object" && value.metadata.selectedRequest !== null
|
|
1210
|
+
? value.metadata.selectedRequest
|
|
1211
|
+
: null;
|
|
1212
|
+
const mirroredModelHints = Array.isArray(mirroredSelectedRequest?.modelHints)
|
|
1213
|
+
? mirroredSelectedRequest.modelHints
|
|
1214
|
+
: [];
|
|
1215
|
+
const rawModelHints = [...topLevelModelHints, ...inferredModelHints, ...mirroredModelHints];
|
|
1216
|
+
return [
|
|
1217
|
+
...new Set(rawModelHints
|
|
1218
|
+
.filter((entry) => typeof entry === "string")
|
|
1219
|
+
.map((entry) => entry.trim()))
|
|
1220
|
+
]
|
|
1221
|
+
.filter(Boolean)
|
|
1222
|
+
.sort((left, right) => left.localeCompare(right));
|
|
1223
|
+
}
|
|
1224
|
+
function readMetadataModelCatalog(metadata) {
|
|
1225
|
+
const explicitLists = [metadata.availableModels, metadata.supportedModels, metadata.modelCatalog];
|
|
1226
|
+
for (const candidate of explicitLists) {
|
|
1227
|
+
const parsed = normalizeModelCatalogEntries(candidate);
|
|
1228
|
+
if (parsed.length > 0) {
|
|
1229
|
+
return parsed;
|
|
1230
|
+
}
|
|
1231
|
+
}
|
|
1232
|
+
return [];
|
|
1233
|
+
}
|
|
1234
|
+
function normalizeModelCatalogEntries(value) {
|
|
1235
|
+
if (!Array.isArray(value)) {
|
|
1236
|
+
return [];
|
|
1237
|
+
}
|
|
1238
|
+
return [
|
|
1239
|
+
...new Set(value.flatMap((entry) => {
|
|
1240
|
+
if (typeof entry === "string") {
|
|
1241
|
+
const normalized = entry.trim();
|
|
1242
|
+
return normalized ? [normalized] : [];
|
|
1243
|
+
}
|
|
1244
|
+
if (typeof entry !== "object" || entry === null || Array.isArray(entry)) {
|
|
1245
|
+
return [];
|
|
1246
|
+
}
|
|
1247
|
+
for (const key of ["id", "model", "name"]) {
|
|
1248
|
+
const candidate = entry[key];
|
|
1249
|
+
if (typeof candidate === "string" && candidate.trim()) {
|
|
1250
|
+
return [candidate.trim()];
|
|
1251
|
+
}
|
|
1252
|
+
}
|
|
1253
|
+
return [];
|
|
1254
|
+
}))
|
|
1255
|
+
].sort((left, right) => left.localeCompare(right));
|
|
1256
|
+
}
|
|
1257
|
+
function mergeModelIds(existing, inferred) {
|
|
1258
|
+
return [...new Set([...existing, ...inferred])].sort((left, right) => left.localeCompare(right));
|
|
1259
|
+
}
|
|
1260
|
+
function readLabel(value, fallback) {
|
|
1261
|
+
const explicit = value.integration?.label?.trim();
|
|
1262
|
+
if (explicit) {
|
|
1263
|
+
return explicit;
|
|
1264
|
+
}
|
|
1265
|
+
const metadata = value.metadata;
|
|
1266
|
+
const title = typeof metadata.tabTitle === "string" ? metadata.tabTitle.trim() : "";
|
|
1267
|
+
if (title) {
|
|
1268
|
+
return title;
|
|
1269
|
+
}
|
|
1270
|
+
try {
|
|
1271
|
+
return new URL(value.origin).hostname;
|
|
1272
|
+
}
|
|
1273
|
+
catch {
|
|
1274
|
+
return fallback;
|
|
1275
|
+
}
|
|
1276
|
+
}
|
|
1277
|
+
function readSelectedRequest(metadata) {
|
|
1278
|
+
const capture = metadata.requestCapture;
|
|
1279
|
+
if (typeof capture !== "object" || capture === null) {
|
|
1280
|
+
return null;
|
|
1281
|
+
}
|
|
1282
|
+
const selectedRequest = capture.selectedRequest;
|
|
1283
|
+
return typeof selectedRequest === "object" && selectedRequest !== null
|
|
1284
|
+
? selectedRequest
|
|
1285
|
+
: null;
|
|
1286
|
+
}
|
|
1287
|
+
function readUsesSse(selectedRequest) {
|
|
1288
|
+
if (selectedRequest.usesSse === true) {
|
|
1289
|
+
return true;
|
|
1290
|
+
}
|
|
1291
|
+
const inferred = selectedRequest.inferred;
|
|
1292
|
+
if (typeof inferred === "object" &&
|
|
1293
|
+
inferred !== null &&
|
|
1294
|
+
inferred.usesSse === true) {
|
|
1295
|
+
return true;
|
|
1296
|
+
}
|
|
1297
|
+
return false;
|
|
1298
|
+
}
|
|
1299
|
+
function readTransportFamily(selectedRequest) {
|
|
1300
|
+
if (readUsesSse(selectedRequest)) {
|
|
1301
|
+
return "http-sse";
|
|
1302
|
+
}
|
|
1303
|
+
if (isConnectJsonContentType(readSelectedRequestContentType(selectedRequest))) {
|
|
1304
|
+
return "http-connect";
|
|
1305
|
+
}
|
|
1306
|
+
return "http-json";
|
|
1307
|
+
}
|
|
1308
|
+
function readSelectedRequestContentType(selectedRequest) {
|
|
1309
|
+
const direct = selectedRequest.contentType;
|
|
1310
|
+
if (typeof direct === "string" && direct.trim()) {
|
|
1311
|
+
return direct.trim();
|
|
1312
|
+
}
|
|
1313
|
+
const headers = readSelectedRequestHeaders(selectedRequest);
|
|
1314
|
+
if (typeof headers !== "object" || headers === null || Array.isArray(headers)) {
|
|
1315
|
+
return "";
|
|
1316
|
+
}
|
|
1317
|
+
const entry = Object.entries(headers).find(([key]) => key.toLowerCase() === "content-type")?.[1];
|
|
1318
|
+
return typeof entry === "string" ? entry.trim() : "";
|
|
1319
|
+
}
|
|
1320
|
+
function readSelectedRequestHeaders(selectedRequest) {
|
|
1321
|
+
for (const key of ["headers", "requestHeaders"]) {
|
|
1322
|
+
const candidate = selectedRequest[key];
|
|
1323
|
+
if (typeof candidate === "object" && candidate !== null && !Array.isArray(candidate)) {
|
|
1324
|
+
return candidate;
|
|
1325
|
+
}
|
|
1326
|
+
}
|
|
1327
|
+
return null;
|
|
1328
|
+
}
|
|
1329
|
+
function isConnectJsonContentType(value) {
|
|
1330
|
+
return /^application\/connect\+json\b/i.test(value.trim());
|
|
1331
|
+
}
|
|
1332
|
+
function isZaiBootstrapRequestUrl(value) {
|
|
1333
|
+
try {
|
|
1334
|
+
const url = new URL(value);
|
|
1335
|
+
return url.origin === "https://chat.z.ai" && url.pathname === "/api/v1/chats/new";
|
|
1336
|
+
}
|
|
1337
|
+
catch {
|
|
1338
|
+
return false;
|
|
1339
|
+
}
|
|
1340
|
+
}
|
|
1341
|
+
function readRequestBodyObject(selectedRequest) {
|
|
1342
|
+
const requestBodyJson = selectedRequest.requestBodyJson;
|
|
1343
|
+
if (requestBodyJson && typeof requestBodyJson === "object" && !Array.isArray(requestBodyJson)) {
|
|
1344
|
+
return requestBodyJson;
|
|
1345
|
+
}
|
|
1346
|
+
const requestBodyText = typeof selectedRequest.requestBodyText === "string"
|
|
1347
|
+
? selectedRequest.requestBodyText.trim()
|
|
1348
|
+
: "";
|
|
1349
|
+
if (!requestBodyText) {
|
|
1350
|
+
return null;
|
|
1351
|
+
}
|
|
1352
|
+
if (isConnectJsonContentType(readSelectedRequestContentType(selectedRequest))) {
|
|
1353
|
+
const decoded = decodeConnectJsonBody(requestBodyText);
|
|
1354
|
+
if (decoded && typeof decoded === "object" && !Array.isArray(decoded)) {
|
|
1355
|
+
return decoded;
|
|
1356
|
+
}
|
|
1357
|
+
}
|
|
1358
|
+
try {
|
|
1359
|
+
const parsed = JSON.parse(requestBodyText);
|
|
1360
|
+
return typeof parsed === "object" && parsed !== null && !Array.isArray(parsed)
|
|
1361
|
+
? parsed
|
|
1362
|
+
: null;
|
|
1363
|
+
}
|
|
1364
|
+
catch {
|
|
1365
|
+
return null;
|
|
1366
|
+
}
|
|
1367
|
+
}
|
|
1368
|
+
function decodeConnectJsonBody(value) {
|
|
1369
|
+
const encoded = value.trim();
|
|
1370
|
+
if (!encoded) {
|
|
1371
|
+
return null;
|
|
1372
|
+
}
|
|
1373
|
+
const bytes = Uint8Array.from(encoded, (char) => char.charCodeAt(0) & 0xff);
|
|
1374
|
+
if (bytes.length >= 5) {
|
|
1375
|
+
const length = ((bytes[1] ?? 0) << 24) | ((bytes[2] ?? 0) << 16) | ((bytes[3] ?? 0) << 8) | (bytes[4] ?? 0);
|
|
1376
|
+
if (length > 0 && bytes.length >= 5 + length) {
|
|
1377
|
+
const payload = new TextDecoder().decode(bytes.slice(5, 5 + length)).trim();
|
|
1378
|
+
if (payload) {
|
|
1379
|
+
try {
|
|
1380
|
+
return JSON.parse(payload);
|
|
1381
|
+
}
|
|
1382
|
+
catch {
|
|
1383
|
+
// Fall through to the textual JSON-start recovery path below.
|
|
1384
|
+
}
|
|
1385
|
+
}
|
|
1386
|
+
}
|
|
1387
|
+
}
|
|
1388
|
+
const jsonStart = [...encoded].findIndex((char) => char === "{" || char === "[");
|
|
1389
|
+
if (jsonStart < 0) {
|
|
1390
|
+
return null;
|
|
1391
|
+
}
|
|
1392
|
+
try {
|
|
1393
|
+
return JSON.parse(encoded.slice(jsonStart).trim());
|
|
1394
|
+
}
|
|
1395
|
+
catch {
|
|
1396
|
+
return null;
|
|
1397
|
+
}
|
|
1398
|
+
}
|
|
1399
|
+
function readConfiguredModelIds(config) {
|
|
1400
|
+
if (!config || !Array.isArray(config.models)) {
|
|
1401
|
+
return [];
|
|
1402
|
+
}
|
|
1403
|
+
return [
|
|
1404
|
+
...new Set(config.models
|
|
1405
|
+
.filter((value) => typeof value === "string")
|
|
1406
|
+
.map((value) => value.trim()))
|
|
1407
|
+
]
|
|
1408
|
+
.filter(Boolean)
|
|
1409
|
+
.sort((left, right) => left.localeCompare(right));
|
|
1410
|
+
}
|
|
1411
|
+
function readConfiguredTransport(config) {
|
|
1412
|
+
if (!config) {
|
|
1413
|
+
return null;
|
|
1414
|
+
}
|
|
1415
|
+
const transport = config.transport;
|
|
1416
|
+
if (typeof transport !== "object" || transport === null || Array.isArray(transport)) {
|
|
1417
|
+
return null;
|
|
1418
|
+
}
|
|
1419
|
+
return transport;
|
|
1420
|
+
}
|
|
1421
|
+
function hasBearerAuthorization(headers) {
|
|
1422
|
+
const authorization = Object.entries(headers).find(([key]) => key.toLowerCase() === "authorization")?.[1];
|
|
1423
|
+
return typeof authorization === "string" && /^Bearer\s+\S+/i.test(authorization);
|
|
1424
|
+
}
|
|
1425
|
+
function hasHeader(headers, headerName) {
|
|
1426
|
+
const target = headerName.toLowerCase();
|
|
1427
|
+
return Object.entries(headers).some(([key, value]) => key.toLowerCase() === target && typeof value === "string" && value.trim());
|
|
1428
|
+
}
|
|
1429
|
+
function readLifecycleIsoString(value, key) {
|
|
1430
|
+
if (typeof value !== "object" || value === null) {
|
|
1431
|
+
return undefined;
|
|
1432
|
+
}
|
|
1433
|
+
const record = value;
|
|
1434
|
+
const candidate = record[key];
|
|
1435
|
+
if (typeof candidate !== "string") {
|
|
1436
|
+
return undefined;
|
|
1437
|
+
}
|
|
1438
|
+
return z.string().datetime({ offset: true }).safeParse(candidate).success ? candidate : undefined;
|
|
1439
|
+
}
|
|
1440
|
+
function createTimestamp(previous) {
|
|
1441
|
+
const previousTime = previous ? Date.parse(previous) : 0;
|
|
1442
|
+
const now = Date.now();
|
|
1443
|
+
const nextTime = previousTime >= now ? previousTime + 1 : now;
|
|
1444
|
+
return new Date(nextTime).toISOString();
|
|
1445
|
+
}
|
|
1446
|
+
function missingProviderError(id) {
|
|
1447
|
+
return new BridgeApiError({
|
|
1448
|
+
statusCode: 404,
|
|
1449
|
+
code: "provider_not_found",
|
|
1450
|
+
message: `Provider '${id}' was not found.`
|
|
1451
|
+
});
|
|
1452
|
+
}
|
|
1453
|
+
const DEFAULT_SSE_CONTENT_PATHS = [
|
|
1454
|
+
"v.message.content.parts.*",
|
|
1455
|
+
"message.content.parts.*",
|
|
1456
|
+
"choices.0.delta.content",
|
|
1457
|
+
"data.choices.0.delta.content",
|
|
1458
|
+
"v.response.fragments.*.content",
|
|
1459
|
+
"response.fragments.*.content",
|
|
1460
|
+
"delta.content",
|
|
1461
|
+
"content"
|
|
1462
|
+
];
|
|
1463
|
+
const DEFAULT_CONNECT_CONTENT_PATHS = [
|
|
1464
|
+
"choices.0.delta.content",
|
|
1465
|
+
"data.choices.0.delta.content",
|
|
1466
|
+
"message.content",
|
|
1467
|
+
"message.blocks.*.text.content",
|
|
1468
|
+
"block.text.content",
|
|
1469
|
+
"blocks.*.text.content",
|
|
1470
|
+
"delta.content",
|
|
1471
|
+
"text",
|
|
1472
|
+
"content"
|
|
1473
|
+
];
|
|
1474
|
+
const DEFAULT_JSON_CONTENT_PATHS = [
|
|
1475
|
+
"choices.0.message.content",
|
|
1476
|
+
"message.content",
|
|
1477
|
+
"output_text",
|
|
1478
|
+
"content",
|
|
1479
|
+
"data.content"
|
|
1480
|
+
];
|
|
1481
|
+
const DEFAULT_RESPONSE_ID_PATHS = [
|
|
1482
|
+
"v.message.id",
|
|
1483
|
+
"response_id",
|
|
1484
|
+
"response_message_id",
|
|
1485
|
+
"id",
|
|
1486
|
+
"message.id",
|
|
1487
|
+
"message_id",
|
|
1488
|
+
"block.messageId",
|
|
1489
|
+
"data.id",
|
|
1490
|
+
"response.id",
|
|
1491
|
+
"response.message_id",
|
|
1492
|
+
"v.response.message_id"
|
|
1493
|
+
];
|
|
1494
|
+
const DEFAULT_CONVERSATION_ID_PATHS = [
|
|
1495
|
+
"v.conversation_id",
|
|
1496
|
+
"conversation_id",
|
|
1497
|
+
"conversation.id",
|
|
1498
|
+
"conversationId",
|
|
1499
|
+
"chat.id",
|
|
1500
|
+
"chat_id",
|
|
1501
|
+
"thread.id",
|
|
1502
|
+
"thread_id",
|
|
1503
|
+
"threadId",
|
|
1504
|
+
"session.id",
|
|
1505
|
+
"session_id",
|
|
1506
|
+
"sessionId",
|
|
1507
|
+
"data.conversation_id",
|
|
1508
|
+
"data.chat_id",
|
|
1509
|
+
"data.thread_id",
|
|
1510
|
+
"response.conversation_id"
|
|
1511
|
+
];
|
|
1512
|
+
export const sessionPackageStoreModule = {
|
|
1513
|
+
sessionPackageSchema,
|
|
1514
|
+
sessionPackageStatusResponseSchema,
|
|
1515
|
+
sessionPackageDeleteResponseSchema,
|
|
1516
|
+
sessionPackageMetadataSchema,
|
|
1517
|
+
installedProviderPackageSchema,
|
|
1518
|
+
createInMemorySessionPackageStore,
|
|
1519
|
+
buildSessionPackageStatus,
|
|
1520
|
+
cloneProvider,
|
|
1521
|
+
cloneConfig,
|
|
1522
|
+
cloneSessionPackage,
|
|
1523
|
+
cloneSessionPackageMetadata,
|
|
1524
|
+
cloneInstalledProviderPackage,
|
|
1525
|
+
buildSessionPackageMetadata,
|
|
1526
|
+
inferProviderFromSessionPackage
|
|
1527
|
+
};
|