@intentic/extension-manifest 1.326.0 → 1.328.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/README.md +4 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/manifest.d.ts +66 -0
- package/dist/manifest.d.ts.map +1 -1
- package/dist/mark.d.ts +1 -0
- package/dist/mark.d.ts.map +1 -1
- package/dist/mark.js +1 -1
- package/dist/mark.js.map +1 -1
- package/dist/permissions.d.ts +7 -0
- package/dist/permissions.d.ts.map +1 -1
- package/dist/permissions.js +13 -0
- package/dist/permissions.js.map +1 -1
- package/dist/points/capabilities.d.ts +182 -0
- package/dist/points/capabilities.d.ts.map +1 -1
- package/dist/points/capabilities.js +74 -3
- package/dist/points/capabilities.js.map +1 -1
- package/dist/points/index.d.ts +132 -0
- package/dist/points/index.d.ts.map +1 -1
- package/intentic-extension.schema.json +309 -0
- package/package.json +14 -3
- package/src/index.ts +1 -0
- package/src/mark.ts +3 -2
- package/src/permissions.test.ts +21 -1
- package/src/permissions.ts +33 -0
- package/src/points/capabilities.ts +112 -7
package/dist/points/index.d.ts
CHANGED
|
@@ -175,6 +175,30 @@ export declare const CONTRIBUTION_POINTS: readonly [{
|
|
|
175
175
|
insecure: z.ZodOptional<z.ZodBoolean>;
|
|
176
176
|
}, z.core.$strip>>;
|
|
177
177
|
hosts: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
178
|
+
broker: z.ZodOptional<z.ZodObject<{
|
|
179
|
+
routes: z.ZodArray<z.ZodObject<{
|
|
180
|
+
upstream: z.ZodString;
|
|
181
|
+
env: z.ZodOptional<z.ZodString>;
|
|
182
|
+
headers: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
183
|
+
basic: z.ZodOptional<z.ZodObject<{
|
|
184
|
+
username: z.ZodString;
|
|
185
|
+
password: z.ZodString;
|
|
186
|
+
}, z.core.$strip>>;
|
|
187
|
+
form: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
188
|
+
pathPrefix: z.ZodOptional<z.ZodString>;
|
|
189
|
+
git: z.ZodOptional<z.ZodBoolean>;
|
|
190
|
+
}, z.core.$strip>>;
|
|
191
|
+
rules: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
192
|
+
methods: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
193
|
+
paths: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
194
|
+
action: z.ZodEnum<{
|
|
195
|
+
allow: "allow";
|
|
196
|
+
ask: "ask";
|
|
197
|
+
deny: "deny";
|
|
198
|
+
}>;
|
|
199
|
+
why: z.ZodOptional<z.ZodString>;
|
|
200
|
+
}, z.core.$strip>>>;
|
|
201
|
+
}, z.core.$strip>>;
|
|
178
202
|
mcp: z.ZodOptional<z.ZodString>;
|
|
179
203
|
}, z.core.$strip>, z.ZodObject<{
|
|
180
204
|
id: z.ZodString;
|
|
@@ -302,6 +326,48 @@ export declare const CONTRIBUTION_POINTS: readonly [{
|
|
|
302
326
|
kind: z.ZodLiteral<"webext">;
|
|
303
327
|
install: z.ZodOptional<z.ZodURL>;
|
|
304
328
|
skill: z.ZodString;
|
|
329
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
330
|
+
id: z.ZodString;
|
|
331
|
+
catalog: z.ZodObject<{
|
|
332
|
+
art: z.ZodOptional<z.ZodString>;
|
|
333
|
+
logo: z.ZodOptional<z.ZodString>;
|
|
334
|
+
icon: z.ZodOptional<z.ZodString>;
|
|
335
|
+
name: z.ZodString;
|
|
336
|
+
description: z.ZodString;
|
|
337
|
+
category: z.ZodString;
|
|
338
|
+
hint: z.ZodOptional<z.ZodString>;
|
|
339
|
+
guide: z.ZodOptional<z.ZodObject<{
|
|
340
|
+
url: z.ZodOptional<z.ZodString>;
|
|
341
|
+
urlFromField: z.ZodOptional<z.ZodString>;
|
|
342
|
+
path: z.ZodOptional<z.ZodString>;
|
|
343
|
+
linkLabel: z.ZodOptional<z.ZodString>;
|
|
344
|
+
scopes: z.ZodOptional<z.ZodString>;
|
|
345
|
+
steps: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
346
|
+
}, z.core.$strip>>;
|
|
347
|
+
}, z.core.$strip>;
|
|
348
|
+
fields: z.ZodArray<z.ZodObject<{
|
|
349
|
+
key: z.ZodString;
|
|
350
|
+
label: z.ZodString;
|
|
351
|
+
placeholder: z.ZodOptional<z.ZodString>;
|
|
352
|
+
secret: z.ZodOptional<z.ZodBoolean>;
|
|
353
|
+
optional: z.ZodOptional<z.ZodBoolean>;
|
|
354
|
+
multiline: z.ZodOptional<z.ZodBoolean>;
|
|
355
|
+
advanced: z.ZodOptional<z.ZodBoolean>;
|
|
356
|
+
boolean: z.ZodOptional<z.ZodBoolean>;
|
|
357
|
+
hint: z.ZodOptional<z.ZodString>;
|
|
358
|
+
rebuild: z.ZodOptional<z.ZodBoolean>;
|
|
359
|
+
default: z.ZodOptional<z.ZodString>;
|
|
360
|
+
options: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
361
|
+
value: z.ZodString;
|
|
362
|
+
label: z.ZodString;
|
|
363
|
+
}, z.core.$strip>>>;
|
|
364
|
+
when: z.ZodOptional<z.ZodString>;
|
|
365
|
+
value: z.ZodOptional<z.ZodString>;
|
|
366
|
+
totp: z.ZodOptional<z.ZodBoolean>;
|
|
367
|
+
}, z.core.$strip>>;
|
|
368
|
+
kind: z.ZodLiteral<"phone">;
|
|
369
|
+
install: z.ZodOptional<z.ZodURL>;
|
|
370
|
+
skill: z.ZodString;
|
|
305
371
|
}, z.core.$strip>, z.ZodObject<{
|
|
306
372
|
id: z.ZodString;
|
|
307
373
|
catalog: z.ZodObject<{
|
|
@@ -515,6 +581,30 @@ export declare const contributesSchema: z.ZodObject<{
|
|
|
515
581
|
insecure: z.ZodOptional<z.ZodBoolean>;
|
|
516
582
|
}, z.core.$strip>>;
|
|
517
583
|
hosts: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
584
|
+
broker: z.ZodOptional<z.ZodObject<{
|
|
585
|
+
routes: z.ZodArray<z.ZodObject<{
|
|
586
|
+
upstream: z.ZodString;
|
|
587
|
+
env: z.ZodOptional<z.ZodString>;
|
|
588
|
+
headers: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
589
|
+
basic: z.ZodOptional<z.ZodObject<{
|
|
590
|
+
username: z.ZodString;
|
|
591
|
+
password: z.ZodString;
|
|
592
|
+
}, z.core.$strip>>;
|
|
593
|
+
form: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
594
|
+
pathPrefix: z.ZodOptional<z.ZodString>;
|
|
595
|
+
git: z.ZodOptional<z.ZodBoolean>;
|
|
596
|
+
}, z.core.$strip>>;
|
|
597
|
+
rules: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
598
|
+
methods: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
599
|
+
paths: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
600
|
+
action: z.ZodEnum<{
|
|
601
|
+
allow: "allow";
|
|
602
|
+
ask: "ask";
|
|
603
|
+
deny: "deny";
|
|
604
|
+
}>;
|
|
605
|
+
why: z.ZodOptional<z.ZodString>;
|
|
606
|
+
}, z.core.$strip>>>;
|
|
607
|
+
}, z.core.$strip>>;
|
|
518
608
|
mcp: z.ZodOptional<z.ZodString>;
|
|
519
609
|
}, z.core.$strip>, z.ZodObject<{
|
|
520
610
|
id: z.ZodString;
|
|
@@ -642,6 +732,48 @@ export declare const contributesSchema: z.ZodObject<{
|
|
|
642
732
|
kind: z.ZodLiteral<"webext">;
|
|
643
733
|
install: z.ZodOptional<z.ZodURL>;
|
|
644
734
|
skill: z.ZodString;
|
|
735
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
736
|
+
id: z.ZodString;
|
|
737
|
+
catalog: z.ZodObject<{
|
|
738
|
+
art: z.ZodOptional<z.ZodString>;
|
|
739
|
+
logo: z.ZodOptional<z.ZodString>;
|
|
740
|
+
icon: z.ZodOptional<z.ZodString>;
|
|
741
|
+
name: z.ZodString;
|
|
742
|
+
description: z.ZodString;
|
|
743
|
+
category: z.ZodString;
|
|
744
|
+
hint: z.ZodOptional<z.ZodString>;
|
|
745
|
+
guide: z.ZodOptional<z.ZodObject<{
|
|
746
|
+
url: z.ZodOptional<z.ZodString>;
|
|
747
|
+
urlFromField: z.ZodOptional<z.ZodString>;
|
|
748
|
+
path: z.ZodOptional<z.ZodString>;
|
|
749
|
+
linkLabel: z.ZodOptional<z.ZodString>;
|
|
750
|
+
scopes: z.ZodOptional<z.ZodString>;
|
|
751
|
+
steps: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
752
|
+
}, z.core.$strip>>;
|
|
753
|
+
}, z.core.$strip>;
|
|
754
|
+
fields: z.ZodArray<z.ZodObject<{
|
|
755
|
+
key: z.ZodString;
|
|
756
|
+
label: z.ZodString;
|
|
757
|
+
placeholder: z.ZodOptional<z.ZodString>;
|
|
758
|
+
secret: z.ZodOptional<z.ZodBoolean>;
|
|
759
|
+
optional: z.ZodOptional<z.ZodBoolean>;
|
|
760
|
+
multiline: z.ZodOptional<z.ZodBoolean>;
|
|
761
|
+
advanced: z.ZodOptional<z.ZodBoolean>;
|
|
762
|
+
boolean: z.ZodOptional<z.ZodBoolean>;
|
|
763
|
+
hint: z.ZodOptional<z.ZodString>;
|
|
764
|
+
rebuild: z.ZodOptional<z.ZodBoolean>;
|
|
765
|
+
default: z.ZodOptional<z.ZodString>;
|
|
766
|
+
options: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
767
|
+
value: z.ZodString;
|
|
768
|
+
label: z.ZodString;
|
|
769
|
+
}, z.core.$strip>>>;
|
|
770
|
+
when: z.ZodOptional<z.ZodString>;
|
|
771
|
+
value: z.ZodOptional<z.ZodString>;
|
|
772
|
+
totp: z.ZodOptional<z.ZodBoolean>;
|
|
773
|
+
}, z.core.$strip>>;
|
|
774
|
+
kind: z.ZodLiteral<"phone">;
|
|
775
|
+
install: z.ZodOptional<z.ZodURL>;
|
|
776
|
+
skill: z.ZodString;
|
|
645
777
|
}, z.core.$strip>, z.ZodObject<{
|
|
646
778
|
id: z.ZodString;
|
|
647
779
|
catalog: z.ZodObject<{
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/points/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAkBxB,cAAc,YAAY,CAAC;AAC3B,cAAc,2BAA2B,CAAC;AAC1C,cAAc,UAAU,CAAC;AACzB,cAAc,mBAAmB,CAAC;AAClC,cAAc,eAAe,CAAC;AAC9B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,kBAAkB,CAAC;AACjC,cAAc,YAAY,CAAC;AAC3B,cAAc,eAAe,CAAC;AAC9B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,eAAe,CAAC;AAC9B,cAAc,iBAAiB,CAAC;AAChC,cAAc,YAAY,CAAC;AAC3B,cAAc,cAAc,CAAC;AAC7B,cAAc,YAAY,CAAC;AAK3B,eAAO,MAAM,mBAAmB
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/points/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAkBxB,cAAc,YAAY,CAAC;AAC3B,cAAc,2BAA2B,CAAC;AAC1C,cAAc,UAAU,CAAC;AACzB,cAAc,mBAAmB,CAAC;AAClC,cAAc,eAAe,CAAC;AAC9B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,kBAAkB,CAAC;AACjC,cAAc,YAAY,CAAC;AAC3B,cAAc,eAAe,CAAC;AAC9B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,eAAe,CAAC;AAC9B,cAAc,iBAAiB,CAAC;AAChC,cAAc,YAAY,CAAC;AAC3B,cAAc,cAAc,CAAC;AAC7B,cAAc,YAAY,CAAC;AAK3B,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAgBiB,CAAC;AAUlD,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAE7B,CAAC"}
|
|
@@ -730,6 +730,129 @@
|
|
|
730
730
|
"minLength": 1
|
|
731
731
|
}
|
|
732
732
|
},
|
|
733
|
+
"broker": {
|
|
734
|
+
"description": "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.",
|
|
735
|
+
"type": "object",
|
|
736
|
+
"properties": {
|
|
737
|
+
"routes": {
|
|
738
|
+
"minItems": 1,
|
|
739
|
+
"type": "array",
|
|
740
|
+
"items": {
|
|
741
|
+
"type": "object",
|
|
742
|
+
"properties": {
|
|
743
|
+
"upstream": {
|
|
744
|
+
"type": "string",
|
|
745
|
+
"minLength": 1,
|
|
746
|
+
"description": "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."
|
|
747
|
+
},
|
|
748
|
+
"env": {
|
|
749
|
+
"description": "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.",
|
|
750
|
+
"type": "string",
|
|
751
|
+
"pattern": "^[A-Z][A-Z0-9_]*$"
|
|
752
|
+
},
|
|
753
|
+
"headers": {
|
|
754
|
+
"description": "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.",
|
|
755
|
+
"type": "object",
|
|
756
|
+
"propertyNames": {
|
|
757
|
+
"type": "string"
|
|
758
|
+
},
|
|
759
|
+
"additionalProperties": {
|
|
760
|
+
"type": "string"
|
|
761
|
+
}
|
|
762
|
+
},
|
|
763
|
+
"basic": {
|
|
764
|
+
"description": "HTTP Basic credentials, templated over the fields, for a service that takes them (git over HTTPS: `x-access-token` and `${token}`).",
|
|
765
|
+
"type": "object",
|
|
766
|
+
"properties": {
|
|
767
|
+
"username": {
|
|
768
|
+
"type": "string"
|
|
769
|
+
},
|
|
770
|
+
"password": {
|
|
771
|
+
"type": "string"
|
|
772
|
+
}
|
|
773
|
+
},
|
|
774
|
+
"required": [
|
|
775
|
+
"username",
|
|
776
|
+
"password"
|
|
777
|
+
],
|
|
778
|
+
"additionalProperties": false
|
|
779
|
+
},
|
|
780
|
+
"form": {
|
|
781
|
+
"description": "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.",
|
|
782
|
+
"type": "object",
|
|
783
|
+
"propertyNames": {
|
|
784
|
+
"type": "string"
|
|
785
|
+
},
|
|
786
|
+
"additionalProperties": {
|
|
787
|
+
"type": "string"
|
|
788
|
+
}
|
|
789
|
+
},
|
|
790
|
+
"pathPrefix": {
|
|
791
|
+
"description": "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}`).",
|
|
792
|
+
"type": "string",
|
|
793
|
+
"format": "starts_with",
|
|
794
|
+
"pattern": "^\\/.*"
|
|
795
|
+
},
|
|
796
|
+
"git": {
|
|
797
|
+
"description": "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.",
|
|
798
|
+
"type": "boolean"
|
|
799
|
+
}
|
|
800
|
+
},
|
|
801
|
+
"required": [
|
|
802
|
+
"upstream"
|
|
803
|
+
],
|
|
804
|
+
"additionalProperties": false
|
|
805
|
+
}
|
|
806
|
+
},
|
|
807
|
+
"rules": {
|
|
808
|
+
"description": "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.",
|
|
809
|
+
"type": "array",
|
|
810
|
+
"items": {
|
|
811
|
+
"type": "object",
|
|
812
|
+
"properties": {
|
|
813
|
+
"methods": {
|
|
814
|
+
"description": "The HTTP methods it covers (`DELETE`, `PUT`); absent covers every method.",
|
|
815
|
+
"type": "array",
|
|
816
|
+
"items": {
|
|
817
|
+
"type": "string",
|
|
818
|
+
"pattern": "^[A-Z]+$"
|
|
819
|
+
}
|
|
820
|
+
},
|
|
821
|
+
"paths": {
|
|
822
|
+
"description": "The paths it covers, below the route's upstream: `*` matches one segment, `**` any number of them (`/repos/*/*/hooks/**`). Absent covers every path.",
|
|
823
|
+
"type": "array",
|
|
824
|
+
"items": {
|
|
825
|
+
"type": "string",
|
|
826
|
+
"format": "starts_with",
|
|
827
|
+
"pattern": "^\\/.*"
|
|
828
|
+
}
|
|
829
|
+
},
|
|
830
|
+
"action": {
|
|
831
|
+
"type": "string",
|
|
832
|
+
"enum": [
|
|
833
|
+
"allow",
|
|
834
|
+
"ask",
|
|
835
|
+
"deny"
|
|
836
|
+
],
|
|
837
|
+
"description": "`allow` forwards it, `ask` holds it on a card for the owner, `deny` refuses it."
|
|
838
|
+
},
|
|
839
|
+
"why": {
|
|
840
|
+
"description": "One line on what the rule protects, shown on the card or in the refusal.",
|
|
841
|
+
"type": "string"
|
|
842
|
+
}
|
|
843
|
+
},
|
|
844
|
+
"required": [
|
|
845
|
+
"action"
|
|
846
|
+
],
|
|
847
|
+
"additionalProperties": false
|
|
848
|
+
}
|
|
849
|
+
}
|
|
850
|
+
},
|
|
851
|
+
"required": [
|
|
852
|
+
"routes"
|
|
853
|
+
],
|
|
854
|
+
"additionalProperties": false
|
|
855
|
+
},
|
|
733
856
|
"mcp": {
|
|
734
857
|
"description": "Deprecated: declare `contributes.tools` with `perCard` naming this card instead, and serve the tools with `api.tools.serve`. A path in this extension's backend (`server`) answering MCP over Streamable HTTP; every turn granted a card of this kind gets it as a server named by the card's id, each request arriving at `<path>/<card id>`.",
|
|
735
858
|
"effect": "mcp",
|
|
@@ -1470,6 +1593,192 @@
|
|
|
1470
1593
|
"additionalProperties": false
|
|
1471
1594
|
}
|
|
1472
1595
|
},
|
|
1596
|
+
"kind": {
|
|
1597
|
+
"type": "string",
|
|
1598
|
+
"const": "phone"
|
|
1599
|
+
},
|
|
1600
|
+
"install": {
|
|
1601
|
+
"description": "Where this phone's app is installed from: its store listing, or a page offering the build.",
|
|
1602
|
+
"type": "string",
|
|
1603
|
+
"format": "uri"
|
|
1604
|
+
},
|
|
1605
|
+
"skill": {
|
|
1606
|
+
"type": "string",
|
|
1607
|
+
"minLength": 1,
|
|
1608
|
+
"description": "Checkout-relative SKILL.md teaching the agent to work on this phone."
|
|
1609
|
+
}
|
|
1610
|
+
},
|
|
1611
|
+
"required": [
|
|
1612
|
+
"id",
|
|
1613
|
+
"catalog",
|
|
1614
|
+
"fields",
|
|
1615
|
+
"kind",
|
|
1616
|
+
"skill"
|
|
1617
|
+
],
|
|
1618
|
+
"mintsServer": true,
|
|
1619
|
+
"additionalProperties": false
|
|
1620
|
+
},
|
|
1621
|
+
{
|
|
1622
|
+
"type": "object",
|
|
1623
|
+
"properties": {
|
|
1624
|
+
"id": {
|
|
1625
|
+
"type": "string",
|
|
1626
|
+
"pattern": "^[a-z0-9][a-z0-9-]*$"
|
|
1627
|
+
},
|
|
1628
|
+
"catalog": {
|
|
1629
|
+
"type": "object",
|
|
1630
|
+
"properties": {
|
|
1631
|
+
"name": {
|
|
1632
|
+
"type": "string",
|
|
1633
|
+
"minLength": 1
|
|
1634
|
+
},
|
|
1635
|
+
"art": {
|
|
1636
|
+
"description": "This extension's own mark, as a complete SVG document inline: the tier an author controls fully. Give it a viewBox and let it fill its own square edge to edge; it is drawn as the tile, not as a glyph on a plate. Kept as readable SVG text (not base64) so a registry reviewer can see what they are publishing, drawn inert so it cannot script the page, and capped at 4 KB. Anything that does not parse as SVG falls back to `logo`, then `icon`, then initials.",
|
|
1637
|
+
"type": "string",
|
|
1638
|
+
"maxLength": 4096
|
|
1639
|
+
},
|
|
1640
|
+
"logo": {
|
|
1641
|
+
"description": "A simple-icons slug, fetched from a CDN: right for standing in for somebody else's product. Add a \"/<hex>\" suffix to force a colour for a mark that vanishes against the surface it lands on. Unreachable in an offline sandbox, so it falls back to `icon`, then to initials.",
|
|
1642
|
+
"type": "string"
|
|
1643
|
+
},
|
|
1644
|
+
"icon": {
|
|
1645
|
+
"description": "A name from the host's own icon set, drawn when no simple-icons slug fits. It ships in the image, follows the theme and costs no request: what actually carries a first-party extension. An unknown name falls back to initials rather than to a hole.",
|
|
1646
|
+
"type": "string"
|
|
1647
|
+
},
|
|
1648
|
+
"description": {
|
|
1649
|
+
"type": "string",
|
|
1650
|
+
"minLength": 1,
|
|
1651
|
+
"description": "ONE LINE: aim for 60 characters or fewer. The grid clamps it at two lines in a narrow pane, so a paragraph here is a paragraph the reader gets truncated. Everything longer belongs in `hint`."
|
|
1652
|
+
},
|
|
1653
|
+
"category": {
|
|
1654
|
+
"type": "string",
|
|
1655
|
+
"minLength": 1
|
|
1656
|
+
},
|
|
1657
|
+
"hint": {
|
|
1658
|
+
"description": "The paragraph, shown under the add form and searched from the catalog, so the words that identify this card to someone hunting for it (\"webauthn\", \"socket mode\") belong here even when the tile cannot show them.",
|
|
1659
|
+
"type": "string"
|
|
1660
|
+
},
|
|
1661
|
+
"guide": {
|
|
1662
|
+
"description": "The walkthrough the install dialog renders for getting the credential this card asks for.",
|
|
1663
|
+
"type": "object",
|
|
1664
|
+
"properties": {
|
|
1665
|
+
"url": {
|
|
1666
|
+
"type": "string"
|
|
1667
|
+
},
|
|
1668
|
+
"urlFromField": {
|
|
1669
|
+
"type": "string"
|
|
1670
|
+
},
|
|
1671
|
+
"path": {
|
|
1672
|
+
"type": "string"
|
|
1673
|
+
},
|
|
1674
|
+
"linkLabel": {
|
|
1675
|
+
"type": "string"
|
|
1676
|
+
},
|
|
1677
|
+
"scopes": {
|
|
1678
|
+
"type": "string"
|
|
1679
|
+
},
|
|
1680
|
+
"steps": {
|
|
1681
|
+
"type": "array",
|
|
1682
|
+
"items": {
|
|
1683
|
+
"type": "string"
|
|
1684
|
+
}
|
|
1685
|
+
}
|
|
1686
|
+
},
|
|
1687
|
+
"additionalProperties": false
|
|
1688
|
+
}
|
|
1689
|
+
},
|
|
1690
|
+
"required": [
|
|
1691
|
+
"name",
|
|
1692
|
+
"description",
|
|
1693
|
+
"category"
|
|
1694
|
+
],
|
|
1695
|
+
"additionalProperties": false
|
|
1696
|
+
},
|
|
1697
|
+
"fields": {
|
|
1698
|
+
"type": "array",
|
|
1699
|
+
"items": {
|
|
1700
|
+
"type": "object",
|
|
1701
|
+
"properties": {
|
|
1702
|
+
"key": {
|
|
1703
|
+
"type": "string",
|
|
1704
|
+
"pattern": "^[a-zA-Z][a-zA-Z0-9]*$"
|
|
1705
|
+
},
|
|
1706
|
+
"label": {
|
|
1707
|
+
"type": "string",
|
|
1708
|
+
"minLength": 1
|
|
1709
|
+
},
|
|
1710
|
+
"placeholder": {
|
|
1711
|
+
"type": "string"
|
|
1712
|
+
},
|
|
1713
|
+
"secret": {
|
|
1714
|
+
"description": "Mask it, and never echo it back.",
|
|
1715
|
+
"type": "boolean"
|
|
1716
|
+
},
|
|
1717
|
+
"optional": {
|
|
1718
|
+
"type": "boolean"
|
|
1719
|
+
},
|
|
1720
|
+
"multiline": {
|
|
1721
|
+
"type": "boolean"
|
|
1722
|
+
},
|
|
1723
|
+
"advanced": {
|
|
1724
|
+
"description": "Fold this field behind the form's Advanced disclosure: for answers whose default is right for nearly everyone. The disclosure opens by itself while any advanced field holds a non-default value, so an edit never hides live settings.",
|
|
1725
|
+
"type": "boolean"
|
|
1726
|
+
},
|
|
1727
|
+
"boolean": {
|
|
1728
|
+
"description": "Render it as a switch, carrying \"on\"/\"off\". For an opt-in EXTRA rather than a decision: a two-option picker says the same thing but presents a choice the user must make to proceed, sized like the required fields around it. A switch always holds a value, so a field like this never blocks a submit.",
|
|
1729
|
+
"type": "boolean"
|
|
1730
|
+
},
|
|
1731
|
+
"hint": {
|
|
1732
|
+
"description": "A line under this control, for what the label alone cannot say: a host requirement, when a value takes effect. The card's own `hint` speaks for the whole card; this one is bound to the field it qualifies.",
|
|
1733
|
+
"type": "string"
|
|
1734
|
+
},
|
|
1735
|
+
"rebuild": {
|
|
1736
|
+
"description": "This value only takes effect after the sandbox is rebuilt, because it rides the image overlay. Shown as a chip beside the label: two switches side by side, identical in every visible way, can otherwise cost five seconds or five minutes with no way to tell which.",
|
|
1737
|
+
"type": "boolean"
|
|
1738
|
+
},
|
|
1739
|
+
"default": {
|
|
1740
|
+
"type": "string"
|
|
1741
|
+
},
|
|
1742
|
+
"options": {
|
|
1743
|
+
"description": "Turns the field into a select.",
|
|
1744
|
+
"type": "array",
|
|
1745
|
+
"items": {
|
|
1746
|
+
"type": "object",
|
|
1747
|
+
"properties": {
|
|
1748
|
+
"value": {
|
|
1749
|
+
"type": "string"
|
|
1750
|
+
},
|
|
1751
|
+
"label": {
|
|
1752
|
+
"type": "string"
|
|
1753
|
+
}
|
|
1754
|
+
},
|
|
1755
|
+
"required": [
|
|
1756
|
+
"value",
|
|
1757
|
+
"label"
|
|
1758
|
+
],
|
|
1759
|
+
"additionalProperties": false
|
|
1760
|
+
}
|
|
1761
|
+
},
|
|
1762
|
+
"when": {
|
|
1763
|
+
"description": "Only show this field while a condition over the answers already given holds: `auth == 'key'`, `provider in ['ipsec', 'fortinet']`, `!advanced`. Supports `&&`, `||`, `!`, comparisons and `in`.",
|
|
1764
|
+
"type": "string"
|
|
1765
|
+
},
|
|
1766
|
+
"value": {
|
|
1767
|
+
"description": "A fixed value baked into the config rather than asked for: how a card pins its discriminator (platform=\"reddit\", provider=\"stripe\"). Renders as nothing.",
|
|
1768
|
+
"type": "string"
|
|
1769
|
+
},
|
|
1770
|
+
"totp": {
|
|
1771
|
+
"description": "This field holds a TOTP seed, the base32 key or otpauth:// URI a service shows when enrolling an authenticator app. Declare it with `secret: true`. Unlike an ordinary secret it never enters the agent's environment: the daemon mints the six-digit codes on demand and only those cross.",
|
|
1772
|
+
"type": "boolean"
|
|
1773
|
+
}
|
|
1774
|
+
},
|
|
1775
|
+
"required": [
|
|
1776
|
+
"key",
|
|
1777
|
+
"label"
|
|
1778
|
+
],
|
|
1779
|
+
"additionalProperties": false
|
|
1780
|
+
}
|
|
1781
|
+
},
|
|
1473
1782
|
"kind": {
|
|
1474
1783
|
"type": "string",
|
|
1475
1784
|
"const": "agent"
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@intentic/extension-manifest",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.328.0",
|
|
4
4
|
"description": "What an intentic extension DECLARES, the intentic-extension.json schema and the sandbox-route allowlist rule",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -29,10 +29,21 @@
|
|
|
29
29
|
"@intentic/src": "./src/index.ts",
|
|
30
30
|
"default": "./dist/index.js"
|
|
31
31
|
}
|
|
32
|
+
},
|
|
33
|
+
"./permissions": {
|
|
34
|
+
"types": "./dist/permissions.d.ts",
|
|
35
|
+
"import": {
|
|
36
|
+
"@intentic/src": "./src/permissions.ts",
|
|
37
|
+
"default": "./dist/permissions.js"
|
|
38
|
+
},
|
|
39
|
+
"require": {
|
|
40
|
+
"@intentic/src": "./src/permissions.ts",
|
|
41
|
+
"default": "./dist/permissions.js"
|
|
42
|
+
}
|
|
32
43
|
}
|
|
33
44
|
},
|
|
34
45
|
"dependencies": {
|
|
35
|
-
"@intentic/base": "1.
|
|
46
|
+
"@intentic/base": "1.328.0",
|
|
36
47
|
"tslib": "2.8.1",
|
|
37
48
|
"zod": "4.6.5"
|
|
38
49
|
},
|
|
@@ -40,7 +51,7 @@
|
|
|
40
51
|
"@intentic/testing": "0.0.0",
|
|
41
52
|
"@intentic/tsconfig": "0.0.0",
|
|
42
53
|
"@types/bun": "1.4.2",
|
|
43
|
-
"@types/node": "24.
|
|
54
|
+
"@types/node": "24.19.1",
|
|
44
55
|
"@typescript/native-preview": "7.0.0-dev.20260707.2"
|
|
45
56
|
},
|
|
46
57
|
"scripts": {
|
package/src/index.ts
CHANGED
|
@@ -2,6 +2,7 @@ export * from "./bundle.js";
|
|
|
2
2
|
export * from "./contribution-point.js";
|
|
3
3
|
export * from "./json-schema.js";
|
|
4
4
|
export * from "./manifest.js";
|
|
5
|
+
export { ART_MAX_BYTES } from "./mark.js";
|
|
5
6
|
export * from "./meaning.js";
|
|
6
7
|
export * from "./permissions.js";
|
|
7
8
|
export * from "./points/index.js";
|
package/src/mark.ts
CHANGED
|
@@ -4,8 +4,9 @@ import { z } from "zod";
|
|
|
4
4
|
// `art` (inline SVG, own drawing) beats `logo` (simple-icons slug) beats `icon` (host's set), falling back to initials
|
|
5
5
|
// when none is declared.
|
|
6
6
|
|
|
7
|
-
// Big enough for a drawn mark, far too small for a traced photograph.
|
|
8
|
-
|
|
7
|
+
// Big enough for a drawn mark, far too small for a traced photograph. Exported for the registry, which copies a
|
|
8
|
+
// manifest's `art` into its entries and holds it to the same cap.
|
|
9
|
+
export const ART_MAX_BYTES = 4096;
|
|
9
10
|
|
|
10
11
|
export const MARK_FIELDS = {
|
|
11
12
|
// SVG document itself, not a URL or base64; drawn inert (<img>, never inlined) so a row can't script the page.
|
package/src/permissions.test.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ExtensionManifestSchema } from "./manifest.js";
|
|
2
|
-
import { permissionProblem, sandboxRouteAllowed } from "./permissions.js";
|
|
2
|
+
import { extensionRouteReach, permissionProblem, sandboxRouteAllowed } from "./permissions.js";
|
|
3
3
|
|
|
4
4
|
// The glob grammar: each segment of the declared path is literal or a lone `*`, and a `*` matches one whole segment
|
|
5
5
|
// that the URL layer would route rather than resolve away.
|
|
@@ -96,3 +96,23 @@ describe("a manifest's permissions", () => {
|
|
|
96
96
|
]);
|
|
97
97
|
});
|
|
98
98
|
});
|
|
99
|
+
|
|
100
|
+
describe("extensionRouteReach", () => {
|
|
101
|
+
const gateway = { permissions: ["GET /ports"], listener: "slack" };
|
|
102
|
+
test.each([
|
|
103
|
+
["its own settings, undeclared", "GET", "/extension/settings", true],
|
|
104
|
+
["its own event stream, undeclared", "GET", "/extension/events", true],
|
|
105
|
+
["no write through its own routes", "POST", "/extension/settings", false],
|
|
106
|
+
["what it declared", "GET", "/ports", true],
|
|
107
|
+
["what it did not declare", "GET", "/agents", false],
|
|
108
|
+
["its own provider's listener route", "GET", "/listeners/slack/state", true],
|
|
109
|
+
["another provider's listener route, however it is declared", "GET", "/listeners/discord/state", false],
|
|
110
|
+
["a provider spelled to decode into its own", "GET", "/listeners/sl%61ck/state", false],
|
|
111
|
+
])("%s", (_name, method, path, expected) => {
|
|
112
|
+
expect(extensionRouteReach(gateway, method, path)).toBe(expected);
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
test("an extension without a listener reaches no listener route, even one it globbed", () => {
|
|
116
|
+
expect(extensionRouteReach({ permissions: ["GET /listeners/*/state"] }, "GET", "/listeners/slack/state")).toBe(false);
|
|
117
|
+
});
|
|
118
|
+
});
|
package/src/permissions.ts
CHANGED
|
@@ -90,3 +90,36 @@ export const sandboxRouteAllowed = (permissions: readonly string[], method: stri
|
|
|
90
90
|
);
|
|
91
91
|
});
|
|
92
92
|
};
|
|
93
|
+
|
|
94
|
+
// The routes every extension's own token reaches without declaring them: what the host tells an extension about
|
|
95
|
+
// itself, its own settings (secrets included) and its own event stream. Each answers only about the extension asking,
|
|
96
|
+
// so declaring them would grant nothing a reviewer could weigh.
|
|
97
|
+
export const EXTENSION_OWN_ROUTES: readonly string[] = ["GET /extension/settings", "GET /extension/events"];
|
|
98
|
+
|
|
99
|
+
// What an extension token's reach is judged by: the manifest's `permissions.daemon`, and the provider its
|
|
100
|
+
// `contributes.listener` names, when the extension owns that listener.
|
|
101
|
+
export interface ExtensionReach {
|
|
102
|
+
readonly permissions: readonly string[];
|
|
103
|
+
readonly listener?: string | undefined;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
const LISTENER_ROUTE = /^\/listeners\/([^/]+)\/(?:state|dispatch|failure|status)$/u;
|
|
107
|
+
|
|
108
|
+
// The provider segment a listener route addresses, as it arrived; undefined for any other path.
|
|
109
|
+
export const listenerSegmentOf = (path: string): string | undefined => LISTENER_ROUTE.exec(path.split("?")[0] ?? path)?.[1];
|
|
110
|
+
|
|
111
|
+
// Whether an extension's token reaches `method path`: its own routes always; a listener route only for the provider its
|
|
112
|
+
// listener names, matched as sent or as encoded and never decoded, since a provider comes from a manifest and may hold
|
|
113
|
+
// anything a glob would widen on (another provider's /state hands back that provider's stored credentials); anything
|
|
114
|
+
// else by `permissions.daemon`. The daemon's grant (auth/grants.ts) and the SDK's test fake both judge by this, so a
|
|
115
|
+
// fake can't admit what the daemon refuses.
|
|
116
|
+
export const extensionRouteReach = (reach: ExtensionReach, method: string, path: string): boolean => {
|
|
117
|
+
if (sandboxRouteAllowed(EXTENSION_OWN_ROUTES, method, path)) {
|
|
118
|
+
return true;
|
|
119
|
+
}
|
|
120
|
+
const segment = listenerSegmentOf(path);
|
|
121
|
+
if (segment !== undefined) {
|
|
122
|
+
return reach.listener !== undefined && (segment === reach.listener || segment === encodeURIComponent(reach.listener));
|
|
123
|
+
}
|
|
124
|
+
return sandboxRouteAllowed(reach.permissions, method, path);
|
|
125
|
+
};
|