evolcore 0.0.4 → 0.0.6
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/CHANGELOG.md +65 -3
- package/README.md +4 -12
- package/dist/agents/baseagent.js +39 -0
- package/dist/agents/claude-runner.js +10 -2
- package/dist/agents/codex-runner.js +37 -8
- package/dist/agents/ecagent-runner.js +1159 -0
- package/dist/agents/gemini-runner.js +4 -1
- package/dist/agents/runner-types.js +20 -4
- package/dist/aun/msg/history.js +32 -9
- package/dist/aun/outbox.js +4 -9
- package/dist/channels/aun.js +32 -6
- package/dist/channels/daemon.js +7 -4
- package/dist/channels/dingtalk.js +3 -5
- package/dist/channels/feishu.js +16 -108
- package/dist/channels/wechat.js +4 -4
- package/dist/channels/wecom.js +4 -6
- package/dist/cli/agent-command.js +1 -1
- package/dist/cli/agent.js +42 -11
- package/dist/cli/aun-commands.js +50 -3
- package/dist/cli/daemon-commands.js +127 -21
- package/dist/cli/data-command.js +132 -0
- package/dist/cli/index.js +11 -3
- package/dist/cli/init.js +116 -37
- package/dist/cli/net-check.js +9 -20
- package/dist/cli/restart-monitor.js +11 -2
- package/dist/cli/trigger-command.js +1 -1
- package/dist/cli/watch-msg.js +12 -25
- package/dist/config/access-policy-domain.js +0 -20
- package/dist/config/access-policy.js +5 -29
- package/dist/config/builtin-roles.js +3 -1
- package/dist/config/config-field-policy.js +1 -1
- package/dist/config/gateway-config.js +21 -4
- package/dist/config/resolved-config-op.js +10 -0
- package/dist/core/auth/operation-catalog.js +1 -1
- package/dist/core/command/command-handler.js +2 -2
- package/dist/core/command/connect-menu.js +20 -42
- package/dist/core/command/menu-handler.js +11 -9
- package/dist/core/command/role-menu.js +27 -0
- package/dist/core/command/slash-handler.js +18 -14
- package/dist/core/data-migration.js +1434 -0
- package/dist/core/handoff/store.js +14 -4
- package/dist/core/inference/text-inference.js +42 -1
- package/dist/core/message/inbound-admission.js +23 -13
- package/dist/core/message/pending-hints.js +1 -1
- package/dist/core/message/response-engine.js +406 -167
- package/dist/core/message/retry-scheduler.js +71 -0
- package/dist/core/model/model-catalog.js +7 -2
- package/dist/core/model/model-fallback.js +81 -0
- package/dist/core/protected-paths.js +41 -8
- package/dist/core/session/adapters/ecagent-session-file-adapter.js +112 -0
- package/dist/core/session/session-fs-store.js +300 -61
- package/dist/core/session/session-manager.js +225 -21
- package/dist/core/session/session-title.js +1 -0
- package/dist/core/session/session-turn-coordinator.js +8 -1
- package/dist/core/system-channels.js +1 -0
- package/dist/index.js +10 -9
- package/dist/paths.js +35 -27
- package/dist/trigger/feedback.js +16 -0
- package/dist/trigger/legacy-session-history.js +19 -0
- package/dist/trigger/manager.js +12 -1
- package/dist/trigger/parser.js +4 -2
- package/dist/trigger/scheduler.js +185 -15
- package/dist/trigger/session-lock.js +62 -0
- package/dist/trigger/state.js +64 -0
- package/dist/trigger/validation.js +32 -2
- package/dist/utils/aid-bind.js +1 -1
- package/dist/utils/cross-platform.js +8 -2
- package/dist/utils/error-utils.js +9 -0
- package/dist/utils/process-introspect.js +19 -3
- package/dist/utils/welcome.js +2 -3
- package/ecagent/LICENSE +21 -0
- package/ecagent/NOTICE +11 -0
- package/ecagent/README.md +61 -0
- package/ecagent/dist/agent-loop.d.ts +24 -0
- package/ecagent/dist/agent-loop.d.ts.map +1 -0
- package/ecagent/dist/agent-loop.js +547 -0
- package/ecagent/dist/agent-loop.js.map +1 -0
- package/ecagent/dist/agent.d.ts +127 -0
- package/ecagent/dist/agent.d.ts.map +1 -0
- package/ecagent/dist/agent.js +386 -0
- package/ecagent/dist/agent.js.map +1 -0
- package/ecagent/dist/harness/agent-harness.d.ts +95 -0
- package/ecagent/dist/harness/agent-harness.d.ts.map +1 -0
- package/ecagent/dist/harness/agent-harness.js +926 -0
- package/ecagent/dist/harness/agent-harness.js.map +1 -0
- package/ecagent/dist/harness/compaction/branch-summarization.d.ts +51 -0
- package/ecagent/dist/harness/compaction/branch-summarization.d.ts.map +1 -0
- package/ecagent/dist/harness/compaction/branch-summarization.js +174 -0
- package/ecagent/dist/harness/compaction/branch-summarization.js.map +1 -0
- package/ecagent/dist/harness/compaction/compaction.d.ts +95 -0
- package/ecagent/dist/harness/compaction/compaction.d.ts.map +1 -0
- package/ecagent/dist/harness/compaction/compaction.js +528 -0
- package/ecagent/dist/harness/compaction/compaction.js.map +1 -0
- package/ecagent/dist/harness/compaction/utils.d.ts +25 -0
- package/ecagent/dist/harness/compaction/utils.d.ts.map +1 -0
- package/ecagent/dist/harness/compaction/utils.js +131 -0
- package/ecagent/dist/harness/compaction/utils.js.map +1 -0
- package/ecagent/dist/harness/env/nodejs.d.ts +51 -0
- package/ecagent/dist/harness/env/nodejs.d.ts.map +1 -0
- package/ecagent/dist/harness/env/nodejs.js +513 -0
- package/ecagent/dist/harness/env/nodejs.js.map +1 -0
- package/ecagent/dist/harness/messages.d.ts +51 -0
- package/ecagent/dist/harness/messages.d.ts.map +1 -0
- package/ecagent/dist/harness/messages.js +102 -0
- package/ecagent/dist/harness/messages.js.map +1 -0
- package/ecagent/dist/harness/prompt-templates.d.ts +48 -0
- package/ecagent/dist/harness/prompt-templates.d.ts.map +1 -0
- package/ecagent/dist/harness/prompt-templates.js +230 -0
- package/ecagent/dist/harness/prompt-templates.js.map +1 -0
- package/ecagent/dist/harness/session/jsonl-repo.d.ts +26 -0
- package/ecagent/dist/harness/session/jsonl-repo.d.ts.map +1 -0
- package/ecagent/dist/harness/session/jsonl-repo.js +100 -0
- package/ecagent/dist/harness/session/jsonl-repo.js.map +1 -0
- package/ecagent/dist/harness/session/jsonl-storage.d.ts +34 -0
- package/ecagent/dist/harness/session/jsonl-storage.d.ts.map +1 -0
- package/ecagent/dist/harness/session/jsonl-storage.js +234 -0
- package/ecagent/dist/harness/session/jsonl-storage.js.map +1 -0
- package/ecagent/dist/harness/session/memory-repo.d.ts +18 -0
- package/ecagent/dist/harness/session/memory-repo.d.ts.map +1 -0
- package/ecagent/dist/harness/session/memory-repo.js +44 -0
- package/ecagent/dist/harness/session/memory-repo.js.map +1 -0
- package/ecagent/dist/harness/session/memory-storage.d.ts +25 -0
- package/ecagent/dist/harness/session/memory-storage.d.ts.map +1 -0
- package/ecagent/dist/harness/session/memory-storage.js +111 -0
- package/ecagent/dist/harness/session/memory-storage.js.map +1 -0
- package/ecagent/dist/harness/session/repo-utils.d.ts +11 -0
- package/ecagent/dist/harness/session/repo-utils.d.ts.map +1 -0
- package/ecagent/dist/harness/session/repo-utils.js +39 -0
- package/ecagent/dist/harness/session/repo-utils.js.map +1 -0
- package/ecagent/dist/harness/session/session.d.ts +47 -0
- package/ecagent/dist/harness/session/session.d.ts.map +1 -0
- package/ecagent/dist/harness/session/session.js +245 -0
- package/ecagent/dist/harness/session/session.js.map +1 -0
- package/ecagent/dist/harness/session/uuid.d.ts +2 -0
- package/ecagent/dist/harness/session/uuid.d.ts.map +1 -0
- package/ecagent/dist/harness/session/uuid.js +50 -0
- package/ecagent/dist/harness/session/uuid.js.map +1 -0
- package/ecagent/dist/harness/skills.d.ts +44 -0
- package/ecagent/dist/harness/skills.d.ts.map +1 -0
- package/ecagent/dist/harness/skills.js +311 -0
- package/ecagent/dist/harness/skills.js.map +1 -0
- package/ecagent/dist/harness/system-prompt.d.ts +3 -0
- package/ecagent/dist/harness/system-prompt.d.ts.map +1 -0
- package/ecagent/dist/harness/system-prompt.js +30 -0
- package/ecagent/dist/harness/system-prompt.js.map +1 -0
- package/ecagent/dist/harness/types.d.ts +619 -0
- package/ecagent/dist/harness/types.d.ts.map +1 -0
- package/ecagent/dist/harness/types.js +81 -0
- package/ecagent/dist/harness/types.js.map +1 -0
- package/ecagent/dist/harness/utils/shell-output.d.ts +14 -0
- package/ecagent/dist/harness/utils/shell-output.d.ts.map +1 -0
- package/ecagent/dist/harness/utils/shell-output.js +126 -0
- package/ecagent/dist/harness/utils/shell-output.js.map +1 -0
- package/ecagent/dist/harness/utils/truncate.d.ts +70 -0
- package/ecagent/dist/harness/utils/truncate.d.ts.map +1 -0
- package/ecagent/dist/harness/utils/truncate.js +290 -0
- package/ecagent/dist/harness/utils/truncate.js.map +1 -0
- package/ecagent/dist/index.d.ts +22 -0
- package/ecagent/dist/index.d.ts.map +1 -0
- package/ecagent/dist/index.js +27 -0
- package/ecagent/dist/index.js.map +1 -0
- package/ecagent/dist/node.d.ts +3 -0
- package/ecagent/dist/node.d.ts.map +1 -0
- package/ecagent/dist/node.js +3 -0
- package/ecagent/dist/node.js.map +1 -0
- package/ecagent/dist/proxy.d.ts +69 -0
- package/ecagent/dist/proxy.d.ts.map +1 -0
- package/ecagent/dist/proxy.js +278 -0
- package/ecagent/dist/proxy.js.map +1 -0
- package/ecagent/dist/runtime/api/lazy.d.ts +15 -0
- package/ecagent/dist/runtime/api/lazy.d.ts.map +1 -0
- package/ecagent/dist/runtime/api/lazy.js +59 -0
- package/ecagent/dist/runtime/api/lazy.js.map +1 -0
- package/ecagent/dist/runtime/api/pi-messages.d.ts +97 -0
- package/ecagent/dist/runtime/api/pi-messages.d.ts.map +1 -0
- package/ecagent/dist/runtime/api/pi-messages.js +307 -0
- package/ecagent/dist/runtime/api/pi-messages.js.map +1 -0
- package/ecagent/dist/runtime/api/pi-messages.lazy.d.ts +3 -0
- package/ecagent/dist/runtime/api/pi-messages.lazy.d.ts.map +1 -0
- package/ecagent/dist/runtime/api/pi-messages.lazy.js +3 -0
- package/ecagent/dist/runtime/api/pi-messages.lazy.js.map +1 -0
- package/ecagent/dist/runtime/auth/context.d.ts +7 -0
- package/ecagent/dist/runtime/auth/context.d.ts.map +1 -0
- package/ecagent/dist/runtime/auth/context.js +42 -0
- package/ecagent/dist/runtime/auth/context.js.map +1 -0
- package/ecagent/dist/runtime/auth/credential-store.d.ts +16 -0
- package/ecagent/dist/runtime/auth/credential-store.d.ts.map +1 -0
- package/ecagent/dist/runtime/auth/credential-store.js +39 -0
- package/ecagent/dist/runtime/auth/credential-store.js.map +1 -0
- package/ecagent/dist/runtime/auth/helpers.d.ts +20 -0
- package/ecagent/dist/runtime/auth/helpers.d.ts.map +1 -0
- package/ecagent/dist/runtime/auth/helpers.js +46 -0
- package/ecagent/dist/runtime/auth/helpers.js.map +1 -0
- package/ecagent/dist/runtime/auth/resolve.d.ts +26 -0
- package/ecagent/dist/runtime/auth/resolve.d.ts.map +1 -0
- package/ecagent/dist/runtime/auth/resolve.js +100 -0
- package/ecagent/dist/runtime/auth/resolve.js.map +1 -0
- package/ecagent/dist/runtime/auth/types.d.ts +180 -0
- package/ecagent/dist/runtime/auth/types.d.ts.map +1 -0
- package/ecagent/dist/runtime/auth/types.js +2 -0
- package/ecagent/dist/runtime/auth/types.js.map +1 -0
- package/ecagent/dist/runtime/compat.d.ts +28 -0
- package/ecagent/dist/runtime/compat.d.ts.map +1 -0
- package/ecagent/dist/runtime/compat.js +86 -0
- package/ecagent/dist/runtime/compat.js.map +1 -0
- package/ecagent/dist/runtime/index.d.ts +20 -0
- package/ecagent/dist/runtime/index.d.ts.map +1 -0
- package/ecagent/dist/runtime/index.js +17 -0
- package/ecagent/dist/runtime/index.js.map +1 -0
- package/ecagent/dist/runtime/models.d.ts +142 -0
- package/ecagent/dist/runtime/models.d.ts.map +1 -0
- package/ecagent/dist/runtime/models.js +245 -0
- package/ecagent/dist/runtime/models.js.map +1 -0
- package/ecagent/dist/runtime/oauth.d.ts +2 -0
- package/ecagent/dist/runtime/oauth.d.ts.map +1 -0
- package/ecagent/dist/runtime/oauth.js +2 -0
- package/ecagent/dist/runtime/oauth.js.map +1 -0
- package/ecagent/dist/runtime/providers/faux.d.ts +97 -0
- package/ecagent/dist/runtime/providers/faux.d.ts.map +1 -0
- package/ecagent/dist/runtime/providers/faux.js +395 -0
- package/ecagent/dist/runtime/providers/faux.js.map +1 -0
- package/ecagent/dist/runtime/types.d.ts +607 -0
- package/ecagent/dist/runtime/types.d.ts.map +1 -0
- package/ecagent/dist/runtime/types.js +2 -0
- package/ecagent/dist/runtime/types.js.map +1 -0
- package/ecagent/dist/runtime/utils/diagnostics.d.ts +19 -0
- package/ecagent/dist/runtime/utils/diagnostics.d.ts.map +1 -0
- package/ecagent/dist/runtime/utils/diagnostics.js +25 -0
- package/ecagent/dist/runtime/utils/diagnostics.js.map +1 -0
- package/ecagent/dist/runtime/utils/event-stream.d.ts +21 -0
- package/ecagent/dist/runtime/utils/event-stream.d.ts.map +1 -0
- package/ecagent/dist/runtime/utils/event-stream.js +77 -0
- package/ecagent/dist/runtime/utils/event-stream.js.map +1 -0
- package/ecagent/dist/runtime/utils/headers.d.ts +4 -0
- package/ecagent/dist/runtime/utils/headers.d.ts.map +1 -0
- package/ecagent/dist/runtime/utils/headers.js +18 -0
- package/ecagent/dist/runtime/utils/headers.js.map +1 -0
- package/ecagent/dist/runtime/utils/json-parse.d.ts +16 -0
- package/ecagent/dist/runtime/utils/json-parse.d.ts.map +1 -0
- package/ecagent/dist/runtime/utils/json-parse.js +113 -0
- package/ecagent/dist/runtime/utils/json-parse.js.map +1 -0
- package/ecagent/dist/runtime/utils/oauth/types.d.ts +64 -0
- package/ecagent/dist/runtime/utils/oauth/types.d.ts.map +1 -0
- package/ecagent/dist/runtime/utils/oauth/types.js +2 -0
- package/ecagent/dist/runtime/utils/oauth/types.js.map +1 -0
- package/ecagent/dist/runtime/utils/overflow.d.ts +58 -0
- package/ecagent/dist/runtime/utils/overflow.d.ts.map +1 -0
- package/ecagent/dist/runtime/utils/overflow.js +158 -0
- package/ecagent/dist/runtime/utils/overflow.js.map +1 -0
- package/ecagent/dist/runtime/utils/provider-env.d.ts +7 -0
- package/ecagent/dist/runtime/utils/provider-env.d.ts.map +1 -0
- package/ecagent/dist/runtime/utils/provider-env.js +44 -0
- package/ecagent/dist/runtime/utils/provider-env.js.map +1 -0
- package/ecagent/dist/runtime/utils/retry.d.ts +12 -0
- package/ecagent/dist/runtime/utils/retry.d.ts.map +1 -0
- package/ecagent/dist/runtime/utils/retry.js +90 -0
- package/ecagent/dist/runtime/utils/retry.js.map +1 -0
- package/ecagent/dist/runtime/utils/typebox-helpers.d.ts +17 -0
- package/ecagent/dist/runtime/utils/typebox-helpers.d.ts.map +1 -0
- package/ecagent/dist/runtime/utils/typebox-helpers.js +21 -0
- package/ecagent/dist/runtime/utils/typebox-helpers.js.map +1 -0
- package/ecagent/dist/runtime/utils/validation.d.ts +18 -0
- package/ecagent/dist/runtime/utils/validation.d.ts.map +1 -0
- package/ecagent/dist/runtime/utils/validation.js +269 -0
- package/ecagent/dist/runtime/utils/validation.js.map +1 -0
- package/ecagent/dist/types.d.ts +401 -0
- package/ecagent/dist/types.d.ts.map +1 -0
- package/ecagent/dist/types.js +2 -0
- package/ecagent/dist/types.js.map +1 -0
- package/ecagent/package.json +93 -0
- package/ecagent/src/agent-loop.ts +792 -0
- package/ecagent/src/agent.ts +575 -0
- package/ecagent/src/harness/agent-harness.ts +1029 -0
- package/ecagent/src/harness/compaction/branch-summarization.ts +261 -0
- package/ecagent/src/harness/compaction/compaction.ts +753 -0
- package/ecagent/src/harness/compaction/utils.ts +144 -0
- package/ecagent/src/harness/env/nodejs.ts +569 -0
- package/ecagent/src/harness/messages.ts +164 -0
- package/ecagent/src/harness/prompt-templates.ts +267 -0
- package/ecagent/src/harness/session/jsonl-repo.ts +179 -0
- package/ecagent/src/harness/session/jsonl-storage.ts +314 -0
- package/ecagent/src/harness/session/memory-repo.ts +50 -0
- package/ecagent/src/harness/session/memory-storage.ts +133 -0
- package/ecagent/src/harness/session/repo-utils.ts +51 -0
- package/ecagent/src/harness/session/session.ts +338 -0
- package/ecagent/src/harness/session/uuid.ts +54 -0
- package/ecagent/src/harness/skills.ts +375 -0
- package/ecagent/src/harness/system-prompt.ts +34 -0
- package/ecagent/src/harness/types.ts +838 -0
- package/ecagent/src/harness/utils/shell-output.ts +135 -0
- package/ecagent/src/harness/utils/truncate.ts +344 -0
- package/ecagent/src/index.ts +46 -0
- package/ecagent/src/node.ts +2 -0
- package/ecagent/src/proxy.ts +367 -0
- package/ecagent/src/runtime/api/lazy.ts +70 -0
- package/ecagent/src/runtime/api/pi-messages.lazy.ts +4 -0
- package/ecagent/src/runtime/api/pi-messages.ts +436 -0
- package/ecagent/src/runtime/auth/context.ts +45 -0
- package/ecagent/src/runtime/auth/credential-store.ts +47 -0
- package/ecagent/src/runtime/auth/helpers.ts +46 -0
- package/ecagent/src/runtime/auth/resolve.ts +141 -0
- package/ecagent/src/runtime/auth/types.ts +182 -0
- package/ecagent/src/runtime/compat.ts +158 -0
- package/ecagent/src/runtime/index.ts +31 -0
- package/ecagent/src/runtime/models.ts +452 -0
- package/ecagent/src/runtime/oauth.ts +1 -0
- package/ecagent/src/runtime/providers/faux.ts +538 -0
- package/ecagent/src/runtime/types.ts +718 -0
- package/ecagent/src/runtime/utils/diagnostics.ts +45 -0
- package/ecagent/src/runtime/utils/event-stream.ts +88 -0
- package/ecagent/src/runtime/utils/headers.ts +18 -0
- package/ecagent/src/runtime/utils/json-parse.ts +124 -0
- package/ecagent/src/runtime/utils/oauth/types.ts +79 -0
- package/ecagent/src/runtime/utils/overflow.ts +165 -0
- package/ecagent/src/runtime/utils/provider-env.ts +52 -0
- package/ecagent/src/runtime/utils/retry.ts +101 -0
- package/ecagent/src/runtime/utils/typebox-helpers.ts +24 -0
- package/ecagent/src/runtime/utils/validation.ts +310 -0
- package/ecagent/src/types.ts +430 -0
- package/ecagent/tsconfig.build.json +32 -0
- package/kits/docs/evolcore/config.md +4 -4
- package/kits/docs/evolcore/contact.md +2 -1
- package/kits/schemas/_meta.json +7 -4
- package/kits/schemas/agent-config.schema.10.json +370 -0
- package/kits/schemas/agent-config.schema.9.json +2 -12
- package/kits/schemas/defaults.schema.4.json +93 -0
- package/kits/schemas/relation-config.schema.8.json +69 -0
- package/kits/templates/roles/admin.json +1 -1
- package/package.json +22 -6
- package/skills/eclink/SKILL.md +70 -0
- package/skills/eclink/agents/openai.yaml +4 -0
- package/assets/.env.template +0 -4
|
@@ -0,0 +1,452 @@
|
|
|
1
|
+
import { lazyStream } from "./api/lazy.ts";
|
|
2
|
+
import { defaultProviderAuthContext as defaultAuthContext } from "./auth/context.ts";
|
|
3
|
+
import { InMemoryCredentialStore } from "./auth/credential-store.ts";
|
|
4
|
+
import { ModelsError, resolveProviderAuth } from "./auth/resolve.ts";
|
|
5
|
+
import type { AuthContext, AuthResult, CredentialStore, ProviderAuth } from "./auth/types.ts";
|
|
6
|
+
import type {
|
|
7
|
+
Api,
|
|
8
|
+
ApiStreamOptions,
|
|
9
|
+
AssistantMessage,
|
|
10
|
+
AssistantMessageEventStream,
|
|
11
|
+
Context,
|
|
12
|
+
Model,
|
|
13
|
+
ModelCostRates,
|
|
14
|
+
ModelThinkingLevel,
|
|
15
|
+
ProviderHeaders,
|
|
16
|
+
ProviderStreams,
|
|
17
|
+
SimpleStreamOptions,
|
|
18
|
+
StreamOptions,
|
|
19
|
+
Usage,
|
|
20
|
+
} from "./types.ts";
|
|
21
|
+
|
|
22
|
+
export { type AuthModel, ModelsError, type ModelsErrorCode } from "./auth/resolve.ts";
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* A provider is the concrete runtime unit. It owns id/name/base metadata,
|
|
26
|
+
* auth methods, model listing, and stream behavior.
|
|
27
|
+
*
|
|
28
|
+
* `TApi` lets concrete provider factories declare which APIs their models
|
|
29
|
+
* use (e.g. `openaiProvider(): Provider<"openai-responses" | "openai-completions">`),
|
|
30
|
+
* giving typed model lists to direct factory users. Inside a `Models`
|
|
31
|
+
* collection providers are held as `Provider<Api>`.
|
|
32
|
+
*/
|
|
33
|
+
export interface Provider<TApi extends Api = Api> {
|
|
34
|
+
readonly id: string;
|
|
35
|
+
readonly name: string;
|
|
36
|
+
|
|
37
|
+
readonly baseUrl?: string;
|
|
38
|
+
readonly headers?: ProviderHeaders;
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Required: at least one of `apiKey`/`oauth`. Every provider has auth
|
|
42
|
+
* semantics — even providers with only ambient credentials (env vars, AWS
|
|
43
|
+
* profiles, ADC files) and keyless local servers provide `apiKey` auth
|
|
44
|
+
* whose `resolve()` reports whether the provider is configured.
|
|
45
|
+
* `Models.getAuth()` returns undefined when the provider is unconfigured.
|
|
46
|
+
*/
|
|
47
|
+
readonly auth: ProviderAuth;
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Current known models, sync. Static providers return their catalog;
|
|
51
|
+
* dynamic providers return the list as of the last `refreshModels()`
|
|
52
|
+
* (empty before the first). Must not throw; `Models` treats a throwing
|
|
53
|
+
* implementation as having no models.
|
|
54
|
+
*/
|
|
55
|
+
getModels(): readonly Model<TApi>[];
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Dynamic providers only: fetch and update the model list. Side-effect-free
|
|
59
|
+
* discovery (no loading/downloading); provider-specific model lifecycle
|
|
60
|
+
* belongs in app commands. Concurrent calls share one in-flight fetch.
|
|
61
|
+
* May reject (network); on rejection the model list stays at its last-known
|
|
62
|
+
* state and a later call retries.
|
|
63
|
+
*/
|
|
64
|
+
refreshModels?(): Promise<void>;
|
|
65
|
+
|
|
66
|
+
stream<T extends TApi>(
|
|
67
|
+
model: Model<T>,
|
|
68
|
+
context: Context,
|
|
69
|
+
options?: ApiStreamOptions<T>,
|
|
70
|
+
): AssistantMessageEventStream;
|
|
71
|
+
|
|
72
|
+
streamSimple(model: Model<TApi>, context: Context, options?: SimpleStreamOptions): AssistantMessageEventStream;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Runtime collection of providers plus auth application and stream
|
|
77
|
+
* convenience. Providers own stream behavior; `Models` resolves auth and
|
|
78
|
+
* delegates each request to the provider that owns the model.
|
|
79
|
+
*/
|
|
80
|
+
export interface Models {
|
|
81
|
+
getProviders(): readonly Provider[];
|
|
82
|
+
getProvider(id: string): Provider | undefined;
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Sync read of last-known models from one provider or all providers.
|
|
86
|
+
* Best-effort: a provider whose `getModels()` throws yields no models.
|
|
87
|
+
*/
|
|
88
|
+
getModels(provider?: string): readonly Model<Api>[];
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Sync runtime model lookup against last-known lists. Dynamic model lists
|
|
92
|
+
* are typed as `Model<Api>`; narrow with the `hasApi()` type guard.
|
|
93
|
+
*/
|
|
94
|
+
getModel(provider: string, id: string): Model<Api> | undefined;
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Ask dynamic providers to re-fetch their model lists. With a provider id,
|
|
98
|
+
* rejects with `ModelsError` ("model_source") on that provider's fetch
|
|
99
|
+
* failure; without one, refreshes all providers concurrently best-effort.
|
|
100
|
+
* Static providers (no `refreshModels`) are no-ops.
|
|
101
|
+
*/
|
|
102
|
+
refresh(provider?: string): Promise<void>;
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Resolve request auth for a model. Includes a source label for status UI.
|
|
106
|
+
* Resolves `undefined` when the provider is unknown or unconfigured.
|
|
107
|
+
* Rejects with `ModelsError`: code "oauth" when a token refresh fails (the
|
|
108
|
+
* stored credential is preserved for retry; re-login fixes it), code "auth"
|
|
109
|
+
* when api-key resolution or the credential store fails. Request paths
|
|
110
|
+
* surface rejections as stream errors; status/availability UIs catch them
|
|
111
|
+
* and render "needs re-login" instead of treating them as unconfigured.
|
|
112
|
+
*/
|
|
113
|
+
getAuth(model: Model<Api>): Promise<AuthResult | undefined>;
|
|
114
|
+
|
|
115
|
+
stream<TApi extends Api>(
|
|
116
|
+
model: Model<TApi>,
|
|
117
|
+
context: Context,
|
|
118
|
+
options?: ApiStreamOptions<TApi>,
|
|
119
|
+
): AssistantMessageEventStream;
|
|
120
|
+
|
|
121
|
+
complete<TApi extends Api>(
|
|
122
|
+
model: Model<TApi>,
|
|
123
|
+
context: Context,
|
|
124
|
+
options?: ApiStreamOptions<TApi>,
|
|
125
|
+
): Promise<AssistantMessage>;
|
|
126
|
+
|
|
127
|
+
streamSimple(model: Model<Api>, context: Context, options?: SimpleStreamOptions): AssistantMessageEventStream;
|
|
128
|
+
completeSimple(model: Model<Api>, context: Context, options?: SimpleStreamOptions): Promise<AssistantMessage>;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
export interface MutableModels extends Models {
|
|
132
|
+
/** Upsert/replace by provider.id. Provider ids are unique. */
|
|
133
|
+
setProvider(provider: Provider): void;
|
|
134
|
+
deleteProvider(id: string): void;
|
|
135
|
+
clearProviders(): void;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
export interface CreateModelsOptions {
|
|
139
|
+
credentials?: CredentialStore;
|
|
140
|
+
authContext?: AuthContext;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
class ModelsImpl implements MutableModels {
|
|
144
|
+
private providers = new Map<string, Provider>();
|
|
145
|
+
private credentials: CredentialStore;
|
|
146
|
+
private authContext: AuthContext;
|
|
147
|
+
|
|
148
|
+
constructor(options?: CreateModelsOptions) {
|
|
149
|
+
this.credentials = options?.credentials ?? new InMemoryCredentialStore();
|
|
150
|
+
this.authContext = options?.authContext ?? defaultAuthContext();
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
setProvider(provider: Provider): void {
|
|
154
|
+
this.providers.set(provider.id, provider);
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
deleteProvider(id: string): void {
|
|
158
|
+
this.providers.delete(id);
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
clearProviders(): void {
|
|
162
|
+
this.providers.clear();
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
getProviders(): readonly Provider[] {
|
|
166
|
+
return Array.from(this.providers.values());
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
getProvider(id: string): Provider | undefined {
|
|
170
|
+
return this.providers.get(id);
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
getModels(provider?: string): readonly Model<Api>[] {
|
|
174
|
+
if (provider !== undefined) {
|
|
175
|
+
const entry = this.providers.get(provider);
|
|
176
|
+
if (!entry) return [];
|
|
177
|
+
try {
|
|
178
|
+
return entry.getModels();
|
|
179
|
+
} catch {
|
|
180
|
+
return [];
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
const models: Model<Api>[] = [];
|
|
185
|
+
for (const entry of this.providers.values()) {
|
|
186
|
+
try {
|
|
187
|
+
models.push(...entry.getModels());
|
|
188
|
+
} catch {
|
|
189
|
+
// Best-effort: ill-behaved providers yield no models.
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
return models;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
getModel(provider: string, id: string): Model<Api> | undefined {
|
|
196
|
+
return this.getModels(provider).find((model) => model.id === id);
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
async refresh(provider?: string): Promise<void> {
|
|
200
|
+
if (provider !== undefined) {
|
|
201
|
+
const entry = this.providers.get(provider);
|
|
202
|
+
if (!entry?.refreshModels) return;
|
|
203
|
+
try {
|
|
204
|
+
await entry.refreshModels();
|
|
205
|
+
} catch (error) {
|
|
206
|
+
if (error instanceof ModelsError) throw error;
|
|
207
|
+
throw new ModelsError("model_source", `Model refresh failed for ${provider}`, { cause: error });
|
|
208
|
+
}
|
|
209
|
+
return;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
// Cannot reject: the async mapper turns even sync throws from ill-behaved
|
|
213
|
+
// providers into rejections, and allSettled captures all of them.
|
|
214
|
+
await Promise.allSettled(Array.from(this.providers.values(), async (entry) => entry.refreshModels?.()));
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
async getAuth(model: Model<Api>): Promise<AuthResult | undefined> {
|
|
218
|
+
const provider = this.providers.get(model.provider);
|
|
219
|
+
if (!provider) return undefined;
|
|
220
|
+
return resolveProviderAuth(provider, model, this.credentials, this.authContext);
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
private requireProvider(model: Model<Api>): Provider {
|
|
224
|
+
const provider = this.providers.get(model.provider);
|
|
225
|
+
if (!provider) {
|
|
226
|
+
throw new ModelsError("provider", `Unknown provider: ${model.provider}`);
|
|
227
|
+
}
|
|
228
|
+
return provider;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
private async applyAuth<TOptions extends StreamOptions>(
|
|
232
|
+
model: Model<Api>,
|
|
233
|
+
options: TOptions | undefined,
|
|
234
|
+
): Promise<{ requestModel: Model<Api>; requestOptions: TOptions | undefined }> {
|
|
235
|
+
const resolution = await resolveProviderAuth(
|
|
236
|
+
this.requireProvider(model),
|
|
237
|
+
model,
|
|
238
|
+
this.credentials,
|
|
239
|
+
this.authContext,
|
|
240
|
+
{
|
|
241
|
+
apiKey: options?.apiKey,
|
|
242
|
+
env: options?.env,
|
|
243
|
+
},
|
|
244
|
+
);
|
|
245
|
+
const auth = resolution?.auth;
|
|
246
|
+
if (!auth) return { requestModel: model, requestOptions: options };
|
|
247
|
+
|
|
248
|
+
const requestModel = auth.baseUrl ? { ...model, baseUrl: auth.baseUrl } : model;
|
|
249
|
+
|
|
250
|
+
// Explicit request options win per-field; headers/env merge per key.
|
|
251
|
+
const apiKey = options?.apiKey ?? auth.apiKey;
|
|
252
|
+
const headers = auth.headers || options?.headers ? { ...auth.headers, ...options?.headers } : undefined;
|
|
253
|
+
const env = resolution.env || options?.env ? { ...(resolution.env ?? {}), ...(options?.env ?? {}) } : undefined;
|
|
254
|
+
const requestOptions = { ...options, apiKey, headers, env } as TOptions;
|
|
255
|
+
|
|
256
|
+
return { requestModel, requestOptions };
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
stream<TApi extends Api>(
|
|
260
|
+
model: Model<TApi>,
|
|
261
|
+
context: Context,
|
|
262
|
+
options?: ApiStreamOptions<TApi>,
|
|
263
|
+
): AssistantMessageEventStream {
|
|
264
|
+
return lazyStream(model, async () => {
|
|
265
|
+
const provider = this.requireProvider(model);
|
|
266
|
+
const { requestModel, requestOptions } = await this.applyAuth(model, options as StreamOptions | undefined);
|
|
267
|
+
return provider.stream(requestModel as Model<TApi>, context, requestOptions as ApiStreamOptions<TApi>);
|
|
268
|
+
});
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
async complete<TApi extends Api>(
|
|
272
|
+
model: Model<TApi>,
|
|
273
|
+
context: Context,
|
|
274
|
+
options?: ApiStreamOptions<TApi>,
|
|
275
|
+
): Promise<AssistantMessage> {
|
|
276
|
+
return this.stream(model, context, options).result();
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
streamSimple(model: Model<Api>, context: Context, options?: SimpleStreamOptions): AssistantMessageEventStream {
|
|
280
|
+
return lazyStream(model, async () => {
|
|
281
|
+
const provider = this.requireProvider(model);
|
|
282
|
+
const { requestModel, requestOptions } = await this.applyAuth(model, options);
|
|
283
|
+
return provider.streamSimple(requestModel, context, requestOptions);
|
|
284
|
+
});
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
async completeSimple(model: Model<Api>, context: Context, options?: SimpleStreamOptions): Promise<AssistantMessage> {
|
|
288
|
+
return this.streamSimple(model, context, options).result();
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
export function createModels(options?: CreateModelsOptions): MutableModels {
|
|
293
|
+
return new ModelsImpl(options);
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
export interface CreateProviderOptions<TApi extends Api = Api> {
|
|
297
|
+
id: string;
|
|
298
|
+
/** Display name. Default: `id`. */
|
|
299
|
+
name?: string;
|
|
300
|
+
baseUrl?: string;
|
|
301
|
+
headers?: ProviderHeaders;
|
|
302
|
+
/** Required — every provider has auth semantics, even ambient/keyless ones. */
|
|
303
|
+
auth: ProviderAuth;
|
|
304
|
+
/** Initial model list (empty for purely dynamic providers). */
|
|
305
|
+
models: readonly Model<TApi>[];
|
|
306
|
+
/**
|
|
307
|
+
* Dynamic providers: fetch the current list. Stored on success; concurrent
|
|
308
|
+
* calls share one in-flight fetch. May reject: the stored list then stays
|
|
309
|
+
* at its last-known state, the rejection propagates to the caller of
|
|
310
|
+
* `refreshModels()` (wrapped as ModelsError "model_source" by
|
|
311
|
+
* `Models.refresh(provider)`), and a later call retries.
|
|
312
|
+
*/
|
|
313
|
+
refreshModels?: () => Promise<readonly Model<TApi>[]>;
|
|
314
|
+
/** Single implementation, or map keyed by `model.api` for mixed-API providers. */
|
|
315
|
+
api: ProviderStreams | Partial<Record<TApi, ProviderStreams>>;
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
/**
|
|
319
|
+
* Builds a provider from parts. Built-in provider factories and models.json
|
|
320
|
+
* custom providers both go through this. A single `api` streams all models;
|
|
321
|
+
* an `api` map dispatches on `model.api`, and a model whose api has no entry
|
|
322
|
+
* produces a stream error.
|
|
323
|
+
*/
|
|
324
|
+
export function createProvider<TApi extends Api = Api>(input: CreateProviderOptions<TApi>): Provider<TApi> {
|
|
325
|
+
let models = input.models;
|
|
326
|
+
let inflightRefresh: Promise<void> | undefined;
|
|
327
|
+
const refreshModels = input.refreshModels;
|
|
328
|
+
const single =
|
|
329
|
+
typeof (input.api as ProviderStreams).stream === "function" ? (input.api as ProviderStreams) : undefined;
|
|
330
|
+
const byApi = single ? undefined : (input.api as Partial<Record<string, ProviderStreams>>);
|
|
331
|
+
|
|
332
|
+
const apiFor = (model: Model<Api>): ProviderStreams | undefined => single ?? byApi?.[model.api];
|
|
333
|
+
|
|
334
|
+
const dispatch = (
|
|
335
|
+
model: Model<Api>,
|
|
336
|
+
run: (streams: ProviderStreams) => AssistantMessageEventStream,
|
|
337
|
+
): AssistantMessageEventStream => {
|
|
338
|
+
const streams = apiFor(model);
|
|
339
|
+
if (!streams) {
|
|
340
|
+
return lazyStream(model, async () => {
|
|
341
|
+
throw new ModelsError("stream", `Provider ${input.id} has no API implementation for "${model.api}"`);
|
|
342
|
+
});
|
|
343
|
+
}
|
|
344
|
+
return run(streams);
|
|
345
|
+
};
|
|
346
|
+
|
|
347
|
+
return {
|
|
348
|
+
id: input.id,
|
|
349
|
+
name: input.name ?? input.id,
|
|
350
|
+
baseUrl: input.baseUrl,
|
|
351
|
+
headers: input.headers,
|
|
352
|
+
auth: input.auth,
|
|
353
|
+
getModels: () => models,
|
|
354
|
+
refreshModels: refreshModels
|
|
355
|
+
? () => {
|
|
356
|
+
inflightRefresh ??= (async () => {
|
|
357
|
+
try {
|
|
358
|
+
models = await refreshModels();
|
|
359
|
+
} finally {
|
|
360
|
+
inflightRefresh = undefined;
|
|
361
|
+
}
|
|
362
|
+
})();
|
|
363
|
+
return inflightRefresh;
|
|
364
|
+
}
|
|
365
|
+
: undefined,
|
|
366
|
+
stream: (model, context, options) => dispatch(model, (streams) => streams.stream(model, context, options)),
|
|
367
|
+
streamSimple: (model, context, options) =>
|
|
368
|
+
dispatch(model, (streams) => streams.streamSimple(model, context, options)),
|
|
369
|
+
};
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
/**
|
|
373
|
+
* Runtime-checked narrowing for dynamically looked-up models:
|
|
374
|
+
*
|
|
375
|
+
* ```ts
|
|
376
|
+
* const model = models.getModel("anthropic", "claude-opus-4-7");
|
|
377
|
+
* if (model && hasApi(model, "anthropic-messages")) {
|
|
378
|
+
* // model: Model<"anthropic-messages">, stream options fully typed
|
|
379
|
+
* }
|
|
380
|
+
* ```
|
|
381
|
+
*/
|
|
382
|
+
export function hasApi<TApi extends Api>(model: Model<Api>, api: TApi): model is Model<TApi> {
|
|
383
|
+
return model.api === api;
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
export function calculateCost<TApi extends Api>(model: Model<TApi>, usage: Usage): Usage["cost"] {
|
|
387
|
+
const inputTokens = usage.input + usage.cacheRead + usage.cacheWrite;
|
|
388
|
+
let rates: ModelCostRates = model.cost;
|
|
389
|
+
let matchedThreshold = -1;
|
|
390
|
+
for (const tier of model.cost.tiers ?? []) {
|
|
391
|
+
if (inputTokens > tier.inputTokensAbove && tier.inputTokensAbove > matchedThreshold) {
|
|
392
|
+
rates = tier;
|
|
393
|
+
matchedThreshold = tier.inputTokensAbove;
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
// Anthropic charges 2x base input for 1h cache writes.
|
|
398
|
+
const longWrite = usage.cacheWrite1h ?? 0;
|
|
399
|
+
const shortWrite = usage.cacheWrite - longWrite;
|
|
400
|
+
usage.cost.input = (rates.input / 1000000) * usage.input;
|
|
401
|
+
usage.cost.output = (rates.output / 1000000) * usage.output;
|
|
402
|
+
usage.cost.cacheRead = (rates.cacheRead / 1000000) * usage.cacheRead;
|
|
403
|
+
usage.cost.cacheWrite = (rates.cacheWrite * shortWrite + rates.input * 2 * longWrite) / 1000000;
|
|
404
|
+
usage.cost.total = usage.cost.input + usage.cost.output + usage.cost.cacheRead + usage.cost.cacheWrite;
|
|
405
|
+
return usage.cost;
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
const EXTENDED_THINKING_LEVELS: ModelThinkingLevel[] = ["off", "minimal", "low", "medium", "high", "xhigh", "max"];
|
|
409
|
+
|
|
410
|
+
export function getSupportedThinkingLevels<TApi extends Api>(model: Model<TApi>): ModelThinkingLevel[] {
|
|
411
|
+
if (!model.reasoning) return ["off"];
|
|
412
|
+
|
|
413
|
+
return EXTENDED_THINKING_LEVELS.filter((level) => {
|
|
414
|
+
const mapped = model.thinkingLevelMap?.[level];
|
|
415
|
+
if (mapped === null) return false;
|
|
416
|
+
if (level === "xhigh" || level === "max") return mapped !== undefined;
|
|
417
|
+
return true;
|
|
418
|
+
});
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
export function clampThinkingLevel<TApi extends Api>(
|
|
422
|
+
model: Model<TApi>,
|
|
423
|
+
level: ModelThinkingLevel,
|
|
424
|
+
): ModelThinkingLevel {
|
|
425
|
+
const availableLevels = getSupportedThinkingLevels(model);
|
|
426
|
+
if (availableLevels.includes(level)) return level;
|
|
427
|
+
|
|
428
|
+
const requestedIndex = EXTENDED_THINKING_LEVELS.indexOf(level);
|
|
429
|
+
if (requestedIndex === -1) return availableLevels[0] ?? "off";
|
|
430
|
+
|
|
431
|
+
for (let i = requestedIndex; i < EXTENDED_THINKING_LEVELS.length; i++) {
|
|
432
|
+
const candidate = EXTENDED_THINKING_LEVELS[i];
|
|
433
|
+
if (availableLevels.includes(candidate)) return candidate;
|
|
434
|
+
}
|
|
435
|
+
for (let i = requestedIndex - 1; i >= 0; i--) {
|
|
436
|
+
const candidate = EXTENDED_THINKING_LEVELS[i];
|
|
437
|
+
if (availableLevels.includes(candidate)) return candidate;
|
|
438
|
+
}
|
|
439
|
+
return availableLevels[0] ?? "off";
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
/**
|
|
443
|
+
* Check if two models are equal by comparing both their id and provider.
|
|
444
|
+
* Returns false if either model is null or undefined.
|
|
445
|
+
*/
|
|
446
|
+
export function modelsAreEqual<TApi extends Api>(
|
|
447
|
+
a: Model<TApi> | null | undefined,
|
|
448
|
+
b: Model<TApi> | null | undefined,
|
|
449
|
+
): boolean {
|
|
450
|
+
if (!a || !b) return false;
|
|
451
|
+
return a.id === b.id && a.provider === b.provider;
|
|
452
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export type * from "./utils/oauth/types.ts";
|