@poolzin/pool-bot 2026.2.0 → 2026.2.2
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 +118 -0
- package/README-header.png +0 -0
- package/dist/agents/bash-tools.exec.js +76 -25
- package/dist/agents/cli-runner/helpers.js +9 -11
- package/dist/agents/context.js +1 -1
- package/dist/agents/identity.js +47 -7
- package/dist/agents/memory-search.js +25 -8
- package/dist/agents/model-catalog.js +1 -1
- package/dist/agents/model-selection.js +21 -0
- package/dist/agents/pi-embedded-block-chunker.js +117 -42
- package/dist/agents/pi-embedded-helpers/errors.js +183 -78
- package/dist/agents/pi-embedded-helpers.js +1 -1
- package/dist/agents/pi-embedded-runner/compact.js +8 -10
- package/dist/agents/pi-embedded-runner/model.js +62 -3
- package/dist/agents/pi-embedded-runner/run/attempt.js +21 -11
- package/dist/agents/pi-embedded-runner/run.js +199 -46
- package/dist/agents/pi-embedded-runner/system-prompt.js +10 -2
- package/dist/agents/pi-embedded-subscribe.js +118 -29
- package/dist/agents/pi-tools.js +10 -5
- package/dist/agents/poolbot-tools.js +15 -10
- package/dist/agents/sandbox-paths.js +31 -0
- package/dist/agents/session-tool-result-guard.js +94 -15
- package/dist/agents/shell-utils.js +51 -0
- package/dist/agents/skills/bundled-context.js +23 -0
- package/dist/agents/skills/bundled-dir.js +41 -7
- package/dist/agents/skills-install.js +60 -23
- package/dist/agents/subagent-announce.js +79 -34
- package/dist/agents/tool-policy.conformance.js +14 -0
- package/dist/agents/tool-policy.js +24 -0
- package/dist/agents/tools/cron-tool.js +166 -19
- package/dist/agents/tools/discord-actions-presence.js +78 -0
- package/dist/agents/tools/image-tool.js +1 -1
- package/dist/agents/tools/message-tool.js +56 -2
- package/dist/agents/tools/sessions-history-tool.js +69 -1
- package/dist/agents/tools/web-search.js +211 -42
- package/dist/agents/usage.js +23 -1
- package/dist/agents/workspace-run.js +67 -0
- package/dist/agents/workspace-templates.js +44 -0
- package/dist/auto-reply/command-auth.js +121 -6
- package/dist/auto-reply/envelope.js +74 -82
- package/dist/auto-reply/reply/commands-compact.js +1 -0
- package/dist/auto-reply/reply/commands-context-report.js +1 -0
- package/dist/auto-reply/reply/commands-context.js +1 -0
- package/dist/auto-reply/reply/commands-models.js +107 -60
- package/dist/auto-reply/reply/commands-ptt.js +171 -0
- package/dist/auto-reply/reply/get-reply-run.js +2 -1
- package/dist/auto-reply/reply/inbound-context.js +5 -1
- package/dist/auto-reply/reply/mentions.js +1 -1
- package/dist/auto-reply/reply/model-selection.js +3 -3
- package/dist/auto-reply/thinking.js +88 -43
- package/dist/browser/bridge-server.js +13 -0
- package/dist/browser/cdp.helpers.js +38 -24
- package/dist/browser/client-fetch.js +50 -7
- package/dist/browser/config.js +1 -10
- package/dist/browser/extension-relay.js +101 -40
- package/dist/browser/pw-ai.js +1 -1
- package/dist/browser/pw-session.js +143 -8
- package/dist/browser/pw-tools-core.interactions.js +125 -27
- package/dist/browser/pw-tools-core.responses.js +1 -1
- package/dist/browser/pw-tools-core.state.js +1 -1
- package/dist/browser/routes/agent.act.js +86 -41
- package/dist/browser/routes/dispatcher.js +4 -4
- package/dist/browser/screenshot.js +1 -1
- package/dist/browser/server.js +13 -0
- package/dist/build-info.json +3 -3
- package/dist/canvas-host/a2ui/index.html +28 -28
- package/dist/channels/reply-prefix.js +8 -1
- package/dist/cli/cron-cli/register.cron-add.js +61 -40
- package/dist/cli/cron-cli/register.cron-edit.js +60 -34
- package/dist/cli/cron-cli/shared.js +56 -41
- package/dist/cli/dns-cli.js +26 -14
- package/dist/cli/gateway-cli/register.js +37 -19
- package/dist/cli/memory-cli.js +5 -5
- package/dist/cli/parse-bytes.js +37 -0
- package/dist/cli/update-cli.js +173 -52
- package/dist/commands/agent.js +1 -0
- package/dist/commands/auth-choice.apply.oauth.js +1 -1
- package/dist/commands/doctor-config-flow.js +61 -5
- package/dist/commands/doctor-state-migrations.js +1 -1
- package/dist/commands/health.js +1 -1
- package/dist/commands/model-allowlist.js +29 -0
- package/dist/commands/model-picker.js +2 -1
- package/dist/commands/models/list.registry.js +1 -1
- package/dist/commands/models/list.status-command.js +43 -23
- package/dist/commands/models/shared.js +15 -0
- package/dist/commands/onboard-custom.js +384 -0
- package/dist/commands/onboard-non-interactive/local/auth-choice-inference.js +35 -0
- package/dist/commands/onboard-non-interactive/local/auth-choice.js +6 -3
- package/dist/commands/onboard-skills.js +63 -38
- package/dist/commands/openai-model-default.js +41 -0
- package/dist/compat/legacy-names.js +2 -0
- package/dist/config/defaults.js +3 -2
- package/dist/config/paths.js +136 -35
- package/dist/config/plugin-auto-enable.js +21 -5
- package/dist/config/redact-snapshot.js +153 -0
- package/dist/config/schema.field-metadata.js +590 -0
- package/dist/config/schema.js +2 -2
- package/dist/config/sessions/store.js +291 -23
- package/dist/config/zod-schema.agent-defaults.js +3 -0
- package/dist/config/zod-schema.agent-runtime.js +13 -2
- package/dist/config/zod-schema.providers-core.js +142 -0
- package/dist/config/zod-schema.session.js +3 -0
- package/dist/control-ui/assets/{index-CIRDm-Lu.css → index-CSfXd2LO.css} +1 -1
- package/dist/control-ui/assets/{index-CmNMuoem.js → index-HRr1grwl.js} +446 -413
- package/dist/control-ui/assets/index-HRr1grwl.js.map +1 -0
- package/dist/control-ui/index.html +4 -4
- package/dist/cron/delivery.js +57 -0
- package/dist/cron/isolated-agent/delivery-target.js +18 -3
- package/dist/cron/isolated-agent/helpers.js +22 -5
- package/dist/cron/isolated-agent/run.js +172 -63
- package/dist/cron/isolated-agent/session.js +2 -0
- package/dist/cron/normalize.js +356 -28
- package/dist/cron/parse.js +10 -5
- package/dist/cron/run-log.js +35 -10
- package/dist/cron/schedule.js +41 -6
- package/dist/cron/service/jobs.js +208 -35
- package/dist/cron/service/ops.js +72 -16
- package/dist/cron/service/state.js +2 -0
- package/dist/cron/service/store.js +386 -14
- package/dist/cron/service/timer.js +390 -147
- package/dist/cron/session-reaper.js +86 -0
- package/dist/cron/store.js +23 -8
- package/dist/cron/validate-timestamp.js +43 -0
- package/dist/discord/monitor/agent-components.js +438 -0
- package/dist/discord/monitor/allow-list.js +28 -5
- package/dist/discord/monitor/gateway-registry.js +29 -0
- package/dist/discord/monitor/native-command.js +44 -23
- package/dist/discord/monitor/sender-identity.js +45 -0
- package/dist/discord/pluralkit.js +27 -0
- package/dist/discord/send.outbound.js +92 -5
- package/dist/discord/send.shared.js +60 -23
- package/dist/discord/targets.js +84 -1
- package/dist/entry.js +15 -9
- package/dist/extensionAPI.js +8 -0
- package/dist/gateway/control-ui.js +8 -1
- package/dist/gateway/hooks-mapping.js +3 -0
- package/dist/gateway/hooks.js +65 -0
- package/dist/gateway/net.js +96 -31
- package/dist/gateway/node-command-policy.js +50 -15
- package/dist/gateway/origin-check.js +56 -0
- package/dist/gateway/protocol/client-info.js +9 -0
- package/dist/gateway/protocol/index.js +9 -2
- package/dist/gateway/protocol/schema/agents-models-skills.js +71 -1
- package/dist/gateway/protocol/schema/cron.js +22 -10
- package/dist/gateway/protocol/schema/protocol-schemas.js +16 -2
- package/dist/gateway/protocol/schema/sessions.js +12 -0
- package/dist/gateway/server/hooks.js +1 -1
- package/dist/gateway/server-broadcast.js +26 -9
- package/dist/gateway/server-chat.js +112 -23
- package/dist/gateway/server-discovery-runtime.js +10 -2
- package/dist/gateway/server-http.js +109 -11
- package/dist/gateway/server-methods/agent-timestamp.js +60 -0
- package/dist/gateway/server-methods/agents.js +321 -2
- package/dist/gateway/server-methods/usage.js +559 -16
- package/dist/gateway/server-runtime-state.js +22 -8
- package/dist/gateway/server-startup-memory.js +16 -0
- package/dist/gateway/server.impl.js +5 -1
- package/dist/gateway/session-utils.fs.js +23 -25
- package/dist/gateway/session-utils.js +20 -10
- package/dist/gateway/sessions-patch.js +7 -22
- package/dist/gateway/test-helpers.mocks.js +11 -7
- package/dist/gateway/test-helpers.server.js +35 -2
- package/dist/imessage/constants.js +2 -0
- package/dist/imessage/monitor/deliver.js +4 -1
- package/dist/imessage/monitor/monitor-provider.js +51 -1
- package/dist/infra/bonjour-discovery.js +131 -70
- package/dist/infra/control-ui-assets.js +134 -12
- package/dist/infra/errors.js +12 -0
- package/dist/infra/exec-approvals.js +266 -57
- package/dist/infra/format-time/format-datetime.js +79 -0
- package/dist/infra/format-time/format-duration.js +81 -0
- package/dist/infra/format-time/format-relative.js +80 -0
- package/dist/infra/heartbeat-runner.js +140 -49
- package/dist/infra/home-dir.js +54 -0
- package/dist/infra/net/fetch-guard.js +122 -0
- package/dist/infra/net/ssrf.js +65 -29
- package/dist/infra/outbound/abort.js +14 -0
- package/dist/infra/outbound/message-action-runner.js +77 -13
- package/dist/infra/outbound/outbound-session.js +143 -37
- package/dist/infra/poolbot-root.js +43 -1
- package/dist/infra/session-cost-usage.js +631 -41
- package/dist/infra/state-migrations.js +317 -47
- package/dist/infra/update-global.js +35 -0
- package/dist/infra/update-runner.js +149 -43
- package/dist/infra/warning-filter.js +65 -0
- package/dist/infra/widearea-dns.js +30 -9
- package/dist/logging/redact-identifier.js +12 -0
- package/dist/media/fetch.js +81 -58
- package/dist/media/store.js +2 -0
- package/dist/media-understanding/apply.js +403 -3
- package/dist/media-understanding/attachments.js +38 -27
- package/dist/media-understanding/defaults.js +16 -0
- package/dist/media-understanding/providers/deepgram/audio.js +22 -14
- package/dist/media-understanding/providers/google/audio.js +24 -17
- package/dist/media-understanding/providers/google/video.js +24 -17
- package/dist/media-understanding/providers/image.js +3 -3
- package/dist/media-understanding/providers/index.js +4 -1
- package/dist/media-understanding/providers/openai/audio.js +22 -14
- package/dist/media-understanding/providers/shared.js +16 -11
- package/dist/media-understanding/providers/zai/index.js +6 -0
- package/dist/media-understanding/runner.js +158 -90
- package/dist/memory/batch-voyage.js +277 -0
- package/dist/memory/embeddings-voyage.js +75 -0
- package/dist/memory/embeddings.js +28 -16
- package/dist/memory/internal.js +101 -18
- package/dist/memory/manager.js +154 -48
- package/dist/memory/search-manager.js +173 -0
- package/dist/memory/session-files.js +9 -3
- package/dist/node-host/runner.js +34 -24
- package/dist/node-host/with-timeout.js +27 -0
- package/dist/plugins/commands.js +5 -1
- package/dist/plugins/config-state.js +86 -7
- package/dist/plugins/source-display.js +51 -0
- package/dist/process/exec.js +20 -2
- package/dist/routing/resolve-route.js +12 -0
- package/dist/routing/session-key.js +15 -0
- package/dist/runtime.js +2 -0
- package/dist/security/audit-extra.async.js +601 -0
- package/dist/security/audit-extra.js +2 -830
- package/dist/security/audit-extra.sync.js +505 -0
- package/dist/security/channel-metadata.js +34 -0
- package/dist/security/external-content.js +88 -6
- package/dist/security/skill-scanner.js +330 -0
- package/dist/sessions/session-key-utils.js +7 -0
- package/dist/signal/monitor/event-handler.js +80 -1
- package/dist/slack/monitor/media.js +85 -15
- package/dist/tailscale/detect.js +1 -2
- package/dist/telegram/bot/helpers.js +109 -28
- package/dist/telegram/bot-handlers.js +144 -3
- package/dist/telegram/bot-message-context.js +37 -10
- package/dist/telegram/bot-message-dispatch.js +54 -17
- package/dist/telegram/bot-native-commands.js +86 -29
- package/dist/telegram/bot.js +30 -29
- package/dist/telegram/model-buttons.js +163 -0
- package/dist/telegram/monitor.js +110 -85
- package/dist/telegram/send.js +129 -47
- package/dist/terminal/restore.js +45 -0
- package/dist/test-helpers/state-dir-env.js +16 -0
- package/dist/tts/tts.js +12 -6
- package/dist/tui/tui-session-actions.js +166 -54
- package/dist/utils/fetch-timeout.js +20 -0
- package/dist/utils/normalize-secret-input.js +19 -0
- package/dist/utils/transcript-tools.js +58 -0
- package/dist/utils.js +45 -14
- package/dist/version.js +42 -5
- package/dist/wizard/clack-prompter.js +9 -6
- package/extensions/googlechat/node_modules/.bin/poolbot +21 -0
- package/extensions/googlechat/package.json +2 -2
- package/extensions/line/node_modules/.bin/poolbot +21 -0
- package/extensions/line/package.json +1 -1
- package/extensions/matrix/node_modules/.bin/poolbot +21 -0
- package/extensions/matrix/package.json +1 -1
- package/extensions/memory-core/node_modules/.bin/poolbot +21 -0
- package/extensions/memory-core/package.json +4 -1
- package/extensions/twitch/node_modules/.bin/poolbot +21 -0
- package/extensions/twitch/package.json +1 -1
- package/package.json +183 -24
- package/dist/control-ui/assets/index-CmNMuoem.js.map +0 -1
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import { Type } from "@sinclair/typebox";
|
|
2
2
|
import { formatCliCommand } from "../../cli/command-format.js";
|
|
3
|
+
import { wrapWebContent } from "../../security/external-content.js";
|
|
4
|
+
import { normalizeSecretInput } from "../../utils/normalize-secret-input.js";
|
|
3
5
|
import { jsonResult, readNumberParam, readStringParam } from "./common.js";
|
|
4
6
|
import { DEFAULT_CACHE_TTL_MINUTES, DEFAULT_TIMEOUT_SECONDS, normalizeCacheKey, readCache, readResponseText, resolveCacheTtlMs, resolveTimeoutSeconds, withTimeout, writeCache, } from "./web-shared.js";
|
|
5
|
-
const SEARCH_PROVIDERS = ["brave", "perplexity"];
|
|
7
|
+
const SEARCH_PROVIDERS = ["brave", "perplexity", "grok"];
|
|
6
8
|
const DEFAULT_SEARCH_COUNT = 5;
|
|
7
9
|
const MAX_SEARCH_COUNT = 10;
|
|
8
10
|
const BRAVE_SEARCH_ENDPOINT = "https://api.search.brave.com/res/v1/web/search";
|
|
@@ -11,6 +13,8 @@ const PERPLEXITY_DIRECT_BASE_URL = "https://api.perplexity.ai";
|
|
|
11
13
|
const DEFAULT_PERPLEXITY_MODEL = "perplexity/sonar-pro";
|
|
12
14
|
const PERPLEXITY_KEY_PREFIXES = ["pplx-"];
|
|
13
15
|
const OPENROUTER_KEY_PREFIXES = ["sk-or-"];
|
|
16
|
+
const XAI_API_ENDPOINT = "https://api.x.ai/v1/responses";
|
|
17
|
+
const DEFAULT_GROK_MODEL = "grok-4-1-fast";
|
|
14
18
|
const SEARCH_CACHE = new Map();
|
|
15
19
|
const BRAVE_FRESHNESS_SHORTCUTS = new Set(["pd", "pw", "pm", "py"]);
|
|
16
20
|
const BRAVE_FRESHNESS_RANGE = /^(\d{4}-\d{2}-\d{2})to(\d{4}-\d{2}-\d{2})$/;
|
|
@@ -34,22 +38,35 @@ const WebSearchSchema = Type.Object({
|
|
|
34
38
|
description: "Filter results by discovery time (Brave only). Values: 'pd' (past 24h), 'pw' (past week), 'pm' (past month), 'py' (past year), or date range 'YYYY-MM-DDtoYYYY-MM-DD'.",
|
|
35
39
|
})),
|
|
36
40
|
});
|
|
41
|
+
function extractGrokContent(data) {
|
|
42
|
+
// xAI Responses API format: output[0].content[0].text
|
|
43
|
+
const fromResponses = data.output?.[0]?.content?.[0]?.text;
|
|
44
|
+
if (typeof fromResponses === "string" && fromResponses) {
|
|
45
|
+
return fromResponses;
|
|
46
|
+
}
|
|
47
|
+
return typeof data.output_text === "string" ? data.output_text : undefined;
|
|
48
|
+
}
|
|
37
49
|
function resolveSearchConfig(cfg) {
|
|
38
50
|
const search = cfg?.tools?.web?.search;
|
|
39
|
-
if (!search || typeof search !== "object")
|
|
51
|
+
if (!search || typeof search !== "object") {
|
|
40
52
|
return undefined;
|
|
53
|
+
}
|
|
41
54
|
return search;
|
|
42
55
|
}
|
|
43
56
|
function resolveSearchEnabled(params) {
|
|
44
|
-
if (typeof params.search?.enabled === "boolean")
|
|
57
|
+
if (typeof params.search?.enabled === "boolean") {
|
|
45
58
|
return params.search.enabled;
|
|
46
|
-
|
|
59
|
+
}
|
|
60
|
+
if (params.sandboxed) {
|
|
47
61
|
return true;
|
|
62
|
+
}
|
|
48
63
|
return true;
|
|
49
64
|
}
|
|
50
65
|
function resolveSearchApiKey(search) {
|
|
51
|
-
const fromConfig = search && "apiKey" in search && typeof search.apiKey === "string"
|
|
52
|
-
|
|
66
|
+
const fromConfig = search && "apiKey" in search && typeof search.apiKey === "string"
|
|
67
|
+
? normalizeSecretInput(search.apiKey)
|
|
68
|
+
: "";
|
|
69
|
+
const fromEnv = normalizeSecretInput(process.env.BRAVE_API_KEY);
|
|
53
70
|
return fromConfig || fromEnv || undefined;
|
|
54
71
|
}
|
|
55
72
|
function missingSearchKeyPayload(provider) {
|
|
@@ -60,6 +77,13 @@ function missingSearchKeyPayload(provider) {
|
|
|
60
77
|
docs: "https://docs.molt.bot/tools/web",
|
|
61
78
|
};
|
|
62
79
|
}
|
|
80
|
+
if (provider === "grok") {
|
|
81
|
+
return {
|
|
82
|
+
error: "missing_xai_api_key",
|
|
83
|
+
message: "web_search (grok) needs an xAI API key. Set XAI_API_KEY in the Gateway environment, or configure tools.web.search.grok.apiKey.",
|
|
84
|
+
docs: "https://docs.molt.bot/tools/web",
|
|
85
|
+
};
|
|
86
|
+
}
|
|
63
87
|
return {
|
|
64
88
|
error: "missing_brave_api_key",
|
|
65
89
|
message: `web_search needs a Brave Search API key. Run \`${formatCliCommand("poolbot configure --section web")}\` to store it, or set BRAVE_API_KEY in the Gateway environment.`,
|
|
@@ -70,18 +94,25 @@ function resolveSearchProvider(search) {
|
|
|
70
94
|
const raw = search && "provider" in search && typeof search.provider === "string"
|
|
71
95
|
? search.provider.trim().toLowerCase()
|
|
72
96
|
: "";
|
|
73
|
-
if (raw === "perplexity")
|
|
97
|
+
if (raw === "perplexity") {
|
|
74
98
|
return "perplexity";
|
|
75
|
-
|
|
99
|
+
}
|
|
100
|
+
if (raw === "grok") {
|
|
101
|
+
return "grok";
|
|
102
|
+
}
|
|
103
|
+
if (raw === "brave") {
|
|
76
104
|
return "brave";
|
|
105
|
+
}
|
|
77
106
|
return "brave";
|
|
78
107
|
}
|
|
79
108
|
function resolvePerplexityConfig(search) {
|
|
80
|
-
if (!search || typeof search !== "object")
|
|
109
|
+
if (!search || typeof search !== "object") {
|
|
81
110
|
return {};
|
|
111
|
+
}
|
|
82
112
|
const perplexity = "perplexity" in search ? search.perplexity : undefined;
|
|
83
|
-
if (!perplexity || typeof perplexity !== "object")
|
|
113
|
+
if (!perplexity || typeof perplexity !== "object") {
|
|
84
114
|
return {};
|
|
115
|
+
}
|
|
85
116
|
return perplexity;
|
|
86
117
|
}
|
|
87
118
|
function resolvePerplexityApiKey(perplexity) {
|
|
@@ -100,11 +131,12 @@ function resolvePerplexityApiKey(perplexity) {
|
|
|
100
131
|
return { apiKey: undefined, source: "none" };
|
|
101
132
|
}
|
|
102
133
|
function normalizeApiKey(key) {
|
|
103
|
-
return
|
|
134
|
+
return normalizeSecretInput(key);
|
|
104
135
|
}
|
|
105
136
|
function inferPerplexityBaseUrlFromApiKey(apiKey) {
|
|
106
|
-
if (!apiKey)
|
|
137
|
+
if (!apiKey) {
|
|
107
138
|
return undefined;
|
|
139
|
+
}
|
|
108
140
|
const normalized = apiKey.toLowerCase();
|
|
109
141
|
if (PERPLEXITY_KEY_PREFIXES.some((prefix) => normalized.startsWith(prefix))) {
|
|
110
142
|
return "direct";
|
|
@@ -118,18 +150,23 @@ function resolvePerplexityBaseUrl(perplexity, apiKeySource = "none", apiKey) {
|
|
|
118
150
|
const fromConfig = perplexity && "baseUrl" in perplexity && typeof perplexity.baseUrl === "string"
|
|
119
151
|
? perplexity.baseUrl.trim()
|
|
120
152
|
: "";
|
|
121
|
-
if (fromConfig)
|
|
153
|
+
if (fromConfig) {
|
|
122
154
|
return fromConfig;
|
|
123
|
-
|
|
155
|
+
}
|
|
156
|
+
if (apiKeySource === "perplexity_env") {
|
|
124
157
|
return PERPLEXITY_DIRECT_BASE_URL;
|
|
125
|
-
|
|
158
|
+
}
|
|
159
|
+
if (apiKeySource === "openrouter_env") {
|
|
126
160
|
return DEFAULT_PERPLEXITY_BASE_URL;
|
|
161
|
+
}
|
|
127
162
|
if (apiKeySource === "config") {
|
|
128
163
|
const inferred = inferPerplexityBaseUrlFromApiKey(apiKey);
|
|
129
|
-
if (inferred === "direct")
|
|
164
|
+
if (inferred === "direct") {
|
|
130
165
|
return PERPLEXITY_DIRECT_BASE_URL;
|
|
131
|
-
|
|
166
|
+
}
|
|
167
|
+
if (inferred === "openrouter") {
|
|
132
168
|
return DEFAULT_PERPLEXITY_BASE_URL;
|
|
169
|
+
}
|
|
133
170
|
}
|
|
134
171
|
return DEFAULT_PERPLEXITY_BASE_URL;
|
|
135
172
|
}
|
|
@@ -139,42 +176,94 @@ function resolvePerplexityModel(perplexity) {
|
|
|
139
176
|
: "";
|
|
140
177
|
return fromConfig || DEFAULT_PERPLEXITY_MODEL;
|
|
141
178
|
}
|
|
179
|
+
function isDirectPerplexityBaseUrl(baseUrl) {
|
|
180
|
+
const trimmed = baseUrl.trim();
|
|
181
|
+
if (!trimmed) {
|
|
182
|
+
return false;
|
|
183
|
+
}
|
|
184
|
+
try {
|
|
185
|
+
return new URL(trimmed).hostname.toLowerCase() === "api.perplexity.ai";
|
|
186
|
+
}
|
|
187
|
+
catch {
|
|
188
|
+
return false;
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
function resolvePerplexityRequestModel(baseUrl, model) {
|
|
192
|
+
if (!isDirectPerplexityBaseUrl(baseUrl)) {
|
|
193
|
+
return model;
|
|
194
|
+
}
|
|
195
|
+
return model.startsWith("perplexity/") ? model.slice("perplexity/".length) : model;
|
|
196
|
+
}
|
|
197
|
+
function resolveGrokConfig(search) {
|
|
198
|
+
if (!search || typeof search !== "object") {
|
|
199
|
+
return {};
|
|
200
|
+
}
|
|
201
|
+
const grok = "grok" in search ? search.grok : undefined;
|
|
202
|
+
if (!grok || typeof grok !== "object") {
|
|
203
|
+
return {};
|
|
204
|
+
}
|
|
205
|
+
return grok;
|
|
206
|
+
}
|
|
207
|
+
function resolveGrokApiKey(grok) {
|
|
208
|
+
const fromConfig = normalizeApiKey(grok?.apiKey);
|
|
209
|
+
if (fromConfig) {
|
|
210
|
+
return fromConfig;
|
|
211
|
+
}
|
|
212
|
+
const fromEnv = normalizeApiKey(process.env.XAI_API_KEY);
|
|
213
|
+
return fromEnv || undefined;
|
|
214
|
+
}
|
|
215
|
+
function resolveGrokModel(grok) {
|
|
216
|
+
const fromConfig = grok && "model" in grok && typeof grok.model === "string" ? grok.model.trim() : "";
|
|
217
|
+
return fromConfig || DEFAULT_GROK_MODEL;
|
|
218
|
+
}
|
|
219
|
+
function resolveGrokInlineCitations(grok) {
|
|
220
|
+
return grok?.inlineCitations === true;
|
|
221
|
+
}
|
|
142
222
|
function resolveSearchCount(value, fallback) {
|
|
143
223
|
const parsed = typeof value === "number" && Number.isFinite(value) ? value : fallback;
|
|
144
224
|
const clamped = Math.max(1, Math.min(MAX_SEARCH_COUNT, Math.floor(parsed)));
|
|
145
225
|
return clamped;
|
|
146
226
|
}
|
|
147
227
|
function normalizeFreshness(value) {
|
|
148
|
-
if (!value)
|
|
228
|
+
if (!value) {
|
|
149
229
|
return undefined;
|
|
230
|
+
}
|
|
150
231
|
const trimmed = value.trim();
|
|
151
|
-
if (!trimmed)
|
|
232
|
+
if (!trimmed) {
|
|
152
233
|
return undefined;
|
|
234
|
+
}
|
|
153
235
|
const lower = trimmed.toLowerCase();
|
|
154
|
-
if (BRAVE_FRESHNESS_SHORTCUTS.has(lower))
|
|
236
|
+
if (BRAVE_FRESHNESS_SHORTCUTS.has(lower)) {
|
|
155
237
|
return lower;
|
|
238
|
+
}
|
|
156
239
|
const match = trimmed.match(BRAVE_FRESHNESS_RANGE);
|
|
157
|
-
if (!match)
|
|
240
|
+
if (!match) {
|
|
158
241
|
return undefined;
|
|
242
|
+
}
|
|
159
243
|
const [, start, end] = match;
|
|
160
|
-
if (!isValidIsoDate(start) || !isValidIsoDate(end))
|
|
244
|
+
if (!isValidIsoDate(start) || !isValidIsoDate(end)) {
|
|
161
245
|
return undefined;
|
|
162
|
-
|
|
246
|
+
}
|
|
247
|
+
if (start > end) {
|
|
163
248
|
return undefined;
|
|
249
|
+
}
|
|
164
250
|
return `${start}to${end}`;
|
|
165
251
|
}
|
|
166
252
|
function isValidIsoDate(value) {
|
|
167
|
-
if (!/^\d{4}-\d{2}-\d{2}$/.test(value))
|
|
253
|
+
if (!/^\d{4}-\d{2}-\d{2}$/.test(value)) {
|
|
168
254
|
return false;
|
|
255
|
+
}
|
|
169
256
|
const [year, month, day] = value.split("-").map((part) => Number.parseInt(part, 10));
|
|
170
|
-
if (!Number.isFinite(year) || !Number.isFinite(month) || !Number.isFinite(day))
|
|
257
|
+
if (!Number.isFinite(year) || !Number.isFinite(month) || !Number.isFinite(day)) {
|
|
171
258
|
return false;
|
|
259
|
+
}
|
|
172
260
|
const date = new Date(Date.UTC(year, month - 1, day));
|
|
173
261
|
return (date.getUTCFullYear() === year && date.getUTCMonth() === month - 1 && date.getUTCDate() === day);
|
|
174
262
|
}
|
|
175
263
|
function resolveSiteName(url) {
|
|
176
|
-
if (!url)
|
|
264
|
+
if (!url) {
|
|
177
265
|
return undefined;
|
|
266
|
+
}
|
|
178
267
|
try {
|
|
179
268
|
return new URL(url).hostname;
|
|
180
269
|
}
|
|
@@ -183,17 +272,19 @@ function resolveSiteName(url) {
|
|
|
183
272
|
}
|
|
184
273
|
}
|
|
185
274
|
async function runPerplexitySearch(params) {
|
|
186
|
-
const
|
|
275
|
+
const baseUrl = params.baseUrl.trim().replace(/\/$/, "");
|
|
276
|
+
const endpoint = `${baseUrl}/chat/completions`;
|
|
277
|
+
const model = resolvePerplexityRequestModel(baseUrl, params.model);
|
|
187
278
|
const res = await fetch(endpoint, {
|
|
188
279
|
method: "POST",
|
|
189
280
|
headers: {
|
|
190
281
|
"Content-Type": "application/json",
|
|
191
282
|
Authorization: `Bearer ${params.apiKey}`,
|
|
192
283
|
"HTTP-Referer": "https://molt.bot",
|
|
193
|
-
"X-Title": "
|
|
284
|
+
"X-Title": "Pool Bot Web Search",
|
|
194
285
|
},
|
|
195
286
|
body: JSON.stringify({
|
|
196
|
-
model
|
|
287
|
+
model,
|
|
197
288
|
messages: [
|
|
198
289
|
{
|
|
199
290
|
role: "user",
|
|
@@ -212,13 +303,49 @@ async function runPerplexitySearch(params) {
|
|
|
212
303
|
const citations = data.citations ?? [];
|
|
213
304
|
return { content, citations };
|
|
214
305
|
}
|
|
306
|
+
async function runGrokSearch(params) {
|
|
307
|
+
const body = {
|
|
308
|
+
model: params.model,
|
|
309
|
+
input: [
|
|
310
|
+
{
|
|
311
|
+
role: "user",
|
|
312
|
+
content: params.query,
|
|
313
|
+
},
|
|
314
|
+
],
|
|
315
|
+
tools: [{ type: "web_search" }],
|
|
316
|
+
};
|
|
317
|
+
if (params.inlineCitations) {
|
|
318
|
+
body.include = ["inline_citations"];
|
|
319
|
+
}
|
|
320
|
+
const res = await fetch(XAI_API_ENDPOINT, {
|
|
321
|
+
method: "POST",
|
|
322
|
+
headers: {
|
|
323
|
+
"Content-Type": "application/json",
|
|
324
|
+
Authorization: `Bearer ${params.apiKey}`,
|
|
325
|
+
},
|
|
326
|
+
body: JSON.stringify(body),
|
|
327
|
+
signal: withTimeout(undefined, params.timeoutSeconds * 1000),
|
|
328
|
+
});
|
|
329
|
+
if (!res.ok) {
|
|
330
|
+
const detail = await readResponseText(res);
|
|
331
|
+
throw new Error(`xAI API error (${res.status}): ${detail || res.statusText}`);
|
|
332
|
+
}
|
|
333
|
+
const data = (await res.json());
|
|
334
|
+
const content = extractGrokContent(data) ?? "No response";
|
|
335
|
+
const citations = data.citations ?? [];
|
|
336
|
+
const inlineCitations = data.inline_citations;
|
|
337
|
+
return { content, citations, inlineCitations };
|
|
338
|
+
}
|
|
215
339
|
async function runWebSearch(params) {
|
|
216
340
|
const cacheKey = normalizeCacheKey(params.provider === "brave"
|
|
217
341
|
? `${params.provider}:${params.query}:${params.count}:${params.country || "default"}:${params.search_lang || "default"}:${params.ui_lang || "default"}:${params.freshness || "default"}`
|
|
218
|
-
:
|
|
342
|
+
: params.provider === "perplexity"
|
|
343
|
+
? `${params.provider}:${params.query}:${params.perplexityBaseUrl ?? DEFAULT_PERPLEXITY_BASE_URL}:${params.perplexityModel ?? DEFAULT_PERPLEXITY_MODEL}`
|
|
344
|
+
: `${params.provider}:${params.query}:${params.grokModel ?? DEFAULT_GROK_MODEL}:${String(params.grokInlineCitations ?? false)}`);
|
|
219
345
|
const cached = readCache(SEARCH_CACHE, cacheKey);
|
|
220
|
-
if (cached)
|
|
346
|
+
if (cached) {
|
|
221
347
|
return { ...cached.value, cached: true };
|
|
348
|
+
}
|
|
222
349
|
const start = Date.now();
|
|
223
350
|
if (params.provider === "perplexity") {
|
|
224
351
|
const { content, citations } = await runPerplexitySearch({
|
|
@@ -233,8 +360,28 @@ async function runWebSearch(params) {
|
|
|
233
360
|
provider: params.provider,
|
|
234
361
|
model: params.perplexityModel ?? DEFAULT_PERPLEXITY_MODEL,
|
|
235
362
|
tookMs: Date.now() - start,
|
|
236
|
-
content,
|
|
363
|
+
content: wrapWebContent(content),
|
|
364
|
+
citations,
|
|
365
|
+
};
|
|
366
|
+
writeCache(SEARCH_CACHE, cacheKey, payload, params.cacheTtlMs);
|
|
367
|
+
return payload;
|
|
368
|
+
}
|
|
369
|
+
if (params.provider === "grok") {
|
|
370
|
+
const { content, citations, inlineCitations } = await runGrokSearch({
|
|
371
|
+
query: params.query,
|
|
372
|
+
apiKey: params.apiKey,
|
|
373
|
+
model: params.grokModel ?? DEFAULT_GROK_MODEL,
|
|
374
|
+
timeoutSeconds: params.timeoutSeconds,
|
|
375
|
+
inlineCitations: params.grokInlineCitations ?? false,
|
|
376
|
+
});
|
|
377
|
+
const payload = {
|
|
378
|
+
query: params.query,
|
|
379
|
+
provider: params.provider,
|
|
380
|
+
model: params.grokModel ?? DEFAULT_GROK_MODEL,
|
|
381
|
+
tookMs: Date.now() - start,
|
|
382
|
+
content: wrapWebContent(content),
|
|
237
383
|
citations,
|
|
384
|
+
inlineCitations,
|
|
238
385
|
};
|
|
239
386
|
writeCache(SEARCH_CACHE, cacheKey, payload, params.cacheTtlMs);
|
|
240
387
|
return payload;
|
|
@@ -271,13 +418,19 @@ async function runWebSearch(params) {
|
|
|
271
418
|
}
|
|
272
419
|
const data = (await res.json());
|
|
273
420
|
const results = Array.isArray(data.web?.results) ? (data.web?.results ?? []) : [];
|
|
274
|
-
const mapped = results.map((entry) =>
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
421
|
+
const mapped = results.map((entry) => {
|
|
422
|
+
const description = entry.description ?? "";
|
|
423
|
+
const title = entry.title ?? "";
|
|
424
|
+
const url = entry.url ?? "";
|
|
425
|
+
const rawSiteName = resolveSiteName(url);
|
|
426
|
+
return {
|
|
427
|
+
title: title ? wrapWebContent(title, "web_search") : "",
|
|
428
|
+
url, // Keep raw for tool chaining
|
|
429
|
+
description: description ? wrapWebContent(description, "web_search") : "",
|
|
430
|
+
published: entry.age || undefined,
|
|
431
|
+
siteName: rawSiteName || undefined,
|
|
432
|
+
};
|
|
433
|
+
});
|
|
281
434
|
const payload = {
|
|
282
435
|
query: params.query,
|
|
283
436
|
provider: params.provider,
|
|
@@ -290,13 +443,17 @@ async function runWebSearch(params) {
|
|
|
290
443
|
}
|
|
291
444
|
export function createWebSearchTool(options) {
|
|
292
445
|
const search = resolveSearchConfig(options?.config);
|
|
293
|
-
if (!resolveSearchEnabled({ search, sandboxed: options?.sandboxed }))
|
|
446
|
+
if (!resolveSearchEnabled({ search, sandboxed: options?.sandboxed })) {
|
|
294
447
|
return null;
|
|
448
|
+
}
|
|
295
449
|
const provider = resolveSearchProvider(search);
|
|
296
450
|
const perplexityConfig = resolvePerplexityConfig(search);
|
|
451
|
+
const grokConfig = resolveGrokConfig(search);
|
|
297
452
|
const description = provider === "perplexity"
|
|
298
453
|
? "Search the web using Perplexity Sonar (direct or via OpenRouter). Returns AI-synthesized answers with citations from real-time web search."
|
|
299
|
-
:
|
|
454
|
+
: provider === "grok"
|
|
455
|
+
? "Search the web using xAI Grok. Returns AI-synthesized answers with citations from real-time web search."
|
|
456
|
+
: "Search the web using Brave Search API. Supports region-specific and localized search via country and language parameters. Returns titles, URLs, and snippets for fast research.";
|
|
300
457
|
return {
|
|
301
458
|
label: "Web Search",
|
|
302
459
|
name: "web_search",
|
|
@@ -304,7 +461,11 @@ export function createWebSearchTool(options) {
|
|
|
304
461
|
parameters: WebSearchSchema,
|
|
305
462
|
execute: async (_toolCallId, args) => {
|
|
306
463
|
const perplexityAuth = provider === "perplexity" ? resolvePerplexityApiKey(perplexityConfig) : undefined;
|
|
307
|
-
const apiKey = provider === "perplexity"
|
|
464
|
+
const apiKey = provider === "perplexity"
|
|
465
|
+
? perplexityAuth?.apiKey
|
|
466
|
+
: provider === "grok"
|
|
467
|
+
? resolveGrokApiKey(grokConfig)
|
|
468
|
+
: resolveSearchApiKey(search);
|
|
308
469
|
if (!apiKey) {
|
|
309
470
|
return jsonResult(missingSearchKeyPayload(provider));
|
|
310
471
|
}
|
|
@@ -343,6 +504,8 @@ export function createWebSearchTool(options) {
|
|
|
343
504
|
freshness,
|
|
344
505
|
perplexityBaseUrl: resolvePerplexityBaseUrl(perplexityConfig, perplexityAuth?.source, perplexityAuth?.apiKey),
|
|
345
506
|
perplexityModel: resolvePerplexityModel(perplexityConfig),
|
|
507
|
+
grokModel: resolveGrokModel(grokConfig),
|
|
508
|
+
grokInlineCitations: resolveGrokInlineCitations(grokConfig),
|
|
346
509
|
});
|
|
347
510
|
return jsonResult(result);
|
|
348
511
|
},
|
|
@@ -351,5 +514,11 @@ export function createWebSearchTool(options) {
|
|
|
351
514
|
export const __testing = {
|
|
352
515
|
inferPerplexityBaseUrlFromApiKey,
|
|
353
516
|
resolvePerplexityBaseUrl,
|
|
517
|
+
isDirectPerplexityBaseUrl,
|
|
518
|
+
resolvePerplexityRequestModel,
|
|
354
519
|
normalizeFreshness,
|
|
520
|
+
resolveGrokApiKey,
|
|
521
|
+
resolveGrokModel,
|
|
522
|
+
resolveGrokInlineCitations,
|
|
523
|
+
extractGrokContent,
|
|
355
524
|
};
|
package/dist/agents/usage.js
CHANGED
|
@@ -38,11 +38,33 @@ export function normalizeUsage(raw) {
|
|
|
38
38
|
};
|
|
39
39
|
}
|
|
40
40
|
export function derivePromptTokens(usage) {
|
|
41
|
-
if (!usage)
|
|
41
|
+
if (!usage) {
|
|
42
42
|
return undefined;
|
|
43
|
+
}
|
|
43
44
|
const input = usage.input ?? 0;
|
|
44
45
|
const cacheRead = usage.cacheRead ?? 0;
|
|
45
46
|
const cacheWrite = usage.cacheWrite ?? 0;
|
|
46
47
|
const sum = input + cacheRead + cacheWrite;
|
|
47
48
|
return sum > 0 ? sum : undefined;
|
|
48
49
|
}
|
|
50
|
+
export function deriveSessionTotalTokens(params) {
|
|
51
|
+
const usage = params.usage;
|
|
52
|
+
if (!usage) {
|
|
53
|
+
return undefined;
|
|
54
|
+
}
|
|
55
|
+
const input = usage.input ?? 0;
|
|
56
|
+
const promptTokens = derivePromptTokens({
|
|
57
|
+
input: usage.input,
|
|
58
|
+
cacheRead: usage.cacheRead,
|
|
59
|
+
cacheWrite: usage.cacheWrite,
|
|
60
|
+
});
|
|
61
|
+
let total = promptTokens ?? usage.total ?? input;
|
|
62
|
+
if (!(total > 0)) {
|
|
63
|
+
return undefined;
|
|
64
|
+
}
|
|
65
|
+
const contextTokens = params.contextTokens;
|
|
66
|
+
if (typeof contextTokens === "number" && Number.isFinite(contextTokens) && contextTokens > 0) {
|
|
67
|
+
total = Math.min(total, contextTokens);
|
|
68
|
+
}
|
|
69
|
+
return total;
|
|
70
|
+
}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { redactIdentifier } from "../logging/redact-identifier.js";
|
|
2
|
+
import { classifySessionKeyShape, DEFAULT_AGENT_ID, normalizeAgentId, parseAgentSessionKey, } from "../routing/session-key.js";
|
|
3
|
+
import { resolveUserPath } from "../utils.js";
|
|
4
|
+
import { resolveAgentWorkspaceDir, resolveDefaultAgentId } from "./agent-scope.js";
|
|
5
|
+
function resolveRunAgentId(params) {
|
|
6
|
+
const rawSessionKey = params.sessionKey?.trim() ?? "";
|
|
7
|
+
const shape = classifySessionKeyShape(rawSessionKey);
|
|
8
|
+
if (shape === "malformed_agent") {
|
|
9
|
+
throw new Error("Malformed agent session key; refusing workspace resolution.");
|
|
10
|
+
}
|
|
11
|
+
const explicit = typeof params.agentId === "string" && params.agentId.trim()
|
|
12
|
+
? normalizeAgentId(params.agentId)
|
|
13
|
+
: undefined;
|
|
14
|
+
if (explicit) {
|
|
15
|
+
return { agentId: explicit, agentIdSource: "explicit" };
|
|
16
|
+
}
|
|
17
|
+
const defaultAgentId = resolveDefaultAgentId(params.config ?? {});
|
|
18
|
+
if (shape === "missing" || shape === "legacy_or_alias") {
|
|
19
|
+
return {
|
|
20
|
+
agentId: defaultAgentId || DEFAULT_AGENT_ID,
|
|
21
|
+
agentIdSource: "default",
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
const parsed = parseAgentSessionKey(rawSessionKey);
|
|
25
|
+
if (parsed?.agentId) {
|
|
26
|
+
return {
|
|
27
|
+
agentId: normalizeAgentId(parsed.agentId),
|
|
28
|
+
agentIdSource: "session_key",
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
// Defensive fallback, should be unreachable for non-malformed shapes.
|
|
32
|
+
return {
|
|
33
|
+
agentId: defaultAgentId || DEFAULT_AGENT_ID,
|
|
34
|
+
agentIdSource: "default",
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
export function redactRunIdentifier(value) {
|
|
38
|
+
return redactIdentifier(value, { len: 12 });
|
|
39
|
+
}
|
|
40
|
+
export function resolveRunWorkspaceDir(params) {
|
|
41
|
+
const requested = params.workspaceDir;
|
|
42
|
+
const { agentId, agentIdSource } = resolveRunAgentId({
|
|
43
|
+
sessionKey: params.sessionKey,
|
|
44
|
+
agentId: params.agentId,
|
|
45
|
+
config: params.config,
|
|
46
|
+
});
|
|
47
|
+
if (typeof requested === "string") {
|
|
48
|
+
const trimmed = requested.trim();
|
|
49
|
+
if (trimmed) {
|
|
50
|
+
return {
|
|
51
|
+
workspaceDir: resolveUserPath(trimmed),
|
|
52
|
+
usedFallback: false,
|
|
53
|
+
agentId,
|
|
54
|
+
agentIdSource,
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
const fallbackReason = requested == null ? "missing" : typeof requested === "string" ? "blank" : "invalid_type";
|
|
59
|
+
const fallbackWorkspace = resolveAgentWorkspaceDir(params.config ?? {}, agentId);
|
|
60
|
+
return {
|
|
61
|
+
workspaceDir: resolveUserPath(fallbackWorkspace),
|
|
62
|
+
usedFallback: true,
|
|
63
|
+
fallbackReason,
|
|
64
|
+
agentId,
|
|
65
|
+
agentIdSource,
|
|
66
|
+
};
|
|
67
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
import { fileURLToPath } from "node:url";
|
|
3
|
+
import { resolvePoolBotPackageRoot } from "../infra/poolbot-root.js";
|
|
4
|
+
import { pathExists } from "../utils.js";
|
|
5
|
+
const FALLBACK_TEMPLATE_DIR = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "../../docs/reference/templates");
|
|
6
|
+
let cachedTemplateDir;
|
|
7
|
+
let resolvingTemplateDir;
|
|
8
|
+
export async function resolveWorkspaceTemplateDir(opts) {
|
|
9
|
+
if (cachedTemplateDir) {
|
|
10
|
+
return cachedTemplateDir;
|
|
11
|
+
}
|
|
12
|
+
if (resolvingTemplateDir) {
|
|
13
|
+
return resolvingTemplateDir;
|
|
14
|
+
}
|
|
15
|
+
resolvingTemplateDir = (async () => {
|
|
16
|
+
const moduleUrl = opts?.moduleUrl ?? import.meta.url;
|
|
17
|
+
const argv1 = opts?.argv1 ?? process.argv[1];
|
|
18
|
+
const cwd = opts?.cwd ?? process.cwd();
|
|
19
|
+
const packageRoot = await resolvePoolBotPackageRoot({ moduleUrl, argv1, cwd });
|
|
20
|
+
const candidates = [
|
|
21
|
+
packageRoot ? path.join(packageRoot, "docs", "reference", "templates") : null,
|
|
22
|
+
cwd ? path.resolve(cwd, "docs", "reference", "templates") : null,
|
|
23
|
+
FALLBACK_TEMPLATE_DIR,
|
|
24
|
+
].filter(Boolean);
|
|
25
|
+
for (const candidate of candidates) {
|
|
26
|
+
if (await pathExists(candidate)) {
|
|
27
|
+
cachedTemplateDir = candidate;
|
|
28
|
+
return candidate;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
cachedTemplateDir = candidates[0] ?? FALLBACK_TEMPLATE_DIR;
|
|
32
|
+
return cachedTemplateDir;
|
|
33
|
+
})();
|
|
34
|
+
try {
|
|
35
|
+
return await resolvingTemplateDir;
|
|
36
|
+
}
|
|
37
|
+
finally {
|
|
38
|
+
resolvingTemplateDir = undefined;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
export function resetWorkspaceTemplateDirCache() {
|
|
42
|
+
cachedTemplateDir = undefined;
|
|
43
|
+
resolvingTemplateDir = undefined;
|
|
44
|
+
}
|