c0de-agent 0.0.0 → 1.0.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/LICENSE +21 -0
- package/README.md +101 -0
- package/dist/cli/commands/acp.d.ts +19 -0
- package/dist/cli/commands/acp.js +50 -0
- package/dist/cli/commands/chat.d.ts +13 -0
- package/dist/cli/commands/chat.js +26 -0
- package/dist/cli/commands/config.d.ts +17 -0
- package/dist/cli/commands/config.js +77 -0
- package/dist/cli/commands/init.d.ts +9 -0
- package/dist/cli/commands/init.js +14 -0
- package/dist/cli/commands/plugin.d.ts +11 -0
- package/dist/cli/commands/plugin.js +31 -0
- package/dist/cli/commands/serve.d.ts +18 -0
- package/dist/cli/commands/serve.js +35 -0
- package/dist/cli/commands/update.d.ts +24 -0
- package/dist/cli/commands/update.js +40 -0
- package/dist/cli/deps.d.ts +19 -0
- package/dist/cli/deps.js +57 -0
- package/dist/cli/index.d.ts +8 -0
- package/dist/cli/index.js +149 -0
- package/dist/cli/modes/acp.d.ts +18 -0
- package/dist/cli/modes/acp.js +57 -0
- package/dist/cli/modes/print.d.ts +16 -0
- package/dist/cli/modes/print.js +30 -0
- package/dist/cli/parser.d.ts +19 -0
- package/dist/cli/parser.js +28 -0
- package/dist/cli/utils/output.d.ts +11 -0
- package/dist/cli/utils/output.js +23 -0
- package/dist/cli/utils/prompt.d.ts +12 -0
- package/dist/cli/utils/prompt.js +18 -0
- package/dist/core/agent.d.ts +12 -0
- package/dist/core/agent.js +95 -0
- package/dist/core/agents/builtin.d.ts +6 -0
- package/dist/core/agents/builtin.js +76 -0
- package/dist/core/agents/discovery.d.ts +6 -0
- package/dist/core/agents/discovery.js +96 -0
- package/dist/core/agents/index.d.ts +6 -0
- package/dist/core/agents/index.js +4 -0
- package/dist/core/agents/parallel.d.ts +13 -0
- package/dist/core/agents/parallel.js +37 -0
- package/dist/core/agents/registry.d.ts +4 -0
- package/dist/core/agents/registry.js +23 -0
- package/dist/core/agents/types.d.ts +37 -0
- package/dist/core/agents/types.js +1 -0
- package/dist/core/compact.d.ts +11 -0
- package/dist/core/compact.js +31 -0
- package/dist/core/config.d.ts +7 -0
- package/dist/core/config.js +84 -0
- package/dist/core/context.d.ts +23 -0
- package/dist/core/context.js +93 -0
- package/dist/core/index.d.ts +13 -0
- package/dist/core/index.js +11 -0
- package/dist/core/loop.d.ts +25 -0
- package/dist/core/loop.js +651 -0
- package/dist/core/metrics.d.ts +27 -0
- package/dist/core/metrics.js +94 -0
- package/dist/core/prompt-registry.d.ts +21 -0
- package/dist/core/prompt-registry.js +200 -0
- package/dist/core/prompt.d.ts +11 -0
- package/dist/core/prompt.js +13 -0
- package/dist/core/secret.d.ts +12 -0
- package/dist/core/secret.js +51 -0
- package/dist/core/slash.d.ts +15 -0
- package/dist/core/slash.js +114 -0
- package/dist/core/steering.d.ts +8 -0
- package/dist/core/steering.js +15 -0
- package/dist/core/title.d.ts +42 -0
- package/dist/core/title.js +115 -0
- package/dist/core/tool-exec.d.ts +20 -0
- package/dist/core/tool-exec.js +64 -0
- package/dist/core/types.d.ts +95 -0
- package/dist/core/types.js +1 -0
- package/dist/core/worktree.d.ts +24 -0
- package/dist/core/worktree.js +68 -0
- package/dist/dap/index.d.ts +6 -0
- package/dist/dap/index.js +4 -0
- package/dist/dap/protocol.d.ts +40 -0
- package/dist/dap/protocol.js +132 -0
- package/dist/dap/session.d.ts +23 -0
- package/dist/dap/session.js +130 -0
- package/dist/dap/transport.d.ts +8 -0
- package/dist/dap/transport.js +30 -0
- package/dist/dap/types.d.ts +50 -0
- package/dist/dap/types.js +2 -0
- package/dist/db/client.d.ts +22 -0
- package/dist/db/client.js +39 -0
- package/dist/db/index.d.ts +6 -0
- package/dist/db/index.js +4 -0
- package/dist/db/migrate.d.ts +9 -0
- package/dist/db/migrate.js +15 -0
- package/dist/db/schema.d.ts +965 -0
- package/dist/db/schema.js +112 -0
- package/dist/db/types.d.ts +11 -0
- package/dist/db/types.js +1 -0
- package/dist/llm/index.d.ts +13 -0
- package/dist/llm/index.js +8 -0
- package/dist/llm/protocols/openai-compat.d.ts +139 -0
- package/dist/llm/protocols/openai-compat.js +214 -0
- package/dist/llm/protocols/utils/index.d.ts +2 -0
- package/dist/llm/protocols/utils/index.js +2 -0
- package/dist/llm/protocols/utils/lifecycle.d.ts +23 -0
- package/dist/llm/protocols/utils/lifecycle.js +46 -0
- package/dist/llm/protocols/utils/tool-stream.d.ts +46 -0
- package/dist/llm/protocols/utils/tool-stream.js +94 -0
- package/dist/llm/provider-error.d.ts +5 -0
- package/dist/llm/provider-error.js +33 -0
- package/dist/llm/provider.d.ts +32 -0
- package/dist/llm/provider.js +191 -0
- package/dist/llm/registry.d.ts +44 -0
- package/dist/llm/registry.js +107 -0
- package/dist/llm/retry.d.ts +37 -0
- package/dist/llm/retry.js +82 -0
- package/dist/llm/routing.d.ts +36 -0
- package/dist/llm/routing.js +53 -0
- package/dist/llm/schema/errors.d.ts +88 -0
- package/dist/llm/schema/errors.js +33 -0
- package/dist/llm/schema/events.d.ts +135 -0
- package/dist/llm/schema/events.js +35 -0
- package/dist/llm/schema/ids.d.ts +22 -0
- package/dist/llm/schema/ids.js +3 -0
- package/dist/llm/schema/index.d.ts +5 -0
- package/dist/llm/schema/index.js +5 -0
- package/dist/llm/schema/messages.d.ts +97 -0
- package/dist/llm/schema/messages.js +18 -0
- package/dist/llm/schema/options.d.ts +54 -0
- package/dist/llm/schema/options.js +54 -0
- package/dist/llm/token.d.ts +2 -0
- package/dist/llm/token.js +13 -0
- package/dist/llm/transport.d.ts +31 -0
- package/dist/llm/transport.js +165 -0
- package/dist/mcp/index.d.ts +1 -0
- package/dist/mcp/index.js +3 -0
- package/dist/plugins/builtin.d.ts +6 -0
- package/dist/plugins/builtin.js +54 -0
- package/dist/plugins/hooks.d.ts +3 -0
- package/dist/plugins/hooks.js +79 -0
- package/dist/plugins/index.d.ts +9 -0
- package/dist/plugins/index.js +8 -0
- package/dist/plugins/init.d.ts +23 -0
- package/dist/plugins/init.js +30 -0
- package/dist/plugins/lifecycle.d.ts +6 -0
- package/dist/plugins/lifecycle.js +74 -0
- package/dist/plugins/loader.d.ts +16 -0
- package/dist/plugins/loader.js +68 -0
- package/dist/plugins/logger.d.ts +4 -0
- package/dist/plugins/logger.js +31 -0
- package/dist/plugins/registry.d.ts +7 -0
- package/dist/plugins/registry.js +24 -0
- package/dist/plugins/types.d.ts +113 -0
- package/dist/plugins/types.js +1 -0
- package/dist/project/detect.d.ts +4 -0
- package/dist/project/detect.js +131 -0
- package/dist/project/index.d.ts +4 -0
- package/dist/project/index.js +2 -0
- package/dist/project/project.d.ts +23 -0
- package/dist/project/project.js +87 -0
- package/dist/project/resolve.d.ts +8 -0
- package/dist/project/resolve.js +81 -0
- package/dist/server/agent-manager.d.ts +32 -0
- package/dist/server/agent-manager.js +54 -0
- package/dist/server/app.d.ts +5 -0
- package/dist/server/app.js +75 -0
- package/dist/server/context.d.ts +20 -0
- package/dist/server/context.js +47 -0
- package/dist/server/dev.d.ts +11 -0
- package/dist/server/dev.js +83 -0
- package/dist/server/index.d.ts +11 -0
- package/dist/server/index.js +7 -0
- package/dist/server/middleware/auth.d.ts +15 -0
- package/dist/server/middleware/auth.js +29 -0
- package/dist/server/middleware/cors.d.ts +16 -0
- package/dist/server/middleware/cors.js +44 -0
- package/dist/server/middleware/error.d.ts +15 -0
- package/dist/server/middleware/error.js +11 -0
- package/dist/server/permission/interactive.d.ts +24 -0
- package/dist/server/permission/interactive.js +56 -0
- package/dist/server/permission/store.d.ts +30 -0
- package/dist/server/permission/store.js +47 -0
- package/dist/server/routes/agent.d.ts +4 -0
- package/dist/server/routes/agent.js +19 -0
- package/dist/server/routes/catalog.d.ts +42 -0
- package/dist/server/routes/catalog.js +194 -0
- package/dist/server/routes/chat.d.ts +8 -0
- package/dist/server/routes/chat.js +282 -0
- package/dist/server/routes/commands.d.ts +5 -0
- package/dist/server/routes/commands.js +17 -0
- package/dist/server/routes/config.d.ts +4 -0
- package/dist/server/routes/config.js +27 -0
- package/dist/server/routes/files.d.ts +4 -0
- package/dist/server/routes/files.js +183 -0
- package/dist/server/routes/filesystem.d.ts +29 -0
- package/dist/server/routes/filesystem.js +108 -0
- package/dist/server/routes/health.d.ts +3 -0
- package/dist/server/routes/health.js +13 -0
- package/dist/server/routes/permissions.d.ts +5 -0
- package/dist/server/routes/permissions.js +23 -0
- package/dist/server/routes/project.d.ts +4 -0
- package/dist/server/routes/project.js +51 -0
- package/dist/server/routes/provider.d.ts +16 -0
- package/dist/server/routes/provider.js +66 -0
- package/dist/server/routes/session.d.ts +4 -0
- package/dist/server/routes/session.js +130 -0
- package/dist/server/routes/tool.d.ts +4 -0
- package/dist/server/routes/tool.js +28 -0
- package/dist/server/routes/update.d.ts +14 -0
- package/dist/server/routes/update.js +49 -0
- package/dist/server/server.d.ts +43 -0
- package/dist/server/server.js +197 -0
- package/dist/server/types.d.ts +73 -0
- package/dist/server/types.js +2 -0
- package/dist/server/util/safe-path.d.ts +7 -0
- package/dist/server/util/safe-path.js +7 -0
- package/dist/session/archive.d.ts +15 -0
- package/dist/session/archive.js +129 -0
- package/dist/session/branch.d.ts +9 -0
- package/dist/session/branch.js +63 -0
- package/dist/session/compaction.d.ts +27 -0
- package/dist/session/compaction.js +192 -0
- package/dist/session/context.d.ts +16 -0
- package/dist/session/context.js +173 -0
- package/dist/session/index.d.ts +10 -0
- package/dist/session/index.js +10 -0
- package/dist/session/message.d.ts +22 -0
- package/dist/session/message.js +145 -0
- package/dist/session/session.d.ts +37 -0
- package/dist/session/session.js +144 -0
- package/dist/session/snapshot.d.ts +11 -0
- package/dist/session/snapshot.js +60 -0
- package/dist/session/squash.d.ts +9 -0
- package/dist/session/squash.js +88 -0
- package/dist/session/token.d.ts +10 -0
- package/dist/session/token.js +33 -0
- package/dist/session/types.d.ts +122 -0
- package/dist/session/types.js +1 -0
- package/dist/shared/index.d.ts +2 -0
- package/dist/shared/index.js +1 -0
- package/dist/shared/types/agent.d.ts +202 -0
- package/dist/shared/types/agent.js +1 -0
- package/dist/shared/types/base.d.ts +32 -0
- package/dist/shared/types/base.js +1 -0
- package/dist/shared/types/config.d.ts +104 -0
- package/dist/shared/types/config.js +1 -0
- package/dist/shared/types/index.d.ts +6 -0
- package/dist/shared/types/index.js +1 -0
- package/dist/shared/types/llm.d.ts +122 -0
- package/dist/shared/types/llm.js +1 -0
- package/dist/shared/types/message.d.ts +71 -0
- package/dist/shared/types/message.js +1 -0
- package/dist/shared/types/tool.d.ts +134 -0
- package/dist/shared/types/tool.js +1 -0
- package/dist/shared/utils/path.d.ts +15 -0
- package/dist/shared/utils/path.js +23 -0
- package/dist/shared/utils.d.ts +5 -0
- package/dist/shared/utils.js +10 -0
- package/dist/tools/builtin/bash.d.ts +12 -0
- package/dist/tools/builtin/bash.js +121 -0
- package/dist/tools/builtin/dap.d.ts +23 -0
- package/dist/tools/builtin/dap.js +231 -0
- package/dist/tools/builtin/edit.d.ts +12 -0
- package/dist/tools/builtin/edit.js +151 -0
- package/dist/tools/builtin/glob.d.ts +11 -0
- package/dist/tools/builtin/glob.js +120 -0
- package/dist/tools/builtin/grep.d.ts +6 -0
- package/dist/tools/builtin/grep.js +141 -0
- package/dist/tools/builtin/read.d.ts +6 -0
- package/dist/tools/builtin/read.js +73 -0
- package/dist/tools/builtin/resolvers.d.ts +12 -0
- package/dist/tools/builtin/resolvers.js +79 -0
- package/dist/tools/builtin/task.d.ts +9 -0
- package/dist/tools/builtin/task.js +100 -0
- package/dist/tools/builtin/write.d.ts +6 -0
- package/dist/tools/builtin/write.js +36 -0
- package/dist/tools/builtin/yield.d.ts +9 -0
- package/dist/tools/builtin/yield.js +40 -0
- package/dist/tools/executor.d.ts +9 -0
- package/dist/tools/executor.js +54 -0
- package/dist/tools/hashline/index.d.ts +2 -0
- package/dist/tools/hashline/index.js +3 -0
- package/dist/tools/hashline/patch.d.ts +48 -0
- package/dist/tools/hashline/patch.js +201 -0
- package/dist/tools/index.d.ts +30 -0
- package/dist/tools/index.js +55 -0
- package/dist/tools/permission.d.ts +13 -0
- package/dist/tools/permission.js +39 -0
- package/dist/tools/registry.d.ts +15 -0
- package/dist/tools/registry.js +54 -0
- package/dist/tools/resolver.d.ts +15 -0
- package/dist/tools/resolver.js +47 -0
- package/dist/tools/truncate.d.ts +8 -0
- package/dist/tools/truncate.js +50 -0
- package/dist/tools/types.d.ts +101 -0
- package/dist/tools/types.js +1 -0
- package/dist/tools/validate.d.ts +8 -0
- package/dist/tools/validate.js +130 -0
- package/dist/tools/websearch/fetch.d.ts +11 -0
- package/dist/tools/websearch/fetch.js +21 -0
- package/dist/tools/websearch/index.d.ts +19 -0
- package/dist/tools/websearch/index.js +78 -0
- package/dist/tools/websearch/providers/brave.d.ts +5 -0
- package/dist/tools/websearch/providers/brave.js +53 -0
- package/dist/tools/websearch/providers/duckduckgo.d.ts +3 -0
- package/dist/tools/websearch/providers/duckduckgo.js +75 -0
- package/dist/tools/websearch/providers/tavily.d.ts +11 -0
- package/dist/tools/websearch/providers/tavily.js +89 -0
- package/dist/tools/websearch/types.d.ts +51 -0
- package/dist/tools/websearch/types.js +18 -0
- package/dist/tools/websearch/websearch.d.ts +10 -0
- package/dist/tools/websearch/websearch.js +48 -0
- package/dist/update/index.d.ts +10 -0
- package/dist/update/index.js +6 -0
- package/dist/update/ipc.d.ts +15 -0
- package/dist/update/ipc.js +41 -0
- package/dist/update/scheduler.d.ts +34 -0
- package/dist/update/scheduler.js +57 -0
- package/dist/update/snapshot.d.ts +39 -0
- package/dist/update/snapshot.js +99 -0
- package/dist/update/updater.d.ts +48 -0
- package/dist/update/updater.js +83 -0
- package/dist/update/version.d.ts +18 -0
- package/dist/update/version.js +49 -0
- package/drizzle/0000_magical_nightshade.sql +55 -0
- package/drizzle/0001_chemical_doctor_faustus.sql +13 -0
- package/drizzle/0002_amusing_micromacro.sql +12 -0
- package/drizzle/0003_regular_purifiers.sql +2 -0
- package/drizzle/meta/0000_snapshot.json +448 -0
- package/drizzle/meta/0001_snapshot.json +539 -0
- package/drizzle/meta/0002_snapshot.json +633 -0
- package/drizzle/meta/0003_snapshot.json +645 -0
- package/drizzle/meta/_journal.json +34 -0
- package/package.json +100 -8
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { resolveRoute } from './registry.js';
|
|
2
|
+
import { withRetry } from './retry.js';
|
|
3
|
+
import { isLLMError } from './schema/errors.js';
|
|
4
|
+
/**
|
|
5
|
+
* Run `run` against the primary route first. If it throws a retryable error
|
|
6
|
+
* that exhausts retries, try each fallback in order. Non-retryable errors
|
|
7
|
+
* (context overflow, auth, invalid request) propagate immediately without
|
|
8
|
+
* trying fallbacks.
|
|
9
|
+
*/
|
|
10
|
+
const runWithFallback = async (registry, chain, run) => {
|
|
11
|
+
const targets = [chain.primary, ...chain.fallbacks];
|
|
12
|
+
let lastError;
|
|
13
|
+
for (let i = 0; i < targets.length; i += 1) {
|
|
14
|
+
const target = targets[i];
|
|
15
|
+
if (target === undefined)
|
|
16
|
+
continue;
|
|
17
|
+
// Validate the route exists before attempting (fails fast with NoRoute).
|
|
18
|
+
resolveRoute(registry, target.provider, target.model);
|
|
19
|
+
try {
|
|
20
|
+
const result = await withRetry(() => run(target.provider, target.model), {
|
|
21
|
+
maxRetries: chain.maxRetries,
|
|
22
|
+
sleep: chain.sleep,
|
|
23
|
+
});
|
|
24
|
+
return { result, provider: target.provider, model: target.model };
|
|
25
|
+
}
|
|
26
|
+
catch (error) {
|
|
27
|
+
lastError = error;
|
|
28
|
+
// Non-retryable errors do not fall through to fallback.
|
|
29
|
+
if (!shouldFallOver(error))
|
|
30
|
+
throw error;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
throw lastError;
|
|
34
|
+
};
|
|
35
|
+
/**
|
|
36
|
+
* Whether an error should trigger a fallback after retries are exhausted.
|
|
37
|
+
* Per spec §7.6: RateLimit (after retries), ProviderInternal, and Authentication
|
|
38
|
+
* fall over to the next route. Context-overflow, invalid request, and transport
|
|
39
|
+
* errors propagate without trying fallbacks.
|
|
40
|
+
*/
|
|
41
|
+
const shouldFallOver = (error) => {
|
|
42
|
+
if (!isLLMError(error))
|
|
43
|
+
return false;
|
|
44
|
+
const reason = error.reason;
|
|
45
|
+
if (reason._tag === 'ProviderInternal')
|
|
46
|
+
return true;
|
|
47
|
+
if (reason._tag === 'RateLimit')
|
|
48
|
+
return true;
|
|
49
|
+
if (reason._tag === 'Authentication')
|
|
50
|
+
return true;
|
|
51
|
+
return false;
|
|
52
|
+
};
|
|
53
|
+
export { runWithFallback, shouldFallOver };
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
type HttpContext = {
|
|
2
|
+
request: {
|
|
3
|
+
method: string;
|
|
4
|
+
url: string;
|
|
5
|
+
headers: Record<string, string>;
|
|
6
|
+
};
|
|
7
|
+
response?: {
|
|
8
|
+
status: number;
|
|
9
|
+
headers: Record<string, string>;
|
|
10
|
+
};
|
|
11
|
+
body?: string;
|
|
12
|
+
requestId?: string;
|
|
13
|
+
};
|
|
14
|
+
type LLMErrorReason = {
|
|
15
|
+
_tag: 'InvalidRequest';
|
|
16
|
+
message: string;
|
|
17
|
+
parameter?: string;
|
|
18
|
+
classification?: 'context-overflow';
|
|
19
|
+
http?: HttpContext;
|
|
20
|
+
} | {
|
|
21
|
+
_tag: 'NoRoute';
|
|
22
|
+
route: string;
|
|
23
|
+
provider: string;
|
|
24
|
+
model: string;
|
|
25
|
+
} | {
|
|
26
|
+
_tag: 'Authentication';
|
|
27
|
+
message: string;
|
|
28
|
+
kind: 'missing' | 'invalid' | 'expired' | 'insufficient-permissions' | 'unknown';
|
|
29
|
+
http?: HttpContext;
|
|
30
|
+
} | {
|
|
31
|
+
_tag: 'RateLimit';
|
|
32
|
+
message: string;
|
|
33
|
+
retryAfterMs?: number;
|
|
34
|
+
http?: HttpContext;
|
|
35
|
+
} | {
|
|
36
|
+
_tag: 'QuotaExceeded';
|
|
37
|
+
message: string;
|
|
38
|
+
http?: HttpContext;
|
|
39
|
+
} | {
|
|
40
|
+
_tag: 'ContentPolicy';
|
|
41
|
+
message: string;
|
|
42
|
+
http?: HttpContext;
|
|
43
|
+
} | {
|
|
44
|
+
_tag: 'ProviderInternal';
|
|
45
|
+
message: string;
|
|
46
|
+
status: number;
|
|
47
|
+
retryAfterMs?: number;
|
|
48
|
+
http?: HttpContext;
|
|
49
|
+
} | {
|
|
50
|
+
_tag: 'Transport';
|
|
51
|
+
message: string;
|
|
52
|
+
kind?: string;
|
|
53
|
+
url?: string;
|
|
54
|
+
http?: HttpContext;
|
|
55
|
+
} | {
|
|
56
|
+
_tag: 'InvalidProviderOutput';
|
|
57
|
+
message: string;
|
|
58
|
+
raw?: string;
|
|
59
|
+
} | {
|
|
60
|
+
_tag: 'UnknownProvider';
|
|
61
|
+
message: string;
|
|
62
|
+
status?: number;
|
|
63
|
+
http?: HttpContext;
|
|
64
|
+
};
|
|
65
|
+
/** Human-readable message extracted from any reason. */
|
|
66
|
+
declare const reasonMessage: (reason: LLMErrorReason) => string;
|
|
67
|
+
/** Whether a reason is retryable (RateLimit / ProviderInternal). */
|
|
68
|
+
declare const reasonRetryable: (reason: LLMErrorReason) => boolean;
|
|
69
|
+
/** Retry-after delay in ms for reasons that carry one. */
|
|
70
|
+
declare const reasonRetryAfterMs: (reason: LLMErrorReason) => number | undefined;
|
|
71
|
+
type LLMError = {
|
|
72
|
+
_tag: 'LLMError';
|
|
73
|
+
module: string;
|
|
74
|
+
method: string;
|
|
75
|
+
reason: LLMErrorReason;
|
|
76
|
+
message: string;
|
|
77
|
+
};
|
|
78
|
+
declare const llmError: (module: string, method: string, reason: LLMErrorReason) => LLMError;
|
|
79
|
+
declare const isLLMError: (e: unknown) => e is LLMError;
|
|
80
|
+
type ToolFailure = {
|
|
81
|
+
_tag: 'ToolFailure';
|
|
82
|
+
message: string;
|
|
83
|
+
metadata?: Record<string, unknown>;
|
|
84
|
+
};
|
|
85
|
+
declare const toolFailure: (message: string, metadata?: Record<string, unknown>) => ToolFailure;
|
|
86
|
+
declare const isToolFailure: (e: unknown) => e is ToolFailure;
|
|
87
|
+
export type { HttpContext, LLMError, LLMErrorReason, ToolFailure };
|
|
88
|
+
export { isLLMError, isToolFailure, llmError, reasonMessage, reasonRetryAfterMs, reasonRetryable, toolFailure, };
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/** Human-readable message extracted from any reason. */
|
|
2
|
+
const reasonMessage = (reason) => {
|
|
3
|
+
switch (reason._tag) {
|
|
4
|
+
case 'NoRoute':
|
|
5
|
+
return `No LLM route for model "${reason.model}" using provider "${reason.provider}" (route "${reason.route}")`;
|
|
6
|
+
default:
|
|
7
|
+
return reason.message;
|
|
8
|
+
}
|
|
9
|
+
};
|
|
10
|
+
/** Whether a reason is retryable (RateLimit / ProviderInternal). */
|
|
11
|
+
const reasonRetryable = (reason) => reason._tag === 'RateLimit' || reason._tag === 'ProviderInternal';
|
|
12
|
+
/** Retry-after delay in ms for reasons that carry one. */
|
|
13
|
+
const reasonRetryAfterMs = (reason) => {
|
|
14
|
+
if (reason._tag === 'RateLimit' || reason._tag === 'ProviderInternal') {
|
|
15
|
+
return reason.retryAfterMs;
|
|
16
|
+
}
|
|
17
|
+
return undefined;
|
|
18
|
+
};
|
|
19
|
+
const llmError = (module, method, reason) => ({
|
|
20
|
+
_tag: 'LLMError',
|
|
21
|
+
module,
|
|
22
|
+
method,
|
|
23
|
+
reason,
|
|
24
|
+
message: `${module}.${method}: ${reasonMessage(reason)}`,
|
|
25
|
+
});
|
|
26
|
+
const isLLMError = (e) => typeof e === 'object' && e !== null && e._tag === 'LLMError';
|
|
27
|
+
const toolFailure = (message, metadata) => ({
|
|
28
|
+
_tag: 'ToolFailure',
|
|
29
|
+
message,
|
|
30
|
+
metadata,
|
|
31
|
+
});
|
|
32
|
+
const isToolFailure = (e) => typeof e === 'object' && e !== null && e._tag === 'ToolFailure';
|
|
33
|
+
export { isLLMError, isToolFailure, llmError, reasonMessage, reasonRetryAfterMs, reasonRetryable, toolFailure, };
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
import type { ContentBlockID, FinishReason, ProtocolID, ProviderMetadata, ResponseID, RouteID, ToolCallID } from './ids.js';
|
|
2
|
+
import type { ToolResultValue } from './messages.js';
|
|
3
|
+
import type { Model } from './options.js';
|
|
4
|
+
type Usage = {
|
|
5
|
+
inputTokens?: number;
|
|
6
|
+
outputTokens?: number;
|
|
7
|
+
nonCachedInputTokens?: number;
|
|
8
|
+
cacheReadInputTokens?: number;
|
|
9
|
+
cacheWriteInputTokens?: number;
|
|
10
|
+
reasoningTokens?: number;
|
|
11
|
+
totalTokens?: number;
|
|
12
|
+
providerMetadata?: ProviderMetadata;
|
|
13
|
+
};
|
|
14
|
+
type UsageInput = Partial<Usage>;
|
|
15
|
+
declare const usageFrom: (input: UsageInput) => Usage;
|
|
16
|
+
/** Visible (non-reasoning) output tokens: max(0, output - reasoning). */
|
|
17
|
+
declare const visibleOutputTokens: (u: Usage) => number;
|
|
18
|
+
type StepStart = {
|
|
19
|
+
type: 'step-start';
|
|
20
|
+
index: number;
|
|
21
|
+
};
|
|
22
|
+
type TextStart = {
|
|
23
|
+
type: 'text-start';
|
|
24
|
+
id: ContentBlockID;
|
|
25
|
+
providerMetadata?: ProviderMetadata;
|
|
26
|
+
};
|
|
27
|
+
type TextDelta = {
|
|
28
|
+
type: 'text-delta';
|
|
29
|
+
id: ContentBlockID;
|
|
30
|
+
text: string;
|
|
31
|
+
providerMetadata?: ProviderMetadata;
|
|
32
|
+
};
|
|
33
|
+
type TextEnd = {
|
|
34
|
+
type: 'text-end';
|
|
35
|
+
id: ContentBlockID;
|
|
36
|
+
providerMetadata?: ProviderMetadata;
|
|
37
|
+
};
|
|
38
|
+
type ReasoningStart = {
|
|
39
|
+
type: 'reasoning-start';
|
|
40
|
+
id: ContentBlockID;
|
|
41
|
+
providerMetadata?: ProviderMetadata;
|
|
42
|
+
};
|
|
43
|
+
type ReasoningDelta = {
|
|
44
|
+
type: 'reasoning-delta';
|
|
45
|
+
id: ContentBlockID;
|
|
46
|
+
text: string;
|
|
47
|
+
providerMetadata?: ProviderMetadata;
|
|
48
|
+
};
|
|
49
|
+
type ReasoningEnd = {
|
|
50
|
+
type: 'reasoning-end';
|
|
51
|
+
id: ContentBlockID;
|
|
52
|
+
providerMetadata?: ProviderMetadata;
|
|
53
|
+
};
|
|
54
|
+
type ToolInputStart = {
|
|
55
|
+
type: 'tool-input-start';
|
|
56
|
+
id: ToolCallID;
|
|
57
|
+
name: string;
|
|
58
|
+
providerMetadata?: ProviderMetadata;
|
|
59
|
+
};
|
|
60
|
+
type ToolInputDelta = {
|
|
61
|
+
type: 'tool-input-delta';
|
|
62
|
+
id: ToolCallID;
|
|
63
|
+
name: string;
|
|
64
|
+
text: string;
|
|
65
|
+
providerMetadata?: ProviderMetadata;
|
|
66
|
+
};
|
|
67
|
+
type ToolInputEnd = {
|
|
68
|
+
type: 'tool-input-end';
|
|
69
|
+
id: ToolCallID;
|
|
70
|
+
name: string;
|
|
71
|
+
providerMetadata?: ProviderMetadata;
|
|
72
|
+
};
|
|
73
|
+
type ToolCallEvent = {
|
|
74
|
+
type: 'tool-call';
|
|
75
|
+
id: ToolCallID;
|
|
76
|
+
name: string;
|
|
77
|
+
input: unknown;
|
|
78
|
+
providerExecuted?: boolean;
|
|
79
|
+
providerMetadata?: ProviderMetadata;
|
|
80
|
+
};
|
|
81
|
+
type ToolResultEvent = {
|
|
82
|
+
type: 'tool-result';
|
|
83
|
+
id: ToolCallID;
|
|
84
|
+
name: string;
|
|
85
|
+
result: ToolResultValue;
|
|
86
|
+
providerExecuted?: boolean;
|
|
87
|
+
providerMetadata?: ProviderMetadata;
|
|
88
|
+
};
|
|
89
|
+
type ToolErrorEvent = {
|
|
90
|
+
type: 'tool-error';
|
|
91
|
+
id: ToolCallID;
|
|
92
|
+
name: string;
|
|
93
|
+
message: string;
|
|
94
|
+
providerMetadata?: ProviderMetadata;
|
|
95
|
+
};
|
|
96
|
+
type StepFinish = {
|
|
97
|
+
type: 'step-finish';
|
|
98
|
+
index: number;
|
|
99
|
+
reason: FinishReason;
|
|
100
|
+
usage?: Usage;
|
|
101
|
+
providerMetadata?: ProviderMetadata;
|
|
102
|
+
};
|
|
103
|
+
type FinishEvent = {
|
|
104
|
+
type: 'finish';
|
|
105
|
+
reason: FinishReason;
|
|
106
|
+
usage?: Usage;
|
|
107
|
+
providerMetadata?: ProviderMetadata;
|
|
108
|
+
responseId?: ResponseID;
|
|
109
|
+
};
|
|
110
|
+
type ProviderErrorEvent = {
|
|
111
|
+
type: 'provider-error';
|
|
112
|
+
message: string;
|
|
113
|
+
classification?: 'context-overflow';
|
|
114
|
+
retryable?: boolean;
|
|
115
|
+
providerMetadata?: ProviderMetadata;
|
|
116
|
+
};
|
|
117
|
+
type StreamEvent = StepStart | TextStart | TextDelta | TextEnd | ReasoningStart | ReasoningDelta | ReasoningEnd | ToolInputStart | ToolInputDelta | ToolInputEnd | ToolCallEvent | ToolResultEvent | ToolErrorEvent | StepFinish | FinishEvent | ProviderErrorEvent;
|
|
118
|
+
type PreparedRequest = {
|
|
119
|
+
id: string;
|
|
120
|
+
route: RouteID;
|
|
121
|
+
protocol: ProtocolID;
|
|
122
|
+
model: Model;
|
|
123
|
+
body: unknown;
|
|
124
|
+
};
|
|
125
|
+
type LLMResponse = {
|
|
126
|
+
events: StreamEvent[];
|
|
127
|
+
usage?: Usage;
|
|
128
|
+
};
|
|
129
|
+
/** Fold a list of events into an LLMResponse (used by non-streaming chat). */
|
|
130
|
+
declare const foldResponse: (events: StreamEvent[]) => LLMResponse;
|
|
131
|
+
declare const responseText: (res: LLMResponse) => string;
|
|
132
|
+
declare const responseReasoning: (res: LLMResponse) => string;
|
|
133
|
+
declare const responseToolCalls: (res: LLMResponse) => ToolCallEvent[];
|
|
134
|
+
export type { FinishEvent, LLMResponse, PreparedRequest, ProviderErrorEvent, ReasoningDelta, ReasoningEnd, ReasoningStart, StepFinish, StepStart, StreamEvent, TextDelta, TextEnd, TextStart, ToolCallEvent, ToolErrorEvent, ToolInputDelta, ToolInputEnd, ToolInputStart, ToolResultEvent, Usage, UsageInput, };
|
|
135
|
+
export { foldResponse, responseReasoning, responseText, responseToolCalls, usageFrom, visibleOutputTokens, };
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
const usageFrom = (input) => {
|
|
2
|
+
const inputTokens = input.inputTokens;
|
|
3
|
+
const outputTokens = input.outputTokens;
|
|
4
|
+
const total = input.totalTokens ??
|
|
5
|
+
(inputTokens !== undefined || outputTokens !== undefined
|
|
6
|
+
? (inputTokens ?? 0) + (outputTokens ?? 0)
|
|
7
|
+
: undefined);
|
|
8
|
+
return { ...input, totalTokens: total };
|
|
9
|
+
};
|
|
10
|
+
/** Visible (non-reasoning) output tokens: max(0, output - reasoning). */
|
|
11
|
+
const visibleOutputTokens = (u) => {
|
|
12
|
+
const out = u.outputTokens ?? 0;
|
|
13
|
+
const reasoning = u.reasoningTokens ?? 0;
|
|
14
|
+
return Math.max(0, out - reasoning);
|
|
15
|
+
};
|
|
16
|
+
/** Fold a list of events into an LLMResponse (used by non-streaming chat). */
|
|
17
|
+
const foldResponse = (events) => {
|
|
18
|
+
let usage;
|
|
19
|
+
for (const event of events) {
|
|
20
|
+
if ((event.type === 'finish' || event.type === 'step-finish') && event.usage !== undefined) {
|
|
21
|
+
usage = event.usage;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
return { events, usage };
|
|
25
|
+
};
|
|
26
|
+
const responseText = (res) => res.events
|
|
27
|
+
.filter((e) => e.type === 'text-delta')
|
|
28
|
+
.map((e) => e.text)
|
|
29
|
+
.join('');
|
|
30
|
+
const responseReasoning = (res) => res.events
|
|
31
|
+
.filter((e) => e.type === 'reasoning-delta')
|
|
32
|
+
.map((e) => e.text)
|
|
33
|
+
.join('');
|
|
34
|
+
const responseToolCalls = (res) => res.events.filter((e) => e.type === 'tool-call');
|
|
35
|
+
export { foldResponse, responseReasoning, responseText, responseToolCalls, usageFrom, visibleOutputTokens, };
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/** Opaque-brand helper: a value of type T carrying a phantom brand B. */
|
|
2
|
+
type Brand<T, B> = T & {
|
|
3
|
+
readonly _brand?: B;
|
|
4
|
+
};
|
|
5
|
+
type ProtocolID = string;
|
|
6
|
+
type RouteID = string;
|
|
7
|
+
type ModelID = Brand<string, 'ModelID'>;
|
|
8
|
+
type ProviderID = Brand<string, 'ProviderID'>;
|
|
9
|
+
type ResponseID = string;
|
|
10
|
+
type ContentBlockID = string;
|
|
11
|
+
type ToolCallID = string;
|
|
12
|
+
type ReasoningEffort = 'none' | 'minimal' | 'low' | 'medium' | 'high' | 'xhigh' | 'max';
|
|
13
|
+
type TextVerbosity = 'low' | 'medium' | 'high';
|
|
14
|
+
type FinishReason = 'stop' | 'length' | 'tool-calls' | 'content-filter' | 'error' | 'unknown';
|
|
15
|
+
/** Loose JSON schema (provider passthrough; not validated structurally here). */
|
|
16
|
+
type JsonSchema = Record<string, unknown>;
|
|
17
|
+
/** Per-provider raw payload passthrough, keyed by provider id. */
|
|
18
|
+
type ProviderMetadata = Record<string, Record<string, unknown>>;
|
|
19
|
+
declare const modelId: (value: string) => ModelID;
|
|
20
|
+
declare const providerId: (value: string) => ProviderID;
|
|
21
|
+
export type { Brand, ContentBlockID, FinishReason, JsonSchema, ModelID, ProtocolID, ProviderID, ProviderMetadata, ReasoningEffort, ResponseID, RouteID, TextVerbosity, ToolCallID, };
|
|
22
|
+
export { modelId, providerId };
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import type { JsonSchema, ProviderMetadata, ToolCallID } from './ids.js';
|
|
2
|
+
import type { CacheHint, GenerationOptions, HttpOptions, Model, ProviderOptions } from './options.js';
|
|
3
|
+
type SystemPart = {
|
|
4
|
+
type: 'text';
|
|
5
|
+
text: string;
|
|
6
|
+
cache?: CacheHint;
|
|
7
|
+
metadata?: Record<string, unknown>;
|
|
8
|
+
};
|
|
9
|
+
type TextPart = {
|
|
10
|
+
type: 'text';
|
|
11
|
+
text: string;
|
|
12
|
+
cache?: CacheHint;
|
|
13
|
+
providerMetadata?: ProviderMetadata;
|
|
14
|
+
};
|
|
15
|
+
type ReasoningPart = {
|
|
16
|
+
type: 'reasoning';
|
|
17
|
+
text: string;
|
|
18
|
+
encrypted?: string;
|
|
19
|
+
providerMetadata?: ProviderMetadata;
|
|
20
|
+
};
|
|
21
|
+
type ToolCallPart = {
|
|
22
|
+
type: 'tool-call';
|
|
23
|
+
id: ToolCallID;
|
|
24
|
+
name: string;
|
|
25
|
+
input: unknown;
|
|
26
|
+
providerExecuted?: boolean;
|
|
27
|
+
providerMetadata?: ProviderMetadata;
|
|
28
|
+
};
|
|
29
|
+
type ToolResultValue = {
|
|
30
|
+
type: 'json';
|
|
31
|
+
value: unknown;
|
|
32
|
+
} | {
|
|
33
|
+
type: 'text';
|
|
34
|
+
value: unknown;
|
|
35
|
+
} | {
|
|
36
|
+
type: 'error';
|
|
37
|
+
value: unknown;
|
|
38
|
+
};
|
|
39
|
+
type ToolResultPart = {
|
|
40
|
+
type: 'tool-result';
|
|
41
|
+
id: ToolCallID;
|
|
42
|
+
name: string;
|
|
43
|
+
result: ToolResultValue;
|
|
44
|
+
providerExecuted?: boolean;
|
|
45
|
+
cache?: CacheHint;
|
|
46
|
+
providerMetadata?: ProviderMetadata;
|
|
47
|
+
};
|
|
48
|
+
type ContentPart = TextPart | ReasoningPart | ToolCallPart | ToolResultPart;
|
|
49
|
+
type MessageRole = 'system' | 'user' | 'assistant' | 'tool';
|
|
50
|
+
type Message = {
|
|
51
|
+
id?: string;
|
|
52
|
+
role: MessageRole;
|
|
53
|
+
content: ContentPart[];
|
|
54
|
+
metadata?: Record<string, unknown>;
|
|
55
|
+
};
|
|
56
|
+
declare const messageUser: (text: string) => Message;
|
|
57
|
+
declare const messageAssistant: (text: string) => Message;
|
|
58
|
+
declare const messageSystem: (text: string) => Message;
|
|
59
|
+
type ToolDefinition = {
|
|
60
|
+
name: string;
|
|
61
|
+
description: string;
|
|
62
|
+
inputSchema: JsonSchema;
|
|
63
|
+
outputSchema?: JsonSchema;
|
|
64
|
+
cache?: CacheHint;
|
|
65
|
+
};
|
|
66
|
+
type ToolChoice = {
|
|
67
|
+
type: 'auto';
|
|
68
|
+
} | {
|
|
69
|
+
type: 'none';
|
|
70
|
+
} | {
|
|
71
|
+
type: 'required';
|
|
72
|
+
} | {
|
|
73
|
+
type: 'tool';
|
|
74
|
+
name: string;
|
|
75
|
+
};
|
|
76
|
+
type ResponseFormat = {
|
|
77
|
+
type: 'text';
|
|
78
|
+
} | {
|
|
79
|
+
type: 'json';
|
|
80
|
+
schema: JsonSchema;
|
|
81
|
+
};
|
|
82
|
+
type InternalRequest = {
|
|
83
|
+
id?: string;
|
|
84
|
+
model: Model;
|
|
85
|
+
system: SystemPart[];
|
|
86
|
+
messages: Message[];
|
|
87
|
+
tools: ToolDefinition[];
|
|
88
|
+
toolChoice?: ToolChoice;
|
|
89
|
+
generation?: GenerationOptions;
|
|
90
|
+
providerOptions?: ProviderOptions;
|
|
91
|
+
http?: HttpOptions;
|
|
92
|
+
responseFormat?: ResponseFormat;
|
|
93
|
+
};
|
|
94
|
+
/** Immutable patch of an InternalRequest. */
|
|
95
|
+
declare const requestUpdate: (req: InternalRequest, patch: Partial<InternalRequest>) => InternalRequest;
|
|
96
|
+
export type { ContentPart, InternalRequest, Message, MessageRole, ReasoningPart, ResponseFormat, SystemPart, TextPart, ToolCallPart, ToolChoice, ToolDefinition, ToolResultPart, ToolResultValue, };
|
|
97
|
+
export { messageAssistant, messageSystem, messageUser, requestUpdate };
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
const messageUser = (text) => ({
|
|
2
|
+
role: 'user',
|
|
3
|
+
content: [{ type: 'text', text }],
|
|
4
|
+
});
|
|
5
|
+
const messageAssistant = (text) => ({
|
|
6
|
+
role: 'assistant',
|
|
7
|
+
content: [{ type: 'text', text }],
|
|
8
|
+
});
|
|
9
|
+
const messageSystem = (text) => ({
|
|
10
|
+
role: 'system',
|
|
11
|
+
content: [{ type: 'text', text }],
|
|
12
|
+
});
|
|
13
|
+
/** Immutable patch of an InternalRequest. */
|
|
14
|
+
const requestUpdate = (req, patch) => ({
|
|
15
|
+
...req,
|
|
16
|
+
...patch,
|
|
17
|
+
});
|
|
18
|
+
export { messageAssistant, messageSystem, messageUser, requestUpdate };
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import type { JsonSchema, ModelID, ProviderID } from './ids.js';
|
|
2
|
+
type HttpOptions = {
|
|
3
|
+
body?: JsonSchema;
|
|
4
|
+
headers?: Record<string, string>;
|
|
5
|
+
query?: Record<string, string>;
|
|
6
|
+
};
|
|
7
|
+
type GenerationOptions = {
|
|
8
|
+
maxTokens?: number;
|
|
9
|
+
temperature?: number;
|
|
10
|
+
topP?: number;
|
|
11
|
+
topK?: number;
|
|
12
|
+
frequencyPenalty?: number;
|
|
13
|
+
presencePenalty?: number;
|
|
14
|
+
seed?: number;
|
|
15
|
+
stop?: string[];
|
|
16
|
+
};
|
|
17
|
+
type ModelLimits = {
|
|
18
|
+
context?: number;
|
|
19
|
+
output?: number;
|
|
20
|
+
};
|
|
21
|
+
type Model = {
|
|
22
|
+
readonly id: ModelID;
|
|
23
|
+
readonly provider: ProviderID;
|
|
24
|
+
readonly limits?: ModelLimits;
|
|
25
|
+
};
|
|
26
|
+
declare const model: (id: string, provider: string, limits?: ModelLimits) => Model;
|
|
27
|
+
/** Immutable patch of a Model. */
|
|
28
|
+
declare const modelUpdate: (m: Model, patch: Partial<ModelLimits>) => Model;
|
|
29
|
+
type CacheHint = {
|
|
30
|
+
type: 'ephemeral' | 'persistent';
|
|
31
|
+
ttlSeconds?: number;
|
|
32
|
+
};
|
|
33
|
+
type CachePolicyObject = {
|
|
34
|
+
tools?: boolean;
|
|
35
|
+
system?: boolean;
|
|
36
|
+
messages?: 'latest-user-message' | 'latest-assistant' | {
|
|
37
|
+
tail: number;
|
|
38
|
+
};
|
|
39
|
+
ttlSeconds?: number;
|
|
40
|
+
};
|
|
41
|
+
type CachePolicy = 'auto' | 'none' | CachePolicyObject;
|
|
42
|
+
type ProviderOptions = Record<string, Record<string, unknown>>;
|
|
43
|
+
type RouteDefaults = {
|
|
44
|
+
headers?: Record<string, string>;
|
|
45
|
+
limits?: ModelLimits;
|
|
46
|
+
generation?: GenerationOptions;
|
|
47
|
+
providerOptions?: ProviderOptions;
|
|
48
|
+
http?: HttpOptions;
|
|
49
|
+
};
|
|
50
|
+
declare const mergeGenerationOptions: (...opts: (GenerationOptions | undefined)[]) => GenerationOptions | undefined;
|
|
51
|
+
declare const mergeHttpOptions: (...opts: (HttpOptions | undefined)[]) => HttpOptions | undefined;
|
|
52
|
+
declare const mergeProviderOptions: (...opts: (ProviderOptions | undefined)[]) => ProviderOptions | undefined;
|
|
53
|
+
export type { CacheHint, CachePolicy, CachePolicyObject, GenerationOptions, HttpOptions, Model, ModelLimits, ProviderOptions, RouteDefaults, };
|
|
54
|
+
export { mergeGenerationOptions, mergeHttpOptions, mergeProviderOptions, model, modelUpdate };
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { modelId, providerId } from './ids.js';
|
|
2
|
+
const model = (id, provider, limits) => ({
|
|
3
|
+
id: modelId(id),
|
|
4
|
+
provider: providerId(provider),
|
|
5
|
+
limits,
|
|
6
|
+
});
|
|
7
|
+
/** Immutable patch of a Model. */
|
|
8
|
+
const modelUpdate = (m, patch) => ({
|
|
9
|
+
...m,
|
|
10
|
+
limits: { ...m.limits, ...patch },
|
|
11
|
+
});
|
|
12
|
+
const mergeGenerationOptions = (...opts) => {
|
|
13
|
+
const filtered = opts.filter((o) => o !== undefined);
|
|
14
|
+
if (filtered.length === 0)
|
|
15
|
+
return undefined;
|
|
16
|
+
const merged = {};
|
|
17
|
+
for (const o of filtered)
|
|
18
|
+
Object.assign(merged, o);
|
|
19
|
+
return merged;
|
|
20
|
+
};
|
|
21
|
+
const mergeHttpOptions = (...opts) => {
|
|
22
|
+
const filtered = opts.filter((o) => o !== undefined);
|
|
23
|
+
if (filtered.length === 0)
|
|
24
|
+
return undefined;
|
|
25
|
+
const merged = {};
|
|
26
|
+
const headers = {};
|
|
27
|
+
const query = {};
|
|
28
|
+
for (const o of filtered) {
|
|
29
|
+
if (o.body !== undefined)
|
|
30
|
+
merged.body = o.body;
|
|
31
|
+
if (o.headers !== undefined)
|
|
32
|
+
Object.assign(headers, o.headers);
|
|
33
|
+
if (o.query !== undefined)
|
|
34
|
+
Object.assign(query, o.query);
|
|
35
|
+
}
|
|
36
|
+
if (Object.keys(headers).length > 0)
|
|
37
|
+
merged.headers = headers;
|
|
38
|
+
if (Object.keys(query).length > 0)
|
|
39
|
+
merged.query = query;
|
|
40
|
+
return merged;
|
|
41
|
+
};
|
|
42
|
+
const mergeProviderOptions = (...opts) => {
|
|
43
|
+
const filtered = opts.filter((o) => o !== undefined);
|
|
44
|
+
if (filtered.length === 0)
|
|
45
|
+
return undefined;
|
|
46
|
+
const merged = {};
|
|
47
|
+
for (const o of filtered) {
|
|
48
|
+
for (const key of Object.keys(o)) {
|
|
49
|
+
merged[key] = { ...(merged[key] ?? {}), ...o[key] };
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
return merged;
|
|
53
|
+
};
|
|
54
|
+
export { mergeGenerationOptions, mergeHttpOptions, mergeProviderOptions, model, modelUpdate };
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Heuristic token estimate: ~4 characters per token for English/code text.
|
|
3
|
+
* This mirrors the common "chars / 4" approximation used by tiktoken's
|
|
4
|
+
* rough estimate mode. A real BPE tokenizer can be plugged in later without
|
|
5
|
+
* changing this signature.
|
|
6
|
+
*/
|
|
7
|
+
const TOKEN_CHARS_RATIO = 4;
|
|
8
|
+
const estimateTokens = (text) => {
|
|
9
|
+
if (text.length === 0)
|
|
10
|
+
return 0;
|
|
11
|
+
return Math.ceil(text.length / TOKEN_CHARS_RATIO);
|
|
12
|
+
};
|
|
13
|
+
export { estimateTokens };
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { llmError } from './schema/errors.js';
|
|
2
|
+
/**
|
|
3
|
+
* Parse a Server-Sent Events byte stream into individual `data:` payloads.
|
|
4
|
+
* Emits the decoded data string for each event block. Skips empty data and
|
|
5
|
+
* the `[DONE]` sentinel. Works for both OpenAI (`data: {...}`) and Anthropic
|
|
6
|
+
* (`event: {type}\ndata: {...}`) framing — only the `data:` lines are emitted.
|
|
7
|
+
*/
|
|
8
|
+
declare const sseFraming: (stream: ReadableStream<Uint8Array>) => AsyncGenerator<string, void, unknown>;
|
|
9
|
+
type StreamHTTPOptions = {
|
|
10
|
+
url: string;
|
|
11
|
+
body: unknown;
|
|
12
|
+
headers: Record<string, string>;
|
|
13
|
+
signal?: AbortSignal;
|
|
14
|
+
/** Injectable fetch (for tests). Defaults to global fetch. */
|
|
15
|
+
fetchImpl?: typeof fetch;
|
|
16
|
+
};
|
|
17
|
+
/**
|
|
18
|
+
* Eagerly POST a JSON body and return the response body stream for framing.
|
|
19
|
+
* Throws an LLMError (classified) on non-2xx responses or transport failure.
|
|
20
|
+
* Used when the connection must be retryable independently of frame consumption.
|
|
21
|
+
*/
|
|
22
|
+
declare const httpPost: (options: StreamHTTPOptions) => Promise<ReadableStream<Uint8Array>>;
|
|
23
|
+
/**
|
|
24
|
+
* POST a JSON body and yield SSE data frames from the response.
|
|
25
|
+
* Throws an LLMError on non-2xx responses, classifying context-overflow.
|
|
26
|
+
*/
|
|
27
|
+
declare const streamHTTP: (options: StreamHTTPOptions) => AsyncGenerator<string, void, unknown>;
|
|
28
|
+
/** Map an HTTP failure status + body to an LLMError. */
|
|
29
|
+
declare const classifyHttpError: (status: number, body: string, url: string, headers: Headers) => ReturnType<typeof llmError>;
|
|
30
|
+
export type { StreamHTTPOptions };
|
|
31
|
+
export { classifyHttpError, httpPost, sseFraming, streamHTTP };
|