@opengeni/codemode 0.4.22 → 0.4.27-canary.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 +44 -4
- package/dist/declarations.d.ts +2 -2
- package/dist/index.d.ts +29 -41
- package/dist/index.js +283 -474
- package/dist/index.js.map +1 -1
- package/dist/site.d.ts +9 -0
- package/package.json +3 -3
- package/src/declarations.ts +13 -326
- package/src/index.ts +288 -317
- package/src/site.ts +131 -0
package/src/site.ts
ADDED
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
import { randomUUID } from "node:crypto";
|
|
2
|
+
import { generateToolDeclarations } from "@opengeni/tool-gateway";
|
|
3
|
+
|
|
4
|
+
import { CodemodeClient, CodemodeTransportError } from "./index";
|
|
5
|
+
import { environmentCodemodeClient, type CodemodeClientProvider } from "./environment";
|
|
6
|
+
|
|
7
|
+
export const CODEMODE_SITE_LOCAL_PATH = "/__opengeni/site-tools" as const;
|
|
8
|
+
|
|
9
|
+
export type CodemodeSiteRequestHandler = (request: Request) => Promise<Response>;
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Same-origin local Site preview adapter. The Bun host retains the exact
|
|
13
|
+
* attempt bearer; browser code receives only the ordinary Site tool protocol.
|
|
14
|
+
*/
|
|
15
|
+
export function createCodemodeSiteRequestHandler(
|
|
16
|
+
client: CodemodeClient | CodemodeClientProvider = () => environmentCodemodeClient(),
|
|
17
|
+
): CodemodeSiteRequestHandler {
|
|
18
|
+
const provide = typeof client === "function" ? client : () => client;
|
|
19
|
+
return async (request) => {
|
|
20
|
+
try {
|
|
21
|
+
const active = await provide();
|
|
22
|
+
const pathname = new URL(request.url).pathname;
|
|
23
|
+
if (request.method === "GET" && pathname === `${CODEMODE_SITE_LOCAL_PATH}/catalog`) {
|
|
24
|
+
const catalog = await active.catalog({ signal: request.signal });
|
|
25
|
+
return Response.json(projectSiteCatalog(catalog));
|
|
26
|
+
}
|
|
27
|
+
if (request.method === "GET" && pathname === `${CODEMODE_SITE_LOCAL_PATH}/declarations`) {
|
|
28
|
+
const catalog = await active.catalog({ signal: request.signal });
|
|
29
|
+
return Response.json({
|
|
30
|
+
catalogDigest: catalog.digest,
|
|
31
|
+
moduleSpecifier: "@opengeni/sdk",
|
|
32
|
+
source: generateToolDeclarations(
|
|
33
|
+
{ digest: catalog.digest, entries: catalog.entries },
|
|
34
|
+
{
|
|
35
|
+
moduleSpecifier: "@opengeni/sdk",
|
|
36
|
+
interfaceName: "OpenGeniGeneratedTools",
|
|
37
|
+
callOptionsType: "OpenGeniToolCallOptions",
|
|
38
|
+
fallbackResultType: "ToolGatewayResult",
|
|
39
|
+
generatedBy: "@opengeni/codemode local Site preview",
|
|
40
|
+
catalogDigestLabel: "Attempt catalog digest",
|
|
41
|
+
},
|
|
42
|
+
),
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
if (request.method === "POST" && pathname === `${CODEMODE_SITE_LOCAL_PATH}/calls`) {
|
|
46
|
+
const body = await request.json();
|
|
47
|
+
if (!isSiteCall(body)) return siteError(400, "invalid_request", "Invalid Site tool call");
|
|
48
|
+
const catalog = await active.catalog({ signal: request.signal });
|
|
49
|
+
if (body.catalogDigest !== catalog.digest) {
|
|
50
|
+
return siteError(409, "catalog_stale", "The local Site tool catalog changed", true);
|
|
51
|
+
}
|
|
52
|
+
const operationId = body.operationId ?? randomUUID();
|
|
53
|
+
const result = await active.call(body.identity, body.arguments, {
|
|
54
|
+
operationId,
|
|
55
|
+
signal: request.signal,
|
|
56
|
+
});
|
|
57
|
+
return Response.json({
|
|
58
|
+
operationId,
|
|
59
|
+
catalogDigest: catalog.digest,
|
|
60
|
+
result,
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
return siteError(404, "not_found", "Local Site tool endpoint not found");
|
|
64
|
+
} catch (error) {
|
|
65
|
+
if (error instanceof CodemodeTransportError) {
|
|
66
|
+
return siteError(
|
|
67
|
+
error.status && error.status >= 400 && error.status <= 599 ? error.status : 502,
|
|
68
|
+
error.remoteCode ?? error.code,
|
|
69
|
+
error.message,
|
|
70
|
+
error.retryable === true,
|
|
71
|
+
error.outcomeUnknown === true,
|
|
72
|
+
);
|
|
73
|
+
}
|
|
74
|
+
return siteError(
|
|
75
|
+
500,
|
|
76
|
+
"local_codemode_error",
|
|
77
|
+
error instanceof Error ? error.message : "Local Site tool request failed",
|
|
78
|
+
);
|
|
79
|
+
}
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
function projectSiteCatalog(catalog: Awaited<ReturnType<CodemodeClient["catalog"]>>) {
|
|
84
|
+
return {
|
|
85
|
+
version: catalog.version,
|
|
86
|
+
generation: catalog.generation,
|
|
87
|
+
digest: catalog.digest,
|
|
88
|
+
createdAt: catalog.createdAt,
|
|
89
|
+
entries: catalog.entries,
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
function isSiteCall(value: unknown): value is {
|
|
94
|
+
operationId?: string;
|
|
95
|
+
catalogDigest: string;
|
|
96
|
+
identity: { serverId: string; toolName: string };
|
|
97
|
+
arguments: Record<string, unknown>;
|
|
98
|
+
} {
|
|
99
|
+
if (!isRecord(value) || typeof value.catalogDigest !== "string") return false;
|
|
100
|
+
if (value.operationId !== undefined && typeof value.operationId !== "string") return false;
|
|
101
|
+
return (
|
|
102
|
+
isRecord(value.identity) &&
|
|
103
|
+
typeof value.identity.serverId === "string" &&
|
|
104
|
+
typeof value.identity.toolName === "string" &&
|
|
105
|
+
isRecord(value.arguments)
|
|
106
|
+
);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
function siteError(
|
|
110
|
+
status: number,
|
|
111
|
+
code: string,
|
|
112
|
+
message: string,
|
|
113
|
+
retryable = false,
|
|
114
|
+
outcomeUnknown = false,
|
|
115
|
+
): Response {
|
|
116
|
+
return Response.json(
|
|
117
|
+
{
|
|
118
|
+
error: {
|
|
119
|
+
code,
|
|
120
|
+
message,
|
|
121
|
+
retryable,
|
|
122
|
+
...(outcomeUnknown ? { outcomeUnknown: true } : {}),
|
|
123
|
+
},
|
|
124
|
+
},
|
|
125
|
+
{ status },
|
|
126
|
+
);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
function isRecord(value: unknown): value is Record<string, unknown> {
|
|
130
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
131
|
+
}
|