@nextclaw/server 0.5.17 → 0.5.19
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/index.d.ts +57 -1
- package/dist/index.js +213 -17
- package/package.json +2 -2
package/dist/index.d.ts
CHANGED
|
@@ -147,6 +147,49 @@ type RuntimeConfigUpdate = {
|
|
|
147
147
|
bindings?: AgentBindingView[];
|
|
148
148
|
session?: SessionConfigView;
|
|
149
149
|
};
|
|
150
|
+
type SecretSourceView = "env" | "file" | "exec";
|
|
151
|
+
type SecretRefView = {
|
|
152
|
+
source: SecretSourceView;
|
|
153
|
+
provider?: string;
|
|
154
|
+
id: string;
|
|
155
|
+
};
|
|
156
|
+
type SecretProviderEnvView = {
|
|
157
|
+
source: "env";
|
|
158
|
+
prefix?: string;
|
|
159
|
+
};
|
|
160
|
+
type SecretProviderFileView = {
|
|
161
|
+
source: "file";
|
|
162
|
+
path: string;
|
|
163
|
+
format?: "json";
|
|
164
|
+
};
|
|
165
|
+
type SecretProviderExecView = {
|
|
166
|
+
source: "exec";
|
|
167
|
+
command: string;
|
|
168
|
+
args?: string[];
|
|
169
|
+
cwd?: string;
|
|
170
|
+
timeoutMs?: number;
|
|
171
|
+
};
|
|
172
|
+
type SecretProviderView = SecretProviderEnvView | SecretProviderFileView | SecretProviderExecView;
|
|
173
|
+
type SecretsView = {
|
|
174
|
+
enabled: boolean;
|
|
175
|
+
defaults: {
|
|
176
|
+
env?: string;
|
|
177
|
+
file?: string;
|
|
178
|
+
exec?: string;
|
|
179
|
+
};
|
|
180
|
+
providers: Record<string, SecretProviderView>;
|
|
181
|
+
refs: Record<string, SecretRefView>;
|
|
182
|
+
};
|
|
183
|
+
type SecretsConfigUpdate = {
|
|
184
|
+
enabled?: boolean;
|
|
185
|
+
defaults?: {
|
|
186
|
+
env?: string | null;
|
|
187
|
+
file?: string | null;
|
|
188
|
+
exec?: string | null;
|
|
189
|
+
};
|
|
190
|
+
providers?: Record<string, SecretProviderView> | null;
|
|
191
|
+
refs?: Record<string, SecretRefView> | null;
|
|
192
|
+
};
|
|
150
193
|
type ChatTurnRequest = {
|
|
151
194
|
message: string;
|
|
152
195
|
sessionKey?: string;
|
|
@@ -163,6 +206,16 @@ type ChatTurnResult = {
|
|
|
163
206
|
model?: string;
|
|
164
207
|
metadata?: Record<string, unknown>;
|
|
165
208
|
};
|
|
209
|
+
type ChatTurnStreamEvent = {
|
|
210
|
+
type: "delta";
|
|
211
|
+
delta: string;
|
|
212
|
+
} | {
|
|
213
|
+
type: "final";
|
|
214
|
+
result: ChatTurnResult;
|
|
215
|
+
} | {
|
|
216
|
+
type: "error";
|
|
217
|
+
error: string;
|
|
218
|
+
};
|
|
166
219
|
type ChatTurnView = {
|
|
167
220
|
reply: string;
|
|
168
221
|
sessionKey: string;
|
|
@@ -174,6 +227,7 @@ type ChatTurnView = {
|
|
|
174
227
|
};
|
|
175
228
|
type UiChatRuntime = {
|
|
176
229
|
processTurn: (params: ChatTurnRequest) => Promise<ChatTurnResult>;
|
|
230
|
+
processTurnStream?: (params: ChatTurnRequest) => AsyncGenerator<ChatTurnStreamEvent>;
|
|
177
231
|
};
|
|
178
232
|
type ConfigView = {
|
|
179
233
|
agents: {
|
|
@@ -206,6 +260,7 @@ type ConfigView = {
|
|
|
206
260
|
tools?: Record<string, unknown>;
|
|
207
261
|
gateway?: Record<string, unknown>;
|
|
208
262
|
ui?: Record<string, unknown>;
|
|
263
|
+
secrets?: SecretsView;
|
|
209
264
|
};
|
|
210
265
|
type ProviderSpecView = {
|
|
211
266
|
name: string;
|
|
@@ -522,5 +577,6 @@ declare function getSessionHistory(configPath: string, key: string, limit?: numb
|
|
|
522
577
|
declare function patchSession(configPath: string, key: string, patch: SessionPatchUpdate): SessionHistoryView | null;
|
|
523
578
|
declare function deleteSession(configPath: string, key: string): boolean;
|
|
524
579
|
declare function updateRuntime(configPath: string, patch: RuntimeConfigUpdate): Pick<ConfigView, "agents" | "bindings" | "session">;
|
|
580
|
+
declare function updateSecrets(configPath: string, patch: SecretsConfigUpdate): SecretsView;
|
|
525
581
|
|
|
526
|
-
export { type AgentBindingView, type AgentProfileView, type ApiError, type ApiResponse, type BindingPeerView, type ChannelSpecView, type ChatTurnRequest, type ChatTurnResult, type ChatTurnView, type ConfigActionExecuteRequest, type ConfigActionExecuteResult, type ConfigActionManifest, type ConfigActionType, type ConfigMetaView, type ConfigSchemaResponse, type ConfigUiHint, type ConfigUiHints, type ConfigView, type CronActionResult, type CronEnableRequest, type CronJobStateView, type CronJobView, type CronListView, type CronPayloadView, type CronRunRequest, type CronScheduleView, type MarketplaceApiConfig, type MarketplaceInstallKind, type MarketplaceInstallSkillParams, type MarketplaceInstallSpec, type MarketplaceInstalledRecord, type MarketplaceInstalledView, type MarketplaceInstaller, type MarketplaceItemSummary, type MarketplaceItemType, type MarketplaceItemView, type MarketplaceListView, type MarketplacePluginInstallRequest, type MarketplacePluginInstallResult, type MarketplacePluginManageAction, type MarketplacePluginManageRequest, type MarketplacePluginManageResult, type MarketplaceRecommendationView, type MarketplaceSkillInstallRequest, type MarketplaceSkillInstallResult, type MarketplaceSkillManageAction, type MarketplaceSkillManageRequest, type MarketplaceSkillManageResult, type MarketplaceSort, type ProviderConfigUpdate, type ProviderConfigView, type ProviderSpecView, type RuntimeConfigUpdate, type SessionConfigView, type SessionEntryView, type SessionHistoryView, type SessionMessageView, type SessionPatchUpdate, type SessionsListView, type UiChatRuntime, type UiServerEvent, type UiServerHandle, type UiServerOptions, buildConfigMeta, buildConfigSchemaView, buildConfigView, createUiRouter, deleteSession, executeConfigAction, getSessionHistory, listSessions, loadConfigOrDefault, patchSession, startUiServer, updateChannel, updateModel, updateProvider, updateRuntime };
|
|
582
|
+
export { type AgentBindingView, type AgentProfileView, type ApiError, type ApiResponse, type BindingPeerView, type ChannelSpecView, type ChatTurnRequest, type ChatTurnResult, type ChatTurnStreamEvent, type ChatTurnView, type ConfigActionExecuteRequest, type ConfigActionExecuteResult, type ConfigActionManifest, type ConfigActionType, type ConfigMetaView, type ConfigSchemaResponse, type ConfigUiHint, type ConfigUiHints, type ConfigView, type CronActionResult, type CronEnableRequest, type CronJobStateView, type CronJobView, type CronListView, type CronPayloadView, type CronRunRequest, type CronScheduleView, type MarketplaceApiConfig, type MarketplaceInstallKind, type MarketplaceInstallSkillParams, type MarketplaceInstallSpec, type MarketplaceInstalledRecord, type MarketplaceInstalledView, type MarketplaceInstaller, type MarketplaceItemSummary, type MarketplaceItemType, type MarketplaceItemView, type MarketplaceListView, type MarketplacePluginInstallRequest, type MarketplacePluginInstallResult, type MarketplacePluginManageAction, type MarketplacePluginManageRequest, type MarketplacePluginManageResult, type MarketplaceRecommendationView, type MarketplaceSkillInstallRequest, type MarketplaceSkillInstallResult, type MarketplaceSkillManageAction, type MarketplaceSkillManageRequest, type MarketplaceSkillManageResult, type MarketplaceSort, type ProviderConfigUpdate, type ProviderConfigView, type ProviderSpecView, type RuntimeConfigUpdate, type SecretProviderEnvView, type SecretProviderExecView, type SecretProviderFileView, type SecretProviderView, type SecretRefView, type SecretSourceView, type SecretsConfigUpdate, type SecretsView, type SessionConfigView, type SessionEntryView, type SessionHistoryView, type SessionMessageView, type SessionPatchUpdate, type SessionsListView, type UiChatRuntime, type UiServerEvent, type UiServerHandle, type UiServerOptions, buildConfigMeta, buildConfigSchemaView, buildConfigView, createUiRouter, deleteSession, executeConfigAction, getSessionHistory, listSessions, loadConfigOrDefault, patchSession, startUiServer, updateChannel, updateModel, updateProvider, updateRuntime, updateSecrets };
|
package/dist/index.js
CHANGED
|
@@ -23,6 +23,7 @@ import {
|
|
|
23
23
|
buildConfigSchema,
|
|
24
24
|
findProviderByName,
|
|
25
25
|
getPackageVersion,
|
|
26
|
+
hasSecretRef,
|
|
26
27
|
isSensitiveConfigPath,
|
|
27
28
|
SessionManager,
|
|
28
29
|
getWorkspacePathFromConfig
|
|
@@ -230,7 +231,9 @@ function maskApiKey(value) {
|
|
|
230
231
|
apiKeyMasked: `${value.slice(0, 2)}****${value.slice(-4)}`
|
|
231
232
|
};
|
|
232
233
|
}
|
|
233
|
-
function toProviderView(provider, providerName, uiHints, spec) {
|
|
234
|
+
function toProviderView(config, provider, providerName, uiHints, spec) {
|
|
235
|
+
const apiKeyPath = `providers.${providerName}.apiKey`;
|
|
236
|
+
const apiKeyRefSet = hasSecretRef(config, apiKeyPath);
|
|
234
237
|
const masked = maskApiKey(provider.apiKey);
|
|
235
238
|
const extraHeaders = provider.extraHeaders && Object.keys(provider.extraHeaders).length > 0 ? sanitizePublicConfigValue(
|
|
236
239
|
provider.extraHeaders,
|
|
@@ -238,8 +241,8 @@ function toProviderView(provider, providerName, uiHints, spec) {
|
|
|
238
241
|
uiHints
|
|
239
242
|
) : null;
|
|
240
243
|
const view = {
|
|
241
|
-
apiKeySet: masked.apiKeySet,
|
|
242
|
-
apiKeyMasked: masked.apiKeyMasked,
|
|
244
|
+
apiKeySet: masked.apiKeySet || apiKeyRefSet,
|
|
245
|
+
apiKeyMasked: masked.apiKeyMasked ?? (apiKeyRefSet ? "****" : void 0),
|
|
243
246
|
apiBase: provider.apiBase ?? null,
|
|
244
247
|
extraHeaders: extraHeaders && Object.keys(extraHeaders).length > 0 ? extraHeaders : null
|
|
245
248
|
};
|
|
@@ -253,7 +256,7 @@ function buildConfigView(config) {
|
|
|
253
256
|
const providers = {};
|
|
254
257
|
for (const [name, provider] of Object.entries(config.providers)) {
|
|
255
258
|
const spec = findProviderByName(name);
|
|
256
|
-
providers[name] = toProviderView(provider, name, uiHints, spec);
|
|
259
|
+
providers[name] = toProviderView(config, provider, name, uiHints, spec);
|
|
257
260
|
}
|
|
258
261
|
return {
|
|
259
262
|
agents: config.agents,
|
|
@@ -267,9 +270,20 @@ function buildConfigView(config) {
|
|
|
267
270
|
session: sanitizePublicConfigValue(config.session, "session", uiHints),
|
|
268
271
|
tools: sanitizePublicConfigValue(config.tools, "tools", uiHints),
|
|
269
272
|
gateway: sanitizePublicConfigValue(config.gateway, "gateway", uiHints),
|
|
270
|
-
ui: sanitizePublicConfigValue(config.ui, "ui", uiHints)
|
|
273
|
+
ui: sanitizePublicConfigValue(config.ui, "ui", uiHints),
|
|
274
|
+
secrets: {
|
|
275
|
+
enabled: config.secrets.enabled,
|
|
276
|
+
defaults: { ...config.secrets.defaults },
|
|
277
|
+
providers: { ...config.secrets.providers },
|
|
278
|
+
refs: { ...config.secrets.refs }
|
|
279
|
+
}
|
|
271
280
|
};
|
|
272
281
|
}
|
|
282
|
+
function clearSecretRef(config, path) {
|
|
283
|
+
if (config.secrets.refs[path]) {
|
|
284
|
+
delete config.secrets.refs[path];
|
|
285
|
+
}
|
|
286
|
+
}
|
|
273
287
|
function buildConfigMeta(config) {
|
|
274
288
|
const providers = PROVIDERS.map((spec) => ({
|
|
275
289
|
name: spec.name,
|
|
@@ -369,6 +383,7 @@ function updateProvider(configPath, providerName, patch) {
|
|
|
369
383
|
const spec = findProviderByName(providerName);
|
|
370
384
|
if (Object.prototype.hasOwnProperty.call(patch, "apiKey")) {
|
|
371
385
|
provider.apiKey = patch.apiKey ?? "";
|
|
386
|
+
clearSecretRef(config, `providers.${providerName}.apiKey`);
|
|
372
387
|
}
|
|
373
388
|
if (Object.prototype.hasOwnProperty.call(patch, "apiBase")) {
|
|
374
389
|
provider.apiBase = patch.apiBase ?? null;
|
|
@@ -383,7 +398,7 @@ function updateProvider(configPath, providerName, patch) {
|
|
|
383
398
|
saveConfig(next, configPath);
|
|
384
399
|
const uiHints = buildUiHints(next);
|
|
385
400
|
const updated = next.providers[providerName];
|
|
386
|
-
return toProviderView(updated, providerName, uiHints, spec ?? void 0);
|
|
401
|
+
return toProviderView(next, updated, providerName, uiHints, spec ?? void 0);
|
|
387
402
|
}
|
|
388
403
|
function updateChannel(configPath, channelName, patch) {
|
|
389
404
|
const config = loadConfigOrDefault(configPath);
|
|
@@ -391,6 +406,12 @@ function updateChannel(configPath, channelName, patch) {
|
|
|
391
406
|
if (!channel) {
|
|
392
407
|
return null;
|
|
393
408
|
}
|
|
409
|
+
for (const key of Object.keys(patch)) {
|
|
410
|
+
const path = `channels.${channelName}.${key}`;
|
|
411
|
+
if (isSensitivePath(path)) {
|
|
412
|
+
clearSecretRef(config, path);
|
|
413
|
+
}
|
|
414
|
+
}
|
|
394
415
|
config.channels[channelName] = { ...channel, ...patch };
|
|
395
416
|
const next = ConfigSchema.parse(config);
|
|
396
417
|
saveConfig(next, configPath);
|
|
@@ -575,6 +596,41 @@ function updateRuntime(configPath, patch) {
|
|
|
575
596
|
session: view.session ?? {}
|
|
576
597
|
};
|
|
577
598
|
}
|
|
599
|
+
function updateSecrets(configPath, patch) {
|
|
600
|
+
const config = loadConfigOrDefault(configPath);
|
|
601
|
+
if (Object.prototype.hasOwnProperty.call(patch, "enabled")) {
|
|
602
|
+
config.secrets.enabled = Boolean(patch.enabled);
|
|
603
|
+
}
|
|
604
|
+
if (patch.defaults) {
|
|
605
|
+
const nextDefaults = { ...config.secrets.defaults };
|
|
606
|
+
for (const source of ["env", "file", "exec"]) {
|
|
607
|
+
if (!Object.prototype.hasOwnProperty.call(patch.defaults, source)) {
|
|
608
|
+
continue;
|
|
609
|
+
}
|
|
610
|
+
const value = patch.defaults[source];
|
|
611
|
+
if (typeof value === "string" && value.trim()) {
|
|
612
|
+
nextDefaults[source] = value.trim();
|
|
613
|
+
} else {
|
|
614
|
+
delete nextDefaults[source];
|
|
615
|
+
}
|
|
616
|
+
}
|
|
617
|
+
config.secrets.defaults = nextDefaults;
|
|
618
|
+
}
|
|
619
|
+
if (Object.prototype.hasOwnProperty.call(patch, "providers")) {
|
|
620
|
+
config.secrets.providers = patch.providers ?? {};
|
|
621
|
+
}
|
|
622
|
+
if (Object.prototype.hasOwnProperty.call(patch, "refs")) {
|
|
623
|
+
config.secrets.refs = patch.refs ?? {};
|
|
624
|
+
}
|
|
625
|
+
const next = ConfigSchema.parse(config);
|
|
626
|
+
saveConfig(next, configPath);
|
|
627
|
+
return {
|
|
628
|
+
enabled: next.secrets.enabled,
|
|
629
|
+
defaults: { ...next.secrets.defaults },
|
|
630
|
+
providers: { ...next.secrets.providers },
|
|
631
|
+
refs: { ...next.secrets.refs }
|
|
632
|
+
};
|
|
633
|
+
}
|
|
578
634
|
|
|
579
635
|
// src/ui/router.ts
|
|
580
636
|
var DEFAULT_MARKETPLACE_API_BASE = "https://marketplace-api.nextclaw.io";
|
|
@@ -763,6 +819,24 @@ function resolveAgentIdFromSessionKey(sessionKey) {
|
|
|
763
819
|
const agentId = readNonEmptyString(parsed?.agentId);
|
|
764
820
|
return agentId;
|
|
765
821
|
}
|
|
822
|
+
function buildChatTurnView(params) {
|
|
823
|
+
const completedAt = /* @__PURE__ */ new Date();
|
|
824
|
+
return {
|
|
825
|
+
reply: String(params.result.reply ?? ""),
|
|
826
|
+
sessionKey: readNonEmptyString(params.result.sessionKey) ?? params.fallbackSessionKey,
|
|
827
|
+
...readNonEmptyString(params.result.agentId) || params.requestedAgentId ? { agentId: readNonEmptyString(params.result.agentId) ?? params.requestedAgentId } : {},
|
|
828
|
+
...readNonEmptyString(params.result.model) || params.requestedModel ? { model: readNonEmptyString(params.result.model) ?? params.requestedModel } : {},
|
|
829
|
+
requestedAt: params.requestedAt.toISOString(),
|
|
830
|
+
completedAt: completedAt.toISOString(),
|
|
831
|
+
durationMs: Math.max(0, completedAt.getTime() - params.startedAtMs)
|
|
832
|
+
};
|
|
833
|
+
}
|
|
834
|
+
function toSseFrame(event, data) {
|
|
835
|
+
return `event: ${event}
|
|
836
|
+
data: ${JSON.stringify(data)}
|
|
837
|
+
|
|
838
|
+
`;
|
|
839
|
+
}
|
|
766
840
|
function normalizeMarketplaceBaseUrl(options) {
|
|
767
841
|
const fromOptions = options.marketplace?.apiBaseUrl?.trim();
|
|
768
842
|
const fromEnv = process.env.NEXTCLAW_MARKETPLACE_API_BASE?.trim();
|
|
@@ -1506,6 +1580,15 @@ function createUiRouter(options) {
|
|
|
1506
1580
|
options.publish({ type: "config.updated", payload: { path: `channels.${channel}` } });
|
|
1507
1581
|
return c.json(ok(result));
|
|
1508
1582
|
});
|
|
1583
|
+
app.put("/api/config/secrets", async (c) => {
|
|
1584
|
+
const body = await readJson(c.req.raw);
|
|
1585
|
+
if (!body.ok) {
|
|
1586
|
+
return c.json(err("INVALID_BODY", "invalid json body"), 400);
|
|
1587
|
+
}
|
|
1588
|
+
const result = updateSecrets(options.configPath, body.data);
|
|
1589
|
+
options.publish({ type: "config.updated", payload: { path: "secrets" } });
|
|
1590
|
+
return c.json(ok(result));
|
|
1591
|
+
});
|
|
1509
1592
|
app.post("/api/chat/turn", async (c) => {
|
|
1510
1593
|
if (!options.chatRuntime) {
|
|
1511
1594
|
return c.json(err("NOT_AVAILABLE", "chat runtime unavailable"), 503);
|
|
@@ -1535,22 +1618,134 @@ function createUiRouter(options) {
|
|
|
1535
1618
|
};
|
|
1536
1619
|
try {
|
|
1537
1620
|
const result = await options.chatRuntime.processTurn(request);
|
|
1538
|
-
const
|
|
1539
|
-
|
|
1540
|
-
|
|
1541
|
-
|
|
1542
|
-
|
|
1543
|
-
|
|
1544
|
-
|
|
1545
|
-
|
|
1546
|
-
durationMs: Math.max(0, completedAt.getTime() - startedAtMs)
|
|
1547
|
-
};
|
|
1621
|
+
const response = buildChatTurnView({
|
|
1622
|
+
result,
|
|
1623
|
+
fallbackSessionKey: sessionKey,
|
|
1624
|
+
requestedAgentId,
|
|
1625
|
+
requestedModel,
|
|
1626
|
+
requestedAt,
|
|
1627
|
+
startedAtMs
|
|
1628
|
+
});
|
|
1548
1629
|
options.publish({ type: "config.updated", payload: { path: "session" } });
|
|
1549
1630
|
return c.json(ok(response));
|
|
1550
1631
|
} catch (error) {
|
|
1551
1632
|
return c.json(err("CHAT_TURN_FAILED", String(error)), 500);
|
|
1552
1633
|
}
|
|
1553
1634
|
});
|
|
1635
|
+
app.post("/api/chat/turn/stream", async (c) => {
|
|
1636
|
+
const chatRuntime = options.chatRuntime;
|
|
1637
|
+
if (!chatRuntime) {
|
|
1638
|
+
return c.json(err("NOT_AVAILABLE", "chat runtime unavailable"), 503);
|
|
1639
|
+
}
|
|
1640
|
+
const body = await readJson(c.req.raw);
|
|
1641
|
+
if (!body.ok) {
|
|
1642
|
+
return c.json(err("INVALID_BODY", "invalid json body"), 400);
|
|
1643
|
+
}
|
|
1644
|
+
const message = readNonEmptyString(body.data.message);
|
|
1645
|
+
if (!message) {
|
|
1646
|
+
return c.json(err("INVALID_BODY", "message is required"), 400);
|
|
1647
|
+
}
|
|
1648
|
+
const sessionKey = readNonEmptyString(body.data.sessionKey) ?? `ui:${Date.now().toString(36)}:${Math.random().toString(36).slice(2, 8)}`;
|
|
1649
|
+
const requestedAt = /* @__PURE__ */ new Date();
|
|
1650
|
+
const startedAtMs = requestedAt.getTime();
|
|
1651
|
+
const metadata = isRecord(body.data.metadata) ? body.data.metadata : void 0;
|
|
1652
|
+
const requestedAgentId = readNonEmptyString(body.data.agentId) ?? resolveAgentIdFromSessionKey(sessionKey);
|
|
1653
|
+
const requestedModel = readNonEmptyString(body.data.model);
|
|
1654
|
+
const request = {
|
|
1655
|
+
message,
|
|
1656
|
+
sessionKey,
|
|
1657
|
+
channel: readNonEmptyString(body.data.channel) ?? "ui",
|
|
1658
|
+
chatId: readNonEmptyString(body.data.chatId) ?? "web-ui",
|
|
1659
|
+
...requestedAgentId ? { agentId: requestedAgentId } : {},
|
|
1660
|
+
...requestedModel ? { model: requestedModel } : {},
|
|
1661
|
+
...metadata ? { metadata } : {}
|
|
1662
|
+
};
|
|
1663
|
+
const encoder = new TextEncoder();
|
|
1664
|
+
const stream = new ReadableStream({
|
|
1665
|
+
start: async (controller) => {
|
|
1666
|
+
const push = (event, data) => {
|
|
1667
|
+
controller.enqueue(encoder.encode(toSseFrame(event, data)));
|
|
1668
|
+
};
|
|
1669
|
+
try {
|
|
1670
|
+
push("ready", {
|
|
1671
|
+
sessionKey,
|
|
1672
|
+
requestedAt: requestedAt.toISOString()
|
|
1673
|
+
});
|
|
1674
|
+
const streamTurn = chatRuntime.processTurnStream;
|
|
1675
|
+
if (!streamTurn) {
|
|
1676
|
+
const result = await chatRuntime.processTurn(request);
|
|
1677
|
+
const response = buildChatTurnView({
|
|
1678
|
+
result,
|
|
1679
|
+
fallbackSessionKey: sessionKey,
|
|
1680
|
+
requestedAgentId,
|
|
1681
|
+
requestedModel,
|
|
1682
|
+
requestedAt,
|
|
1683
|
+
startedAtMs
|
|
1684
|
+
});
|
|
1685
|
+
push("final", response);
|
|
1686
|
+
options.publish({ type: "config.updated", payload: { path: "session" } });
|
|
1687
|
+
push("done", { ok: true });
|
|
1688
|
+
return;
|
|
1689
|
+
}
|
|
1690
|
+
let hasFinal = false;
|
|
1691
|
+
for await (const event of streamTurn(request)) {
|
|
1692
|
+
const typed = event;
|
|
1693
|
+
if (typed.type === "delta") {
|
|
1694
|
+
if (typed.delta) {
|
|
1695
|
+
push("delta", { delta: typed.delta });
|
|
1696
|
+
}
|
|
1697
|
+
continue;
|
|
1698
|
+
}
|
|
1699
|
+
if (typed.type === "final") {
|
|
1700
|
+
const response = buildChatTurnView({
|
|
1701
|
+
result: typed.result,
|
|
1702
|
+
fallbackSessionKey: sessionKey,
|
|
1703
|
+
requestedAgentId,
|
|
1704
|
+
requestedModel,
|
|
1705
|
+
requestedAt,
|
|
1706
|
+
startedAtMs
|
|
1707
|
+
});
|
|
1708
|
+
hasFinal = true;
|
|
1709
|
+
push("final", response);
|
|
1710
|
+
options.publish({ type: "config.updated", payload: { path: "session" } });
|
|
1711
|
+
continue;
|
|
1712
|
+
}
|
|
1713
|
+
if (typed.type === "error") {
|
|
1714
|
+
push("error", {
|
|
1715
|
+
code: "CHAT_TURN_FAILED",
|
|
1716
|
+
message: typed.error
|
|
1717
|
+
});
|
|
1718
|
+
return;
|
|
1719
|
+
}
|
|
1720
|
+
}
|
|
1721
|
+
if (!hasFinal) {
|
|
1722
|
+
push("error", {
|
|
1723
|
+
code: "CHAT_TURN_FAILED",
|
|
1724
|
+
message: "stream ended without a final result"
|
|
1725
|
+
});
|
|
1726
|
+
return;
|
|
1727
|
+
}
|
|
1728
|
+
push("done", { ok: true });
|
|
1729
|
+
} catch (error) {
|
|
1730
|
+
push("error", {
|
|
1731
|
+
code: "CHAT_TURN_FAILED",
|
|
1732
|
+
message: String(error)
|
|
1733
|
+
});
|
|
1734
|
+
} finally {
|
|
1735
|
+
controller.close();
|
|
1736
|
+
}
|
|
1737
|
+
}
|
|
1738
|
+
});
|
|
1739
|
+
return new Response(stream, {
|
|
1740
|
+
status: 200,
|
|
1741
|
+
headers: {
|
|
1742
|
+
"Content-Type": "text/event-stream; charset=utf-8",
|
|
1743
|
+
"Cache-Control": "no-cache, no-transform",
|
|
1744
|
+
"Connection": "keep-alive",
|
|
1745
|
+
"X-Accel-Buffering": "no"
|
|
1746
|
+
}
|
|
1747
|
+
});
|
|
1748
|
+
});
|
|
1554
1749
|
app.get("/api/sessions", (c) => {
|
|
1555
1750
|
const query = c.req.query();
|
|
1556
1751
|
const q = typeof query.q === "string" ? query.q : void 0;
|
|
@@ -1791,5 +1986,6 @@ export {
|
|
|
1791
1986
|
updateChannel,
|
|
1792
1987
|
updateModel,
|
|
1793
1988
|
updateProvider,
|
|
1794
|
-
updateRuntime
|
|
1989
|
+
updateRuntime,
|
|
1990
|
+
updateSecrets
|
|
1795
1991
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nextclaw/server",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.19",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "Nextclaw UI/API server.",
|
|
6
6
|
"type": "module",
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
"@nextclaw/openclaw-compat": "^0.1.28",
|
|
19
19
|
"hono": "^4.6.2",
|
|
20
20
|
"ws": "^8.18.0",
|
|
21
|
-
"@nextclaw/core": "^0.6.
|
|
21
|
+
"@nextclaw/core": "^0.6.36"
|
|
22
22
|
},
|
|
23
23
|
"devDependencies": {
|
|
24
24
|
"@types/node": "^20.17.6",
|