@poolzin/pool-bot 2026.2.23 → 2026.2.25
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 +29 -0
- package/dist/acp/client.js +207 -18
- package/dist/acp/secret-file.js +22 -0
- package/dist/agents/agent-scope.js +10 -0
- package/dist/agents/bash-process-registry.test-helpers.js +29 -0
- package/dist/agents/bash-tools.exec-approval-request.js +20 -0
- package/dist/agents/bash-tools.exec-host-gateway.js +230 -0
- package/dist/agents/bash-tools.exec-host-node.js +235 -0
- package/dist/agents/bash-tools.exec-types.js +1 -0
- package/dist/agents/bash-tools.process.js +224 -218
- package/dist/agents/content-blocks.js +16 -0
- package/dist/agents/model-fallback.js +96 -101
- package/dist/agents/models-config.providers.js +299 -182
- package/dist/agents/pi-embedded-payloads.js +1 -0
- package/dist/agents/pi-embedded-runner/run.overflow-compaction.fixture.js +34 -0
- package/dist/agents/skills.test-helpers.js +13 -0
- package/dist/agents/stable-stringify.js +12 -0
- package/dist/agents/subagent-registry.mocks.shared.js +12 -0
- package/dist/agents/test-helpers/assistant-message-fixtures.js +29 -0
- package/dist/agents/test-helpers/pi-tools-sandbox-context.js +27 -0
- package/dist/agents/tool-policy-shared.js +108 -0
- package/dist/agents/tools/browser-tool.js +160 -54
- package/dist/agents/tools/cron-tool.test-helpers.js +12 -0
- package/dist/agents/tools/discord-actions-moderation-shared.js +27 -0
- package/dist/agents/tools/image-tool.js +214 -99
- package/dist/agents/tools/sessions-history-tool.js +140 -108
- package/dist/agents/workspace.js +222 -46
- package/dist/auto-reply/commands-registry.js +15 -18
- package/dist/auto-reply/fallback-state.js +114 -0
- package/dist/auto-reply/model-runtime.js +68 -0
- package/dist/auto-reply/reply/agent-runner-execution.js +36 -4
- package/dist/auto-reply/reply/agent-runner.js +165 -39
- package/dist/auto-reply/reply/commands-setunset-standard.js +13 -0
- package/dist/browser/config.js +26 -0
- package/dist/browser/navigation-guard.js +31 -0
- package/dist/browser/routes/agent.act.js +431 -424
- package/dist/browser/routes/agent.shared.js +47 -3
- package/dist/browser/routes/agent.snapshot.js +122 -116
- package/dist/browser/routes/agent.storage.js +303 -297
- package/dist/browser/routes/tabs.js +154 -100
- package/dist/browser/server-lifecycle.js +37 -0
- package/dist/build-info.json +3 -3
- package/dist/channels/allow-from.js +25 -0
- package/dist/channels/plugins/account-action-gate.js +13 -0
- package/dist/channels/plugins/message-actions.js +10 -0
- package/dist/channels/telegram/api.js +18 -0
- package/dist/cli/argv.js +84 -21
- package/dist/cli/banner.js +2 -1
- package/dist/cli/exec-approvals-cli.js +92 -124
- package/dist/cli/memory-cli.js +158 -61
- package/dist/cli/nodes-cli/register.push.js +63 -0
- package/dist/cli/nodes-media-utils.js +21 -0
- package/dist/cli/plugins-cli.js +245 -61
- package/dist/cli/program/build-program.js +3 -1
- package/dist/cli/program/command-registry.js +223 -136
- package/dist/cli/program/help.js +43 -12
- package/dist/cli/route.js +1 -1
- package/dist/cli/test-runtime-capture.js +24 -0
- package/dist/commands/agent.js +163 -87
- package/dist/commands/channels.mock-harness.js +23 -0
- package/dist/commands/daemon-install-runtime-warning.js +11 -0
- package/dist/commands/onboard-helpers.js +4 -4
- package/dist/commands/sessions.test-helpers.js +61 -0
- package/dist/compat/legacy-names.js +2 -2
- package/dist/config/commands.js +3 -0
- package/dist/config/config.js +1 -1
- package/dist/config/env-substitution.js +62 -34
- package/dist/config/env-vars.js +9 -0
- package/dist/config/io.js +571 -171
- package/dist/config/merge-patch.js +50 -4
- package/dist/config/redact-snapshot.js +404 -76
- package/dist/config/schema.js +58 -570
- package/dist/config/validation.js +140 -85
- package/dist/config/zod-schema.hooks.js +40 -11
- package/dist/config/zod-schema.installs.js +20 -0
- package/dist/config/zod-schema.js +8 -7
- package/dist/control-ui/assets/{index-HRr1grwl.js → index-Dvkl4Xlx.js} +2 -1
- package/dist/control-ui/assets/{index-HRr1grwl.js.map → index-Dvkl4Xlx.js.map} +1 -1
- package/dist/control-ui/index.html +1 -1
- package/dist/daemon/cmd-argv.js +21 -0
- package/dist/daemon/cmd-set.js +58 -0
- package/dist/daemon/service-types.js +1 -0
- package/dist/discord/monitor/exec-approvals.js +357 -162
- package/dist/gateway/auth.js +38 -3
- package/dist/gateway/call.js +149 -68
- package/dist/gateway/canvas-capability.js +75 -0
- package/dist/gateway/control-plane-audit.js +28 -0
- package/dist/gateway/control-plane-rate-limit.js +53 -0
- package/dist/gateway/events.js +1 -0
- package/dist/gateway/hooks.js +109 -54
- package/dist/gateway/http-common.js +22 -0
- package/dist/gateway/method-scopes.js +169 -0
- package/dist/gateway/net.js +23 -0
- package/dist/gateway/openresponses-http.js +120 -110
- package/dist/gateway/probe-auth.js +2 -0
- package/dist/gateway/protocol/index.js +3 -2
- package/dist/gateway/protocol/schema/protocol-schemas.js +2 -0
- package/dist/gateway/protocol/schema/push.js +18 -0
- package/dist/gateway/protocol/schema.js +1 -0
- package/dist/gateway/server-http.js +236 -52
- package/dist/gateway/server-methods/agent.js +162 -24
- package/dist/gateway/server-methods/chat.js +461 -130
- package/dist/gateway/server-methods/config.js +193 -150
- package/dist/gateway/server-methods/nodes.helpers.js +12 -0
- package/dist/gateway/server-methods/nodes.js +251 -69
- package/dist/gateway/server-methods/push.js +53 -0
- package/dist/gateway/server-reload-handlers.js +2 -3
- package/dist/gateway/server-runtime-config.js +5 -0
- package/dist/gateway/server-runtime-state.js +2 -0
- package/dist/gateway/server-ws-runtime.js +1 -0
- package/dist/gateway/server.impl.js +296 -139
- package/dist/gateway/session-preview.test-helpers.js +11 -0
- package/dist/gateway/startup-auth.js +126 -0
- package/dist/gateway/test-helpers.agent-results.js +15 -0
- package/dist/gateway/test-helpers.mocks.js +37 -14
- package/dist/gateway/test-helpers.server.js +161 -77
- package/dist/hooks/bundled/session-memory/handler.js +165 -34
- package/dist/hooks/gmail-watcher-lifecycle.js +23 -0
- package/dist/infra/archive-path.js +49 -0
- package/dist/infra/device-pairing.js +148 -167
- package/dist/infra/exec-approvals-allowlist.js +19 -70
- package/dist/infra/exec-approvals-analysis.js +44 -17
- package/dist/infra/exec-safe-bin-policy.js +269 -0
- package/dist/infra/fixed-window-rate-limit.js +33 -0
- package/dist/infra/git-root.js +61 -0
- package/dist/infra/heartbeat-active-hours.js +2 -2
- package/dist/infra/heartbeat-reason.js +40 -0
- package/dist/infra/heartbeat-runner.js +72 -32
- package/dist/infra/install-source-utils.js +91 -7
- package/dist/infra/node-pairing.js +50 -105
- package/dist/infra/npm-integrity.js +45 -0
- package/dist/infra/npm-pack-install.js +40 -0
- package/dist/infra/outbound/channel-adapters.js +20 -7
- package/dist/infra/outbound/message-action-runner.js +107 -327
- package/dist/infra/outbound/message.js +59 -36
- package/dist/infra/outbound/outbound-policy.js +52 -25
- package/dist/infra/outbound/outbound-send-service.js +58 -71
- package/dist/infra/pairing-files.js +10 -0
- package/dist/infra/plain-object.js +9 -0
- package/dist/infra/push-apns.js +365 -0
- package/dist/infra/restart-sentinel.js +16 -1
- package/dist/infra/restart.js +229 -26
- package/dist/infra/scp-host.js +54 -0
- package/dist/infra/update-startup.js +86 -9
- package/dist/media/inbound-path-policy.js +114 -0
- package/dist/media/input-files.js +16 -0
- package/dist/memory/test-manager.js +8 -0
- package/dist/plugin-sdk/temp-path.js +47 -0
- package/dist/plugins/discovery.js +217 -23
- package/dist/plugins/hook-runner-global.js +16 -0
- package/dist/plugins/loader.js +192 -26
- package/dist/plugins/logger.js +8 -0
- package/dist/plugins/manifest-registry.js +3 -0
- package/dist/plugins/path-safety.js +34 -0
- package/dist/plugins/registry.js +5 -2
- package/dist/plugins/runtime/index.js +271 -206
- package/dist/providers/github-copilot-models.js +4 -1
- package/dist/security/audit-channel.js +8 -19
- package/dist/security/audit-extra.async.js +354 -182
- package/dist/security/audit-extra.js +11 -1
- package/dist/security/audit-extra.sync.js +340 -33
- package/dist/security/audit-fs.js +31 -13
- package/dist/security/audit.js +145 -371
- package/dist/security/dm-policy-shared.js +24 -0
- package/dist/security/external-content.js +20 -8
- package/dist/security/fix.js +49 -85
- package/dist/security/scan-paths.js +20 -0
- package/dist/security/secret-equal.js +3 -7
- package/dist/security/windows-acl.js +30 -15
- package/dist/shared/node-list-parse.js +13 -0
- package/dist/shared/operator-scope-compat.js +37 -0
- package/dist/shared/text-chunking.js +29 -0
- package/dist/slack/blocks.test-helpers.js +31 -0
- package/dist/slack/monitor/mrkdwn.js +8 -0
- package/dist/telegram/bot-message-dispatch.js +366 -164
- package/dist/telegram/draft-stream.js +30 -7
- package/dist/telegram/reasoning-lane-coordinator.js +128 -0
- package/dist/terminal/prompt-select-styled.js +9 -0
- package/dist/test-utils/command-runner.js +6 -0
- package/dist/test-utils/internal-hook-event-payload.js +10 -0
- package/dist/test-utils/model-auth-mock.js +12 -0
- package/dist/test-utils/provider-usage-fetch.js +14 -0
- package/dist/test-utils/temp-home.js +33 -0
- package/dist/tui/components/chat-log.js +9 -0
- package/dist/tui/tui-command-handlers.js +36 -27
- package/dist/tui/tui-event-handlers.js +122 -32
- package/dist/tui/tui.js +181 -45
- package/dist/utils/mask-api-key.js +10 -0
- package/dist/utils/run-with-concurrency.js +39 -0
- package/dist/web/media.js +4 -0
- package/docs/tools/slash-commands.md +5 -1
- package/extensions/bluebubbles/package.json +1 -1
- package/extensions/copilot-proxy/package.json +1 -1
- package/extensions/diagnostics-otel/package.json +1 -1
- package/extensions/discord/package.json +1 -1
- package/extensions/feishu/package.json +1 -1
- package/extensions/feishu/src/external-keys.ts +19 -0
- package/extensions/google-antigravity-auth/package.json +1 -1
- package/extensions/google-gemini-cli-auth/package.json +1 -1
- package/extensions/googlechat/package.json +1 -1
- package/extensions/imessage/package.json +1 -1
- package/extensions/irc/package.json +1 -1
- package/extensions/line/package.json +1 -1
- package/extensions/llm-task/package.json +1 -1
- package/extensions/lobster/package.json +1 -1
- package/extensions/lobster/src/windows-spawn.ts +193 -0
- package/extensions/matrix/CHANGELOG.md +5 -0
- package/extensions/matrix/package.json +1 -1
- package/extensions/matrix/src/matrix/actions/limits.ts +6 -0
- package/extensions/mattermost/package.json +1 -1
- package/extensions/mattermost/src/mattermost/reactions.test-helpers.ts +83 -0
- package/extensions/memory-core/package.json +1 -1
- package/extensions/memory-lancedb/package.json +1 -1
- package/extensions/minimax-portal-auth/package.json +1 -1
- package/extensions/msteams/CHANGELOG.md +5 -0
- package/extensions/msteams/package.json +1 -1
- package/extensions/nextcloud-talk/package.json +1 -1
- package/extensions/nostr/CHANGELOG.md +5 -0
- package/extensions/nostr/package.json +1 -1
- package/extensions/open-prose/package.json +1 -1
- package/extensions/openai-codex-auth/package.json +1 -1
- package/extensions/signal/package.json +1 -1
- package/extensions/slack/package.json +1 -1
- package/extensions/telegram/package.json +1 -1
- package/extensions/tlon/package.json +1 -1
- package/extensions/twitch/CHANGELOG.md +5 -0
- package/extensions/twitch/package.json +1 -1
- package/extensions/voice-call/CHANGELOG.md +5 -0
- package/extensions/voice-call/package.json +1 -1
- package/extensions/whatsapp/package.json +1 -1
- package/extensions/zalo/CHANGELOG.md +5 -0
- package/extensions/zalo/package.json +1 -1
- package/extensions/zalouser/CHANGELOG.md +5 -0
- package/extensions/zalouser/package.json +1 -1
- package/package.json +1 -1
package/dist/commands/agent.js
CHANGED
|
@@ -1,38 +1,122 @@
|
|
|
1
|
-
import { listAgentIds, resolveAgentDir,
|
|
1
|
+
import { listAgentIds, resolveAgentDir, resolveEffectiveModelFallbacks, resolveAgentModelPrimary, resolveAgentSkillsFilter, resolveAgentWorkspaceDir, } from "../agents/agent-scope.js";
|
|
2
2
|
import { ensureAuthProfileStore } from "../agents/auth-profiles.js";
|
|
3
|
+
import { clearSessionAuthProfileOverride } from "../agents/auth-profiles/session-override.js";
|
|
3
4
|
import { runCliAgent } from "../agents/cli-runner.js";
|
|
4
5
|
import { getCliSessionId } from "../agents/cli-session.js";
|
|
5
6
|
import { DEFAULT_MODEL, DEFAULT_PROVIDER } from "../agents/defaults.js";
|
|
7
|
+
import { AGENT_LANE_SUBAGENT } from "../agents/lanes.js";
|
|
6
8
|
import { loadModelCatalog } from "../agents/model-catalog.js";
|
|
7
9
|
import { runWithModelFallback } from "../agents/model-fallback.js";
|
|
8
|
-
import { buildAllowedModelSet, isCliProvider, modelKey, resolveConfiguredModelRef, resolveThinkingDefault, } from "../agents/model-selection.js";
|
|
10
|
+
import { buildAllowedModelSet, isCliProvider, modelKey, normalizeModelRef, resolveConfiguredModelRef, resolveThinkingDefault, } from "../agents/model-selection.js";
|
|
9
11
|
import { runEmbeddedPiAgent } from "../agents/pi-embedded.js";
|
|
10
12
|
import { buildWorkspaceSkillSnapshot } from "../agents/skills.js";
|
|
11
13
|
import { getSkillsSnapshotVersion } from "../agents/skills/refresh.js";
|
|
12
14
|
import { resolveAgentTimeoutMs } from "../agents/timeout.js";
|
|
13
15
|
import { ensureAgentWorkspace } from "../agents/workspace.js";
|
|
14
16
|
import { formatThinkingLevels, formatXHighModelHint, normalizeThinkLevel, normalizeVerboseLevel, supportsXHighThinking, } from "../auto-reply/thinking.js";
|
|
17
|
+
import { formatCliCommand } from "../cli/command-format.js";
|
|
15
18
|
import { createDefaultDeps } from "../cli/deps.js";
|
|
16
19
|
import { loadConfig } from "../config/config.js";
|
|
17
20
|
import { resolveAgentIdFromSessionKey, resolveSessionFilePath, updateSessionStore, } from "../config/sessions.js";
|
|
18
21
|
import { clearAgentRunContext, emitAgentEvent, registerAgentRunContext, } from "../infra/agent-events.js";
|
|
19
22
|
import { getRemoteSkillEligibility } from "../infra/skills-remote.js";
|
|
23
|
+
import { normalizeAgentId } from "../routing/session-key.js";
|
|
20
24
|
import { defaultRuntime } from "../runtime.js";
|
|
21
|
-
import { formatCliCommand } from "../cli/command-format.js";
|
|
22
25
|
import { applyVerboseOverride } from "../sessions/level-overrides.js";
|
|
23
|
-
import { resolveSendPolicy } from "../sessions/send-policy.js";
|
|
24
26
|
import { applyModelOverrideToSessionEntry } from "../sessions/model-overrides.js";
|
|
25
|
-
import {
|
|
27
|
+
import { resolveSendPolicy } from "../sessions/send-policy.js";
|
|
26
28
|
import { resolveMessageChannel } from "../utils/message-channel.js";
|
|
27
29
|
import { deliverAgentCommandResult } from "./agent/delivery.js";
|
|
28
30
|
import { resolveAgentRunContext } from "./agent/run-context.js";
|
|
29
|
-
import { resolveSession } from "./agent/session.js";
|
|
30
31
|
import { updateSessionStoreAfterAgentRun } from "./agent/session-store.js";
|
|
31
|
-
import {
|
|
32
|
+
import { resolveSession } from "./agent/session.js";
|
|
33
|
+
async function persistSessionEntry(params) {
|
|
34
|
+
params.sessionStore[params.sessionKey] = params.entry;
|
|
35
|
+
await updateSessionStore(params.storePath, (store) => {
|
|
36
|
+
store[params.sessionKey] = params.entry;
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
function resolveFallbackRetryPrompt(params) {
|
|
40
|
+
if (!params.isFallbackRetry) {
|
|
41
|
+
return params.body;
|
|
42
|
+
}
|
|
43
|
+
return "Continue where you left off. The previous model attempt failed or timed out.";
|
|
44
|
+
}
|
|
45
|
+
function runAgentAttempt(params) {
|
|
46
|
+
const effectivePrompt = resolveFallbackRetryPrompt({
|
|
47
|
+
body: params.body,
|
|
48
|
+
isFallbackRetry: params.isFallbackRetry,
|
|
49
|
+
});
|
|
50
|
+
if (isCliProvider(params.providerOverride, params.cfg)) {
|
|
51
|
+
const cliSessionId = getCliSessionId(params.sessionEntry, params.providerOverride);
|
|
52
|
+
return runCliAgent({
|
|
53
|
+
sessionId: params.sessionId,
|
|
54
|
+
sessionKey: params.sessionKey,
|
|
55
|
+
agentId: params.sessionAgentId,
|
|
56
|
+
sessionFile: params.sessionFile,
|
|
57
|
+
workspaceDir: params.workspaceDir,
|
|
58
|
+
config: params.cfg,
|
|
59
|
+
prompt: effectivePrompt,
|
|
60
|
+
provider: params.providerOverride,
|
|
61
|
+
model: params.modelOverride,
|
|
62
|
+
thinkLevel: params.resolvedThinkLevel,
|
|
63
|
+
timeoutMs: params.timeoutMs,
|
|
64
|
+
runId: params.runId,
|
|
65
|
+
extraSystemPrompt: params.opts.extraSystemPrompt,
|
|
66
|
+
cliSessionId,
|
|
67
|
+
images: params.isFallbackRetry ? undefined : params.opts.images,
|
|
68
|
+
streamParams: params.opts.streamParams,
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
const authProfileId = params.providerOverride === params.primaryProvider
|
|
72
|
+
? params.sessionEntry?.authProfileOverride
|
|
73
|
+
: undefined;
|
|
74
|
+
return runEmbeddedPiAgent({
|
|
75
|
+
sessionId: params.sessionId,
|
|
76
|
+
sessionKey: params.sessionKey,
|
|
77
|
+
agentId: params.sessionAgentId,
|
|
78
|
+
messageChannel: params.messageChannel,
|
|
79
|
+
agentAccountId: params.runContext.accountId,
|
|
80
|
+
messageTo: params.opts.replyTo ?? params.opts.to,
|
|
81
|
+
messageThreadId: params.opts.threadId,
|
|
82
|
+
groupId: params.runContext.groupId,
|
|
83
|
+
groupChannel: params.runContext.groupChannel,
|
|
84
|
+
groupSpace: params.runContext.groupSpace,
|
|
85
|
+
spawnedBy: params.spawnedBy,
|
|
86
|
+
currentChannelId: params.runContext.currentChannelId,
|
|
87
|
+
currentThreadTs: params.runContext.currentThreadTs,
|
|
88
|
+
replyToMode: params.runContext.replyToMode,
|
|
89
|
+
hasRepliedRef: params.runContext.hasRepliedRef,
|
|
90
|
+
senderIsOwner: true,
|
|
91
|
+
sessionFile: params.sessionFile,
|
|
92
|
+
workspaceDir: params.workspaceDir,
|
|
93
|
+
config: params.cfg,
|
|
94
|
+
skillsSnapshot: params.skillsSnapshot,
|
|
95
|
+
prompt: effectivePrompt,
|
|
96
|
+
images: params.isFallbackRetry ? undefined : params.opts.images,
|
|
97
|
+
clientTools: params.opts.clientTools,
|
|
98
|
+
provider: params.providerOverride,
|
|
99
|
+
model: params.modelOverride,
|
|
100
|
+
authProfileId,
|
|
101
|
+
authProfileIdSource: authProfileId ? params.sessionEntry?.authProfileOverrideSource : undefined,
|
|
102
|
+
thinkLevel: params.resolvedThinkLevel,
|
|
103
|
+
verboseLevel: params.resolvedVerboseLevel,
|
|
104
|
+
timeoutMs: params.timeoutMs,
|
|
105
|
+
runId: params.runId,
|
|
106
|
+
lane: params.opts.lane,
|
|
107
|
+
abortSignal: params.opts.abortSignal,
|
|
108
|
+
extraSystemPrompt: params.opts.extraSystemPrompt,
|
|
109
|
+
inputProvenance: params.opts.inputProvenance,
|
|
110
|
+
streamParams: params.opts.streamParams,
|
|
111
|
+
agentDir: params.agentDir,
|
|
112
|
+
onAgentEvent: params.onAgentEvent,
|
|
113
|
+
});
|
|
114
|
+
}
|
|
32
115
|
export async function agentCommand(opts, runtime = defaultRuntime, deps = createDefaultDeps()) {
|
|
33
116
|
const body = (opts.message ?? "").trim();
|
|
34
|
-
if (!body)
|
|
117
|
+
if (!body) {
|
|
35
118
|
throw new Error("Message (--message) is required");
|
|
119
|
+
}
|
|
36
120
|
if (!opts.to && !opts.sessionId && !opts.sessionKey && !opts.agentId) {
|
|
37
121
|
throw new Error("Pass --to <E.164>, --session-id, or --agent to choose a session");
|
|
38
122
|
}
|
|
@@ -78,10 +162,16 @@ export async function agentCommand(opts, runtime = defaultRuntime, deps = create
|
|
|
78
162
|
if (opts.verbose && !verboseOverride) {
|
|
79
163
|
throw new Error('Invalid verbose level. Use "on", "full", or "off".');
|
|
80
164
|
}
|
|
81
|
-
const
|
|
165
|
+
const laneRaw = typeof opts.lane === "string" ? opts.lane.trim() : "";
|
|
166
|
+
const isSubagentLane = laneRaw === String(AGENT_LANE_SUBAGENT);
|
|
167
|
+
const timeoutSecondsRaw = opts.timeout !== undefined
|
|
168
|
+
? Number.parseInt(String(opts.timeout), 10)
|
|
169
|
+
: isSubagentLane
|
|
170
|
+
? 0
|
|
171
|
+
: undefined;
|
|
82
172
|
if (timeoutSecondsRaw !== undefined &&
|
|
83
|
-
(Number.isNaN(timeoutSecondsRaw) || timeoutSecondsRaw
|
|
84
|
-
throw new Error("--timeout must be a
|
|
173
|
+
(Number.isNaN(timeoutSecondsRaw) || timeoutSecondsRaw < 0)) {
|
|
174
|
+
throw new Error("--timeout must be a non-negative integer (seconds; 0 means no timeout)");
|
|
85
175
|
}
|
|
86
176
|
const timeoutMs = resolveAgentTimeoutMs({
|
|
87
177
|
cfg,
|
|
@@ -123,11 +213,13 @@ export async function agentCommand(opts, runtime = defaultRuntime, deps = create
|
|
|
123
213
|
}
|
|
124
214
|
const needsSkillsSnapshot = isNewSession || !sessionEntry?.skillsSnapshot;
|
|
125
215
|
const skillsSnapshotVersion = getSkillsSnapshotVersion(workspaceDir);
|
|
216
|
+
const skillFilter = resolveAgentSkillsFilter(cfg, sessionAgentId);
|
|
126
217
|
const skillsSnapshot = needsSkillsSnapshot
|
|
127
218
|
? buildWorkspaceSkillSnapshot(workspaceDir, {
|
|
128
219
|
config: cfg,
|
|
129
220
|
eligibility: { remote: getRemoteSkillEligibility() },
|
|
130
221
|
snapshotVersion: skillsSnapshotVersion,
|
|
222
|
+
skillFilter,
|
|
131
223
|
})
|
|
132
224
|
: sessionEntry?.skillsSnapshot;
|
|
133
225
|
if (skillsSnapshot && sessionStore && sessionKey && needsSkillsSnapshot) {
|
|
@@ -141,9 +233,11 @@ export async function agentCommand(opts, runtime = defaultRuntime, deps = create
|
|
|
141
233
|
updatedAt: Date.now(),
|
|
142
234
|
skillsSnapshot,
|
|
143
235
|
};
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
236
|
+
await persistSessionEntry({
|
|
237
|
+
sessionStore,
|
|
238
|
+
sessionKey,
|
|
239
|
+
storePath,
|
|
240
|
+
entry: next,
|
|
147
241
|
});
|
|
148
242
|
sessionEntry = next;
|
|
149
243
|
}
|
|
@@ -153,15 +247,14 @@ export async function agentCommand(opts, runtime = defaultRuntime, deps = create
|
|
|
153
247
|
sessionEntry ?? { sessionId, updatedAt: Date.now() };
|
|
154
248
|
const next = { ...entry, sessionId, updatedAt: Date.now() };
|
|
155
249
|
if (thinkOverride) {
|
|
156
|
-
|
|
157
|
-
delete next.thinkingLevel;
|
|
158
|
-
else
|
|
159
|
-
next.thinkingLevel = thinkOverride;
|
|
250
|
+
next.thinkingLevel = thinkOverride;
|
|
160
251
|
}
|
|
161
252
|
applyVerboseOverride(next, verboseOverride);
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
253
|
+
await persistSessionEntry({
|
|
254
|
+
sessionStore,
|
|
255
|
+
sessionKey,
|
|
256
|
+
storePath,
|
|
257
|
+
entry: next,
|
|
165
258
|
});
|
|
166
259
|
}
|
|
167
260
|
const agentModelPrimary = resolveAgentModelPrimary(cfg, sessionAgentId);
|
|
@@ -182,11 +275,12 @@ export async function agentCommand(opts, runtime = defaultRuntime, deps = create
|
|
|
182
275
|
},
|
|
183
276
|
}
|
|
184
277
|
: cfg;
|
|
185
|
-
const
|
|
278
|
+
const configuredDefaultRef = resolveConfiguredModelRef({
|
|
186
279
|
cfg: cfgForModelSelection,
|
|
187
280
|
defaultProvider: DEFAULT_PROVIDER,
|
|
188
281
|
defaultModel: DEFAULT_MODEL,
|
|
189
282
|
});
|
|
283
|
+
const { provider: defaultProvider, model: defaultModel } = normalizeModelRef(configuredDefaultRef.provider, configuredDefaultRef.model);
|
|
190
284
|
let provider = defaultProvider;
|
|
191
285
|
let model = defaultModel;
|
|
192
286
|
const hasAllowlist = agentCfg?.models && Object.keys(agentCfg.models).length > 0;
|
|
@@ -211,8 +305,9 @@ export async function agentCommand(opts, runtime = defaultRuntime, deps = create
|
|
|
211
305
|
const overrideProvider = sessionEntry.providerOverride?.trim() || defaultProvider;
|
|
212
306
|
const overrideModel = sessionEntry.modelOverride?.trim();
|
|
213
307
|
if (overrideModel) {
|
|
214
|
-
const
|
|
215
|
-
|
|
308
|
+
const normalizedOverride = normalizeModelRef(overrideProvider, overrideModel);
|
|
309
|
+
const key = modelKey(normalizedOverride.provider, normalizedOverride.model);
|
|
310
|
+
if (!isCliProvider(normalizedOverride.provider, cfg) &&
|
|
216
311
|
allowedModelKeys.size > 0 &&
|
|
217
312
|
!allowedModelKeys.has(key)) {
|
|
218
313
|
const { updated } = applyModelOverrideToSessionEntry({
|
|
@@ -220,9 +315,11 @@ export async function agentCommand(opts, runtime = defaultRuntime, deps = create
|
|
|
220
315
|
selection: { provider: defaultProvider, model: defaultModel, isDefault: true },
|
|
221
316
|
});
|
|
222
317
|
if (updated) {
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
318
|
+
await persistSessionEntry({
|
|
319
|
+
sessionStore,
|
|
320
|
+
sessionKey,
|
|
321
|
+
storePath,
|
|
322
|
+
entry,
|
|
226
323
|
});
|
|
227
324
|
}
|
|
228
325
|
}
|
|
@@ -232,12 +329,13 @@ export async function agentCommand(opts, runtime = defaultRuntime, deps = create
|
|
|
232
329
|
const storedModelOverride = sessionEntry?.modelOverride?.trim();
|
|
233
330
|
if (storedModelOverride) {
|
|
234
331
|
const candidateProvider = storedProviderOverride || defaultProvider;
|
|
235
|
-
const
|
|
236
|
-
|
|
332
|
+
const normalizedStored = normalizeModelRef(candidateProvider, storedModelOverride);
|
|
333
|
+
const key = modelKey(normalizedStored.provider, normalizedStored.model);
|
|
334
|
+
if (isCliProvider(normalizedStored.provider, cfg) ||
|
|
237
335
|
allowedModelKeys.size === 0 ||
|
|
238
336
|
allowedModelKeys.has(key)) {
|
|
239
|
-
provider =
|
|
240
|
-
model =
|
|
337
|
+
provider = normalizedStored.provider;
|
|
338
|
+
model = normalizedStored.model;
|
|
241
339
|
}
|
|
242
340
|
}
|
|
243
341
|
if (sessionEntry) {
|
|
@@ -281,9 +379,11 @@ export async function agentCommand(opts, runtime = defaultRuntime, deps = create
|
|
|
281
379
|
const entry = sessionEntry;
|
|
282
380
|
entry.thinkingLevel = "high";
|
|
283
381
|
entry.updatedAt = Date.now();
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
382
|
+
await persistSessionEntry({
|
|
383
|
+
sessionStore,
|
|
384
|
+
sessionKey,
|
|
385
|
+
storePath,
|
|
386
|
+
entry,
|
|
287
387
|
});
|
|
288
388
|
}
|
|
289
389
|
}
|
|
@@ -299,72 +399,48 @@ export async function agentCommand(opts, runtime = defaultRuntime, deps = create
|
|
|
299
399
|
const runContext = resolveAgentRunContext(opts);
|
|
300
400
|
const messageChannel = resolveMessageChannel(runContext.messageChannel, opts.replyChannel ?? opts.channel);
|
|
301
401
|
const spawnedBy = opts.spawnedBy ?? sessionEntry?.spawnedBy;
|
|
402
|
+
// Keep fallback candidate resolution centralized so session model overrides,
|
|
403
|
+
// per-agent overrides, and default fallbacks stay consistent across callers.
|
|
404
|
+
const effectiveFallbacksOverride = resolveEffectiveModelFallbacks({
|
|
405
|
+
cfg,
|
|
406
|
+
agentId: sessionAgentId,
|
|
407
|
+
hasSessionModelOverride: Boolean(storedModelOverride),
|
|
408
|
+
});
|
|
409
|
+
// Track model fallback attempts so retries on an existing session don't
|
|
410
|
+
// re-inject the original prompt as a duplicate user message.
|
|
411
|
+
let fallbackAttemptIndex = 0;
|
|
302
412
|
const fallbackResult = await runWithModelFallback({
|
|
303
413
|
cfg,
|
|
304
414
|
provider,
|
|
305
415
|
model,
|
|
306
416
|
agentDir,
|
|
307
|
-
fallbacksOverride:
|
|
417
|
+
fallbacksOverride: effectiveFallbacksOverride,
|
|
308
418
|
run: (providerOverride, modelOverride) => {
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
config: cfg,
|
|
317
|
-
prompt: body,
|
|
318
|
-
provider: providerOverride,
|
|
319
|
-
model: modelOverride,
|
|
320
|
-
thinkLevel: resolvedThinkLevel,
|
|
321
|
-
timeoutMs,
|
|
322
|
-
runId,
|
|
323
|
-
extraSystemPrompt: opts.extraSystemPrompt,
|
|
324
|
-
cliSessionId,
|
|
325
|
-
images: opts.images,
|
|
326
|
-
streamParams: opts.streamParams,
|
|
327
|
-
});
|
|
328
|
-
}
|
|
329
|
-
const authProfileId = providerOverride === provider ? sessionEntry?.authProfileOverride : undefined;
|
|
330
|
-
return runEmbeddedPiAgent({
|
|
419
|
+
const isFallbackRetry = fallbackAttemptIndex > 0;
|
|
420
|
+
fallbackAttemptIndex += 1;
|
|
421
|
+
return runAgentAttempt({
|
|
422
|
+
providerOverride,
|
|
423
|
+
modelOverride,
|
|
424
|
+
cfg,
|
|
425
|
+
sessionEntry,
|
|
331
426
|
sessionId,
|
|
332
427
|
sessionKey,
|
|
333
|
-
|
|
334
|
-
agentAccountId: runContext.accountId,
|
|
335
|
-
messageTo: opts.replyTo ?? opts.to,
|
|
336
|
-
messageThreadId: opts.threadId,
|
|
337
|
-
groupId: runContext.groupId,
|
|
338
|
-
groupChannel: runContext.groupChannel,
|
|
339
|
-
groupSpace: runContext.groupSpace,
|
|
340
|
-
spawnedBy,
|
|
341
|
-
currentChannelId: runContext.currentChannelId,
|
|
342
|
-
currentThreadTs: runContext.currentThreadTs,
|
|
343
|
-
replyToMode: runContext.replyToMode,
|
|
344
|
-
hasRepliedRef: runContext.hasRepliedRef,
|
|
345
|
-
senderIsOwner: true,
|
|
428
|
+
sessionAgentId,
|
|
346
429
|
sessionFile,
|
|
347
430
|
workspaceDir,
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
images: opts.images,
|
|
352
|
-
clientTools: opts.clientTools,
|
|
353
|
-
provider: providerOverride,
|
|
354
|
-
model: modelOverride,
|
|
355
|
-
authProfileId,
|
|
356
|
-
authProfileIdSource: authProfileId
|
|
357
|
-
? sessionEntry?.authProfileOverrideSource
|
|
358
|
-
: undefined,
|
|
359
|
-
thinkLevel: resolvedThinkLevel,
|
|
360
|
-
verboseLevel: resolvedVerboseLevel,
|
|
431
|
+
body,
|
|
432
|
+
isFallbackRetry,
|
|
433
|
+
resolvedThinkLevel,
|
|
361
434
|
timeoutMs,
|
|
362
435
|
runId,
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
436
|
+
opts,
|
|
437
|
+
runContext,
|
|
438
|
+
spawnedBy,
|
|
439
|
+
messageChannel,
|
|
440
|
+
skillsSnapshot,
|
|
441
|
+
resolvedVerboseLevel,
|
|
367
442
|
agentDir,
|
|
443
|
+
primaryProvider: provider,
|
|
368
444
|
onAgentEvent: (evt) => {
|
|
369
445
|
// Track lifecycle end for fallback emission below.
|
|
370
446
|
if (evt.stream === "lifecycle" &&
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { vi } from "vitest";
|
|
2
|
+
export const configMocks = {
|
|
3
|
+
readConfigFileSnapshot: vi.fn(),
|
|
4
|
+
writeConfigFile: vi.fn().mockResolvedValue(undefined),
|
|
5
|
+
};
|
|
6
|
+
export const offsetMocks = {
|
|
7
|
+
deleteTelegramUpdateOffset: vi.fn().mockResolvedValue(undefined),
|
|
8
|
+
};
|
|
9
|
+
vi.mock("../config/config.js", async (importOriginal) => {
|
|
10
|
+
const actual = await importOriginal();
|
|
11
|
+
return {
|
|
12
|
+
...actual,
|
|
13
|
+
readConfigFileSnapshot: configMocks.readConfigFileSnapshot,
|
|
14
|
+
writeConfigFile: configMocks.writeConfigFile,
|
|
15
|
+
};
|
|
16
|
+
});
|
|
17
|
+
vi.mock("../telegram/update-offset-store.js", async (importOriginal) => {
|
|
18
|
+
const actual = await importOriginal();
|
|
19
|
+
return {
|
|
20
|
+
...actual,
|
|
21
|
+
deleteTelegramUpdateOffset: offsetMocks.deleteTelegramUpdateOffset,
|
|
22
|
+
};
|
|
23
|
+
});
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { renderSystemNodeWarning, resolveSystemNodeInfo } from "../daemon/runtime-paths.js";
|
|
2
|
+
export async function emitNodeRuntimeWarning(params) {
|
|
3
|
+
if (params.runtime !== "node") {
|
|
4
|
+
return;
|
|
5
|
+
}
|
|
6
|
+
const systemNode = await resolveSystemNodeInfo({ env: params.env });
|
|
7
|
+
const warning = renderSystemNodeWarning(systemNode, params.nodeProgram);
|
|
8
|
+
if (warning) {
|
|
9
|
+
params.warn?.(warning, params.title);
|
|
10
|
+
}
|
|
11
|
+
}
|
|
@@ -85,11 +85,11 @@ export function validateGatewayPasswordInput(value) {
|
|
|
85
85
|
export function printWizardHeader(runtime) {
|
|
86
86
|
const header = [
|
|
87
87
|
"▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄",
|
|
88
|
-
"
|
|
89
|
-
"
|
|
90
|
-
"
|
|
88
|
+
"██░▄▄░███░▄▄▄░██░▄▄▄░██░██████░▄▄▀░██░▄▄▄░██▀▀░▀▀███",
|
|
89
|
+
"██░▀▀░███░███░██░███░██░██████░██▄░██░███░████░█████",
|
|
90
|
+
"██░██████░▀▀▀░██░▀▀▀░██░▀▀▀░██░▀▀▀░██░▀▀▀░████░█████",
|
|
91
91
|
"▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀",
|
|
92
|
-
"
|
|
92
|
+
" 🎱 POOL BOT 🎱 ",
|
|
93
93
|
" ",
|
|
94
94
|
].join("\n");
|
|
95
95
|
runtime.log(header);
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
import os from "node:os";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import { vi } from "vitest";
|
|
5
|
+
export function mockSessionsConfig() {
|
|
6
|
+
vi.mock("../config/config.js", async (importOriginal) => {
|
|
7
|
+
const actual = await importOriginal();
|
|
8
|
+
return {
|
|
9
|
+
...actual,
|
|
10
|
+
loadConfig: () => ({
|
|
11
|
+
agents: {
|
|
12
|
+
defaults: {
|
|
13
|
+
model: { primary: "pi:opus" },
|
|
14
|
+
models: { "pi:opus": {} },
|
|
15
|
+
contextTokens: 32000,
|
|
16
|
+
},
|
|
17
|
+
},
|
|
18
|
+
}),
|
|
19
|
+
};
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
export function makeRuntime(params) {
|
|
23
|
+
const logs = [];
|
|
24
|
+
const errors = [];
|
|
25
|
+
const throwOnError = params?.throwOnError ?? false;
|
|
26
|
+
return {
|
|
27
|
+
runtime: {
|
|
28
|
+
log: (msg) => logs.push(String(msg)),
|
|
29
|
+
error: (msg) => {
|
|
30
|
+
errors.push(String(msg));
|
|
31
|
+
if (throwOnError) {
|
|
32
|
+
throw new Error(String(msg));
|
|
33
|
+
}
|
|
34
|
+
},
|
|
35
|
+
exit: (code) => {
|
|
36
|
+
throw new Error(`exit ${code}`);
|
|
37
|
+
},
|
|
38
|
+
},
|
|
39
|
+
logs,
|
|
40
|
+
errors,
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
export function writeStore(data, prefix = "sessions") {
|
|
44
|
+
const file = path.join(os.tmpdir(), `${prefix}-${Date.now()}-${Math.random().toString(16).slice(2)}.json`);
|
|
45
|
+
fs.writeFileSync(file, JSON.stringify(data, null, 2));
|
|
46
|
+
return file;
|
|
47
|
+
}
|
|
48
|
+
export async function runSessionsJson(run, store, options) {
|
|
49
|
+
const { runtime, logs } = makeRuntime();
|
|
50
|
+
try {
|
|
51
|
+
await run({
|
|
52
|
+
store,
|
|
53
|
+
json: true,
|
|
54
|
+
active: options?.active,
|
|
55
|
+
}, runtime);
|
|
56
|
+
}
|
|
57
|
+
finally {
|
|
58
|
+
fs.rmSync(store, { force: true });
|
|
59
|
+
}
|
|
60
|
+
return JSON.parse(logs[0] ?? "{}");
|
|
61
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
export const LEGACY_PROJECT_NAME = "
|
|
1
|
+
export const LEGACY_PROJECT_NAME = "clawdbot";
|
|
2
2
|
export const LEGACY_MANIFEST_KEY = LEGACY_PROJECT_NAME;
|
|
3
|
-
export const MANIFEST_KEY =
|
|
3
|
+
export const MANIFEST_KEY = "poolbot";
|
|
4
4
|
export const LEGACY_MANIFEST_KEYS = [LEGACY_MANIFEST_KEY];
|
|
5
5
|
export const LEGACY_PLUGIN_MANIFEST_FILENAME = `${LEGACY_PROJECT_NAME}.plugin.json`;
|
|
6
6
|
export const LEGACY_CANVAS_HANDLER_NAME = `${LEGACY_PROJECT_NAME}CanvasA2UIAction`;
|
package/dist/config/commands.js
CHANGED
package/dist/config/config.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { createConfigIO, loadConfig, parseConfigJson5, readConfigFileSnapshot, resolveConfigSnapshotHash, writeConfigFile, } from "./io.js";
|
|
1
|
+
export { createConfigIO, loadConfig, parseConfigJson5, readConfigFileSnapshot, readConfigFileSnapshotForWrite, resolveConfigSnapshotHash, writeConfigFile, } from "./io.js";
|
|
2
2
|
export { migrateLegacyConfig } from "./legacy-migrate.js";
|
|
3
3
|
export * from "./paths.js";
|
|
4
4
|
export * from "./runtime-overrides.js";
|
|
@@ -21,6 +21,7 @@
|
|
|
21
21
|
*/
|
|
22
22
|
// Pattern for valid uppercase env var names: starts with letter or underscore,
|
|
23
23
|
// followed by letters, numbers, or underscores (all uppercase)
|
|
24
|
+
import { isPlainObject } from "../utils.js";
|
|
24
25
|
const ENV_VAR_NAME_PATTERN = /^[A-Z_][A-Z0-9_]*$/;
|
|
25
26
|
export class MissingEnvVarError extends Error {
|
|
26
27
|
varName;
|
|
@@ -32,11 +33,35 @@ export class MissingEnvVarError extends Error {
|
|
|
32
33
|
this.name = "MissingEnvVarError";
|
|
33
34
|
}
|
|
34
35
|
}
|
|
35
|
-
function
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
36
|
+
function parseEnvTokenAt(value, index) {
|
|
37
|
+
if (value[index] !== "$") {
|
|
38
|
+
return null;
|
|
39
|
+
}
|
|
40
|
+
const next = value[index + 1];
|
|
41
|
+
const afterNext = value[index + 2];
|
|
42
|
+
// Escaped: $${VAR} -> ${VAR}
|
|
43
|
+
if (next === "$" && afterNext === "{") {
|
|
44
|
+
const start = index + 3;
|
|
45
|
+
const end = value.indexOf("}", start);
|
|
46
|
+
if (end !== -1) {
|
|
47
|
+
const name = value.slice(start, end);
|
|
48
|
+
if (ENV_VAR_NAME_PATTERN.test(name)) {
|
|
49
|
+
return { kind: "escaped", name, end };
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
// Substitution: ${VAR} -> value
|
|
54
|
+
if (next === "{") {
|
|
55
|
+
const start = index + 2;
|
|
56
|
+
const end = value.indexOf("}", start);
|
|
57
|
+
if (end !== -1) {
|
|
58
|
+
const name = value.slice(start, end);
|
|
59
|
+
if (ENV_VAR_NAME_PATTERN.test(name)) {
|
|
60
|
+
return { kind: "substitution", name, end };
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
return null;
|
|
40
65
|
}
|
|
41
66
|
function substituteString(value, env, configPath) {
|
|
42
67
|
if (!value.includes("$")) {
|
|
@@ -49,43 +74,46 @@ function substituteString(value, env, configPath) {
|
|
|
49
74
|
chunks.push(char);
|
|
50
75
|
continue;
|
|
51
76
|
}
|
|
52
|
-
const
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
const end = value.indexOf("}", start);
|
|
58
|
-
if (end !== -1) {
|
|
59
|
-
const name = value.slice(start, end);
|
|
60
|
-
if (ENV_VAR_NAME_PATTERN.test(name)) {
|
|
61
|
-
chunks.push(`\${${name}}`);
|
|
62
|
-
i = end;
|
|
63
|
-
continue;
|
|
64
|
-
}
|
|
65
|
-
}
|
|
77
|
+
const token = parseEnvTokenAt(value, i);
|
|
78
|
+
if (token?.kind === "escaped") {
|
|
79
|
+
chunks.push(`\${${token.name}}`);
|
|
80
|
+
i = token.end;
|
|
81
|
+
continue;
|
|
66
82
|
}
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
if (end !== -1) {
|
|
72
|
-
const name = value.slice(start, end);
|
|
73
|
-
if (ENV_VAR_NAME_PATTERN.test(name)) {
|
|
74
|
-
const envValue = env[name];
|
|
75
|
-
if (envValue === undefined || envValue === "") {
|
|
76
|
-
throw new MissingEnvVarError(name, configPath);
|
|
77
|
-
}
|
|
78
|
-
chunks.push(envValue);
|
|
79
|
-
i = end;
|
|
80
|
-
continue;
|
|
81
|
-
}
|
|
83
|
+
if (token?.kind === "substitution") {
|
|
84
|
+
const envValue = env[token.name];
|
|
85
|
+
if (envValue === undefined || envValue === "") {
|
|
86
|
+
throw new MissingEnvVarError(token.name, configPath);
|
|
82
87
|
}
|
|
88
|
+
chunks.push(envValue);
|
|
89
|
+
i = token.end;
|
|
90
|
+
continue;
|
|
83
91
|
}
|
|
84
92
|
// Leave untouched if not a recognized pattern
|
|
85
93
|
chunks.push(char);
|
|
86
94
|
}
|
|
87
95
|
return chunks.join("");
|
|
88
96
|
}
|
|
97
|
+
export function containsEnvVarReference(value) {
|
|
98
|
+
if (!value.includes("$")) {
|
|
99
|
+
return false;
|
|
100
|
+
}
|
|
101
|
+
for (let i = 0; i < value.length; i += 1) {
|
|
102
|
+
const char = value[i];
|
|
103
|
+
if (char !== "$") {
|
|
104
|
+
continue;
|
|
105
|
+
}
|
|
106
|
+
const token = parseEnvTokenAt(value, i);
|
|
107
|
+
if (token?.kind === "escaped") {
|
|
108
|
+
i = token.end;
|
|
109
|
+
continue;
|
|
110
|
+
}
|
|
111
|
+
if (token?.kind === "substitution") {
|
|
112
|
+
return true;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
return false;
|
|
116
|
+
}
|
|
89
117
|
function substituteAny(value, env, path) {
|
|
90
118
|
if (typeof value === "string") {
|
|
91
119
|
return substituteString(value, env, path);
|
package/dist/config/env-vars.js
CHANGED
|
@@ -19,3 +19,12 @@ export function collectConfigEnvVars(cfg) {
|
|
|
19
19
|
}
|
|
20
20
|
return entries;
|
|
21
21
|
}
|
|
22
|
+
export function applyConfigEnvVars(cfg, env = process.env) {
|
|
23
|
+
const entries = collectConfigEnvVars(cfg);
|
|
24
|
+
for (const [key, value] of Object.entries(entries)) {
|
|
25
|
+
if (env[key]?.trim()) {
|
|
26
|
+
continue;
|
|
27
|
+
}
|
|
28
|
+
env[key] = value;
|
|
29
|
+
}
|
|
30
|
+
}
|