@portel/photon 1.26.1 → 1.28.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 +33 -0
- package/dist/auto-ui/beam/routes/api-daemon.d.ts +1 -0
- package/dist/auto-ui/beam/routes/api-daemon.d.ts.map +1 -1
- package/dist/auto-ui/beam/routes/api-daemon.js +35 -1
- package/dist/auto-ui/beam/routes/api-daemon.js.map +1 -1
- package/dist/beam-form.bundle.js +41 -1
- package/dist/beam-form.bundle.js.map +2 -2
- package/dist/beam.bundle.js +1661 -252
- package/dist/beam.bundle.js.map +4 -4
- package/dist/cli/commands/daemon.d.ts.map +1 -1
- package/dist/cli/commands/daemon.js +157 -0
- package/dist/cli/commands/daemon.js.map +1 -1
- package/dist/cli/commands/update.d.ts.map +1 -1
- package/dist/cli/commands/update.js +7 -8
- package/dist/cli/commands/update.js.map +1 -1
- package/dist/daemon/client.d.ts +1 -0
- package/dist/daemon/client.d.ts.map +1 -1
- package/dist/daemon/client.js +110 -23
- package/dist/daemon/client.js.map +1 -1
- package/dist/daemon/in-process-bridge.d.ts +29 -0
- package/dist/daemon/in-process-bridge.d.ts.map +1 -0
- package/dist/daemon/in-process-bridge.js +26 -0
- package/dist/daemon/in-process-bridge.js.map +1 -0
- package/dist/daemon/manager.d.ts +103 -1
- package/dist/daemon/manager.d.ts.map +1 -1
- package/dist/daemon/manager.js +313 -92
- package/dist/daemon/manager.js.map +1 -1
- package/dist/daemon/protocol.d.ts +1 -1
- package/dist/daemon/protocol.d.ts.map +1 -1
- package/dist/daemon/protocol.js +1 -0
- package/dist/daemon/protocol.js.map +1 -1
- package/dist/daemon/server.js +859 -38
- package/dist/daemon/server.js.map +1 -1
- package/dist/loader.d.ts.map +1 -1
- package/dist/loader.js +39 -13
- package/dist/loader.js.map +1 -1
- package/dist/sample-augmenter.d.ts +84 -0
- package/dist/sample-augmenter.d.ts.map +1 -0
- package/dist/sample-augmenter.js +164 -0
- package/dist/sample-augmenter.js.map +1 -0
- package/dist/shared/npm-registry.d.ts +30 -0
- package/dist/shared/npm-registry.d.ts.map +1 -0
- package/dist/shared/npm-registry.js +97 -0
- package/dist/shared/npm-registry.js.map +1 -0
- package/dist/version-notify.d.ts +5 -0
- package/dist/version-notify.d.ts.map +1 -1
- package/dist/version-notify.js +46 -23
- package/dist/version-notify.js.map +1 -1
- package/package.json +1 -1
- package/templates/cloudflare/worker.ts.template +94 -22
|
@@ -535,6 +535,65 @@ function spreadArgs(toolDef: any, args: Record<string, unknown>): unknown[] {
|
|
|
535
535
|
return [args];
|
|
536
536
|
}
|
|
537
537
|
|
|
538
|
+
/**
|
|
539
|
+
* Match a request against the `@get`/`@post` route table. Two passes:
|
|
540
|
+
* exact paths first (cheaper, also gives them precedence over patterns
|
|
541
|
+
* that would also match), then `:param` patterns. Returns the matched
|
|
542
|
+
* route plus any extracted path params, or null when nothing matches.
|
|
543
|
+
*
|
|
544
|
+
* Patterns: `/b/:token` matches `/b/abc123` -> { token: 'abc123' }.
|
|
545
|
+
* Segment counts must be equal -- `/b/:token` does not match `/b/x/y`.
|
|
546
|
+
*
|
|
547
|
+
* Tested in tests/cf-template-route-matcher.test.ts. Keep the two
|
|
548
|
+
* definitions in sync if either is edited.
|
|
549
|
+
*/
|
|
550
|
+
function matchHttpRoute(
|
|
551
|
+
routes: { method: string; path: string; handler: string }[],
|
|
552
|
+
method: string,
|
|
553
|
+
pathname: string
|
|
554
|
+
): {
|
|
555
|
+
route: { method: string; path: string; handler: string };
|
|
556
|
+
params: Record<string, string>;
|
|
557
|
+
} | null {
|
|
558
|
+
for (const route of routes) {
|
|
559
|
+
if (route.method !== method) continue;
|
|
560
|
+
if (!route.path.includes(':') && route.path === pathname) {
|
|
561
|
+
return { route, params: {} };
|
|
562
|
+
}
|
|
563
|
+
}
|
|
564
|
+
for (const route of routes) {
|
|
565
|
+
if (route.method !== method) continue;
|
|
566
|
+
if (!route.path.includes(':')) continue;
|
|
567
|
+
const params = matchPathPattern(route.path, pathname);
|
|
568
|
+
if (params) return { route, params };
|
|
569
|
+
}
|
|
570
|
+
return null;
|
|
571
|
+
}
|
|
572
|
+
|
|
573
|
+
function matchPathPattern(
|
|
574
|
+
pattern: string,
|
|
575
|
+
pathname: string
|
|
576
|
+
): Record<string, string> | null {
|
|
577
|
+
const patternParts = pattern.split('/').filter(Boolean);
|
|
578
|
+
const pathParts = pathname.split('/').filter(Boolean);
|
|
579
|
+
if (patternParts.length !== pathParts.length) return null;
|
|
580
|
+
const params: Record<string, string> = {};
|
|
581
|
+
for (let i = 0; i < patternParts.length; i++) {
|
|
582
|
+
const pp = patternParts[i];
|
|
583
|
+
const rp = pathParts[i];
|
|
584
|
+
if (pp.startsWith(':')) {
|
|
585
|
+
try {
|
|
586
|
+
params[pp.slice(1)] = decodeURIComponent(rp);
|
|
587
|
+
} catch {
|
|
588
|
+
return null;
|
|
589
|
+
}
|
|
590
|
+
} else if (pp !== rp) {
|
|
591
|
+
return null;
|
|
592
|
+
}
|
|
593
|
+
}
|
|
594
|
+
return params;
|
|
595
|
+
}
|
|
596
|
+
|
|
538
597
|
async function handleMCPRequest(
|
|
539
598
|
request: any,
|
|
540
599
|
photon: any,
|
|
@@ -718,23 +777,35 @@ abstract class BasePhotonDO extends DurableObject<Env> {
|
|
|
718
777
|
return new Response(null, { status: 204, headers: CORS_HEADERS });
|
|
719
778
|
}
|
|
720
779
|
|
|
721
|
-
// Info endpoint
|
|
780
|
+
// Info endpoint with content negotiation. A photon may declare
|
|
781
|
+
// `@get /` to serve a public HTML homepage; in that case JSON
|
|
782
|
+
// requests still get the discovery payload and everything else
|
|
783
|
+
// (browsers, default curl, anything not asking for JSON) falls
|
|
784
|
+
// through to the photon's handler in the route table below.
|
|
722
785
|
if (url.pathname === '/' && request.method === 'GET') {
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
transport: 'streamable-http',
|
|
728
|
-
runtime: 'cloudflare-workers',
|
|
729
|
-
endpoints: {
|
|
730
|
-
mcp: '/mcp',
|
|
731
|
-
events: '/events?channel=<name>',
|
|
732
|
-
...(DEV_MODE ? { playground: '/playground' } : {}),
|
|
733
|
-
},
|
|
734
|
-
tools: this.toolDefinitions.length,
|
|
735
|
-
},
|
|
736
|
-
{ headers: CORS_HEADERS }
|
|
786
|
+
const accept = (request.headers.get('accept') || '').toLowerCase();
|
|
787
|
+
const wantsJson = accept.includes('application/json');
|
|
788
|
+
const userHomeRoute = this.httpRoutes.find(
|
|
789
|
+
(r) => r.method === 'GET' && r.path === '/'
|
|
737
790
|
);
|
|
791
|
+
if (wantsJson || !userHomeRoute) {
|
|
792
|
+
return Response.json(
|
|
793
|
+
{
|
|
794
|
+
name: this.photonName,
|
|
795
|
+
instance: this.instanceName,
|
|
796
|
+
transport: 'streamable-http',
|
|
797
|
+
runtime: 'cloudflare-workers',
|
|
798
|
+
endpoints: {
|
|
799
|
+
mcp: '/mcp',
|
|
800
|
+
events: '/events?channel=<name>',
|
|
801
|
+
...(DEV_MODE ? { playground: '/playground' } : {}),
|
|
802
|
+
},
|
|
803
|
+
tools: this.toolDefinitions.length,
|
|
804
|
+
},
|
|
805
|
+
{ headers: CORS_HEADERS }
|
|
806
|
+
);
|
|
807
|
+
}
|
|
808
|
+
// Fall through to the @get/@post route table (handles `@get /`).
|
|
738
809
|
}
|
|
739
810
|
|
|
740
811
|
// Dev-only endpoints
|
|
@@ -767,15 +838,16 @@ abstract class BasePhotonDO extends DurableObject<Env> {
|
|
|
767
838
|
}
|
|
768
839
|
}
|
|
769
840
|
|
|
770
|
-
// @get / @post HTTP routes — dispatch to photon method, bypass MCP
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
841
|
+
// @get / @post HTTP routes — dispatch to photon method, bypass MCP.
|
|
842
|
+
// Handler signature: (request: Request, params?: Record<string, string>)
|
|
843
|
+
// — the second arg carries `:param` values extracted from the path so a
|
|
844
|
+
// route declared `@get /b/:token` receives `{ token }`.
|
|
845
|
+
const matchedRoute = matchHttpRoute(this.httpRoutes, request.method, url.pathname);
|
|
846
|
+
if (matchedRoute) {
|
|
847
|
+
const fn = (this.photon as any)[matchedRoute.route.handler];
|
|
776
848
|
if (typeof fn === 'function') {
|
|
777
849
|
try {
|
|
778
|
-
const response = await fn.call(this.photon, request);
|
|
850
|
+
const response = await fn.call(this.photon, request, matchedRoute.params);
|
|
779
851
|
if (response instanceof Response) return response;
|
|
780
852
|
return Response.json(response, { headers: CORS_HEADERS });
|
|
781
853
|
} catch (error: any) {
|