@grackle-ai/core 0.96.1 → 0.96.3

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 (130) hide show
  1. package/dist/event-processor.js +1 -1
  2. package/dist/event-processor.js.map +1 -1
  3. package/dist/{grpc-shared.d.ts → grpc-shared-utils.d.ts} +6 -10
  4. package/dist/grpc-shared-utils.d.ts.map +1 -0
  5. package/dist/grpc-shared-utils.js +57 -0
  6. package/dist/grpc-shared-utils.js.map +1 -0
  7. package/dist/index.d.ts +33 -27
  8. package/dist/index.d.ts.map +1 -1
  9. package/dist/index.js +42 -31
  10. package/dist/index.js.map +1 -1
  11. package/dist/lifecycle-streams.d.ts +27 -0
  12. package/dist/lifecycle-streams.d.ts.map +1 -0
  13. package/dist/lifecycle-streams.js +46 -0
  14. package/dist/lifecycle-streams.js.map +1 -0
  15. package/dist/reanimate-agent.js +1 -1
  16. package/dist/reanimate-agent.js.map +1 -1
  17. package/dist/task-session.js +1 -1
  18. package/dist/task-session.js.map +1 -1
  19. package/package.json +8 -8
  20. package/dist/codespace-handlers.d.ts +0 -6
  21. package/dist/codespace-handlers.d.ts.map +0 -1
  22. package/dist/codespace-handlers.js +0 -66
  23. package/dist/codespace-handlers.js.map +0 -1
  24. package/dist/cron-phase.d.ts +0 -46
  25. package/dist/cron-phase.d.ts.map +0 -1
  26. package/dist/cron-phase.js +0 -88
  27. package/dist/cron-phase.js.map +0 -1
  28. package/dist/dispatch-phase.d.ts +0 -46
  29. package/dist/dispatch-phase.d.ts.map +0 -1
  30. package/dist/dispatch-phase.js +0 -99
  31. package/dist/dispatch-phase.js.map +0 -1
  32. package/dist/environment-handlers.d.ts +0 -16
  33. package/dist/environment-handlers.d.ts.map +0 -1
  34. package/dist/environment-handlers.js +0 -255
  35. package/dist/environment-handlers.js.map +0 -1
  36. package/dist/environment-reconciliation.d.ts +0 -35
  37. package/dist/environment-reconciliation.d.ts.map +0 -1
  38. package/dist/environment-reconciliation.js +0 -74
  39. package/dist/environment-reconciliation.js.map +0 -1
  40. package/dist/escalation-handlers.d.ts +0 -8
  41. package/dist/escalation-handlers.d.ts.map +0 -1
  42. package/dist/escalation-handlers.js +0 -60
  43. package/dist/escalation-handlers.js.map +0 -1
  44. package/dist/finding-handlers.d.ts +0 -8
  45. package/dist/finding-handlers.d.ts.map +0 -1
  46. package/dist/finding-handlers.js +0 -38
  47. package/dist/finding-handlers.js.map +0 -1
  48. package/dist/grpc-proto-converters.d.ts +0 -31
  49. package/dist/grpc-proto-converters.d.ts.map +0 -1
  50. package/dist/grpc-proto-converters.js +0 -222
  51. package/dist/grpc-proto-converters.js.map +0 -1
  52. package/dist/grpc-service.d.ts +0 -14
  53. package/dist/grpc-service.d.ts.map +0 -1
  54. package/dist/grpc-service.js +0 -46
  55. package/dist/grpc-service.js.map +0 -1
  56. package/dist/grpc-shared.d.ts.map +0 -1
  57. package/dist/grpc-shared.js +0 -110
  58. package/dist/grpc-shared.js.map +0 -1
  59. package/dist/knowledge-handlers.d.ts +0 -12
  60. package/dist/knowledge-handlers.d.ts.map +0 -1
  61. package/dist/knowledge-handlers.js +0 -149
  62. package/dist/knowledge-handlers.js.map +0 -1
  63. package/dist/lifecycle-cleanup.d.ts +0 -13
  64. package/dist/lifecycle-cleanup.d.ts.map +0 -1
  65. package/dist/lifecycle-cleanup.js +0 -35
  66. package/dist/lifecycle-cleanup.js.map +0 -1
  67. package/dist/lifecycle.d.ts +0 -44
  68. package/dist/lifecycle.d.ts.map +0 -1
  69. package/dist/lifecycle.js +0 -169
  70. package/dist/lifecycle.js.map +0 -1
  71. package/dist/orphan-phase.d.ts +0 -27
  72. package/dist/orphan-phase.d.ts.map +0 -1
  73. package/dist/orphan-phase.js +0 -69
  74. package/dist/orphan-phase.js.map +0 -1
  75. package/dist/persona-handlers.d.ts +0 -12
  76. package/dist/persona-handlers.d.ts.map +0 -1
  77. package/dist/persona-handlers.js +0 -156
  78. package/dist/persona-handlers.js.map +0 -1
  79. package/dist/root-task-boot.d.ts +0 -67
  80. package/dist/root-task-boot.d.ts.map +0 -1
  81. package/dist/root-task-boot.js +0 -234
  82. package/dist/root-task-boot.js.map +0 -1
  83. package/dist/schedule-expression.d.ts +0 -43
  84. package/dist/schedule-expression.d.ts.map +0 -1
  85. package/dist/schedule-expression.js +0 -105
  86. package/dist/schedule-expression.js.map +0 -1
  87. package/dist/schedule-handlers.d.ts +0 -12
  88. package/dist/schedule-handlers.d.ts.map +0 -1
  89. package/dist/schedule-handlers.js +0 -122
  90. package/dist/schedule-handlers.js.map +0 -1
  91. package/dist/session-handlers.d.ts +0 -40
  92. package/dist/session-handlers.d.ts.map +0 -1
  93. package/dist/session-handlers.js +0 -610
  94. package/dist/session-handlers.js.map +0 -1
  95. package/dist/settings-handlers.d.ts +0 -10
  96. package/dist/settings-handlers.d.ts.map +0 -1
  97. package/dist/settings-handlers.js +0 -80
  98. package/dist/settings-handlers.js.map +0 -1
  99. package/dist/signals/escalation-auto.d.ts +0 -20
  100. package/dist/signals/escalation-auto.d.ts.map +0 -1
  101. package/dist/signals/escalation-auto.js +0 -126
  102. package/dist/signals/escalation-auto.js.map +0 -1
  103. package/dist/signals/orphan-reparent.d.ts +0 -31
  104. package/dist/signals/orphan-reparent.d.ts.map +0 -1
  105. package/dist/signals/orphan-reparent.js +0 -175
  106. package/dist/signals/orphan-reparent.js.map +0 -1
  107. package/dist/signals/sigchld.d.ts +0 -12
  108. package/dist/signals/sigchld.d.ts.map +0 -1
  109. package/dist/signals/sigchld.js +0 -177
  110. package/dist/signals/sigchld.js.map +0 -1
  111. package/dist/task-handlers.d.ts +0 -22
  112. package/dist/task-handlers.d.ts.map +0 -1
  113. package/dist/task-handlers.js +0 -518
  114. package/dist/task-handlers.js.map +0 -1
  115. package/dist/test-utils/integration-setup.d.ts +0 -11
  116. package/dist/test-utils/integration-setup.d.ts.map +0 -1
  117. package/dist/test-utils/integration-setup.js +0 -26
  118. package/dist/test-utils/integration-setup.js.map +0 -1
  119. package/dist/token-handlers.d.ts +0 -12
  120. package/dist/token-handlers.d.ts.map +0 -1
  121. package/dist/token-handlers.js +0 -85
  122. package/dist/token-handlers.js.map +0 -1
  123. package/dist/utils/format-gh-error.d.ts +0 -6
  124. package/dist/utils/format-gh-error.d.ts.map +0 -1
  125. package/dist/utils/format-gh-error.js +0 -30
  126. package/dist/utils/format-gh-error.js.map +0 -1
  127. package/dist/workspace-handlers.d.ts +0 -16
  128. package/dist/workspace-handlers.d.ts.map +0 -1
  129. package/dist/workspace-handlers.js +0 -146
  130. package/dist/workspace-handlers.js.map +0 -1
