@intentic/extension-manifest 1.326.0 → 1.327.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.
@@ -104,6 +104,86 @@ const ProbeSchema = z.object({
104
104
  .describe("Accept a self-signed certificate, for a service whose local install ships one (Obsidian's Local REST API)."),
105
105
  });
106
106
 
107
+ // How a cli card's credential reaches the services it is for without ever reaching the agent: the sandbox's credential
108
+ // gateway, a loopback-only listener the agent's shell calls instead of the service. The gateway picks the upstream from
109
+ // this declaration (never from the request), attaches the credential the way the service takes it, checks the card's
110
+ // rules and gates, and forwards. The agent's env holds the gateway's address and, where a tool insists on a token
111
+ // variable, an inert placeholder.
112
+ const BrokerRouteSchema = z.object({
113
+ upstream: z
114
+ .string()
115
+ .min(1)
116
+ .describe(
117
+ "The service's base URL, a template over the fields like `env` (`https://api.github.com`, `${url}`). What is sent to this route's gateway address goes here and nowhere else.",
118
+ ),
119
+ env: z
120
+ .string()
121
+ .regex(/^[A-Z][A-Z0-9_]*$/)
122
+ .optional()
123
+ .describe(
124
+ "The variable the agent's shell finds this route's gateway address in (`GITHUB_API_URL`), suffixed per instance like `env`. Naming one of `env`'s own variables (`GITLAB_URL`) points it at the gateway instead of the service, so a skill written against it needs no change.",
125
+ ),
126
+ headers: z
127
+ .record(z.string(), z.string())
128
+ .optional()
129
+ .describe(
130
+ 'The headers that carry the credential, templated over the fields (`{"authorization": "Bearer ${token}"}`). The gateway sets them on every request it forwards, replacing any the agent sent under the same name.',
131
+ ),
132
+ basic: z
133
+ .object({ username: z.string(), password: z.string() })
134
+ .optional()
135
+ .describe(
136
+ "HTTP Basic credentials, templated over the fields, for a service that takes them (git over HTTPS: `x-access-token` and `${token}`).",
137
+ ),
138
+ form: z
139
+ .record(z.string(), z.string())
140
+ .optional()
141
+ .describe(
142
+ "Fields the gateway sets in a request's url-encoded form body, templated over the fields, for a service that takes its credential there: an OAuth token exchange's `client_secret` or `refresh_token`. What the exchange answers (a short-lived access token) is the agent's to use; the long-lived secret never is.",
143
+ ),
144
+ pathPrefix: z
145
+ .string()
146
+ .startsWith("/")
147
+ .optional()
148
+ .describe(
149
+ "A path the gateway puts before the agent's own, templated over the fields, for a service that takes its credential in the path (Telegram's `/bot${token}`).",
150
+ ),
151
+ git: z
152
+ .boolean()
153
+ .optional()
154
+ .describe(
155
+ "This upstream serves git over HTTP: the agent's git is pointed at the gateway for it (`url.<gateway>.insteadOf`), so a clone, fetch or push needs no credential in the agent's hands.",
156
+ ),
157
+ });
158
+ export type BrokerRoute = z.infer<typeof BrokerRouteSchema>;
159
+
160
+ export const BrokerRuleSchema = z.object({
161
+ methods: z
162
+ .array(z.string().regex(/^[A-Z]+$/))
163
+ .optional()
164
+ .describe("The HTTP methods it covers (`DELETE`, `PUT`); absent covers every method."),
165
+ paths: z
166
+ .array(z.string().startsWith("/"))
167
+ .optional()
168
+ .describe(
169
+ "The paths it covers, below the route's upstream: `*` matches one segment, `**` any number of them (`/repos/*/*/hooks/**`). Absent covers every path.",
170
+ ),
171
+ action: z.enum(["allow", "ask", "deny"]).describe("`allow` forwards it, `ask` holds it on a card for the owner, `deny` refuses it."),
172
+ why: z.string().optional().describe("One line on what the rule protects, shown on the card or in the refusal."),
173
+ });
174
+ export type BrokerRule = z.infer<typeof BrokerRuleSchema>;
175
+
176
+ export const BrokerSchema = z.object({
177
+ routes: z.array(BrokerRouteSchema).min(1),
178
+ rules: z
179
+ .array(BrokerRuleSchema)
180
+ .optional()
181
+ .describe(
182
+ "What the credential may do, checked in order against each request the gateway forwards; the first rule covering a request decides, and one no rule covers is allowed. The owner's own rules for a card replace these.",
183
+ ),
184
+ });
185
+ export type Broker = z.infer<typeof BrokerSchema>;
186
+
107
187
  // The install-dialog card: how it looks in the grid and how the user gets its credential. Shared by every kind below.
