@hybridaione/hybridclaw 0.2.3 → 0.2.7
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/.github/workflows/ci.yml +70 -0
- package/.husky/pre-commit +1 -0
- package/CHANGELOG.md +95 -0
- package/CONTRIBUTING.md +33 -0
- package/README.md +57 -19
- package/SECURITY.md +17 -0
- package/biome.json +35 -0
- package/config.example.json +72 -7
- package/container/package-lock.json +2 -2
- package/container/package.json +1 -1
- package/container/src/approval-policy.ts +1405 -0
- package/container/src/browser-tools.ts +672 -136
- package/container/src/extensions.ts +36 -12
- package/container/src/hybridai-client.ts +65 -16
- package/container/src/index.ts +463 -110
- package/container/src/ipc.ts +5 -3
- package/container/src/token-usage.ts +107 -18
- package/container/src/tools.ts +600 -225
- package/container/src/types.ts +49 -2
- package/container/src/web-fetch.ts +89 -32
- package/dist/agent.d.ts.map +1 -1
- package/dist/agent.js +15 -4
- package/dist/agent.js.map +1 -1
- package/dist/audit-cli.d.ts.map +1 -1
- package/dist/audit-cli.js +4 -2
- package/dist/audit-cli.js.map +1 -1
- package/dist/audit-events.d.ts.map +1 -1
- package/dist/audit-events.js +53 -3
- package/dist/audit-events.js.map +1 -1
- package/dist/audit-trail.d.ts.map +1 -1
- package/dist/audit-trail.js +17 -8
- package/dist/audit-trail.js.map +1 -1
- package/dist/channels/discord/attachments.d.ts.map +1 -1
- package/dist/channels/discord/attachments.js +14 -7
- package/dist/channels/discord/attachments.js.map +1 -1
- package/dist/channels/discord/debounce.d.ts +9 -0
- package/dist/channels/discord/debounce.d.ts.map +1 -0
- package/dist/channels/discord/debounce.js +20 -0
- package/dist/channels/discord/debounce.js.map +1 -0
- package/dist/channels/discord/delivery.d.ts +4 -1
- package/dist/channels/discord/delivery.d.ts.map +1 -1
- package/dist/channels/discord/delivery.js +24 -4
- package/dist/channels/discord/delivery.js.map +1 -1
- package/dist/channels/discord/human-delay.d.ts +16 -0
- package/dist/channels/discord/human-delay.d.ts.map +1 -0
- package/dist/channels/discord/human-delay.js +29 -0
- package/dist/channels/discord/human-delay.js.map +1 -0
- package/dist/channels/discord/inbound.d.ts +31 -0
- package/dist/channels/discord/inbound.d.ts.map +1 -1
- package/dist/channels/discord/inbound.js +156 -6
- package/dist/channels/discord/inbound.js.map +1 -1
- package/dist/channels/discord/mentions.d.ts.map +1 -1
- package/dist/channels/discord/mentions.js +16 -4
- package/dist/channels/discord/mentions.js.map +1 -1
- package/dist/channels/discord/presence.d.ts +33 -0
- package/dist/channels/discord/presence.d.ts.map +1 -0
- package/dist/channels/discord/presence.js +111 -0
- package/dist/channels/discord/presence.js.map +1 -0
- package/dist/channels/discord/rate-limiter.d.ts +14 -0
- package/dist/channels/discord/rate-limiter.d.ts.map +1 -0
- package/dist/channels/discord/rate-limiter.js +49 -0
- package/dist/channels/discord/rate-limiter.js.map +1 -0
- package/dist/channels/discord/reactions.d.ts +38 -0
- package/dist/channels/discord/reactions.d.ts.map +1 -0
- package/dist/channels/discord/reactions.js +151 -0
- package/dist/channels/discord/reactions.js.map +1 -0
- package/dist/channels/discord/runtime.d.ts +7 -4
- package/dist/channels/discord/runtime.d.ts.map +1 -1
- package/dist/channels/discord/runtime.js +755 -150
- package/dist/channels/discord/runtime.js.map +1 -1
- package/dist/channels/discord/stream.d.ts +4 -1
- package/dist/channels/discord/stream.d.ts.map +1 -1
- package/dist/channels/discord/stream.js +19 -12
- package/dist/channels/discord/stream.js.map +1 -1
- package/dist/channels/discord/tool-actions.d.ts.map +1 -1
- package/dist/channels/discord/tool-actions.js +24 -12
- package/dist/channels/discord/tool-actions.js.map +1 -1
- package/dist/channels/discord/typing.d.ts +15 -0
- package/dist/channels/discord/typing.d.ts.map +1 -0
- package/dist/channels/discord/typing.js +106 -0
- package/dist/channels/discord/typing.js.map +1 -0
- package/dist/chunk.d.ts.map +1 -1
- package/dist/chunk.js +4 -2
- package/dist/chunk.js.map +1 -1
- package/dist/cli.js +77 -23
- package/dist/cli.js.map +1 -1
- package/dist/config.d.ts +24 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +113 -18
- package/dist/config.js.map +1 -1
- package/dist/container-runner.d.ts.map +1 -1
- package/dist/container-runner.js +59 -26
- package/dist/container-runner.js.map +1 -1
- package/dist/container-setup.d.ts.map +1 -1
- package/dist/container-setup.js +10 -9
- package/dist/container-setup.js.map +1 -1
- package/dist/conversation.d.ts +2 -2
- package/dist/conversation.d.ts.map +1 -1
- package/dist/conversation.js +1 -1
- package/dist/conversation.js.map +1 -1
- package/dist/db.d.ts +118 -2
- package/dist/db.d.ts.map +1 -1
- package/dist/db.js +1568 -50
- package/dist/db.js.map +1 -1
- package/dist/delegation-manager.d.ts.map +1 -1
- package/dist/delegation-manager.js +3 -2
- package/dist/delegation-manager.js.map +1 -1
- package/dist/gateway-client.d.ts +2 -2
- package/dist/gateway-client.d.ts.map +1 -1
- package/dist/gateway-client.js +10 -4
- package/dist/gateway-client.js.map +1 -1
- package/dist/gateway-service.d.ts +3 -3
- package/dist/gateway-service.d.ts.map +1 -1
- package/dist/gateway-service.js +624 -87
- package/dist/gateway-service.js.map +1 -1
- package/dist/gateway-types.d.ts +24 -0
- package/dist/gateway-types.d.ts.map +1 -1
- package/dist/gateway-types.js.map +1 -1
- package/dist/gateway.js +303 -26
- package/dist/gateway.js.map +1 -1
- package/dist/health.d.ts.map +1 -1
- package/dist/health.js +20 -10
- package/dist/health.js.map +1 -1
- package/dist/heartbeat.d.ts +4 -0
- package/dist/heartbeat.d.ts.map +1 -1
- package/dist/heartbeat.js +62 -20
- package/dist/heartbeat.js.map +1 -1
- package/dist/hybridai-bots.d.ts.map +1 -1
- package/dist/hybridai-bots.js +4 -2
- package/dist/hybridai-bots.js.map +1 -1
- package/dist/hybridai-models.d.ts +8 -0
- package/dist/hybridai-models.d.ts.map +1 -0
- package/dist/hybridai-models.js +94 -0
- package/dist/hybridai-models.js.map +1 -0
- package/dist/instruction-approval-audit.d.ts.map +1 -1
- package/dist/instruction-approval-audit.js.map +1 -1
- package/dist/instruction-integrity.d.ts.map +1 -1
- package/dist/instruction-integrity.js +8 -2
- package/dist/instruction-integrity.js.map +1 -1
- package/dist/ipc.d.ts.map +1 -1
- package/dist/ipc.js +6 -1
- package/dist/ipc.js.map +1 -1
- package/dist/logger.js.map +1 -1
- package/dist/memory-consolidation.d.ts +17 -0
- package/dist/memory-consolidation.d.ts.map +1 -0
- package/dist/memory-consolidation.js +25 -0
- package/dist/memory-consolidation.js.map +1 -0
- package/dist/memory-service.d.ts +200 -0
- package/dist/memory-service.d.ts.map +1 -0
- package/dist/memory-service.js +294 -0
- package/dist/memory-service.js.map +1 -0
- package/dist/mount-security.d.ts.map +1 -1
- package/dist/mount-security.js +31 -7
- package/dist/mount-security.js.map +1 -1
- package/dist/observability-ingest.d.ts.map +1 -1
- package/dist/observability-ingest.js +32 -11
- package/dist/observability-ingest.js.map +1 -1
- package/dist/onboarding.d.ts.map +1 -1
- package/dist/onboarding.js +32 -9
- package/dist/onboarding.js.map +1 -1
- package/dist/proactive-policy.d.ts.map +1 -1
- package/dist/proactive-policy.js +2 -1
- package/dist/proactive-policy.js.map +1 -1
- package/dist/prompt-hooks.d.ts.map +1 -1
- package/dist/prompt-hooks.js +11 -7
- package/dist/prompt-hooks.js.map +1 -1
- package/dist/runtime-config.d.ts +104 -1
- package/dist/runtime-config.d.ts.map +1 -1
- package/dist/runtime-config.js +503 -24
- package/dist/runtime-config.js.map +1 -1
- package/dist/scheduled-task-runner.d.ts +1 -0
- package/dist/scheduled-task-runner.d.ts.map +1 -1
- package/dist/scheduled-task-runner.js +43 -10
- package/dist/scheduled-task-runner.js.map +1 -1
- package/dist/scheduler.d.ts +43 -4
- package/dist/scheduler.d.ts.map +1 -1
- package/dist/scheduler.js +530 -56
- package/dist/scheduler.js.map +1 -1
- package/dist/session-export.d.ts +26 -0
- package/dist/session-export.d.ts.map +1 -0
- package/dist/session-export.js +149 -0
- package/dist/session-export.js.map +1 -0
- package/dist/session-maintenance.d.ts.map +1 -1
- package/dist/session-maintenance.js +75 -13
- package/dist/session-maintenance.js.map +1 -1
- package/dist/session-transcripts.d.ts.map +1 -1
- package/dist/session-transcripts.js.map +1 -1
- package/dist/side-effects.d.ts.map +1 -1
- package/dist/side-effects.js +14 -2
- package/dist/side-effects.js.map +1 -1
- package/dist/skills-guard.d.ts.map +1 -1
- package/dist/skills-guard.js +893 -130
- package/dist/skills-guard.js.map +1 -1
- package/dist/skills.d.ts +5 -0
- package/dist/skills.d.ts.map +1 -1
- package/dist/skills.js +29 -15
- package/dist/skills.js.map +1 -1
- package/dist/token-efficiency.d.ts.map +1 -1
- package/dist/token-efficiency.js.map +1 -1
- package/dist/tui.js +92 -11
- package/dist/tui.js.map +1 -1
- package/dist/types.d.ts +150 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +24 -1
- package/dist/types.js.map +1 -1
- package/dist/update.d.ts.map +1 -1
- package/dist/update.js +42 -14
- package/dist/update.js.map +1 -1
- package/dist/workspace.d.ts.map +1 -1
- package/dist/workspace.js +49 -9
- package/dist/workspace.js.map +1 -1
- package/docs/chat.html +9 -3
- package/docs/index.html +72 -13
- package/package.json +8 -2
- package/src/agent.ts +31 -4
- package/src/audit-cli.ts +44 -16
- package/src/audit-events.ts +69 -5
- package/src/audit-trail.ts +41 -15
- package/src/channels/discord/attachments.ts +81 -27
- package/src/channels/discord/debounce.ts +25 -0
- package/src/channels/discord/delivery.ts +65 -14
- package/src/channels/discord/human-delay.ts +48 -0
- package/src/channels/discord/inbound.ts +190 -8
- package/src/channels/discord/mentions.ts +42 -18
- package/src/channels/discord/presence.ts +148 -0
- package/src/channels/discord/rate-limiter.ts +58 -0
- package/src/channels/discord/reactions.ts +211 -0
- package/src/channels/discord/runtime.ts +1161 -205
- package/src/channels/discord/stream.ts +85 -31
- package/src/channels/discord/tool-actions.ts +78 -37
- package/src/channels/discord/typing.ts +140 -0
- package/src/chunk.ts +12 -4
- package/src/cli.ts +174 -57
- package/src/config.ts +208 -36
- package/src/container-runner.ts +134 -42
- package/src/container-setup.ts +57 -22
- package/src/conversation.ts +9 -7
- package/src/db.ts +2217 -84
- package/src/delegation-manager.ts +6 -2
- package/src/gateway-client.ts +41 -17
- package/src/gateway-service.ts +996 -220
- package/src/gateway-types.ts +33 -0
- package/src/gateway.ts +487 -52
- package/src/health.ts +66 -26
- package/src/heartbeat.ts +99 -22
- package/src/hybridai-bots.ts +14 -5
- package/src/hybridai-models.ts +158 -0
- package/src/instruction-approval-audit.ts +4 -1
- package/src/instruction-integrity.ts +30 -9
- package/src/ipc.ts +23 -5
- package/src/logger.ts +4 -1
- package/src/memory-consolidation.ts +41 -0
- package/src/memory-service.ts +606 -0
- package/src/mount-security.ts +58 -13
- package/src/observability-ingest.ts +134 -35
- package/src/onboarding.ts +126 -35
- package/src/proactive-policy.ts +3 -1
- package/src/prompt-hooks.ts +42 -17
- package/src/runtime-config.ts +1112 -122
- package/src/scheduled-task-runner.ts +77 -11
- package/src/scheduler.ts +683 -60
- package/src/session-export.ts +196 -0
- package/src/session-maintenance.ts +125 -22
- package/src/session-transcripts.ts +12 -3
- package/src/side-effects.ts +28 -5
- package/src/skills-guard.ts +1067 -219
- package/src/skills.ts +163 -65
- package/src/token-efficiency.ts +31 -9
- package/src/tui.ts +166 -25
- package/src/types.ts +199 -2
- package/src/update.ts +79 -23
- package/src/workspace.ts +63 -11
- package/tests/approval-policy.test.ts +335 -0
- package/tests/discord.basic.test.ts +213 -4
- package/tests/discord.human-presence.test.ts +85 -0
- package/tests/gateway-service.media-routing.test.ts +8 -2
- package/tests/hybridai-client.test.ts +112 -0
- package/tests/hybridai-models.test.ts +46 -0
- package/tests/memory-service.test.ts +1114 -0
- package/tests/token-efficiency.basic.test.ts +8 -2
- package/tests/token-usage.cache.test.ts +128 -0
- package/vitest.e2e.config.ts +3 -1
- package/vitest.integration.config.ts +3 -1
- package/vitest.live.config.ts +3 -1
- package/vitest.unit.config.ts +9 -0
|
@@ -16,14 +16,22 @@ interface RuntimeEventPayload {
|
|
|
16
16
|
interface RuntimeExtension {
|
|
17
17
|
name: string;
|
|
18
18
|
onEvent?: (payload: RuntimeEventPayload) => void | Promise<void>;
|
|
19
|
-
onBeforeToolCall?: (
|
|
20
|
-
|
|
19
|
+
onBeforeToolCall?: (
|
|
20
|
+
toolName: string,
|
|
21
|
+
args: Record<string, unknown>,
|
|
22
|
+
) => string | null | Promise<string | null>;
|
|
23
|
+
onAfterToolCall?: (
|
|
24
|
+
toolName: string,
|
|
25
|
+
args: Record<string, unknown>,
|
|
26
|
+
result: string,
|
|
27
|
+
) => void | Promise<void>;
|
|
21
28
|
}
|
|
22
29
|
|
|
23
30
|
const DANGEROUS_FILE_CONTENT_PATTERNS: Array<{ re: RegExp; reason: string }> = [
|
|
24
31
|
{
|
|
25
32
|
re: /\brm\s+-rf\s+\/(\s|$)/i,
|
|
26
|
-
reason:
|
|
33
|
+
reason:
|
|
34
|
+
'Detected destructive root delete pattern (`rm -rf /`) in file content.',
|
|
27
35
|
},
|
|
28
36
|
{
|
|
29
37
|
re: /:\(\)\s*\{.*\};\s*:/i,
|
|
@@ -31,7 +39,8 @@ const DANGEROUS_FILE_CONTENT_PATTERNS: Array<{ re: RegExp; reason: string }> = [
|
|
|
31
39
|
},
|
|
32
40
|
{
|
|
33
41
|
re: /\bcurl\b[^\n|]*\|\s*(sh|bash|zsh)\b/i,
|
|
34
|
-
reason:
|
|
42
|
+
reason:
|
|
43
|
+
'Detected remote shell execution pattern (`curl | sh`) in file content.',
|
|
35
44
|
},
|
|
36
45
|
];
|
|
37
46
|
|
|
@@ -50,9 +59,10 @@ const securityHookExtension: RuntimeExtension = {
|
|
|
50
59
|
name: 'security-hook',
|
|
51
60
|
onBeforeToolCall: (toolName, args) => {
|
|
52
61
|
if (toolName === 'write' || toolName === 'edit') {
|
|
53
|
-
const content =
|
|
54
|
-
|
|
55
|
-
|
|
62
|
+
const content =
|
|
63
|
+
toolName === 'write'
|
|
64
|
+
? String(args.contents || '')
|
|
65
|
+
: String(args.new || '');
|
|
56
66
|
for (const pattern of DANGEROUS_FILE_CONTENT_PATTERNS) {
|
|
57
67
|
if (pattern.re.test(content)) return pattern.reason;
|
|
58
68
|
}
|
|
@@ -74,14 +84,17 @@ const runtimeExtensions: RuntimeExtension[] = [securityHookExtension];
|
|
|
74
84
|
function parseArgs(argsJson: string): Record<string, unknown> {
|
|
75
85
|
try {
|
|
76
86
|
const parsed = JSON.parse(argsJson) as unknown;
|
|
77
|
-
if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed))
|
|
87
|
+
if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed))
|
|
88
|
+
return {};
|
|
78
89
|
return parsed as Record<string, unknown>;
|
|
79
90
|
} catch {
|
|
80
91
|
return {};
|
|
81
92
|
}
|
|
82
93
|
}
|
|
83
94
|
|
|
84
|
-
export async function emitRuntimeEvent(
|
|
95
|
+
export async function emitRuntimeEvent(
|
|
96
|
+
payload: RuntimeEventPayload,
|
|
97
|
+
): Promise<void> {
|
|
85
98
|
for (const ext of runtimeExtensions) {
|
|
86
99
|
if (!ext.onEvent) continue;
|
|
87
100
|
try {
|
|
@@ -92,7 +105,10 @@ export async function emitRuntimeEvent(payload: RuntimeEventPayload): Promise<vo
|
|
|
92
105
|
}
|
|
93
106
|
}
|
|
94
107
|
|
|
95
|
-
export async function runBeforeToolHooks(
|
|
108
|
+
export async function runBeforeToolHooks(
|
|
109
|
+
toolName: string,
|
|
110
|
+
argsJson: string,
|
|
111
|
+
): Promise<string | null> {
|
|
96
112
|
const args = parseArgs(argsJson);
|
|
97
113
|
for (const ext of runtimeExtensions) {
|
|
98
114
|
if (!ext.onBeforeToolCall) continue;
|
|
@@ -112,11 +128,19 @@ export async function runBeforeToolHooks(toolName: string, argsJson: string): Pr
|
|
|
112
128
|
// ignore broken extensions
|
|
113
129
|
}
|
|
114
130
|
}
|
|
115
|
-
await emitRuntimeEvent({
|
|
131
|
+
await emitRuntimeEvent({
|
|
132
|
+
event: 'before_tool_call',
|
|
133
|
+
toolName,
|
|
134
|
+
blocked: false,
|
|
135
|
+
});
|
|
116
136
|
return null;
|
|
117
137
|
}
|
|
118
138
|
|
|
119
|
-
export async function runAfterToolHooks(
|
|
139
|
+
export async function runAfterToolHooks(
|
|
140
|
+
toolName: string,
|
|
141
|
+
argsJson: string,
|
|
142
|
+
result: string,
|
|
143
|
+
): Promise<void> {
|
|
120
144
|
const args = parseArgs(argsJson);
|
|
121
145
|
for (const ext of runtimeExtensions) {
|
|
122
146
|
if (!ext.onAfterToolCall) continue;
|
|
@@ -1,4 +1,9 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type {
|
|
2
|
+
ChatCompletionResponse,
|
|
3
|
+
ChatMessage,
|
|
4
|
+
ToolCall,
|
|
5
|
+
ToolDefinition,
|
|
6
|
+
} from './types.js';
|
|
2
7
|
|
|
3
8
|
export class HybridAIRequestError extends Error {
|
|
4
9
|
status: number;
|
|
@@ -49,8 +54,9 @@ function buildRequestBody(
|
|
|
49
54
|
enableRag: boolean,
|
|
50
55
|
messages: ChatMessage[],
|
|
51
56
|
tools: ToolDefinition[],
|
|
57
|
+
maxTokens?: number,
|
|
52
58
|
): Record<string, unknown> {
|
|
53
|
-
|
|
59
|
+
const request: Record<string, unknown> = {
|
|
54
60
|
model,
|
|
55
61
|
chatbot_id: chatbotId,
|
|
56
62
|
messages,
|
|
@@ -58,6 +64,14 @@ function buildRequestBody(
|
|
|
58
64
|
tool_choice: 'auto',
|
|
59
65
|
enable_rag: enableRag,
|
|
60
66
|
};
|
|
67
|
+
if (
|
|
68
|
+
typeof maxTokens === 'number' &&
|
|
69
|
+
Number.isFinite(maxTokens) &&
|
|
70
|
+
maxTokens > 0
|
|
71
|
+
) {
|
|
72
|
+
request.max_tokens = Math.floor(maxTokens);
|
|
73
|
+
}
|
|
74
|
+
return request;
|
|
61
75
|
}
|
|
62
76
|
|
|
63
77
|
function parseStreamPayloadLine(rawLine: string): string | null {
|
|
@@ -86,7 +100,10 @@ function ensureToolCall(toolCalls: ToolCall[], index: number): ToolCall {
|
|
|
86
100
|
return toolCalls[index];
|
|
87
101
|
}
|
|
88
102
|
|
|
89
|
-
function mergeToolCallDelta(
|
|
103
|
+
function mergeToolCallDelta(
|
|
104
|
+
target: ToolCall,
|
|
105
|
+
delta: StreamToolCallDelta,
|
|
106
|
+
): void {
|
|
90
107
|
if (typeof delta.id === 'string' && delta.id) {
|
|
91
108
|
target.id = target.id ? `${target.id}${delta.id}` : delta.id;
|
|
92
109
|
}
|
|
@@ -99,7 +116,10 @@ function mergeToolCallDelta(target: ToolCall, delta: StreamToolCallDelta): void
|
|
|
99
116
|
? `${target.function.name}${delta.function.name}`
|
|
100
117
|
: delta.function.name;
|
|
101
118
|
}
|
|
102
|
-
if (
|
|
119
|
+
if (
|
|
120
|
+
typeof delta.function.arguments === 'string' &&
|
|
121
|
+
delta.function.arguments
|
|
122
|
+
) {
|
|
103
123
|
target.function.arguments += delta.function.arguments;
|
|
104
124
|
}
|
|
105
125
|
}
|
|
@@ -113,10 +133,18 @@ export async function callHybridAI(
|
|
|
113
133
|
enableRag: boolean,
|
|
114
134
|
messages: ChatMessage[],
|
|
115
135
|
tools: ToolDefinition[],
|
|
136
|
+
maxTokens?: number,
|
|
116
137
|
): Promise<ChatCompletionResponse> {
|
|
117
138
|
const url = `${baseUrl}/v1/chat/completions`;
|
|
118
139
|
|
|
119
|
-
const body = buildRequestBody(
|
|
140
|
+
const body = buildRequestBody(
|
|
141
|
+
model,
|
|
142
|
+
chatbotId,
|
|
143
|
+
enableRag,
|
|
144
|
+
messages,
|
|
145
|
+
tools,
|
|
146
|
+
maxTokens,
|
|
147
|
+
);
|
|
120
148
|
|
|
121
149
|
const response = await fetch(url, {
|
|
122
150
|
method: 'POST',
|
|
@@ -144,11 +172,22 @@ export async function callHybridAIStream(
|
|
|
144
172
|
messages: ChatMessage[],
|
|
145
173
|
tools: ToolDefinition[],
|
|
146
174
|
onTextDelta: (delta: string) => void,
|
|
175
|
+
maxTokens?: number,
|
|
147
176
|
): Promise<ChatCompletionResponse> {
|
|
148
177
|
const url = `${baseUrl}/v1/chat/completions`;
|
|
149
178
|
const body = {
|
|
150
|
-
...buildRequestBody(
|
|
179
|
+
...buildRequestBody(
|
|
180
|
+
model,
|
|
181
|
+
chatbotId,
|
|
182
|
+
enableRag,
|
|
183
|
+
messages,
|
|
184
|
+
tools,
|
|
185
|
+
maxTokens,
|
|
186
|
+
),
|
|
151
187
|
stream: true,
|
|
188
|
+
stream_options: {
|
|
189
|
+
include_usage: true,
|
|
190
|
+
},
|
|
152
191
|
};
|
|
153
192
|
|
|
154
193
|
const response = await fetch(url, {
|
|
@@ -166,11 +205,13 @@ export async function callHybridAIStream(
|
|
|
166
205
|
throw new HybridAIRequestError(response.status, text);
|
|
167
206
|
}
|
|
168
207
|
|
|
169
|
-
const contentType = (
|
|
208
|
+
const contentType = (
|
|
209
|
+
response.headers.get('content-type') || ''
|
|
210
|
+
).toLowerCase();
|
|
170
211
|
if (
|
|
171
|
-
contentType.includes('application/json')
|
|
172
|
-
|
|
173
|
-
|
|
212
|
+
contentType.includes('application/json') &&
|
|
213
|
+
!contentType.includes('ndjson') &&
|
|
214
|
+
!contentType.includes('event-stream')
|
|
174
215
|
) {
|
|
175
216
|
return (await response.json()) as ChatCompletionResponse;
|
|
176
217
|
}
|
|
@@ -208,10 +249,14 @@ export async function callHybridAIStream(
|
|
|
208
249
|
|
|
209
250
|
sawPayload = true;
|
|
210
251
|
if (typeof payload.id === 'string' && payload.id) streamId = payload.id;
|
|
211
|
-
if (typeof payload.model === 'string' && payload.model)
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
252
|
+
if (typeof payload.model === 'string' && payload.model)
|
|
253
|
+
streamModel = payload.model;
|
|
254
|
+
if (payload.usage && typeof payload.usage === 'object')
|
|
255
|
+
usage = payload.usage;
|
|
256
|
+
|
|
257
|
+
const choice = Array.isArray(payload.choices)
|
|
258
|
+
? payload.choices[0]
|
|
259
|
+
: undefined;
|
|
215
260
|
if (!choice) return;
|
|
216
261
|
|
|
217
262
|
if (choice.message) {
|
|
@@ -249,7 +294,10 @@ export async function callHybridAIStream(
|
|
|
249
294
|
}
|
|
250
295
|
if (Array.isArray(delta.tool_calls) && delta.tool_calls.length > 0) {
|
|
251
296
|
for (const callDelta of delta.tool_calls) {
|
|
252
|
-
const index =
|
|
297
|
+
const index =
|
|
298
|
+
typeof callDelta.index === 'number' && callDelta.index >= 0
|
|
299
|
+
? callDelta.index
|
|
300
|
+
: 0;
|
|
253
301
|
const target = ensureToolCall(toolCalls, index);
|
|
254
302
|
mergeToolCallDelta(target, callDelta);
|
|
255
303
|
}
|
|
@@ -293,7 +341,8 @@ export async function callHybridAIStream(
|
|
|
293
341
|
throw new Error('Streaming response ended without payload');
|
|
294
342
|
}
|
|
295
343
|
|
|
296
|
-
const finalFinishReason =
|
|
344
|
+
const finalFinishReason =
|
|
345
|
+
finishReason || (toolCalls.length > 0 ? 'tool_calls' : 'stop');
|
|
297
346
|
return {
|
|
298
347
|
id: streamId || 'stream',
|
|
299
348
|
model: streamModel,
|