@@ -1 +0,0 @@
1
- {"version":3,"file":"grpc-shared.d.ts","sourceRoot":"","sources":["../src/grpc-shared.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AASvD,oEAAoE;AACpE,eAAO,MAAM,gBAAgB,EAAE,WAAW,CAAC,MAAM,CAA4C,CAAC;AAE9F,oFAAoF;AACpF,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,GAAG,IAAI,CAa9E;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAYvD;AAED;;;GAGG;AACH,wBAAgB,4BAA4B,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,CAczE;AAED;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,UAAU,GAAG,IAAI,CAgD/D"}
@@ -1,110 +0,0 @@
1
- import { ConnectError, Code } from "@connectrpc/connect";
2
- import { create } from "@bufbuild/protobuf";
3
- import { grackle, powerline } from "@grackle-ai/common";
4
- import { MAX_TASK_DEPTH, ROOT_TASK_ID, SESSION_STATUS, TERMINAL_SESSION_STATUSES, END_REASON, } from "@grackle-ai/common";
5
- import { transferAllPipeSubscriptions } from "./signals/orphan-reparent.js";
6
- import { sessionStore, taskStore } from "@grackle-ai/database";
7
- import * as adapterManager from "./adapter-manager.js";
8
- import * as streamHub from "./stream-hub.js";
9
- import * as streamRegistry from "./stream-registry.js";
10
- import { cleanupLifecycleStream } from "./lifecycle.js";
11
- import { logger } from "./logger.js";
12
- import { emit } from "./event-bus.js";
13
- /** Valid pipe mode values for SpawnRequest and StartTaskRequest. */
14
- export const VALID_PIPE_MODES = new Set(["", "sync", "async", "detach"]);
15
- /** Validate pipe mode and parentSessionId. Throws ConnectError on invalid input. */
16
- export function validatePipeInputs(pipe, parentSessionId) {
17
- if (pipe && !VALID_PIPE_MODES.has(pipe)) {
18
- throw new ConnectError(`Invalid pipe mode: "${pipe}". Must be "sync", "async", "detach", or empty.`, Code.InvalidArgument);
19
- }
20
- if (pipe && pipe !== "detach" && !parentSessionId) {
21
- throw new ConnectError(`Pipe mode "${pipe}" requires parent_session_id`, Code.InvalidArgument);
22
- }
23
- }
24
- /**
25
- * Map a bind host to a dialable URL host. Wildcard addresses become loopback,
26
- * unless GRACKLE_DOCKER_HOST is set (DooD mode) — in that case, use that value
27
- * so sibling containers can reach the server by container name.
28
- */
29
- export function toDialableHost(bindHost) {
30
- if (bindHost === "0.0.0.0" || bindHost === "::") {
31
- const dockerHost = process.env.GRACKLE_DOCKER_HOST;
32
- if (dockerHost) {
33
- if (dockerHost.startsWith("[") && dockerHost.endsWith("]")) {
34
- return dockerHost;
35
- }
36
- return dockerHost.includes(":") ? `[${dockerHost}]` : dockerHost;
37
- }
38
- return bindHost === "::" ? "[::1]" : "127.0.0.1";
39
- }
40
- return bindHost.includes(":") ? `[${bindHost}]` : bindHost;
41
- }
42
- /**
43
- * Walk up the task parent chain and return the environmentId from the first
44
- * ancestor that has a session. Returns empty string if no ancestor has one.
45
- */
46
- export function resolveAncestorEnvironmentId(parentTaskId) {
47
- let currentId = parentTaskId;
48
- for (let i = 0; i < MAX_TASK_DEPTH && currentId; i++) {
49
- const session = sessionStore.getLatestSessionForTask(currentId);
50
- if (session?.environmentId) {
51
- return session.environmentId;
52
- }
53
- const parent = taskStore.getTask(currentId);
54
- if (!parent) {
55
- break;
56
- }
57
- currentId = parent.parentTaskId;
58
- }
59
- return "";
60
- }
61
- /**
62
- * Terminate a session and clean up all associated streams and subscriptions.
63
- *
64
- * If the session is already in a terminal state the status update is skipped,
65
- * but lifecycle and subscription streams are always removed so stale handles
66
- * do not accumulate.
67
- */
68
- export function killSessionAndCleanup(session) {
69
- if (!TERMINAL_SESSION_STATUSES.has(session.status)) {
70
- sessionStore.updateSession(session.id, SESSION_STATUS.STOPPED, undefined, undefined, END_REASON.KILLED);
71
- streamHub.publish(create(grackle.SessionEventSchema, {
72
- sessionId: session.id,
73
- type: grackle.EventType.STATUS,
74
- timestamp: new Date().toISOString(),
75
- content: END_REASON.KILLED,
76
- raw: "",
77
- }));
78
- if (session.taskId) {
79
- const task = taskStore.getTask(session.taskId);
80
- if (task) {
81
- emit("task.updated", { taskId: task.id, workspaceId: task.workspaceId || "" });
82
- }
83
- }
84
- }
85
- // Forward kill to PowerLine so the agent process is actually terminated.
86
- // The orphan callback also sends a kill, but that fires asynchronously
87
- // after subscription cleanup — this ensures immediate process termination.
88
- const conn = adapterManager.getConnection(session.environmentId);
89
- if (conn) {
90
- conn.client.kill(create(powerline.KillRequestSchema, { id: session.id, reason: END_REASON.KILLED })).catch((err) => {
91
- logger.debug({ err, sessionId: session.id }, "PowerLine kill failed (process may have already exited)");
92
- });
93
- }
94
- // Transfer ALL pipe fds to grandparent BEFORE cleaning up subscriptions.
95
- // Always transfer regardless of orphaned tasks: ipc_spawn creates child sessions
96
- // (not tasks), so pipe subs exist even when getOrphanedTasks returns empty.
97
- if (session.taskId) {
98
- const task = taskStore.getTask(session.taskId);
99
- if (task) {
100
- const grandparentId = task.parentTaskId || ROOT_TASK_ID;
101
- transferAllPipeSubscriptions(task.id, grandparentId);
102
- }
103
- }
104
- cleanupLifecycleStream(session.id);
105
- const subs = streamRegistry.getSubscriptionsForSession(session.id);
106
- for (const sub of subs) {
107
- streamRegistry.unsubscribe(sub.id);
108
- }
109
- }
110
- //# sourceMappingURL=grpc-shared.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"grpc-shared.js","sourceRoot":"","sources":["../src/grpc-shared.ts"],"names":[],"mappings":"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"}
@@ -1,12 +0,0 @@
1
- import { grackle } from "@grackle-ai/common";
2
- /** Search the knowledge graph using semantic similarity. */
3
- export declare function searchKnowledge(req: grackle.SearchKnowledgeRequest): Promise<grackle.SearchKnowledgeResponse>;
4
- /** Get a knowledge node by ID. */
5
- export declare function getKnowledgeNode(req: grackle.GetKnowledgeNodeRequest): Promise<grackle.GetKnowledgeNodeResponse>;
6
- /** Expand a knowledge node to retrieve its neighbors. */
7
- export declare function expandKnowledgeNode(req: grackle.ExpandKnowledgeNodeRequest): Promise<grackle.ExpandKnowledgeNodeResponse>;
8
- /** List recently created knowledge nodes. */
9
- export declare function listRecentKnowledgeNodes(req: grackle.ListRecentKnowledgeNodesRequest): Promise<grackle.ListRecentKnowledgeNodesResponse>;
10
- /** Create a new native knowledge node with embedding. */
11
- export declare function createKnowledgeNode(req: grackle.CreateKnowledgeNodeRequest): Promise<grackle.CreateKnowledgeNodeResponse>;
12
- //# sourceMappingURL=knowledge-handlers.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"knowledge-handlers.d.ts","sourceRoot":"","sources":["../src/knowledge-handlers.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AA+D7C,4DAA4D;AAC5D,wBAAsB,eAAe,CAAC,GAAG,EAAE,OAAO,CAAC,sBAAsB,GAAG,OAAO,CAAC,OAAO,CAAC,uBAAuB,CAAC,CAqBnH;AAED,kCAAkC;AAClC,wBAAsB,gBAAgB,CAAC,GAAG,EAAE,OAAO,CAAC,uBAAuB,GAAG,OAAO,CAAC,OAAO,CAAC,wBAAwB,CAAC,CAmBtH;AAED,yDAAyD;AACzD,wBAAsB,mBAAmB,CAAC,GAAG,EAAE,OAAO,CAAC,0BAA0B,GAAG,OAAO,CAAC,OAAO,CAAC,2BAA2B,CAAC,CAmB/H;AAED,6CAA6C;AAC7C,wBAAsB,wBAAwB,CAAC,GAAG,EAAE,OAAO,CAAC,+BAA+B,GAAG,OAAO,CAAC,OAAO,CAAC,gCAAgC,CAAC,CAmB9I;AAED,yDAAyD;AACzD,wBAAsB,mBAAmB,CAAC,GAAG,EAAE,OAAO,CAAC,0BAA0B,GAAG,OAAO,CAAC,OAAO,CAAC,2BAA2B,CAAC,CAuB/H"}
@@ -1,149 +0,0 @@
1
- import { ConnectError, Code } from "@connectrpc/connect";
2
- import { create } from "@bufbuild/protobuf";
3
- import { grackle } from "@grackle-ai/common";
4
- import { knowledgeSearch, getNode as getKnowledgeNodeById, expandNode, createNativeNode, ingest, createPassThroughChunker, listRecentNodes, } from "@grackle-ai/knowledge";
5
- import { getKnowledgeEmbedder, isKnowledgeEnabled } from "./knowledge-init.js";
6
- import { isNeo4jHealthy } from "./knowledge-health.js";
7
- import { knowledgeNodeToProto, knowledgeEdgeToProto } from "./grpc-proto-converters.js";
8
- import { logger } from "./logger.js";
9
- /** Error message returned when Neo4j is unreachable. */
10
- const NEO4J_UNAVAILABLE_MESSAGE = "Knowledge graph temporarily unavailable — Neo4j unreachable";
11
- /**
12
- * Guard that checks Neo4j health status.
13
- *
14
- * @throws ConnectError with Code.Unavailable if Neo4j is unreachable.
15
- */
16
- function requireKnowledgeReady() {
17
- if (!isNeo4jHealthy()) {
18
- throw new ConnectError(NEO4J_UNAVAILABLE_MESSAGE, Code.Unavailable);
19
- }
20
- }
21
- /**
22
- * Guard that checks embedder availability and Neo4j health, returning the embedder.
23
- *
24
- * @throws ConnectError with Code.Unavailable if knowledge is not ready.
25
- */
26
- function requireEmbedder() {
27
- const embedder = getKnowledgeEmbedder();
28
- if (!embedder) {
29
- throw new ConnectError("Knowledge graph not available", Code.Unavailable);
30
- }
31
- requireKnowledgeReady();
32
- return embedder;
33
- }
34
- /**
35
- * Wrap non-ConnectError exceptions as Code.Unavailable.
36
- *
37
- * ConnectErrors (e.g. NotFound, InvalidArgument) are re-thrown as-is so
38
- * the handler's own error semantics are preserved.
39
- */
40
- function wrapNeo4jError(err) {
41
- if (err instanceof ConnectError) {
42
- throw err;
43
- }
44
- // Log the full error server-side for debugging; return a generic message
45
- // to clients to avoid leaking internal details (hostnames, ports, etc.)
46
- logger.error({ err }, "Knowledge graph operation failed");
47
- throw new ConnectError(NEO4J_UNAVAILABLE_MESSAGE, Code.Unavailable);
48
- }
49
- /** Search the knowledge graph using semantic similarity. */
50
- export async function searchKnowledge(req) {
51
- const embedder = requireEmbedder();
52
- try {
53
- const results = await knowledgeSearch(req.query, embedder, {
54
- limit: req.limit || 10,
55
- workspaceId: req.workspaceId || undefined,
56
- });
57
- return create(grackle.SearchKnowledgeResponseSchema, {
58
- results: results.map((r) => create(grackle.SearchKnowledgeResultSchema, {
59
- score: r.score,
60
- node: knowledgeNodeToProto(r.node),
61
- edges: r.edges.map(knowledgeEdgeToProto),
62
- })),
63
- });
64
- }
65
- catch (err) {
66
- wrapNeo4jError(err);
67
- }
68
- }
69
- /** Get a knowledge node by ID. */
70
- export async function getKnowledgeNode(req) {
71
- if (!isKnowledgeEnabled()) {
72
- throw new ConnectError("Knowledge graph not available", Code.Unavailable);
73
- }
74
- requireKnowledgeReady();
75
- try {
76
- const result = await getKnowledgeNodeById(req.id);
77
- if (!result) {
78
- throw new ConnectError(`Knowledge node not found: ${req.id}`, Code.NotFound);
79
- }
80
- return create(grackle.GetKnowledgeNodeResponseSchema, {
81
- node: knowledgeNodeToProto(result.node),
82
- edges: result.edges.map(knowledgeEdgeToProto),
83
- });
84
- }
85
- catch (err) {
86
- wrapNeo4jError(err);
87
- }
88
- }
89
- /** Expand a knowledge node to retrieve its neighbors. */
90
- export async function expandKnowledgeNode(req) {
91
- if (!isKnowledgeEnabled()) {
92
- throw new ConnectError("Knowledge graph not available", Code.Unavailable);
93
- }
94
- requireKnowledgeReady();
95
- try {
96
- const result = await expandNode(req.id, {
97
- depth: req.depth || 1,
98
- edgeTypes: req.edgeTypes.length > 0 ? req.edgeTypes : undefined,
99
- });
100
- return create(grackle.ExpandKnowledgeNodeResponseSchema, {
101
- nodes: result.nodes.map(knowledgeNodeToProto),
102
- edges: result.edges.map(knowledgeEdgeToProto),
103
- });
104
- }
105
- catch (err) {
106
- wrapNeo4jError(err);
107
- }
108
- }
109
- /** List recently created knowledge nodes. */
110
- export async function listRecentKnowledgeNodes(req) {
111
- if (!isKnowledgeEnabled()) {
112
- throw new ConnectError("Knowledge graph not available", Code.Unavailable);
113
- }
114
- requireKnowledgeReady();
115
- try {
116
- const result = await listRecentNodes(req.limit || 20, req.workspaceId || undefined);
117
- return create(grackle.ListRecentKnowledgeNodesResponseSchema, {
118
- nodes: result.nodes.map(knowledgeNodeToProto),
119
- edges: result.edges.map(knowledgeEdgeToProto),
120
- });
121
- }
122
- catch (err) {
123
- wrapNeo4jError(err);
124
- }
125
- }
126
- /** Create a new native knowledge node with embedding. */
127
- export async function createKnowledgeNode(req) {
128
- const embedder = requireEmbedder();
129
- try {
130
- const chunker = createPassThroughChunker();
131
- const embedded = await ingest(req.content, chunker, embedder);
132
- if (embedded.length === 0) {
133
- throw new ConnectError("Content produced no embeddings", Code.InvalidArgument);
134
- }
135
- const id = await createNativeNode({
136
- category: (req.category || "insight"),
137
- title: req.title,
138
- content: req.content,
139
- tags: [...req.tags],
140
- embedding: embedded[0].vector,
141
- workspaceId: req.workspaceId || "",
142
- });
143
- return create(grackle.CreateKnowledgeNodeResponseSchema, { id });
144
- }
145
- catch (err) {
146
- wrapNeo4jError(err);
147
- }
148
- }
149
- //# sourceMappingURL=knowledge-handlers.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"knowledge-handlers.js","sourceRoot":"","sources":["../src/knowledge-handlers.ts"],"names":[],"mappings":"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"}
@@ -1,13 +0,0 @@
1
- /**
2
- * Lifecycle cleanup reconciliation phase — removes orphaned lifecycle streams
3
- * whose sessions have been deleted from the database.
4
- *
5
- * Prevents unbounded memory growth from accumulating in-memory streams for
6
- * sessions that no longer exist.
7
- *
8
- * @module
9
- */
10
- import type { ReconciliationPhase } from "./reconciliation-manager.js";
11
- /** Reconciliation phase that cleans up lifecycle streams for deleted sessions. */
12
- export declare const lifecycleCleanupPhase: ReconciliationPhase;
13
- //# sourceMappingURL=lifecycle-cleanup.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"lifecycle-cleanup.d.ts","sourceRoot":"","sources":["../src/lifecycle-cleanup.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAGH,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,6BAA6B,CAAC;AAOvE,kFAAkF;AAClF,eAAO,MAAM,qBAAqB,EAAE,mBAkBnC,CAAC"}
@@ -1,35 +0,0 @@
1
- /**
2
- * Lifecycle cleanup reconciliation phase — removes orphaned lifecycle streams
3
- * whose sessions have been deleted from the database.
4
- *
5
- * Prevents unbounded memory growth from accumulating in-memory streams for
6
- * sessions that no longer exist.
7
- *
8
- * @module
9
- */
10
- import { sessionStore } from "@grackle-ai/database";
11
- import * as streamRegistry from "./stream-registry.js";
12
- import { logger } from "./logger.js";
13
- /** Prefix for lifecycle stream names. */
14
- const LIFECYCLE_PREFIX = "lifecycle:";
15
- /** Reconciliation phase that cleans up lifecycle streams for deleted sessions. */
16
- export const lifecycleCleanupPhase = {
17
- name: "lifecycle-cleanup",
18
- execute: async () => {
19
- let cleaned = 0;
20
- for (const stream of streamRegistry.listStreams()) {
21
- if (!stream.name.startsWith(LIFECYCLE_PREFIX)) {
22
- continue;
23
- }
24
- const sessionId = stream.name.slice(LIFECYCLE_PREFIX.length);
25
- if (!sessionStore.getSession(sessionId)) {
26
- streamRegistry.deleteStream(stream.id);
27
- cleaned++;
28
- }
29
- }
30
- if (cleaned > 0) {
31
- logger.info({ cleaned }, "Lifecycle cleanup: removed %d orphaned stream(s)", cleaned);
32
- }
33
- },
34
- };
35
- //# sourceMappingURL=lifecycle-cleanup.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"lifecycle-cleanup.js","sourceRoot":"","sources":["../src/lifecycle-cleanup.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAEpD,OAAO,KAAK,cAAc,MAAM,sBAAsB,CAAC;AACvD,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAErC,yCAAyC;AACzC,MAAM,gBAAgB,GAAW,YAAY,CAAC;AAE9C,kFAAkF;AAClF,MAAM,CAAC,MAAM,qBAAqB,GAAwB;IACxD,IAAI,EAAE,mBAAmB;IACzB,OAAO,EAAE,KAAK,IAAmB,EAAE;QACjC,IAAI,OAAO,GAAW,CAAC,CAAC;QACxB,KAAK,MAAM,MAAM,IAAI,cAAc,CAAC,WAAW,EAAE,EAAE,CAAC;YAClD,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,gBAAgB,CAAC,EAAE,CAAC;gBAC9C,SAAS;YACX,CAAC;YACD,MAAM,SAAS,GAAW,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,gBAAgB,CAAC,MAAM,CAAC,CAAC;YACrE,IAAI,CAAC,YAAY,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;gBACxC,cAAc,CAAC,YAAY,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;gBACvC,OAAO,EAAE,CAAC;YACZ,CAAC;QACH,CAAC;QACD,IAAI,OAAO,GAAG,CAAC,EAAE,CAAC;YAChB,MAAM,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,EAAE,kDAAkD,EAAE,OAAO,CAAC,CAAC;QACxF,CAAC;IACH,CAAC;CACF,CAAC"}
@@ -1,44 +0,0 @@
1
- /**
2
- * Lifecycle manager — auto-stops sessions when all their file descriptors are closed.
3
- *
4
- * When the last subscription (fd) for a session is removed from the stream-registry,
5
- * the orphan callback fires and this module:
6
- * 1. Sets the session status to STOPPED with an appropriate end reason
7
- * 2. Kills the PowerLine process (best-effort)
8
- * 3. Broadcasts the end reason to UI clients
9
- * 4. Emits a task.updated event if the session has a task
10
- *
11
- * This is the foundation of the emergent lifecycle model: session alive/dead is
12
- * determined by subscription state, not explicit status calls.
13
- */
14
- import type { Disposable, PluginContext } from "./subscriber-types.js";
15
- /**
16
- * Create the lifecycle manager subscriber.
17
- *
18
- * Registers orphan and revival callbacks on the stream-registry so that
19
- * sessions auto-stop when all fds are closed and auto-reanimate when
20
- * a new fd is opened.
21
- *
22
- * @param ctx - Plugin context providing event-bus access.
23
- * @returns A Disposable that unregisters both callbacks.
24
- */
25
- export declare function createLifecycleSubscriber(ctx: PluginContext): Disposable;
26
- /**
27
- * Clean up lifecycle stream for a session. Deletes the stream and all its
28
- * subscriptions, which triggers the orphan callback (auto-stop).
29
- *
30
- * Called from killAgent when explicitly terminating a session, and from the
31
- * event processor on "failed" status to clean up zombie fds. For sessions
32
- * that complete normally, lifecycle streams persist until the UI or
33
- * reconciliation loop closes them — this is intentional (the session stays
34
- * "alive" and reanimate-safe until someone decides to close the fd).
35
- */
36
- export declare function cleanupLifecycleStream(sessionId: string): void;
37
- /**
38
- * Ensure a lifecycle stream exists for a session. Creates the stream with
39
- * spawner + session subscriptions if it was previously deleted (e.g. by
40
- * killAgent or a "failed" event). No-op if the stream still exists (e.g.
41
- * session went idle naturally and lifecycle stream was preserved).
42
- */
43
- export declare function ensureLifecycleStream(sessionId: string, spawnerId: string): void;
44
- //# sourceMappingURL=lifecycle.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"lifecycle.d.ts","sourceRoot":"","sources":["../src/lifecycle.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAWH,OAAO,KAAK,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAEvE;;;;;;;;;GASG;AACH,wBAAgB,yBAAyB,CAAC,GAAG,EAAE,aAAa,GAAG,UAAU,CAqHxE;AAED;;;;;;;;;GASG;AACH,wBAAgB,sBAAsB,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAU9D;AAED;;;;;GAKG;AACH,wBAAgB,qBAAqB,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,IAAI,CAQhF"}
package/dist/lifecycle.js DELETED
@@ -1,169 +0,0 @@
1
- /**
2
- * Lifecycle manager — auto-stops sessions when all their file descriptors are closed.
3
- *
4
- * When the last subscription (fd) for a session is removed from the stream-registry,
5
- * the orphan callback fires and this module:
6
- * 1. Sets the session status to STOPPED with an appropriate end reason
7
- * 2. Kills the PowerLine process (best-effort)
8
- * 3. Broadcasts the end reason to UI clients
9
- * 4. Emits a task.updated event if the session has a task
10
- *
11
- * This is the foundation of the emergent lifecycle model: session alive/dead is
12
- * determined by subscription state, not explicit status calls.
13
- */
14
- import { create } from "@bufbuild/protobuf";
15
- import { grackle, SESSION_STATUS, TERMINAL_SESSION_STATUSES, END_REASON, powerline } from "@grackle-ai/common";
16
- import { sessionStore, taskStore } from "@grackle-ai/database";
17
- import * as streamRegistry from "./stream-registry.js";
18
- import * as adapterManager from "./adapter-manager.js";
19
- import * as streamHub from "./stream-hub.js";
20
- import { reanimateAgent } from "./reanimate-agent.js";
21
- import { logger } from "./logger.js";
22
- /**
23
- * Create the lifecycle manager subscriber.
24
- *
25
- * Registers orphan and revival callbacks on the stream-registry so that
26
- * sessions auto-stop when all fds are closed and auto-reanimate when
27
- * a new fd is opened.
28
- *
29
- * @param ctx - Plugin context providing event-bus access.
30
- * @returns A Disposable that unregisters both callbacks.
31
- */
32
- export function createLifecycleSubscriber(ctx) {
33
- const unsubOrphan = streamRegistry.onSessionOrphaned((sessionId) => {
34
- const session = sessionStore.getSession(sessionId);
35
- if (!session) {
36
- return;
37
- }
38
- const alreadyTerminal = TERMINAL_SESSION_STATUSES.has(session.status);
39
- // Always kill the PowerLine process (best-effort — may have already exited).
40
- // Even if the session is already STOPPED (e.g. killAgent pre-set it), the
41
- // process may still be running and needs to be terminated.
42
- const conn = adapterManager.getConnection(session.environmentId);
43
- if (conn) {
44
- // Use the session's endReason if already set (killAgent pre-set it),
45
- // otherwise determine from the session's status at time of orphaning.
46
- let reason;
47
- if (alreadyTerminal && session.endReason) {
48
- reason = session.endReason;
49
- }
50
- else if (!alreadyTerminal && session.status === SESSION_STATUS.IDLE) {
51
- reason = session.sigtermSentAt ? END_REASON.TERMINATED : END_REASON.COMPLETED;
52
- }
53
- else {
54
- reason = END_REASON.KILLED;
55
- }
56
- conn.client.kill(create(powerline.KillRequestSchema, { id: sessionId, reason })).catch((err) => {
57
- logger.debug({ err, sessionId }, "Lifecycle: PowerLine kill failed (process may have already exited)");
58
- });
59
- }
60
- // Skip status change and broadcast if already terminal (killAgent already handled it)
61
- if (alreadyTerminal) {
62
- return;
63
- }
64
- // Determine reason: IDLE sessions completed naturally; others were killed.
65
- // If SIGTERM was sent and the session reached IDLE before being orphaned,
66
- // use TERMINATED instead of COMPLETED to distinguish graceful shutdowns.
67
- const reason = session.status === SESSION_STATUS.IDLE
68
- ? (session.sigtermSentAt ? END_REASON.TERMINATED : END_REASON.COMPLETED)
69
- : END_REASON.KILLED;
70
- logger.info({ sessionId, previousStatus: session.status, reason }, "Session orphaned (no remaining fds) — stopping");
71
- sessionStore.updateSession(sessionId, SESSION_STATUS.STOPPED, undefined, undefined, reason);
72
- // Broadcast end reason to UI clients
73
- streamHub.publish(create(grackle.SessionEventSchema, {
74
- sessionId,
75
- type: grackle.EventType.STATUS,
76
- timestamp: new Date().toISOString(),
77
- content: reason,
78
- raw: "",
79
- }));
80
- // Notify task system if this session belongs to a task
81
- if (session.taskId) {
82
- const task = taskStore.getTask(session.taskId);
83
- if (task) {
84
- ctx.emit("task.updated", { taskId: task.id, workspaceId: task.workspaceId || "" });
85
- }
86
- }
87
- });
88
- // ── Auto-reanimate: when an external session subscribes to a lifecycle
89
- // stream whose session is stopped, automatically restart it. This is the
90
- // "open() IS reanimate" model from the streams IPC spec.
91
- const unsubRevived = streamRegistry.onSessionRevived((targetSessionId, _subscriberSessionId) => {
92
- const session = sessionStore.getSession(targetSessionId);
93
- if (!session) {
94
- return;
95
- }
96
- // Only reanimate stopped or suspended sessions
97
- if (!TERMINAL_SESSION_STATUSES.has(session.status) && session.status !== SESSION_STATUS.SUSPENDED) {
98
- return;
99
- }
100
- // Must have a runtimeSessionId to resume from JSONL
101
- if (!session.runtimeSessionId) {
102
- logger.debug({ targetSessionId }, "Auto-reanimate skipped: no runtimeSessionId");
103
- return;
104
- }
105
- // Environment must not have another active session
106
- const existingActive = sessionStore.getActiveForEnv(session.environmentId);
107
- if (existingActive) {
108
- logger.debug({ targetSessionId, existingActive: existingActive.id }, "Auto-reanimate skipped: environment busy");
109
- return;
110
- }
111
- // Environment must be connected
112
- const conn = adapterManager.getConnection(session.environmentId);
113
- if (!conn) {
114
- logger.debug({ targetSessionId }, "Auto-reanimate skipped: environment disconnected");
115
- return;
116
- }
117
- logger.info({ targetSessionId }, "Auto-reanimating session on new lifecycle subscription");
118
- try {
119
- reanimateAgent(targetSessionId);
120
- }
121
- catch (err) {
122
- logger.debug({ err, targetSessionId }, "Auto-reanimate failed (non-fatal)");
123
- }
124
- });
125
- logger.info("Lifecycle manager initialized");
126
- return {
127
- dispose() {
128
- unsubOrphan();
129
- unsubRevived();
130
- },
131
- };
132
- }
133
- /**
134
- * Clean up lifecycle stream for a session. Deletes the stream and all its
135
- * subscriptions, which triggers the orphan callback (auto-stop).
136
- *
137
- * Called from killAgent when explicitly terminating a session, and from the
138
- * event processor on "failed" status to clean up zombie fds. For sessions
139
- * that complete normally, lifecycle streams persist until the UI or
140
- * reconciliation loop closes them — this is intentional (the session stays
141
- * "alive" and reanimate-safe until someone decides to close the fd).
142
- */
143
- export function cleanupLifecycleStream(sessionId) {
144
- const lifecycleStream = streamRegistry.getStreamByName(`lifecycle:${sessionId}`);
145
- if (lifecycleStream) {
146
- streamRegistry.deleteStream(lifecycleStream.id);
147
- }
148
- // Also clean up stdin stream to prevent it from keeping the session alive
149
- const stdinStream = streamRegistry.getStreamByName(`stdin:${sessionId}`);
150
- if (stdinStream) {
151
- streamRegistry.deleteStream(stdinStream.id);
152
- }
153
- }
154
- /**
155
- * Ensure a lifecycle stream exists for a session. Creates the stream with
156
- * spawner + session subscriptions if it was previously deleted (e.g. by
157
- * killAgent or a "failed" event). No-op if the stream still exists (e.g.
158
- * session went idle naturally and lifecycle stream was preserved).
159
- */
160
- export function ensureLifecycleStream(sessionId, spawnerId) {
161
- const existing = streamRegistry.getStreamByName(`lifecycle:${sessionId}`);
162
- if (existing) {
163
- return;
164
- }
165
- const stream = streamRegistry.createStream(`lifecycle:${sessionId}`);
166
- streamRegistry.subscribe(stream.id, spawnerId, "rw", "detach", true);
167
- streamRegistry.subscribe(stream.id, sessionId, "rw", "detach", false);
168
- }
169
- //# sourceMappingURL=lifecycle.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"lifecycle.js","sourceRoot":"","sources":["../src/lifecycle.ts"],"names":[],"mappings":"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"}
@@ -1,27 +0,0 @@
1
- /**
2
- * Orphan reconciliation phase — periodic safety net for orphaned tasks.
3
- *
4
- * Sweeps all tasks for children whose parent is in a terminal state but
5
- * haven't been reparented by the event-driven handler. This catches edge
6
- * cases like server restarts, race conditions, or missed events.
7
- */
8
- import type { TaskRow } from "@grackle-ai/database";
9
- import type { GrackleEventType } from "./event-bus.js";
10
- import type { ReconciliationPhase } from "./reconciliation-manager.js";
11
- /** Dependencies injected into the orphan phase for testability. */
12
- export interface OrphanPhaseDeps {
13
- /** Get all tasks (across all workspaces). */
14
- listAllTasks: () => TaskRow[];
15
- /** Reparent a task to a new parent. */
16
- reparentTask: (taskId: string, newParentTaskId: string) => void;
17
- /** Emit a domain event. */
18
- emit: (type: GrackleEventType, payload: Record<string, unknown>) => void;
19
- }
20
- /**
21
- * Create the orphan reconciliation phase.
22
- *
23
- * @param deps - Injected dependencies for testability.
24
- * @returns A ReconciliationPhase that can be registered with the ReconciliationManager.
25
- */
26
- export declare function createOrphanPhase(deps: OrphanPhaseDeps): ReconciliationPhase;
27
- //# sourceMappingURL=orphan-phase.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"orphan-phase.d.ts","sourceRoot":"","sources":["../src/orphan-phase.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAC;AACpD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AACvD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,6BAA6B,CAAC;AAQvE,mEAAmE;AACnE,MAAM,WAAW,eAAe;IAC9B,6CAA6C;IAC7C,YAAY,EAAE,MAAM,OAAO,EAAE,CAAC;IAC9B,uCAAuC;IACvC,YAAY,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,KAAK,IAAI,CAAC;IAChE,2BAA2B;IAC3B,IAAI,EAAE,CAAC,IAAI,EAAE,gBAAgB,EAAE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAC;CAC1E;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,eAAe,GAAG,mBAAmB,CA6D5E"}