108
188
  const CatalogSchema = z.object({
109
189
  name: z.string().min(1),
@@ -191,6 +271,10 @@ export const CapabilityContributionSchema = z
191
271
  .describe(
192
272
  "The hosts this card's credential is meant for, as templates over the fields like `env` (`api.github.com`, `*.githubusercontent.com`, `${url}`); a value that comes out as a URL counts as its host. The sandbox limits the credential's `{{secret:…}}` reference to them by default, so a use aimed anywhere else asks a person first. The owner can change or lift the list on the Secrets view.",
193
273
  ),
274
+ // Only narrows how the credential is used, so it carries no effect: nothing here grants the extension reach.
275
+ broker: BrokerSchema.optional().describe(
276
+ "Route the credential through the sandbox's credential gateway instead of handing it to the agent: per upstream, the variable carrying the gateway's address and how the credential is attached, plus optional method and path rules. Every `env` variable whose template names a secret field then holds an inert placeholder. Declare it on every card whose service is spoken to over HTTP.",
277
+ ),
194
278
  // The first way a card served tools, kept one release as an alias of `contributes.tools` with this card as
195
279
  // `perCard` and this value as `path` (points/tools.ts); a manifest declaring both is served by `tools`.
196
280
  mcp: z
@@ -246,10 +330,23 @@ export const CapabilityContributionSchema = z
246
330
  .object({
247
331
  ...contributionBase,
248
332
  kind: z.literal("webext"),
249
- install: z.url().optional().describe("Where this browser's extension is installed from: its store listing, or a page offering the build."),
333
+ install: z
334
+ .url()
335
+ .optional()
336
+ .describe("Where this browser's extension is installed from: its store listing, or a page offering the build."),
250
337
  skill: z.string().min(1).describe("Checkout-relative SKILL.md teaching the agent to drive this browser."),
251
338
  })
252
339
  .meta({ mintsServer: true }),
340
+ // A phone family the user connects their own phone of, through an app installed on it; `install` is where that
341
+ // app comes from (a store listing, or a page offering the build), omitted until one exists.
342
+ z
343
+ .object({
344
+ ...contributionBase,
345
+ kind: z.literal("phone"),
346
+ install: z.url().optional().describe("Where this phone's app is installed from: its store listing, or a page offering the build."),
347
+ skill: z.string().min(1).describe("Checkout-relative SKILL.md teaching the agent to work on this phone."),
348
+ })
349
+ .meta({ mintsServer: true }),
253
350
  // A preset over a core kind: no payload, just a name, a logo and a filled-in form.
254
351
  z.object({ ...contributionBase, kind: z.literal("agent") }),
255
352
  ])
@@ -275,10 +372,14 @@ export type SkillContribution = Extract<CapabilityContribution, { skill: string
275
372
 
276
373
  // The config key a kind's cards pin to their own id, so a stored capability traces back to its card. `agent` has none:
277
374
  // its cards differ only in defaults.
278
- const DISCRIMINATOR = { cli: "provider", browser: "platform", device: "platform", webext: "platform", agent: undefined } satisfies Record<
279
- CapabilityContribution["kind"],
280
- string | undefined
281
- >;
375
+ const DISCRIMINATOR = {
376
+ cli: "provider",
377
+ browser: "platform",
378
+ device: "platform",
379
+ webext: "platform",
380
+ phone: "platform",
381
+ agent: undefined,
382
+ } satisfies Record<CapabilityContribution["kind"], string | undefined>;
282
383
  export const contributionDiscriminator = (kind: string): string | undefined => DISCRIMINATOR[kind as keyof typeof DISCRIMINATOR];
283
384
 
284
385
  // Which contributed card a configured capability was added from, undefined when none was: the only link between a
@@ -309,11 +410,15 @@ export const contributedServerMintingKinds = (): ReadonlySet<CapabilityContribut
309
410
  const kinds = new Set<CapabilityContribution["kind"]>();
310
411
  for (const option of CapabilityContributionSchema.options) {
311
412
  const shape = option.shape as Record<string, z.ZodType>;
312
- const kind = (shape["kind"]?._zod.def as { values?: readonly string[] } | undefined)?.values?.[0] as CapabilityContribution["kind"] | undefined;
413
+ const kind = (shape["kind"]?._zod.def as { values?: readonly string[] } | undefined)?.values?.[0] as
414
+ CapabilityContribution["kind"] | undefined;
313
415
  if (kind === undefined) {
314
416
  continue;
315
417
  }
316
- if (unwrapMeaning(option).meaning.mintsServer === true || [...fieldMeanings(option).values()].some((meaning) => meaning.mintsServer === true)) {
418
+ if (
419
+ unwrapMeaning(option).meaning.mintsServer === true ||
420
+ [...fieldMeanings(option).values()].some((meaning) => meaning.mintsServer === true)
421
+ ) {
317
422
  kinds.add(kind);
318
423
  }
319
424
  }