@kya-os/create-mcpi-app 1.7.26 → 1.7.28
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/.turbo/turbo-test$colon$coverage.log +1080 -175
- package/dist/.tsbuildinfo +1 -1
- package/dist/helpers/fetch-cloudflare-mcpi-template.d.ts.map +1 -1
- package/dist/helpers/fetch-cloudflare-mcpi-template.js +27 -16
- package/dist/helpers/fetch-cloudflare-mcpi-template.js.map +1 -1
- package/package.json +1 -1
- package/src/helpers/fetch-cloudflare-mcpi-template.ts +27 -16
- package/coverage/base.css +0 -224
- package/coverage/block-navigation.js +0 -87
- package/coverage/clover.xml +0 -252
- package/coverage/config-builder.ts.html +0 -580
- package/coverage/coverage-final.json +0 -7
- package/coverage/favicon.png +0 -0
- package/coverage/fetch-cloudflare-mcpi-template.ts.html +0 -7006
- package/coverage/generate-config.ts.html +0 -436
- package/coverage/generate-identity.ts.html +0 -574
- package/coverage/index.html +0 -191
- package/coverage/install.ts.html +0 -322
- package/coverage/prettify.css +0 -1
- package/coverage/prettify.js +0 -2
- package/coverage/sort-arrow-sprite.png +0 -0
- package/coverage/sorter.js +0 -210
- package/coverage/validate-project-structure.ts.html +0 -466
|
@@ -1,81 +1,97 @@
|
|
|
1
1
|
|
|
2
2
|
|
|
3
|
-
> @kya-os/create-mcpi-app@1.7.
|
|
3
|
+
> @kya-os/create-mcpi-app@1.7.26 test:coverage /Users/dylanhobbs/Documents/@kya-os/xmcp-i/packages/create-mcpi-app
|
|
4
4
|
> vitest --run --coverage
|
|
5
5
|
|
|
6
|
-
[?25l
|
|
6
|
+
[?25l[33m▲ [43;33m[[43;30mWARNING[43;33m][0m [1mThe condition "types" here will never be used as it comes after both "import" and "require"[0m [package.json]
|
|
7
|
+
|
|
8
|
+
package.json:15:6:
|
|
9
|
+
[37m 15 │ [32m"types"[37m: "./dist/index.d.ts"
|
|
10
|
+
╵ [32m~~~~~~~[0m
|
|
11
|
+
|
|
12
|
+
The "import" condition comes earlier and will be used for all "import" statements:
|
|
13
|
+
|
|
14
|
+
package.json:13:6:
|
|
15
|
+
[37m 13 │ [32m"import"[37m: "./dist/index.js",
|
|
16
|
+
╵ [32m~~~~~~~~[0m
|
|
17
|
+
|
|
18
|
+
The "require" condition comes earlier and will be used for all "require" calls:
|
|
19
|
+
|
|
20
|
+
package.json:14:6:
|
|
21
|
+
[37m 14 │ [32m"require"[37m: "./dist/index.js",
|
|
22
|
+
╵ [32m~~~~~~~~~[0m
|
|
23
|
+
|
|
24
|
+
[33m▲ [43;33m[[43;30mWARNING[43;33m][0m [1mThe condition "types" here will never be used as it comes after both "import" and "require"[0m [package.json]
|
|
25
|
+
|
|
26
|
+
package.json:20:6:
|
|
27
|
+
[37m 20 │ [32m"types"[37m: "./dist/helpers/config-builder.d.ts"
|
|
28
|
+
╵ [32m~~~~~~~[0m
|
|
29
|
+
|
|
30
|
+
The "import" condition comes earlier and will be used for all "import" statements:
|
|
31
|
+
|
|
32
|
+
package.json:18:6:
|
|
33
|
+
[37m 18 │ [32m"import"[37m: "./dist/helpers/config-builder.js",
|
|
34
|
+
╵ [32m~~~~~~~~[0m
|
|
35
|
+
|
|
36
|
+
The "require" condition comes earlier and will be used for all "require" calls:
|
|
37
|
+
|
|
38
|
+
package.json:19:6:
|
|
39
|
+
[37m 19 │ [32m"require"[37m: "./dist/helpers/config-builder.js",
|
|
40
|
+
╵ [32m~~~~~~~~~[0m
|
|
41
|
+
|
|
42
|
+
|
|
7
43
|
[1m[46m RUN [49m[22m [36mv4.0.5 [39m[90m/Users/dylanhobbs/Documents/@kya-os/xmcp-i/packages/create-mcpi-app[39m
|
|
8
44
|
[2mCoverage enabled with [22m[33mv8[39m
|
|
9
45
|
|
|
10
46
|
[?2026h
|
|
11
|
-
[1m[33m ❯ [39m[22msrc/__tests__/helpers/
|
|
47
|
+
[1m[33m ❯ [39m[22msrc/__tests__/helpers/fetch-cloudflare-mcpi-template.test.ts[2m [queued][22m
|
|
12
48
|
|
|
13
49
|
[2m Test Files [22m[1m[32m0 passed[39m[22m[90m (12)[39m
|
|
14
50
|
[2m Tests [22m[1m[32m0 passed[39m[22m[90m (0)[39m
|
|
15
|
-
[2m Start at [
|
|
16
|
-
[2m Duration [
|
|
51
|
+
[2m Start at [22m14:20:47
|
|
52
|
+
[2m Duration [22m201ms
|
|
17
53
|
[?2026l[?2026h[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K
|
|
54
|
+
[1m[33m ❯ [39m[22msrc/__tests__/helpers/fetch-cloudflare-mcpi-template.test.ts[2m [queued][22m
|
|
18
55
|
[1m[33m ❯ [39m[22msrc/__tests__/helpers/generate-identity.test.ts[2m [queued][22m
|
|
19
|
-
[1m[33m ❯ [39m[
|
|
20
|
-
[1m[33m ❯ [39m[22mtest-cloudflare/tests/cache-invalidation.test.ts[2m [queued][22m
|
|
21
|
-
[1m[33m ❯ [39m[22mtest-cloudflare/tests/cors-security.test.ts[2m [queued][22m
|
|
22
|
-
[1m[33m ❯ [39m[22mtest-cloudflare/tests/session-management.test.ts[2m [queued][22m
|
|
56
|
+
[1m[33m ❯ [39m[22mtest-cloudflare/tests/delegation.test.ts[2m 0/12[22m
|
|
23
57
|
|
|
24
58
|
[2m Test Files [22m[1m[32m0 passed[39m[22m[90m (12)[39m
|
|
25
|
-
[2m Tests [22m[1m[32m0 passed[39m[22m[90m (
|
|
26
|
-
[2m Start at [
|
|
27
|
-
[2m Duration [
|
|
28
|
-
[?2026l[?2026h[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K
|
|
59
|
+
[2m Tests [22m[1m[32m0 passed[39m[22m[90m (12)[39m
|
|
60
|
+
[2m Start at [22m14:20:47
|
|
61
|
+
[2m Duration [22m509ms
|
|
62
|
+
[?2026l[?2026h[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K
|
|
63
|
+
[1m[33m ❯ [39m[22msrc/__tests__/helpers/fetch-cloudflare-mcpi-template.test.ts[2m [queued][22m
|
|
29
64
|
[1m[33m ❯ [39m[22msrc/__tests__/helpers/generate-identity.test.ts[2m [queued][22m
|
|
30
|
-
[1m[33m ❯ [39m[
|
|
31
|
-
[1m[33m ❯ [39m[22mtest-cloudflare/tests/
|
|
32
|
-
[1m[33m ❯ [39m[22mtest-cloudflare/tests/cors-security.test.ts[2m 1/29[22m
|
|
33
|
-
[1m[33m ❯ [39m[22mtest-cloudflare/tests/delegation.test.ts[2m [queued][22m
|
|
34
|
-
[1m[33m ❯ [39m[22mtest-cloudflare/tests/do-routing.test.ts[2m [queued][22m
|
|
35
|
-
[1m[33m ❯ [39m[22mtest-cloudflare/tests/session-management.test.ts[2m 0/17[22m
|
|
65
|
+
[1m[33m ❯ [39m[22mtest-cloudflare/tests/cors-security.test.ts[2m [queued][22m
|
|
66
|
+
[1m[33m ❯ [39m[22mtest-cloudflare/tests/delegation.test.ts[2m 0/12[22m
|
|
36
67
|
|
|
37
68
|
[2m Test Files [22m[1m[32m0 passed[39m[22m[90m (12)[39m
|
|
38
|
-
[2m Tests [22m[1m[
|
|
39
|
-
[2m Start at [
|
|
40
|
-
[2m Duration [
|
|
41
|
-
[?2026l[?2026h[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K
|
|
42
|
-
[
|
|
43
|
-
[22m[
|
|
44
|
-
|
|
45
|
-
[32m✓[39m test-cloudflare/tests/session-management.test.ts [2m([22m[2m17 tests[22m[2m)[22m[32m 57[2mms[22m[39m
|
|
46
|
-
[32m✓[39m test-cloudflare/tests/delegation.test.ts [2m([22m[2m12 tests[22m[2m)[22m[32m 5[2mms[22m[39m
|
|
47
|
-
[32m✓[39m test-cloudflare/tests/cache-invalidation.test.ts [2m([22m[2m18 tests[22m[2m)[22m[32m 11[2mms[22m[39m
|
|
69
|
+
[2m Tests [22m[1m[32m0 passed[39m[22m[90m (12)[39m
|
|
70
|
+
[2m Start at [22m14:20:47
|
|
71
|
+
[2m Duration [22m637ms
|
|
72
|
+
[?2026l[?2026h[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K [32m✓[39m test-cloudflare/tests/delegation.test.ts [2m([22m[2m12 tests[22m[2m)[22m[32m 8[2mms[22m[39m
|
|
73
|
+
[32m✓[39m test-cloudflare/tests/cors-security.test.ts [2m([22m[2m29 tests[22m[2m)[22m[32m 5[2mms[22m[39m
|
|
74
|
+
[32m✓[39m src/__tests__/helpers/generate-identity.test.ts [2m([22m[2m24 tests[22m[2m)[22m[32m 34[2mms[22m[39m
|
|
48
75
|
|
|
49
76
|
[1m[33m ❯ [39m[22msrc/__tests__/cloudflare-template.test.ts[2m [queued][22m
|
|
50
|
-
[1m[33m ❯ [39m[22msrc/__tests__/helpers/fetch-cloudflare-mcpi-template.test.ts[2m
|
|
77
|
+
[1m[33m ❯ [39m[22msrc/__tests__/helpers/fetch-cloudflare-mcpi-template.test.ts[2m 0/19[22m
|
|
51
78
|
[1m[33m ❯ [39m[22msrc/__tests__/helpers/generate-config.test.ts[2m [queued][22m
|
|
52
|
-
[1m[33m ❯ [39m[22msrc/__tests__/helpers/generate-identity.test.ts[2m 0/24[22m
|
|
53
79
|
[1m[33m ❯ [39m[22msrc/__tests__/helpers/install.test.ts[2m [queued][22m
|
|
54
80
|
[1m[33m ❯ [39m[22msrc/__tests__/helpers/validate-project-structure.test.ts[2m [queued][22m
|
|
55
81
|
[1m[33m ❯ [39m[22msrc/helpers/__tests__/config-builder.spec.ts[2m [queued][22m
|
|
82
|
+
[1m[33m ❯ [39m[22mtest-cloudflare/tests/cache-invalidation.test.ts[2m 1/18[22m
|
|
56
83
|
[1m[33m ❯ [39m[22mtest-cloudflare/tests/do-routing.test.ts[2m 0/14[22m
|
|
84
|
+
[1m[33m ❯ [39m[22mtest-cloudflare/tests/session-management.test.ts[2m 0/17[22m
|
|
57
85
|
|
|
58
|
-
[2m Test Files [22m[1m[
|
|
59
|
-
[2m Tests [22m[1m[
|
|
60
|
-
[2m Start at [
|
|
61
|
-
[2m Duration [
|
|
62
|
-
[?2026l[?2026h[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[
|
|
63
|
-
[22m[
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
[1m[33m ❯ [39m[22msrc/__tests__/cloudflare-template.test.ts[2m 0/24[22m
|
|
67
|
-
[1m[33m ❯ [39m[22msrc/__tests__/helpers/fetch-cloudflare-mcpi-template.test.ts[2m 0/19[22m
|
|
68
|
-
[1m[33m ❯ [39m[22msrc/__tests__/helpers/generate-config.test.ts[2m 0/25[22m
|
|
69
|
-
[1m[33m ❯ [39m[22msrc/__tests__/helpers/install.test.ts[2m 1/20[22m
|
|
70
|
-
[1m[33m ❯ [39m[22msrc/__tests__/helpers/validate-project-structure.test.ts[2m 0/23[22m
|
|
71
|
-
[1m[33m ❯ [39m[22mtest-cloudflare/tests/do-routing.test.ts[2m 1/14[22m
|
|
86
|
+
[2m Test Files [22m[1m[32m3 passed[39m[22m[90m (12)[39m
|
|
87
|
+
[2m Tests [22m[1m[32m66 passed[39m[22m[90m (133)[39m
|
|
88
|
+
[2m Start at [22m14:20:47
|
|
89
|
+
[2m Duration [22m739ms
|
|
90
|
+
[?2026l[?2026h[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K [32m✓[39m test-cloudflare/tests/cache-invalidation.test.ts [2m([22m[2m18 tests[22m[2m)[22m[32m 6[2mms[22m[39m
|
|
91
|
+
[90mstdout[2m | test-cloudflare/tests/session-management.test.ts[2m > [22m[2mSession Management[2m > [22m[2mSession Security[2m > [22m[2mshould not expose session data in logs
|
|
92
|
+
[22m[39m[Session] Created session: secure-session
|
|
72
93
|
|
|
73
|
-
[
|
|
74
|
-
[2m Tests [22m[1m[32m114 passed[39m[22m[90m (237)[39m
|
|
75
|
-
[2m Start at [22m11:56:38
|
|
76
|
-
[2m Duration [22m645ms
|
|
77
|
-
[?2026l[?2026h[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K [32m✓[39m src/__tests__/helpers/generate-identity.test.ts [2m([22m[2m24 tests[22m[2m)[22m[32m 44[2mms[22m[39m
|
|
78
|
-
[32m✓[39m src/helpers/__tests__/config-builder.spec.ts [2m([22m[2m12 tests[22m[2m)[22m[32m 6[2mms[22m[39m
|
|
94
|
+
[32m✓[39m test-cloudflare/tests/session-management.test.ts [2m([22m[2m17 tests[22m[2m)[22m[32m 54[2mms[22m[39m
|
|
79
95
|
[90mstdout[2m | src/__tests__/helpers/install.test.ts[2m > [22m[2minstall[2m > [22m[2mDependency installation[2m > [22m[2mshould install dependencies with npm
|
|
80
96
|
[22m[39m
|
|
81
97
|
📦 Installing dependencies with npm...
|
|
@@ -98,32 +114,34 @@
|
|
|
98
114
|
|
|
99
115
|
|
|
100
116
|
[1m[33m ❯ [39m[22msrc/__tests__/cloudflare-template.test.ts[2m 0/24[22m
|
|
101
|
-
[1m[33m ❯ [39m[22msrc/__tests__/helpers/fetch-cloudflare-mcpi-template.test.ts[2m
|
|
117
|
+
[1m[33m ❯ [39m[22msrc/__tests__/helpers/fetch-cloudflare-mcpi-template.test.ts[2m 4/19[22m
|
|
102
118
|
[1m[33m ❯ [39m[22msrc/__tests__/helpers/generate-config.test.ts[2m 0/25[22m
|
|
103
|
-
[1m[33m ❯ [39m[22msrc/__tests__/helpers/install.test.ts[2m
|
|
119
|
+
[1m[33m ❯ [39m[22msrc/__tests__/helpers/install.test.ts[2m 0/20[22m
|
|
104
120
|
[1m[33m ❯ [39m[22msrc/__tests__/helpers/validate-project-structure.test.ts[2m 0/23[22m
|
|
121
|
+
[1m[33m ❯ [39m[22msrc/helpers/__tests__/config-builder.spec.ts[2m [queued][22m
|
|
105
122
|
[1m[33m ❯ [39m[22mtest-cloudflare/tests/do-routing.test.ts[2m 1/14[22m
|
|
106
123
|
|
|
107
|
-
[2m Test Files [22m[1m[
|
|
108
|
-
[2m Tests [22m[1m[
|
|
109
|
-
[2m Start at [
|
|
110
|
-
[2m Duration [
|
|
111
|
-
[?2026l[?2026h[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[90mstderr[2m | src/__tests__/helpers/install.test.ts[2m > [22m[2minstall[2m > [22m[2mInstall progress reporting[2m > [22m[2mshould report correct package manager in log
|
|
124
|
+
[2m Test Files [22m[1m[32m5 passed[39m[22m[90m (12)[39m
|
|
125
|
+
[2m Tests [22m[1m[32m105 passed[39m[22m[90m (225)[39m
|
|
126
|
+
[2m Start at [22m14:20:47
|
|
127
|
+
[2m Duration [22m840ms
|
|
128
|
+
[?2026l[?2026h[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[90mstderr[2m | src/__tests__/helpers/install.test.ts[2m > [22m[2minstall[2m > [22m[2mInstall progress reporting[2m > [22m[2mshould report correct package manager in log
|
|
112
129
|
[22m[39m⚠️ Warning: No lockfile generated (pnpm-lock.yaml)
|
|
113
130
|
|
|
114
131
|
|
|
115
132
|
[1m[33m ❯ [39m[22msrc/__tests__/cloudflare-template.test.ts[2m 0/24[22m
|
|
116
|
-
[1m[33m ❯ [39m[22msrc/__tests__/helpers/fetch-cloudflare-mcpi-template.test.ts[2m
|
|
133
|
+
[1m[33m ❯ [39m[22msrc/__tests__/helpers/fetch-cloudflare-mcpi-template.test.ts[2m 4/19[22m
|
|
117
134
|
[1m[33m ❯ [39m[22msrc/__tests__/helpers/generate-config.test.ts[2m 0/25[22m
|
|
118
|
-
[1m[33m ❯ [39m[22msrc/__tests__/helpers/install.test.ts[2m
|
|
135
|
+
[1m[33m ❯ [39m[22msrc/__tests__/helpers/install.test.ts[2m 0/20[22m
|
|
119
136
|
[1m[33m ❯ [39m[22msrc/__tests__/helpers/validate-project-structure.test.ts[2m 0/23[22m
|
|
137
|
+
[1m[33m ❯ [39m[22msrc/helpers/__tests__/config-builder.spec.ts[2m [queued][22m
|
|
120
138
|
[1m[33m ❯ [39m[22mtest-cloudflare/tests/do-routing.test.ts[2m 1/14[22m
|
|
121
139
|
|
|
122
|
-
[2m Test Files [22m[1m[
|
|
123
|
-
[2m Tests [22m[1m[
|
|
124
|
-
[2m Start at [
|
|
125
|
-
[2m Duration [
|
|
126
|
-
[?2026l[?2026h[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[90mstdout[2m | src/__tests__/helpers/install.test.ts[2m > [22m[2minstall[2m > [22m[2mInstall progress reporting[2m > [22m[2mshould check for lockfile after installation
|
|
140
|
+
[2m Test Files [22m[1m[32m5 passed[39m[22m[90m (12)[39m
|
|
141
|
+
[2m Tests [22m[1m[32m105 passed[39m[22m[90m (225)[39m
|
|
142
|
+
[2m Start at [22m14:20:47
|
|
143
|
+
[2m Duration [22m840ms
|
|
144
|
+
[?2026l[?2026h[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[90mstdout[2m | src/__tests__/helpers/install.test.ts[2m > [22m[2minstall[2m > [22m[2mInstall progress reporting[2m > [22m[2mshould check for lockfile after installation
|
|
127
145
|
[22m[39m
|
|
128
146
|
📦 Installing dependencies with npm...
|
|
129
147
|
✓ Lockfile created (package-lock.json) - remember to commit it
|
|
@@ -134,182 +152,1069 @@
|
|
|
134
152
|
|
|
135
153
|
|
|
136
154
|
[1m[33m ❯ [39m[22msrc/__tests__/cloudflare-template.test.ts[2m 0/24[22m
|
|
137
|
-
[1m[33m ❯ [39m[22msrc/__tests__/helpers/fetch-cloudflare-mcpi-template.test.ts[2m
|
|
155
|
+
[1m[33m ❯ [39m[22msrc/__tests__/helpers/fetch-cloudflare-mcpi-template.test.ts[2m 4/19[22m
|
|
138
156
|
[1m[33m ❯ [39m[22msrc/__tests__/helpers/generate-config.test.ts[2m 0/25[22m
|
|
139
|
-
[1m[33m ❯ [39m[22msrc/__tests__/helpers/install.test.ts[2m
|
|
157
|
+
[1m[33m ❯ [39m[22msrc/__tests__/helpers/install.test.ts[2m 0/20[22m
|
|
140
158
|
[1m[33m ❯ [39m[22msrc/__tests__/helpers/validate-project-structure.test.ts[2m 0/23[22m
|
|
159
|
+
[1m[33m ❯ [39m[22msrc/helpers/__tests__/config-builder.spec.ts[2m [queued][22m
|
|
141
160
|
[1m[33m ❯ [39m[22mtest-cloudflare/tests/do-routing.test.ts[2m 1/14[22m
|
|
142
161
|
|
|
143
|
-
[2m Test Files [22m[1m[
|
|
144
|
-
[2m Tests [22m[1m[
|
|
145
|
-
[2m Start at [
|
|
146
|
-
[2m Duration [
|
|
147
|
-
[?2026l[?2026h[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[90mstderr[2m | src/__tests__/helpers/install.test.ts[2m > [22m[2minstall[2m > [22m[2mError handling[2m > [22m[2mshould throw error when installation fails
|
|
162
|
+
[2m Test Files [22m[1m[32m5 passed[39m[22m[90m (12)[39m
|
|
163
|
+
[2m Tests [22m[1m[32m105 passed[39m[22m[90m (225)[39m
|
|
164
|
+
[2m Start at [22m14:20:47
|
|
165
|
+
[2m Duration [22m840ms
|
|
166
|
+
[?2026l[?2026h[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[90mstderr[2m | src/__tests__/helpers/install.test.ts[2m > [22m[2minstall[2m > [22m[2mError handling[2m > [22m[2mshould throw error when installation fails
|
|
148
167
|
[22m[39mFailed to install dependencies with npm.
|
|
149
168
|
|
|
150
169
|
|
|
151
170
|
[1m[33m ❯ [39m[22msrc/__tests__/cloudflare-template.test.ts[2m 0/24[22m
|
|
152
|
-
[1m[33m ❯ [39m[22msrc/__tests__/helpers/fetch-cloudflare-mcpi-template.test.ts[2m
|
|
171
|
+
[1m[33m ❯ [39m[22msrc/__tests__/helpers/fetch-cloudflare-mcpi-template.test.ts[2m 4/19[22m
|
|
153
172
|
[1m[33m ❯ [39m[22msrc/__tests__/helpers/generate-config.test.ts[2m 0/25[22m
|
|
154
|
-
[1m[33m ❯ [39m[22msrc/__tests__/helpers/install.test.ts[2m
|
|
173
|
+
[1m[33m ❯ [39m[22msrc/__tests__/helpers/install.test.ts[2m 0/20[22m
|
|
155
174
|
[1m[33m ❯ [39m[22msrc/__tests__/helpers/validate-project-structure.test.ts[2m 0/23[22m
|
|
175
|
+
[1m[33m ❯ [39m[22msrc/helpers/__tests__/config-builder.spec.ts[2m [queued][22m
|
|
156
176
|
[1m[33m ❯ [39m[22mtest-cloudflare/tests/do-routing.test.ts[2m 1/14[22m
|
|
157
177
|
|
|
158
|
-
[2m Test Files [22m[1m[
|
|
159
|
-
[2m Tests [22m[1m[
|
|
160
|
-
[2m Start at [
|
|
161
|
-
[2m Duration [
|
|
162
|
-
[?2026l[?2026h[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[90mstdout[2m | src/__tests__/helpers/install.test.ts[2m > [22m[2minstall[2m > [22m[2mError handling[2m > [22m[2mshould handle network errors during installation
|
|
178
|
+
[2m Test Files [22m[1m[32m5 passed[39m[22m[90m (12)[39m
|
|
179
|
+
[2m Tests [22m[1m[32m105 passed[39m[22m[90m (225)[39m
|
|
180
|
+
[2m Start at [22m14:20:47
|
|
181
|
+
[2m Duration [22m840ms
|
|
182
|
+
[?2026l[?2026h[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[90mstdout[2m | src/__tests__/helpers/install.test.ts[2m > [22m[2minstall[2m > [22m[2mError handling[2m > [22m[2mshould handle network errors during installation
|
|
163
183
|
[22m[39m
|
|
164
184
|
📦 Installing dependencies with npm...
|
|
165
185
|
|
|
166
186
|
|
|
167
187
|
[1m[33m ❯ [39m[22msrc/__tests__/cloudflare-template.test.ts[2m 0/24[22m
|
|
168
|
-
[1m[33m ❯ [39m[22msrc/__tests__/helpers/fetch-cloudflare-mcpi-template.test.ts[2m
|
|
188
|
+
[1m[33m ❯ [39m[22msrc/__tests__/helpers/fetch-cloudflare-mcpi-template.test.ts[2m 4/19[22m
|
|
169
189
|
[1m[33m ❯ [39m[22msrc/__tests__/helpers/generate-config.test.ts[2m 0/25[22m
|
|
170
|
-
[1m[33m ❯ [39m[22msrc/__tests__/helpers/install.test.ts[2m
|
|
190
|
+
[1m[33m ❯ [39m[22msrc/__tests__/helpers/install.test.ts[2m 0/20[22m
|
|
171
191
|
[1m[33m ❯ [39m[22msrc/__tests__/helpers/validate-project-structure.test.ts[2m 0/23[22m
|
|
192
|
+
[1m[33m ❯ [39m[22msrc/helpers/__tests__/config-builder.spec.ts[2m [queued][22m
|
|
172
193
|
[1m[33m ❯ [39m[22mtest-cloudflare/tests/do-routing.test.ts[2m 1/14[22m
|
|
173
194
|
|
|
174
|
-
[2m Test Files [22m[1m[
|
|
175
|
-
[2m Tests [22m[1m[
|
|
176
|
-
[2m Start at [
|
|
177
|
-
[2m Duration [
|
|
178
|
-
[?2026l[?2026h[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[90mstderr[2m | src/__tests__/helpers/install.test.ts[2m > [22m[2minstall[2m > [22m[2mError handling[2m > [22m[2mshould handle network errors during installation
|
|
195
|
+
[2m Test Files [22m[1m[32m5 passed[39m[22m[90m (12)[39m
|
|
196
|
+
[2m Tests [22m[1m[32m105 passed[39m[22m[90m (225)[39m
|
|
197
|
+
[2m Start at [22m14:20:47
|
|
198
|
+
[2m Duration [22m840ms
|
|
199
|
+
[?2026l[?2026h[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[90mstderr[2m | src/__tests__/helpers/install.test.ts[2m > [22m[2minstall[2m > [22m[2mError handling[2m > [22m[2mshould handle network errors during installation
|
|
179
200
|
[22m[39mFailed to install dependencies with npm.
|
|
180
201
|
|
|
181
202
|
|
|
182
203
|
[1m[33m ❯ [39m[22msrc/__tests__/cloudflare-template.test.ts[2m 0/24[22m
|
|
183
|
-
[1m[33m ❯ [39m[22msrc/__tests__/helpers/fetch-cloudflare-mcpi-template.test.ts[2m
|
|
204
|
+
[1m[33m ❯ [39m[22msrc/__tests__/helpers/fetch-cloudflare-mcpi-template.test.ts[2m 4/19[22m
|
|
184
205
|
[1m[33m ❯ [39m[22msrc/__tests__/helpers/generate-config.test.ts[2m 0/25[22m
|
|
185
|
-
[1m[33m ❯ [39m[22msrc/__tests__/helpers/install.test.ts[2m
|
|
206
|
+
[1m[33m ❯ [39m[22msrc/__tests__/helpers/install.test.ts[2m 0/20[22m
|
|
186
207
|
[1m[33m ❯ [39m[22msrc/__tests__/helpers/validate-project-structure.test.ts[2m 0/23[22m
|
|
208
|
+
[1m[33m ❯ [39m[22msrc/helpers/__tests__/config-builder.spec.ts[2m [queued][22m
|
|
187
209
|
[1m[33m ❯ [39m[22mtest-cloudflare/tests/do-routing.test.ts[2m 1/14[22m
|
|
188
210
|
|
|
189
|
-
[2m Test Files [22m[1m[
|
|
190
|
-
[2m Tests [22m[1m[
|
|
191
|
-
[2m Start at [
|
|
192
|
-
[2m Duration [
|
|
193
|
-
[?2026l[?2026h[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[90mstdout[2m | src/__tests__/helpers/install.test.ts[2m > [22m[2minstall[2m > [22m[2mError handling[2m > [22m[2mshould handle permission errors during installation
|
|
211
|
+
[2m Test Files [22m[1m[32m5 passed[39m[22m[90m (12)[39m
|
|
212
|
+
[2m Tests [22m[1m[32m105 passed[39m[22m[90m (225)[39m
|
|
213
|
+
[2m Start at [22m14:20:47
|
|
214
|
+
[2m Duration [22m840ms
|
|
215
|
+
[?2026l[?2026h[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[90mstdout[2m | src/__tests__/helpers/install.test.ts[2m > [22m[2minstall[2m > [22m[2mError handling[2m > [22m[2mshould handle permission errors during installation
|
|
194
216
|
[22m[39m
|
|
195
217
|
📦 Installing dependencies with npm...
|
|
196
218
|
|
|
197
219
|
|
|
198
220
|
[1m[33m ❯ [39m[22msrc/__tests__/cloudflare-template.test.ts[2m 0/24[22m
|
|
199
|
-
[1m[33m ❯ [39m[22msrc/__tests__/helpers/fetch-cloudflare-mcpi-template.test.ts[2m
|
|
221
|
+
[1m[33m ❯ [39m[22msrc/__tests__/helpers/fetch-cloudflare-mcpi-template.test.ts[2m 4/19[22m
|
|
200
222
|
[1m[33m ❯ [39m[22msrc/__tests__/helpers/generate-config.test.ts[2m 0/25[22m
|
|
201
|
-
[1m[33m ❯ [39m[22msrc/__tests__/helpers/install.test.ts[2m
|
|
223
|
+
[1m[33m ❯ [39m[22msrc/__tests__/helpers/install.test.ts[2m 0/20[22m
|
|
202
224
|
[1m[33m ❯ [39m[22msrc/__tests__/helpers/validate-project-structure.test.ts[2m 0/23[22m
|
|
225
|
+
[1m[33m ❯ [39m[22msrc/helpers/__tests__/config-builder.spec.ts[2m [queued][22m
|
|
203
226
|
[1m[33m ❯ [39m[22mtest-cloudflare/tests/do-routing.test.ts[2m 1/14[22m
|
|
204
227
|
|
|
205
|
-
[2m Test Files [22m[1m[
|
|
206
|
-
[2m Tests [22m[1m[
|
|
207
|
-
[2m Start at [
|
|
208
|
-
[2m Duration [
|
|
209
|
-
[?2026l[?2026h[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[90mstderr[2m | src/__tests__/helpers/install.test.ts[2m > [22m[2minstall[2m > [22m[2mError handling[2m > [22m[2mshould handle permission errors during installation
|
|
228
|
+
[2m Test Files [22m[1m[32m5 passed[39m[22m[90m (12)[39m
|
|
229
|
+
[2m Tests [22m[1m[32m105 passed[39m[22m[90m (225)[39m
|
|
230
|
+
[2m Start at [22m14:20:47
|
|
231
|
+
[2m Duration [22m840ms
|
|
232
|
+
[?2026l[?2026h[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[90mstderr[2m | src/__tests__/helpers/install.test.ts[2m > [22m[2minstall[2m > [22m[2mError handling[2m > [22m[2mshould handle permission errors during installation
|
|
210
233
|
[22m[39mFailed to install dependencies with npm.
|
|
211
234
|
|
|
212
235
|
|
|
213
236
|
[1m[33m ❯ [39m[22msrc/__tests__/cloudflare-template.test.ts[2m 0/24[22m
|
|
214
|
-
[1m[33m ❯ [39m[22msrc/__tests__/helpers/fetch-cloudflare-mcpi-template.test.ts[2m
|
|
237
|
+
[1m[33m ❯ [39m[22msrc/__tests__/helpers/fetch-cloudflare-mcpi-template.test.ts[2m 4/19[22m
|
|
215
238
|
[1m[33m ❯ [39m[22msrc/__tests__/helpers/generate-config.test.ts[2m 0/25[22m
|
|
216
|
-
[1m[33m ❯ [39m[22msrc/__tests__/helpers/install.test.ts[2m
|
|
239
|
+
[1m[33m ❯ [39m[22msrc/__tests__/helpers/install.test.ts[2m 0/20[22m
|
|
217
240
|
[1m[33m ❯ [39m[22msrc/__tests__/helpers/validate-project-structure.test.ts[2m 0/23[22m
|
|
241
|
+
[1m[33m ❯ [39m[22msrc/helpers/__tests__/config-builder.spec.ts[2m [queued][22m
|
|
218
242
|
[1m[33m ❯ [39m[22mtest-cloudflare/tests/do-routing.test.ts[2m 1/14[22m
|
|
219
243
|
|
|
220
|
-
[2m Test Files [22m[1m[
|
|
221
|
-
[2m Tests [22m[1m[
|
|
222
|
-
[2m Start at [
|
|
223
|
-
[2m Duration [
|
|
224
|
-
[?2026l[?2026h[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[90mstdout[2m | src/__tests__/helpers/install.test.ts[2m > [22m[2minstall[2m > [22m[2mError handling[2m > [22m[2mshould log error message when installation fails
|
|
244
|
+
[2m Test Files [22m[1m[32m5 passed[39m[22m[90m (12)[39m
|
|
245
|
+
[2m Tests [22m[1m[32m105 passed[39m[22m[90m (225)[39m
|
|
246
|
+
[2m Start at [22m14:20:47
|
|
247
|
+
[2m Duration [22m840ms
|
|
248
|
+
[?2026l[?2026h[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[90mstdout[2m | src/__tests__/helpers/install.test.ts[2m > [22m[2minstall[2m > [22m[2mError handling[2m > [22m[2mshould log error message when installation fails
|
|
225
249
|
[22m[39m
|
|
226
250
|
📦 Installing dependencies with npm...
|
|
227
251
|
|
|
228
|
-
[90mstdout[2m | src/__tests__/helpers/install.test.ts[2m > [22m[2minstall[2m > [22m[2mError handling[2m > [22m[2mshould handle invalid package manager gracefully
|
|
229
|
-
[22m[39m
|
|
230
|
-
📦 Installing dependencies with unknown...
|
|
231
|
-
|
|
232
252
|
|
|
233
253
|
[1m[33m ❯ [39m[22msrc/__tests__/cloudflare-template.test.ts[2m 0/24[22m
|
|
234
|
-
[1m[33m ❯ [39m[22msrc/__tests__/helpers/fetch-cloudflare-mcpi-template.test.ts[2m
|
|
254
|
+
[1m[33m ❯ [39m[22msrc/__tests__/helpers/fetch-cloudflare-mcpi-template.test.ts[2m 4/19[22m
|
|
235
255
|
[1m[33m ❯ [39m[22msrc/__tests__/helpers/generate-config.test.ts[2m 0/25[22m
|
|
236
|
-
[1m[33m ❯ [39m[22msrc/__tests__/helpers/install.test.ts[2m
|
|
256
|
+
[1m[33m ❯ [39m[22msrc/__tests__/helpers/install.test.ts[2m 0/20[22m
|
|
237
257
|
[1m[33m ❯ [39m[22msrc/__tests__/helpers/validate-project-structure.test.ts[2m 0/23[22m
|
|
258
|
+
[1m[33m ❯ [39m[22msrc/helpers/__tests__/config-builder.spec.ts[2m [queued][22m
|
|
238
259
|
[1m[33m ❯ [39m[22mtest-cloudflare/tests/do-routing.test.ts[2m 1/14[22m
|
|
239
260
|
|
|
261
|
+
[2m Test Files [22m[1m[32m5 passed[39m[22m[90m (12)[39m
|
|
262
|
+
[2m Tests [22m[1m[32m105 passed[39m[22m[90m (225)[39m
|
|
263
|
+
[2m Start at [22m14:20:47
|
|
264
|
+
[2m Duration [22m840ms
|
|
265
|
+
[?2026l[?2026h[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[90mstdout[2m | src/__tests__/helpers/install.test.ts[2m > [22m[2minstall[2m > [22m[2mError handling[2m > [22m[2mshould handle invalid package manager gracefully
|
|
266
|
+
[22m[39m
|
|
267
|
+
📦 Installing dependencies with unknown...
|
|
268
|
+
|
|
269
|
+
|
|
270
|
+
[1m[33m ❯ [39m[22msrc/__tests__/cloudflare-template.test.ts[2m 2/24[22m
|
|
271
|
+
[1m[33m ❯ [39m[22msrc/__tests__/helpers/fetch-cloudflare-mcpi-template.test.ts[2m 4/19[22m
|
|
272
|
+
[1m[33m ❯ [39m[22msrc/__tests__/helpers/generate-config.test.ts[2m 18/25[22m
|
|
273
|
+
[1m[33m ❯ [39m[22msrc/__tests__/helpers/validate-project-structure.test.ts[2m 18/23[22m
|
|
274
|
+
[1m[33m ❯ [39m[22msrc/helpers/__tests__/config-builder.spec.ts[2m [queued][22m
|
|
275
|
+
[1m[33m ❯ [39m[22mtest-cloudflare/tests/do-routing.test.ts[2m 10/14[22m
|
|
276
|
+
|
|
240
277
|
[2m Test Files [22m[1m[32m6 passed[39m[22m[90m (12)[39m
|
|
241
|
-
[2m Tests [22m[1m[
|
|
242
|
-
[2m Start at [
|
|
243
|
-
[2m Duration [
|
|
278
|
+
[2m Tests [22m[1m[32m172 passed[39m[22m[90m (225)[39m
|
|
279
|
+
[2m Start at [22m14:20:47
|
|
280
|
+
[2m Duration [22m1.00s
|
|
244
281
|
[?2026l[?2026h[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[90mstderr[2m | src/__tests__/helpers/install.test.ts[2m > [22m[2minstall[2m > [22m[2mError handling[2m > [22m[2mshould handle invalid package manager gracefully
|
|
245
282
|
[22m[39m⚠️ Warning: Unknown package manager "unknown", cannot check lockfile
|
|
246
283
|
|
|
247
284
|
|
|
248
|
-
[1m[33m ❯ [39m[22msrc/__tests__/cloudflare-template.test.ts[2m
|
|
249
|
-
[1m[33m ❯ [39m[22msrc/__tests__/helpers/fetch-cloudflare-mcpi-template.test.ts[2m
|
|
250
|
-
[1m[33m ❯ [39m[22msrc/__tests__/helpers/generate-config.test.ts[2m
|
|
251
|
-
[1m[33m ❯ [39m[22msrc/__tests__/helpers/
|
|
252
|
-
[1m[33m ❯ [39m[22msrc/__tests__/
|
|
253
|
-
[1m[33m ❯ [39m[22mtest-cloudflare/tests/do-routing.test.ts[2m
|
|
285
|
+
[1m[33m ❯ [39m[22msrc/__tests__/cloudflare-template.test.ts[2m 2/24[22m
|
|
286
|
+
[1m[33m ❯ [39m[22msrc/__tests__/helpers/fetch-cloudflare-mcpi-template.test.ts[2m 4/19[22m
|
|
287
|
+
[1m[33m ❯ [39m[22msrc/__tests__/helpers/generate-config.test.ts[2m 18/25[22m
|
|
288
|
+
[1m[33m ❯ [39m[22msrc/__tests__/helpers/validate-project-structure.test.ts[2m 18/23[22m
|
|
289
|
+
[1m[33m ❯ [39m[22msrc/helpers/__tests__/config-builder.spec.ts[2m [queued][22m
|
|
290
|
+
[1m[33m ❯ [39m[22mtest-cloudflare/tests/do-routing.test.ts[2m 10/14[22m
|
|
254
291
|
|
|
255
292
|
[2m Test Files [22m[1m[32m6 passed[39m[22m[90m (12)[39m
|
|
256
|
-
[2m Tests [22m[1m[
|
|
257
|
-
[2m Start at [
|
|
258
|
-
[2m Duration [
|
|
293
|
+
[2m Tests [22m[1m[32m172 passed[39m[22m[90m (225)[39m
|
|
294
|
+
[2m Start at [22m14:20:47
|
|
295
|
+
[2m Duration [22m1.00s
|
|
259
296
|
[?2026l[?2026h[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[90mstdout[2m | src/__tests__/helpers/install.test.ts[2m > [22m[2minstall[2m > [22m[2mLockfile validation[2m > [22m[2mshould warn when lockfile not created
|
|
260
297
|
[22m[39m
|
|
261
298
|
📦 Installing dependencies with npm...
|
|
262
299
|
|
|
300
|
+
[32m✓[39m src/__tests__/helpers/install.test.ts [2m([22m[2m20 tests[22m[2m)[22m[32m 79[2mms[22m[39m
|
|
263
301
|
|
|
264
|
-
[1m[33m ❯ [39m[22msrc/__tests__/cloudflare-template.test.ts[2m
|
|
265
|
-
[1m[33m ❯ [39m[22msrc/__tests__/helpers/fetch-cloudflare-mcpi-template.test.ts[2m
|
|
266
|
-
[1m[33m ❯ [39m[22msrc/__tests__/helpers/generate-config.test.ts[2m
|
|
267
|
-
[1m[33m ❯ [39m[22msrc/__tests__/helpers/
|
|
268
|
-
[1m[33m ❯ [39m[22msrc/__tests__/
|
|
269
|
-
[1m[33m ❯ [39m[22mtest-cloudflare/tests/do-routing.test.ts[2m
|
|
302
|
+
[1m[33m ❯ [39m[22msrc/__tests__/cloudflare-template.test.ts[2m 2/24[22m
|
|
303
|
+
[1m[33m ❯ [39m[22msrc/__tests__/helpers/fetch-cloudflare-mcpi-template.test.ts[2m 4/19[22m
|
|
304
|
+
[1m[33m ❯ [39m[22msrc/__tests__/helpers/generate-config.test.ts[2m 18/25[22m
|
|
305
|
+
[1m[33m ❯ [39m[22msrc/__tests__/helpers/validate-project-structure.test.ts[2m 18/23[22m
|
|
306
|
+
[1m[33m ❯ [39m[22msrc/helpers/__tests__/config-builder.spec.ts[2m [queued][22m
|
|
307
|
+
[1m[33m ❯ [39m[22mtest-cloudflare/tests/do-routing.test.ts[2m 10/14[22m
|
|
270
308
|
|
|
271
309
|
[2m Test Files [22m[1m[32m6 passed[39m[22m[90m (12)[39m
|
|
272
|
-
[2m Tests [22m[1m[
|
|
273
|
-
[2m Start at [
|
|
274
|
-
[2m Duration [
|
|
275
|
-
[?2026l[?2026h[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
[1m[33m ❯ [39m[22msrc/__tests__/cloudflare-template.test.ts[2m
|
|
282
|
-
[1m[33m ❯ [39m[22msrc/__tests__/helpers/fetch-cloudflare-mcpi-template.test.ts[2m
|
|
283
|
-
|
|
284
|
-
[2m Test Files [22m[1m[
|
|
285
|
-
[2m Tests [22m[1m[
|
|
286
|
-
[2m Start at [
|
|
287
|
-
[2m Duration [
|
|
288
|
-
[?2026l[?2026h[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K [32m✓[39m src/__tests__/helpers/
|
|
289
|
-
[32m✓[39m src/__tests__/
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
[
|
|
294
|
-
[
|
|
295
|
-
[
|
|
296
|
-
[
|
|
297
|
-
[
|
|
298
|
-
[
|
|
299
|
-
[
|
|
300
|
-
[
|
|
301
|
-
[
|
|
302
|
-
|
|
303
|
-
[
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
[
|
|
308
|
-
[
|
|
309
|
-
|
|
310
|
-
[
|
|
311
|
-
[
|
|
312
|
-
[
|
|
313
|
-
[
|
|
314
|
-
|
|
315
|
-
[
|
|
310
|
+
[2m Tests [22m[1m[32m172 passed[39m[22m[90m (225)[39m
|
|
311
|
+
[2m Start at [22m14:20:47
|
|
312
|
+
[2m Duration [22m1.00s
|
|
313
|
+
[?2026l[?2026h[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[90mstderr[2m | src/helpers/__tests__/config-builder.spec.ts[2m > [22m[2mbuildConfigWithRemote[2m > [22m[2mshould fallback to local config when remote fetch fails
|
|
314
|
+
[22m[39m[RemoteConfig] Neither projectId nor agentDid provided
|
|
315
|
+
|
|
316
|
+
|
|
317
|
+
|
|
318
|
+
|
|
319
|
+
[1m[33m ❯ [39m[22msrc/__tests__/cloudflare-template.test.ts[2m 4/24[22m
|
|
320
|
+
[1m[33m ❯ [39m[22msrc/__tests__/helpers/fetch-cloudflare-mcpi-template.test.ts[2m 18/19[22m
|
|
321
|
+
|
|
322
|
+
[2m Test Files [22m[1m[31m1 failed[39m[22m[2m | [22m[1m[32m9 passed[39m[22m[90m (12)[39m
|
|
323
|
+
[2m Tests [22m[1m[31m1 failed[39m[22m[2m | [22m[1m[32m215 passed[39m[22m[90m (237)[39m
|
|
324
|
+
[2m Start at [22m14:20:47
|
|
325
|
+
[2m Duration [22m1.10s
|
|
326
|
+
[?2026l[?2026h[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K [32m✓[39m src/__tests__/helpers/validate-project-structure.test.ts [2m([22m[2m23 tests[22m[2m)[22m[32m 128[2mms[22m[39m
|
|
327
|
+
[32m✓[39m src/__tests__/helpers/generate-config.test.ts [2m([22m[2m25 tests[22m[2m)[22m[32m 197[2mms[22m[39m
|
|
328
|
+
[32m✓[39m src/helpers/__tests__/config-builder.spec.ts [2m([22m[2m12 tests[22m[2m)[22m[32m 6[2mms[22m[39m
|
|
329
|
+
[31m❯[39m test-cloudflare/tests/do-routing.test.ts [2m([22m[2m14 tests[22m[2m | [22m[31m1 failed[39m[2m)[22m[33m 320[2mms[22m[39m
|
|
330
|
+
[32m✓[39m should route to different instances for different sessions[32m 15[2mms[22m[39m
|
|
331
|
+
[32m✓[39m should route to same instance for same session[32m 0[2mms[22m[39m
|
|
332
|
+
[32m✓[39m should handle both mcp-session-id header casings[32m 0[2mms[22m[39m
|
|
333
|
+
[32m✓[39m should generate random session if header missing[32m 0[2mms[22m[39m
|
|
334
|
+
[32m✓[39m should distribute requests across shards[32m 50[2mms[22m[39m
|
|
335
|
+
[32m✓[39m should consistently route same session to same shard[32m 0[2mms[22m[39m
|
|
336
|
+
[32m✓[39m should respect custom shard count[32m 2[2mms[22m[39m
|
|
337
|
+
[32m✓[39m should fall back to default when strategy unknown[32m 0[2mms[22m[39m
|
|
338
|
+
[32m✓[39m should use session strategy when not configured[32m 0[2mms[22m[39m
|
|
339
|
+
[32m✓[39m session routing should have O(1) complexity[32m 85[2mms[22m[39m
|
|
340
|
+
[31m [31m×[31m shard routing should have O(n) complexity for hash[39m[32m 164[2mms[22m[39m
|
|
341
|
+
[32m✓[39m should handle empty session ID[32m 0[2mms[22m[39m
|
|
342
|
+
[32m✓[39m should handle non-numeric shard count[32m 0[2mms[22m[39m
|
|
343
|
+
[32m✓[39m should handle special characters in session ID[32m 1[2mms[22m[39m
|
|
344
|
+
|
|
345
|
+
[1m[33m ❯ [39m[22msrc/__tests__/cloudflare-template.test.ts[2m 4/24[22m
|
|
346
|
+
[1m[33m ❯ [39m[22msrc/__tests__/helpers/fetch-cloudflare-mcpi-template.test.ts[2m 18/19[22m
|
|
347
|
+
|
|
348
|
+
[2m Test Files [22m[1m[31m1 failed[39m[22m[2m | [22m[1m[32m9 passed[39m[22m[90m (12)[39m
|
|
349
|
+
[2m Tests [22m[1m[31m1 failed[39m[22m[2m | [22m[1m[32m215 passed[39m[22m[90m (237)[39m
|
|
350
|
+
[2m Start at [22m14:20:47
|
|
351
|
+
[2m Duration [22m1.10s
|
|
352
|
+
[?2026l[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K [32m✓[39m src/__tests__/helpers/fetch-cloudflare-mcpi-template.test.ts [2m([22m[2m19 tests[22m[2m)[22m[33m 391[2mms[22m[39m
|
|
353
|
+
[31m❯[39m src/__tests__/cloudflare-template.test.ts [2m([22m[2m24 tests[22m[2m | [22m[31m1 failed[39m[2m)[22m[33m 381[2mms[22m[39m
|
|
354
|
+
[32m✓[39m should create all required files and directories[32m 40[2mms[22m[39m
|
|
355
|
+
[32m✓[39m should create mcpi-runtime-config.ts with correct structure[32m 30[2mms[22m[39m
|
|
356
|
+
[32m✓[39m should create index.ts with correct structure[32m 95[2mms[22m[39m
|
|
357
|
+
[32m✓[39m should include MCP_SERVER_URL placeholder in wrangler.toml[32m 26[2mms[22m[39m
|
|
358
|
+
[31m [31m×[31m should log warning when MCP_SERVER_URL not configured[39m[32m 27[2mms[22m[39m
|
|
359
|
+
[32m✓[39m should store MCP_SERVER_URL in class property[32m 22[2mms[22m[39m
|
|
360
|
+
[32m✓[39m should include all required KV namespace bindings in wrangler.toml[32m 11[2mms[22m[39m
|
|
361
|
+
[32m✓[39m should create KV namespace creation scripts in package.json[32m 9[2mms[22m[39m
|
|
362
|
+
[32m✓[39m should create KV namespace listing scripts[32m 8[2mms[22m[39m
|
|
363
|
+
[32m✓[39m should include tool protection configuration in runtime config[32m 9[2mms[22m[39m
|
|
364
|
+
[32m✓[39m should include CloudflareRuntime import for tool protection[32m 7[2mms[22m[39m
|
|
365
|
+
[32m✓[39m should conditionally enable tool protection KV when API key provided[32m 12[2mms[22m[39m
|
|
366
|
+
[32m✓[39m should comment out tool protection KV when no API key provided[32m 9[2mms[22m[39m
|
|
367
|
+
[32m✓[39m should generate identity when skipIdentity is false[32m 7[2mms[22m[39m
|
|
368
|
+
[32m✓[39m should skip identity generation when skipIdentity is true[32m 4[2mms[22m[39m
|
|
369
|
+
[32m✓[39m should include identity variables in wrangler.toml[32m 10[2mms[22m[39m
|
|
370
|
+
[32m✓[39m should create .dev.vars.example template[32m 9[2mms[22m[39m
|
|
371
|
+
[32m✓[39m should handle file system errors gracefully[32m 1[2mms[22m[39m
|
|
372
|
+
[32m✓[39m should handle invalid project names[32m 6[2mms[22m[39m
|
|
373
|
+
[32m✓[39m should use correct package manager in scripts[32m 8[2mms[22m[39m
|
|
374
|
+
[32m✓[39m should create correct package.json structure[32m 11[2mms[22m[39m
|
|
375
|
+
[32m✓[39m should create greet tool with correct structure[32m 8[2mms[22m[39m
|
|
376
|
+
[32m✓[39m should create test files with correct structure[32m 6[2mms[22m[39m
|
|
377
|
+
[32m✓[39m should create README with project name[32m 5[2mms[22m[39m
|
|
378
|
+
|
|
379
|
+
[31m⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[39m[1m[41m Failed Tests 2 [49m[22m[31m⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[39m
|
|
380
|
+
|
|
381
|
+
[41m[1m FAIL [22m[49m src/__tests__/cloudflare-template.test.ts[2m > [22mCloudflare Template Generation[2m > [22mMCP_SERVER_URL configuration[2m > [22mshould log warning when MCP_SERVER_URL not configured
|
|
382
|
+
[31m[1mAssertionError[22m: expected 'import { McpAgent } from "agents/mcp"…' to contain 'Warning: MCP_SERVER_URL not configured'[39m
|
|
383
|
+
|
|
384
|
+
[32m- Expected[39m
|
|
385
|
+
[31m+ Received[39m
|
|
386
|
+
|
|
387
|
+
[32m- Warning: MCP_SERVER_URL not configured[39m
|
|
388
|
+
[31m+ import { McpAgent } from "agents/mcp";[39m
|
|
389
|
+
[31m+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";[39m
|
|
390
|
+
[31m+ import { createCloudflareRuntime, type CloudflareEnv, KVProofArchive, type DetachedProof, createOAuthCallbackHandler, CloudflareRuntime } from "@kya-os/mcp-i-cloudflare";[39m
|
|
391
|
+
[31m+ import { DelegationRequiredError } from "@kya-os/mcp-i-core";[39m
|
|
392
|
+
[31m+ import type { ToolProtectionService } from "@kya-os/mcp-i-core";[39m
|
|
393
|
+
[31m+ import { Hono } from "hono";[39m
|
|
394
|
+
[31m+ import { cors } from "hono/cors";[39m
|
|
395
|
+
[31m+ import { greetTool } from "./tools/greet";[39m
|
|
396
|
+
[31m+ import { getRuntimeConfig } from "./mcpi-runtime-config";[39m
|
|
397
|
+
[31m+ import type { CloudflareRuntimeConfig } from "@kya-os/mcp-i-cloudflare/config";[39m
|
|
398
|
+
[31m+[39m
|
|
399
|
+
[31m+ /**[39m
|
|
400
|
+
[31m+ * Extended CloudflareEnv with prefixed KV bindings for multi-agent deployments[39m
|
|
401
|
+
[31m+ * This allows multiple agents to share the same Cloudflare account without conflicts[39m
|
|
402
|
+
[31m+ */[39m
|
|
403
|
+
[31m+ interface PrefixedCloudflareEnv extends CloudflareEnv {[39m
|
|
404
|
+
[31m+ // Prefixed KV bindings (e.g., MYAGENT_NONCE_CACHE, MYAGENT_PROOF_ARCHIVE)[39m
|
|
405
|
+
[31m+ [key: string]: KVNamespace | string | DurableObjectState | undefined;[39m
|
|
406
|
+
[31m+ // Optional routing configuration[39m
|
|
407
|
+
[31m+ DO_ROUTING_STRATEGY?: string;[39m
|
|
408
|
+
[31m+ DO_SHARD_COUNT?: string;[39m
|
|
409
|
+
[31m+ // Prefixed KV namespaces (dynamically accessed)[39m
|
|
410
|
+
[31m+ TESTPROJECT_NONCE_CACHE?: KVNamespace;[39m
|
|
411
|
+
[31m+ TESTPROJECT_PROOF_ARCHIVE?: KVNamespace;[39m
|
|
412
|
+
[31m+ TESTPROJECT_IDENTITY_STORAGE?: KVNamespace;[39m
|
|
413
|
+
[31m+ TESTPROJECT_DELEGATION_STORAGE?: KVNamespace;[39m
|
|
414
|
+
[31m+ TESTPROJECT_TOOL_PROTECTION_KV?: KVNamespace;[39m
|
|
415
|
+
[31m+ }[39m
|
|
416
|
+
[31m+[39m
|
|
417
|
+
[31m+ export class TestprojectMCP extends McpAgent {[39m
|
|
418
|
+
[31m+ server = new McpServer({[39m
|
|
419
|
+
[31m+ name: "test-project",[39m
|
|
420
|
+
[31m+ version: "1.0.0"[39m
|
|
421
|
+
[31m+ });[39m
|
|
422
|
+
[31m+[39m
|
|
423
|
+
[31m+ private mcpiRuntime?: ReturnType<typeof createCloudflareRuntime>;[39m
|
|
424
|
+
[31m+ private proofArchive?: KVProofArchive;[39m
|
|
425
|
+
[31m+ private agentShieldConfig?: { apiUrl: string; apiKey: string };[39m
|
|
426
|
+
[31m+ private env: PrefixedCloudflareEnv;[39m
|
|
427
|
+
[31m+ private mcpServerUrl?: string;[39m
|
|
428
|
+
[31m+[39m
|
|
429
|
+
[31m+ constructor(state: DurableObjectState, env: PrefixedCloudflareEnv) {[39m
|
|
430
|
+
[31m+ super(state, env);[39m
|
|
431
|
+
[31m+ this.env = env;[39m
|
|
432
|
+
[31m+[39m
|
|
433
|
+
[31m+ // Create CloudflareEnv adapter to map prefixed KV bindings to expected names[39m
|
|
434
|
+
[31m+ // This allows multiple agents to be deployed without KV namespace conflicts[39m
|
|
435
|
+
[31m+ const mappedEnv: CloudflareEnv = {[39m
|
|
436
|
+
[31m+ // Map prefixed bindings to standard names expected by createCloudflareRuntime[39m
|
|
437
|
+
[31m+ NONCE_CACHE: env.TESTPROJECT_NONCE_CACHE,[39m
|
|
438
|
+
[31m+ PROOF_ARCHIVE: env.TESTPROJECT_PROOF_ARCHIVE,[39m
|
|
439
|
+
[31m+ IDENTITY_STORAGE: env.TESTPROJECT_IDENTITY_STORAGE,[39m
|
|
440
|
+
[31m+ DELEGATION_STORAGE: env.TESTPROJECT_DELEGATION_STORAGE,[39m
|
|
441
|
+
[31m+ TOOL_PROTECTION_KV: env.TESTPROJECT_TOOL_PROTECTION_KV,[39m
|
|
442
|
+
[31m+ // Pass through environment variables unchanged[39m
|
|
443
|
+
[31m+ MCP_IDENTITY_PRIVATE_KEY: env.MCP_IDENTITY_PRIVATE_KEY,[39m
|
|
444
|
+
[31m+ MCP_IDENTITY_PUBLIC_KEY: env.MCP_IDENTITY_PUBLIC_KEY,[39m
|
|
445
|
+
[31m+ MCP_IDENTITY_AGENT_DID: env.MCP_IDENTITY_AGENT_DID,[39m
|
|
446
|
+
[31m+ // Pass through other env vars for runtime config[39m
|
|
447
|
+
[31m+ AGENTSHIELD_API_URL: env.AGENTSHIELD_API_URL,[39m
|
|
448
|
+
[31m+ AGENTSHIELD_API_KEY: env.AGENTSHIELD_API_KEY,[39m
|
|
449
|
+
[31m+ AGENTSHIELD_PROJECT_ID: env.AGENTSHIELD_PROJECT_ID,[39m
|
|
450
|
+
[31m+ MCPI_ENV: env.MCPI_ENV,[39m
|
|
451
|
+
[31m+ MCP_SERVER_URL: env.MCP_SERVER_URL,[39m
|
|
452
|
+
[31m+ // Pass Durable Object state for identity persistence[39m
|
|
453
|
+
[31m+ // NOTE: Without this, identity will be ephemeral (new DID every call)![39m
|
|
454
|
+
[31m+ // Note: createCloudflareRuntime will automatically use KVIdentityProvider if IDENTITY_STORAGE KV is available[39m
|
|
455
|
+
[31m+ _durableObjectState: state,[39m
|
|
456
|
+
[31m+ };[39m
|
|
457
|
+
[31m+[39m
|
|
458
|
+
[31m+ // Store MCP server URL for proof submission context[39m
|
|
459
|
+
[31m+ // Auto-detect from request URL if not explicitly set (will be set in fetch handler)[39m
|
|
460
|
+
[31m+ this.mcpServerUrl = env.MCP_SERVER_URL;[39m
|
|
461
|
+
[31m+ if (this.mcpServerUrl) {[39m
|
|
462
|
+
[31m+ // Ensure URL includes /mcp path if not already present[39m
|
|
463
|
+
[31m+ if (!this.mcpServerUrl.endsWith('/mcp')) {[39m
|
|
464
|
+
[31m+ this.mcpServerUrl = this.mcpServerUrl.replace(//$/, '') + '/mcp';[39m
|
|
465
|
+
[31m+ }[39m
|
|
466
|
+
[31m+ console.log('[MCP-I] MCP Server URL configured:', this.mcpServerUrl);[39m
|
|
467
|
+
[31m+ } else {[39m
|
|
468
|
+
[31m+ // Will be auto-detected from request URL in fetch handler[39m
|
|
469
|
+
[31m+ console.log('[MCP-I] MCP Server URL will be auto-detected from request');[39m
|
|
470
|
+
[31m+ }[39m
|
|
471
|
+
[31m+[39m
|
|
472
|
+
[31m+ // Load runtime configuration for AgentShield integration[39m
|
|
473
|
+
[31m+ // Pass mappedEnv so it can access KV bindings with standard names[39m
|
|
474
|
+
[31m+ const runtimeConfig = getRuntimeConfig(mappedEnv);[39m
|
|
475
|
+
[31m+[39m
|
|
476
|
+
[31m+ // ✅ Create tool protection service helper function[39m
|
|
477
|
+
[31m+ // Always import CloudflareRuntime but conditionally instantiate[39m
|
|
478
|
+
[31m+ function createToolProtectionService(env: CloudflareEnv, runtimeConfig: CloudflareRuntimeConfig): ToolProtectionService | undefined {[39m
|
|
479
|
+
[31m+ if (!runtimeConfig.toolProtection) {[39m
|
|
480
|
+
[31m+ return undefined;[39m
|
|
481
|
+
[31m+ }[39m
|
|
482
|
+
[31m+[39m
|
|
483
|
+
[31m+ if (!env.TOOL_PROTECTION_KV || !env.AGENTSHIELD_API_KEY) {[39m
|
|
484
|
+
[31m+ console.log('[MCP-I] Tool protection disabled - configure TOOL_PROTECTION_KV and AGENTSHIELD_API_KEY to enable');[39m
|
|
485
|
+
[31m+ return undefined;[39m
|
|
486
|
+
[31m+ }[39m
|
|
487
|
+
[31m+[39m
|
|
488
|
+
[31m+ return CloudflareRuntime.createToolProtectionService([39m
|
|
489
|
+
[31m+ env.TOOL_PROTECTION_KV,[39m
|
|
490
|
+
[31m+ {[39m
|
|
491
|
+
[31m+ apiUrl: runtimeConfig.toolProtection.agentShield?.apiUrl || env.AGENTSHIELD_API_URL || 'https://kya.vouched.id',[39m
|
|
492
|
+
[31m+ apiKey: env.AGENTSHIELD_API_KEY,[39m
|
|
493
|
+
[31m+ projectId: runtimeConfig.toolProtection.agentShield?.projectId || env.AGENTSHIELD_PROJECT_ID,[39m
|
|
494
|
+
[31m+ cacheTtl: runtimeConfig.toolProtection.agentShield?.cacheTtl || 300000,[39m
|
|
495
|
+
[31m+ debug: runtimeConfig.environment === 'development',[39m
|
|
496
|
+
[31m+ fallbackConfig: runtimeConfig.toolProtection.fallback[39m
|
|
497
|
+
[31m+ }[39m
|
|
498
|
+
[31m+ );[39m
|
|
499
|
+
[31m+ }[39m
|
|
500
|
+
[31m+[39m
|
|
501
|
+
[31m+ // Create tool protection service if configured[39m
|
|
502
|
+
[31m+ // Note: createCloudflareRuntime will automatically use KVIdentityProvider if IDENTITY_STORAGE KV is available[39m
|
|
503
|
+
[31m+ const toolProtectionService = createToolProtectionService(mappedEnv, runtimeConfig);[39m
|
|
504
|
+
[31m+[39m
|
|
505
|
+
[31m+ // Initialize MCP-I runtime for cryptographic proofs and identity[39m
|
|
506
|
+
[31m+ this.mcpiRuntime = createCloudflareRuntime({[39m
|
|
507
|
+
[31m+ env: mappedEnv,[39m
|
|
508
|
+
[31m+ environment: runtimeConfig.environment,[39m
|
|
509
|
+
[31m+ audit: {[39m
|
|
510
|
+
[31m+ enabled: runtimeConfig.audit?.enabled ?? true,[39m
|
|
511
|
+
[31m+ logFunction: runtimeConfig.audit?.logFunction || ((record) => console.log('[MCP-I Audit]', record))[39m
|
|
512
|
+
[31m+ },[39m
|
|
513
|
+
[31m+ toolProtectionService[39m
|
|
514
|
+
[31m+ });[39m
|
|
515
|
+
[31m+[39m
|
|
516
|
+
[31m+ // Initialize proof archive if PROOF_ARCHIVE KV is available[39m
|
|
517
|
+
[31m+ if (mappedEnv.PROOF_ARCHIVE) {[39m
|
|
518
|
+
[31m+ this.proofArchive = new KVProofArchive(mappedEnv.PROOF_ARCHIVE);[39m
|
|
519
|
+
[31m+ console.log('[MCP-I] Proof archive enabled');[39m
|
|
520
|
+
[31m+ }[39m
|
|
521
|
+
[31m+[39m
|
|
522
|
+
[31m+ // Load AgentShield config for proof submission[39m
|
|
523
|
+
[31m+ if (runtimeConfig.proofing?.enabled && runtimeConfig.proofing.batchQueue) {[39m
|
|
524
|
+
[31m+ const agentShieldDest = runtimeConfig.proofing.batchQueue.destinations?.find([39m
|
|
525
|
+
[31m+ (dest) => dest.type === "agentshield" && dest.apiKey[39m
|
|
526
|
+
[31m+ );[39m
|
|
527
|
+
[31m+ if (agentShieldDest) {[39m
|
|
528
|
+
[31m+ this.agentShieldConfig = {[39m
|
|
529
|
+
[31m+ apiUrl: agentShieldDest.apiUrl,[39m
|
|
530
|
+
[31m+ apiKey: agentShieldDest.apiKey![39m
|
|
531
|
+
[31m+ };[39m
|
|
532
|
+
[31m+ console.log('[MCP-I] AgentShield enabled:', agentShieldDest.apiUrl);[39m
|
|
533
|
+
[31m+ }[39m
|
|
534
|
+
[31m+ }[39m
|
|
535
|
+
[31m+ }[39m
|
|
536
|
+
[31m+[39m
|
|
537
|
+
[31m+ /**[39m
|
|
538
|
+
[31m+ * Handle incoming requests[39m
|
|
539
|
+
[31m+ * Auto-detects MCP Server URL from request if not explicitly configured[39m
|
|
540
|
+
[31m+ */[39m
|
|
541
|
+
[31m+ async fetch(request: Request): Promise<Response> {[39m
|
|
542
|
+
[31m+ // Auto-detect MCP Server URL from request if not already set[39m
|
|
543
|
+
[31m+ if (!this.mcpServerUrl && request.url) {[39m
|
|
544
|
+
[31m+ try {[39m
|
|
545
|
+
[31m+ const requestUrl = new URL(request.url);[39m
|
|
546
|
+
[31m+ // Extract origin and ensure /mcp path is included[39m
|
|
547
|
+
[31m+ this.mcpServerUrl = requestUrl.origin + '/mcp';[39m
|
|
548
|
+
[31m+ console.log('[MCP-I] MCP Server URL auto-detected from request:', this.mcpServerUrl);[39m
|
|
549
|
+
[31m+ } catch (error) {[39m
|
|
550
|
+
[31m+ console.warn('[MCP-I] Failed to auto-detect MCP Server URL from request:', error);[39m
|
|
551
|
+
[31m+ }[39m
|
|
552
|
+
[31m+ }[39m
|
|
553
|
+
[31m+[39m
|
|
554
|
+
[31m+ // Delegate to McpAgent's fetch handler[39m
|
|
555
|
+
[31m+ return super.fetch(request);[39m
|
|
556
|
+
[31m+ }[39m
|
|
557
|
+
[31m+[39m
|
|
558
|
+
[31m+ /**[39m
|
|
559
|
+
[31m+ * Override getInstanceId() to enable multi-instance Durable Object routing[39m
|
|
560
|
+
[31m+ *[39m
|
|
561
|
+
[31m+ * This method is called internally by McpAgent to determine which DO instance[39m
|
|
562
|
+
[31m+ * should handle the request. By overriding it, we can implement custom routing[39m
|
|
563
|
+
[31m+ * strategies (session-based, shard-based, etc.) while maintaining full[39m
|
|
564
|
+
[31m+ * McpAgent compatibility and preserving PartyServer routing context.[39m
|
|
565
|
+
[31m+ *[39m
|
|
566
|
+
[31m+ * @returns Instance ID used by McpAgent for DO routing[39m
|
|
567
|
+
[31m+ */[39m
|
|
568
|
+
[31m+ getInstanceId(): string {[39m
|
|
569
|
+
[31m+ try {[39m
|
|
570
|
+
[31m+ // Get session ID from McpAgent's built-in extraction[39m
|
|
571
|
+
[31m+ const sessionId = this.getSessionId();[39m
|
|
572
|
+
[31m+[39m
|
|
573
|
+
[31m+ // Get routing strategy from environment (default: session)[39m
|
|
574
|
+
[31m+ const strategy = this.env.DO_ROUTING_STRATEGY || 'session';[39m
|
|
575
|
+
[31m+[39m
|
|
576
|
+
[31m+ if (strategy === 'session') {[39m
|
|
577
|
+
[31m+ // One DO instance per MCP session (recommended for most use cases)[39m
|
|
578
|
+
[31m+ // Sessions are isolated, ensuring data consistency per client[39m
|
|
579
|
+
[31m+ return `session:${sessionId}`;[39m
|
|
580
|
+
[31m+ } else if (strategy === 'shard') {[39m
|
|
581
|
+
[31m+ // Hash-based sharding across N DO instances (for high load)[39m
|
|
582
|
+
[31m+ // Distributes load evenly while maintaining session affinity[39m
|
|
583
|
+
[31m+ const shardCount = parseInt(this.env.DO_SHARD_COUNT || '10');[39m
|
|
584
|
+
[31m+ // Validate shard count - must be a valid positive number[39m
|
|
585
|
+
[31m+ const validShardCount = (!isNaN(shardCount) && shardCount > 0) ? shardCount : 10;[39m
|
|
586
|
+
[31m+[39m
|
|
587
|
+
[31m+ // Simple hash function for session ID[39m
|
|
588
|
+
[31m+ let hash = 0;[39m
|
|
589
|
+
[31m+ for (let i = 0; i < sessionId.length; i++) {[39m
|
|
590
|
+
[31m+ hash = ((hash << 5) - hash) + sessionId.charCodeAt(i);[39m
|
|
591
|
+
[31m+ hash = hash & hash; // Convert to 32bit integer[39m
|
|
592
|
+
[31m+ }[39m
|
|
593
|
+
[31m+[39m
|
|
594
|
+
[31m+ const shard = Math.abs(hash) % validShardCount;[39m
|
|
595
|
+
[31m+ return `shard:${shard}`;[39m
|
|
596
|
+
[31m+ }[39m
|
|
597
|
+
[31m+[39m
|
|
598
|
+
[31m+ // Fallback to single instance (legacy behavior)[39m
|
|
599
|
+
[31m+ return 'default';[39m
|
|
600
|
+
[31m+ } catch (error) {[39m
|
|
601
|
+
[31m+ // If session extraction fails, fall back to default instance[39m
|
|
602
|
+
[31m+ console.error('[DO Routing] Failed to extract session ID:', error);[39m
|
|
603
|
+
[31m+ return 'default';[39m
|
|
604
|
+
[31m+ }[39m
|
|
605
|
+
[31m+ }[39m
|
|
606
|
+
[31m+[39m
|
|
607
|
+
[31m+ /**[39m
|
|
608
|
+
[31m+ * Retrieve delegation token from KV storage[39m
|
|
609
|
+
[31m+ * Uses two-tier lookup: session cache (fast) → agent DID (stable)[39m
|
|
610
|
+
[31m+ *[39m
|
|
611
|
+
[31m+ * @param sessionId - MCP session ID from Claude Desktop[39m
|
|
612
|
+
[31m+ * @returns Delegation token if found, null otherwise[39m
|
|
613
|
+
[31m+ */[39m
|
|
614
|
+
[31m+ private async getDelegationToken(sessionId?: string): Promise<string | null> {[39m
|
|
615
|
+
[31m+ const delegationStorage = this.env.TESTPROJECT_DELEGATION_STORAGE;[39m
|
|
616
|
+
[31m+[39m
|
|
617
|
+
[31m+ if (!delegationStorage) {[39m
|
|
618
|
+
[31m+ console.log('[Delegation] No delegation storage configured');[39m
|
|
619
|
+
[31m+ return null;[39m
|
|
620
|
+
[31m+ }[39m
|
|
621
|
+
[31m+[39m
|
|
622
|
+
[31m+ try {[39m
|
|
623
|
+
[31m+ // Fast path: Try session cache first[39m
|
|
624
|
+
[31m+ if (sessionId) {[39m
|
|
625
|
+
[31m+ const sessionKey = `session:${sessionId}`;[39m
|
|
626
|
+
[31m+ const sessionToken = await delegationStorage.get(sessionKey);[39m
|
|
627
|
+
[31m+[39m
|
|
628
|
+
[31m+ if (sessionToken) {[39m
|
|
629
|
+
[31m+ // Verify token is still valid before returning[39m
|
|
630
|
+
[31m+ const isValid = await this.verifyDelegationWithAgentShield(sessionToken);[39m
|
|
631
|
+
[31m+ if (isValid) {[39m
|
|
632
|
+
[31m+ console.log('[Delegation] ✅ Token retrieved from session cache and verified');[39m
|
|
633
|
+
[31m+ return sessionToken;[39m
|
|
634
|
+
[31m+ } else {[39m
|
|
635
|
+
[31m+ // Token invalid, remove from cache[39m
|
|
636
|
+
[31m+ await this.invalidateDelegationCache(sessionId, sessionToken);[39m
|
|
637
|
+
[31m+ console.log('[Delegation] ⚠️ Cached token was invalid, removed from cache');[39m
|
|
638
|
+
[31m+ }[39m
|
|
639
|
+
[31m+ }[39m
|
|
640
|
+
[31m+ }[39m
|
|
641
|
+
[31m+[39m
|
|
642
|
+
[31m+ // Fallback: Try agent DID (stable across session changes)[39m
|
|
643
|
+
[31m+ if (this.mcpiRuntime) {[39m
|
|
644
|
+
[31m+ const identity = await this.mcpiRuntime.getIdentity();[39m
|
|
645
|
+
[31m+ if (identity?.did) {[39m
|
|
646
|
+
[31m+ const agentKey = `agent:${identity.did}:delegation`;[39m
|
|
647
|
+
[31m+ const agentToken = await delegationStorage.get(agentKey);[39m
|
|
648
|
+
[31m+[39m
|
|
649
|
+
[31m+ if (agentToken) {[39m
|
|
650
|
+
[31m+ // Verify token is still valid before returning[39m
|
|
651
|
+
[31m+ const isValid = await this.verifyDelegationWithAgentShield(agentToken);[39m
|
|
652
|
+
[31m+ if (isValid) {[39m
|
|
653
|
+
[31m+ console.log('[Delegation] ✅ Token retrieved using agent DID and verified');[39m
|
|
654
|
+
[31m+[39m
|
|
655
|
+
[31m+ // Re-cache for current session (performance optimization)[39m
|
|
656
|
+
[31m+ if (sessionId) {[39m
|
|
657
|
+
[31m+ const sessionCacheKey = `session:${sessionId}`;[39m
|
|
658
|
+
[31m+ await delegationStorage.put(sessionCacheKey, agentToken, {[39m
|
|
659
|
+
[31m+ expirationTtl: 300 // 5 minutes for security (reduced from 30)[39m
|
|
660
|
+
[31m+ });[39m
|
|
661
|
+
[31m+ console.log('[Delegation] Token cached for session with 5-minute TTL:', sessionId);[39m
|
|
662
|
+
[31m+ }[39m
|
|
663
|
+
[31m+[39m
|
|
664
|
+
[31m+ return agentToken;[39m
|
|
665
|
+
[31m+ } else {[39m
|
|
666
|
+
[31m+ // Token invalid, remove from cache[39m
|
|
667
|
+
[31m+ await this.invalidateDelegationCache(sessionId, agentToken, identity.did);[39m
|
|
668
|
+
[31m+ console.log('[Delegation] ⚠️ Agent token was invalid, removed from cache');[39m
|
|
669
|
+
[31m+ }[39m
|
|
670
|
+
[31m+ }[39m
|
|
671
|
+
[31m+ }[39m
|
|
672
|
+
[31m+ }[39m
|
|
673
|
+
[31m+[39m
|
|
674
|
+
[31m+ console.log('[Delegation] No delegation token found');[39m
|
|
675
|
+
[31m+ return null;[39m
|
|
676
|
+
[31m+ } catch (error) {[39m
|
|
677
|
+
[31m+ console.error('[Delegation] Failed to retrieve token:', error);[39m
|
|
678
|
+
[31m+ return null;[39m
|
|
679
|
+
[31m+ }[39m
|
|
680
|
+
[31m+ }[39m
|
|
681
|
+
[31m+[39m
|
|
682
|
+
[31m+ /**[39m
|
|
683
|
+
[31m+ * Verify delegation token with AgentShield API[39m
|
|
684
|
+
[31m+ * @param token - Delegation token to verify[39m
|
|
685
|
+
[31m+ * @returns True if token is valid, false otherwise[39m
|
|
686
|
+
[31m+ */[39m
|
|
687
|
+
[31m+ private async verifyDelegationWithAgentShield(token: string): Promise<boolean> {[39m
|
|
688
|
+
[31m+ // Check verification cache first (1 minute TTL for verified tokens)[39m
|
|
689
|
+
[31m+ const verificationCache = this.env.TOOL_PROTECTION_KV;[39m
|
|
690
|
+
[31m+ if (verificationCache) {[39m
|
|
691
|
+
[31m+ const cacheKey = `verified:${token.substring(0, 16)}`; // Use prefix to avoid key size issues[39m
|
|
692
|
+
[31m+ const cached = await verificationCache.get(cacheKey);[39m
|
|
693
|
+
[31m+ if (cached === '1') {[39m
|
|
694
|
+
[31m+ console.log('[Delegation] Token verification cached as valid');[39m
|
|
695
|
+
[31m+ return true;[39m
|
|
696
|
+
[31m+ }[39m
|
|
697
|
+
[31m+ }[39m
|
|
698
|
+
[31m+[39m
|
|
699
|
+
[31m+ try {[39m
|
|
700
|
+
[31m+ const agentShieldUrl = this.env.AGENTSHIELD_API_URL || 'https://kya.vouched.id';[39m
|
|
701
|
+
[31m+ const apiKey = this.env.AGENTSHIELD_API_KEY;[39m
|
|
702
|
+
[31m+[39m
|
|
703
|
+
[31m+ if (!apiKey) {[39m
|
|
704
|
+
[31m+ console.warn('[Delegation] No AgentShield API key configured, skipping verification');[39m
|
|
705
|
+
[31m+ return true; // Allow in development without API key[39m
|
|
706
|
+
[31m+ }[39m
|
|
707
|
+
[31m+[39m
|
|
708
|
+
[31m+ // Verify with AgentShield API[39m
|
|
709
|
+
[31m+ const response = await fetch(`${agentShieldUrl}/api/v1/bouncer/delegations/verify`, {[39m
|
|
710
|
+
[31m+ method: 'POST',[39m
|
|
711
|
+
[31m+ headers: {[39m
|
|
712
|
+
[31m+ 'Authorization': `Bearer ${apiKey}`,[39m
|
|
713
|
+
[31m+ 'Content-Type': 'application/json'[39m
|
|
714
|
+
[31m+ },[39m
|
|
715
|
+
[31m+ body: JSON.stringify({ token })[39m
|
|
716
|
+
[31m+ });[39m
|
|
717
|
+
[31m+[39m
|
|
718
|
+
[31m+ if (response.ok) {[39m
|
|
719
|
+
[31m+ // Cache successful verification for 1 minute[39m
|
|
720
|
+
[31m+ if (verificationCache) {[39m
|
|
721
|
+
[31m+ const cacheKey = `verified:${token.substring(0, 16)}`;[39m
|
|
722
|
+
[31m+ await verificationCache.put(cacheKey, '1', {[39m
|
|
723
|
+
[31m+ expirationTtl: 60 // 1 minute cache for verified tokens[39m
|
|
724
|
+
[31m+ });[39m
|
|
725
|
+
[31m+ }[39m
|
|
726
|
+
[31m+ console.log('[Delegation] Token verified successfully with AgentShield');[39m
|
|
727
|
+
[31m+ return true;[39m
|
|
728
|
+
[31m+ }[39m
|
|
729
|
+
[31m+[39m
|
|
730
|
+
[31m+ if (response.status === 401 || response.status === 403) {[39m
|
|
731
|
+
[31m+ console.log('[Delegation] Token verification failed: unauthorized');[39m
|
|
732
|
+
[31m+ return false;[39m
|
|
733
|
+
[31m+ }[39m
|
|
734
|
+
[31m+[39m
|
|
735
|
+
[31m+ console.warn('[Delegation] Token verification returned unexpected status:', response.status);[39m
|
|
736
|
+
[31m+ return false; // Fail closed for security[39m
|
|
737
|
+
[31m+[39m
|
|
738
|
+
[31m+ } catch (error) {[39m
|
|
739
|
+
[31m+ console.error('[Delegation] Error verifying token with AgentShield:', error);[39m
|
|
740
|
+
[31m+ return false; // Fail closed on errors[39m
|
|
741
|
+
[31m+ }[39m
|
|
742
|
+
[31m+ }[39m
|
|
743
|
+
[31m+[39m
|
|
744
|
+
[31m+ /**[39m
|
|
745
|
+
[31m+ * Invalidate delegation token in all caches[39m
|
|
746
|
+
[31m+ * @param sessionId - Session ID to clear[39m
|
|
747
|
+
[31m+ * @param token - Token to invalidate[39m
|
|
748
|
+
[31m+ * @param agentDid - Agent DID to clear[39m
|
|
749
|
+
[31m+ */[39m
|
|
750
|
+
[31m+ private async invalidateDelegationCache(sessionId?: string, token?: string, agentDid?: string): Promise<void> {[39m
|
|
751
|
+
[31m+ const delegationStorage = this.env.TESTPROJECT_DELEGATION_STORAGE;[39m
|
|
752
|
+
[31m+ const verificationCache = this.env.TOOL_PROTECTION_KV;[39m
|
|
753
|
+
[31m+[39m
|
|
754
|
+
[31m+ if (!delegationStorage) return;[39m
|
|
755
|
+
[31m+[39m
|
|
756
|
+
[31m+ const deletions: Promise<void>[] = [];[39m
|
|
757
|
+
[31m+[39m
|
|
758
|
+
[31m+ // Clear session cache[39m
|
|
759
|
+
[31m+ if (sessionId) {[39m
|
|
760
|
+
[31m+ const sessionKey = `session:${sessionId}`;[39m
|
|
761
|
+
[31m+ deletions.push(delegationStorage.delete(sessionKey));[39m
|
|
762
|
+
[31m+ }[39m
|
|
763
|
+
[31m+[39m
|
|
764
|
+
[31m+ // Clear agent cache[39m
|
|
765
|
+
[31m+ if (agentDid) {[39m
|
|
766
|
+
[31m+ const agentKey = `agent:${agentDid}:delegation`;[39m
|
|
767
|
+
[31m+ deletions.push(delegationStorage.delete(agentKey));[39m
|
|
768
|
+
[31m+ }[39m
|
|
769
|
+
[31m+[39m
|
|
770
|
+
[31m+ // Clear verification cache[39m
|
|
771
|
+
[31m+ if (token && verificationCache) {[39m
|
|
772
|
+
[31m+ const cacheKey = `verified:${token.substring(0, 16)}`;[39m
|
|
773
|
+
[31m+ deletions.push(verificationCache.delete(cacheKey));[39m
|
|
774
|
+
[31m+ }[39m
|
|
775
|
+
[31m+[39m
|
|
776
|
+
[31m+ await Promise.all(deletions);[39m
|
|
777
|
+
[31m+ console.log('[Delegation] Cache invalidated for revoked/invalid token');[39m
|
|
778
|
+
[31m+ }[39m
|
|
779
|
+
[31m+[39m
|
|
780
|
+
[31m+ /**[39m
|
|
781
|
+
[31m+ * Submit proof to AgentShield API[39m
|
|
782
|
+
[31m+ * Uses the proof.jws directly (full JWS format from CloudflareRuntime)[39m
|
|
783
|
+
[31m+ *[39m
|
|
784
|
+
[31m+ * Also submits optional context for AgentShield dashboard integration.[39m
|
|
785
|
+
[31m+ * Context provides plaintext tool/args data while proof provides cryptographic verification.[39m
|
|
786
|
+
[31m+ */[39m
|
|
787
|
+
[31m+ private async submitProofToAgentShield([39m
|
|
788
|
+
[31m+ proof: DetachedProof,[39m
|
|
789
|
+
[31m+ session: { id: string },[39m
|
|
790
|
+
[31m+ toolName: string,[39m
|
|
791
|
+
[31m+ args: Record<string, unknown>,[39m
|
|
792
|
+
[31m+ result: unknown[39m
|
|
793
|
+
[31m+ ): Promise<void> {[39m
|
|
794
|
+
[31m+ if (!this.agentShieldConfig || !proof.jws || !proof.meta) return;[39m
|
|
795
|
+
[31m+[39m
|
|
796
|
+
[31m+ const { apiUrl, apiKey } = this.agentShieldConfig;[39m
|
|
797
|
+
[31m+[39m
|
|
798
|
+
[31m+ // Get tool call context from runtime (if available)[39m
|
|
799
|
+
[31m+ const toolCallContext = this.mcpiRuntime?.getLastToolCallContext();[39m
|
|
800
|
+
[31m+[39m
|
|
801
|
+
[31m+ // Proof already has correct format from CloudflareRuntime[39m
|
|
802
|
+
[31m+ // Adding optional context for AgentShield dashboard (Option A architecture)[39m
|
|
803
|
+
[31m+ const requestBody = {[39m
|
|
804
|
+
[31m+ session_id: session.id,[39m
|
|
805
|
+
[31m+ delegation_id: null,[39m
|
|
806
|
+
[31m+ proofs: [{[39m
|
|
807
|
+
[31m+ jws: proof.jws, // Already in full JWS format[39m
|
|
808
|
+
[31m+ meta: proof.meta // Already has all required fields[39m
|
|
809
|
+
[31m+ }],[39m
|
|
810
|
+
[31m+ // ✅ NEW: Optional context for dashboard integration[39m
|
|
811
|
+
[31m+ context: {[39m
|
|
812
|
+
[31m+ toolCalls: toolCallContext ? [toolCallContext] : [{[39m
|
|
813
|
+
[31m+ // Fallback if context not available from runtime[39m
|
|
814
|
+
[31m+ tool: toolName,[39m
|
|
815
|
+
[31m+ args: args,[39m
|
|
816
|
+
[31m+ result: result,[39m
|
|
817
|
+
[31m+ scopeId: proof.meta.scopeId || `${toolName}:execute`[39m
|
|
818
|
+
[31m+ }],[39m
|
|
819
|
+
[31m+ // ✅ NEW: MCP server URL for tool discovery (optional, only needed once)[39m
|
|
820
|
+
[31m+ mcpServerUrl: this.mcpServerUrl[39m
|
|
821
|
+
[31m+ }[39m
|
|
822
|
+
[31m+ };[39m
|
|
823
|
+
[31m+[39m
|
|
824
|
+
[31m+ console.log('[AgentShield] Submitting proof with context:', {[39m
|
|
825
|
+
[31m+ did: proof.meta.did,[39m
|
|
826
|
+
[31m+ sessionId: proof.meta.sessionId,[39m
|
|
827
|
+
[31m+ jwsFormat: proof.jws.split('.').length === 3 ? 'valid (3 parts)' : 'invalid',[39m
|
|
828
|
+
[31m+ contextTool: requestBody.context.toolCalls[0]?.tool,[39m
|
|
829
|
+
[31m+ contextScopeId: requestBody.context.toolCalls[0]?.scopeId,[39m
|
|
830
|
+
[31m+ mcpServerUrl: requestBody.context.mcpServerUrl || 'not-set'[39m
|
|
831
|
+
[31m+ });[39m
|
|
832
|
+
[31m+[39m
|
|
833
|
+
[31m+ const response = await fetch(`${apiUrl}/api/v1/bouncer/proofs`, {[39m
|
|
834
|
+
[31m+ method: 'POST',[39m
|
|
835
|
+
[31m+ headers: {[39m
|
|
836
|
+
[31m+ 'Content-Type': 'application/json',[39m
|
|
837
|
+
[31m+ 'Authorization': `Bearer ${apiKey}`[39m
|
|
838
|
+
[31m+ },[39m
|
|
839
|
+
[31m+ body: JSON.stringify(requestBody)[39m
|
|
840
|
+
[31m+ });[39m
|
|
841
|
+
[31m+[39m
|
|
842
|
+
[31m+ if (!response.ok) {[39m
|
|
843
|
+
[31m+ const errorText = await response.text();[39m
|
|
844
|
+
[31m+ console.error('[AgentShield] Submission failed:', response.status, errorText);[39m
|
|
845
|
+
[31m+ throw new Error(`AgentShield error: ${response.status}`);[39m
|
|
846
|
+
[31m+ }[39m
|
|
847
|
+
[31m+[39m
|
|
848
|
+
[31m+ const responseData = await response.json() as { success?: boolean; received?: number; processed?: number; accepted?: number; rejected?: number; errors?: Array<{ proofId: string; error: string }> };[39m
|
|
849
|
+
[31m+ console.log('[AgentShield] Response:', responseData);[39m
|
|
850
|
+
[31m+[39m
|
|
851
|
+
[31m+ if (responseData.accepted) {[39m
|
|
852
|
+
[31m+ console.log('[AgentShield] ✅ Proofs accepted:', responseData.accepted);[39m
|
|
853
|
+
[31m+ }[39m
|
|
854
|
+
[31m+ if (responseData.rejected) {[39m
|
|
855
|
+
[31m+ console.log('[AgentShield] ❌ Proofs rejected:', responseData.rejected);[39m
|
|
856
|
+
[31m+ }[39m
|
|
857
|
+
[31m+ }[39m
|
|
858
|
+
[31m+[39m
|
|
859
|
+
[31m+ async init() {[39m
|
|
860
|
+
[31m+ // Initialize MCP-I runtime (generates/loads identity, sets up nonce cache)[39m
|
|
861
|
+
[31m+ await this.mcpiRuntime?.initialize();[39m
|
|
862
|
+
[31m+[39m
|
|
863
|
+
[31m+ const identity = await this.mcpiRuntime?.getIdentity();[39m
|
|
864
|
+
[31m+ console.log('[MCP-I] Initialized with DID:', identity?.did);[39m
|
|
865
|
+
[31m+[39m
|
|
866
|
+
[31m+ this.server.tool([39m
|
|
867
|
+
[31m+ greetTool.name,[39m
|
|
868
|
+
[31m+ greetTool.description,[39m
|
|
869
|
+
[31m+ greetTool.inputSchema.shape,[39m
|
|
870
|
+
[31m+ async (args: { name: string }) => {[39m
|
|
871
|
+
[31m+ // Use MCP-I runtime's processToolCall for automatic proof generation[39m
|
|
872
|
+
[31m+ if (this.mcpiRuntime) {[39m
|
|
873
|
+
[31m+ try {[39m
|
|
874
|
+
[31m+ // Read MCP session ID from Claude Desktop (via agents framework)[39m
|
|
875
|
+
[31m+ let mcpSessionId: string | undefined;[39m
|
|
876
|
+
[31m+ try {[39m
|
|
877
|
+
[31m+ mcpSessionId = this.getSessionId();[39m
|
|
878
|
+
[31m+ console.log('[Delegation] Session ID from agents framework:', mcpSessionId);[39m
|
|
879
|
+
[31m+ } catch (error) {[39m
|
|
880
|
+
[31m+ console.log('[Delegation] Failed to get session ID from framework:', error);[39m
|
|
881
|
+
[31m+ mcpSessionId = undefined;[39m
|
|
882
|
+
[31m+ }[39m
|
|
883
|
+
[31m+[39m
|
|
884
|
+
[31m+ // Retrieve delegation token if available[39m
|
|
885
|
+
[31m+ const delegationToken = await this.getDelegationToken(mcpSessionId);[39m
|
|
886
|
+
[31m+[39m
|
|
887
|
+
[31m+ // Create session with proper ID (use actual session ID when available)[39m
|
|
888
|
+
[31m+ const timestamp = Date.now();[39m
|
|
889
|
+
[31m+ const sessionId = mcpSessionId || `ephemeral-${timestamp}-${Math.random().toString(36).substring(2, 10)}`;[39m
|
|
890
|
+
[31m+[39m
|
|
891
|
+
[31m+ const session = {[39m
|
|
892
|
+
[31m+ id: sessionId, // Use actual session ID from Claude Desktop[39m
|
|
893
|
+
[31m+ audience: 'https://kya.vouched.id', // CRITICAL: Must match AgentShield domain[39m
|
|
894
|
+
[31m+ agentDid: (await this.mcpiRuntime.getIdentity()).did,[39m
|
|
895
|
+
[31m+ createdAt: timestamp,[39m
|
|
896
|
+
[31m+ expiresAt: timestamp + (30 * 60 * 1000), // 30 minutes[39m
|
|
897
|
+
[31m+ delegationToken // Include delegation token if available[39m
|
|
898
|
+
[31m+ };[39m
|
|
899
|
+
[31m+[39m
|
|
900
|
+
[31m+ // Execute tool with automatic proof generation[39m
|
|
901
|
+
[31m+ const result = await this.mcpiRuntime.processToolCall([39m
|
|
902
|
+
[31m+ greetTool.name,[39m
|
|
903
|
+
[31m+ args,[39m
|
|
904
|
+
[31m+ greetTool.handler,[39m
|
|
905
|
+
[31m+ session[39m
|
|
906
|
+
[31m+ );[39m
|
|
907
|
+
[31m+[39m
|
|
908
|
+
[31m+ // Get proof in DetachedProof format[39m
|
|
909
|
+
[31m+ const proof = this.mcpiRuntime.getLastProof() as DetachedProof;[39m
|
|
910
|
+
[31m+[39m
|
|
911
|
+
[31m+ if (proof && proof.jws && proof.meta) {[39m
|
|
912
|
+
[31m+ // Log proof details (using DetachedProof format)[39m
|
|
913
|
+
[31m+ console.log('[MCP-I Proof]', {[39m
|
|
914
|
+
[31m+ tool: greetTool.name,[39m
|
|
915
|
+
[31m+ did: proof.meta.did,[39m
|
|
916
|
+
[31m+ timestamp: proof.meta.ts,[39m
|
|
917
|
+
[31m+ jws: proof.jws.substring(0, 50) + '...',[39m
|
|
918
|
+
[31m+ jwsValid: proof.jws.split('.').length === 3[39m
|
|
919
|
+
[31m+ });[39m
|
|
920
|
+
[31m+[39m
|
|
921
|
+
[31m+ // Parallelize proof operations for better performance[39m
|
|
922
|
+
[31m+ const proofOperations: Promise<void>[] = [];[39m
|
|
923
|
+
[31m+[39m
|
|
924
|
+
[31m+ // Add proof archive operation[39m
|
|
925
|
+
[31m+ if (this.proofArchive) {[39m
|
|
926
|
+
[31m+ proofOperations.push([39m
|
|
927
|
+
[31m+ this.proofArchive.store(proof, {[39m
|
|
928
|
+
[31m+ toolName: greetTool.name[39m
|
|
929
|
+
[31m+ }).then(() => {[39m
|
|
930
|
+
[31m+ console.log('[MCP-I] Proof stored in archive');[39m
|
|
931
|
+
[31m+ }).catch((archiveError: unknown) => {[39m
|
|
932
|
+
[31m+ console.error('[MCP-I] Archive error:', archiveError instanceof Error ? archiveError.message : String(archiveError));[39m
|
|
933
|
+
[31m+ })[39m
|
|
934
|
+
[31m+ );[39m
|
|
935
|
+
[31m+ }[39m
|
|
936
|
+
[31m+[39m
|
|
937
|
+
[31m+ // Add AgentShield submission operation[39m
|
|
938
|
+
[31m+ if (this.agentShieldConfig) {[39m
|
|
939
|
+
[31m+ proofOperations.push([39m
|
|
940
|
+
[31m+ this.submitProofToAgentShield(proof, session, greetTool.name, args, result)[39m
|
|
941
|
+
[31m+ .catch((err: unknown) => {[39m
|
|
942
|
+
[31m+ console.error('[MCP-I] AgentShield failed:', err instanceof Error ? err.message : String(err));[39m
|
|
943
|
+
[31m+ })[39m
|
|
944
|
+
[31m+ );[39m
|
|
945
|
+
[31m+ }[39m
|
|
946
|
+
[31m+[39m
|
|
947
|
+
[31m+ // Execute all proof operations in parallel for better performance[39m
|
|
948
|
+
[31m+ if (proofOperations.length > 0) {[39m
|
|
949
|
+
[31m+ await Promise.allSettled(proofOperations);[39m
|
|
950
|
+
[31m+ }[39m
|
|
951
|
+
[31m+[39m
|
|
952
|
+
[31m+ // Attach proof to result for MCP Inspector[39m
|
|
953
|
+
[31m+ if (result && typeof result === 'object' && result !== null) {[39m
|
|
954
|
+
[31m+ (result as Record<string, unknown>)._meta = {[39m
|
|
955
|
+
[31m+ proof: {[39m
|
|
956
|
+
[31m+ jws: proof.jws,[39m
|
|
957
|
+
[31m+ did: proof.meta.did,[39m
|
|
958
|
+
[31m+ kid: proof.meta.kid,[39m
|
|
959
|
+
[31m+ timestamp: proof.meta.ts,[39m
|
|
960
|
+
[31m+ nonce: proof.meta.nonce,[39m
|
|
961
|
+
[31m+ sessionId: proof.meta.sessionId,[39m
|
|
962
|
+
[31m+ requestHash: proof.meta.requestHash,[39m
|
|
963
|
+
[31m+ responseHash: proof.meta.responseHash[39m
|
|
964
|
+
[31m+ }[39m
|
|
965
|
+
[31m+ };[39m
|
|
966
|
+
[31m+ }[39m
|
|
967
|
+
[31m+ }[39m
|
|
968
|
+
[31m+[39m
|
|
969
|
+
[31m+ return result;[39m
|
|
970
|
+
[31m+ } catch (error: unknown) {[39m
|
|
971
|
+
[31m+ // If this is a DelegationRequiredError, re-throw it so the MCP framework can handle it properly[39m
|
|
972
|
+
[31m+ // The agents/mcp framework will format it as a proper error response to Claude Desktop[39m
|
|
973
|
+
[31m+ if (error instanceof DelegationRequiredError) {[39m
|
|
974
|
+
[31m+ console.warn('[MCP-I] Delegation required, propagating error:', {[39m
|
|
975
|
+
[31m+ tool: error.toolName,[39m
|
|
976
|
+
[31m+ requiredScopes: error.requiredScopes,[39m
|
|
977
|
+
[31m+ consentUrl: error.consentUrl[39m
|
|
978
|
+
[31m+ });[39m
|
|
979
|
+
[31m+ throw error;[39m
|
|
980
|
+
[31m+ }[39m
|
|
981
|
+
[31m+ // Check for DelegationRequiredError by name (for cases where error is not instanceof)[39m
|
|
982
|
+
[31m+ if (error && typeof error === 'object' && 'name' in error && error.name === 'DelegationRequiredError') {[39m
|
|
983
|
+
[31m+ const delegationError = error as DelegationRequiredError;[39m
|
|
984
|
+
[31m+ console.warn('[MCP-I] Delegation required, propagating error:', {[39m
|
|
985
|
+
[31m+ tool: delegationError.toolName,[39m
|
|
986
|
+
[31m+ requiredScopes: delegationError.requiredScopes,[39m
|
|
987
|
+
[31m+ consentUrl: delegationError.consentUrl[39m
|
|
988
|
+
[31m+ });[39m
|
|
989
|
+
[31m+ throw error;[39m
|
|
990
|
+
[31m+ }[39m
|
|
991
|
+
[31m+ [39m
|
|
992
|
+
[31m+ // For other errors, log and fallback to direct execution[39m
|
|
993
|
+
[31m+ console.error('[MCP-I] Failed to process tool with runtime:', error);[39m
|
|
994
|
+
[31m+ // Fallback to direct execution[39m
|
|
995
|
+
[31m+ return await greetTool.handler(args);[39m
|
|
996
|
+
[31m+ }[39m
|
|
997
|
+
[31m+ }[39m
|
|
998
|
+
[31m+[39m
|
|
999
|
+
[31m+ // Fallback if runtime not available[39m
|
|
1000
|
+
[31m+ return await greetTool.handler(args);[39m
|
|
1001
|
+
[31m+ }[39m
|
|
1002
|
+
[31m+ );[39m
|
|
1003
|
+
[31m+ }[39m
|
|
1004
|
+
[31m+ }[39m
|
|
1005
|
+
[31m+[39m
|
|
1006
|
+
[31m+ const app = new Hono();[39m
|
|
1007
|
+
[31m+[39m
|
|
1008
|
+
[31m+ // Secure CORS configuration[39m
|
|
1009
|
+
[31m+ app.use("/*", (c, next) => {[39m
|
|
1010
|
+
[31m+ const allowedOrigins = c.env.ALLOWED_ORIGINS?.split(',').map((o: string) => o.trim()) || [[39m
|
|
1011
|
+
[31m+ 'https://claude.ai',[39m
|
|
1012
|
+
[31m+ 'https://app.anthropic.com'[39m
|
|
1013
|
+
[31m+ ];[39m
|
|
1014
|
+
[31m+[39m
|
|
1015
|
+
[31m+ // Add localhost for development if not in production[39m
|
|
1016
|
+
[31m+ if (c.env.MCPI_ENV !== 'production' && !allowedOrigins.includes('http://localhost:3000')) {[39m
|
|
1017
|
+
[31m+ allowedOrigins.push('http://localhost:3000');[39m
|
|
1018
|
+
[31m+ }[39m
|
|
1019
|
+
[31m+[39m
|
|
1020
|
+
[31m+ const origin = c.req.header('Origin') || '';[39m
|
|
1021
|
+
[31m+ const isAllowed = allowedOrigins.includes(origin);[39m
|
|
1022
|
+
[31m+[39m
|
|
1023
|
+
[31m+ return cors({[39m
|
|
1024
|
+
[31m+ origin: isAllowed ? origin : allowedOrigins[0], // Default to first allowed origin if not matched[39m
|
|
1025
|
+
[31m+ allowMethods: ["GET", "POST", "PUT", "DELETE", "OPTIONS"],[39m
|
|
1026
|
+
[31m+ allowHeaders: ["Content-Type", "Authorization", "mcp-session-id", "Mcp-Session-Id", "mcp-protocol-version"],[39m
|
|
1027
|
+
[31m+ exposeHeaders: ["mcp-session-id", "Mcp-Session-Id"],[39m
|
|
1028
|
+
[31m+ credentials: true,[39m
|
|
1029
|
+
[31m+ })(c, next);[39m
|
|
1030
|
+
[31m+ });[39m
|
|
1031
|
+
[31m+[39m
|
|
1032
|
+
[31m+ app.get("/health", (c) => c.json({[39m
|
|
1033
|
+
[31m+ status: 'healthy',[39m
|
|
1034
|
+
[31m+ timestamp: new Date().toISOString(),[39m
|
|
1035
|
+
[31m+ transport: { sse: '/sse', streamableHttp: '/mcp' }[39m
|
|
1036
|
+
[31m+ }));[39m
|
|
1037
|
+
[31m+[39m
|
|
1038
|
+
[31m+ /**[39m
|
|
1039
|
+
[31m+ * Admin endpoint to clear tool protection cache[39m
|
|
1040
|
+
[31m+ *[39m
|
|
1041
|
+
[31m+ * This allows AgentShield dashboard to invalidate cached tool protection[39m
|
|
1042
|
+
[31m+ * config immediately after changing delegation requirements.[39m
|
|
1043
|
+
[31m+ *[39m
|
|
1044
|
+
[31m+ * The API key is validated by making a test call to AgentShield API.[39m
|
|
1045
|
+
[31m+ *[39m
|
|
1046
|
+
[31m+ * Usage:[39m
|
|
1047
|
+
[31m+ * POST /admin/clear-cache[39m
|
|
1048
|
+
[31m+ * Headers: Authorization: Bearer <AGENTSHIELD_ADMIN_API_KEY>[39m
|
|
1049
|
+
[31m+ * Body: { "agent_did": "did:key:z6Mk..." }[39m
|
|
1050
|
+
[31m+ *[39m
|
|
1051
|
+
[31m+ * Response:[39m
|
|
1052
|
+
[31m+ * { "success": true, "message": "Cache cleared", "agent_did": "..." }[39m
|
|
1053
|
+
[31m+ */[39m
|
|
1054
|
+
[31m+ app.post("/admin/clear-cache", async (c) => {[39m
|
|
1055
|
+
[31m+ const env = c.env as PrefixedCloudflareEnv;[39m
|
|
1056
|
+
[31m+[39m
|
|
1057
|
+
[31m+ // Parse request body first to get agent_did[39m
|
|
1058
|
+
[31m+ const body = await c.req.json().catch(() => ({}));[39m
|
|
1059
|
+
[31m+ const agentDid = body.agent_did;[39m
|
|
1060
|
+
[31m+[39m
|
|
1061
|
+
[31m+ if (!agentDid || typeof agentDid !== 'string') {[39m
|
|
1062
|
+
[31m+ return c.json({[39m
|
|
1063
|
+
[31m+ success: false,[39m
|
|
1064
|
+
[31m+ error: "Bad Request - agent_did required in body"[39m
|
|
1065
|
+
[31m+ }, 400);[39m
|
|
1066
|
+
[31m+ }[39m
|
|
1067
|
+
[31m+[39m
|
|
1068
|
+
[31m+ // Extract API key from Authorization header[39m
|
|
1069
|
+
[31m+ const authHeader = c.req.header("Authorization");[39m
|
|
1070
|
+
[31m+ if (!authHeader || !authHeader.startsWith("Bearer ")) {[39m
|
|
1071
|
+
[31m+ return c.json({[39m
|
|
1072
|
+
[31m+ success: false,[39m
|
|
1073
|
+
[31m+ error: "Unauthorized - Missing or invalid Authorization header"[39m
|
|
1074
|
+
[31m+ }, 401);[39m
|
|
1075
|
+
[31m+ }[39m
|
|
1076
|
+
[31m+[39m
|
|
1077
|
+
[31m+ const apiKey = authHeader.slice(7); // Remove "Bearer " prefix[39m
|
|
1078
|
+
[31m+[39m
|
|
1079
|
+
[31m+ // Validate API key by making a test call to AgentShield[39m
|
|
1080
|
+
[31m+ // Use the bouncer config endpoint as the validation mechanism[39m
|
|
1081
|
+
[31m+ const agentShieldUrl = env.AGENTSHIELD_API_URL || "https://kya.vouched.id";[39m
|
|
1082
|
+
[31m+ const validationUrl = `${agentShieldUrl}/api/v1/bouncer/config?agent_did=${encodeURIComponent(agentDid)}`;[39m
|
|
1083
|
+
[31m+[39m
|
|
1084
|
+
[31m+ try {[39m
|
|
1085
|
+
[31m+ const validationResponse = await fetch(validationUrl, {[39m
|
|
1086
|
+
[31m+ method: 'GET',[39m
|
|
1087
|
+
[31m+ headers: {[39m
|
|
1088
|
+
[31m+ 'Content-Type': 'application/json',[39m
|
|
1089
|
+
[31m+ 'Authorization': `Bearer ${apiKey}`[39m
|
|
1090
|
+
[31m+ }[39m
|
|
1091
|
+
[31m+ });[39m
|
|
1092
|
+
[31m+[39m
|
|
1093
|
+
[31m+ if (!validationResponse.ok) {[39m
|
|
1094
|
+
[31m+ console.warn('[Admin] API key validation failed:', validationResponse.status);[39m
|
|
1095
|
+
[31m+ return c.json({[39m
|
|
1096
|
+
[31m+ success: false,[39m
|
|
1097
|
+
[31m+ error: "Unauthorized - Invalid API key"[39m
|
|
1098
|
+
[31m+ }, 401);[39m
|
|
1099
|
+
[31m+ }[39m
|
|
1100
|
+
[31m+[39m
|
|
1101
|
+
[31m+ // API key is valid, proceed to clear cache[39m
|
|
1102
|
+
[31m+ console.log('[Admin] API key validated successfully');[39m
|
|
1103
|
+
[31m+ } catch (error) {[39m
|
|
1104
|
+
[31m+ console.error('[Admin] API key validation error:', error);[39m
|
|
1105
|
+
[31m+ return c.json({[39m
|
|
1106
|
+
[31m+ success: false,[39m
|
|
1107
|
+
[31m+ error: "Failed to validate API key with AgentShield"[39m
|
|
1108
|
+
[31m+ }, 500);[39m
|
|
1109
|
+
[31m+ }[39m
|
|
1110
|
+
[31m+[39m
|
|
1111
|
+
[31m+ // Clear cache from KV[39m
|
|
1112
|
+
[31m+ // Cache key format: KVToolProtectionCache uses 'tool-protection:' prefix + agentDid[39m
|
|
1113
|
+
[31m+ // Since we're accessing KV directly (not through cache service), we need the full key[39m
|
|
1114
|
+
[31m+ const cacheKey = `tool-protection:${agentDid}`;[39m
|
|
1115
|
+
[31m+ const kvNamespace = env.TESTPROJECT_TOOL_PROTECTION_KV;[39m
|
|
1116
|
+
[31m+[39m
|
|
1117
|
+
[31m+ if (!kvNamespace) {[39m
|
|
1118
|
+
[31m+ return c.json({[39m
|
|
1119
|
+
[31m+ success: false,[39m
|
|
1120
|
+
[31m+ error: "Tool protection KV namespace not configured"[39m
|
|
1121
|
+
[31m+ }, 500);[39m
|
|
1122
|
+
[31m+ }[39m
|
|
1123
|
+
[31m+[39m
|
|
1124
|
+
[31m+ try {[39m
|
|
1125
|
+
[31m+ // Log before and after for debugging[39m
|
|
1126
|
+
[31m+ const before = await kvNamespace.get(cacheKey);[39m
|
|
1127
|
+
[31m+ await kvNamespace.delete(cacheKey);[39m
|
|
1128
|
+
[31m+ const after = await kvNamespace.get(cacheKey);[39m
|
|
1129
|
+
[31m+ [39m
|
|
1130
|
+
[31m+ console.log('[Admin] Cache clear operation', {[39m
|
|
1131
|
+
[31m+ agentDid: agentDid.slice(0, 20) + '...',[39m
|
|
1132
|
+
[31m+ cacheKey,[39m
|
|
1133
|
+
[31m+ hadValue: !!before,[39m
|
|
1134
|
+
[31m+ cleared: !after,[39m
|
|
1135
|
+
[31m+ });[39m
|
|
1136
|
+
[31m+ [39m
|
|
1137
|
+
[31m+ return c.json({[39m
|
|
1138
|
+
[31m+ success: true,[39m
|
|
1139
|
+
[31m+ message: "Cache cleared successfully. Next tool call will fetch fresh config from AgentShield.",[39m
|
|
1140
|
+
[31m+ agent_did: agentDid,[39m
|
|
1141
|
+
[31m+ cache_key: cacheKey,[39m
|
|
1142
|
+
[31m+ had_value: !!before,[39m
|
|
1143
|
+
[31m+ });[39m
|
|
1144
|
+
[31m+ } catch (error) {[39m
|
|
1145
|
+
[31m+ console.error('[Admin] Failed to clear cache:', error);[39m
|
|
1146
|
+
[31m+ return c.json({[39m
|
|
1147
|
+
[31m+ success: false,[39m
|
|
1148
|
+
[31m+ error: "Internal error clearing cache",[39m
|
|
1149
|
+
[31m+ details: error instanceof Error ? error.message : String(error)[39m
|
|
1150
|
+
[31m+ }, 500);[39m
|
|
1151
|
+
[31m+ }[39m
|
|
1152
|
+
[31m+ });[39m
|
|
1153
|
+
[31m+[39m
|
|
1154
|
+
[31m+ /**[39m
|
|
1155
|
+
[31m+ * OAuth Authorization Code Flow callback handler[39m
|
|
1156
|
+
[31m+ *[39m
|
|
1157
|
+
[31m+ * Handles the redirect from AgentShield after user approves delegation.[39m
|
|
1158
|
+
[31m+ * Exchanges authorization code for delegation token and stores in KV.[39m
|
|
1159
|
+
[31m+ *[39m
|
|
1160
|
+
[31m+ * This endpoint is called by AgentShield after user approves delegation:[39m
|
|
1161
|
+
[31m+ * 1. Receives authorization code and state from query params[39m
|
|
1162
|
+
[31m+ * 2. Exchanges code for delegation token with AgentShield API[39m
|
|
1163
|
+
[31m+ * 3. Stores token in KV with session ID as key[39m
|
|
1164
|
+
[31m+ * 4. Returns success page to user[39m
|
|
1165
|
+
[31m+ */[39m
|
|
1166
|
+
[31m+ app.get('/oauth/callback', (c) => {[39m
|
|
1167
|
+
[31m+ const env = c.env as PrefixedCloudflareEnv;[39m
|
|
1168
|
+
[31m+ return createOAuthCallbackHandler({[39m
|
|
1169
|
+
[31m+ agentShieldApiUrl: env.AGENTSHIELD_API_URL || 'https://kya.vouched.id',[39m
|
|
1170
|
+
[31m+ delegationStorage: env.TESTPROJECT_DELEGATION_STORAGE,[39m
|
|
1171
|
+
[31m+ autoClose: true,[39m
|
|
1172
|
+
[31m+ autoCloseDelay: 5000[39m
|
|
1173
|
+
[31m+ })(c);[39m
|
|
1174
|
+
[31m+ });[39m
|
|
1175
|
+
[31m+[39m
|
|
1176
|
+
[31m+ // Multi-instance DO routing using McpAgent's getInstanceId() override[39m
|
|
1177
|
+
[31m+ // The TestprojectMCP class overrides getInstanceId() to enable session-based[39m
|
|
1178
|
+
[31m+ // or shard-based routing while preserving PartyServer compatibility.[39m
|
|
1179
|
+
[31m+ //[39m
|
|
1180
|
+
[31m+ // Routing strategies (configured via DO_ROUTING_STRATEGY env var):[39m
|
|
1181
|
+
[31m+ // - 'session' (default): One DO per MCP session - ensures data isolation[39m
|
|
1182
|
+
[31m+ // - 'shard': Hash-based distribution across N shards - for high load[39m
|
|
1183
|
+
[31m+ //[39m
|
|
1184
|
+
[31m+ // McpAgent automatically routes to the correct DO instance using the ID[39m
|
|
1185
|
+
[31m+ // returned by getInstanceId(), maintaining full routing context.[39m
|
|
1186
|
+
[31m+ app.mount("/sse", TestprojectMCP.serveSSE("/sse").fetch, { replaceRequest: false });[39m
|
|
1187
|
+
[31m+ app.mount("/mcp", TestprojectMCP.serve("/mcp").fetch, { replaceRequest: false });[39m
|
|
1188
|
+
[31m+[39m
|
|
1189
|
+
[31m+ export default app;[39m
|
|
1190
|
+
[31m+[39m
|
|
1191
|
+
|
|
1192
|
+
[36m [2m❯[22m src/__tests__/cloudflare-template.test.ts:[2m149:28[22m[39m
|
|
1193
|
+
[90m147| [39m
|
|
1194
|
+
[90m148| [39m [90m// Check that warning is logged in index.ts[39m
|
|
1195
|
+
[90m149| [39m [34mexpect[39m(indexContent)[33m.[39m[34mtoContain[39m([32m"Warning: MCP_SERVER_URL not configured"[39m)[33m;[39m
|
|
1196
|
+
[90m | [39m [31m^[39m
|
|
1197
|
+
[90m150| [39m })[33m;[39m
|
|
1198
|
+
[90m151| [39m
|
|
1199
|
+
|
|
1200
|
+
[31m[2m⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[1/2]⎯[22m[39m
|
|
1201
|
+
|
|
1202
|
+
[41m[1m FAIL [22m[49m test-cloudflare/tests/do-routing.test.ts[2m > [22mDurable Object Multi-Instance Routing[2m > [22mPerformance Characteristics[2m > [22mshard routing should have O(n) complexity for hash
|
|
1203
|
+
[31m[1mAssertionError[22m: expected 145.8617079999999 to be less than 100[39m
|
|
1204
|
+
[36m [2m❯[22m test-cloudflare/tests/do-routing.test.ts:[2m263:44[22m[39m
|
|
1205
|
+
[90m261| [39m [34mexpect[39m(shortDuration)[33m.[39m[34mtoBeGreaterThan[39m([34m0[39m)[33m;[39m
|
|
1206
|
+
[90m262| [39m [90m// Both operations should complete in reasonable time (< 100ms total for 1000 iterations)[39m
|
|
1207
|
+
[90m263| [39m [34mexpect[39m(longDuration [33m+[39m shortDuration)[33m.[39m[34mtoBeLessThan[39m([34m100[39m)[33m;[39m
|
|
1208
|
+
[90m | [39m [31m^[39m
|
|
1209
|
+
[90m264| [39m })[33m;[39m
|
|
1210
|
+
[90m265| [39m })[33m;[39m
|
|
1211
|
+
|
|
1212
|
+
[31m[2m⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[2/2]⎯[22m[39m
|
|
1213
|
+
|
|
1214
|
+
|
|
1215
|
+
[2m Test Files [22m [1m[31m2 failed[39m[22m[2m | [22m[1m[32m10 passed[39m[22m[90m (12)[39m
|
|
1216
|
+
[2m Tests [22m [1m[31m2 failed[39m[22m[2m | [22m[1m[32m235 passed[39m[22m[90m (237)[39m
|
|
1217
|
+
[2m Start at [22m 14:20:47
|
|
1218
|
+
[2m Duration [22m 1.25s[2m (transform 1.21s, setup 0ms, collect 2.23s, tests 1.61s, environment 1ms, prepare 1.06s)[22m
|
|
1219
|
+
|
|
1220
|
+
[?25h[41m[30m ELIFECYCLE [39m[49m [31mCommand failed with exit code 1.[39m
|