@everfur/cli 0.1.0 → 0.2.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 +272 -17
- package/dist/chunk-CEWWBPPT.js +12726 -0
- package/dist/{chunk-67H43MI6.js → chunk-S6UN7D2O.js} +295 -510
- package/dist/chunk-TBFOL2D3.js +161 -0
- package/dist/chunk-VHZWTB6J.js +893 -0
- package/dist/chunk-WCH6AI6K.js +2512 -0
- package/dist/everfur-mcp-container.d.ts +2 -0
- package/dist/everfur-mcp-container.js +60 -0
- package/dist/everfur-mcp-hosted.d.ts +2 -0
- package/dist/everfur-mcp-hosted.js +28 -0
- package/dist/everfur-mcp-http.d.ts +2 -0
- package/dist/everfur-mcp-http.js +21 -0
- package/dist/everfur-mcp.js +11 -365
- package/dist/everfur.js +4 -3
- package/dist/index.d.ts +875 -41
- package/dist/index.js +2 -21
- package/package.json +5 -4
- package/schema/diagnosis.v1.schema.json +41 -0
- package/schema/plan.v1.schema.json +90 -4
- package/schema/verification.v1.schema.json +7 -3
- package/contract/contract-public.json +0 -1335
- package/dist/chunk-KQZ6ZXL7.js +0 -3994
package/dist/index.d.ts
CHANGED
|
@@ -32,11 +32,12 @@ interface CredentialSpec {
|
|
|
32
32
|
/**
|
|
33
33
|
* Additional accepted prefixes, beyond `prefix`.
|
|
34
34
|
*
|
|
35
|
-
*
|
|
36
|
-
*
|
|
37
|
-
*
|
|
38
|
-
*
|
|
39
|
-
*
|
|
35
|
+
* The prefix a publishable key must carry is a property of the DEPLOYMENT, not of the tenant: production and
|
|
36
|
+
* staging both take `pk_live_` (a staging sandbox tenant is issued a `pk_live_` key and refuses `pk_test_`), and
|
|
37
|
+
* `pk_test_` is the prefix a deployment configured as a sandbox deployment would take instead; no deployed
|
|
38
|
+
* environment is configured that way today, so no deployed environment accepts it. The CLI cannot tell which
|
|
39
|
+
* deployment it is pointed at before it makes a call, so it accepts both shapes. The SERVER is the authority: each
|
|
40
|
+
* deployment refuses the prefix it does not take on the fast-fail path, so accepting both here narrows nothing.
|
|
40
41
|
*/
|
|
41
42
|
readonly alsoAccepts?: readonly string[];
|
|
42
43
|
/** Exact expected length when the prefix is known, or null. */
|
|
@@ -63,6 +64,12 @@ interface ResolvedCredential {
|
|
|
63
64
|
readonly credential: Credential | null;
|
|
64
65
|
/** Why the value was rejected. Names the variable and the expected shape, never the value. */
|
|
65
66
|
readonly reason: string | null;
|
|
67
|
+
/**
|
|
68
|
+
* Which accepted prefix a `present` value starts with (`pk_live_` or `pk_test_`), or null for an
|
|
69
|
+
* opaque credential or one that is not present. A prefix is a public fact about the key, so a
|
|
70
|
+
* caller that needs it reads it here instead of reading the raw value out of the environment.
|
|
71
|
+
*/
|
|
72
|
+
readonly matchedPrefix: string | null;
|
|
66
73
|
}
|
|
67
74
|
/**
|
|
68
75
|
* Wrap a value that did NOT come from the environment, for example a session token the CLI just
|
|
@@ -87,6 +94,28 @@ declare function withPrefix(credential: Credential, prefix: string): Credential;
|
|
|
87
94
|
*/
|
|
88
95
|
declare function resolveCredential(env: Readonly<Record<string, string | undefined>>, spec: CredentialSpec): ResolvedCredential;
|
|
89
96
|
|
|
97
|
+
/**
|
|
98
|
+
* WHERE A FETCHED CONTRACT IS KEPT BETWEEN RUNS.
|
|
99
|
+
*
|
|
100
|
+
* The contract is served only to an authenticated partner (`GET /partners/contract`), so every
|
|
101
|
+
* command that needs it would otherwise make a network call per run. The route answers an ETag that
|
|
102
|
+
* IS the contract digest, so a cached copy costs one conditional request and an empty 304 while it is
|
|
103
|
+
* current, and is replaced the moment the platform publishes a new one.
|
|
104
|
+
*
|
|
105
|
+
* A PORT, NOT A MODULE-LEVEL FILESYSTEM, for the same reason `FileSystemPort` is one: commands stay pure
|
|
106
|
+
* functions over injected dependencies and a test never touches a real directory. Only the bin shims and
|
|
107
|
+
* the MCP server construct the node adapter.
|
|
108
|
+
*
|
|
109
|
+
* Writes never throw. A read-only home directory or a full disk degrades to fetching every time, which is
|
|
110
|
+
* slower and still correct; failing a plan because a cache could not be written would not be.
|
|
111
|
+
*/
|
|
112
|
+
interface ContractCachePort {
|
|
113
|
+
/** The entry's contents, or null when absent or unreadable. */
|
|
114
|
+
read(name: string): string | null;
|
|
115
|
+
/** Store an entry. Best effort: a failure is swallowed and the next run fetches again. */
|
|
116
|
+
write(name: string, contents: string): void;
|
|
117
|
+
}
|
|
118
|
+
|
|
90
119
|
/**
|
|
91
120
|
* The filesystem seam. Detection and contract loading are pure functions over this interface,
|
|
92
121
|
* which is the whole reason they can be tested against fixtures without a temp directory
|
|
@@ -105,6 +134,11 @@ interface FileSystemPort {
|
|
|
105
134
|
exists(path: string): boolean;
|
|
106
135
|
/** True when the path exists and is a directory. */
|
|
107
136
|
isDirectory(path: string): boolean;
|
|
137
|
+
/**
|
|
138
|
+
* The names of a directory's direct entries, sorted, or null when the path is not a readable directory. Used only
|
|
139
|
+
* by the offline project checks of `verify`, which have to find a secret wherever it was written.
|
|
140
|
+
*/
|
|
141
|
+
listDirectory(path: string): readonly string[] | null;
|
|
108
142
|
}
|
|
109
143
|
|
|
110
144
|
/**
|
|
@@ -116,7 +150,8 @@ interface FileSystemPort {
|
|
|
116
150
|
* a `CommandOutcome`: it holds the credential headers, and an outcome is a thing the formatter
|
|
117
151
|
* prints. Failures carry the method, the path, and the request id, never the request object.
|
|
118
152
|
*/
|
|
119
|
-
|
|
153
|
+
/** OPTIONS is sent only by the web checks' CORS preflight, directly through a transport, never retried. */
|
|
154
|
+
type HttpMethod = 'GET' | 'POST' | 'DELETE' | 'OPTIONS';
|
|
120
155
|
/** Methods that may be retried. A retry of anything else could mint a second credential. */
|
|
121
156
|
declare const IDEMPOTENT_METHODS: readonly HttpMethod[];
|
|
122
157
|
interface HttpRequest {
|
|
@@ -304,6 +339,11 @@ interface CommandContext {
|
|
|
304
339
|
readonly transport: TransportPort;
|
|
305
340
|
/** Waiting, injected so a poll loop in a test costs nothing. */
|
|
306
341
|
readonly clock: ClockPort;
|
|
342
|
+
/**
|
|
343
|
+
* Where a contract fetched from `GET /partners/contract` is kept between runs. Absent means nothing is
|
|
344
|
+
* cached and every run that needs the contract fetches it. `src/bin` supplies the one real adapter.
|
|
345
|
+
*/
|
|
346
|
+
readonly contractCache?: ContractCachePort;
|
|
307
347
|
}
|
|
308
348
|
/**
|
|
309
349
|
* A positional argument. Declared as data beside the flags so `--help` documents it and the
|
|
@@ -334,7 +374,7 @@ interface Command {
|
|
|
334
374
|
* The credentials this command can actually use, declared as data for the same reason the
|
|
335
375
|
* flags are: `--help` renders what the command declares, so a credential a command reads is a
|
|
336
376
|
* credential its own help names. Absent means the command touches none, which is the truth
|
|
337
|
-
* for `
|
|
377
|
+
* for `contract validate`.
|
|
338
378
|
*
|
|
339
379
|
* This exists because per-command help used to render only the flags. A partner told to run
|
|
340
380
|
* one command had no way to learn from the tool that they must export EVERFUR_PARTNER_KEY;
|
|
@@ -438,6 +478,10 @@ declare const fetchTransport: TransportPort;
|
|
|
438
478
|
* `API_PREFIX` is appended by this module rather than being part of what the operator types,
|
|
439
479
|
* because it is a deployment fact of the API and not a choice. A base URL that already ends in
|
|
440
480
|
* the prefix is accepted as-is, so both spellings work and neither doubles up.
|
|
481
|
+
*
|
|
482
|
+
* HTTPS, EXCEPT ON THIS MACHINE. Every networked command sends a credential to this base (the partner
|
|
483
|
+
* key, the secret key, the docs key), so plain `http:` is accepted only for `localhost`, `127.0.0.1`
|
|
484
|
+
* and `[::1]`, where a local API runs. Anything else must be https.
|
|
441
485
|
*/
|
|
442
486
|
declare const BASE_URL_ENV_VAR = "EVERFUR_API_BASE_URL";
|
|
443
487
|
/** `app/main.py` mounts every router used here at `settings.api_prefix`. */
|
|
@@ -571,6 +615,26 @@ declare const SCHEMAS: Readonly<{
|
|
|
571
615
|
type?: never;
|
|
572
616
|
})[];
|
|
573
617
|
};
|
|
618
|
+
embedding: {
|
|
619
|
+
description: string;
|
|
620
|
+
oneOf: ({
|
|
621
|
+
type: string;
|
|
622
|
+
$ref?: never;
|
|
623
|
+
} | {
|
|
624
|
+
$ref: string;
|
|
625
|
+
type?: never;
|
|
626
|
+
})[];
|
|
627
|
+
};
|
|
628
|
+
environment: {
|
|
629
|
+
description: string;
|
|
630
|
+
oneOf: ({
|
|
631
|
+
type: string;
|
|
632
|
+
enum?: never;
|
|
633
|
+
} | {
|
|
634
|
+
enum: string[];
|
|
635
|
+
type?: never;
|
|
636
|
+
})[];
|
|
637
|
+
};
|
|
574
638
|
};
|
|
575
639
|
};
|
|
576
640
|
missingFacts: {
|
|
@@ -605,6 +669,16 @@ declare const SCHEMAS: Readonly<{
|
|
|
605
669
|
$ref: string;
|
|
606
670
|
};
|
|
607
671
|
};
|
|
672
|
+
platformBlock: {
|
|
673
|
+
description: string;
|
|
674
|
+
oneOf: ({
|
|
675
|
+
type: string;
|
|
676
|
+
$ref?: never;
|
|
677
|
+
} | {
|
|
678
|
+
$ref: string;
|
|
679
|
+
type?: never;
|
|
680
|
+
})[];
|
|
681
|
+
};
|
|
608
682
|
decisionSpace: {
|
|
609
683
|
description: string;
|
|
610
684
|
oneOf: ({
|
|
@@ -746,6 +820,159 @@ declare const SCHEMAS: Readonly<{
|
|
|
746
820
|
$ref: string;
|
|
747
821
|
};
|
|
748
822
|
};
|
|
823
|
+
webEmbedding: {
|
|
824
|
+
description: string;
|
|
825
|
+
oneOf: ({
|
|
826
|
+
type: string;
|
|
827
|
+
$ref?: never;
|
|
828
|
+
} | {
|
|
829
|
+
$ref: string;
|
|
830
|
+
type?: never;
|
|
831
|
+
})[];
|
|
832
|
+
};
|
|
833
|
+
webFramework: {
|
|
834
|
+
description: string;
|
|
835
|
+
oneOf: ({
|
|
836
|
+
type: string;
|
|
837
|
+
enum?: never;
|
|
838
|
+
} | {
|
|
839
|
+
enum: string[];
|
|
840
|
+
type?: never;
|
|
841
|
+
})[];
|
|
842
|
+
};
|
|
843
|
+
theme: {
|
|
844
|
+
description: string;
|
|
845
|
+
oneOf: ({
|
|
846
|
+
type: string;
|
|
847
|
+
$ref?: never;
|
|
848
|
+
} | {
|
|
849
|
+
$ref: string;
|
|
850
|
+
type?: never;
|
|
851
|
+
})[];
|
|
852
|
+
};
|
|
853
|
+
};
|
|
854
|
+
};
|
|
855
|
+
ThemeToken: {
|
|
856
|
+
enum: string[];
|
|
857
|
+
};
|
|
858
|
+
ThemeDetection: {
|
|
859
|
+
type: string;
|
|
860
|
+
required: string[];
|
|
861
|
+
properties: {
|
|
862
|
+
source: {
|
|
863
|
+
enum: string[];
|
|
864
|
+
};
|
|
865
|
+
confidence: {
|
|
866
|
+
enum: string[];
|
|
867
|
+
};
|
|
868
|
+
theme: {
|
|
869
|
+
description: string;
|
|
870
|
+
type: string;
|
|
871
|
+
properties: {
|
|
872
|
+
primaryColor: {
|
|
873
|
+
type: string;
|
|
874
|
+
pattern: string;
|
|
875
|
+
};
|
|
876
|
+
accentColor: {
|
|
877
|
+
type: string;
|
|
878
|
+
pattern: string;
|
|
879
|
+
};
|
|
880
|
+
primaryColorDark: {
|
|
881
|
+
type: string;
|
|
882
|
+
pattern: string;
|
|
883
|
+
};
|
|
884
|
+
accentColorDark: {
|
|
885
|
+
type: string;
|
|
886
|
+
pattern: string;
|
|
887
|
+
};
|
|
888
|
+
brightness: {
|
|
889
|
+
enum: string[];
|
|
890
|
+
};
|
|
891
|
+
surfaceStyle: {
|
|
892
|
+
enum: string[];
|
|
893
|
+
};
|
|
894
|
+
radiusScale: {
|
|
895
|
+
enum: string[];
|
|
896
|
+
};
|
|
897
|
+
fontFamily: {
|
|
898
|
+
type: string;
|
|
899
|
+
minLength: number;
|
|
900
|
+
};
|
|
901
|
+
fontRegular: {
|
|
902
|
+
type: string;
|
|
903
|
+
minLength: number;
|
|
904
|
+
description: string;
|
|
905
|
+
};
|
|
906
|
+
fontMedium: {
|
|
907
|
+
type: string;
|
|
908
|
+
minLength: number;
|
|
909
|
+
description: string;
|
|
910
|
+
};
|
|
911
|
+
fontBold: {
|
|
912
|
+
type: string;
|
|
913
|
+
minLength: number;
|
|
914
|
+
description: string;
|
|
915
|
+
};
|
|
916
|
+
};
|
|
917
|
+
additionalProperties: boolean;
|
|
918
|
+
};
|
|
919
|
+
evidence: {
|
|
920
|
+
type: string;
|
|
921
|
+
items: {
|
|
922
|
+
type: string;
|
|
923
|
+
required: string[];
|
|
924
|
+
properties: {
|
|
925
|
+
file: {
|
|
926
|
+
type: string;
|
|
927
|
+
minLength: number;
|
|
928
|
+
};
|
|
929
|
+
line: {
|
|
930
|
+
type: string;
|
|
931
|
+
minimum: number;
|
|
932
|
+
};
|
|
933
|
+
key: {
|
|
934
|
+
type: string;
|
|
935
|
+
minLength: number;
|
|
936
|
+
};
|
|
937
|
+
value: {
|
|
938
|
+
type: string;
|
|
939
|
+
};
|
|
940
|
+
token: {
|
|
941
|
+
oneOf: ({
|
|
942
|
+
type: string;
|
|
943
|
+
$ref?: never;
|
|
944
|
+
} | {
|
|
945
|
+
$ref: string;
|
|
946
|
+
type?: never;
|
|
947
|
+
})[];
|
|
948
|
+
};
|
|
949
|
+
reason: {
|
|
950
|
+
type: string;
|
|
951
|
+
minLength: number;
|
|
952
|
+
};
|
|
953
|
+
};
|
|
954
|
+
};
|
|
955
|
+
};
|
|
956
|
+
scanned: {
|
|
957
|
+
type: string;
|
|
958
|
+
items: {
|
|
959
|
+
type: string;
|
|
960
|
+
minLength: number;
|
|
961
|
+
};
|
|
962
|
+
};
|
|
963
|
+
missing: {
|
|
964
|
+
type: string;
|
|
965
|
+
items: {
|
|
966
|
+
type: string;
|
|
967
|
+
minLength: number;
|
|
968
|
+
};
|
|
969
|
+
};
|
|
970
|
+
inferred: {
|
|
971
|
+
type: string;
|
|
972
|
+
items: {
|
|
973
|
+
$ref: string;
|
|
974
|
+
};
|
|
975
|
+
};
|
|
749
976
|
};
|
|
750
977
|
};
|
|
751
978
|
Dependency: {
|
|
@@ -802,6 +1029,28 @@ declare const SCHEMAS: Readonly<{
|
|
|
802
1029
|
minLength: number;
|
|
803
1030
|
};
|
|
804
1031
|
};
|
|
1032
|
+
blockedBy: {
|
|
1033
|
+
description: string;
|
|
1034
|
+
enum: string[];
|
|
1035
|
+
};
|
|
1036
|
+
};
|
|
1037
|
+
};
|
|
1038
|
+
PlatformBlock: {
|
|
1039
|
+
type: string;
|
|
1040
|
+
required: string[];
|
|
1041
|
+
properties: {
|
|
1042
|
+
reason: {
|
|
1043
|
+
type: string;
|
|
1044
|
+
minLength: number;
|
|
1045
|
+
};
|
|
1046
|
+
unblockOwner: {
|
|
1047
|
+
type: string;
|
|
1048
|
+
minLength: number;
|
|
1049
|
+
};
|
|
1050
|
+
requestPath: {
|
|
1051
|
+
type: string;
|
|
1052
|
+
pattern: string;
|
|
1053
|
+
};
|
|
805
1054
|
};
|
|
806
1055
|
};
|
|
807
1056
|
PlanPrinciple: {
|
|
@@ -1117,6 +1366,18 @@ declare const SCHEMAS: Readonly<{
|
|
|
1117
1366
|
$ref: string;
|
|
1118
1367
|
};
|
|
1119
1368
|
};
|
|
1369
|
+
switches: {
|
|
1370
|
+
description: string;
|
|
1371
|
+
oneOf: ({
|
|
1372
|
+
type: string;
|
|
1373
|
+
items?: never;
|
|
1374
|
+
} | {
|
|
1375
|
+
type: string;
|
|
1376
|
+
items: {
|
|
1377
|
+
$ref: string;
|
|
1378
|
+
};
|
|
1379
|
+
})[];
|
|
1380
|
+
};
|
|
1120
1381
|
};
|
|
1121
1382
|
$defs: {
|
|
1122
1383
|
GeneratedBy: {
|
|
@@ -1187,6 +1448,54 @@ declare const SCHEMAS: Readonly<{
|
|
|
1187
1448
|
};
|
|
1188
1449
|
};
|
|
1189
1450
|
};
|
|
1451
|
+
SwitchDiagnosis: {
|
|
1452
|
+
type: string;
|
|
1453
|
+
required: string[];
|
|
1454
|
+
properties: {
|
|
1455
|
+
name: {
|
|
1456
|
+
description: string;
|
|
1457
|
+
type: string;
|
|
1458
|
+
minLength: number;
|
|
1459
|
+
};
|
|
1460
|
+
enabled: {
|
|
1461
|
+
description: string;
|
|
1462
|
+
oneOf: {
|
|
1463
|
+
type: string;
|
|
1464
|
+
}[];
|
|
1465
|
+
};
|
|
1466
|
+
kind: {
|
|
1467
|
+
description: string;
|
|
1468
|
+
enum: string[];
|
|
1469
|
+
};
|
|
1470
|
+
gates: {
|
|
1471
|
+
description: string;
|
|
1472
|
+
type: string;
|
|
1473
|
+
items: {
|
|
1474
|
+
type: string;
|
|
1475
|
+
minLength: number;
|
|
1476
|
+
};
|
|
1477
|
+
};
|
|
1478
|
+
tenantTerm: {
|
|
1479
|
+
description: string;
|
|
1480
|
+
oneOf: ({
|
|
1481
|
+
type: string;
|
|
1482
|
+
minLength?: never;
|
|
1483
|
+
} | {
|
|
1484
|
+
type: string;
|
|
1485
|
+
minLength: number;
|
|
1486
|
+
})[];
|
|
1487
|
+
};
|
|
1488
|
+
reason: {
|
|
1489
|
+
description: string;
|
|
1490
|
+
type: string;
|
|
1491
|
+
};
|
|
1492
|
+
nextAction: {
|
|
1493
|
+
description: string;
|
|
1494
|
+
type: string;
|
|
1495
|
+
minLength: number;
|
|
1496
|
+
};
|
|
1497
|
+
};
|
|
1498
|
+
};
|
|
1190
1499
|
};
|
|
1191
1500
|
};
|
|
1192
1501
|
sandboxCreate: {
|
|
@@ -1370,6 +1679,11 @@ declare const SCHEMAS: Readonly<{
|
|
|
1370
1679
|
type: string;
|
|
1371
1680
|
minimum: number;
|
|
1372
1681
|
};
|
|
1682
|
+
gated: {
|
|
1683
|
+
description: string;
|
|
1684
|
+
type: string;
|
|
1685
|
+
minimum: number;
|
|
1686
|
+
};
|
|
1373
1687
|
};
|
|
1374
1688
|
};
|
|
1375
1689
|
steps: {
|
|
@@ -1388,6 +1702,7 @@ declare const SCHEMAS: Readonly<{
|
|
|
1388
1702
|
minLength: number;
|
|
1389
1703
|
};
|
|
1390
1704
|
result: {
|
|
1705
|
+
description: string;
|
|
1391
1706
|
enum: string[];
|
|
1392
1707
|
};
|
|
1393
1708
|
reason: {
|
|
@@ -1616,7 +1931,14 @@ interface ErrorRegistryEntry {
|
|
|
1616
1931
|
readonly note: string;
|
|
1617
1932
|
}
|
|
1618
1933
|
interface ErrorRegistry {
|
|
1934
|
+
/**
|
|
1935
|
+
* The row for a code. A code can ride both envelopes as two rows (`unavailable`: the 503 body and the SSE frame a
|
|
1936
|
+
* partner chat turn ends with); this answers the HTTP row then, and `lookupAll` answers both.
|
|
1937
|
+
*/
|
|
1619
1938
|
lookup(code: string): ErrorRegistryEntry | null;
|
|
1939
|
+
/** Every row for a code, one per envelope it is registered on. Empty for an unknown code. */
|
|
1940
|
+
lookupAll(code: string): readonly ErrorRegistryEntry[];
|
|
1941
|
+
/** The distinct codes, sorted. */
|
|
1620
1942
|
readonly codes: readonly string[];
|
|
1621
1943
|
}
|
|
1622
1944
|
/**
|
|
@@ -1660,6 +1982,8 @@ interface ApiSuccess<T> {
|
|
|
1660
1982
|
/** The server's id, or null when the response carried none. */
|
|
1661
1983
|
readonly requestId: string | null;
|
|
1662
1984
|
readonly attempts: number;
|
|
1985
|
+
/** The response headers, names lowercased by the adapter. A check on what a browser could read needs them. */
|
|
1986
|
+
readonly headers: Readonly<Record<string, string>>;
|
|
1663
1987
|
}
|
|
1664
1988
|
type ApiFailure = {
|
|
1665
1989
|
readonly ok: false;
|
|
@@ -1728,6 +2052,11 @@ interface ApiClientOptions {
|
|
|
1728
2052
|
readonly maxAttempts?: number;
|
|
1729
2053
|
/** Delay between attempts, in milliseconds. */
|
|
1730
2054
|
readonly retryDelayMs?: number;
|
|
2055
|
+
/**
|
|
2056
|
+
* The `x-everfur-sdk-platform` every /widget/v1 call sends (`sdkClientHeaders`). Default `cli`; a caller that read
|
|
2057
|
+
* the project passes `sdkPlatformForProjectType` of it. A header the request itself names always wins.
|
|
2058
|
+
*/
|
|
2059
|
+
readonly sdkPlatform?: string;
|
|
1731
2060
|
}
|
|
1732
2061
|
interface RequestSpec {
|
|
1733
2062
|
readonly method: HttpMethod;
|
|
@@ -1739,11 +2068,18 @@ interface RequestSpec {
|
|
|
1739
2068
|
readonly body?: JsonValue;
|
|
1740
2069
|
/** Statuses that are a successful outcome for this call, in addition to 2xx. */
|
|
1741
2070
|
readonly acceptStatuses?: readonly number[];
|
|
2071
|
+
/**
|
|
2072
|
+
* `text` hands back the accepted body as the raw string instead of parsing it, for a route that
|
|
2073
|
+
* answers `text/event-stream`. A failure body is still read for its wire code either way.
|
|
2074
|
+
*/
|
|
2075
|
+
readonly responseType?: 'json' | 'text';
|
|
1742
2076
|
}
|
|
1743
2077
|
interface ApiClient {
|
|
1744
2078
|
request(spec: RequestSpec): Promise<ApiResult<JsonValue>>;
|
|
1745
2079
|
/** The resolved base URL, for reporting. Never a credential. */
|
|
1746
2080
|
readonly baseUrl: string;
|
|
2081
|
+
/** The absolute URL `request` would call for `path`, for a probe that goes straight to a transport. */
|
|
2082
|
+
urlFor(path: string): string;
|
|
1747
2083
|
}
|
|
1748
2084
|
declare function clampTimeout(value: number): number;
|
|
1749
2085
|
/** True when the value is a shape `RequestIDMiddleware` will reuse rather than replace. */
|
|
@@ -1783,6 +2119,38 @@ declare function failureDetails(failure: ApiFailure): readonly string[];
|
|
|
1783
2119
|
|
|
1784
2120
|
declare function failureOutcome(failure: ApiFailure, extraDetails?: readonly string[]): CommandOutcome;
|
|
1785
2121
|
|
|
2122
|
+
/**
|
|
2123
|
+
* WHY A CAPABILITY IS UNAVAILABLE, and what to do about it.
|
|
2124
|
+
*
|
|
2125
|
+
* The nine codes are the platform's own `DiagnosticsReasonCode`, which exists because an empty
|
|
2126
|
+
* `capabilities:{}` verdict has five byte-identical causes and the render payload deliberately
|
|
2127
|
+
* carries no "why". The server sends the code and its own safe copy; this table adds the part
|
|
2128
|
+
* the server cannot know, which is what the PARTNER should do next.
|
|
2129
|
+
*
|
|
2130
|
+
* The distinction that makes this table worth having: three of these are somebody else's job
|
|
2131
|
+
* (`scope_not_provisioned`, `not_in_grant`, `runtime_gate_off`), one is a commercial
|
|
2132
|
+
* conversation (`outside_ceiling`), one is deliberate configuration (`capability_denied`), one
|
|
2133
|
+
* is transient (`resolver_unavailable`), and one is a bug to report (`gate_unknown`). A single
|
|
2134
|
+
* "the feature is unavailable" message collapses all seven into one wrong next step.
|
|
2135
|
+
*
|
|
2136
|
+
* An UNKNOWN code is not an error. The enum grows when the platform grows a new decision point,
|
|
2137
|
+
* and a CLI that rejected the answer would be useless exactly when something new broke. It
|
|
2138
|
+
* renders the code verbatim with an upgrade instruction.
|
|
2139
|
+
*/
|
|
2140
|
+
declare const REASON_CODES: readonly ["granted", "scope_not_provisioned", "capability_denied", "outside_ceiling", "not_in_grant", "runtime_gate_off", "gate_unknown", "platform_invariant", "resolver_unavailable"];
|
|
2141
|
+
type ReasonCode = (typeof REASON_CODES)[number];
|
|
2142
|
+
declare function isKnownReasonCode(value: string): value is ReasonCode;
|
|
2143
|
+
/** The next action for a code, including one this CLI has never heard of. */
|
|
2144
|
+
declare function nextActionFor$1(code: string): string;
|
|
2145
|
+
/**
|
|
2146
|
+
* What a partner switch is. A ROUTE GATE opens or closes partner routes (off, they answer 404). A POSTURE changes how
|
|
2147
|
+
* routes behave and is often off by design: `partner.min_version_gate_enabled` is inert off, and
|
|
2148
|
+
* `partner.sessions_required` or `partner.transcript_consent_required` armed would refuse callers. UNKNOWN is an entry
|
|
2149
|
+
* that neither says which it is nor names what it gates.
|
|
2150
|
+
*/
|
|
2151
|
+
declare const SWITCH_KINDS: readonly ["route_gate", "posture", "unknown"];
|
|
2152
|
+
type SwitchKind = (typeof SWITCH_KINDS)[number];
|
|
2153
|
+
|
|
1786
2154
|
/**
|
|
1787
2155
|
* Narrow `GET /widget/v1/diagnostics` into the CLI's own shape.
|
|
1788
2156
|
*
|
|
@@ -1814,6 +2182,35 @@ interface ScopeLevelDiagnosis {
|
|
|
1814
2182
|
readonly kind: string;
|
|
1815
2183
|
readonly present: boolean;
|
|
1816
2184
|
}
|
|
2185
|
+
/**
|
|
2186
|
+
* One partner switch that governs a partner-facing route, as the diagnostics block reports it.
|
|
2187
|
+
*
|
|
2188
|
+
* The capability list alone cannot say why a granted surface's routes 404: five switches have a capability gate
|
|
2189
|
+
* (records, records clinic, Televet, records push, server pets), and the rest (notifications, webhooks, records depth,
|
|
2190
|
+
* the Televet sub-features, follow-ups, branding and more) had none, so a partner whose switch was off was told
|
|
2191
|
+
* everything was granted. The CLI renders EVERY switch the backend sends, keyed by its name, in the order sent:
|
|
2192
|
+
* there is no list of known switches here to fall behind the platform.
|
|
2193
|
+
*/
|
|
2194
|
+
interface SwitchDiagnosis {
|
|
2195
|
+
/** The switch's name as the backend sends it, e.g. `partner.notifications_enabled`. */
|
|
2196
|
+
readonly name: string;
|
|
2197
|
+
/** On, off, or null when the entry carried no state this CLI can read. */
|
|
2198
|
+
readonly enabled: boolean | null;
|
|
2199
|
+
/**
|
|
2200
|
+
* A route gate (off, its routes 404), a posture (changes behaviour, often off by design), or unknown. The backend's
|
|
2201
|
+
* `kind` when it sends one; otherwise a switch that names what it gates is a route gate, and one that names nothing
|
|
2202
|
+
* is unknown. Only a route gate is ever told to ask Everfur to switch it on.
|
|
2203
|
+
*/
|
|
2204
|
+
readonly kind: SwitchKind;
|
|
2205
|
+
/** What it governs, as the backend names it: routes, capabilities or a description. */
|
|
2206
|
+
readonly gates: readonly string[];
|
|
2207
|
+
/** The tenant-level feature term the switch pairs with, when it has one. */
|
|
2208
|
+
readonly tenantTerm: string | null;
|
|
2209
|
+
/** The server's own copy for the switch, or ''. */
|
|
2210
|
+
readonly reason: string;
|
|
2211
|
+
/** CLI-authored. What the partner should do; see `reasons.ts`. */
|
|
2212
|
+
readonly nextAction: string;
|
|
2213
|
+
}
|
|
1817
2214
|
interface Diagnosis {
|
|
1818
2215
|
readonly requestId: string | null;
|
|
1819
2216
|
readonly evaluatedAt: string;
|
|
@@ -1836,6 +2233,11 @@ interface Diagnosis {
|
|
|
1836
2233
|
readonly levels: readonly ScopeLevelDiagnosis[];
|
|
1837
2234
|
};
|
|
1838
2235
|
readonly capabilities: readonly CapabilityDiagnosis[];
|
|
2236
|
+
/**
|
|
2237
|
+
* The partner switches, or null when the response carried no switches block (a deployment older than it). An
|
|
2238
|
+
* empty array is a deployment that reports switches and has none to report.
|
|
2239
|
+
*/
|
|
2240
|
+
readonly switches: readonly SwitchDiagnosis[] | null;
|
|
1839
2241
|
}
|
|
1840
2242
|
type DiagnosisParse = {
|
|
1841
2243
|
readonly ok: true;
|
|
@@ -1868,30 +2270,6 @@ interface DiagnosisRenderInput {
|
|
|
1868
2270
|
}
|
|
1869
2271
|
declare function renderDiagnosis(input: DiagnosisRenderInput): string;
|
|
1870
2272
|
|
|
1871
|
-
/**
|
|
1872
|
-
* WHY A CAPABILITY IS UNAVAILABLE, and what to do about it.
|
|
1873
|
-
*
|
|
1874
|
-
* The nine codes are the platform's own `DiagnosticsReasonCode`, which exists because an empty
|
|
1875
|
-
* `capabilities:{}` verdict has five byte-identical causes and the render payload deliberately
|
|
1876
|
-
* carries no "why". The server sends the code and its own safe copy; this table adds the part
|
|
1877
|
-
* the server cannot know, which is what the PARTNER should do next.
|
|
1878
|
-
*
|
|
1879
|
-
* The distinction that makes this table worth having: three of these are somebody else's job
|
|
1880
|
-
* (`scope_not_provisioned`, `not_in_grant`, `runtime_gate_off`), one is a commercial
|
|
1881
|
-
* conversation (`outside_ceiling`), one is deliberate configuration (`capability_denied`), one
|
|
1882
|
-
* is transient (`resolver_unavailable`), and one is a bug to report (`gate_unknown`). A single
|
|
1883
|
-
* "the feature is unavailable" message collapses all seven into one wrong next step.
|
|
1884
|
-
*
|
|
1885
|
-
* An UNKNOWN code is not an error. The enum grows when the platform grows a new decision point,
|
|
1886
|
-
* and a CLI that rejected the answer would be useless exactly when something new broke. It
|
|
1887
|
-
* renders the code verbatim with an upgrade instruction.
|
|
1888
|
-
*/
|
|
1889
|
-
declare const REASON_CODES: readonly ["granted", "scope_not_provisioned", "capability_denied", "outside_ceiling", "not_in_grant", "runtime_gate_off", "gate_unknown", "platform_invariant", "resolver_unavailable"];
|
|
1890
|
-
type ReasonCode = (typeof REASON_CODES)[number];
|
|
1891
|
-
declare function isKnownReasonCode(value: string): value is ReasonCode;
|
|
1892
|
-
/** The next action for a code, including one this CLI has never heard of. */
|
|
1893
|
-
declare function nextActionFor$1(code: string): string;
|
|
1894
|
-
|
|
1895
2273
|
/**
|
|
1896
2274
|
* THE SECRET FENCE. This module turns an admin mint response into the only shape this CLI is
|
|
1897
2275
|
* allowed to hand back, and it is written so that a raw secret CANNOT travel through it.
|
|
@@ -1974,13 +2352,207 @@ declare function buildSandboxDocument(input: SandboxDocumentInput): JsonObject;
|
|
|
1974
2352
|
/** The human projection. */
|
|
1975
2353
|
declare function renderSandboxCreate(creation: SandboxCreation, revocation: SandboxRevocation, requestId: string | null): string;
|
|
1976
2354
|
|
|
2355
|
+
/**
|
|
2356
|
+
* THEME DETECTION: what the partner's project already says about its own look, read statically, mapped to the
|
|
2357
|
+
* SDK's `theme` prop only where the mapping is unambiguous, and graded so the planner knows whether to emit it.
|
|
2358
|
+
*
|
|
2359
|
+
* Owner decision, 18 September 2026: the MCP-built app must match the partner's existing theme automatically
|
|
2360
|
+
* when it can, and refuse to guess when it cannot. Four sources are read, in confidence order:
|
|
2361
|
+
*
|
|
2362
|
+
* (a) a Tailwind v4 `@theme` / `@theme inline` block in the project's CSS (what the everfur-frontend console
|
|
2363
|
+
* itself uses), with `var()` references resolved one level through `:root` and the dark block;
|
|
2364
|
+
* (b) a Tailwind v3 `tailwind.config.{js,ts,cjs,mjs}`: `theme.extend.colors`, `fontFamily`, `borderRadius`,
|
|
2365
|
+
* read by a tolerant static parser (theme-js.ts), `hsl(var(--x))` resolved through the project CSS;
|
|
2366
|
+
* (c) root CSS custom properties: `--primary`, `--brand`, `--color-primary`, `--background`, `--foreground`,
|
|
2367
|
+
* `--radius`, `--font-sans` and their common spellings, in a stylesheet or a static page's `<style>`;
|
|
2368
|
+
* (d) React Native: a react-navigation `Theme` object (`colors: { primary, background, card, text, border }`)
|
|
2369
|
+
* or a theme or colours file with obvious keys, identifiers resolved one level to `const` strings; and, from
|
|
2370
|
+
* the same theme files, the exact `fontFamily: '<Name>'` literals, mapped to the SDK's per-weight `fonts`
|
|
2371
|
+
* map by the weight word in each name (`Azeret-Regular`, `Inter_500Medium`, `Roboto Bold`), or the one
|
|
2372
|
+
* family the files name when none carries a weight. Never a family the files do not name.
|
|
2373
|
+
*
|
|
2374
|
+
* STATIC PARSING ONLY. Nothing here requires, evaluates or executes a partner's file; a value that is computed
|
|
2375
|
+
* (an identifier, a call, a template literal, a `calc()`) is dropped with that reason, and a config that runs
|
|
2376
|
+
* code at load time (a Node built-in module, `eval`) is refused whole. `tests/unit/theme-detect.test.ts` pins
|
|
2377
|
+
* that at the source.
|
|
2378
|
+
*
|
|
2379
|
+
* THE MAPPING is to the SDK's `EverfurThemeInput` (everfur-sdk-rn src/client/theme/input.ts), and only where
|
|
2380
|
+
* it is unambiguous: primary or brand to `primaryColor`; accent or secondary to `accentColor`, unless it reads
|
|
2381
|
+
* as a surface tint (under 1.5:1 against the background, the shadcn `--accent` hover wash); the background to
|
|
2382
|
+
* `brightness` (pinned when the project declares no dark variant) and, for a light ground close to one of the
|
|
2383
|
+
* SDK's three compiled surfaces, `surfaceStyle`; a base radius to `radiusScale` by size; the first family of a
|
|
2384
|
+
* font stack to `fontFamily` when it is a plain family name (the web, where the page loads the weights itself); a
|
|
2385
|
+
* React Native theme file's `fontFamily` literals to the registered faces `fontRegular`, `fontMedium` and
|
|
2386
|
+
* `fontBold` (written as the SDK's `fonts` map, names only: the app registers the faces, the SDK bundles no font
|
|
2387
|
+
* and synthesizes no weight on a named face). The foreground is read as evidence only: the SDK
|
|
2388
|
+
* computes its text colours from the ground (WCAG), and the prop has no text token outside slots. Every colour
|
|
2389
|
+
* is written as `#RRGGBB`, the form the SDK parses; `hsl()` and `oklch()` are converted (theme-color.ts).
|
|
2390
|
+
*
|
|
2391
|
+
* THE CONFIDENCE GATE. `high` when a primary and a background both come from one source with literal values;
|
|
2392
|
+
* `medium` when only some tokens were read; `low` otherwise. A computed colour the mapping wanted drops the
|
|
2393
|
+
* grade one level; a config that runs code at load time, or builds a theme value with a template literal, is
|
|
2394
|
+
* `low` whatever it declares. At `low` the theme is empty: nothing read from a source this tool could not fully
|
|
2395
|
+
* trust is written into a partner's app.
|
|
2396
|
+
*/
|
|
2397
|
+
type ThemeSource = 'tailwind-v4' | 'tailwind-v3' | 'css-variables' | 'react-navigation' | 'rn-colors' | 'none';
|
|
2398
|
+
type ThemeConfidence = 'high' | 'medium' | 'low';
|
|
2399
|
+
/**
|
|
2400
|
+
* The subset of the SDK's `EverfurThemeInput` a plan writes. Every value is a string, so the emitted literal
|
|
2401
|
+
* type-checks against the prop on every SDK release that publishes it. Mirrors input.ts; extend both together.
|
|
2402
|
+
*/
|
|
2403
|
+
interface DetectedTheme {
|
|
2404
|
+
/** `#RRGGBB`. */
|
|
2405
|
+
readonly primaryColor?: string;
|
|
2406
|
+
readonly accentColor?: string;
|
|
2407
|
+
/** The fills on the dark palette, when the project declares a dark variant (or is dark only). */
|
|
2408
|
+
readonly primaryColorDark?: string;
|
|
2409
|
+
readonly accentColorDark?: string;
|
|
2410
|
+
/** Pinned only when the project declares no dark variant: the surface then matches the page whatever the device says. */
|
|
2411
|
+
readonly brightness?: 'light' | 'dark';
|
|
2412
|
+
/** The compiled SDK surface nearest a light background, when one is within tolerance. */
|
|
2413
|
+
readonly surfaceStyle?: 'white' | 'cream' | 'subtle';
|
|
2414
|
+
readonly radiusScale?: 'sharp' | 'default' | 'round';
|
|
2415
|
+
/** One plain family name, never a stack. */
|
|
2416
|
+
readonly fontFamily?: string;
|
|
2417
|
+
/**
|
|
2418
|
+
* The registered face per weight (the SDK's `fonts` map, `regular`, `medium` and `bold`): one family NAME each,
|
|
2419
|
+
* exactly as a React Native theme file declares it in a `fontFamily` literal. The app registers the faces itself.
|
|
2420
|
+
*/
|
|
2421
|
+
readonly fontRegular?: string;
|
|
2422
|
+
readonly fontMedium?: string;
|
|
2423
|
+
readonly fontBold?: string;
|
|
2424
|
+
}
|
|
2425
|
+
type ThemeToken = keyof DetectedTheme;
|
|
2426
|
+
/** The order the tokens are written in generated code. */
|
|
2427
|
+
declare const THEME_TOKEN_ORDER: readonly ThemeToken[];
|
|
2428
|
+
interface ThemeEvidence {
|
|
2429
|
+
/** The file, relative to the project root, or the label of a pasted source. */
|
|
2430
|
+
readonly file: string;
|
|
2431
|
+
/** 1-based line of the declaration the value was read from (the literal's line after a one-level resolution). */
|
|
2432
|
+
readonly line: number;
|
|
2433
|
+
/** The declaration read, with its resolution chain: `--color-primary -> --primary`, `Colors.light.tint -> tintColorLight`. */
|
|
2434
|
+
readonly key: string;
|
|
2435
|
+
/** The value as written. */
|
|
2436
|
+
readonly value: string;
|
|
2437
|
+
/** The theme field it became, or null when it was read and dropped (or read as evidence only). */
|
|
2438
|
+
readonly token: ThemeToken | null;
|
|
2439
|
+
/** How it mapped, or why it did not. */
|
|
2440
|
+
readonly reason: string;
|
|
2441
|
+
}
|
|
2442
|
+
/** Where one logo URL was read from. */
|
|
2443
|
+
interface ThemeLogoEvidence {
|
|
2444
|
+
readonly file: string;
|
|
2445
|
+
/** 1-based line of the declaration in the file as written. */
|
|
2446
|
+
readonly line: number;
|
|
2447
|
+
/** The declaration read: a custom property name, or the img tag's attribute. */
|
|
2448
|
+
readonly key: string;
|
|
2449
|
+
readonly value: string;
|
|
2450
|
+
}
|
|
2451
|
+
/**
|
|
2452
|
+
* THE LOGO (MCP-11). The SDK's theme takes `logoUrl` and `logoUrlDark` and the chat header shows them, and the
|
|
2453
|
+
* planner's theme never carried either, so every generated integration rendered Everfur's header on a partner's own
|
|
2454
|
+
* colours with no partner mark on it.
|
|
2455
|
+
*
|
|
2456
|
+
* https ONLY. The SDK drops a relative path (the frame and the app resolve it against the wrong origin) and plain
|
|
2457
|
+
* http (a mixed-content load the browser blocks), so a value that is not an absolute https URL is not read at all
|
|
2458
|
+
* rather than written and silently dropped at runtime.
|
|
2459
|
+
*/
|
|
2460
|
+
interface ThemeLogo {
|
|
2461
|
+
readonly light: string;
|
|
2462
|
+
readonly dark: string | null;
|
|
2463
|
+
readonly evidence: readonly ThemeLogoEvidence[];
|
|
2464
|
+
}
|
|
2465
|
+
interface ThemeDetection {
|
|
2466
|
+
readonly source: ThemeSource;
|
|
2467
|
+
readonly confidence: ThemeConfidence;
|
|
2468
|
+
/** Empty at `low`. */
|
|
2469
|
+
readonly theme: DetectedTheme;
|
|
2470
|
+
readonly evidence: readonly ThemeEvidence[];
|
|
2471
|
+
/** The files read, relative to the root, so a refusal says where it looked. */
|
|
2472
|
+
readonly scanned: readonly string[];
|
|
2473
|
+
/** The facts a high-confidence match needs and this project did not give, in the refusal's words. Empty at `high`. */
|
|
2474
|
+
readonly missing: readonly string[];
|
|
2475
|
+
/** The fields whose value is a nearest match rather than a literal; generated code marks them `REPLACE: verify`. */
|
|
2476
|
+
readonly inferred: readonly ThemeToken[];
|
|
2477
|
+
/** The logo the project declares, https only; null when it declares none this detector can use. */
|
|
2478
|
+
readonly logo?: ThemeLogo | null;
|
|
2479
|
+
}
|
|
2480
|
+
/**
|
|
2481
|
+
* Detect the project's theme from disk, through the filesystem port. Every project gets every reader (a React
|
|
2482
|
+
* Native app may carry a NativeWind config, a web project a colours module); `native` only puts the React
|
|
2483
|
+
* Native readers first, so a tie in confidence goes to the source that fits the shape.
|
|
2484
|
+
*/
|
|
2485
|
+
declare function detectTheme(fs: FileSystemPort, root: string, options?: {
|
|
2486
|
+
readonly native?: boolean;
|
|
2487
|
+
}): ThemeDetection;
|
|
2488
|
+
/**
|
|
2489
|
+
* Detect a theme from pasted text (the MCP `theme_source` argument): a stylesheet, a Tailwind config, or a
|
|
2490
|
+
* React Native theme file. The stylesheet readers and the Tailwind reader run over the text; the React Native
|
|
2491
|
+
* readers run only when it is not a Tailwind config (a config's `theme.extend.colors` would read as a colours
|
|
2492
|
+
* object otherwise). The best reading wins, and `label` names the text in the evidence.
|
|
2493
|
+
*/
|
|
2494
|
+
declare function detectThemeFromText(text: string, label: string): ThemeDetection;
|
|
2495
|
+
|
|
2496
|
+
/**
|
|
2497
|
+
* THE PARTNER'S `theme` PROP, as `everfur plan` writes it for a project: the `EVERFUR_THEME` constant a generated
|
|
2498
|
+
* provider passes as `theme={EVERFUR_THEME}` (codegen.ts themeConstant), from the same theme detection the plan reads
|
|
2499
|
+
* (the project on disk, or a pasted `theme_source`). The SDK merges it over the tenant's console branding per field,
|
|
2500
|
+
* so `verify --surfaces theme` judges that merge rather than the console branding alone.
|
|
2501
|
+
*
|
|
2502
|
+
* The object holds exactly the fields the plan writes: every detected token by its own name (they are the SDK's
|
|
2503
|
+
* `EverfurThemeInput` field names), with the three registered faces written as the `fonts` map. A detection the plan
|
|
2504
|
+
* would not write a theme for (low confidence, or nothing read) yields null: the plan passes no prop then.
|
|
2505
|
+
*/
|
|
2506
|
+
interface ThemeProp {
|
|
2507
|
+
/** The prop, in the SDK's `EverfurThemeInput` field names. */
|
|
2508
|
+
readonly input: Readonly<Record<string, unknown>>;
|
|
2509
|
+
/** Where it was read, for the report: the detection source and the file:line of each field. */
|
|
2510
|
+
readonly source: string;
|
|
2511
|
+
}
|
|
2512
|
+
|
|
2513
|
+
/**
|
|
2514
|
+
* THE SURFACE CHECKS, run when `--surfaces` names them: each asks whether one Everfur surface works for THIS tenant
|
|
2515
|
+
* with the session `verify` just minted, from the same wire a partner's app uses.
|
|
2516
|
+
*
|
|
2517
|
+
* chat the diagnostics reason for chat.message.create and chat.conversation.read, then GET
|
|
2518
|
+
* /widget/v1/conversations on the bearer.
|
|
2519
|
+
* records the diagnostics reason for records.record.read, then GET /widget/v1/records/requests on the bearer.
|
|
2520
|
+
* televet SANDBOX TENANTS ONLY (verdict livemode false): POST /widget/v1/televet/handoffs on the bearer. A live
|
|
2521
|
+
* tenant is never sent a write. The handoff token rides the URL fragment; it is stripped before anything
|
|
2522
|
+
* is kept, so only the origin, the path and the expiry reach the report.
|
|
2523
|
+
* theme the branding the verdict's render_hints carry, rendered by the SDK's own resolver (theme-render.ts, over
|
|
2524
|
+
* the SDK code mirrored into src/registry/sdk): which fields are overridden and which the tenant locked,
|
|
2525
|
+
* whether the SDK drops the whole branding for a schema_version it does not read, whether it would drop a
|
|
2526
|
+
* logo or font URL, whether text on the brand fill it paints reaches WCAG 4.5:1 on each palette it shows
|
|
2527
|
+
* (light unless a brightness says otherwise, both for auto), and which configured slot colours its guard
|
|
2528
|
+
* repaints. The inks it pushes until they read (brand text, links) and the dark variants it derives are
|
|
2529
|
+
* reported, not failed. With a project (`--project-root`, `project_root`) or a pasted `theme_source`, the
|
|
2530
|
+
* branding is judged MERGED with the `theme` prop `everfur plan` writes from that theme, as the SDK merges
|
|
2531
|
+
* them: the prop wins per field unless the tenant locked it.
|
|
2532
|
+
*
|
|
2533
|
+
* Every step authenticates with the identity verify used: the minted session bearer, or, for
|
|
2534
|
+
* `--identity anonymous`, the publishable key and the derived device session id (Records and Televet take a
|
|
2535
|
+
* signed session only, so an anonymous run skips both and reads chat alone).
|
|
2536
|
+
*
|
|
2537
|
+
* A surface Everfur has not switched on for the tenant is GATED, not FAIL: a platform setting is not a broken
|
|
2538
|
+
* integration, and reporting it as one would send a partner debugging code that is fine.
|
|
2539
|
+
*/
|
|
2540
|
+
declare const SURFACES: readonly ["chat", "records", "televet", "theme"];
|
|
2541
|
+
type Surface = (typeof SURFACES)[number];
|
|
2542
|
+
|
|
1977
2543
|
/**
|
|
1978
2544
|
* THE WIRE EXERCISE. Three steps, run in order, each of which reports what happened rather than
|
|
1979
2545
|
* what the process is about to exit with.
|
|
1980
2546
|
*
|
|
1981
|
-
* mint-session
|
|
2547
|
+
* mint-session the session to verify with: EVERFUR_SESSION_TOKEN when set (a short-lived session the
|
|
2548
|
+
* partner backend minted, the only source the MCP tool reads), else, from the local CLI
|
|
2549
|
+
* only, POST /widget/v1/sessions with the sk + pk pair. On the Everfur-hosted MCP the
|
|
2550
|
+
* session was minted by the Everfur API for the signed-in sandbox tenant before this ran
|
|
2551
|
+
* (`sessionSource: 'hosted'`), and a live tenant is GATED here rather than skipped.
|
|
1982
2552
|
* poll-entitlements GET /widget/v1/entitlements with the minted bearer.
|
|
1983
|
-
* assert-verdict the verdict carries at least one capability.
|
|
2553
|
+
* assert-verdict the verdict carries at least one capability, and it is ENABLED. A listed capability
|
|
2554
|
+
* whose surface is switched off is reported as unavailable with its reason code, never
|
|
2555
|
+
* as granted: see `VerdictCapability`.
|
|
1984
2556
|
*
|
|
1985
2557
|
* Three properties this file exists to guarantee:
|
|
1986
2558
|
*
|
|
@@ -1996,8 +2568,24 @@ declare function renderSandboxCreate(creation: SandboxCreation, revocation: Sand
|
|
|
1996
2568
|
* The mint is a POST and gets exactly one attempt. The poll is a GET, so repeating it is safe,
|
|
1997
2569
|
* and it repeats on purpose: an entitlement scope provisioned seconds ago propagates on a
|
|
1998
2570
|
* revision bump, and a single read would report a stale empty verdict as a failure.
|
|
2571
|
+
*
|
|
2572
|
+
* `identityMode: 'anonymous'` verifies the path an anonymous integration actually uses, which has no
|
|
2573
|
+
* backend to mint a session: the publishable key plus a device session id derived from the user ref
|
|
2574
|
+
* (`x-everfur-session-id`), exactly what the SDK sends without a user. It runs the entitlement read and
|
|
2575
|
+
* the assertion on that identity, then reads the tenant's session policy and lists the identity's conversations.
|
|
2576
|
+
* `sessions_required` refuses only an UNSIGNED caller that claims an identity (a publishable key plus
|
|
2577
|
+
* `x-everfur-user-ref`); signed callers and pure-anonymous callers stay exempt (EFBackend widget_dependencies.py,
|
|
2578
|
+
* "Session enforcement"), so the policy is reported, never failed, on the anonymous path.
|
|
2579
|
+
*/
|
|
2580
|
+
/** The identities a verification can exercise, in the plan's own vocabulary. `partner-user-ref` is the default. */
|
|
2581
|
+
declare const VERIFY_IDENTITY_MODES: readonly ["partner-user-ref", "anonymous"];
|
|
2582
|
+
type VerifyIdentityMode = (typeof VERIFY_IDENTITY_MODES)[number];
|
|
2583
|
+
/**
|
|
2584
|
+
* GATED is the fourth answer, added with the surface checks: the step ran and found a surface Everfur has switched
|
|
2585
|
+
* off for the tenant. It is neither a failure of the integration (FAIL) nor something the operator can supply to make
|
|
2586
|
+
* the step run (SKIP), so it moves the status in neither direction.
|
|
1999
2587
|
*/
|
|
2000
|
-
type StepResult = 'PASS' | 'FAIL' | 'SKIP';
|
|
2588
|
+
type StepResult = 'PASS' | 'FAIL' | 'SKIP' | 'GATED';
|
|
2001
2589
|
interface VerifyStep {
|
|
2002
2590
|
/** Stable within a schemaVersion. Callers may key on it. */
|
|
2003
2591
|
readonly id: string;
|
|
@@ -2008,6 +2596,51 @@ interface VerifyStep {
|
|
|
2008
2596
|
readonly requestId: string | null;
|
|
2009
2597
|
readonly details: readonly string[];
|
|
2010
2598
|
}
|
|
2599
|
+
/**
|
|
2600
|
+
* What the Everfur-hosted MCP did about a session before `runVerification` ran.
|
|
2601
|
+
*
|
|
2602
|
+
* The hosted server holds no key of the partner's, so it asks the Everfur API to mint a verify session for
|
|
2603
|
+
* the signed-in tenant (`POST /mcp/verify-sessions`, sandbox tenants only). The outcome is data here, not a
|
|
2604
|
+
* credential: a minted session travels in the env map like a backend-minted one, and this record carries
|
|
2605
|
+
* only what the step report may say about it.
|
|
2606
|
+
*/
|
|
2607
|
+
type HostedSessionOutcome = {
|
|
2608
|
+
readonly kind: 'minted';
|
|
2609
|
+
readonly userRef: string;
|
|
2610
|
+
readonly expiresAt: string;
|
|
2611
|
+
readonly capabilities: readonly string[];
|
|
2612
|
+
readonly requestId: string | null;
|
|
2613
|
+
} | {
|
|
2614
|
+
readonly kind: 'gated';
|
|
2615
|
+
readonly reason: string;
|
|
2616
|
+
readonly requestId: string | null;
|
|
2617
|
+
} | {
|
|
2618
|
+
readonly kind: 'failed';
|
|
2619
|
+
readonly reason: string;
|
|
2620
|
+
readonly requestId: string | null;
|
|
2621
|
+
readonly details: readonly string[];
|
|
2622
|
+
/**
|
|
2623
|
+
* The operator-owned facts of the failed mint call, when there was one: how it failed (`http`, `network`,
|
|
2624
|
+
* `timeout`), the status and the wire code. Never the wire text. Lets a caller tell a transient failure (a 429
|
|
2625
|
+
* VerifyMintRateLimited, a 503 VerifyMintUnavailable, a timeout) from a permanent one. Absent when no call was made.
|
|
2626
|
+
*/
|
|
2627
|
+
readonly failure?: {
|
|
2628
|
+
readonly kind: string;
|
|
2629
|
+
readonly status: number | null;
|
|
2630
|
+
readonly code: string | null;
|
|
2631
|
+
};
|
|
2632
|
+
};
|
|
2633
|
+
/** What a hosted mint hands back: the outcome for the report, and the session itself when one was minted. */
|
|
2634
|
+
interface HostedMintResult {
|
|
2635
|
+
readonly outcome: HostedSessionOutcome;
|
|
2636
|
+
/** The minted widget session, wrapped as an ephemeral credential the moment it is read here. Null unless minted. */
|
|
2637
|
+
readonly sessionToken: string | null;
|
|
2638
|
+
}
|
|
2639
|
+
/**
|
|
2640
|
+
* The hosted server's mint, called by this step once verification has decided to run, so a call refused for
|
|
2641
|
+
* its arguments never mints, and the session never travels through the env map.
|
|
2642
|
+
*/
|
|
2643
|
+
type HostedMint = () => Promise<HostedMintResult>;
|
|
2011
2644
|
interface VerifyOptions {
|
|
2012
2645
|
readonly client: ApiClient;
|
|
2013
2646
|
readonly clock: ClockPort;
|
|
@@ -2016,6 +2649,47 @@ interface VerifyOptions {
|
|
|
2016
2649
|
/** How many times to read the verdict before concluding it is empty. */
|
|
2017
2650
|
readonly attempts: number;
|
|
2018
2651
|
readonly pollDelayMs: number;
|
|
2652
|
+
/**
|
|
2653
|
+
* The page origin a web integration embeds from. When set, the web checks (`web.ts`) run after the wire
|
|
2654
|
+
* exercise: the embed fence, the CORS exposure, the session policy, the loader. Null skips them.
|
|
2655
|
+
*/
|
|
2656
|
+
readonly origin?: string | null;
|
|
2657
|
+
/** The transport for the loader probe, which leaves the API host. Null skips that one check. */
|
|
2658
|
+
readonly transport?: TransportPort | null;
|
|
2659
|
+
readonly timeoutMs?: number;
|
|
2660
|
+
/** The surfaces to exercise with the minted session (`surfaces.ts`). Empty or absent runs none. */
|
|
2661
|
+
readonly surfaces?: readonly Surface[];
|
|
2662
|
+
/** The project to run the offline checks over (`project-checks.ts`), with the port to read it. Null runs none. */
|
|
2663
|
+
readonly project?: {
|
|
2664
|
+
readonly fs: FileSystemPort;
|
|
2665
|
+
readonly root: string;
|
|
2666
|
+
} | null;
|
|
2667
|
+
/**
|
|
2668
|
+
* Whether the key pair may mint when EVERFUR_SESSION_TOKEN is absent. True for the local CLI (the fallback); false
|
|
2669
|
+
* for the MCP tool, whose documented environment never holds the secret key, so it never reads one.
|
|
2670
|
+
*/
|
|
2671
|
+
readonly mintWithSecretKey?: boolean;
|
|
2672
|
+
/** The loader to probe for the web checks, overriding the one derived from the API host. Null derives it. */
|
|
2673
|
+
readonly loaderUrl?: string | null;
|
|
2674
|
+
/**
|
|
2675
|
+
* Where the session comes from. `env` (the default): EVERFUR_SESSION_TOKEN, else the local key-pair mint when
|
|
2676
|
+
* `mintWithSecretKey` allows it. `hosted`: this step asks the Everfur API for one on the signed-in tenant's
|
|
2677
|
+
* behalf through `hostedMint`, and reports how that went. The hosted wording names no variable, because the
|
|
2678
|
+
* partner exported none.
|
|
2679
|
+
*/
|
|
2680
|
+
readonly sessionSource?: 'env' | 'hosted';
|
|
2681
|
+
readonly hostedMint?: HostedMint | null;
|
|
2682
|
+
/**
|
|
2683
|
+
* Which identity to verify with. `partner-user-ref` (the default): a signed session, from `sessionSource` as
|
|
2684
|
+
* above. `anonymous`: the publishable key and a derived device session id; nothing is minted, on either server.
|
|
2685
|
+
*/
|
|
2686
|
+
readonly identityMode?: VerifyIdentityMode;
|
|
2687
|
+
/**
|
|
2688
|
+
* The `theme` prop the theme check merges over the tenant's branding, as the SDK does. Absent: the prop `everfur plan`
|
|
2689
|
+
* writes from the project's own theme when `project` is given (none otherwise). Null: no prop. The MCP tool passes
|
|
2690
|
+
* the prop read from a pasted `theme_source`, which wins over the project on disk, as it does for the plan.
|
|
2691
|
+
*/
|
|
2692
|
+
readonly themeProp?: ThemeProp | null;
|
|
2019
2693
|
}
|
|
2020
2694
|
interface Verification {
|
|
2021
2695
|
readonly steps: readonly VerifyStep[];
|
|
@@ -2072,7 +2746,26 @@ declare function createMemoryFileSystem(files: Readonly<Record<string, string>>)
|
|
|
2072
2746
|
* disk. Anything it cannot establish lives in `src/commands/plan/facts.ts` as a supplied fact,
|
|
2073
2747
|
* and the two sets are deliberately disjoint.
|
|
2074
2748
|
*/
|
|
2075
|
-
type ProjectType = 'expo-managed' | 'bare-react-native' | 'flutter' | 'web' | 'unknown';
|
|
2749
|
+
type ProjectType = 'expo-managed' | 'bare-react-native' | 'flutter' | 'web' | 'shopify-storefront' | 'unknown';
|
|
2750
|
+
/**
|
|
2751
|
+
* How a web project embeds the Everfur surface, read from the project: `in-page` when package.json
|
|
2752
|
+
* declares react-dom (the SDK's React components render in the host's own tree), `frame` otherwise (the
|
|
2753
|
+
* loader puts the surface in an iframe on Everfur's origin, and nothing is installed). The platform tree
|
|
2754
|
+
* asks this as its `web-embedding` question; `--embedding` overrides the detected answer. Null for every
|
|
2755
|
+
* other project shape.
|
|
2756
|
+
*/
|
|
2757
|
+
type WebEmbedding = 'in-page' | 'frame';
|
|
2758
|
+
/**
|
|
2759
|
+
* The web framework facet of a `web` project (see `web-framework.ts`). It spells the generated files; the
|
|
2760
|
+
* contract's platform tree still branches on the project type, which this never replaces.
|
|
2761
|
+
*/
|
|
2762
|
+
type WebFramework = 'next-app-router' | 'next-pages-router' | 'vite-react' | 'remix' | 'static-html' | 'other-web';
|
|
2763
|
+
interface WebFrameworkDetection {
|
|
2764
|
+
readonly framework: WebFramework;
|
|
2765
|
+
/** `src/` when the framework's source root is `src/` (Next.js with src/app, a Vite app), else empty. */
|
|
2766
|
+
readonly sourceDir: '' | 'src/';
|
|
2767
|
+
readonly evidence: readonly string[];
|
|
2768
|
+
}
|
|
2076
2769
|
type PackageManager = 'npm' | 'pnpm' | 'yarn' | 'bun' | 'not-applicable' | 'undetermined';
|
|
2077
2770
|
type DependencySource = 'package.json' | 'pubspec.yaml';
|
|
2078
2771
|
type DependencyScope = 'dependencies' | 'devDependencies' | 'peerDependencies' | 'sdk';
|
|
@@ -2097,6 +2790,47 @@ interface ProjectDetection {
|
|
|
2097
2790
|
readonly packageManager: PackageManager;
|
|
2098
2791
|
readonly packageManagerEvidence: readonly string[];
|
|
2099
2792
|
readonly dependencies: readonly DetectedDependency[];
|
|
2793
|
+
/** The detected embedding of a `web` project; null for every other shape. Its evidence is in `projectTypeEvidence`. */
|
|
2794
|
+
readonly webEmbedding: WebEmbedding | null;
|
|
2795
|
+
/**
|
|
2796
|
+
* The detected framework of a `web` project; null (or absent, for a detection built by hand) for every
|
|
2797
|
+
* other shape.
|
|
2798
|
+
*/
|
|
2799
|
+
readonly webFramework?: WebFrameworkDetection | null;
|
|
2800
|
+
/**
|
|
2801
|
+
* What the project already says about its own look (theme-detect.ts), for the shapes the plan writes a provider
|
|
2802
|
+
* for (web, Expo, bare React Native); null for every other shape, and absent for a detection built by hand.
|
|
2803
|
+
*/
|
|
2804
|
+
readonly theme?: ThemeDetection | null;
|
|
2805
|
+
/**
|
|
2806
|
+
* Expo Router, for a React Native project that uses it (expo-router.ts); null when it does not, and absent for a
|
|
2807
|
+
* detection built by hand. It decides where the plan tells the app to mount its Everfur module: Expo Router never
|
|
2808
|
+
* renders App.tsx, and every file under its routes directory is a route.
|
|
2809
|
+
*/
|
|
2810
|
+
readonly expoRouter?: ExpoRouterDetection | null;
|
|
2811
|
+
/**
|
|
2812
|
+
* The URL schemes a React Native project declares and the application ids beside them (app-schemes.ts), so the
|
|
2813
|
+
* visit-return step can say whether one of them is a destination Everfur would register (MCP-14). Null for every
|
|
2814
|
+
* other shape, and absent for a detection built by hand.
|
|
2815
|
+
*/
|
|
2816
|
+
readonly appSchemes?: AppSchemeDetection | null;
|
|
2817
|
+
}
|
|
2818
|
+
/** What a React Native project declares about its own URL schemes. */
|
|
2819
|
+
interface AppSchemeDetection {
|
|
2820
|
+
/** Every declared scheme, in the order app.json, iOS, Android. */
|
|
2821
|
+
readonly schemes: readonly string[];
|
|
2822
|
+
/** The application ids declared beside them (the iOS bundle identifier, the Android package). */
|
|
2823
|
+
readonly appIds: readonly string[];
|
|
2824
|
+
/** The first declared scheme in reverse-DNS form, which is the only form Everfur registers; null when there is none. */
|
|
2825
|
+
readonly reverseDns: string | null;
|
|
2826
|
+
/** The file and key each scheme was read from. */
|
|
2827
|
+
readonly evidence: readonly string[];
|
|
2828
|
+
}
|
|
2829
|
+
/** An Expo Router project: its routes directory, and the files that said so. */
|
|
2830
|
+
interface ExpoRouterDetection {
|
|
2831
|
+
/** `app`, or `src/app` when the routes live there (Expo Router reads `src/app` when `app` is absent). */
|
|
2832
|
+
readonly appDir: 'app' | 'src/app';
|
|
2833
|
+
readonly evidence: readonly string[];
|
|
2100
2834
|
}
|
|
2101
2835
|
|
|
2102
2836
|
declare function detectProject(fs: FileSystemPort, root: string): ProjectDetection;
|
|
@@ -2119,6 +2853,23 @@ interface TerminalOutcome {
|
|
|
2119
2853
|
readonly capabilityRefs: readonly string[];
|
|
2120
2854
|
/** The tree that must be answered next, or null when this answer stands alone. */
|
|
2121
2855
|
readonly thenAskTreeId: string | null;
|
|
2856
|
+
/**
|
|
2857
|
+
* Present for a `human_ui` outcome (owner decision 2026-09-17): the plan may emit the UI a person taps, and no
|
|
2858
|
+
* agent may perform what it does. Why, and where to ask. Absent (or null) for an ordinary terminal. A
|
|
2859
|
+
* `partner_backend` outcome carries it too, for what no agent does with a delivery.
|
|
2860
|
+
*/
|
|
2861
|
+
readonly agentBlocked?: AgentBlock | null;
|
|
2862
|
+
/**
|
|
2863
|
+
* True for a `partner_backend` outcome (DECISIONS.md entry 21): the plan writes code the partner's BACKEND runs to
|
|
2864
|
+
* receive from Everfur (the webhook receiver), not a surface a device mounts. Absent for every other terminal.
|
|
2865
|
+
*/
|
|
2866
|
+
readonly partnerBackend?: true;
|
|
2867
|
+
}
|
|
2868
|
+
/** The agent refusal a `human_ui` outcome carries beside its terminal facts. */
|
|
2869
|
+
interface AgentBlock {
|
|
2870
|
+
readonly reason: string;
|
|
2871
|
+
readonly unblockOwner: string;
|
|
2872
|
+
readonly requestPath: string;
|
|
2122
2873
|
}
|
|
2123
2874
|
interface BlockedOutcome {
|
|
2124
2875
|
readonly kind: 'blocked';
|
|
@@ -2233,7 +2984,7 @@ interface PlanCode {
|
|
|
2233
2984
|
/** Suggested path, relative to the project root. */
|
|
2234
2985
|
readonly path: string;
|
|
2235
2986
|
/** For syntax highlighting and for an agent deciding how to write it. */
|
|
2236
|
-
readonly language: 'tsx' | 'ts' | 'dart';
|
|
2987
|
+
readonly language: 'tsx' | 'ts' | 'dart' | 'html' | 'liquid' | 'dotenv';
|
|
2237
2988
|
readonly contents: string;
|
|
2238
2989
|
}
|
|
2239
2990
|
|
|
@@ -2270,6 +3021,11 @@ declare const PLAN_DOCUMENT_KIND = "everfur.plan";
|
|
|
2270
3021
|
type Capability = string;
|
|
2271
3022
|
/** An identity mode id: one option of the identity-mode tree's entry question. */
|
|
2272
3023
|
type IdentityMode = string;
|
|
3024
|
+
/**
|
|
3025
|
+
* A web embedding id: one option of the platform tree's `web-embedding` question. Detected from the
|
|
3026
|
+
* project (react-dom present means in-page, otherwise the frame) and overridable by `--embedding`.
|
|
3027
|
+
*/
|
|
3028
|
+
type Embedding = string;
|
|
2273
3029
|
/** A backend language id: one option of the session-mint-language tree's entry question. */
|
|
2274
3030
|
type SessionMintLanguage = string;
|
|
2275
3031
|
type PlanStatus = 'ready' | 'underspecified' | 'blocked';
|
|
@@ -2282,7 +3038,7 @@ type PlanStatus = 'ready' | 'underspecified' | 'blocked';
|
|
|
2282
3038
|
* reachable. It is a REFUSAL rather than a broken-artifact failure because nothing was loaded
|
|
2283
3039
|
* and nothing on disk is wrong; the operator simply has not said where the contract is.
|
|
2284
3040
|
*/
|
|
2285
|
-
declare const MISSING_FACT_NAMES: readonly ["decisionTrees", "projectType", "packageManager", "capabilities", "identityMode", "sessionMintLanguage"];
|
|
3041
|
+
declare const MISSING_FACT_NAMES: readonly ["decisionTrees", "projectType", "packageManager", "embedding", "capabilities", "identityMode", "sessionMintLanguage", "environment"];
|
|
2286
3042
|
type MissingFactName = (typeof MISSING_FACT_NAMES)[number];
|
|
2287
3043
|
interface MissingFact {
|
|
2288
3044
|
readonly fact: MissingFactName;
|
|
@@ -2331,8 +3087,18 @@ interface BlockedCapability {
|
|
|
2331
3087
|
readonly unblockOwner: string;
|
|
2332
3088
|
/** Site-relative path on the partner documentation site. Resolved at compile time. */
|
|
2333
3089
|
readonly requestPath: string;
|
|
2334
|
-
/** The capability pack keys the block derives from. */
|
|
3090
|
+
/** The capability pack keys the block derives from. Empty when the block is the platform's. */
|
|
2335
3091
|
readonly capabilityKeys: readonly string[];
|
|
3092
|
+
/**
|
|
3093
|
+
* What refused it. `capability` (the default when absent, for documents written before this field
|
|
3094
|
+
* existed) is a BLOCKED terminal in the capabilities tree: the surface itself cannot be built.
|
|
3095
|
+
* `platform` is the host project shape: the surface is buildable, but not for this project, because
|
|
3096
|
+
* the SDK publishes no entry point for it or the contract blocks the shape outright. An agent that
|
|
3097
|
+
* reads the two the same way tells a developer to ask support about chat when the answer is "not
|
|
3098
|
+
* from this project shape". (Next.js, the App Router and the Pages Router alike, IS plannable: the
|
|
3099
|
+
* framework is detected from the project and gets its own route convention.)
|
|
3100
|
+
*/
|
|
3101
|
+
readonly blockedBy?: 'capability' | 'platform';
|
|
2336
3102
|
}
|
|
2337
3103
|
/**
|
|
2338
3104
|
* Guidance that is true regardless of what was answered, carried in the document rather than
|
|
@@ -2364,6 +3130,22 @@ interface PlanDetection {
|
|
|
2364
3130
|
readonly source: string;
|
|
2365
3131
|
readonly scope: string;
|
|
2366
3132
|
}[];
|
|
3133
|
+
/**
|
|
3134
|
+
* The detected embedding of a `web` project (`in-page` or `frame`), null for other shapes. Additive to
|
|
3135
|
+
* schema v1: absent on documents written before the web shapes existed.
|
|
3136
|
+
*/
|
|
3137
|
+
readonly webEmbedding?: string | null;
|
|
3138
|
+
/**
|
|
3139
|
+
* The detected framework of a `web` project (next-app-router, next-pages-router, vite-react, remix,
|
|
3140
|
+
* static-html, other-web), null for other shapes. Additive to schema v1.
|
|
3141
|
+
*/
|
|
3142
|
+
readonly webFramework?: string | null;
|
|
3143
|
+
/**
|
|
3144
|
+
* What the project says about its own look, read statically (detect/theme-detect.ts): the source, the confidence,
|
|
3145
|
+
* the SDK theme fields it mapped, and the file:line evidence for each. Null for a shape the plan writes no
|
|
3146
|
+
* provider for, or for a detection built by hand. Additive to schema v1.
|
|
3147
|
+
*/
|
|
3148
|
+
readonly theme?: ThemeDetection | null;
|
|
2367
3149
|
}
|
|
2368
3150
|
interface PlanDocument {
|
|
2369
3151
|
readonly schemaVersion: typeof PLAN_SCHEMA_VERSION;
|
|
@@ -2380,6 +3162,13 @@ interface PlanDocument {
|
|
|
2380
3162
|
readonly capabilities: readonly Capability[] | null;
|
|
2381
3163
|
readonly identityMode: IdentityMode | null;
|
|
2382
3164
|
readonly sessionMintLanguage: SessionMintLanguage | null;
|
|
3165
|
+
/** `--embedding`, when given; null means the detected embedding decided. Additive to schema v1. */
|
|
3166
|
+
readonly embedding?: Embedding | null;
|
|
3167
|
+
/**
|
|
3168
|
+
* `--environment` (test, staging or production); null means it was not given. Required for a plan that writes
|
|
3169
|
+
* configuration, and never defaulted. Additive to schema v1.
|
|
3170
|
+
*/
|
|
3171
|
+
readonly environment?: string | null;
|
|
2383
3172
|
};
|
|
2384
3173
|
/** Empty when `status` is `ready`. Non-empty exactly when it is `underspecified`. */
|
|
2385
3174
|
readonly missingFacts: readonly MissingFact[];
|
|
@@ -2387,12 +3176,31 @@ interface PlanDocument {
|
|
|
2387
3176
|
readonly steps: readonly PlanStep[];
|
|
2388
3177
|
/** Non-empty exactly when a selected capability cannot be built today. */
|
|
2389
3178
|
readonly blocked: readonly BlockedCapability[];
|
|
3179
|
+
/**
|
|
3180
|
+
* Non-null when the host project SHAPE refuses every plan, whatever was asked for: the contract blocks
|
|
3181
|
+
* the shape, or the SDK publishes no entry point for it. Carried at the top level, beside the
|
|
3182
|
+
* per-capability blocks, because it is a fact about the project rather than about any capability, and
|
|
3183
|
+
* a reader branching on `blocked[].blockedBy` alone would miss it on a document whose only asked-for
|
|
3184
|
+
* capabilities were also blocked by the registry. Additive to schema v1 (optional; absent on documents
|
|
3185
|
+
* written before it existed, which means "no platform block").
|
|
3186
|
+
*/
|
|
3187
|
+
readonly platformBlock?: PlatformBlock | null;
|
|
2390
3188
|
/** The principles of every tree this plan consulted. */
|
|
2391
3189
|
readonly principles: readonly PlanPrinciple[];
|
|
2392
3190
|
readonly warnings: readonly PlanWarning[];
|
|
2393
3191
|
/** Null only on the refusal that says no decision space was found. */
|
|
2394
3192
|
readonly decisionSpace: DecisionSpaceProvenance | null;
|
|
2395
3193
|
}
|
|
3194
|
+
/** Why a whole project shape is refused, independent of which capabilities were asked for. */
|
|
3195
|
+
interface PlatformBlock {
|
|
3196
|
+
readonly reason: string;
|
|
3197
|
+
readonly unblockOwner: string;
|
|
3198
|
+
/** Site-relative path on the partner documentation site. */
|
|
3199
|
+
readonly requestPath: string;
|
|
3200
|
+
}
|
|
3201
|
+
|
|
3202
|
+
declare const ENVIRONMENTS: readonly ["test", "staging", "production"];
|
|
3203
|
+
type Environment = (typeof ENVIRONMENTS)[number];
|
|
2396
3204
|
|
|
2397
3205
|
/**
|
|
2398
3206
|
* The planner. A pure function from (what was detected, what was supplied, what the contract
|
|
@@ -2427,9 +3235,27 @@ interface PlanInput {
|
|
|
2427
3235
|
readonly capabilities: readonly Capability[] | null;
|
|
2428
3236
|
readonly identityMode: IdentityMode | null;
|
|
2429
3237
|
readonly sessionMintLanguage: SessionMintLanguage | null;
|
|
3238
|
+
/** `--embedding`, overriding the detected web embedding; absent or null means detection decides. */
|
|
3239
|
+
readonly embedding?: Embedding | null;
|
|
3240
|
+
/**
|
|
3241
|
+
* `--environment`: the Everfur deployment the generated configuration targets. Absent or null is a missing fact
|
|
3242
|
+
* for a plan that writes configuration; it is never defaulted.
|
|
3243
|
+
*/
|
|
3244
|
+
readonly environment?: Environment | null;
|
|
2430
3245
|
/** The decision space from the contract projection, or null when none was found. */
|
|
2431
3246
|
readonly space: DecisionSpace | null;
|
|
2432
3247
|
readonly cliVersion: string;
|
|
3248
|
+
/**
|
|
3249
|
+
* True when `capabilities` came from the `all` sentinel (every capability the contract can plan). The plan then says
|
|
3250
|
+
* so, and says that `verify` is the fail-closed check of what the tenant actually has: `plan` holds no credential.
|
|
3251
|
+
*/
|
|
3252
|
+
readonly allCapabilities?: boolean;
|
|
3253
|
+
/**
|
|
3254
|
+
* A theme detection that replaces the one on `detection`: a remote MCP that cannot read the project received the
|
|
3255
|
+
* partner's Tailwind config or CSS as `theme_source` and read it with `detectThemeFromText`. Absent means the
|
|
3256
|
+
* detection's own (which is absent too for a detection built by hand, and then no theme step is planned).
|
|
3257
|
+
*/
|
|
3258
|
+
readonly theme?: ThemeDetection | null;
|
|
2433
3259
|
}
|
|
2434
3260
|
/**
|
|
2435
3261
|
* Compute the missing facts in a fixed order: the contract first, because everything else is
|
|
@@ -2474,17 +3300,25 @@ declare function renderPlan(document: PlanDocument): string;
|
|
|
2474
3300
|
interface SuppliedFactsResult {
|
|
2475
3301
|
readonly ok: boolean;
|
|
2476
3302
|
readonly capabilities: readonly Capability[] | null;
|
|
3303
|
+
/** True when `--capabilities all` expanded to every plannable capability, so the plan can say so. */
|
|
3304
|
+
readonly allCapabilities: boolean;
|
|
2477
3305
|
readonly identityMode: IdentityMode | null;
|
|
2478
3306
|
readonly sessionMintLanguage: SessionMintLanguage | null;
|
|
3307
|
+
readonly embedding: Embedding | null;
|
|
2479
3308
|
readonly errors: readonly string[];
|
|
2480
3309
|
}
|
|
2481
3310
|
/**
|
|
2482
3311
|
* Parse `--capabilities chat,records`. Order is normalised to sorted order and duplicates
|
|
2483
3312
|
* collapse, so two equivalent invocations produce a byte-identical plan document.
|
|
3313
|
+
*
|
|
3314
|
+
* `all` is the one token the contract does not publish: it expands to every capability the loaded space can plan
|
|
3315
|
+
* (a BLOCKED option is left out, since asking for it is asking for a refusal). `all` is reported so the plan can say
|
|
3316
|
+
* what it meant, and that `verify` is the fail-closed check of what the tenant actually has.
|
|
2484
3317
|
*/
|
|
2485
3318
|
declare function parseCapabilities(raw: string | null, space: DecisionSpace | null): {
|
|
2486
3319
|
readonly value: readonly Capability[] | null;
|
|
2487
3320
|
readonly errors: readonly string[];
|
|
3321
|
+
readonly all: boolean;
|
|
2488
3322
|
};
|
|
2489
3323
|
declare function parseIdentityMode(raw: string | null, space: DecisionSpace | null): {
|
|
2490
3324
|
readonly value: IdentityMode | null;
|
|
@@ -2496,7 +3330,7 @@ declare function parseSessionMintLanguage(raw: string | null, space: DecisionSpa
|
|
|
2496
3330
|
readonly errors: readonly string[];
|
|
2497
3331
|
};
|
|
2498
3332
|
/** Parse every supplied fact, accumulating all errors rather than stopping at the first. */
|
|
2499
|
-
declare function parseSuppliedFacts(capabilitiesRaw: string | null, identityRaw: string | null, backendRaw: string | null, space: DecisionSpace | null): SuppliedFactsResult;
|
|
3333
|
+
declare function parseSuppliedFacts(capabilitiesRaw: string | null, identityRaw: string | null, backendRaw: string | null, space: DecisionSpace | null, embeddingRaw?: string | null): SuppliedFactsResult;
|
|
2500
3334
|
|
|
2501
3335
|
/**
|
|
2502
3336
|
* The CLI version, stamped into every emitted document under `generatedBy.version`.
|
|
@@ -2506,6 +3340,6 @@ declare function parseSuppliedFacts(capabilitiesRaw: string | null, identityRaw:
|
|
|
2506
3340
|
* install, and a bundled artifact. `tests/unit/version.test.ts` asserts this constant equals
|
|
2507
3341
|
* the package.json version, so the two cannot drift.
|
|
2508
3342
|
*/
|
|
2509
|
-
declare const CLI_VERSION = "0.
|
|
3343
|
+
declare const CLI_VERSION = "0.2.0";
|
|
2510
3344
|
|
|
2511
|
-
export { ADMIN_TOKEN, API_PREFIX, type ApiClient, type ApiFailure, type ApiResult, type ApiSuccess, BASE_URL_ENV_VAR, type BlockedCapability, type BlockedOutcome, CLI_VERSION, COMMANDS, CREDENTIAL_SPECS, type Capability, type CapabilityDiagnosis, type ClockPort, type Command, type CommandContext, type CommandOutcome, type ContractValidationOutcome, type Credential, type CredentialSpec, DEFAULT_TIMEOUT_MS, type DecisionSpace, type DecisionSpaceProvenance, type DecisionTree, type DetectedDependency, type Diagnosis, EMPTY_REGISTRY, ERRORS_DOCUMENT_KEY, type ErrorRegistry, type ErrorRegistryEntry, ExitCode, type FileSystemPort, type FormatOptions, type FormattedOutput, type HttpMethod, type HttpRequest, type HttpResponse, IDEMPOTENT_METHODS, type IdentityMode, MISSING_FACT_NAMES, type MissingFact, type MissingFactName, type Outcome, PARTNER_KEY, PARTNER_SECRET_KEY, PLAN_DOCUMENT_KIND, PLAN_SCHEMA_VERSION, type PackageManager, type PlanDocument, type PlanInput, type PlanPrinciple, type PlanStep, type PlanWarning, type PositionalSpec, type ProjectDetection, type ProjectType, REASON_CODES, REDACTED, type ReasonCode, type RegistryLoad, type RequestSpec, type ResolvedCredential, type ResolvedEndpoint, type RunOptions, SCHEMAS, SESSION_TOKEN, type SandboxCreateStatus, type SandboxCreation, type SchemaValidation, type SchemaViolation, type SessionMintLanguage, type StepResult, type TerminalOutcome, TransportError, type TransportPort, type TreeOption, type TreeQuestion, type Verification, type VerifyStep, type WalkResult, apiUrl, buildDecisionSpace, buildDiagnosisDocument, buildExplanationDocument, buildSandboxDocument, buildVerificationDocument, clampTimeout, createApiClient, createMemoryFileSystem, createRecordingClock, describeFailure, detectProject, digestOfProjection, digestsEqual, editDistance, entryFromRow, ephemeralCredential, errorCodeOf, failureDetails, failureOutcome, fetchTransport, formatOutcome, isCorrelatableRequestId, isIdempotent, isKnownReasonCode, loadDecisionSpace, loadErrorRegistry, matchCommand, missingFactsFor, nextActionFor as nextActionForErrorCode, nextActionFor$1 as nextActionForReason, nextActionsFor, nodeFileSystem, parseCapabilities, parseDiagnostics, parseIdentityMode, parseSessionMintLanguage, parseSuppliedFacts, planIntegration, projectSandboxCreate, renderDiagnosis, renderExplanation, renderPlan, renderSandboxCreate, renderVerification, resolveContractPath, resolveCredential, resolveEndpoint, runCli, runVerification, suggestCodes, systemClock, validateContractFile, validateContractPublicEnvelope, validateDiagnosisDocument, validateErrorExplanationDocument, validatePlanDocument, validateSandboxCreateDocument, validateVerificationDocument, verifyDigest, walkSingle, walkTree, withPrefix };
|
|
3345
|
+
export { ADMIN_TOKEN, API_PREFIX, type ApiClient, type ApiFailure, type ApiResult, type ApiSuccess, BASE_URL_ENV_VAR, type BlockedCapability, type BlockedOutcome, CLI_VERSION, COMMANDS, CREDENTIAL_SPECS, type Capability, type CapabilityDiagnosis, type ClockPort, type Command, type CommandContext, type CommandOutcome, type ContractValidationOutcome, type Credential, type CredentialSpec, DEFAULT_TIMEOUT_MS, type DecisionSpace, type DecisionSpaceProvenance, type DecisionTree, type DetectedDependency, type DetectedTheme, type Diagnosis, EMPTY_REGISTRY, ERRORS_DOCUMENT_KEY, type ErrorRegistry, type ErrorRegistryEntry, ExitCode, type FileSystemPort, type FormatOptions, type FormattedOutput, type HttpMethod, type HttpRequest, type HttpResponse, IDEMPOTENT_METHODS, type IdentityMode, MISSING_FACT_NAMES, type MissingFact, type MissingFactName, type Outcome, PARTNER_KEY, PARTNER_SECRET_KEY, PLAN_DOCUMENT_KIND, PLAN_SCHEMA_VERSION, type PackageManager, type PlanDocument, type PlanInput, type PlanPrinciple, type PlanStep, type PlanWarning, type PositionalSpec, type ProjectDetection, type ProjectType, REASON_CODES, REDACTED, type ReasonCode, type RegistryLoad, type RequestSpec, type ResolvedCredential, type ResolvedEndpoint, type RunOptions, SCHEMAS, SESSION_TOKEN, type SandboxCreateStatus, type SandboxCreation, type SchemaValidation, type SchemaViolation, type SessionMintLanguage, type StepResult, THEME_TOKEN_ORDER, type TerminalOutcome, type ThemeConfidence, type ThemeDetection, type ThemeEvidence, type ThemeSource, type ThemeToken, TransportError, type TransportPort, type TreeOption, type TreeQuestion, type Verification, type VerifyStep, type WalkResult, apiUrl, buildDecisionSpace, buildDiagnosisDocument, buildExplanationDocument, buildSandboxDocument, buildVerificationDocument, clampTimeout, createApiClient, createMemoryFileSystem, createRecordingClock, describeFailure, detectProject, detectTheme, detectThemeFromText, digestOfProjection, digestsEqual, editDistance, entryFromRow, ephemeralCredential, errorCodeOf, failureDetails, failureOutcome, fetchTransport, formatOutcome, isCorrelatableRequestId, isIdempotent, isKnownReasonCode, loadDecisionSpace, loadErrorRegistry, matchCommand, missingFactsFor, nextActionFor as nextActionForErrorCode, nextActionFor$1 as nextActionForReason, nextActionsFor, nodeFileSystem, parseCapabilities, parseDiagnostics, parseIdentityMode, parseSessionMintLanguage, parseSuppliedFacts, planIntegration, projectSandboxCreate, renderDiagnosis, renderExplanation, renderPlan, renderSandboxCreate, renderVerification, resolveContractPath, resolveCredential, resolveEndpoint, runCli, runVerification, suggestCodes, systemClock, validateContractFile, validateContractPublicEnvelope, validateDiagnosisDocument, validateErrorExplanationDocument, validatePlanDocument, validateSandboxCreateDocument, validateVerificationDocument, verifyDigest, walkSingle, walkTree, withPrefix };
|