@dbx-tools/appkit-memory 0.0.0-stage → 0.9.132

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.
Files changed (42) hide show
  1. package/LICENSE +202 -0
  2. package/README.md +116 -2
  3. package/index.ts +17 -0
  4. package/lib/index.d.ts +13 -0
  5. package/lib/index.js +14 -0
  6. package/lib/smoke/mastra-tool.d.ts +1 -0
  7. package/lib/smoke/mastra-tool.js +46 -0
  8. package/lib/src/_contracts.d.ts +71 -0
  9. package/lib/src/_contracts.js +63 -0
  10. package/lib/src/_mastra.d.ts +11 -0
  11. package/lib/src/_mastra.js +66 -0
  12. package/lib/src/config.d.ts +70 -0
  13. package/lib/src/config.js +87 -0
  14. package/lib/src/databricks/_runtime.d.ts +18 -0
  15. package/lib/src/databricks/_runtime.js +79 -0
  16. package/lib/src/databricks/client.d.ts +48 -0
  17. package/lib/src/databricks/client.js +174 -0
  18. package/lib/src/databricks/index.d.ts +3 -0
  19. package/lib/src/databricks/index.js +6 -0
  20. package/lib/src/graphiti/_backend.d.ts +9 -0
  21. package/lib/src/graphiti/_backend.js +214 -0
  22. package/lib/src/graphiti/index.d.ts +3 -0
  23. package/lib/src/graphiti/index.js +6 -0
  24. package/lib/src/graphiti/options.d.ts +7 -0
  25. package/lib/src/graphiti/options.js +7 -0
  26. package/lib/src/graphiti/runtime.d.ts +49 -0
  27. package/lib/src/graphiti/runtime.js +170 -0
  28. package/lib/src/plugin.d.ts +38 -0
  29. package/lib/src/plugin.js +196 -0
  30. package/lib/tsconfig.tsbuildinfo +1 -0
  31. package/package.json +104 -4
  32. package/src/_contracts.ts +107 -0
  33. package/src/_mastra.ts +80 -0
  34. package/src/config.ts +134 -0
  35. package/src/databricks/_runtime.ts +103 -0
  36. package/src/databricks/client.ts +251 -0
  37. package/src/databricks/index.ts +7 -0
  38. package/src/graphiti/_backend.ts +282 -0
  39. package/src/graphiti/index.ts +7 -0
  40. package/src/graphiti/options.ts +17 -0
  41. package/src/graphiti/runtime.ts +261 -0
  42. package/src/plugin.ts +254 -0
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Lazy Graphiti implementation of the backend-neutral memory contract.
3
+ *
4
+ * @module
5
+ */
6
+ import { type GraphitiMemoryBackend } from "../_contracts.ts";
7
+ import { type GraphitiOptions } from "./options.ts";
8
+ /** Start a fully ready Graphiti backend for the first fallback operation. */
9
+ export declare function startGraphitiBackend(options: GraphitiOptions, signal?: AbortSignal): Promise<GraphitiMemoryBackend>;
@@ -0,0 +1,214 @@
1
+ /**
2
+ * Lazy Graphiti implementation of the backend-neutral memory contract.
3
+ *
4
+ * @module
5
+ */
6
+ import { createHash, randomBytes } from "node:crypto";
7
+ import { createServer } from "node:net";
8
+ import { ConfigurationError } from "@databricks/appkit";
9
+ import { openApiTools } from "@dbx-tools/appkit/openapi-tool";
10
+ import { profile as authProfile } from "@dbx-tools/auth";
11
+ import { configUtils } from "@dbx-tools/core";
12
+ import { z } from "zod";
13
+ import { graphitiOptionOverrides, graphitiOptionsFromEnvironment, resolveGraphitiOptions, } from "./options.js";
14
+ import { createGraphitiChildProcess, graphitiHealthCheck, graphitiHttpUrl, graphitiRequestHeaders, } from "./runtime.js";
15
+ const GraphitiFactSchema = z
16
+ .object({
17
+ name: z.string().optional().describe("Graphiti fact name."),
18
+ fact: z.string().describe("Retrieved graph fact."),
19
+ })
20
+ .loose()
21
+ .describe("Graphiti fact search result.");
22
+ const GraphitiFactSearchSchema = z
23
+ .object({
24
+ facts: z.array(GraphitiFactSchema).optional().describe("Matching graph facts."),
25
+ error: z.string().optional().describe("Graphiti operation error."),
26
+ })
27
+ .loose()
28
+ .describe("Graphiti fact search response.");
29
+ const GraphitiWriteSchema = z
30
+ .object({
31
+ message: z.string().optional().describe("Graphiti write confirmation."),
32
+ error: z.string().optional().describe("Graphiti operation error."),
33
+ })
34
+ .loose()
35
+ .describe("Graphiti write response.");
36
+ class GraphitiBackend {
37
+ options;
38
+ child;
39
+ writeTool;
40
+ recallTool;
41
+ constructor(options, child, writeTool, recallTool) {
42
+ this.options = options;
43
+ this.child = child;
44
+ this.writeTool = writeTool;
45
+ this.recallTool = recallTool;
46
+ }
47
+ get running() {
48
+ return ((this.child.exitCode === null || this.child.exitCode === undefined) &&
49
+ (this.child.signalCode === null || this.child.signalCode === undefined));
50
+ }
51
+ async remember(actorId, input, signal) {
52
+ await this.write(actorId, {
53
+ name: input.path,
54
+ episode_body: input.content,
55
+ source: "text",
56
+ source_description: input.description ? `${input.path}: ${input.description}` : input.path,
57
+ }, signal);
58
+ return {
59
+ backend: "graphiti",
60
+ memory: {
61
+ path: input.path,
62
+ content: input.content,
63
+ ...(input.description ? { description: input.description } : {}),
64
+ },
65
+ };
66
+ }
67
+ async recall(actorId, input, signal) {
68
+ const response = GraphitiFactSearchSchema.parse(await this.request(this.recallTool, {
69
+ query: input.query,
70
+ max_facts: input.limit,
71
+ group_ids: [userScope(actorId)],
72
+ }, signal));
73
+ if (response.error)
74
+ throw new Error(response.error);
75
+ return {
76
+ backend: "graphiti",
77
+ memories: (response.facts ?? []).map((fact) => ({
78
+ content: fact.fact,
79
+ ...(fact.name ? { description: fact.name } : {}),
80
+ })),
81
+ };
82
+ }
83
+ async saveTurn(turn, signal) {
84
+ await this.write(turn.actorId, {
85
+ name: `Mastra turn ${turn.agentId}/${turn.threadId}`,
86
+ episode_body: `User: ${turn.user}\n\nAssistant: ${turn.assistant}`,
87
+ source: "message",
88
+ source_description: `Completed ${turn.agentId} conversation turn`,
89
+ }, signal);
90
+ }
91
+ shutdown() {
92
+ return this.child.shutdown();
93
+ }
94
+ async write(actorId, args, signal) {
95
+ const response = GraphitiWriteSchema.parse(await this.request(this.writeTool, { ...args, group_id: userScope(actorId) }, signal));
96
+ if (response.error)
97
+ throw new Error(response.error);
98
+ }
99
+ async request(tool, args, signal) {
100
+ if (!this.running)
101
+ throw new Error("Graphiti sidecar is not running");
102
+ const response = await fetch(tool.url, {
103
+ method: tool.method,
104
+ headers: {
105
+ ...graphitiRequestHeaders(this.options),
106
+ "content-type": "application/json",
107
+ },
108
+ body: JSON.stringify(args),
109
+ signal,
110
+ });
111
+ if (!response.ok) {
112
+ throw new Error(`Graphiti operation ${tool.id} failed with HTTP ${response.status}: ${await response.text()}`);
113
+ }
114
+ return response.json();
115
+ }
116
+ }
117
+ /** Start a fully ready Graphiti backend for the first fallback operation. */
118
+ export async function startGraphitiBackend(options, signal) {
119
+ const configured = resolveGraphitiConfig(options);
120
+ if (configured.listen.scheme !== "tcp") {
121
+ throw new Error("AppKit memory requires a TCP Graphiti listener");
122
+ }
123
+ const [graphitiPort] = await distinctPorts(configUtils.port(undefined, "DATABRICKS_APP_PORT", 8000, configUtils.ENV_ONLY), configured.listen.port);
124
+ const resolved = resolveGraphitiOptions({
125
+ ...configured,
126
+ bearer: randomBytes(32).toString("base64url"),
127
+ listen: { ...configured.listen, port: graphitiPort },
128
+ });
129
+ let tools;
130
+ const { child } = await createGraphitiChildProcess({
131
+ ...resolved,
132
+ ...(signal ? { signal } : {}),
133
+ healthCheck: async ({ signal }) => {
134
+ try {
135
+ if (!(await graphitiHealthCheck(resolved, signal)))
136
+ return false;
137
+ const loaded = await openApiTools(graphitiHttpUrl(resolved, "/openapi.json"), {
138
+ signal,
139
+ headers: graphitiRequestHeaders(resolved),
140
+ });
141
+ tools = [
142
+ requiredOperation(loaded, "add_memory_sync"),
143
+ requiredOperation(loaded, "search_memory_facts"),
144
+ ];
145
+ return true;
146
+ }
147
+ catch (error) {
148
+ if (signal.aborted)
149
+ throw error;
150
+ return false;
151
+ }
152
+ },
153
+ });
154
+ if (!tools) {
155
+ await child.shutdown();
156
+ throw new Error("Graphiti OpenAPI tools were not captured during readiness");
157
+ }
158
+ return new GraphitiBackend(resolved, child, tools[0], tools[1]);
159
+ }
160
+ function resolveGraphitiConfig(options) {
161
+ const environment = graphitiOptionsFromEnvironment(process.env);
162
+ if (environment.profile && !authProfile.resolveProfile({ profile: environment.profile })) {
163
+ environment.profile = undefined;
164
+ }
165
+ const overrides = graphitiOptionOverrides(options);
166
+ return resolveGraphitiOptions({
167
+ ...environment,
168
+ ...overrides,
169
+ listen: overrides.listen ??
170
+ environment.listen ?? {
171
+ scheme: "tcp",
172
+ host: "127.0.0.1",
173
+ port: 0,
174
+ },
175
+ });
176
+ }
177
+ function requiredOperation(tools, name) {
178
+ const tool = tools.find(({ id }) => id === name);
179
+ if (!tool)
180
+ throw new Error(`Graphiti OpenAPI is missing operation: ${name}`);
181
+ return tool;
182
+ }
183
+ function userScope(userId) {
184
+ return `user_${createHash("sha256").update(userId).digest("base64url")}`;
185
+ }
186
+ async function availablePort() {
187
+ return new Promise((resolve, reject) => {
188
+ const server = createServer();
189
+ server.once("error", reject);
190
+ server.listen(0, "127.0.0.1", () => {
191
+ const address = server.address();
192
+ if (!address || typeof address === "string") {
193
+ server.close();
194
+ reject(new Error("Could not allocate a Graphiti loopback port"));
195
+ return;
196
+ }
197
+ server.close((error) => (error ? reject(error) : resolve(address.port)));
198
+ });
199
+ });
200
+ }
201
+ async function distinctPorts(appPort, graphitiPort) {
202
+ const ports = [appPort];
203
+ for (const configuredPort of [graphitiPort]) {
204
+ if (configuredPort && ports.includes(configuredPort)) {
205
+ throw new ConfigurationError("Graphiti sidecar ports must differ from DATABRICKS_APP_PORT");
206
+ }
207
+ let port = configuredPort || (await availablePort());
208
+ while (ports.includes(port))
209
+ port = await availablePort();
210
+ ports.push(port);
211
+ }
212
+ return ports.slice(1);
213
+ }
214
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiX2JhY2tlbmQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvZ3JhcGhpdGkvX2JhY2tlbmQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7R0FJRztBQUVILE9BQU8sRUFBRSxVQUFVLEVBQUUsV0FBVyxFQUFFLE1BQU0sYUFBYSxDQUFDO0FBQ3RELE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSxVQUFVLENBQUM7QUFDeEMsT0FBTyxFQUFFLGtCQUFrQixFQUFFLE1BQU0sb0JBQW9CLENBQUM7QUFDeEQsT0FBTyxFQUFFLFlBQVksRUFBb0IsTUFBTSxnQ0FBZ0MsQ0FBQztBQUNoRixPQUFPLEVBQUUsT0FBTyxJQUFJLFdBQVcsRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBQ3pELE9BQU8sRUFBRSxXQUFXLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUU5QyxPQUFPLEVBQUUsQ0FBQyxFQUFFLE1BQU0sS0FBSyxDQUFDO0FBVXhCLE9BQU8sRUFDTCx1QkFBdUIsRUFDdkIsOEJBQThCLEVBQzlCLHNCQUFzQixHQUd2QixNQUFNLGNBQWMsQ0FBQztBQUN0QixPQUFPLEVBQ0wsMEJBQTBCLEVBQzFCLG1CQUFtQixFQUNuQixlQUFlLEVBQ2Ysc0JBQXNCLEdBQ3ZCLE1BQU0sY0FBYyxDQUFDO0FBRXRCLE1BQU0sa0JBQWtCLEdBQUcsQ0FBQztLQUN6QixNQUFNLENBQUM7SUFDTixJQUFJLEVBQUUsQ0FBQyxDQUFDLE1BQU0sRUFBRSxDQUFDLFFBQVEsRUFBRSxDQUFDLFFBQVEsQ0FBQyxxQkFBcUIsQ0FBQztJQUMzRCxJQUFJLEVBQUUsQ0FBQyxDQUFDLE1BQU0sRUFBRSxDQUFDLFFBQVEsQ0FBQyx1QkFBdUIsQ0FBQztDQUNuRCxDQUFDO0tBQ0QsS0FBSyxFQUFFO0tBQ1AsUUFBUSxDQUFDLDhCQUE4QixDQUFDLENBQUM7QUFFNUMsTUFBTSx3QkFBd0IsR0FBRyxDQUFDO0tBQy9CLE1BQU0sQ0FBQztJQUNOLEtBQUssRUFB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LENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxPQUFPLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUMzRSxDQUFDLENBQUMsQ0FBQztJQUNMLENBQUMsQ0FBQyxDQUFDO0FBQ0wsQ0FBQztBQUVELEtBQUssVUFBVSxhQUFhLENBQUMsT0FBZSxFQUFFLFlBQW9CO0lBQ2hFLE1BQU0sS0FBSyxHQUFHLENBQUMsT0FBTyxDQUFDLENBQUM7SUFDeEIsS0FBSyxNQUFNLGNBQWMsSUFBSSxDQUFDLFlBQVksQ0FBQyxFQUFFLENBQUM7UUFDNUMsSUFBSSxjQUFjLElBQUksS0FBSyxDQUFDLFFBQVEsQ0FBQyxjQUFjLENBQUMsRUFBRSxDQUFDO1lBQ3JELE1BQU0sSUFBSSxrQkFBa0IsQ0FBQyw2REFBNkQsQ0FBQyxDQUFDO1FBQzlGLENBQUM7UUFDRCxJQUFJLElBQUksR0FBRyxjQUFjLElBQUksQ0FBQyxNQUFNLGFBQWEsRUFBRSxDQUFDLENBQUM7UUFDckQsT0FBTyxLQUFLLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQztZQUFFLElBQUksR0FBRyxNQUFNLGFBQWEsRUFBRSxDQUFDO1FBQzFELEtBQUssQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUM7SUFDbkIsQ0FBQztJQUNELE9BQU8sS0FBSyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQWEsQ0FBQztBQUNwQyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBMYXp5IEdyYXBoaXRpIGltcGxlbWVudGF0aW9uIG9mIHRoZSBiYWNrZW5kLW5ldXRyYWwgbWVtb3J5IGNvbnRyYWN0LlxuICpcbiAqIEBtb2R1bGVcbiAqL1xuXG5pbXBvcnQgeyBjcmVhdGVIYXNoLCByYW5kb21CeXRlcyB9IGZyb20gXCJub2RlOmNyeXB0b1wiO1xuaW1wb3J0IHsgY3JlYXRlU2VydmVyIH0gZnJvbSBcIm5vZGU6bmV0XCI7XG5pbXBvcnQgeyBDb25maWd1cmF0aW9uRXJyb3IgfSBmcm9tIFwiQGRhdGFicmlja3MvYXBwa2l0XCI7XG5pbXBvcnQgeyBvcGVuQXBpVG9vbHMsIHR5cGUgT3BlbkFwaVRvb2wgfSBmcm9tIFwiQGRieC10b29scy9hcHBraXQvb3BlbmFwaS10b29sXCI7XG5pbXBvcnQgeyBwcm9maWxlIGFzIGF1dGhQcm9maWxlIH0gZnJvbSBcIkBkYngtdG9vbHMvYXV0aFwiO1xuaW1wb3J0IHsgY29uZmlnVXRpbHMgfSBmcm9tIFwiQGRieC10b29scy9jb3JlXCI7XG5pbXBvcnQgdHlwZSB7IENoaWxkUHJvY2Vzc1Jlc3VsdCB9IGZyb20gXCJAZGJ4LXRvb2xzL2NvcmUvZXhlY1wiO1xuaW1wb3J0IHsgeiB9IGZyb20gXCJ6b2RcIjtcblxuaW1wb3J0IHtcbiAgdHlwZSBHcmFwaGl0aU1lbW9yeUJhY2tlbmQsXG4gIHR5cGUgTWVtb3J5VHVybixcbiAgdHlwZSBSZWNhbGxNZW1vcnlJbnB1dCxcbiAgdHlwZSBSZWNhbGxNZW1vcnlSZXN1bHQsXG4gIHR5cGUgUmVtZW1iZXJNZW1vcnlJbnB1dCxcbiAgdHlwZSBSZW1lbWJlck1lbW9yeVJlc3VsdCxcbn0gZnJvbSBcIi4uL19jb250cmFjdHMudHNcIjtcbmltcG9ydCB7XG4gIGdyYXBoaXRpT3B0aW9uT3ZlcnJpZGVzLFxuICBncmFwaGl0aU9wdGlvbnNGcm9tRW52aXJvbm1lbnQsXG4gIHJlc29sdmVHcmFwaGl0aU9wdGlvbnMsXG4gIHR5cGUgR3JhcGhpdGlPcHRpb25zLFxuICB0eXBlIFJlc29sdmVkR3JhcGhpdGlPcHRpb25zLFxufSBmcm9tIFwiLi9vcHRpb25zLnRzXCI7XG5pbXBvcnQge1xuICBjcmVhdGVHcmFwaGl0aUNoaWxkUHJvY2VzcyxcbiAgZ3JhcGhpdGlIZWFsdGhDaGVjayxcbiAgZ3JhcGhpdGlIdHRwVXJsLFxuICBncmFwaGl0aVJlcXVlc3RIZWFkZXJzLFxufSBmcm9tIFwiLi9ydW50aW1lLnRzXCI7XG5cbmNvbnN0IEdyYXBoaXRpRmFjdFNjaGVtYSA9IHpcbiAgLm9iamVjdCh7XG4gICAgbmFtZTogei5zdHJpbmcoKS5vcHRpb25hbCgpLmRlc2NyaWJlKFwiR3JhcGhpdGkgZmFjdCBuYW1lLlwiKSxcbiAgICBmYWN0OiB6LnN0cmluZygpLmRlc2NyaWJlKFwiUmV0cmlldmVkIGdyYXBoIGZhY3QuXCIpLFxuICB9KVxuICAubG9vc2UoKVxuICAuZGVzY3JpYmUoXCJHcmFwaGl0aSBmYWN0IHNlYXJjaCByZXN1bHQuXCIpO1xuXG5jb25zdCBHcmFwaGl0aUZhY3RTZWFyY2hTY2hlbWEgPSB6XG4gIC5vYmplY3Qoe1xuICAgIGZhY3RzOiB6LmFycmF5KEdyYXBoaXRpRmFjdFNjaGVtYSkub3B0aW9uYWwoKS5kZXNjcmliZShcIk1hdGNoaW5nIGdyYXBoIGZhY3RzLlwiKSxcbiAgICBlcnJvcjogei5zdHJpbmcoKS5vcHRpb25hbCgpLmRlc2NyaWJlKFwiR3JhcGhpdGkgb3BlcmF0aW9uIGVycm9yLlwiKSxcbiAgfSlcbiAgLmxvb3NlKClcbiAgLmRlc2NyaWJlKFwiR3JhcGhpdGkgZmFjdCBzZWFyY2ggcmVzcG9uc2UuXCIpO1xuXG5jb25zdCBHcmFwaGl0aVdyaXRlU2NoZW1hID0gelxuICAub2JqZWN0KHtcbiAgICBtZXNzYWdlOiB6LnN0cmluZygpLm9wdGlvbmFsKCkuZGVzY3JpYmUoXCJHcmFwaGl0aSB3cml0ZSBjb25maXJtYXRpb24uXCIpLFxuICAgIGVycm9yOiB6LnN0cmluZygpLm9wdGlvbmFsKCkuZGVzY3JpYmUoXCJHcmFwaGl0aSBvcGVyYXRpb24gZXJyb3IuXCIpLFxuICB9KVxuICAubG9vc2UoKVxuICAuZGVzY3JpYmUoXCJHcmFwaGl0aSB3cml0ZSByZXNwb25zZS5cIik7XG5cbmNsYXNzIEdyYXBoaXRpQmFja2VuZCBpbXBsZW1lbnRzIEdyYXBoaXRpTWVtb3J5QmFja2VuZCB7XG4gIGNvbnN0cnVjdG9yKFxuICAgIHByaXZhdGUgcmVhZG9ubHkgb3B0aW9uczogUmVzb2x2ZWRHcmFwaGl0aU9wdGlvbnMsXG4gICAgcHJpdmF0ZSByZWFkb25seSBjaGlsZDogQ2hpbGRQcm9jZXNzUmVzdWx0LFxuICAgIHByaXZhdGUgcmVhZG9ubHkgd3JpdGVUb29sOiBPcGVuQXBpVG9vbCxcbiAgICBwcml2YXRlIHJlYWRvbmx5IHJlY2FsbFRvb2w6IE9wZW5BcGlUb29sLFxuICApIHt9XG5cbiAgZ2V0IHJ1bm5pbmcoKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIChcbiAgICAgICh0aGlzLmNoaWxkLmV4aXRDb2RlID09PSBudWxsIHx8IHRoaXMuY2hpbGQuZXhpdENvZGUgPT09IHVuZGVmaW5lZCkgJiZcbiAgICAgICh0aGlzLmNoaWxkLnNpZ25hbENvZGUgPT09IG51bGwgfHwgdGhpcy5jaGlsZC5zaWduYWxDb2RlID09PSB1bmRlZmluZWQpXG4gICAgKTtcbiAgfVxuXG4gIGFzeW5jIHJlbWVtYmVyKFxuICAgIGFjdG9ySWQ6IHN0cmluZyxcbiAgICBpbnB1dDogUmVtZW1iZXJNZW1vcnlJbnB1dCxcbiAgICBzaWduYWw/OiBBYm9ydFNpZ25hbCxcbiAgKTogUHJvbWlzZTxSZW1lbWJlck1lbW9yeVJlc3VsdD4ge1xuICAgIGF3YWl0IHRoaXMud3JpdGUoXG4gICAgICBhY3RvcklkLFxuICAgICAge1xuICAgICAgICBuYW1lOiBpbnB1dC5wYXRoLFxuICAgICAgICBlcGlzb2RlX2JvZHk6IGlucHV0LmNvbnRlbnQsXG4gICAgICAgIHNvdXJjZTogXCJ0ZXh0XCIsXG4gICAgICAgIHNvdXJjZV9kZXNjcmlwdGlvbjogaW5wdXQuZGVzY3JpcHRpb24gPyBgJHtpbnB1dC5wYXRofTogJHtpbnB1dC5kZXNjcmlwdGlvbn1gIDogaW5wdXQucGF0aCxcbiAgICAgIH0sXG4gICAgICBzaWduYWwsXG4gICAgKTtcbiAgICByZXR1cm4ge1xuICAgICAgYmFja2VuZDogXCJncmFwaGl0aVwiLFxuICAgICAgbWVtb3J5OiB7XG4gICAgICAgIHBhdGg6IGlucHV0LnBhdGgsXG4gICAgICAgIGNvbnRlbnQ6IGlucHV0LmNvbnRlbnQsXG4gICAgICAgIC4uLihpbnB1dC5kZXNjcmlwdGlvbiA/IHsgZGVzY3JpcHRpb246IGlucHV0LmRlc2NyaXB0aW9uIH0gOiB7fSksXG4gICAgICB9LFxuICAgIH07XG4gIH1cblxuICBhc3luYyByZWNhbGwoXG4gICAgYWN0b3JJZDogc3RyaW5nLFxuICAgIGlucHV0OiBSZWNhbGxNZW1vcnlJbnB1dCxcbiAgICBzaWduYWw/OiBBYm9ydFNpZ25hbCxcbiAgKTogUHJvbWlzZTxSZWNhbGxNZW1vcnlSZXN1bHQ+IHtcbiAgICBjb25zdCByZXNwb25zZSA9IEdyYXBoaXRpRmFjdFNlYXJjaFNjaGVtYS5wYXJzZShcbiAgICAgIGF3YWl0IHRoaXMucmVxdWVzdChcbiAgICAgICAgdGhpcy5yZWNhbGxUb29sLFxuICAgICAgICB7XG4gICAgICAgICAgcXVlcnk6IGlucHV0LnF1ZXJ5LFxuICAgICAgICAgIG1heF9mYWN0czogaW5wdXQubGltaXQsXG4gICAgICAgICAgZ3JvdXBfaWRzOiBbdXNlclNjb3BlKGFjdG9ySWQpXSxcbiAgICAgICAgfSxcbiAgICAgICAgc2lnbmFsLFxuICAgICAgKSxcbiAgICApO1xuICAgIGlmIChyZXNwb25zZS5lcnJvcikgdGhyb3cgbmV3IEVycm9yKHJlc3BvbnNlLmVycm9yKTtcbiAgICByZXR1cm4ge1xuICAgICAgYmFja2VuZDogXCJncmFwaGl0aVwiLFxuICAgICAgbWVtb3JpZXM6IChyZXNwb25zZS5mYWN0cyA/PyBbXSkubWFwKChmYWN0KSA9PiAoe1xuICAgICAgICBjb250ZW50OiBmYWN0LmZhY3QsXG4gICAgICAgIC4uLihmYWN0Lm5hbWUgPyB7IGRlc2NyaXB0aW9uOiBmYWN0Lm5hbWUgfSA6IHt9KSxcbiAgICAgIH0pKSxcbiAgICB9O1xuICB9XG5cbiAgYXN5bmMgc2F2ZVR1cm4odHVybjogTWVtb3J5VHVybiwgc2lnbmFsPzogQWJvcnRTaWduYWwpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBhd2FpdCB0aGlzLndyaXRlKFxuICAgICAgdHVybi5hY3RvcklkLFxuICAgICAge1xuICAgICAgICBuYW1lOiBgTWFzdHJhIHR1cm4gJHt0dXJuLmFnZW50SWR9LyR7dHVybi50aHJlYWRJZH1gLFxuICAgICAgICBlcGlzb2RlX2JvZHk6IGBVc2VyOiAke3R1cm4udXNlcn1cXG5cXG5Bc3Npc3RhbnQ6ICR7dHVybi5hc3Npc3RhbnR9YCxcbiAgICAgICAgc291cmNlOiBcIm1lc3NhZ2VcIixcbiAgICAgICAgc291cmNlX2Rlc2NyaXB0aW9uOiBgQ29tcGxldGVkICR7dHVybi5hZ2VudElkfSBjb252ZXJzYXRpb24gdHVybmAsXG4gICAgICB9LFxuICAgICAgc2lnbmFsLFxuICAgICk7XG4gIH1cblxuICBzaHV0ZG93bigpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICByZXR1cm4gdGhpcy5jaGlsZC5zaHV0ZG93bigpO1xuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyB3cml0ZShcbiAgICBhY3RvcklkOiBzdHJpbmcsXG4gICAgYXJnczogUmVjb3JkPHN0cmluZywgdW5rbm93bj4sXG4gICAgc2lnbmFsPzogQWJvcnRTaWduYWwsXG4gICk6IFByb21pc2U8dm9pZD4ge1xuICAgIGNvbnN0IHJlc3BvbnNlID0gR3JhcGhpdGlXcml0ZVNjaGVtYS5wYXJzZShcbiAgICAgIGF3YWl0IHRoaXMucmVxdWVzdCh0aGlzLndyaXRlVG9vbCwgeyAuLi5hcmdzLCBncm91cF9pZDogdXNlclNjb3BlKGFjdG9ySWQpIH0sIHNpZ25hbCksXG4gICAgKTtcbiAgICBpZiAocmVzcG9uc2UuZXJyb3IpIHRocm93IG5ldyBFcnJvcihyZXNwb25zZS5lcnJvcik7XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIHJlcXVlc3QoXG4gICAgdG9vbDogT3BlbkFwaVRvb2wsXG4gICAgYXJnczogUmVjb3JkPHN0cmluZywgdW5rbm93bj4sXG4gICAgc2lnbmFsPzogQWJvcnRTaWduYWwsXG4gICk6IFByb21pc2U8dW5rbm93bj4ge1xuICAgIGlmICghdGhpcy5ydW5uaW5nKSB0aHJvdyBuZXcgRXJyb3IoXCJHcmFwaGl0aSBzaWRlY2FyIGlzIG5vdCBydW5uaW5nXCIpO1xuICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgZmV0Y2godG9vbC51cmwsIHtcbiAgICAgIG1ldGhvZDogdG9vbC5tZXRob2QsXG4gICAgICBoZWFkZXJzOiB7XG4gICAgICAgIC4uLmdyYXBoaXRpUmVxdWVzdEhlYWRlcnModGhpcy5vcHRpb25zKSxcbiAgICAgICAgXCJjb250ZW50LXR5cGVcIjogXCJhcHBsaWNhdGlvbi9qc29uXCIsXG4gICAgICB9LFxuICAgICAgYm9keTogSlNPTi5zdHJpbmdpZnkoYXJncyksXG4gICAgICBzaWduYWwsXG4gICAgfSk7XG4gICAgaWYgKCFyZXNwb25zZS5vaykge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICBgR3JhcGhpdGkgb3BlcmF0aW9uICR7dG9vbC5pZH0gZmFpbGVkIHdpdGggSFRUUCAke3Jlc3BvbnNlLnN0YXR1c306ICR7YXdhaXQgcmVzcG9uc2UudGV4dCgpfWAsXG4gICAgICApO1xuICAgIH1cbiAgICByZXR1cm4gcmVzcG9uc2UuanNvbigpO1xuICB9XG59XG5cbi8qKiBTdGFydCBhIGZ1bGx5IHJlYWR5IEdyYXBoaXRpIGJhY2tlbmQgZm9yIHRoZSBmaXJzdCBmYWxsYmFjayBvcGVyYXRpb24uICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gc3RhcnRHcmFwaGl0aUJhY2tlbmQoXG4gIG9wdGlvbnM6IEdyYXBoaXRpT3B0aW9ucyxcbiAgc2lnbmFsPzogQWJvcnRTaWduYWwsXG4pOiBQcm9taXNlPEdyYXBoaXRpTWVtb3J5QmFja2VuZD4ge1xuICBjb25zdCBjb25maWd1cmVkID0gcmVzb2x2ZUdyYXBoaXRpQ29uZmlnKG9wdGlvbnMpO1xuICBpZiAoY29uZmlndXJlZC5saXN0ZW4uc2NoZW1lICE9PSBcInRjcFwiKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKFwiQXBwS2l0IG1lbW9yeSByZXF1aXJlcyBhIFRDUCBHcmFwaGl0aSBsaXN0ZW5lclwiKTtcbiAgfVxuICBjb25zdCBbZ3JhcGhpdGlQb3J0XSA9IGF3YWl0IGRpc3RpbmN0UG9ydHMoXG4gICAgY29uZmlnVXRpbHMucG9ydCh1bmRlZmluZWQsIFwiREFUQUJSSUNLU19BUFBfUE9SVFwiLCA4MDAwLCBjb25maWdVdGlscy5FTlZfT05MWSksXG4gICAgY29uZmlndXJlZC5saXN0ZW4ucG9ydCxcbiAgKTtcbiAgY29uc3QgcmVzb2x2ZWQgPSByZXNvbHZlR3JhcGhpdGlPcHRpb25zKHtcbiAgICAuLi5jb25maWd1cmVkLFxuICAgIGJlYXJlcjogcmFuZG9tQnl0ZXMoMzIpLnRvU3RyaW5nKFwiYmFzZTY0dXJsXCIpLFxuICAgIGxpc3RlbjogeyAuLi5jb25maWd1cmVkLmxpc3RlbiwgcG9ydDogZ3JhcGhpdGlQb3J0IH0sXG4gIH0pO1xuICBsZXQgdG9vbHM6IE9wZW5BcGlUb29sW10gfCB1bmRlZmluZWQ7XG4gIGNvbnN0IHsgY2hpbGQgfSA9IGF3YWl0IGNyZWF0ZUdyYXBoaXRpQ2hpbGRQcm9jZXNzKHtcbiAgICAuLi5yZXNvbHZlZCxcbiAgICAuLi4oc2lnbmFsID8geyBzaWduYWwgfSA6IHt9KSxcbiAgICBoZWFsdGhDaGVjazogYXN5bmMgKHsgc2lnbmFsIH0pID0+IHtcbiAgICAgIHRyeSB7XG4gICAgICAgIGlmICghKGF3YWl0IGdyYXBoaXRpSGVhbHRoQ2hlY2socmVzb2x2ZWQsIHNpZ25hbCkpKSByZXR1cm4gZmFsc2U7XG4gICAgICAgIGNvbnN0IGxvYWRlZCA9IGF3YWl0IG9wZW5BcGlUb29scyhncmFwaGl0aUh0dHBVcmwocmVzb2x2ZWQsIFwiL29wZW5hcGkuanNvblwiKSwge1xuICAgICAgICAgIHNpZ25hbCxcbiAgICAgICAgICBoZWFkZXJzOiBncmFwaGl0aVJlcXVlc3RIZWFkZXJzKHJlc29sdmVkKSxcbiAgICAgICAgfSk7XG4gICAgICAgIHRvb2xzID0gW1xuICAgICAgICAgIHJlcXVpcmVkT3BlcmF0aW9uKGxvYWRlZCwgXCJhZGRfbWVtb3J5X3N5bmNcIiksXG4gICAgICAgICAgcmVxdWlyZWRPcGVyYXRpb24obG9hZGVkLCBcInNlYXJjaF9tZW1vcnlfZmFjdHNcIiksXG4gICAgICAgIF07XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgaWYgKHNpZ25hbC5hYm9ydGVkKSB0aHJvdyBlcnJvcjtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgfVxuICAgIH0sXG4gIH0pO1xuICBpZiAoIXRvb2xzKSB7XG4gICAgYXdhaXQgY2hpbGQuc2h1dGRvd24oKTtcbiAgICB0aHJvdyBuZXcgRXJyb3IoXCJHcmFwaGl0aSBPcGVuQVBJIHRvb2xzIHdlcmUgbm90IGNhcHR1cmVkIGR1cmluZyByZWFkaW5lc3NcIik7XG4gIH1cbiAgcmV0dXJuIG5ldyBHcmFwaGl0aUJhY2tlbmQocmVzb2x2ZWQsIGNoaWxkLCB0b29sc1swXSEsIHRvb2xzWzFdISk7XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVHcmFwaGl0aUNvbmZpZyhvcHRpb25zOiBHcmFwaGl0aU9wdGlvbnMpOiBSZXNvbHZlZEdyYXBoaXRpT3B0aW9ucyB7XG4gIGNvbnN0IGVudmlyb25tZW50ID0gZ3JhcGhpdGlPcHRpb25zRnJvbUVudmlyb25tZW50KHByb2Nlc3MuZW52KTtcbiAgaWYgKGVudmlyb25tZW50LnByb2ZpbGUgJiYgIWF1dGhQcm9maWxlLnJlc29sdmVQcm9maWxlKHsgcHJvZmlsZTogZW52aXJvbm1lbnQucHJvZmlsZSB9KSkge1xuICAgIGVudmlyb25tZW50LnByb2ZpbGUgPSB1bmRlZmluZWQ7XG4gIH1cbiAgY29uc3Qgb3ZlcnJpZGVzID0gZ3JhcGhpdGlPcHRpb25PdmVycmlkZXMob3B0aW9ucyk7XG4gIHJldHVybiByZXNvbHZlR3JhcGhpdGlPcHRpb25zKHtcbiAgICAuLi5lbnZpcm9ubWVudCxcbiAgICAuLi5vdmVycmlkZXMsXG4gICAgbGlzdGVuOiBvdmVycmlkZXMubGlzdGVuID8/XG4gICAgICBlbnZpcm9ubWVudC5saXN0ZW4gPz8ge1xuICAgICAgICBzY2hlbWU6IFwidGNwXCIsXG4gICAgICAgIGhvc3Q6IFwiMTI3LjAuMC4xXCIsXG4gICAgICAgIHBvcnQ6IDAsXG4gICAgICB9LFxuICB9KTtcbn1cblxuZnVuY3Rpb24gcmVxdWlyZWRPcGVyYXRpb24odG9vbHM6IHJlYWRvbmx5IE9wZW5BcGlUb29sW10sIG5hbWU6IHN0cmluZyk6IE9wZW5BcGlUb29sIHtcbiAgY29uc3QgdG9vbCA9IHRvb2xzLmZpbmQoKHsgaWQgfSkgPT4gaWQgPT09IG5hbWUpO1xuICBpZiAoIXRvb2wpIHRocm93IG5ldyBFcnJvcihgR3JhcGhpdGkgT3BlbkFQSSBpcyBtaXNzaW5nIG9wZXJhdGlvbjogJHtuYW1lfWApO1xuICByZXR1cm4gdG9vbDtcbn1cblxuZnVuY3Rpb24gdXNlclNjb3BlKHVzZXJJZDogc3RyaW5nKTogc3RyaW5nIHtcbiAgcmV0dXJuIGB1c2VyXyR7Y3JlYXRlSGFzaChcInNoYTI1NlwiKS51cGRhdGUodXNlcklkKS5kaWdlc3QoXCJiYXNlNjR1cmxcIil9YDtcbn1cblxuYXN5bmMgZnVuY3Rpb24gYXZhaWxhYmxlUG9ydCgpOiBQcm9taXNlPG51bWJlcj4ge1xuICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgIGNvbnN0IHNlcnZlciA9IGNyZWF0ZVNlcnZlcigpO1xuICAgIHNlcnZlci5vbmNlKFwiZXJyb3JcIiwgcmVqZWN0KTtcbiAgICBzZXJ2ZXIubGlzdGVuKDAsIFwiMTI3LjAuMC4xXCIsICgpID0+IHtcbiAgICAgIGNvbnN0IGFkZHJlc3MgPSBzZXJ2ZXIuYWRkcmVzcygpO1xuICAgICAgaWYgKCFhZGRyZXNzIHx8IHR5cGVvZiBhZGRyZXNzID09PSBcInN0cmluZ1wiKSB7XG4gICAgICAgIHNlcnZlci5jbG9zZSgpO1xuICAgICAgICByZWplY3QobmV3IEVycm9yKFwiQ291bGQgbm90IGFsbG9jYXRlIGEgR3JhcGhpdGkgbG9vcGJhY2sgcG9ydFwiKSk7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cbiAgICAgIHNlcnZlci5jbG9zZSgoZXJyb3IpID0+IChlcnJvciA/IHJlamVjdChlcnJvcikgOiByZXNvbHZlKGFkZHJlc3MucG9ydCkpKTtcbiAgICB9KTtcbiAgfSk7XG59XG5cbmFzeW5jIGZ1bmN0aW9uIGRpc3RpbmN0UG9ydHMoYXBwUG9ydDogbnVtYmVyLCBncmFwaGl0aVBvcnQ6IG51bWJlcik6IFByb21pc2U8W251bWJlcl0+IHtcbiAgY29uc3QgcG9ydHMgPSBbYXBwUG9ydF07XG4gIGZvciAoY29uc3QgY29uZmlndXJlZFBvcnQgb2YgW2dyYXBoaXRpUG9ydF0pIHtcbiAgICBpZiAoY29uZmlndXJlZFBvcnQgJiYgcG9ydHMuaW5jbHVkZXMoY29uZmlndXJlZFBvcnQpKSB7XG4gICAgICB0aHJvdyBuZXcgQ29uZmlndXJhdGlvbkVycm9yKFwiR3JhcGhpdGkgc2lkZWNhciBwb3J0cyBtdXN0IGRpZmZlciBmcm9tIERBVEFCUklDS1NfQVBQX1BPUlRcIik7XG4gICAgfVxuICAgIGxldCBwb3J0ID0gY29uZmlndXJlZFBvcnQgfHwgKGF3YWl0IGF2YWlsYWJsZVBvcnQoKSk7XG4gICAgd2hpbGUgKHBvcnRzLmluY2x1ZGVzKHBvcnQpKSBwb3J0ID0gYXdhaXQgYXZhaWxhYmxlUG9ydCgpO1xuICAgIHBvcnRzLnB1c2gocG9ydCk7XG4gIH1cbiAgcmV0dXJuIHBvcnRzLnNsaWNlKDEpIGFzIFtudW1iZXJdO1xufVxuIl19
@@ -0,0 +1,3 @@
1
+ export * as options from "./options.ts";
2
+ export * as runtime from "./runtime.ts";
3
+ export type { GraphitiHealthCheckContext, GraphitiHealthCheck, GraphitiChildProcess, GraphitiRuntimeOptions, GraphitiPythonCommand } from "./runtime.ts";
@@ -0,0 +1,6 @@
1
+ // GENERATED by projen watch - DO NOT EDIT.
2
+ // Regenerated from the exporting modules in ./src.
3
+ // Hand edits are overwritten on the next watch; this file is read-only.
4
+ export * as options from "./options.js";
5
+ export * as runtime from "./runtime.js";
6
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvZ3JhcGhpdGkvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsMkNBQTJDO0FBQzNDLG1EQUFtRDtBQUNuRCx3RUFBd0U7QUFFeEUsT0FBTyxLQUFLLE9BQU8sTUFBTSxjQUFjLENBQUM7QUFDeEMsT0FBTyxLQUFLLE9BQU8sTUFBTSxjQUFjLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvLyBHRU5FUkFURUQgYnkgcHJvamVuIHdhdGNoIC0gRE8gTk9UIEVESVQuXG4vLyBSZWdlbmVyYXRlZCBmcm9tIHRoZSBleHBvcnRpbmcgbW9kdWxlcyBpbiAuL3NyYy5cbi8vIEhhbmQgZWRpdHMgYXJlIG92ZXJ3cml0dGVuIG9uIHRoZSBuZXh0IHdhdGNoOyB0aGlzIGZpbGUgaXMgcmVhZC1vbmx5LlxuXG5leHBvcnQgKiBhcyBvcHRpb25zIGZyb20gXCIuL29wdGlvbnMudHNcIjtcbmV4cG9ydCAqIGFzIHJ1bnRpbWUgZnJvbSBcIi4vcnVudGltZS50c1wiO1xuZXhwb3J0IHR5cGUgeyBHcmFwaGl0aUhlYWx0aENoZWNrQ29udGV4dCwgR3JhcGhpdGlIZWFsdGhDaGVjaywgR3JhcGhpdGlDaGlsZFByb2Nlc3MsIEdyYXBoaXRpUnVudGltZU9wdGlvbnMsIEdyYXBoaXRpUHl0aG9uQ29tbWFuZCB9IGZyb20gXCIuL3J1bnRpbWUudHNcIjtcbiJdfQ==
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Node export of the shared Graphiti option contract.
3
+ *
4
+ * @module
5
+ */
6
+ export { GRAPHITI_DEFAULTS, GraphitiCliOptionsSchema, GraphitiOptionsSchema, ResolvedGraphitiOptionsSchema, graphitiOptionOverrides, graphitiOptionsEnvironment, graphitiOptionsFromEnvironment, resolveGraphitiOptions, } from "@dbx-tools/shared-graphiti";
7
+ export type { GraphitiOptions, ResolvedGraphitiOptions } from "@dbx-tools/shared-graphiti";
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Node export of the shared Graphiti option contract.
3
+ *
4
+ * @module
5
+ */
6
+ export { GRAPHITI_DEFAULTS, GraphitiCliOptionsSchema, GraphitiOptionsSchema, ResolvedGraphitiOptionsSchema, graphitiOptionOverrides, graphitiOptionsEnvironment, graphitiOptionsFromEnvironment, resolveGraphitiOptions, } from "@dbx-tools/shared-graphiti";
7
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoib3B0aW9ucy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9ncmFwaGl0aS9vcHRpb25zLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7O0dBSUc7QUFFSCxPQUFPLEVBQ0wsaUJBQWlCLEVBQ2pCLHdCQUF3QixFQUN4QixxQkFBcUIsRUFDckIsNkJBQTZCLEVBQzdCLHVCQUF1QixFQUN2QiwwQkFBMEIsRUFDMUIsOEJBQThCLEVBQzlCLHNCQUFzQixHQUN2QixNQUFNLDRCQUE0QixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBOb2RlIGV4cG9ydCBvZiB0aGUgc2hhcmVkIEdyYXBoaXRpIG9wdGlvbiBjb250cmFjdC5cbiAqXG4gKiBAbW9kdWxlXG4gKi9cblxuZXhwb3J0IHtcbiAgR1JBUEhJVElfREVGQVVMVFMsXG4gIEdyYXBoaXRpQ2xpT3B0aW9uc1NjaGVtYSxcbiAgR3JhcGhpdGlPcHRpb25zU2NoZW1hLFxuICBSZXNvbHZlZEdyYXBoaXRpT3B0aW9uc1NjaGVtYSxcbiAgZ3JhcGhpdGlPcHRpb25PdmVycmlkZXMsXG4gIGdyYXBoaXRpT3B0aW9uc0Vudmlyb25tZW50LFxuICBncmFwaGl0aU9wdGlvbnNGcm9tRW52aXJvbm1lbnQsXG4gIHJlc29sdmVHcmFwaGl0aU9wdGlvbnMsXG59IGZyb20gXCJAZGJ4LXRvb2xzL3NoYXJlZC1ncmFwaGl0aVwiO1xuZXhwb3J0IHR5cGUgeyBHcmFwaGl0aU9wdGlvbnMsIFJlc29sdmVkR3JhcGhpdGlPcHRpb25zIH0gZnJvbSBcIkBkYngtdG9vbHMvc2hhcmVkLWdyYXBoaXRpXCI7XG4iXX0=
@@ -0,0 +1,49 @@
1
+ /**
2
+ * Node Graphiti runtime and process supervision.
3
+ *
4
+ * @module
5
+ */
6
+ import type { ChildProcessResult } from "@dbx-tools/core/exec";
7
+ import { type GraphitiOptions, type ResolvedGraphitiOptions } from "./options.ts";
8
+ /** Context passed to one Graphiti sidecar readiness probe. */
9
+ export interface GraphitiHealthCheckContext {
10
+ readonly process: ChildProcessResult;
11
+ readonly signal: AbortSignal;
12
+ readonly attempt: number;
13
+ }
14
+ /** HTTP probe used to decide that the Graphiti sidecar has started listening. */
15
+ export type GraphitiHealthCheck = (context: GraphitiHealthCheckContext) => boolean | PromiseLike<boolean>;
16
+ /** Async creation result that preserves the awaitable child handle. */
17
+ export interface GraphitiChildProcess {
18
+ child: ChildProcessResult;
19
+ }
20
+ /** Shared Graphiti options plus the Node-only sidecar readiness probe. */
21
+ export type GraphitiRuntimeOptions = GraphitiOptions & {
22
+ /** Readiness probe for {@link createGraphitiChildProcess}. Defaults to `/healthcheck`. */
23
+ healthCheck?: GraphitiHealthCheck;
24
+ /** Cancels sidecar startup without changing the serialized Graphiti configuration. */
25
+ signal?: AbortSignal;
26
+ };
27
+ /** Milliseconds left in a startup budget after `startedAt`. */
28
+ export declare function remainingTimeoutMs(startedAt: number, timeoutMs: number, now?: number): number;
29
+ /** Return whether the Graphiti `/healthcheck` endpoint responds successfully. */
30
+ export declare function graphitiHealthCheck(options: Pick<ResolvedGraphitiOptions, "listen" | "bearer">, signal: AbortSignal): Promise<boolean>;
31
+ /** Poll `/healthcheck` until it succeeds or `timeoutMs` elapses. */
32
+ export declare function waitForGraphitiHealth(options: Pick<ResolvedGraphitiOptions, "listen" | "bearer">, timeoutMs: number, signal?: AbortSignal): Promise<void>;
33
+ /** Build authorization headers for one optionally secured Graphiti runtime. */
34
+ export declare function graphitiRequestHeaders(options: Pick<ResolvedGraphitiOptions, "bearer">): Readonly<Record<string, string>>;
35
+ /** Executable and arguments used to launch Graphiti. */
36
+ export interface GraphitiPythonCommand {
37
+ command: string;
38
+ args: string[];
39
+ }
40
+ /** Resolve configured or app-installed Python, otherwise a uv-provisioned runtime. */
41
+ export declare function resolveGraphitiPythonCommand(options?: {
42
+ dev?: boolean;
43
+ }, ...args: string[]): Promise<GraphitiPythonCommand>;
44
+ /** Build one HTTP URL for a resolved Graphiti listener. */
45
+ export declare function graphitiHttpUrl(options: Pick<ResolvedGraphitiOptions, "listen">, path: string): string;
46
+ /** Build one readiness-gated Graphiti sidecar from the shared typed options. */
47
+ export declare function createGraphitiChildProcess(options?: GraphitiRuntimeOptions): Promise<GraphitiChildProcess>;
48
+ /** Run the supervised stack until the child exits. */
49
+ export declare function runGraphiti(options?: GraphitiRuntimeOptions): Promise<void>;
@@ -0,0 +1,170 @@
1
+ /**
2
+ * Node Graphiti runtime and process supervision.
3
+ *
4
+ * @module
5
+ */
6
+ import { delimiter, dirname } from "node:path";
7
+ import { exec } from "@dbx-tools/core";
8
+ import { asyncUtils, environmentUtils, functionUtils, options as sharedOptions, } from "@dbx-tools/shared-core";
9
+ import { coerce, rcompare } from "semver";
10
+ import { graphitiOptionsEnvironment, resolveGraphitiOptions, } from "./options.js";
11
+ const HEALTH_CHECK_INTERVAL_MS = 200;
12
+ const PYTHON_CANDIDATES = ["python", "python3"];
13
+ const GRAPHITI_IMPORT_PROBE = "import dbx_tools.graphiti";
14
+ const graphitiPython = functionUtils.memoize(async () => {
15
+ const available = (await Promise.all(PYTHON_CANDIDATES.map((command) => _probePython(command)))).filter((candidate) => candidate !== undefined);
16
+ available.sort((left, right) => rcompare(left.version, right.version));
17
+ return available[0]?.command;
18
+ });
19
+ function graphitiOptions(options) {
20
+ const { healthCheck: _healthCheck, signal: _signal, ...graphiti } = options;
21
+ return graphiti;
22
+ }
23
+ /** Milliseconds left in a startup budget after `startedAt`. */
24
+ export function remainingTimeoutMs(startedAt, timeoutMs, now = Date.now()) {
25
+ return Math.max(0, timeoutMs - (now - startedAt));
26
+ }
27
+ function _runtimeEnvironment(options) {
28
+ if (options.listen.scheme !== "tcp")
29
+ throw new Error("Graphiti requires a TCP listener");
30
+ const nodeBin = process.env.DBX_TOOLS_NODE_BIN?.trim();
31
+ const path = nodeBin
32
+ ? [dirname(nodeBin), process.env.PATH].filter(Boolean).join(delimiter)
33
+ : process.env.PATH;
34
+ return {
35
+ ...process.env,
36
+ ...(path ? { PATH: path } : {}),
37
+ ...graphitiOptionsEnvironment(options),
38
+ };
39
+ }
40
+ /** Return whether the Graphiti `/healthcheck` endpoint responds successfully. */
41
+ export async function graphitiHealthCheck(options, signal) {
42
+ try {
43
+ return (await fetch(graphitiHttpUrl(options, "/healthcheck"), {
44
+ signal,
45
+ headers: graphitiRequestHeaders(options),
46
+ })).ok;
47
+ }
48
+ catch (error) {
49
+ if (signal.aborted)
50
+ throw error;
51
+ return false;
52
+ }
53
+ }
54
+ /** Poll `/healthcheck` until it succeeds or `timeoutMs` elapses. */
55
+ export async function waitForGraphitiHealth(options, timeoutMs, signal) {
56
+ const budget = Math.max(1, timeoutMs);
57
+ for await (const healthy of asyncUtils.poll(({ signal: pollSignal }) => graphitiHealthCheck(options, pollSignal), {
58
+ intervalMs: HEALTH_CHECK_INTERVAL_MS,
59
+ timeoutMs: budget,
60
+ signal,
61
+ predicate: (ready) => !ready,
62
+ })) {
63
+ if (healthy)
64
+ return;
65
+ }
66
+ throw new Error("Graphiti sidecar healthcheck did not succeed");
67
+ }
68
+ /** Build authorization headers for one optionally secured Graphiti runtime. */
69
+ export function graphitiRequestHeaders(options) {
70
+ return options.bearer ? { authorization: `Bearer ${options.bearer}` } : {};
71
+ }
72
+ /** Resolve configured or app-installed Python, otherwise a uv-provisioned runtime. */
73
+ export async function resolveGraphitiPythonCommand(options = {}, ...args) {
74
+ const python = process.env.PYTHON?.trim();
75
+ if (python)
76
+ return { command: python, args };
77
+ if (environmentUtils.isDatabricksAppEnv()) {
78
+ const installed = await graphitiPython();
79
+ if (installed)
80
+ return { command: installed, args };
81
+ }
82
+ const extra = options.dev ? "[dev]" : "";
83
+ const packageArgs = [
84
+ "--with",
85
+ `dbx-tools-graphiti${extra}==${(await import("../../index.js")).PACKAGE_VERSION}`,
86
+ ];
87
+ return {
88
+ command: "uv",
89
+ args: ["run", "--no-project", ...packageArgs, "--python", "python3", "python", ...args],
90
+ };
91
+ }
92
+ async function _probePython(command) {
93
+ const versionResult = await exec.spawn(command, ["-V"], {
94
+ check: false,
95
+ stdin: "ignore",
96
+ stdout: "capture",
97
+ stderr: "capture",
98
+ trim: true,
99
+ });
100
+ if (versionResult.exitCode !== 0)
101
+ return undefined;
102
+ const version = coerce(`${versionResult.stdout}\n${versionResult.stderr}`);
103
+ if (!version)
104
+ return undefined;
105
+ const importResult = await exec.spawn(command, ["-c", GRAPHITI_IMPORT_PROBE], {
106
+ check: false,
107
+ stdin: "ignore",
108
+ stdout: "ignore",
109
+ stderr: "ignore",
110
+ });
111
+ return importResult.exitCode === 0 ? { command, version } : undefined;
112
+ }
113
+ /** Build one HTTP URL for a resolved Graphiti listener. */
114
+ export function graphitiHttpUrl(options, path) {
115
+ return `${sharedOptions
116
+ .formatListenAddress(options.listen)
117
+ .replace(/^tcp:/, "http:")}${path.startsWith("/") ? path : `/${path}`}`;
118
+ }
119
+ /** Build one readiness-gated Graphiti sidecar from the shared typed options. */
120
+ export async function createGraphitiChildProcess(options = {}) {
121
+ const healthCheck = options.healthCheck;
122
+ const resolved = resolveGraphitiOptions(graphitiOptions(options));
123
+ const python = await resolveGraphitiPythonCommand({ dev: !resolved.databaseUrl }, "-m", "dbx_tools.graphiti");
124
+ const child = exec.spawn(python.command, python.args, {
125
+ env: _runtimeEnvironment(resolved),
126
+ forwardTerminationSignals: false,
127
+ });
128
+ const controller = new AbortController();
129
+ const startupSignal = options.signal
130
+ ? AbortSignal.any([controller.signal, options.signal])
131
+ : controller.signal;
132
+ const probe = healthCheck ?? (({ signal }) => graphitiHealthCheck(resolved, signal));
133
+ try {
134
+ await Promise.race([
135
+ waitForGraphitiChild(child, probe, resolved.startupTimeoutMs, startupSignal),
136
+ child.then((result) => {
137
+ throw new Error(`Graphiti child ${child.pid ?? "<unknown>"} exited before becoming ready ` +
138
+ `(exit ${result.exitCode})`);
139
+ }),
140
+ ]);
141
+ return { child };
142
+ }
143
+ catch (error) {
144
+ await child.shutdown();
145
+ throw error;
146
+ }
147
+ finally {
148
+ controller.abort();
149
+ }
150
+ }
151
+ async function waitForGraphitiChild(child, healthCheck, timeoutMs, signal) {
152
+ for await (const healthy of asyncUtils.poll(({ attempt, signal: pollSignal }) => healthCheck({ process: child, signal: pollSignal, attempt }), {
153
+ intervalMs: HEALTH_CHECK_INTERVAL_MS,
154
+ timeoutMs,
155
+ signal,
156
+ predicate: (ready) => !ready,
157
+ })) {
158
+ if (healthy)
159
+ return;
160
+ }
161
+ }
162
+ /** Run the supervised stack until the child exits. */
163
+ export async function runGraphiti(options = {}) {
164
+ const { child } = await createGraphitiChildProcess(options);
165
+ const outcome = await child;
166
+ if (outcome.exitCode !== 0) {
167
+ throw new Error(`Graphiti child exited with status ${outcome.exitCode}`);
168
+ }
169
+ }
170
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicnVudGltZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9ncmFwaGl0aS9ydW50aW1lLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7O0dBSUc7QUFFSCxPQUFPLEVBQUUsU0FBUyxFQUFFLE9BQU8sRUFBRSxNQUFNLFdBQVcsQ0FBQztBQUMvQyxPQUFPLEVBQUUsSUFBSSxFQUFFLE1BQU0saUJBQWlCLENBQUM7QUFFdkMsT0FBTyxFQUNMLFVBQVUsRUFDVixnQkFBZ0IsRUFDaEIsYUFBYSxFQUNiLE9BQU8sSUFBSSxhQUFhLEdBQ3pCLE1BQU0sd0JBQXdCLENBQUM7QUFDaEMsT0FBTyxFQUFFLE1BQU0sRUFBRSxRQUFRLEVBQWUsTUFBTSxRQUFRLENBQUM7QUFFdkQsT0FBTyxFQUNMLDBCQUEwQixFQUMxQixzQkFBc0IsR0FHdkIsTUFBTSxjQUFjLENBQUM7QUEyQnRCLE1BQU0sd0JBQXdCLEdBQUcsR0FBRyxDQUFDO0FBQ3JDLE1BQU0saUJBQWlCLEdBQUcsQ0FBQyxRQUFRLEVBQUUsU0FBUyxDQUFVLENBQUM7QUFDekQsTUFBTSxxQkFBcUIsR0FBRywyQkFBMkIsQ0FBQztBQU8xRCxNQUFNLGNBQWMsR0FBRyxhQUFhLENBQUMsT0FBTyxDQUFDLEtBQUssSUFBaUMsRUFBRTtJQUNuRixNQUFNLFNBQVMsR0FBRyxDQUNoQixNQUFNLE9BQU8sQ0FBQyxHQUFHLENBQUMsaUJBQWlCLENBQUMsR0FBRyxDQUFDLENBQUMsT0FBTyxFQUFFLEVBQUUsQ0FBQyxZQUFZLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxDQUM3RSxDQUFDLE1BQU0sQ0FBQyxDQUFDLFNBQVMsRUFBZ0MsRUFBRSxDQUFDLFNBQVMsS0FBSyxTQUFTLENBQUMsQ0FBQztJQUMvRSxTQUFTLENBQUMsSUFBSSxDQUFDLENBQUMsSUFBSSxFQUFFLEtBQUssRUFBRSxFQUFFLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxPQUFPLEVBQUUsS0FBSyxDQUFD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cEUsTUFBTSxFQUFFLEtBQUssRUFBRSxHQUFHLE1BQU0sMEJBQTBCLENBQUMsT0FBTyxDQUFDLENBQUM7SUFDNUQsTUFBTSxPQUFPLEdBQUcsTUFBTSxLQUFLLENBQUM7SUFDNUIsSUFBSSxPQUFPLENBQUMsUUFBUSxLQUFLLENBQUMsRUFBRSxDQUFDO1FBQzNCLE1BQU0sSUFBSSxLQUFLLENBQUMscUNBQXFDLE9BQU8sQ0FBQyxRQUFRLEVBQUUsQ0FBQyxDQUFDO0lBQzNFLENBQUM7QUFDSCxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBOb2RlIEdyYXBoaXRpIHJ1bnRpbWUgYW5kIHByb2Nlc3Mgc3VwZXJ2aXNpb24uXG4gKlxuICogQG1vZHVsZVxuICovXG5cbmltcG9ydCB7IGRlbGltaXRlciwgZGlybmFtZSB9IGZyb20gXCJub2RlOnBhdGhcIjtcbmltcG9ydCB7IGV4ZWMgfSBmcm9tIFwiQGRieC10b29scy9jb3JlXCI7XG5pbXBvcnQgdHlwZSB7IENoaWxkUHJvY2Vzc1Jlc3VsdCB9IGZyb20gXCJAZGJ4LXRvb2xzL2NvcmUvZXhlY1wiO1xuaW1wb3J0IHtcbiAgYXN5bmNVdGlscyxcbiAgZW52aXJvbm1lbnRVdGlscyxcbiAgZnVuY3Rpb25VdGlscyxcbiAgb3B0aW9ucyBhcyBzaGFyZWRPcHRpb25zLFxufSBmcm9tIFwiQGRieC10b29scy9zaGFyZWQtY29yZVwiO1xuaW1wb3J0IHsgY29lcmNlLCByY29tcGFyZSwgdHlwZSBTZW1WZXIgfSBmcm9tIFwic2VtdmVyXCI7XG5cbmltcG9ydCB7XG4gIGdyYXBoaXRpT3B0aW9uc0Vudmlyb25tZW50LFxuICByZXNvbHZlR3JhcGhpdGlPcHRpb25zLFxuICB0eXBlIEdyYXBoaXRpT3B0aW9ucyxcbiAgdHlwZSBSZXNvbHZlZEdyYXBoaXRpT3B0aW9ucyxcbn0gZnJvbSBcIi4vb3B0aW9ucy50c1wiO1xuXG4vKiogQ29udGV4dCBwYXNzZWQgdG8gb25lIEdyYXBoaXRpIHNpZGVjYXIgcmVhZGluZXNzIHByb2JlLiAqL1xuZXhwb3J0IGludGVyZmFjZSBHcmFwaGl0aUhlYWx0aENoZWNrQ29udGV4dCB7XG4gIHJlYWRvbmx5IHByb2Nlc3M6IENoaWxkUHJvY2Vzc1Jlc3VsdDtcbiAgcmVhZG9ubHkgc2lnbmFsOiBBYm9ydFNpZ25hbDtcbiAgcmVhZG9ubHkgYXR0ZW1wdDogbnVtYmVyO1xufVxuXG4vKiogSFRUUCBwcm9iZSB1c2VkIHRvIGRlY2lkZSB0aGF0IHRoZSBHcmFwaGl0aSBzaWRlY2FyIGhhcyBzdGFydGVkIGxpc3RlbmluZy4gKi9cbmV4cG9ydCB0eXBlIEdyYXBoaXRpSGVhbHRoQ2hlY2sgPSAoXG4gIGNvbnRleHQ6IEdyYXBoaXRpSGVhbHRoQ2hlY2tDb250ZXh0LFxuKSA9PiBib29sZWFuIHwgUHJvbWlzZUxpa2U8Ym9vbGVhbj47XG5cbi8qKiBBc3luYyBjcmVhdGlvbiByZXN1bHQgdGhhdCBwcmVzZXJ2ZXMgdGhlIGF3YWl0YWJsZSBjaGlsZCBoYW5kbGUuICovXG5leHBvcnQgaW50ZXJmYWNlIEdyYXBoaXRpQ2hpbGRQcm9jZXNzIHtcbiAgY2hpbGQ6IENoaWxkUHJvY2Vzc1Jlc3VsdDtcbn1cblxuLyoqIFNoYXJlZCBHcmFwaGl0aSBvcHRpb25zIHBsdXMgdGhlIE5vZGUtb25seSBzaWRlY2FyIHJlYWRpbmVzcyBwcm9iZS4gKi9cbmV4cG9ydCB0eXBlIEdyYXBoaXRpUnVudGltZU9wdGlvbnMgPSBHcmFwaGl0aU9wdGlvbnMgJiB7XG4gIC8qKiBSZWFkaW5lc3MgcHJvYmUgZm9yIHtAbGluayBjcmVhdGVHcmFwaGl0aUNoaWxkUHJvY2Vzc30uIERlZmF1bHRzIHRvIGAvaGVhbHRoY2hlY2tgLiAqL1xuICBoZWFsdGhDaGVjaz86IEdyYXBoaXRpSGVhbHRoQ2hlY2s7XG4gIC8qKiBDYW5jZWxzIHNpZGVjYXIgc3RhcnR1cCB3aXRob3V0IGNoYW5naW5nIHRoZSBzZXJpYWxpemVkIEdyYXBoaXRpIGNvbmZpZ3VyYXRpb24uICovXG4gIHNpZ25hbD86IEFib3J0U2lnbmFsO1xufTtcblxuY29uc3QgSEVBTFRIX0NIRUNLX0lOVEVSVkFMX01TID0gMjAwO1xuY29uc3QgUFlUSE9OX0NBTkRJREFURVMgPSBbXCJweXRob25cIiwgXCJweXRob24zXCJdIGFzIGNvbnN0O1xuY29uc3QgR1JBUEhJVElfSU1QT1JUX1BST0JFID0gXCJpbXBvcnQgZGJ4X3Rvb2xzLmdyYXBoaXRpXCI7XG5cbmludGVyZmFjZSBQeXRob25DYW5kaWRhdGUge1xuICBjb21tYW5kOiBzdHJpbmc7XG4gIHZlcnNpb246IFNlbVZlcjtcbn1cblxuY29uc3QgZ3JhcGhpdGlQeXRob24gPSBmdW5jdGlvblV0aWxzLm1lbW9pemUoYXN5bmMgKCk6IFByb21pc2U8c3RyaW5nIHwgdW5kZWZpbmVkPiA9PiB7XG4gIGNvbnN0IGF2YWlsYWJsZSA9IChcbiAgICBhd2FpdCBQcm9taXNlLmFsbChQWVRIT05fQ0FORElEQVRFUy5tYXAoKGNvbW1hbmQpID0+IF9wcm9iZVB5dGhvbihjb21tYW5kKSkpXG4gICkuZmlsdGVyKChjYW5kaWRhdGUpOiBjYW5kaWRhdGUgaXMgUHl0aG9uQ2FuZGlkYXRlID0+IGNhbmRpZGF0ZSAhPT0gdW5kZWZpbmVkKTtcbiAgYXZhaWxhYmxlLnNvcnQoKGxlZnQsIHJpZ2h0KSA9PiByY29tcGFyZShsZWZ0LnZlcnNpb24sIHJpZ2h0LnZlcnNpb24pKTtcbiAgcmV0dXJuIGF2YWlsYWJsZVswXT8uY29tbWFuZDtcbn0pO1xuXG5mdW5jdGlvbiBncmFwaGl0aU9wdGlvbnMob3B0aW9uczogR3JhcGhpdGlSdW50aW1lT3B0aW9ucyk6IEdyYXBoaXRpT3B0aW9ucyB7XG4gIGNvbnN0IHsgaGVhbHRoQ2hlY2s6IF9oZWFsdGhDaGVjaywgc2lnbmFsOiBfc2lnbmFsLCAuLi5ncmFwaGl0aSB9ID0gb3B0aW9ucztcbiAgcmV0dXJuIGdyYXBoaXRpO1xufVxuXG4vKiogTWlsbGlzZWNvbmRzIGxlZnQgaW4gYSBzdGFydHVwIGJ1ZGdldCBhZnRlciBgc3RhcnRlZEF0YC4gKi9cbmV4cG9ydCBmdW5jdGlvbiByZW1haW5pbmdUaW1lb3V0TXMoc3RhcnRlZEF0OiBudW1iZXIsIHRpbWVvdXRNczogbnVtYmVyLCBub3cgPSBEYXRlLm5vdygpKTogbnVtYmVyIHtcbiAgcmV0dXJuIE1hdGgubWF4KDAsIHRpbWVvdXRNcyAtIChub3cgLSBzdGFydGVkQXQpKTtcbn1cblxuZnVuY3Rpb24gX3J1bnRpbWVFbnZpcm9ubWVudChvcHRpb25zOiBSZXNvbHZlZEdyYXBoaXRpT3B0aW9ucyk6IE5vZGVKUy5Qcm9jZXNzRW52IHtcbiAgaWYgKG9wdGlvbnMubGlzdGVuLnNjaGVtZSAhPT0gXCJ0Y3BcIikgdGhyb3cgbmV3IEVycm9yKFwiR3JhcGhpdGkgcmVxdWlyZXMgYSBUQ1AgbGlzdGVuZXJcIik7XG4gIGNvbnN0IG5vZGVCaW4gPSBwcm9jZXNzLmVudi5EQlhfVE9PTFNfTk9ERV9CSU4/LnRyaW0oKTtcbiAgY29uc3QgcGF0aCA9IG5vZGVCaW5cbiAgICA/IFtkaXJuYW1lKG5vZGVCaW4pLCBwcm9jZXNzLmVudi5QQVRIXS5maWx0ZXIoQm9vbGVhbikuam9pbihkZWxpbWl0ZXIpXG4gICAgOiBwcm9jZXNzLmVudi5QQVRIO1xuICByZXR1cm4ge1xuICAgIC4uLnByb2Nlc3MuZW52LFxuICAgIC4uLihwYXRoID8geyBQQVRIOiBwYXRoIH0gOiB7fSksXG4gICAgLi4uZ3JhcGhpdGlPcHRpb25zRW52aXJvbm1lbnQob3B0aW9ucyksXG4gIH07XG59XG5cbi8qKiBSZXR1cm4gd2hldGhlciB0aGUgR3JhcGhpdGkgYC9oZWFsdGhjaGVja2AgZW5kcG9pbnQgcmVzcG9uZHMgc3VjY2Vzc2Z1bGx5LiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGdyYXBoaXRpSGVhbHRoQ2hlY2soXG4gIG9wdGlvbnM6IFBpY2s8UmVzb2x2ZWRHcmFwaGl0aU9wdGlvbnMsIFwibGlzdGVuXCIgfCBcImJlYXJlclwiPixcbiAgc2lnbmFsOiBBYm9ydFNpZ25hbCxcbik6IFByb21pc2U8Ym9vbGVhbj4ge1xuICB0cnkge1xuICAgIHJldHVybiAoXG4gICAgICBhd2FpdCBmZXRjaChncmFwaGl0aUh0dHBVcmwob3B0aW9ucywgXCIvaGVhbHRoY2hlY2tcIiksIHtcbiAgICAgICAgc2lnbmFsLFxuICAgICAgICBoZWFkZXJzOiBncmFwaGl0aVJlcXVlc3RIZWFkZXJzKG9wdGlvbnMpLFxuICAgICAgfSlcbiAgICApLm9rO1xuICB9IGNhdGNoIChlcnJvcikge1xuICAgIGlmIChzaWduYWwuYWJvcnRlZCkgdGhyb3cgZXJyb3I7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG59XG5cbi8qKiBQb2xsIGAvaGVhbHRoY2hlY2tgIHVudGlsIGl0IHN1Y2NlZWRzIG9yIGB0aW1lb3V0TXNgIGVsYXBzZXMuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gd2FpdEZvckdyYXBoaXRpSGVhbHRoKFxuICBvcHRpb25zOiBQaWNrPFJlc29sdmVkR3JhcGhpdGlPcHRpb25zLCBcImxpc3RlblwiIHwgXCJiZWFyZXJcIj4sXG4gIHRpbWVvdXRNczogbnVtYmVyLFxuICBzaWduYWw/OiBBYm9ydFNpZ25hbCxcbik6IFByb21pc2U8dm9pZD4ge1xuICBjb25zdCBidWRnZXQgPSBNYXRoLm1heCgxLCB0aW1lb3V0TXMpO1xuICBmb3IgYXdhaXQgKGNvbnN0IGhlYWx0aHkgb2YgYXN5bmNVdGlscy5wb2xsKFxuICAgICh7IHNpZ25hbDogcG9sbFNpZ25hbCB9KSA9PiBncmFwaGl0aUhlYWx0aENoZWNrKG9wdGlvbnMsIHBvbGxTaWduYWwpLFxuICAgIHtcbiAgICAgIGludGVydmFsTXM6IEhFQUxUSF9DSEVDS19JTlRFUlZBTF9NUyxcbiAgICAgIHRpbWVvdXRNczogYnVkZ2V0LFxuICAgICAgc2lnbmFsLFxuICAgICAgcHJlZGljYXRlOiAocmVhZHkpID0+ICFyZWFkeSxcbiAgICB9LFxuICApKSB7XG4gICAgaWYgKGhlYWx0aHkpIHJldHVybjtcbiAgfVxuICB0aHJvdyBuZXcgRXJyb3IoXCJHcmFwaGl0aSBzaWRlY2FyIGhlYWx0aGNoZWNrIGRpZCBub3Qgc3VjY2VlZFwiKTtcbn1cblxuLyoqIEJ1aWxkIGF1dGhvcml6YXRpb24gaGVhZGVycyBmb3Igb25lIG9wdGlvbmFsbHkgc2VjdXJlZCBHcmFwaGl0aSBydW50aW1lLiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGdyYXBoaXRpUmVxdWVzdEhlYWRlcnMoXG4gIG9wdGlvbnM6IFBpY2s8UmVzb2x2ZWRHcmFwaGl0aU9wdGlvbnMsIFwiYmVhcmVyXCI+LFxuKTogUmVhZG9ubHk8UmVjb3JkPHN0cmluZywgc3RyaW5nPj4ge1xuICByZXR1cm4gb3B0aW9ucy5iZWFyZXIgPyB7IGF1dGhvcml6YXRpb246IGBCZWFyZXIgJHtvcHRpb25zLmJlYXJlcn1gIH0gOiB7fTtcbn1cblxuLyoqIEV4ZWN1dGFibGUgYW5kIGFyZ3VtZW50cyB1c2VkIHRvIGxhdW5jaCBHcmFwaGl0aS4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgR3JhcGhpdGlQeXRob25Db21tYW5kIHtcbiAgY29tbWFuZDogc3RyaW5nO1xuICBhcmdzOiBzdHJpbmdbXTtcbn1cblxuLyoqIFJlc29sdmUgY29uZmlndXJlZCBvciBhcHAtaW5zdGFsbGVkIFB5dGhvbiwgb3RoZXJ3aXNlIGEgdXYtcHJvdmlzaW9uZWQgcnVudGltZS4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiByZXNvbHZlR3JhcGhpdGlQeXRob25Db21tYW5kKFxuICBvcHRpb25zOiB7IGRldj86IGJvb2xlYW4gfSA9IHt9LFxuICAuLi5hcmdzOiBzdHJpbmdbXVxuKTogUHJvbWlzZTxHcmFwaGl0aVB5dGhvbkNvbW1hbmQ+IHtcbiAgY29uc3QgcHl0aG9uID0gcHJvY2Vzcy5lbnYuUFlUSE9OPy50cmltKCk7XG4gIGlmIChweXRob24pIHJldHVybiB7IGNvbW1hbmQ6IHB5dGhvbiwgYXJncyB9O1xuICBpZiAoZW52aXJvbm1lbnRVdGlscy5pc0RhdGFicmlja3NBcHBFbnYoKSkge1xuICAgIGNvbnN0IGluc3RhbGxlZCA9IGF3YWl0IGdyYXBoaXRpUHl0aG9uKCk7XG4gICAgaWYgKGluc3RhbGxlZCkgcmV0dXJuIHsgY29tbWFuZDogaW5zdGFsbGVkLCBhcmdzIH07XG4gIH1cbiAgY29uc3QgZXh0cmEgPSBvcHRpb25zLmRldiA/IFwiW2Rldl1cIiA6IFwiXCI7XG4gIGNvbnN0IHBhY2thZ2VBcmdzID0gW1xuICAgIFwiLS13aXRoXCIsXG4gICAgYGRieC10b29scy1ncmFwaGl0aSR7ZXh0cmF9PT0keyhhd2FpdCBpbXBvcnQoXCIuLi8uLi9pbmRleC50c1wiKSkuUEFDS0FHRV9WRVJTSU9OfWAsXG4gIF07XG4gIHJldHVybiB7XG4gICAgY29tbWFuZDogXCJ1dlwiLFxuICAgIGFyZ3M6IFtcInJ1blwiLCBcIi0tbm8tcHJvamVjdFwiLCAuLi5wYWNrYWdlQXJncywgXCItLXB5dGhvblwiLCBcInB5dGhvbjNcIiwgXCJweXRob25cIiwgLi4uYXJnc10sXG4gIH07XG59XG5cbmFzeW5jIGZ1bmN0aW9uIF9wcm9iZVB5dGhvbihjb21tYW5kOiBzdHJpbmcpOiBQcm9taXNlPFB5dGhvbkNhbmRpZGF0ZSB8IHVuZGVmaW5lZD4ge1xuICBjb25zdCB2ZXJzaW9uUmVzdWx0ID0gYXdhaXQgZXhlYy5zcGF3bihjb21tYW5kLCBbXCItVlwiXSwge1xuICAgIGNoZWNrOiBmYWxzZSxcbiAgICBzdGRpbjogXCJpZ25vcmVcIixcbiAgICBzdGRvdXQ6IFwiY2FwdHVyZVwiLFxuICAgIHN0ZGVycjogXCJjYXB0dXJlXCIsXG4gICAgdHJpbTogdHJ1ZSxcbiAgfSk7XG4gIGlmICh2ZXJzaW9uUmVzdWx0LmV4aXRDb2RlICE9PSAwKSByZXR1cm4gdW5kZWZpbmVkO1xuICBjb25zdCB2ZXJzaW9uID0gY29lcmNlKGAke3ZlcnNpb25SZXN1bHQuc3Rkb3V0fVxcbiR7dmVyc2lvblJlc3VsdC5zdGRlcnJ9YCk7XG4gIGlmICghdmVyc2lvbikgcmV0dXJuIHVuZGVmaW5lZDtcblxuICBjb25zdCBpbXBvcnRSZXN1bHQgPSBhd2FpdCBleGVjLnNwYXduKGNvbW1hbmQsIFtcIi1jXCIsIEdSQVBISVRJX0lNUE9SVF9QUk9CRV0sIHtcbiAgICBjaGVjazogZmFsc2UsXG4gICAgc3RkaW46IFwiaWdub3JlXCIsXG4gICAgc3Rkb3V0OiBcImlnbm9yZVwiLFxuICAgIHN0ZGVycjogXCJpZ25vcmVcIixcbiAgfSk7XG4gIHJldHVybiBpbXBvcnRSZXN1bHQuZXhpdENvZGUgPT09IDAgPyB7IGNvbW1hbmQsIHZlcnNpb24gfSA6IHVuZGVmaW5lZDtcbn1cblxuLyoqIEJ1aWxkIG9uZSBIVFRQIFVSTCBmb3IgYSByZXNvbHZlZCBHcmFwaGl0aSBsaXN0ZW5lci4gKi9cbmV4cG9ydCBmdW5jdGlvbiBncmFwaGl0aUh0dHBVcmwoXG4gIG9wdGlvbnM6IFBpY2s8UmVzb2x2ZWRHcmFwaGl0aU9wdGlvbnMsIFwibGlzdGVuXCI+LFxuICBwYXRoOiBzdHJpbmcsXG4pOiBzdHJpbmcge1xuICByZXR1cm4gYCR7c2hhcmVkT3B0aW9uc1xuICAgIC5mb3JtYXRMaXN0ZW5BZGRyZXNzKG9wdGlvbnMubGlzdGVuKVxuICAgIC5yZXBsYWNlKC9edGNwOi8sIFwiaHR0cDpcIil9JHtwYXRoLnN0YXJ0c1dpdGgoXCIvXCIpID8gcGF0aCA6IGAvJHtwYXRofWB9YDtcbn1cblxuLyoqIEJ1aWxkIG9uZSByZWFkaW5lc3MtZ2F0ZWQgR3JhcGhpdGkgc2lkZWNhciBmcm9tIHRoZSBzaGFyZWQgdHlwZWQgb3B0aW9ucy4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBjcmVhdGVHcmFwaGl0aUNoaWxkUHJvY2VzcyhcbiAgb3B0aW9uczogR3JhcGhpdGlSdW50aW1lT3B0aW9ucyA9IHt9LFxuKTogUHJvbWlzZTxHcmFwaGl0aUNoaWxkUHJvY2Vzcz4ge1xuICBjb25zdCBoZWFsdGhDaGVjayA9IG9wdGlvbnMuaGVhbHRoQ2hlY2s7XG4gIGNvbnN0IHJlc29sdmVkID0gcmVzb2x2ZUdyYXBoaXRpT3B0aW9ucyhncmFwaGl0aU9wdGlvbnMob3B0aW9ucykpO1xuICBjb25zdCBweXRob24gPSBhd2FpdCByZXNvbHZlR3JhcGhpdGlQeXRob25Db21tYW5kKFxuICAgIHsgZGV2OiAhcmVzb2x2ZWQuZGF0YWJhc2VVcmwgfSxcbiAgICBcIi1tXCIsXG4gICAgXCJkYnhfdG9vbHMuZ3JhcGhpdGlcIixcbiAgKTtcbiAgY29uc3QgY2hpbGQgPSBleGVjLnNwYXduKHB5dGhvbi5jb21tYW5kLCBweXRob24uYXJncywge1xuICAgIGVudjogX3J1bnRpbWVFbnZpcm9ubWVudChyZXNvbHZlZCksXG4gICAgZm9yd2FyZFRlcm1pbmF0aW9uU2lnbmFsczogZmFsc2UsXG4gIH0pO1xuICBjb25zdCBjb250cm9sbGVyID0gbmV3IEFib3J0Q29udHJvbGxlcigpO1xuICBjb25zdCBzdGFydHVwU2lnbmFsID0gb3B0aW9ucy5zaWduYWxcbiAgICA/IEFib3J0U2lnbmFsLmFueShbY29udHJvbGxlci5zaWduYWwsIG9wdGlvbnMuc2lnbmFsXSlcbiAgICA6IGNvbnRyb2xsZXIuc2lnbmFsO1xuICBjb25zdCBwcm9iZSA9IGhlYWx0aENoZWNrID8/ICgoeyBzaWduYWwgfSkgPT4gZ3JhcGhpdGlIZWFsdGhDaGVjayhyZXNvbHZlZCwgc2lnbmFsKSk7XG4gIHRyeSB7XG4gICAgYXdhaXQgUHJvbWlzZS5yYWNlKFtcbiAgICAgIHdhaXRGb3JHcmFwaGl0aUNoaWxkKGNoaWxkLCBwcm9iZSwgcmVzb2x2ZWQuc3RhcnR1cFRpbWVvdXRNcywgc3RhcnR1cFNpZ25hbCksXG4gICAgICBjaGlsZC50aGVuKChyZXN1bHQpID0+IHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICAgIGBHcmFwaGl0aSBjaGlsZCAke2NoaWxkLnBpZCA/PyBcIjx1bmtub3duPlwifSBleGl0ZWQgYmVmb3JlIGJlY29taW5nIHJlYWR5IGAgK1xuICAgICAgICAgICAgYChleGl0ICR7cmVzdWx0LmV4aXRDb2RlfSlgLFxuICAgICAgICApO1xuICAgICAgfSksXG4gICAgXSk7XG4gICAgcmV0dXJuIHsgY2hpbGQgfTtcbiAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICBhd2FpdCBjaGlsZC5zaHV0ZG93bigpO1xuICAgIHRocm93IGVycm9yO1xuICB9IGZpbmFsbHkge1xuICAgIGNvbnRyb2xsZXIuYWJvcnQoKTtcbiAgfVxufVxuXG5hc3luYyBmdW5jdGlvbiB3YWl0Rm9yR3JhcGhpdGlDaGlsZChcbiAgY2hpbGQ6IENoaWxkUHJvY2Vzc1Jlc3VsdCxcbiAgaGVhbHRoQ2hlY2s6IEdyYXBoaXRpSGVhbHRoQ2hlY2ssXG4gIHRpbWVvdXRNczogbnVtYmVyLFxuICBzaWduYWw6IEFib3J0U2lnbmFsLFxuKTogUHJvbWlzZTx2b2lkPiB7XG4gIGZvciBhd2FpdCAoY29uc3QgaGVhbHRoeSBvZiBhc3luY1V0aWxzLnBvbGwoXG4gICAgKHsgYXR0ZW1wdCwgc2lnbmFsOiBwb2xsU2lnbmFsIH0pID0+XG4gICAgICBoZWFsdGhDaGVjayh7IHByb2Nlc3M6IGNoaWxkLCBzaWduYWw6IHBvbGxTaWduYWwsIGF0dGVtcHQgfSksXG4gICAge1xuICAgICAgaW50ZXJ2YWxNczogSEVBTFRIX0NIRUNLX0lOVEVSVkFMX01TLFxuICAgICAgdGltZW91dE1zLFxuICAgICAgc2lnbmFsLFxuICAgICAgcHJlZGljYXRlOiAocmVhZHkpID0+ICFyZWFkeSxcbiAgICB9LFxuICApKSB7XG4gICAgaWYgKGhlYWx0aHkpIHJldHVybjtcbiAgfVxufVxuXG4vKiogUnVuIHRoZSBzdXBlcnZpc2VkIHN0YWNrIHVudGlsIHRoZSBjaGlsZCBleGl0cy4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBydW5HcmFwaGl0aShvcHRpb25zOiBHcmFwaGl0aVJ1bnRpbWVPcHRpb25zID0ge30pOiBQcm9taXNlPHZvaWQ+IHtcbiAgY29uc3QgeyBjaGlsZCB9ID0gYXdhaXQgY3JlYXRlR3JhcGhpdGlDaGlsZFByb2Nlc3Mob3B0aW9ucyk7XG4gIGNvbnN0IG91dGNvbWUgPSBhd2FpdCBjaGlsZDtcbiAgaWYgKG91dGNvbWUuZXhpdENvZGUgIT09IDApIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoYEdyYXBoaXRpIGNoaWxkIGV4aXRlZCB3aXRoIHN0YXR1cyAke291dGNvbWUuZXhpdENvZGV9YCk7XG4gIH1cbn1cbiJdfQ==
@@ -0,0 +1,38 @@
1
+ /**
2
+ * AppKit memory plugin with Databricks-first tools and lazy Graphiti fallback.
3
+ *
4
+ * @module
5
+ */
6
+ import { type PluginManifest } from "@databricks/appkit";
7
+ import { type ToolkitEntry, type ToolkitOptions, type ToolRegistry } from "@databricks/appkit/beta";
8
+ import { ToolRegistryPlugin, type AgentToolExecutionContext } from "@dbx-tools/appkit";
9
+ import { type MemoryPluginConfig } from "./config.ts";
10
+ /** AppKit memory plugin with Databricks managed memory and Graphiti fallback. */
11
+ export declare class MemoryPlugin extends ToolRegistryPlugin<MemoryPluginConfig> {
12
+ static phase: "deferred";
13
+ static manifest: PluginManifest<"memory">;
14
+ private readonly logger;
15
+ private resolved?;
16
+ private databricks?;
17
+ private graphiti?;
18
+ private graphitiStarting?;
19
+ private readonly graphitiStartupAbort;
20
+ private closed;
21
+ protected get toolRegistry(): ToolRegistry;
22
+ setup(): Promise<void>;
23
+ toolkit(options?: ToolkitOptions): Promise<Record<string, ToolkitEntry>>;
24
+ executeAgentTool(name: string, args: unknown, signal?: AbortSignal, context?: AgentToolExecutionContext): Promise<unknown>;
25
+ abortActiveOperations(): void;
26
+ shutdown(): Promise<void>;
27
+ private registry;
28
+ private remember;
29
+ private recall;
30
+ private saveTurn;
31
+ private databricksBackend;
32
+ private shouldFallbackFromDatabricks;
33
+ private graphitiBackend;
34
+ private actorId;
35
+ private requireConfig;
36
+ }
37
+ /** AppKit registration factory for {@link MemoryPlugin}. */
38
+ export declare const memory: import("@databricks/appkit").ToPlugin<typeof MemoryPlugin, MemoryPluginConfig, "memory">;