@aitne/shared 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/dist/advisor-models.d.ts +34 -0
- package/dist/advisor-models.d.ts.map +1 -0
- package/dist/advisor-models.js +39 -0
- package/dist/advisor-models.js.map +1 -0
- package/dist/agent-identity.d.ts +11 -0
- package/dist/agent-identity.d.ts.map +1 -0
- package/dist/agent-identity.js +29 -0
- package/dist/agent-identity.js.map +1 -0
- package/dist/alerts.d.ts +44 -0
- package/dist/alerts.d.ts.map +1 -0
- package/dist/alerts.js +12 -0
- package/dist/alerts.js.map +1 -0
- package/dist/backend-api-key-config.d.ts +337 -0
- package/dist/backend-api-key-config.d.ts.map +1 -0
- package/dist/backend-api-key-config.js +682 -0
- package/dist/backend-api-key-config.js.map +1 -0
- package/dist/backend.d.ts +93 -0
- package/dist/backend.d.ts.map +1 -0
- package/dist/backend.js +22 -0
- package/dist/backend.js.map +1 -0
- package/dist/branding.d.ts +96 -0
- package/dist/branding.d.ts.map +1 -0
- package/dist/branding.js +102 -0
- package/dist/branding.js.map +1 -0
- package/dist/chat-session-scope.d.ts +14 -0
- package/dist/chat-session-scope.d.ts.map +1 -0
- package/dist/chat-session-scope.js +18 -0
- package/dist/chat-session-scope.js.map +1 -0
- package/dist/date-utils.d.ts +80 -0
- package/dist/date-utils.d.ts.map +1 -0
- package/dist/date-utils.js +187 -0
- package/dist/date-utils.js.map +1 -0
- package/dist/docs-frontmatter.d.ts +51 -0
- package/dist/docs-frontmatter.d.ts.map +1 -0
- package/dist/docs-frontmatter.js +184 -0
- package/dist/docs-frontmatter.js.map +1 -0
- package/dist/docs-schema.d.ts +79 -0
- package/dist/docs-schema.d.ts.map +1 -0
- package/dist/docs-schema.js +135 -0
- package/dist/docs-schema.js.map +1 -0
- package/dist/editable-config-keys.d.ts +14 -0
- package/dist/editable-config-keys.d.ts.map +1 -0
- package/dist/editable-config-keys.js +157 -0
- package/dist/editable-config-keys.js.map +1 -0
- package/dist/exec-with-stdin.d.ts +14 -0
- package/dist/exec-with-stdin.d.ts.map +1 -0
- package/dist/exec-with-stdin.js +35 -0
- package/dist/exec-with-stdin.js.map +1 -0
- package/dist/index.d.ts +37 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +49 -0
- package/dist/index.js.map +1 -0
- package/dist/integrations-snapshot.d.ts +183 -0
- package/dist/integrations-snapshot.d.ts.map +1 -0
- package/dist/integrations-snapshot.js +757 -0
- package/dist/integrations-snapshot.js.map +1 -0
- package/dist/integrations.d.ts +675 -0
- package/dist/integrations.d.ts.map +1 -0
- package/dist/integrations.js +1656 -0
- package/dist/integrations.js.map +1 -0
- package/dist/keychain-helper-client.d.ts +31 -0
- package/dist/keychain-helper-client.d.ts.map +1 -0
- package/dist/keychain-helper-client.js +105 -0
- package/dist/keychain-helper-client.js.map +1 -0
- package/dist/log-entry.d.ts +14 -0
- package/dist/log-entry.d.ts.map +1 -0
- package/dist/log-entry.js +2 -0
- package/dist/log-entry.js.map +1 -0
- package/dist/management-domains.d.ts +369 -0
- package/dist/management-domains.d.ts.map +1 -0
- package/dist/management-domains.js +499 -0
- package/dist/management-domains.js.map +1 -0
- package/dist/process-key.d.ts +67 -0
- package/dist/process-key.d.ts.map +1 -0
- package/dist/process-key.js +366 -0
- package/dist/process-key.js.map +1 -0
- package/dist/schemas.d.ts +267 -0
- package/dist/schemas.d.ts.map +1 -0
- package/dist/schemas.js +271 -0
- package/dist/schemas.js.map +1 -0
- package/dist/secret-client-factory.d.ts +16 -0
- package/dist/secret-client-factory.d.ts.map +1 -0
- package/dist/secret-client-factory.js +111 -0
- package/dist/secret-client-factory.js.map +1 -0
- package/dist/secret-client-file.d.ts +51 -0
- package/dist/secret-client-file.d.ts.map +1 -0
- package/dist/secret-client-file.js +160 -0
- package/dist/secret-client-file.js.map +1 -0
- package/dist/secret-client-linux.d.ts +26 -0
- package/dist/secret-client-linux.d.ts.map +1 -0
- package/dist/secret-client-linux.js +63 -0
- package/dist/secret-client-linux.js.map +1 -0
- package/dist/secret-client-windows.d.ts +37 -0
- package/dist/secret-client-windows.d.ts.map +1 -0
- package/dist/secret-client-windows.js +82 -0
- package/dist/secret-client-windows.js.map +1 -0
- package/dist/secret-redaction.d.ts +3 -0
- package/dist/secret-redaction.d.ts.map +1 -0
- package/dist/secret-redaction.js +31 -0
- package/dist/secret-redaction.js.map +1 -0
- package/dist/skill-curation/decision-language.d.ts +6 -0
- package/dist/skill-curation/decision-language.d.ts.map +1 -0
- package/dist/skill-curation/decision-language.js +38 -0
- package/dist/skill-curation/decision-language.js.map +1 -0
- package/dist/skill-curation/schemas.d.ts +461 -0
- package/dist/skill-curation/schemas.d.ts.map +1 -0
- package/dist/skill-curation/schemas.js +211 -0
- package/dist/skill-curation/schemas.js.map +1 -0
- package/dist/types.d.ts +204 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +54 -0
- package/dist/types.js.map +1 -0
- package/package.json +50 -0
|
@@ -0,0 +1,675 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { type BackendId } from "./backend.js";
|
|
3
|
+
/**
|
|
4
|
+
* Integration Delegation Framework — shared types (Phase 1–3).
|
|
5
|
+
*
|
|
6
|
+
* See `GOOGLE_AUTH_DELEGATION_DESIGN.md` v3. Phase 1 ships the registry +
|
|
7
|
+
* per-integration mode config with Gmail + Calendar as the first two keys.
|
|
8
|
+
* Phase 3 adds skill / task-flow variant selection helpers consumed by
|
|
9
|
+
* SkillsCompiler and prompts.ts. Git lifecycle Phase 4 retroactively registers
|
|
10
|
+
* the local Git / GitHub observers under the same mode framework.
|
|
11
|
+
*/
|
|
12
|
+
/**
|
|
13
|
+
* Mode-aware integrations — the ones that can flip between `direct` and
|
|
14
|
+
* `delegated` and route through the per-backend probe / connector / skill
|
|
15
|
+
* filter framework. Other surfaces (lifestyle services like
|
|
16
|
+
* receipts/books/travel-bookings, Obsidian) integrate via dedicated routes
|
|
17
|
+
* and observers without participating in this registry.
|
|
18
|
+
*/
|
|
19
|
+
export declare const INTEGRATION_KEYS: readonly ["gmail", "google_calendar", "notion", "git", "github", "outlook_mail", "outlook_calendar"];
|
|
20
|
+
export type IntegrationKey = (typeof INTEGRATION_KEYS)[number];
|
|
21
|
+
export declare function isIntegrationKey(value: string): value is IntegrationKey;
|
|
22
|
+
export declare const INTEGRATION_MODES: readonly ["direct", "delegated", "disabled"];
|
|
23
|
+
export type IntegrationMode = (typeof INTEGRATION_MODES)[number];
|
|
24
|
+
export declare function isIntegrationMode(value: string): value is IntegrationMode;
|
|
25
|
+
export interface IntegrationBackendConnector {
|
|
26
|
+
/** Prefix that vendor-shipped MCP tools share, e.g. `mcp__claude_ai_Gmail__`. */
|
|
27
|
+
toolNamespace: string;
|
|
28
|
+
/** Capabilities that must all be present for delegated mode to be offered. */
|
|
29
|
+
requiredCapabilities: readonly string[];
|
|
30
|
+
/** Capabilities the feature matrix renders from (tick/cross UI). */
|
|
31
|
+
optionalCapabilities: readonly string[];
|
|
32
|
+
/**
|
|
33
|
+
* Maps each capability name to the unsuffixed tool names that satisfy it.
|
|
34
|
+
* Used by the probe to translate a live MCP tool list into per-capability
|
|
35
|
+
* presence. Tool names are the part after `toolNamespace` (e.g. for the
|
|
36
|
+
* Claude Gmail connector `toolNamespace = "mcp__claude_ai_Gmail__"`,
|
|
37
|
+
* `"search"` maps to `["search_threads"]`).
|
|
38
|
+
*
|
|
39
|
+
* Every capability listed in `requiredCapabilities` ∪ `optionalCapabilities`
|
|
40
|
+
* MUST have an entry here. An empty array means "no shipped tool satisfies
|
|
41
|
+
* this capability" (always absent in the probe). The registry
|
|
42
|
+
* self-consistency test in `integration-probe.test.ts` enforces this.
|
|
43
|
+
*/
|
|
44
|
+
capabilityTools: Readonly<Record<string, readonly string[]>>;
|
|
45
|
+
/**
|
|
46
|
+
* DELEGATED-TASK-MODE-DESIGN.md §7.3 — bare tool names (same form as
|
|
47
|
+
* `capabilityTools` values) whose invocation mutates user-visible state
|
|
48
|
+
* in a way that requires explicit confirmation per the CLAUDE.md
|
|
49
|
+
* "destructive ops require user confirmation" invariant. Concrete tool
|
|
50
|
+
* names rather than capability keys because some capabilities mix reads
|
|
51
|
+
* and writes (Gemini Gmail's `label` covers `listLabels` (read) and
|
|
52
|
+
* `modify` (write)); a tool-level list lets us deny the writes without
|
|
53
|
+
* classifying the read as destructive.
|
|
54
|
+
*
|
|
55
|
+
* Used by:
|
|
56
|
+
* - Task mode `runDelegatedTask`: when `allowDestructive: false`,
|
|
57
|
+
* these are removed from the SDK's `allowedTools` (Claude) /
|
|
58
|
+
* emitted as priority-998 deny rules (Gemini), and the subprocess
|
|
59
|
+
* is instructed to return `{needsConfirmation, confirmationPlan}`.
|
|
60
|
+
* - The `destructive-coverage.test.ts` drift test asserts every entry
|
|
61
|
+
* in `RECOMMENDED_STARTER_DENIED_TOOLS` for this connector appears
|
|
62
|
+
* here (i.e. the recommended starter list is a subset of the
|
|
63
|
+
* descriptor's destructive set).
|
|
64
|
+
*
|
|
65
|
+
* Every entry MUST also appear in some `capabilityTools[k]` array — a
|
|
66
|
+
* destructive tool the descriptor doesn't otherwise know about would be
|
|
67
|
+
* dead weight. Enforced by the same self-consistency test that covers
|
|
68
|
+
* the rest of the descriptor surface.
|
|
69
|
+
*/
|
|
70
|
+
destructiveTools: readonly string[];
|
|
71
|
+
}
|
|
72
|
+
export interface IntegrationDirectSetup {
|
|
73
|
+
/** Keychain keys that must be present for direct mode to function. */
|
|
74
|
+
credentialKeys: readonly string[];
|
|
75
|
+
/** Documentation URL shown in the setup wizard and dashboard cards. */
|
|
76
|
+
helpUrl: string;
|
|
77
|
+
}
|
|
78
|
+
export interface IntegrationDescriptor {
|
|
79
|
+
key: IntegrationKey;
|
|
80
|
+
displayName: string;
|
|
81
|
+
supportedModes: readonly IntegrationMode[];
|
|
82
|
+
directSetup?: IntegrationDirectSetup;
|
|
83
|
+
backendConnectors: Partial<Record<BackendId, IntegrationBackendConnector>>;
|
|
84
|
+
/** Skill slugs whose bodies depend on this integration. Declarative only in Phase 1. */
|
|
85
|
+
skillsTouched: readonly string[];
|
|
86
|
+
/** Task-flow keys same. Declarative only in Phase 1. */
|
|
87
|
+
taskFlowsTouched: readonly string[];
|
|
88
|
+
/**
|
|
89
|
+
* Runtime observer names gated by `integration.mode === "direct"`. Each
|
|
90
|
+
* string is the value the observer exposes via its `Observer.name`
|
|
91
|
+
* property — `ObserverManager.has()` / `stopAndUnregister()` look up by
|
|
92
|
+
* that exact key. (The design doc uses class names like `MailPoller`
|
|
93
|
+
* for human readability; the registry uses the runtime name so the
|
|
94
|
+
* lifecycle module can act without a translation table.)
|
|
95
|
+
*/
|
|
96
|
+
observersTouched: readonly string[];
|
|
97
|
+
/**
|
|
98
|
+
* Path prefixes the registry middleware 410-gates when delegated. The
|
|
99
|
+
* 410 is **defense-in-depth** in v2 (DELEGATED-MODE-V2-DESIGN.md §6.3):
|
|
100
|
+
* cross-backend skill prose directs the agent at
|
|
101
|
+
* `POST /api/integrations/:key/invoke`, and same-backend skill is not
|
|
102
|
+
* provisioned at all. The gate fires only when the agent invents a
|
|
103
|
+
* call the variant prose did not teach it.
|
|
104
|
+
*
|
|
105
|
+
* Multi-provider routes (e.g. Gmail under `/api/mail/*`) are
|
|
106
|
+
* intentionally NOT listed here — prefix matching would also block
|
|
107
|
+
* other providers (iCloud, Outlook, IMAP). Per-account 410 inside the
|
|
108
|
+
* route handler covers those cases. Single-provider surfaces like
|
|
109
|
+
* `/api/calendar` can be listed safely.
|
|
110
|
+
*/
|
|
111
|
+
apiRoutesTouched: readonly string[];
|
|
112
|
+
/**
|
|
113
|
+
* Skill slugs whose `SKILL.md` body should be filtered by this
|
|
114
|
+
* integration's `deniedTools` independently of `skillsTouched` —
|
|
115
|
+
* forward-compat hook for skill bodies that touch the integration but
|
|
116
|
+
* should not trigger variant resolution. Today, `skillsTouched`
|
|
117
|
+
* already covers every body that needs the deny pass; this field
|
|
118
|
+
* remains for symmetry with non-default-variant cases.
|
|
119
|
+
*/
|
|
120
|
+
deniedToolsAppliesToSkills?: readonly string[];
|
|
121
|
+
/**
|
|
122
|
+
* Subset of `skillsTouched` whose body the integration's same-backend
|
|
123
|
+
* connector tools fully cover. When `selectSkillVariantFile` resolves
|
|
124
|
+
* to "same-backend", a touched skill is dropped (returns `null`) only
|
|
125
|
+
* if EVERY touching integration declares it here. Skills broader than
|
|
126
|
+
* the integration (e.g. `mail` covers IMAP/Outlook on top of Gmail;
|
|
127
|
+
* `external-services` covers Obsidian/GitHub/scheduling on top of
|
|
128
|
+
* Google Calendar) must NOT appear here — dropping them would orphan
|
|
129
|
+
* the non-delegated functionality. Skills that are pure connector
|
|
130
|
+
* wrappers (e.g. `notion` is solely Notion) belong here.
|
|
131
|
+
*/
|
|
132
|
+
sameBackendDropsSkillBody?: readonly string[];
|
|
133
|
+
/**
|
|
134
|
+
* Marks an integration whose delegated mode relies on an MCP server or
|
|
135
|
+
* connector the user installs on the agent backend (Claude Code / Codex /
|
|
136
|
+
* Gemini CLI) themselves. The daemon does not ship a tool inventory for
|
|
137
|
+
* these connectors, so:
|
|
138
|
+
* - `backendConnectors` may be empty (no descriptor-driven feature
|
|
139
|
+
* matrix or capability probe).
|
|
140
|
+
* - The PATCH `/integrations/:key` endpoint accepts any `delegatedBackend`
|
|
141
|
+
* supported by the daemon — capability probing is the user's
|
|
142
|
+
* responsibility on the backend side.
|
|
143
|
+
* - The probe and route-gate surfaces fall back to a generic
|
|
144
|
+
* "user-managed connector" path that does not enforce the daemon's
|
|
145
|
+
* normal tool-inventory checks.
|
|
146
|
+
*
|
|
147
|
+
* Today: `outlook_mail` and `outlook_calendar`. Microsoft does not ship
|
|
148
|
+
* a hosted MCP connector for Claude / Codex / Gemini; users register an
|
|
149
|
+
* Outlook / Microsoft Graph MCP server on their backend (Claude Code
|
|
150
|
+
* Connector, Codex MCP, Gemini extension) and we trust that wiring.
|
|
151
|
+
*/
|
|
152
|
+
userManagedConnector?: boolean;
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* The registry. Single source of truth for which integrations exist, what
|
|
156
|
+
* backends can delegate for them, and which parts of the daemon they touch.
|
|
157
|
+
*
|
|
158
|
+
* `backendConnectors` is a `Partial` record — omitting a backend means
|
|
159
|
+
* delegation through that backend is unsupported.
|
|
160
|
+
*
|
|
161
|
+
* Gemini namespace convention differs from Claude / Codex. Gemini CLI's
|
|
162
|
+
* MCP_TOOL_PREFIX is `mcp_` (single underscore) and the per-server prefix
|
|
163
|
+
* is `mcp_<serverName>_`, so a tool registered as `gmail.search` on the
|
|
164
|
+
* `google-workspace` extension surfaces as `mcp_google-workspace_gmail.search`.
|
|
165
|
+
* Hyphens and dots in the registered name are preserved. The tool-name
|
|
166
|
+
* format was confirmed by stream-event probe (2026-04-26 — see
|
|
167
|
+
* `gemini -p ... --output-format stream-json` `tool_use` events) and is
|
|
168
|
+
* the source of truth for `toolNamespace` and `capabilityTools` below.
|
|
169
|
+
*
|
|
170
|
+
* Gemini connectors require host-side MCP setup the daemon does not
|
|
171
|
+
* manage:
|
|
172
|
+
* - Gmail + Calendar: `~/.gemini/extensions/google-workspace/`
|
|
173
|
+
* (install via `gemini extensions install <url>`).
|
|
174
|
+
* - Notion: register Notion's official MCP server under the server name
|
|
175
|
+
* `notion` (e.g. `gemini mcp add notion <url>`); changing the server
|
|
176
|
+
* name breaks the namespace assumption — see Gemini Notion descriptor
|
|
177
|
+
* notes below.
|
|
178
|
+
*/
|
|
179
|
+
export declare const INTEGRATION_DESCRIPTORS: Readonly<Record<IntegrationKey, IntegrationDescriptor>>;
|
|
180
|
+
export declare function getIntegrationDescriptor(key: IntegrationKey): IntegrationDescriptor;
|
|
181
|
+
export declare function listIntegrationDescriptors(): readonly IntegrationDescriptor[];
|
|
182
|
+
/**
|
|
183
|
+
* Per-integration runtime state. Persisted as a single JSON blob in the
|
|
184
|
+
* `settings` table under key `"integrations"`; rendered into
|
|
185
|
+
* `~/.personal-agent/integrations.md` so users can edit by hand.
|
|
186
|
+
*/
|
|
187
|
+
export declare const integrationStateSchema: z.ZodObject<{
|
|
188
|
+
mode: z.ZodEnum<{
|
|
189
|
+
direct: "direct";
|
|
190
|
+
delegated: "delegated";
|
|
191
|
+
disabled: "disabled";
|
|
192
|
+
}>;
|
|
193
|
+
delegatedBackend: z.ZodOptional<z.ZodNullable<z.ZodOptional<z.ZodEnum<{
|
|
194
|
+
claude: "claude";
|
|
195
|
+
codex: "codex";
|
|
196
|
+
gemini: "gemini";
|
|
197
|
+
}>>>>;
|
|
198
|
+
delegatedModel: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
199
|
+
delegatedMaxTurns: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
200
|
+
delegatedSyncEnabled: z.ZodOptional<z.ZodBoolean>;
|
|
201
|
+
deniedTools: z.ZodDefault<z.ZodOptional<z.ZodArray<z.ZodString>>>;
|
|
202
|
+
lastChangedAt: z.ZodString;
|
|
203
|
+
}, z.core.$strip>;
|
|
204
|
+
export type IntegrationState = z.infer<typeof integrationStateSchema>;
|
|
205
|
+
/**
|
|
206
|
+
* The full integrations map stored in the `settings` table. Every registered
|
|
207
|
+
* integration key has an entry; missing keys are filled with the per-key
|
|
208
|
+
* default before persistence. Gmail / Calendar / Notion stay disabled on
|
|
209
|
+
* fresh installs, while Git / GitHub default to direct mode to preserve the
|
|
210
|
+
* pre-registry observer behaviour and match the Git lifecycle design.
|
|
211
|
+
*/
|
|
212
|
+
export declare const integrationsMapSchema: z.ZodObject<{
|
|
213
|
+
git: z.ZodOptional<z.ZodObject<{
|
|
214
|
+
mode: z.ZodEnum<{
|
|
215
|
+
direct: "direct";
|
|
216
|
+
delegated: "delegated";
|
|
217
|
+
disabled: "disabled";
|
|
218
|
+
}>;
|
|
219
|
+
delegatedBackend: z.ZodOptional<z.ZodNullable<z.ZodOptional<z.ZodEnum<{
|
|
220
|
+
claude: "claude";
|
|
221
|
+
codex: "codex";
|
|
222
|
+
gemini: "gemini";
|
|
223
|
+
}>>>>;
|
|
224
|
+
delegatedModel: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
225
|
+
delegatedMaxTurns: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
226
|
+
delegatedSyncEnabled: z.ZodOptional<z.ZodBoolean>;
|
|
227
|
+
deniedTools: z.ZodDefault<z.ZodOptional<z.ZodArray<z.ZodString>>>;
|
|
228
|
+
lastChangedAt: z.ZodString;
|
|
229
|
+
}, z.core.$strip>>;
|
|
230
|
+
gmail: z.ZodOptional<z.ZodObject<{
|
|
231
|
+
mode: z.ZodEnum<{
|
|
232
|
+
direct: "direct";
|
|
233
|
+
delegated: "delegated";
|
|
234
|
+
disabled: "disabled";
|
|
235
|
+
}>;
|
|
236
|
+
delegatedBackend: z.ZodOptional<z.ZodNullable<z.ZodOptional<z.ZodEnum<{
|
|
237
|
+
claude: "claude";
|
|
238
|
+
codex: "codex";
|
|
239
|
+
gemini: "gemini";
|
|
240
|
+
}>>>>;
|
|
241
|
+
delegatedModel: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
242
|
+
delegatedMaxTurns: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
243
|
+
delegatedSyncEnabled: z.ZodOptional<z.ZodBoolean>;
|
|
244
|
+
deniedTools: z.ZodDefault<z.ZodOptional<z.ZodArray<z.ZodString>>>;
|
|
245
|
+
lastChangedAt: z.ZodString;
|
|
246
|
+
}, z.core.$strip>>;
|
|
247
|
+
google_calendar: z.ZodOptional<z.ZodObject<{
|
|
248
|
+
mode: z.ZodEnum<{
|
|
249
|
+
direct: "direct";
|
|
250
|
+
delegated: "delegated";
|
|
251
|
+
disabled: "disabled";
|
|
252
|
+
}>;
|
|
253
|
+
delegatedBackend: z.ZodOptional<z.ZodNullable<z.ZodOptional<z.ZodEnum<{
|
|
254
|
+
claude: "claude";
|
|
255
|
+
codex: "codex";
|
|
256
|
+
gemini: "gemini";
|
|
257
|
+
}>>>>;
|
|
258
|
+
delegatedModel: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
259
|
+
delegatedMaxTurns: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
260
|
+
delegatedSyncEnabled: z.ZodOptional<z.ZodBoolean>;
|
|
261
|
+
deniedTools: z.ZodDefault<z.ZodOptional<z.ZodArray<z.ZodString>>>;
|
|
262
|
+
lastChangedAt: z.ZodString;
|
|
263
|
+
}, z.core.$strip>>;
|
|
264
|
+
notion: z.ZodOptional<z.ZodObject<{
|
|
265
|
+
mode: z.ZodEnum<{
|
|
266
|
+
direct: "direct";
|
|
267
|
+
delegated: "delegated";
|
|
268
|
+
disabled: "disabled";
|
|
269
|
+
}>;
|
|
270
|
+
delegatedBackend: z.ZodOptional<z.ZodNullable<z.ZodOptional<z.ZodEnum<{
|
|
271
|
+
claude: "claude";
|
|
272
|
+
codex: "codex";
|
|
273
|
+
gemini: "gemini";
|
|
274
|
+
}>>>>;
|
|
275
|
+
delegatedModel: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
276
|
+
delegatedMaxTurns: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
277
|
+
delegatedSyncEnabled: z.ZodOptional<z.ZodBoolean>;
|
|
278
|
+
deniedTools: z.ZodDefault<z.ZodOptional<z.ZodArray<z.ZodString>>>;
|
|
279
|
+
lastChangedAt: z.ZodString;
|
|
280
|
+
}, z.core.$strip>>;
|
|
281
|
+
github: z.ZodOptional<z.ZodObject<{
|
|
282
|
+
mode: z.ZodEnum<{
|
|
283
|
+
direct: "direct";
|
|
284
|
+
delegated: "delegated";
|
|
285
|
+
disabled: "disabled";
|
|
286
|
+
}>;
|
|
287
|
+
delegatedBackend: z.ZodOptional<z.ZodNullable<z.ZodOptional<z.ZodEnum<{
|
|
288
|
+
claude: "claude";
|
|
289
|
+
codex: "codex";
|
|
290
|
+
gemini: "gemini";
|
|
291
|
+
}>>>>;
|
|
292
|
+
delegatedModel: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
293
|
+
delegatedMaxTurns: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
294
|
+
delegatedSyncEnabled: z.ZodOptional<z.ZodBoolean>;
|
|
295
|
+
deniedTools: z.ZodDefault<z.ZodOptional<z.ZodArray<z.ZodString>>>;
|
|
296
|
+
lastChangedAt: z.ZodString;
|
|
297
|
+
}, z.core.$strip>>;
|
|
298
|
+
outlook_mail: z.ZodOptional<z.ZodObject<{
|
|
299
|
+
mode: z.ZodEnum<{
|
|
300
|
+
direct: "direct";
|
|
301
|
+
delegated: "delegated";
|
|
302
|
+
disabled: "disabled";
|
|
303
|
+
}>;
|
|
304
|
+
delegatedBackend: z.ZodOptional<z.ZodNullable<z.ZodOptional<z.ZodEnum<{
|
|
305
|
+
claude: "claude";
|
|
306
|
+
codex: "codex";
|
|
307
|
+
gemini: "gemini";
|
|
308
|
+
}>>>>;
|
|
309
|
+
delegatedModel: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
310
|
+
delegatedMaxTurns: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
311
|
+
delegatedSyncEnabled: z.ZodOptional<z.ZodBoolean>;
|
|
312
|
+
deniedTools: z.ZodDefault<z.ZodOptional<z.ZodArray<z.ZodString>>>;
|
|
313
|
+
lastChangedAt: z.ZodString;
|
|
314
|
+
}, z.core.$strip>>;
|
|
315
|
+
outlook_calendar: z.ZodOptional<z.ZodObject<{
|
|
316
|
+
mode: z.ZodEnum<{
|
|
317
|
+
direct: "direct";
|
|
318
|
+
delegated: "delegated";
|
|
319
|
+
disabled: "disabled";
|
|
320
|
+
}>;
|
|
321
|
+
delegatedBackend: z.ZodOptional<z.ZodNullable<z.ZodOptional<z.ZodEnum<{
|
|
322
|
+
claude: "claude";
|
|
323
|
+
codex: "codex";
|
|
324
|
+
gemini: "gemini";
|
|
325
|
+
}>>>>;
|
|
326
|
+
delegatedModel: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
327
|
+
delegatedMaxTurns: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
328
|
+
delegatedSyncEnabled: z.ZodOptional<z.ZodBoolean>;
|
|
329
|
+
deniedTools: z.ZodDefault<z.ZodOptional<z.ZodArray<z.ZodString>>>;
|
|
330
|
+
lastChangedAt: z.ZodString;
|
|
331
|
+
}, z.core.$strip>>;
|
|
332
|
+
}, z.core.$strict>;
|
|
333
|
+
export type IntegrationsMap = Partial<Record<IntegrationKey, IntegrationState>>;
|
|
334
|
+
/** Build the default integration map used for fresh installs. */
|
|
335
|
+
export declare function defaultIntegrationsMap(now?: string): Record<IntegrationKey, IntegrationState>;
|
|
336
|
+
/**
|
|
337
|
+
* Narrow user input (from integrations.md or PATCH /api/integrations/:key) to a
|
|
338
|
+
* valid state. Used by the parser and the API route so both enforce identical
|
|
339
|
+
* rules.
|
|
340
|
+
*/
|
|
341
|
+
export declare const integrationPatchSchema: z.ZodObject<{
|
|
342
|
+
mode: z.ZodEnum<{
|
|
343
|
+
direct: "direct";
|
|
344
|
+
delegated: "delegated";
|
|
345
|
+
disabled: "disabled";
|
|
346
|
+
}>;
|
|
347
|
+
delegatedBackend: z.ZodNullable<z.ZodOptional<z.ZodEnum<{
|
|
348
|
+
claude: "claude";
|
|
349
|
+
codex: "codex";
|
|
350
|
+
gemini: "gemini";
|
|
351
|
+
}>>>;
|
|
352
|
+
delegatedModel: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
353
|
+
delegatedMaxTurns: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
354
|
+
delegatedSyncEnabled: z.ZodOptional<z.ZodBoolean>;
|
|
355
|
+
deniedTools: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
356
|
+
}, z.core.$strip>;
|
|
357
|
+
export type IntegrationPatch = z.infer<typeof integrationPatchSchema>;
|
|
358
|
+
/**
|
|
359
|
+
* DELEGATED-MODE-V2-DESIGN.md §4.1.1 — pick the SKILL.md variant for a given
|
|
360
|
+
* skill, **session backend**, and integration state. Three outcomes:
|
|
361
|
+
*
|
|
362
|
+
* - `"SKILL.md"` — direct/default body. Used when no touched
|
|
363
|
+
* integration is delegated, when the skill is
|
|
364
|
+
* integration-agnostic, OR when every touched
|
|
365
|
+
* integration is same-backend delegated but the
|
|
366
|
+
* skill body covers more than the connector
|
|
367
|
+
* exposes (see `sameBackendDropsSkillBody`).
|
|
368
|
+
* - `null` — do **not** materialize the skill at all. Reached
|
|
369
|
+
* when every touched integration is delegated AND
|
|
370
|
+
* `delegatedBackend === sessionBackend` AND every
|
|
371
|
+
* touching integration declares the skill in its
|
|
372
|
+
* `sameBackendDropsSkillBody` (i.e. the connector
|
|
373
|
+
* covers the entire skill surface). The agent
|
|
374
|
+
* already has the connector's tools natively, so
|
|
375
|
+
* a redundant skill body is omitted.
|
|
376
|
+
* - `"SKILL.delegated.<sessionBackend>.md"` — cross-backend variant. The
|
|
377
|
+
* DM session runs on `sessionBackend` but the
|
|
378
|
+
* connector for at least one touched integration
|
|
379
|
+
* lives on a *different* backend, so the agent
|
|
380
|
+
* must call the daemon's generic invoke endpoint
|
|
381
|
+
* which spawns the delegatedBackend subprocess.
|
|
382
|
+
*
|
|
383
|
+
* Combination rule for skills that touch multiple integrations: cross-backend
|
|
384
|
+
* wins over same-backend (a single skill body cannot reliably span both
|
|
385
|
+
* worlds), and same-backend → null wins over direct only when *every*
|
|
386
|
+
* touched integration resolves to same-backend AND every touched integration
|
|
387
|
+
* declares the skill in `sameBackendDropsSkillBody`. Any other configuration
|
|
388
|
+
* falls back to `"SKILL.md"`.
|
|
389
|
+
*
|
|
390
|
+
* Callers are responsible for existence-checking: if the returned variant
|
|
391
|
+
* file does not exist on disk, fall back to `"SKILL.md"`.
|
|
392
|
+
*/
|
|
393
|
+
export declare function selectSkillVariantFile(skillSlug: string, sessionBackend: BackendId, integrations: Partial<Record<IntegrationKey, IntegrationState>>): string | null;
|
|
394
|
+
/**
|
|
395
|
+
* Return the task-flow variant suffix for a given event type, backend, and
|
|
396
|
+
* integration state. Returns `"direct"` when no touched integration is
|
|
397
|
+
* delegated. Returns `"delegated.<backendId>"` otherwise.
|
|
398
|
+
*
|
|
399
|
+
* The caller constructs the filename as `<eventType>.<suffix>.md` and checks
|
|
400
|
+
* for existence before falling back to `<eventType>.md`.
|
|
401
|
+
*/
|
|
402
|
+
export declare function selectTaskFlowVariantSuffix(taskFlowKey: string, backendId: BackendId, integrations: Partial<Record<IntegrationKey, IntegrationState>>): string;
|
|
403
|
+
/**
|
|
404
|
+
* Return the delegated integrations whose `taskFlowsTouched` declares a
|
|
405
|
+
* dependency on this process key. Skills are intentionally not consulted —
|
|
406
|
+
* skills load on demand mid-session, so the router cannot predict them from
|
|
407
|
+
* a process key alone.
|
|
408
|
+
*
|
|
409
|
+
* **Excludes proxy-driven integrations** (see {@link PROXY_DRIVEN_INTEGRATIONS}).
|
|
410
|
+
* The router uses this helper only to decide whether to refuse a fallback
|
|
411
|
+
* because the fallback backend lacks the integration's connector. For
|
|
412
|
+
* proxy-driven integrations the connector lives on `delegatedBackend` and
|
|
413
|
+
* is invoked by the daemon — the agent backend never touches it, so the
|
|
414
|
+
* fallback gate is irrelevant. (Gmail/Calendar still appear in
|
|
415
|
+
* `taskFlowsTouched` because their delegated variant is what
|
|
416
|
+
* `selectTaskFlowVariantSuffix` reads to compensate for stopped pollers;
|
|
417
|
+
* the asymmetry is intentional.)
|
|
418
|
+
*
|
|
419
|
+
* Returns an empty array when no native-MCP delegated integration touches
|
|
420
|
+
* the key.
|
|
421
|
+
*/
|
|
422
|
+
export declare function delegatedIntegrationsForProcessKey(processKey: string, integrations: Partial<Record<IntegrationKey, IntegrationState>>): IntegrationKey[];
|
|
423
|
+
/**
|
|
424
|
+
* True when the registry declares a connector for `(integrationKey, backendId)`.
|
|
425
|
+
* Descriptor presence is the contract the BackendRouter consults on the
|
|
426
|
+
* fallback path — a missing entry means the backend has no connector for
|
|
427
|
+
* this integration, so routing a delegated-integration process key through
|
|
428
|
+
* it would silently execute with the wrong tool surface.
|
|
429
|
+
*
|
|
430
|
+
* This does NOT consult capability lists or live probe state; `PATCH
|
|
431
|
+
* /api/integrations/:key` already enforces `requiredCapabilities` against
|
|
432
|
+
* the live probe before a delegated flip is accepted, and the router does
|
|
433
|
+
* not re-run that check at dispatch time.
|
|
434
|
+
*/
|
|
435
|
+
export declare function backendHasIntegrationConnector(integrationKey: IntegrationKey, backendId: BackendId): boolean;
|
|
436
|
+
/**
|
|
437
|
+
* DELEGATED-MODE-V2-DESIGN.md §4.3.5 — match a deny pattern against a single
|
|
438
|
+
* tool name. Patterns are bare unsuffixed tool names — no `mcp__*` prefix,
|
|
439
|
+
* no leading underscore (the connector's `toolNamespace` already terminates
|
|
440
|
+
* as needed; e.g. Codex Gmail's namespace is `mcp__codex_apps__gmail._`,
|
|
441
|
+
* so the bare match key is `send_email`, not `_send_email`). Optionally
|
|
442
|
+
* suffixed with `*`:
|
|
443
|
+
*
|
|
444
|
+
* `send_email` — exact match
|
|
445
|
+
* `send_*` — prefix match, anything starting with `send_`
|
|
446
|
+
* `*` — matches anything (deny everything; rare)
|
|
447
|
+
*
|
|
448
|
+
* Anchors are implicit; `*` is only honored as a suffix to keep the pattern
|
|
449
|
+
* language single-purpose. `*` mid-string is treated as literal text.
|
|
450
|
+
*
|
|
451
|
+
* Used by `validateDeniedTools` (typo defense at PATCH time),
|
|
452
|
+
* `filterDeniedToolsForBackend` (active/stale partition during
|
|
453
|
+
* materialization), and the `/api/integrations/:key/invoke` chokepoint
|
|
454
|
+
* (per-call deny enforcement).
|
|
455
|
+
*/
|
|
456
|
+
export declare function matchToolPattern(pattern: string, tool: string): boolean;
|
|
457
|
+
export type ValidateDeniedToolsResult = {
|
|
458
|
+
ok: true;
|
|
459
|
+
} | {
|
|
460
|
+
ok: false;
|
|
461
|
+
error: "no_connector";
|
|
462
|
+
backendId: BackendId;
|
|
463
|
+
} | {
|
|
464
|
+
ok: false;
|
|
465
|
+
error: "unknown_tool";
|
|
466
|
+
tool: string;
|
|
467
|
+
knownTools: readonly string[];
|
|
468
|
+
} | {
|
|
469
|
+
ok: false;
|
|
470
|
+
error: "denial_breaks_required_capability";
|
|
471
|
+
capability: string;
|
|
472
|
+
remainingTools: readonly string[];
|
|
473
|
+
};
|
|
474
|
+
/**
|
|
475
|
+
* Validate a proposed `deniedTools` list against an integration's
|
|
476
|
+
* descriptor for a given `delegatedBackend`. Returns the first failure;
|
|
477
|
+
* callers map this to the documented 400 shapes.
|
|
478
|
+
*
|
|
479
|
+
* Patterns: each entry is either an exact tool name (e.g. `_send_email`)
|
|
480
|
+
* or a `*`-suffixed glob (e.g. `_delete_*`, `*`). See {@link matchToolPattern}.
|
|
481
|
+
*
|
|
482
|
+
* - **`unknown_tool`**: an exact entry isn't in any of the connector's
|
|
483
|
+
* `capabilityTools` arrays, OR a glob entry matches no known tool
|
|
484
|
+
* (typo defense for both forms). Helps users catch typos and stale
|
|
485
|
+
* Claude / Codex names after a backend swap. (Note: the *materializer*
|
|
486
|
+
* tolerates stale entries silently per §7.7 — but PATCH is strict so
|
|
487
|
+
* the user sees the typo before saving. The dashboard's stale-entries
|
|
488
|
+
* UI handles the soft case after a backend flip.)
|
|
489
|
+
* - **`denial_breaks_required_capability`**: collectively, the proposal
|
|
490
|
+
* drops every tool that satisfies at least one `requiredCapability`.
|
|
491
|
+
* Multi-cap overlap matters — Notion's `notion-update-page` covers
|
|
492
|
+
* `update_properties`, `patch_content`, `archive`, and `apply_template`,
|
|
493
|
+
* so denying it breaks all four required caps at once. The error names
|
|
494
|
+
* the first failing capability and lists what's still in the
|
|
495
|
+
* `capabilityTools[capability]` set after the deny — so the dashboard
|
|
496
|
+
* can show a "you'd need to keep X, Y, or Z" hint without a second call.
|
|
497
|
+
* Globs are expanded against the connector's known tools before the
|
|
498
|
+
* capability-coverage check runs.
|
|
499
|
+
*/
|
|
500
|
+
export declare function validateDeniedTools(integrationKey: IntegrationKey, backendId: BackendId, deniedTools: readonly string[]): ValidateDeniedToolsResult;
|
|
501
|
+
/**
|
|
502
|
+
* Filter a `deniedTools` list down to entries that exist in the active
|
|
503
|
+
* backend's capability tools, expanding glob patterns. Used by the
|
|
504
|
+
* materializer to silently drop stale names after a `delegatedBackend`
|
|
505
|
+
* swap (§7.7 mode-flip behavior) and by `collectSessionDeniedTools` to
|
|
506
|
+
* produce concrete namespaced tool names for backend `disallowedTools`.
|
|
507
|
+
*
|
|
508
|
+
* The output `active` list is the **expanded** concrete tool name set
|
|
509
|
+
* (globs replaced by their matches) so callers can feed it directly into
|
|
510
|
+
* an SDK `disallowedTools` array or `applyDeniedTools`. `stale` carries
|
|
511
|
+
* the original user-entered patterns that matched nothing on this
|
|
512
|
+
* backend's tool universe (typo or post-swap leftover).
|
|
513
|
+
*
|
|
514
|
+
* Distinct from `validateDeniedTools` — the API rejects unknown tools at
|
|
515
|
+
* PATCH time, but a user who flips claude → codex carries Claude-namespaced
|
|
516
|
+
* entries that the API didn't see at PATCH time. The materializer ignores
|
|
517
|
+
* them; the dashboard surfaces them as "stale" so the user can clean up.
|
|
518
|
+
*/
|
|
519
|
+
export declare function filterDeniedToolsForBackend(integrationKey: IntegrationKey, backendId: BackendId, deniedTools: readonly string[]): {
|
|
520
|
+
active: string[];
|
|
521
|
+
stale: string[];
|
|
522
|
+
};
|
|
523
|
+
/**
|
|
524
|
+
* Lookup the recommended starter denylist for `(integrationKey,
|
|
525
|
+
* backendId)`. Returns a fresh array each call so the caller can store it
|
|
526
|
+
* directly without aliasing the registry constant.
|
|
527
|
+
*/
|
|
528
|
+
export declare function recommendedStarterDeniedTools(integrationKey: IntegrationKey, backendId: BackendId): string[];
|
|
529
|
+
/**
|
|
530
|
+
* DELEGATED-TASK-MODE-DESIGN.md §7.3 — destructive tool list for
|
|
531
|
+
* `(integrationKey, backendId)`, returned as **fully-qualified names**
|
|
532
|
+
* (`toolNamespace + bareName`). Used by `runDelegatedTask` to feed into
|
|
533
|
+
* SDK `disallowedTools` (Claude) or admin-policy deny rules (Gemini)
|
|
534
|
+
* when `allowDestructive: false`.
|
|
535
|
+
*
|
|
536
|
+
* Returns `[]` when the backend has no connector for the integration
|
|
537
|
+
* (forward-compat: this never happens today; every backend has a
|
|
538
|
+
* connector for every registered integration).
|
|
539
|
+
*/
|
|
540
|
+
export declare function destructiveTaskTools(integrationKey: IntegrationKey, backendId: BackendId): string[];
|
|
541
|
+
/**
|
|
542
|
+
* DELEGATED-TASK-MODE-DESIGN.md §7.3 — bare-name version of
|
|
543
|
+
* {@link destructiveTaskTools}, returned WITHOUT the `toolNamespace`
|
|
544
|
+
* prefix. Used by anti-prompt-injection assertions and by callers that
|
|
545
|
+
* already namespace separately.
|
|
546
|
+
*/
|
|
547
|
+
export declare function destructiveTaskToolsBare(integrationKey: IntegrationKey, backendId: BackendId): string[];
|
|
548
|
+
/**
|
|
549
|
+
* DELEGATED-MODE-V2-DESIGN.md §4.3.3 — collect every `deniedTools` entry
|
|
550
|
+
* that applies to the **session backend's own native MCP** (the
|
|
551
|
+
* "same-backend" delegated state). For each integration whose
|
|
552
|
+
* `delegatedBackend === sessionBackend`, expand the user's deny patterns
|
|
553
|
+
* against the connector's known tools and return the namespaced tool names
|
|
554
|
+
* (`mcp__<connector>__<tool>`) ready to drop into:
|
|
555
|
+
*
|
|
556
|
+
* - Claude Code SDK `disallowedTools` array (hard enforcement)
|
|
557
|
+
* - Gemini admin policy `denied_tools` rules (hard enforcement)
|
|
558
|
+
* - Codex agent profile prose block (soft enforcement — accepted gap,
|
|
559
|
+
* §4.3.4 outcome γ)
|
|
560
|
+
*
|
|
561
|
+
* Cross-backend (delegatedBackend !== sessionBackend) integrations are
|
|
562
|
+
* excluded — those calls go through `/api/integrations/:key/invoke` which
|
|
563
|
+
* enforces deny at the daemon chokepoint (§4.3.2). Disabled / direct
|
|
564
|
+
* integrations are excluded — deny only applies to delegated mode.
|
|
565
|
+
*
|
|
566
|
+
* Returns a `Map` keyed by integration so callers can attribute denies
|
|
567
|
+
* per-integration in logs / prose. Empty entries are omitted.
|
|
568
|
+
*/
|
|
569
|
+
export declare function collectSessionDeniedTools(integrations: Partial<Record<IntegrationKey, IntegrationState>>, sessionBackend: BackendId): Map<IntegrationKey, string[]>;
|
|
570
|
+
/**
|
|
571
|
+
* Predicates accepted by `applyIntegrationModeFilter`. Each one keeps the
|
|
572
|
+
* wrapped section when its condition holds for the given integration key
|
|
573
|
+
* and session backend.
|
|
574
|
+
*/
|
|
575
|
+
export declare const INTEGRATION_MODE_PREDICATES: readonly ["direct", "delegated", "delegated-same", "delegated-cross", "disabled"];
|
|
576
|
+
export type IntegrationModePredicate = (typeof INTEGRATION_MODE_PREDICATES)[number];
|
|
577
|
+
/**
|
|
578
|
+
* Strip mode-conditional sections from a task-flow or skill body based on
|
|
579
|
+
* current integration state and session backend. Mirrors the
|
|
580
|
+
* `<!-- service:* -->` family used by `stripUnconfiguredServices` in
|
|
581
|
+
* skills-compiler.ts.
|
|
582
|
+
*
|
|
583
|
+
* Section syntax (HTML comment delimiters, kept literal so authoring stays
|
|
584
|
+
* markdown-friendly):
|
|
585
|
+
*
|
|
586
|
+
* <!-- mode:<predicate>:<key> -->
|
|
587
|
+
* ...content shown only when the predicate holds...
|
|
588
|
+
* <!-- /mode:<predicate>:<key> -->
|
|
589
|
+
*
|
|
590
|
+
* Predicates and the state they keep content for:
|
|
591
|
+
*
|
|
592
|
+
* direct — `integrations[key].mode === "direct"`
|
|
593
|
+
* delegated — `mode === "delegated"` (regardless of which backend)
|
|
594
|
+
* delegated-same — delegated AND `delegatedBackend === sessionBackend`
|
|
595
|
+
* (the connector is signed in to this same session's
|
|
596
|
+
* backend; the agent uses native MCP tools and skill
|
|
597
|
+
* bodies are typically not materialized)
|
|
598
|
+
* delegated-cross — delegated AND `delegatedBackend !== sessionBackend`
|
|
599
|
+
* (the agent reaches the connector via the daemon
|
|
600
|
+
* proxy at `POST /api/integrations/:key/invoke`)
|
|
601
|
+
* disabled — `mode === "disabled"` OR no state row (treated as
|
|
602
|
+
* disabled by `defaultIntegrationsMap`)
|
|
603
|
+
*
|
|
604
|
+
* Behaviour notes:
|
|
605
|
+
*
|
|
606
|
+
* - **Unknown predicate**: section preserved verbatim. Surfaces the typo in
|
|
607
|
+
* the rendered prompt rather than silently losing or duplicating prose.
|
|
608
|
+
* - **Unknown integration key**: section preserved verbatim. Same rationale —
|
|
609
|
+
* a misspelled key (or registry drift mid-deploy) should remain visible.
|
|
610
|
+
* - **Sections do not nest**: the regex is non-greedy and matches the
|
|
611
|
+
* first close tag. Two sibling blocks at the same level work; nesting
|
|
612
|
+
* a same-key block inside another doesn't and is unsupported.
|
|
613
|
+
* - **Idempotent**: running the filter twice on the same content with the
|
|
614
|
+
* same state produces identical output.
|
|
615
|
+
*
|
|
616
|
+
* Apply this AFTER any whole-file variant selection (e.g. `SKILL.delegated.
|
|
617
|
+
* <backend>.md`) so the variant author can use mode markers freely without
|
|
618
|
+
* worrying about pre-filtering interactions.
|
|
619
|
+
*/
|
|
620
|
+
export declare function applyIntegrationModeFilter(content: string, integrations: Partial<Record<IntegrationKey, IntegrationState>>, sessionBackend: BackendId): string;
|
|
621
|
+
/**
|
|
622
|
+
* Validation regex for an `allowedTools` entry on `POST /api/delegated/run`
|
|
623
|
+
* (Phase 2 generic task mode for unregistered MCPs).
|
|
624
|
+
*
|
|
625
|
+
* Spec §4.2 reads: "Specifically rejected: bare `*`, patterns starting with
|
|
626
|
+
* `*`, prefixes shorter than 4 characters before `*` (e.g. `mcp_*`), and
|
|
627
|
+
* anything containing shell metacharacters." The literal example `mcp_*`
|
|
628
|
+
* has a 4-character prefix yet must be rejected — i.e. the spec's prose
|
|
629
|
+
* intent is "≥5 chars before `*`," and the {4,} quantifier in the literal
|
|
630
|
+
* regex contradicts the example. We honor the example: prefix-before-`*`
|
|
631
|
+
* must be ≥5 chars, and bare/leading `*` is rejected outright.
|
|
632
|
+
*
|
|
633
|
+
* Allowed shape:
|
|
634
|
+
* - 5+ chars of `[A-Za-z0-9_-]` to start.
|
|
635
|
+
* - Optional dotted/underscored continuation segments
|
|
636
|
+
* (`([._][A-Za-z0-9_-]+)*`).
|
|
637
|
+
* - Optional trailing `*` for a glob.
|
|
638
|
+
*
|
|
639
|
+
* Examples accepted: `mcp_my-server_*`, `mcp_my-server_subtool.action`,
|
|
640
|
+
* `mcp__custom-srv_doIt`. Examples rejected: `*`, `*foo`, `mcp_*`,
|
|
641
|
+
* `mcp_my-server_*.action`, `srv;rm -rf /`.
|
|
642
|
+
*
|
|
643
|
+
* Shell-metacharacter rejection is doubled-up: even if a pattern slipped
|
|
644
|
+
* through the regex (it can't — the character class excludes them), the
|
|
645
|
+
* dedicated check in {@link validateRunAllowedTool} would reject. This
|
|
646
|
+
* keeps the safety floor obvious in review.
|
|
647
|
+
*/
|
|
648
|
+
export declare const MCP_PATTERN_REGEX: RegExp;
|
|
649
|
+
export type ValidateRunAllowedToolsResult = {
|
|
650
|
+
ok: true;
|
|
651
|
+
} | {
|
|
652
|
+
ok: false;
|
|
653
|
+
errorClass: "bad_allowed_tools";
|
|
654
|
+
pattern: string;
|
|
655
|
+
reason: "empty" | "bare_star" | "leading_star" | "prefix_too_short" | "shell_metachar" | "shape_invalid";
|
|
656
|
+
message: string;
|
|
657
|
+
};
|
|
658
|
+
/** Validate a single pattern entry. Exported for unit tests. */
|
|
659
|
+
export declare function validateRunAllowedTool(pattern: unknown): ValidateRunAllowedToolsResult;
|
|
660
|
+
/**
|
|
661
|
+
* Validate every entry in a `/api/delegated/run` `allowedTools` array.
|
|
662
|
+
* Returns the first failing entry (HTTP 400 maps to that), or `{ok: true}`
|
|
663
|
+
* if every pattern is well-formed and the array is non-empty.
|
|
664
|
+
*/
|
|
665
|
+
export declare function validateRunAllowedTools(patterns: readonly unknown[]): ValidateRunAllowedToolsResult;
|
|
666
|
+
/**
|
|
667
|
+
* Match an `/api/delegated/run` allowedTools entry against a fully
|
|
668
|
+
* qualified tool name observed in the subprocess stream. Mirrors the
|
|
669
|
+
* `matchToolPattern` semantics used elsewhere — exact equality or
|
|
670
|
+
* `*`-suffix prefix match — but the input space is fully-qualified MCP
|
|
671
|
+
* names, not the bare deny vocabulary, so we expose it as a separate
|
|
672
|
+
* symbol.
|
|
673
|
+
*/
|
|
674
|
+
export declare function matchRunAllowedToolPattern(pattern: string, tool: string): boolean;
|
|
675
|
+
//# sourceMappingURL=integrations.d.ts.map
|