@capybara-hq/kernel 0.1.0-rc.2 → 0.1.0-rc.4
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/dist/admin/admin.controller.d.ts +9 -4
- package/dist/admin/admin.controller.js +13 -4
- package/dist/admin/extensions.controller.d.ts +8 -1
- package/dist/admin/extensions.controller.js +22 -2
- package/dist/agents/agent-lookup.d.ts +3 -0
- package/dist/agents/agent-lookup.js +20 -2
- package/dist/agents/agent-profile.service.d.ts +29 -0
- package/dist/agents/agent-profile.service.js +117 -0
- package/dist/agents/agents.controller.d.ts +93 -3
- package/dist/agents/agents.controller.js +114 -4
- package/dist/agents/agents.module.js +6 -2
- package/dist/agents/agents.service.d.ts +13 -5
- package/dist/agents/agents.service.js +49 -13
- package/dist/agents/definition.d.ts +35 -8
- package/dist/agents/definition.js +203 -17
- package/dist/agents/instruction-files.d.ts +60 -0
- package/dist/agents/instruction-files.js +111 -0
- package/dist/agents/models.controller.d.ts +9 -3
- package/dist/agents/models.controller.js +19 -4
- package/dist/agents/profile.d.ts +96 -0
- package/dist/agents/profile.js +51 -0
- package/dist/agents/readiness.controller.d.ts +26 -0
- package/dist/agents/readiness.controller.js +56 -0
- package/dist/agents/templates.js +20 -5
- package/dist/background/background.controller.d.ts +38 -0
- package/dist/background/background.controller.js +87 -0
- package/dist/background/background.module.d.ts +10 -0
- package/dist/background/background.module.js +32 -0
- package/dist/background/finish.d.ts +43 -0
- package/dist/background/finish.js +94 -0
- package/dist/background/launch-lock.d.ts +14 -0
- package/dist/background/launch-lock.js +39 -0
- package/dist/background/launch.d.ts +36 -0
- package/dist/background/launch.js +70 -0
- package/dist/background/poll.job.d.ts +53 -0
- package/dist/background/poll.job.js +182 -0
- package/dist/background/render.d.ts +23 -0
- package/dist/background/render.js +48 -0
- package/dist/background/session.d.ts +37 -0
- package/dist/background/session.js +66 -0
- package/dist/background/status.d.ts +35 -0
- package/dist/background/status.js +57 -0
- package/dist/background/stop.d.ts +62 -0
- package/dist/background/stop.js +225 -0
- package/dist/background/store.d.ts +150 -0
- package/dist/background/store.js +351 -0
- package/dist/background/store.module.d.ts +6 -0
- package/dist/background/store.module.js +22 -0
- package/dist/background/tasks.service.d.ts +67 -0
- package/dist/background/tasks.service.js +186 -0
- package/dist/background/wake-rules.d.ts +57 -0
- package/dist/background/wake-rules.js +83 -0
- package/dist/background/wake.d.ts +28 -0
- package/dist/background/wake.js +57 -0
- package/dist/catalog/catalog-content.js +4 -1
- package/dist/catalog/claude/agents.js +15 -10
- package/dist/catalog/marketplaces.service.d.ts +1 -1
- package/dist/catalog/plugin-import.js +1 -1
- package/dist/catalog/plugin-upgrade.js +1 -1
- package/dist/channels/cards.d.ts +8 -2
- package/dist/channels/cards.js +17 -9
- package/dist/channels/connections.service.d.ts +16 -1
- package/dist/channels/connections.service.js +38 -4
- package/dist/channels/threads.d.ts +5 -0
- package/dist/channels/threads.js +8 -0
- package/dist/config/schema.d.ts +18 -0
- package/dist/config/schema.js +104 -2
- package/dist/conversations/access.js +2 -0
- package/dist/conversations/artifacts.d.ts +1 -1
- package/dist/conversations/artifacts.js +1 -1
- package/dist/conversations/attachments.service.d.ts +30 -0
- package/dist/conversations/attachments.service.js +130 -5
- package/dist/conversations/conversations.controller.d.ts +36 -5
- package/dist/conversations/conversations.controller.js +62 -12
- package/dist/conversations/conversations.module.js +3 -0
- package/dist/conversations/conversations.service.d.ts +44 -2
- package/dist/conversations/conversations.service.js +140 -12
- package/dist/conversations/event-log.d.ts +12 -1
- package/dist/conversations/event-log.js +29 -1
- package/dist/conversations/events.d.ts +81 -3
- package/dist/conversations/events.js +83 -16
- package/dist/conversations/queue.d.ts +3 -1
- package/dist/conversations/queue.js +13 -2
- package/dist/conversations/queue.service.js +3 -1
- package/dist/conversations/titles.d.ts +7 -0
- package/dist/conversations/titles.js +15 -0
- package/dist/db/kernel-schema.d.ts +60 -4
- package/dist/db/pool.d.ts +5 -0
- package/dist/db/pool.js +3 -0
- package/dist/errors.d.ts +8 -0
- package/dist/errors.js +8 -0
- package/dist/evals/recorded-tools.d.ts +27 -1
- package/dist/evals/recorded-tools.js +85 -10
- package/dist/evals/run-replay.d.ts +10 -2
- package/dist/evals/run-replay.js +49 -12
- package/dist/evals/step-replay.js +12 -6
- package/dist/evals/trajectory.d.ts +2 -2
- package/dist/evals/trajectory.js +1 -1
- package/dist/extensions/admin-ops.js +2 -0
- package/dist/extensions/admin-view.d.ts +3 -1
- package/dist/extensions/admin-view.js +10 -2
- package/dist/extensions/blobs.js +1 -0
- package/dist/extensions/config-issues.d.ts +13 -1
- package/dist/extensions/config-issues.js +22 -5
- package/dist/extensions/config-json-schema.d.ts +43 -7
- package/dist/extensions/config-json-schema.js +124 -58
- package/dist/extensions/deployment-config-store.d.ts +6 -0
- package/dist/extensions/deployment-config.d.ts +50 -3
- package/dist/extensions/deployment-config.js +125 -28
- package/dist/extensions/display-name.d.ts +22 -0
- package/dist/extensions/display-name.js +77 -0
- package/dist/extensions/extensions.module.js +6 -0
- package/dist/extensions/host.d.ts +26 -1
- package/dist/extensions/host.js +82 -9
- package/dist/extensions/org-config.controller.d.ts +11 -3
- package/dist/extensions/org-config.controller.js +14 -6
- package/dist/extensions/org-config.d.ts +6 -0
- package/dist/extensions/org-config.js +12 -13
- package/dist/extensions/package.d.ts +14 -1
- package/dist/extensions/package.js +51 -2
- package/dist/extensions/permission-view.d.ts +3 -0
- package/dist/extensions/point-defaults.controller.d.ts +34 -0
- package/dist/extensions/point-defaults.controller.js +71 -0
- package/dist/extensions/point-defaults.d.ts +64 -0
- package/dist/extensions/point-defaults.js +206 -0
- package/dist/extensions/registry.d.ts +1 -1
- package/dist/extensions/registry.js +2 -0
- package/dist/http/api.module.js +8 -0
- package/dist/http/nest-logger.d.ts +6 -5
- package/dist/http/nest-logger.js +24 -10
- package/dist/identity/auth.controller.js +9 -5
- package/dist/identity/cookies.d.ts +20 -5
- package/dist/identity/cookies.js +44 -6
- package/dist/identity/me.controller.d.ts +5 -1
- package/dist/identity/me.controller.js +12 -3
- package/dist/identity/sessions.d.ts +12 -0
- package/dist/identity/sessions.js +45 -0
- package/dist/identity/settings.js +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/infra/config/kernel-config.service.js +6 -0
- package/dist/infra/database/database.module.js +1 -0
- package/dist/infra/events/kernel-events.d.ts +8 -0
- package/dist/infra/lifecycle/process-guards.js +4 -0
- package/dist/infra/logging/logging.module.d.ts +4 -2
- package/dist/infra/logging/logging.module.js +24 -6
- package/dist/infra/queue/redis-connection.d.ts +6 -0
- package/dist/infra/queue/redis-connection.js +7 -0
- package/dist/infra/redis/redis.module.js +6 -2
- package/dist/infra/tokens.d.ts +6 -1
- package/dist/infra/tokens.js +6 -1
- package/dist/lifecycle/kernel-lifecycle.js +5 -0
- package/dist/log.d.ts +13 -1
- package/dist/log.js +93 -17
- package/dist/models/purposes.d.ts +23 -0
- package/dist/models/purposes.js +31 -10
- package/dist/orgs/offboarding.d.ts +3 -1
- package/dist/orgs/offboarding.js +26 -16
- package/dist/orgs/settings.service.d.ts +7 -2
- package/dist/orgs/settings.service.js +15 -4
- package/dist/roles/worker.module.js +6 -0
- package/dist/runtime/context/build.d.ts +15 -13
- package/dist/runtime/context/build.js +45 -27
- package/dist/runtime/context/claude-tools.d.ts +3 -1
- package/dist/runtime/context/claude-tools.js +12 -12
- package/dist/runtime/context/compaction.js +4 -0
- package/dist/runtime/context/legacy-text.d.ts +22 -0
- package/dist/runtime/context/legacy-text.js +37 -0
- package/dist/runtime/context/skills.d.ts +29 -11
- package/dist/runtime/context/skills.js +37 -30
- package/dist/runtime/langgraph-loop.js +3 -2
- package/dist/runtime/loop.d.ts +5 -4
- package/dist/runtime/maintenance.d.ts +4 -2
- package/dist/runtime/maintenance.js +17 -5
- package/dist/runtime/model-call.d.ts +17 -1
- package/dist/runtime/model-call.js +4 -3
- package/dist/runtime/providers.d.ts +6 -0
- package/dist/runtime/providers.js +8 -0
- package/dist/runtime/run-finish.d.ts +1 -1
- package/dist/runtime/run-queue.d.ts +28 -5
- package/dist/runtime/run-queue.js +131 -35
- package/dist/runtime/run-worker.d.ts +2 -2
- package/dist/runtime/run-worker.js +20 -7
- package/dist/runtime/runtime.module.js +8 -3
- package/dist/runtime/step-log.d.ts +6 -0
- package/dist/runtime/step-log.js +16 -2
- package/dist/runtime/subagents/definition.d.ts +1 -6
- package/dist/runtime/subagents/definition.js +14 -13
- package/dist/runtime/subagents/dispatch.d.ts +2 -2
- package/dist/runtime/subagents/dispatch.js +2 -2
- package/dist/runtime/subagents/org-agents.js +2 -1
- package/dist/runtime/subagents/roster.d.ts +1 -1
- package/dist/runtime/subagents/roster.js +1 -1
- package/dist/runtime/subagents/skill-fork.d.ts +2 -2
- package/dist/runtime/subagents/skill-fork.js +2 -2
- package/dist/runtime/subagents/subagents.service.d.ts +3 -3
- package/dist/runtime/subagents/subagents.service.js +3 -3
- package/dist/runtime/usage-report.d.ts +2 -1
- package/dist/runtime/usage-report.js +2 -1
- package/dist/runtime/waits.d.ts +13 -7
- package/dist/runtime/waits.js +42 -16
- package/dist/sandbox/sandbox.module.js +6 -1
- package/dist/sandbox/sandbox.service.d.ts +61 -3
- package/dist/sandbox/sandbox.service.js +141 -7
- package/dist/skills/catalog.d.ts +4 -4
- package/dist/skills/catalog.js +4 -4
- package/dist/skills/changes.service.d.ts +2 -2
- package/dist/skills/changes.service.js +5 -4
- package/dist/skills/invocation-keys.d.ts +1 -1
- package/dist/skills/invocation-keys.js +1 -1
- package/dist/skills/invoke.d.ts +1 -1
- package/dist/skills/invoke.js +5 -4
- package/dist/tools/approvals.service.d.ts +6 -0
- package/dist/tools/approvals.service.js +21 -1
- package/dist/tools/builtin-names.d.ts +91 -0
- package/dist/tools/builtin-names.js +143 -0
- package/dist/tools/builtins/agent.d.ts +7 -7
- package/dist/tools/builtins/agent.js +7 -11
- package/dist/tools/builtins/ask-user.d.ts +1 -1
- package/dist/tools/builtins/ask-user.js +2 -2
- package/dist/tools/builtins/builtin-tools.d.ts +17 -3
- package/dist/tools/builtins/builtin-tools.js +36 -4
- package/dist/tools/builtins/read-tool-output.d.ts +1 -1
- package/dist/tools/builtins/read-tool-output.js +2 -2
- package/dist/tools/builtins/sandbox/bash.d.ts +4 -4
- package/dist/tools/builtins/sandbox/bash.js +259 -29
- package/dist/tools/builtins/sandbox/common.d.ts +30 -7
- package/dist/tools/builtins/sandbox/common.js +9 -5
- package/dist/tools/builtins/sandbox/deliver.d.ts +1 -1
- package/dist/tools/builtins/sandbox/deliver.js +12 -12
- package/dist/tools/builtins/sandbox/edit.d.ts +1 -1
- package/dist/tools/builtins/sandbox/edit.js +41 -30
- package/dist/tools/builtins/sandbox/file-state.d.ts +34 -0
- package/dist/tools/builtins/sandbox/file-state.js +34 -0
- package/dist/tools/builtins/sandbox/glob-match.d.ts +1 -1
- package/dist/tools/builtins/sandbox/glob-match.js +1 -1
- package/dist/tools/builtins/sandbox/glob.d.ts +1 -1
- package/dist/tools/builtins/sandbox/glob.js +4 -4
- package/dist/tools/builtins/sandbox/grep.d.ts +7 -4
- package/dist/tools/builtins/sandbox/grep.js +147 -30
- package/dist/tools/builtins/sandbox/index.d.ts +3 -1
- package/dist/tools/builtins/sandbox/index.js +7 -1
- package/dist/tools/builtins/sandbox/read.d.ts +2 -2
- package/dist/tools/builtins/sandbox/read.js +21 -14
- package/dist/tools/builtins/sandbox/task-output.d.ts +63 -0
- package/dist/tools/builtins/sandbox/task-output.js +304 -0
- package/dist/tools/builtins/sandbox/task-stop.d.ts +10 -0
- package/dist/tools/builtins/sandbox/task-stop.js +112 -0
- package/dist/tools/builtins/sandbox/write.d.ts +1 -1
- package/dist/tools/builtins/sandbox/write.js +37 -33
- package/dist/tools/builtins/skill-load.d.ts +3 -3
- package/dist/tools/builtins/skill-load.js +32 -16
- package/dist/tools/builtins/skill-write.d.ts +4 -4
- package/dist/tools/builtins/skill-write.js +10 -10
- package/dist/tools/builtins/tool-search.d.ts +13 -9
- package/dist/tools/builtins/tool-search.js +25 -14
- package/dist/tools/builtins/web/errors.d.ts +8 -0
- package/dist/tools/builtins/web/errors.js +53 -0
- package/dist/tools/builtins/web/extract.d.ts +62 -0
- package/dist/tools/builtins/web/extract.js +267 -0
- package/dist/tools/builtins/web/fetch.d.ts +55 -0
- package/dist/tools/builtins/web/fetch.js +174 -0
- package/dist/tools/builtins/web/index.d.ts +13 -0
- package/dist/tools/builtins/web/index.js +12 -0
- package/dist/tools/builtins/web/page-cache.d.ts +25 -0
- package/dist/tools/builtins/web/page-cache.js +77 -0
- package/dist/tools/builtins/web/search.d.ts +25 -0
- package/dist/tools/builtins/web/search.js +209 -0
- package/dist/tools/builtins/web/url.d.ts +17 -0
- package/dist/tools/builtins/web/url.js +43 -0
- package/dist/tools/connectors.service.js +4 -4
- package/dist/tools/display-names.d.ts +9 -0
- package/dist/tools/display-names.js +24 -0
- package/dist/tools/drift.js +5 -5
- package/dist/tools/elicitation.js +1 -1
- package/dist/tools/info.d.ts +20 -4
- package/dist/tools/info.js +55 -32
- package/dist/tools/legacy-data.d.ts +34 -0
- package/dist/tools/legacy-data.js +76 -0
- package/dist/tools/legacy-keys.d.ts +51 -0
- package/dist/tools/legacy-keys.js +115 -0
- package/dist/tools/naming.d.ts +1 -5
- package/dist/tools/naming.js +1 -7
- package/dist/tools/oauth/flow-paths.d.ts +1 -1
- package/dist/tools/oauth/flow-paths.js +1 -1
- package/dist/tools/outputs.js +1 -1
- package/dist/tools/pipeline.d.ts +13 -7
- package/dist/tools/pipeline.js +112 -39
- package/dist/tools/policy.d.ts +1 -14
- package/dist/tools/policy.js +13 -19
- package/dist/tools/questions.controller.d.ts +1 -1
- package/dist/tools/questions.controller.js +1 -1
- package/dist/tools/questions.service.d.ts +1 -1
- package/dist/tools/registry.d.ts +38 -24
- package/dist/tools/registry.js +54 -47
- package/dist/tools/resources.d.ts +1 -1
- package/dist/tools/resources.js +1 -1
- package/dist/tools/tools.module.js +13 -1
- package/dist/tools/validate.js +1 -1
- package/package.json +3 -3
- package/src/migrations/0063_tool_keys_claude_code.sql +220 -0
- package/src/migrations/0064_account_last_org.sql +7 -0
- package/src/migrations/0065_conversation_archive.sql +8 -0
- package/src/migrations/0066_extension_display_name.sql +4 -0
- package/src/migrations/0067_agent_profiles.sql +20 -0
- package/src/migrations/0068_agent_avatar_uploads.sql +7 -0
- package/src/migrations/0069_attachments_agent_idx.sql +3 -0
- package/src/migrations/0070_background_tasks.sql +37 -0
- package/src/migrations/0071_background_tasks_reserve.sql +6 -0
- package/src/migrations/0072_background_tasks_stopping.sql +5 -0
- package/src/migrations/0073_org_extension_point_defaults.sql +11 -0
- package/dist/tools/builtins/sandbox/names.d.ts +0 -7
- package/dist/tools/builtins/sandbox/names.js +0 -20
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
2
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
+
};
|
|
7
|
+
var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
8
|
+
return function (target, key) { decorator(target, key, paramIndex); }
|
|
9
|
+
};
|
|
10
|
+
import { createHash } from "node:crypto";
|
|
11
|
+
import { Inject, Injectable } from "@nestjs/common";
|
|
12
|
+
import { CacheService } from "../../../infra/cache/cache.service.js";
|
|
13
|
+
import { KernelConfigService } from "../../../infra/config/kernel-config.service.js";
|
|
14
|
+
/**
|
|
15
|
+
* The cache key of a fetched page: per org, provider and URL (the URL hashed, it may be long).
|
|
16
|
+
* `CacheService` stores it under `cache:<key>`.
|
|
17
|
+
*/
|
|
18
|
+
export const webPageKey = (orgId, provider, url) => `web_page:${orgId}:${provider}:${createHash("sha256").update(url).digest("hex")}`;
|
|
19
|
+
/** A stored value read back as a page, or null when it is not one. */
|
|
20
|
+
function asPage(raw) {
|
|
21
|
+
let v;
|
|
22
|
+
try {
|
|
23
|
+
v = JSON.parse(raw);
|
|
24
|
+
}
|
|
25
|
+
catch {
|
|
26
|
+
return null;
|
|
27
|
+
}
|
|
28
|
+
if (v === null || typeof v !== "object")
|
|
29
|
+
return null;
|
|
30
|
+
const p = v;
|
|
31
|
+
if (typeof p.finalUrl !== "string" || typeof p.markdown !== "string")
|
|
32
|
+
return null;
|
|
33
|
+
return {
|
|
34
|
+
finalUrl: p.finalUrl,
|
|
35
|
+
markdown: p.markdown,
|
|
36
|
+
...(typeof p.title === "string" && { title: p.title }),
|
|
37
|
+
...(typeof p.contentType === "string" && { contentType: p.contentType }),
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* The `WebFetch` page cache (web tools spec §10): the provider's page (never the extraction,
|
|
42
|
+
* which depends on the prompt) in Redis under {@link webPageKey}, for `web.fetch.cacheSeconds`
|
|
43
|
+
* (read at every call; 0 turns the cache off). It saves the org's provider quota when an agent
|
|
44
|
+
* reads the same page twice. Through `CacheService`, so it fails open: a Redis error is logged and
|
|
45
|
+
* behaves like a miss or a skipped write. (Not named `*Cache`: that name is `infra/cache`'s.)
|
|
46
|
+
*/
|
|
47
|
+
let WebPages = class WebPages {
|
|
48
|
+
cache;
|
|
49
|
+
config;
|
|
50
|
+
constructor(cache, config) {
|
|
51
|
+
this.cache = cache;
|
|
52
|
+
this.config = config;
|
|
53
|
+
}
|
|
54
|
+
ttl() {
|
|
55
|
+
return this.config.get().web.fetch.cacheSeconds;
|
|
56
|
+
}
|
|
57
|
+
/** The cached page of `url`, or null on a miss, when the cache is off or on a Redis error. */
|
|
58
|
+
async get(orgId, provider, url) {
|
|
59
|
+
if (this.ttl() <= 0)
|
|
60
|
+
return null;
|
|
61
|
+
const raw = await this.cache.get(webPageKey(orgId, provider, url));
|
|
62
|
+
return raw === undefined ? null : asPage(raw);
|
|
63
|
+
}
|
|
64
|
+
/** Caches `page` for `url`; nothing when the cache is off. */
|
|
65
|
+
async set(orgId, provider, url, page) {
|
|
66
|
+
const ttl = this.ttl();
|
|
67
|
+
if (ttl <= 0)
|
|
68
|
+
return;
|
|
69
|
+
await this.cache.setJson(webPageKey(orgId, provider, url), page, ttl);
|
|
70
|
+
}
|
|
71
|
+
};
|
|
72
|
+
WebPages = __decorate([
|
|
73
|
+
Injectable(),
|
|
74
|
+
__param(0, Inject(CacheService)),
|
|
75
|
+
__param(1, Inject(KernelConfigService))
|
|
76
|
+
], WebPages);
|
|
77
|
+
export { WebPages };
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { type ToolSpec } from "@capybara-hq/plugin-sdk";
|
|
2
|
+
import type { ExtensionPointDefaults } from "../../../extensions/point-defaults.js";
|
|
3
|
+
import type { KernelConfigService } from "../../../infra/config/kernel-config.service.js";
|
|
4
|
+
import type { BuiltinTool } from "../../registry.js";
|
|
5
|
+
/**
|
|
6
|
+
* The fixed spec (web tools spec §3.1). No date and nothing per org or provider: `specHash` stays
|
|
7
|
+
* the same across days and providers, so remembered grants survive both and replays match the log.
|
|
8
|
+
* The date is the first line of every result instead.
|
|
9
|
+
*/
|
|
10
|
+
export declare const WEB_SEARCH_SPEC: ToolSpec;
|
|
11
|
+
/** What {@link webSearchTool} needs. */
|
|
12
|
+
export interface WebSearchDeps {
|
|
13
|
+
points: Pick<ExtensionPointDefaults, "resolve">;
|
|
14
|
+
config: Pick<KernelConfigService, "get">;
|
|
15
|
+
/** The clock of the result's date line (tests fix it). */
|
|
16
|
+
now?: () => Date;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* The builtin `WebSearch` (web tools spec §3.1): searches with the org's `web-search@1` provider
|
|
20
|
+
* (`ExtensionPointDefaults`, resolved per call and per step, never cached), asking it for
|
|
21
|
+
* `web.search.maxResults` results with the domain lists as hints and the org's config, then
|
|
22
|
+
* filters the results again. Default `ask`; unavailable when the org has no provider or several
|
|
23
|
+
* without a default.
|
|
24
|
+
*/
|
|
25
|
+
export declare function webSearchTool(deps: WebSearchDeps): BuiltinTool;
|
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
import { domainToASCII } from "node:url";
|
|
2
|
+
import { ToolError, } from "@capybara-hq/plugin-sdk";
|
|
3
|
+
import { BUILTIN } from "../../builtin-names.js";
|
|
4
|
+
import { webToolError } from "./errors.js";
|
|
5
|
+
/** The extension point name (without the major) the provider is resolved from. */
|
|
6
|
+
const POINT = "web-search";
|
|
7
|
+
/**
|
|
8
|
+
* The fixed spec (web tools spec §3.1). No date and nothing per org or provider: `specHash` stays
|
|
9
|
+
* the same across days and providers, so remembered grants survive both and replays match the log.
|
|
10
|
+
* The date is the first line of every result instead.
|
|
11
|
+
*/
|
|
12
|
+
export const WEB_SEARCH_SPEC = {
|
|
13
|
+
name: BUILTIN.WebSearch,
|
|
14
|
+
// Display only (the tool row; not in the fingerprint, never sent to the model).
|
|
15
|
+
keyArgs: ["query"],
|
|
16
|
+
description: "Search the web and get a list of results with title, URL and a short snippet. Use it for " +
|
|
17
|
+
"information newer than your training data, or to check whether something you know is still " +
|
|
18
|
+
"current. Then use WebFetch to read the pages you need. Do not use it for questions you can " +
|
|
19
|
+
"answer reliably without the web. Cite the sources you use.",
|
|
20
|
+
inputSchema: {
|
|
21
|
+
type: "object",
|
|
22
|
+
properties: {
|
|
23
|
+
query: {
|
|
24
|
+
type: "string",
|
|
25
|
+
minLength: 2,
|
|
26
|
+
maxLength: 500,
|
|
27
|
+
description: "The search query.",
|
|
28
|
+
},
|
|
29
|
+
allowed_domains: {
|
|
30
|
+
type: "array",
|
|
31
|
+
items: { type: "string", minLength: 1, maxLength: 253 },
|
|
32
|
+
maxItems: 50,
|
|
33
|
+
description: "Only return results from these domains (hostnames such as example.com; subdomains " +
|
|
34
|
+
"are included). Do not combine with blocked_domains.",
|
|
35
|
+
},
|
|
36
|
+
blocked_domains: {
|
|
37
|
+
type: "array",
|
|
38
|
+
items: { type: "string", minLength: 1, maxLength: 253 },
|
|
39
|
+
maxItems: 50,
|
|
40
|
+
description: "Never return results from these domains (hostnames such as example.com; subdomains " +
|
|
41
|
+
"are included). Do not combine with allowed_domains.",
|
|
42
|
+
},
|
|
43
|
+
},
|
|
44
|
+
required: ["query"],
|
|
45
|
+
additionalProperties: false,
|
|
46
|
+
},
|
|
47
|
+
annotations: { readOnlyHint: true, openWorldHint: true },
|
|
48
|
+
};
|
|
49
|
+
/** The last line of a result with entries (Claude Code tells the model to list its sources). */
|
|
50
|
+
const CITE_LINE = "Cite the sources you use as markdown links in your answer.";
|
|
51
|
+
/** Why the tool is unavailable in an org (web tools spec §3.4; English, actionable). */
|
|
52
|
+
function unavailableText(reason) {
|
|
53
|
+
if (reason === "none") {
|
|
54
|
+
return "No web search provider is enabled in this organization; ask an org admin to enable one.";
|
|
55
|
+
}
|
|
56
|
+
return "Several web search providers are enabled and none is the default; ask an org admin to choose one in the organization settings.";
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* A domain entry as a bare lowercase ASCII hostname: tolerates a scheme, a path, a port, a leading
|
|
60
|
+
* `*.` / `.` and a trailing dot; a Unicode (IDN) name becomes its punycode form, as result hosts
|
|
61
|
+
* are (WHATWG URL parsing). Empty when nothing is left.
|
|
62
|
+
*/
|
|
63
|
+
function normalizeDomain(entry) {
|
|
64
|
+
let d = entry.trim().toLowerCase();
|
|
65
|
+
d = d.replace(/^[a-z][a-z0-9+.-]*:\/\//, "");
|
|
66
|
+
d = d.replace(/[/?#].*$/, "").replace(/:\d+$/, "");
|
|
67
|
+
d = d.replace(/^\*\./, "").replace(/^\.+/, "").replace(/\.+$/, "");
|
|
68
|
+
if (d === "")
|
|
69
|
+
return d;
|
|
70
|
+
// domainToASCII is "" for a name IDNA rejects: keep the entry as given (it matches no host)
|
|
71
|
+
return domainToASCII(d) || d;
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* A domain list normalized; undefined when absent or empty (no filter). A list whose entries all
|
|
75
|
+
* normalize to nothing stays an empty list, which no host matches.
|
|
76
|
+
*/
|
|
77
|
+
const normalizeDomains = (list) => list === undefined || list.length === 0
|
|
78
|
+
? undefined
|
|
79
|
+
: [...new Set(list.map(normalizeDomain).filter((d) => d !== ""))];
|
|
80
|
+
/** Whether `host` is `domain` or one of its subdomains. */
|
|
81
|
+
const covers = (domain, host) => host === domain || host.endsWith(`.${domain}`);
|
|
82
|
+
const oneLine = (s) => s.replace(/\s+/g, " ").trim();
|
|
83
|
+
/**
|
|
84
|
+
* The provider's results the model may see (web tools spec §7.2): an absolute http(s) URL, a
|
|
85
|
+
* non-empty title, each URL once, within the domain lists, at most `max`. The kernel filters even
|
|
86
|
+
* when the provider honored the domain hints.
|
|
87
|
+
*/
|
|
88
|
+
function usable(results, allowed, blocked, max) {
|
|
89
|
+
const seen = new Set();
|
|
90
|
+
const out = [];
|
|
91
|
+
for (const r of results) {
|
|
92
|
+
if (out.length >= max)
|
|
93
|
+
break;
|
|
94
|
+
if (typeof r?.url !== "string" || typeof r.title !== "string")
|
|
95
|
+
continue;
|
|
96
|
+
const title = oneLine(r.title);
|
|
97
|
+
if (title === "")
|
|
98
|
+
continue;
|
|
99
|
+
let u;
|
|
100
|
+
try {
|
|
101
|
+
// no base: a relative URL throws
|
|
102
|
+
u = new URL(r.url.trim());
|
|
103
|
+
}
|
|
104
|
+
catch {
|
|
105
|
+
continue;
|
|
106
|
+
}
|
|
107
|
+
if (u.protocol !== "https:" && u.protocol !== "http:")
|
|
108
|
+
continue;
|
|
109
|
+
const host = u.hostname.toLowerCase().replace(/\.$/, "");
|
|
110
|
+
if (host === "")
|
|
111
|
+
continue;
|
|
112
|
+
if (allowed !== undefined && !allowed.some((d) => covers(d, host)))
|
|
113
|
+
continue;
|
|
114
|
+
if (blocked?.some((d) => covers(d, host)))
|
|
115
|
+
continue;
|
|
116
|
+
if (seen.has(u.href))
|
|
117
|
+
continue;
|
|
118
|
+
seen.add(u.href);
|
|
119
|
+
const date = typeof r.publishedAt === "string" ? /^\d{4}-\d{2}-\d{2}/.exec(r.publishedAt.trim()) : null;
|
|
120
|
+
const snippet = typeof r.snippet === "string" ? oneLine(r.snippet) : "";
|
|
121
|
+
out.push({
|
|
122
|
+
title,
|
|
123
|
+
url: u.href,
|
|
124
|
+
...(date !== null && { date: date[0] }),
|
|
125
|
+
...(snippet !== "" && { snippet }),
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
return out;
|
|
129
|
+
}
|
|
130
|
+
/** The model-visible result (web tools spec §3.1): the date line first, then the entries. */
|
|
131
|
+
function resultText(day, entries) {
|
|
132
|
+
const head = `Search date: ${day} (UTC).`;
|
|
133
|
+
if (entries.length === 0)
|
|
134
|
+
return `${head}\n\nNo results.`;
|
|
135
|
+
const blocks = entries.map((e, i) => [
|
|
136
|
+
`${i + 1}. ${e.title}`,
|
|
137
|
+
` URL: ${e.url}`,
|
|
138
|
+
...(e.date !== undefined ? [` Published: ${e.date}`] : []),
|
|
139
|
+
...(e.snippet !== undefined ? [` ${e.snippet}`] : []),
|
|
140
|
+
].join("\n"));
|
|
141
|
+
return [head, ...blocks, CITE_LINE].join("\n\n");
|
|
142
|
+
}
|
|
143
|
+
/** The query in the display summary: one line, at most this many code points. */
|
|
144
|
+
const DISPLAY_QUERY_MAX = 120;
|
|
145
|
+
function displayQuery(query) {
|
|
146
|
+
const cps = [...oneLine(query)];
|
|
147
|
+
return cps.length > DISPLAY_QUERY_MAX
|
|
148
|
+
? `${cps.slice(0, DISPLAY_QUERY_MAX - 1).join("")}…`
|
|
149
|
+
: cps.join("");
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* The builtin `WebSearch` (web tools spec §3.1): searches with the org's `web-search@1` provider
|
|
153
|
+
* (`ExtensionPointDefaults`, resolved per call and per step, never cached), asking it for
|
|
154
|
+
* `web.search.maxResults` results with the domain lists as hints and the org's config, then
|
|
155
|
+
* filters the results again. Default `ask`; unavailable when the org has no provider or several
|
|
156
|
+
* without a default.
|
|
157
|
+
*/
|
|
158
|
+
export function webSearchTool(deps) {
|
|
159
|
+
const now = deps.now ?? (() => new Date());
|
|
160
|
+
return {
|
|
161
|
+
spec: WEB_SEARCH_SPEC,
|
|
162
|
+
defaultPolicy: "ask",
|
|
163
|
+
async unavailable({ orgId }) {
|
|
164
|
+
const r = await deps.points.resolve(orgId, POINT);
|
|
165
|
+
return r.ok ? null : unavailableText(r.reason);
|
|
166
|
+
},
|
|
167
|
+
async run(input, ctx) {
|
|
168
|
+
const { query, allowed_domains, blocked_domains } = input;
|
|
169
|
+
if (allowed_domains !== undefined && blocked_domains !== undefined) {
|
|
170
|
+
throw new ToolError("Pass either allowed_domains or blocked_domains, not both; call WebSearch again with one of them.");
|
|
171
|
+
}
|
|
172
|
+
const allowed = normalizeDomains(allowed_domains);
|
|
173
|
+
const blocked = normalizeDomains(blocked_domains);
|
|
174
|
+
// the provider may have changed since the step resolved the tool: resolve again
|
|
175
|
+
const resolved = await deps.points.resolve(ctx.orgId, POINT);
|
|
176
|
+
if (!resolved.ok)
|
|
177
|
+
throw new ToolError(unavailableText(resolved.reason));
|
|
178
|
+
const max = deps.config.get().web.search.maxResults;
|
|
179
|
+
const day = now().toISOString().slice(0, 10);
|
|
180
|
+
let results;
|
|
181
|
+
try {
|
|
182
|
+
const out = await resolved.impl.search({
|
|
183
|
+
query,
|
|
184
|
+
...(allowed !== undefined && allowed.length > 0 && { allowedDomains: allowed }),
|
|
185
|
+
...(blocked !== undefined && blocked.length > 0 && { blockedDomains: blocked }),
|
|
186
|
+
maxResults: max,
|
|
187
|
+
orgConfig: resolved.orgConfig,
|
|
188
|
+
signal: ctx.signal,
|
|
189
|
+
});
|
|
190
|
+
results = Array.isArray(out?.results) ? out.results : [];
|
|
191
|
+
}
|
|
192
|
+
catch (e) {
|
|
193
|
+
webToolError(e, "search");
|
|
194
|
+
}
|
|
195
|
+
const entries = usable(results, allowed, blocked, max);
|
|
196
|
+
const q = displayQuery(query);
|
|
197
|
+
const n = entries.length;
|
|
198
|
+
return {
|
|
199
|
+
content: [{ type: "text", text: resultText(day, entries) }],
|
|
200
|
+
display: {
|
|
201
|
+
summary: {
|
|
202
|
+
zh: `搜索网页:${q}(${n} 条结果)`,
|
|
203
|
+
en: `Searched the web: ${q} (${n} result${n === 1 ? "" : "s"})`,
|
|
204
|
+
},
|
|
205
|
+
},
|
|
206
|
+
};
|
|
207
|
+
},
|
|
208
|
+
};
|
|
209
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/** The longest URL `WebFetch` accepts, in characters (Claude Code's limit; web tools spec §7.1). */
|
|
2
|
+
export declare const MAX_FETCH_URL_CHARS = 2000;
|
|
3
|
+
/** The outcome of {@link normalizeFetchUrl}: the URL to fetch, or a model-visible error. */
|
|
4
|
+
export type FetchUrlCheck = {
|
|
5
|
+
ok: true;
|
|
6
|
+
url: string;
|
|
7
|
+
} | {
|
|
8
|
+
ok: false;
|
|
9
|
+
error: string;
|
|
10
|
+
};
|
|
11
|
+
/**
|
|
12
|
+
* A `WebFetch` URL checked and normalized (web tools spec §7.1): absolute http(s), `http:`
|
|
13
|
+
* upgraded to `https:`, no user name or password, at most {@link MAX_FETCH_URL_CHARS} characters
|
|
14
|
+
* (before and after normalization), and a host that can name a public internet host. Pure, no DNS: a public name that resolves to a
|
|
15
|
+
* private address is the provider's to refuse. Errors are English and tell the model what to pass.
|
|
16
|
+
*/
|
|
17
|
+
export declare function normalizeFetchUrl(raw: string): FetchUrlCheck;
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { isPublicHostname } from "@capybara-hq/plugin-sdk";
|
|
2
|
+
/** The longest URL `WebFetch` accepts, in characters (Claude Code's limit; web tools spec §7.1). */
|
|
3
|
+
export const MAX_FETCH_URL_CHARS = 2000;
|
|
4
|
+
const fail = (error) => ({ ok: false, error });
|
|
5
|
+
/**
|
|
6
|
+
* A `WebFetch` URL checked and normalized (web tools spec §7.1): absolute http(s), `http:`
|
|
7
|
+
* upgraded to `https:`, no user name or password, at most {@link MAX_FETCH_URL_CHARS} characters
|
|
8
|
+
* (before and after normalization), and a host that can name a public internet host. Pure, no DNS: a public name that resolves to a
|
|
9
|
+
* private address is the provider's to refuse. Errors are English and tell the model what to pass.
|
|
10
|
+
*/
|
|
11
|
+
export function normalizeFetchUrl(raw) {
|
|
12
|
+
const input = raw.trim();
|
|
13
|
+
// a cheap guard before parsing; the normalized URL is checked again below
|
|
14
|
+
if (input.length > MAX_FETCH_URL_CHARS) {
|
|
15
|
+
return fail(`Pass a URL of at most ${MAX_FETCH_URL_CHARS} characters.`);
|
|
16
|
+
}
|
|
17
|
+
let u;
|
|
18
|
+
try {
|
|
19
|
+
// no base: a relative URL throws
|
|
20
|
+
u = new URL(input);
|
|
21
|
+
}
|
|
22
|
+
catch {
|
|
23
|
+
return fail("Pass a full absolute URL, such as https://example.com/page.");
|
|
24
|
+
}
|
|
25
|
+
if (u.protocol !== "https:" && u.protocol !== "http:") {
|
|
26
|
+
return fail("Pass an https URL; only http and https URLs can be fetched.");
|
|
27
|
+
}
|
|
28
|
+
if (u.username !== "" || u.password !== "") {
|
|
29
|
+
return fail("Pass the URL without a user name or password.");
|
|
30
|
+
}
|
|
31
|
+
u.protocol = "https:";
|
|
32
|
+
// `u.hostname` is WHATWG-normalized (lowercased, IDNA, numeric IPv4 forms such as `0x7f.0.0.1`
|
|
33
|
+
// rewritten to dotted decimal, IPv6 in brackets), which is what isPublicHostname expects: never
|
|
34
|
+
// pass it a hand-parsed host.
|
|
35
|
+
if (!isPublicHostname(u.hostname)) {
|
|
36
|
+
return fail("Pass a full public https URL; this host is private or local.");
|
|
37
|
+
}
|
|
38
|
+
// the limit is on the URL as fetched: the upgrade, IDNA and percent-encoding can lengthen it
|
|
39
|
+
if (u.href.length > MAX_FETCH_URL_CHARS) {
|
|
40
|
+
return fail(`Pass a URL of at most ${MAX_FETCH_URL_CHARS} characters.`);
|
|
41
|
+
}
|
|
42
|
+
return { ok: true, url: u.href };
|
|
43
|
+
}
|
|
@@ -8,7 +8,7 @@ var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
|
8
8
|
return function (target, key) { decorator(target, key, paramIndex); }
|
|
9
9
|
};
|
|
10
10
|
import { randomUUID } from "node:crypto";
|
|
11
|
-
import { ToolError, } from "@capybara-hq/plugin-sdk";
|
|
11
|
+
import { connectorToolKey, ToolError, } from "@capybara-hq/plugin-sdk";
|
|
12
12
|
import { Inject, Injectable } from "@nestjs/common";
|
|
13
13
|
import { sql } from "kysely";
|
|
14
14
|
import { z } from "zod";
|
|
@@ -25,7 +25,7 @@ import { OrgLock } from "../orgs/org-lock.js";
|
|
|
25
25
|
import { CredentialMissing, Credentials, isOAuth, } from "./credentials.js";
|
|
26
26
|
import { snapshot, ToolDrift, toolIssue, } from "./drift.js";
|
|
27
27
|
import { endpointCredentialIssues, endpointView } from "./endpoint.js";
|
|
28
|
-
import { deriveSlug, isValidSlug, SLUG_RULE
|
|
28
|
+
import { deriveSlug, isValidSlug, SLUG_RULE } from "./naming.js";
|
|
29
29
|
import { checkOAuthUrl, discoverMcp, OAuthSetupError, oauthHttpOptions, pickAuthMethod, registerClient, } from "./oauth/discovery.js";
|
|
30
30
|
import { callbackUrl, publicUrlRequired } from "./oauth/flow-paths.js";
|
|
31
31
|
import { OAuthGrantError, OAuthUnavailable, tokenRequest, } from "./oauth/tokens.js";
|
|
@@ -619,7 +619,7 @@ let ConnectorsService = class ConnectorsService {
|
|
|
619
619
|
issues = snap.issues;
|
|
620
620
|
tools = snap.rows.map((r) => ({
|
|
621
621
|
name: r.name,
|
|
622
|
-
key:
|
|
622
|
+
key: connectorToolKey(slug, r.name),
|
|
623
623
|
description: r.spec.description,
|
|
624
624
|
inputSchema: r.spec.inputSchema,
|
|
625
625
|
annotations: r.spec.annotations ?? null,
|
|
@@ -720,7 +720,7 @@ let ConnectorsService = class ConnectorsService {
|
|
|
720
720
|
const next = t.pending_spec;
|
|
721
721
|
return {
|
|
722
722
|
name: t.name,
|
|
723
|
-
key:
|
|
723
|
+
key: connectorToolKey(r.slug, t.name),
|
|
724
724
|
description: spec.description,
|
|
725
725
|
inputSchema: spec.inputSchema,
|
|
726
726
|
annotations: spec.annotations ?? null,
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { LocalizedName } from "@capybara-hq/plugin-sdk";
|
|
2
|
+
import type { KernelSchemaDb } from "../db/kernel-schema.js";
|
|
3
|
+
/**
|
|
4
|
+
* The display names of plugins, for naming their extensions' tools (`<display name> [<tool>]`,
|
|
5
|
+
* tool naming spec §7): the live catalog item's `displayName`, else the plugin name in both
|
|
6
|
+
* languages (a bootstrap or uploaded plugin without a catalog item, or one without a display name).
|
|
7
|
+
* Display only.
|
|
8
|
+
*/
|
|
9
|
+
export declare function pluginDisplayNames(db: KernelSchemaDb, names: readonly string[]): Promise<Map<string, LocalizedName>>;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The display names of plugins, for naming their extensions' tools (`<display name> [<tool>]`,
|
|
3
|
+
* tool naming spec §7): the live catalog item's `displayName`, else the plugin name in both
|
|
4
|
+
* languages (a bootstrap or uploaded plugin without a catalog item, or one without a display name).
|
|
5
|
+
* Display only.
|
|
6
|
+
*/
|
|
7
|
+
export async function pluginDisplayNames(db, names) {
|
|
8
|
+
const unique = [...new Set(names)];
|
|
9
|
+
const out = new Map(unique.map((n) => [n, { zh: n, en: n }]));
|
|
10
|
+
if (unique.length === 0)
|
|
11
|
+
return out;
|
|
12
|
+
const rows = await db
|
|
13
|
+
.selectFrom("catalog_items")
|
|
14
|
+
.select(["name", "display_name"])
|
|
15
|
+
.where("name", "in", unique)
|
|
16
|
+
.where("deleted_at", "is", null)
|
|
17
|
+
.execute();
|
|
18
|
+
for (const r of rows) {
|
|
19
|
+
const d = r.display_name;
|
|
20
|
+
if (d && typeof d.zh === "string" && typeof d.en === "string" && d.zh !== "" && d.en !== "")
|
|
21
|
+
out.set(r.name, { zh: d.zh, en: d.en });
|
|
22
|
+
}
|
|
23
|
+
return out;
|
|
24
|
+
}
|
package/dist/tools/drift.js
CHANGED
|
@@ -7,7 +7,7 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
|
|
|
7
7
|
var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
8
8
|
return function (target, key) { decorator(target, key, paramIndex); }
|
|
9
9
|
};
|
|
10
|
-
import { TOOL_TITLE_MAX, ToolError, validateToolPresentation, } from "@capybara-hq/plugin-sdk";
|
|
10
|
+
import { connectorToolKey, TOOL_TITLE_MAX, ToolError, validateToolPresentation, } from "@capybara-hq/plugin-sdk";
|
|
11
11
|
import { getQueueToken } from "@nestjs/bullmq";
|
|
12
12
|
import { Inject, Injectable } from "@nestjs/common";
|
|
13
13
|
import { sql } from "kysely";
|
|
@@ -21,7 +21,7 @@ import { KERNEL_LOGGER } from "../infra/tokens.js";
|
|
|
21
21
|
import { MAINTENANCE_QUEUE_NAME } from "../runtime/maintenance-queue.js";
|
|
22
22
|
import { HIDDEN_FORMAT_RE } from "../text.js";
|
|
23
23
|
import { CredentialMissing, Credentials, isOAuth } from "./credentials.js";
|
|
24
|
-
import {
|
|
24
|
+
import { toolKeyIssue } from "./naming.js";
|
|
25
25
|
import { redactDeep, redactorFor } from "./redact.js";
|
|
26
26
|
import { canonicalJson, policyFromAnnotations, specHash, ToolRegistry } from "./registry.js";
|
|
27
27
|
import { resourceToolSpecs } from "./resources.js";
|
|
@@ -105,7 +105,7 @@ export function snapshot(slug, specs, resources) {
|
|
|
105
105
|
...(isObj(s.connectorData) && { connectorData: s.connectorData }),
|
|
106
106
|
...displayFields(s),
|
|
107
107
|
};
|
|
108
|
-
let issue = toolKeyIssue(
|
|
108
|
+
let issue = toolKeyIssue(connectorToolKey(slug, name));
|
|
109
109
|
if (!issue && !isObj(s.inputSchema))
|
|
110
110
|
issue = "Tool inputSchema must be an object";
|
|
111
111
|
if (issue)
|
|
@@ -122,7 +122,7 @@ export function snapshot(slug, specs, resources) {
|
|
|
122
122
|
});
|
|
123
123
|
continue;
|
|
124
124
|
}
|
|
125
|
-
const issue = toolKeyIssue(
|
|
125
|
+
const issue = toolKeyIssue(connectorToolKey(slug, spec.name));
|
|
126
126
|
if (issue)
|
|
127
127
|
issues.push({ name: spec.name, reason: issue });
|
|
128
128
|
rows.push({ name: spec.name, spec, specHash: specHash(spec), issue, source: "resources" });
|
|
@@ -172,7 +172,7 @@ const displayOf = (spec) => {
|
|
|
172
172
|
};
|
|
173
173
|
/** 工具当前不能启用的原因(视图、启用与复核校验共用)。 */
|
|
174
174
|
export function toolIssue(slug, spec) {
|
|
175
|
-
const keyIssue = toolKeyIssue(
|
|
175
|
+
const keyIssue = toolKeyIssue(connectorToolKey(slug, spec.name));
|
|
176
176
|
if (keyIssue)
|
|
177
177
|
return keyIssue;
|
|
178
178
|
if (!isObj(spec.inputSchema))
|
|
@@ -33,7 +33,7 @@ export class ElicitationSuspended extends Error {
|
|
|
33
33
|
}
|
|
34
34
|
/** 不能展示的 elicitation 被拒绝时附在工具结果后的说明(模型可见,英文)。 */
|
|
35
35
|
export const UNSUPPORTED_ELICITATION_NOTE = "The app asked the user for input that cannot be shown in this client, so the request was declined";
|
|
36
|
-
const unsupportedNote = (why) => `[${UNSUPPORTED_ELICITATION_NOTE} (${why}). If the call needs that input, ask the user for it with
|
|
36
|
+
const unsupportedNote = (why) => `[${UNSUPPORTED_ELICITATION_NOTE} (${why}). If the call needs that input, ask the user for it with AskUserQuestion and pass it as tool arguments, or try another approach.]`;
|
|
37
37
|
/** URL 模式表单里「已完成」开关的字段名。 */
|
|
38
38
|
export const URL_COMPLETED_FIELD = "completed";
|
|
39
39
|
/** 表单标题(远端给的 message)最多字符数。 */
|
package/dist/tools/info.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { type LocalizedName } from "@capybara-hq/plugin-sdk";
|
|
1
2
|
import { ConversationAccess } from "../conversations/access.js";
|
|
2
3
|
import type { KernelSchemaDb } from "../db/kernel-schema.js";
|
|
3
4
|
import { KernelDb } from "../infra/database/kernel-db.js";
|
|
@@ -11,16 +12,32 @@ export type ToolKind = "command" | "read" | "edit" | "search" | "connector" | "m
|
|
|
11
12
|
export interface ToolInfo {
|
|
12
13
|
/** The model-visible tool key, as asked for. */
|
|
13
14
|
key: string;
|
|
15
|
+
/**
|
|
16
|
+
* Set only for a release-candidate builtin key (old history, tool naming spec §9): the current
|
|
17
|
+
* tool it stands for. Everything else describes that tool, with `keyArgs` in the old parameter
|
|
18
|
+
* names the logged input carries. Pages map a call's name through it (the `Agent` row, labels).
|
|
19
|
+
*/
|
|
20
|
+
aliasOf?: string;
|
|
14
21
|
/** The declared display title (`ToolSpec.title`), or null. */
|
|
15
22
|
title: string | null;
|
|
16
23
|
kind: ToolKind;
|
|
24
|
+
/** True exactly for the builtin tools that run in the conversation's sandbox. */
|
|
25
|
+
sandbox: boolean;
|
|
17
26
|
/** The declared key arguments (`ToolSpec.keyArgs`), or []. */
|
|
18
27
|
keyArgs: string[];
|
|
28
|
+
/**
|
|
29
|
+
* The local tool name parsed from a connector or extension key (`mcp__crm__delete` -> `delete`),
|
|
30
|
+
* shown in brackets after the source's display name; null for builtins and unparsable keys.
|
|
31
|
+
*/
|
|
32
|
+
tool: string | null;
|
|
19
33
|
source: {
|
|
20
34
|
kind: "builtin";
|
|
21
|
-
}
|
|
35
|
+
}
|
|
36
|
+
/** `displayName`: the plugin's catalog display name, else its name. */
|
|
37
|
+
| {
|
|
22
38
|
kind: "extension";
|
|
23
39
|
name: string;
|
|
40
|
+
displayName: LocalizedName;
|
|
24
41
|
} | {
|
|
25
42
|
kind: "connector";
|
|
26
43
|
id: string;
|
|
@@ -31,8 +48,7 @@ export interface ToolInfo {
|
|
|
31
48
|
kind: "unknown";
|
|
32
49
|
};
|
|
33
50
|
}
|
|
34
|
-
|
|
35
|
-
export declare const BUILTIN_TOOL_KINDS: Readonly<Record<string, ToolKind>>;
|
|
51
|
+
export { BUILTIN_TOOL_KINDS } from "./builtin-names.js";
|
|
36
52
|
/** At most this many keys per request, each at most {@link TOOL_INFO_KEY_MAX} characters. */
|
|
37
53
|
export declare const TOOL_INFO_MAX_KEYS = 100;
|
|
38
54
|
export declare const TOOL_INFO_KEY_MAX = 200;
|
|
@@ -42,7 +58,7 @@ export interface ToolInfoDeps {
|
|
|
42
58
|
}
|
|
43
59
|
/**
|
|
44
60
|
* Presentation metadata for `keys` in this org, in request order with repeats dropped. Builtins
|
|
45
|
-
* by name;
|
|
61
|
+
* by name (a release-candidate builtin key as its current tool, with `aliasOf`); `plugin__<plugin>__<tool>` keys as a loaded extension's registration, and `mcp__<slug>__<tool>` keys as a live
|
|
46
62
|
* connector's current stored tool (its reviewed definition, never a pending one). Anything else
|
|
47
63
|
* comes back as an unknown plain tool.
|
|
48
64
|
*
|