@portel/photon 1.17.6 → 1.19.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.
Files changed (194) hide show
  1. package/dist/auto-ui/beam/photon-management.d.ts.map +1 -1
  2. package/dist/auto-ui/beam/photon-management.js +28 -1
  3. package/dist/auto-ui/beam/photon-management.js.map +1 -1
  4. package/dist/auto-ui/beam/routes/api-marketplace.d.ts.map +1 -1
  5. package/dist/auto-ui/beam/routes/api-marketplace.js +10 -5
  6. package/dist/auto-ui/beam/routes/api-marketplace.js.map +1 -1
  7. package/dist/auto-ui/beam.d.ts.map +1 -1
  8. package/dist/auto-ui/beam.js +14 -4
  9. package/dist/auto-ui/beam.js.map +1 -1
  10. package/dist/auto-ui/streamable-http-transport.d.ts.map +1 -1
  11. package/dist/auto-ui/streamable-http-transport.js +259 -88
  12. package/dist/auto-ui/streamable-http-transport.js.map +1 -1
  13. package/dist/auto-ui/types.d.ts +2 -0
  14. package/dist/auto-ui/types.d.ts.map +1 -1
  15. package/dist/auto-ui/types.js +5 -0
  16. package/dist/auto-ui/types.js.map +1 -1
  17. package/dist/beam-form.bundle.js +5 -3
  18. package/dist/beam-form.bundle.js.map +2 -2
  19. package/dist/beam.bundle.js +912 -59
  20. package/dist/beam.bundle.js.map +3 -3
  21. package/dist/claude-code-plugin.js +1 -1
  22. package/dist/cli/commands/beam.d.ts.map +1 -1
  23. package/dist/cli/commands/beam.js +8 -2
  24. package/dist/cli/commands/beam.js.map +1 -1
  25. package/dist/cli/commands/changelog.d.ts +9 -0
  26. package/dist/cli/commands/changelog.d.ts.map +1 -0
  27. package/dist/cli/commands/changelog.js +133 -0
  28. package/dist/cli/commands/changelog.js.map +1 -0
  29. package/dist/cli/commands/maker.d.ts.map +1 -1
  30. package/dist/cli/commands/maker.js +23 -2
  31. package/dist/cli/commands/maker.js.map +1 -1
  32. package/dist/cli/commands/mcp.d.ts.map +1 -1
  33. package/dist/cli/commands/mcp.js +53 -0
  34. package/dist/cli/commands/mcp.js.map +1 -1
  35. package/dist/cli/commands/package.d.ts.map +1 -1
  36. package/dist/cli/commands/package.js +18 -2
  37. package/dist/cli/commands/package.js.map +1 -1
  38. package/dist/cli/commands/run.d.ts.map +1 -1
  39. package/dist/cli/commands/run.js +1 -0
  40. package/dist/cli/commands/run.js.map +1 -1
  41. package/dist/cli/commands/update.d.ts +3 -2
  42. package/dist/cli/commands/update.d.ts.map +1 -1
  43. package/dist/cli/commands/update.js +50 -43
  44. package/dist/cli/commands/update.js.map +1 -1
  45. package/dist/cli/index.d.ts.map +1 -1
  46. package/dist/cli/index.js +16 -2
  47. package/dist/cli/index.js.map +1 -1
  48. package/dist/cli-alias.js +1 -1
  49. package/dist/cli-alias.js.map +1 -1
  50. package/dist/context-store.d.ts +23 -33
  51. package/dist/context-store.d.ts.map +1 -1
  52. package/dist/context-store.js +147 -97
  53. package/dist/context-store.js.map +1 -1
  54. package/dist/context.d.ts +15 -10
  55. package/dist/context.d.ts.map +1 -1
  56. package/dist/context.js +37 -13
  57. package/dist/context.js.map +1 -1
  58. package/dist/daemon/server.js +4 -2
  59. package/dist/daemon/server.js.map +1 -1
  60. package/dist/data-migration.d.ts +27 -0
  61. package/dist/data-migration.d.ts.map +1 -0
  62. package/dist/data-migration.js +307 -0
  63. package/dist/data-migration.js.map +1 -0
  64. package/dist/editor-support/docblock-tag-catalog.d.ts.map +1 -1
  65. package/dist/editor-support/docblock-tag-catalog.js +6 -0
  66. package/dist/editor-support/docblock-tag-catalog.js.map +1 -1
  67. package/dist/loader.d.ts +10 -0
  68. package/dist/loader.d.ts.map +1 -1
  69. package/dist/loader.js +106 -20
  70. package/dist/loader.js.map +1 -1
  71. package/dist/marketplace-manager.d.ts.map +1 -1
  72. package/dist/marketplace-manager.js +25 -5
  73. package/dist/marketplace-manager.js.map +1 -1
  74. package/dist/photon-cli-runner.d.ts.map +1 -1
  75. package/dist/photon-cli-runner.js +56 -19
  76. package/dist/photon-cli-runner.js.map +1 -1
  77. package/dist/photon-doc-extractor.d.ts +1 -0
  78. package/dist/photon-doc-extractor.d.ts.map +1 -1
  79. package/dist/photon-doc-extractor.js +6 -0
  80. package/dist/photon-doc-extractor.js.map +1 -1
  81. package/dist/readme-syncer.d.ts.map +1 -1
  82. package/dist/readme-syncer.js +6 -1
  83. package/dist/readme-syncer.js.map +1 -1
  84. package/dist/server.d.ts +40 -0
  85. package/dist/server.d.ts.map +1 -1
  86. package/dist/server.js +298 -29
  87. package/dist/server.js.map +1 -1
  88. package/dist/shared/audit.js +4 -4
  89. package/dist/shared/audit.js.map +1 -1
  90. package/dist/tasks/executor.d.ts +47 -0
  91. package/dist/tasks/executor.d.ts.map +1 -0
  92. package/dist/tasks/executor.js +180 -0
  93. package/dist/tasks/executor.js.map +1 -0
  94. package/dist/tasks/store.d.ts +13 -6
  95. package/dist/tasks/store.d.ts.map +1 -1
  96. package/dist/tasks/store.js +56 -11
  97. package/dist/tasks/store.js.map +1 -1
  98. package/dist/tasks/types.d.ts +23 -2
  99. package/dist/tasks/types.d.ts.map +1 -1
  100. package/dist/tasks/types.js +23 -3
  101. package/dist/tasks/types.js.map +1 -1
  102. package/dist/version-notify.d.ts +27 -0
  103. package/dist/version-notify.d.ts.map +1 -0
  104. package/dist/version-notify.js +142 -0
  105. package/dist/version-notify.js.map +1 -0
  106. package/package.json +5 -4
  107. package/dist/auto-ui/bridge/openai-shim.d.ts +0 -20
  108. package/dist/auto-ui/bridge/openai-shim.d.ts.map +0 -1
  109. package/dist/auto-ui/bridge/openai-shim.js +0 -231
  110. package/dist/auto-ui/bridge/openai-shim.js.map +0 -1
  111. package/dist/auto-ui/bridge/photon-app.d.ts +0 -162
  112. package/dist/auto-ui/bridge/photon-app.d.ts.map +0 -1
  113. package/dist/auto-ui/bridge/photon-app.js +0 -460
  114. package/dist/auto-ui/bridge/photon-app.js.map +0 -1
  115. package/dist/auto-ui/daemon-tools.d.ts +0 -45
  116. package/dist/auto-ui/daemon-tools.d.ts.map +0 -1
  117. package/dist/auto-ui/daemon-tools.js +0 -581
  118. package/dist/auto-ui/daemon-tools.js.map +0 -1
  119. package/dist/auto-ui/design-system/index.d.ts +0 -21
  120. package/dist/auto-ui/design-system/index.d.ts.map +0 -1
  121. package/dist/auto-ui/design-system/index.js +0 -27
  122. package/dist/auto-ui/design-system/index.js.map +0 -1
  123. package/dist/auto-ui/design-system/transaction-ui.d.ts +0 -70
  124. package/dist/auto-ui/design-system/transaction-ui.d.ts.map +0 -1
  125. package/dist/auto-ui/design-system/transaction-ui.js +0 -982
  126. package/dist/auto-ui/design-system/transaction-ui.js.map +0 -1
  127. package/dist/auto-ui/playground-server.d.ts +0 -7
  128. package/dist/auto-ui/playground-server.d.ts.map +0 -1
  129. package/dist/auto-ui/playground-server.js +0 -840
  130. package/dist/auto-ui/playground-server.js.map +0 -1
  131. package/dist/auto-ui/rendering/components.d.ts +0 -29
  132. package/dist/auto-ui/rendering/components.d.ts.map +0 -1
  133. package/dist/auto-ui/rendering/components.js +0 -1341
  134. package/dist/auto-ui/rendering/components.js.map +0 -1
  135. package/dist/auto-ui/rendering/field-analyzer.d.ts +0 -104
  136. package/dist/auto-ui/rendering/field-analyzer.d.ts.map +0 -1
  137. package/dist/auto-ui/rendering/field-analyzer.js +0 -447
  138. package/dist/auto-ui/rendering/field-analyzer.js.map +0 -1
  139. package/dist/auto-ui/rendering/field-renderers.d.ts +0 -64
  140. package/dist/auto-ui/rendering/field-renderers.d.ts.map +0 -1
  141. package/dist/auto-ui/rendering/field-renderers.js +0 -317
  142. package/dist/auto-ui/rendering/field-renderers.js.map +0 -1
  143. package/dist/auto-ui/rendering/index.d.ts +0 -28
  144. package/dist/auto-ui/rendering/index.d.ts.map +0 -1
  145. package/dist/auto-ui/rendering/index.js +0 -60
  146. package/dist/auto-ui/rendering/index.js.map +0 -1
  147. package/dist/auto-ui/rendering/layout-selector.d.ts +0 -60
  148. package/dist/auto-ui/rendering/layout-selector.d.ts.map +0 -1
  149. package/dist/auto-ui/rendering/layout-selector.js +0 -476
  150. package/dist/auto-ui/rendering/layout-selector.js.map +0 -1
  151. package/dist/markdown-utils.d.ts +0 -8
  152. package/dist/markdown-utils.d.ts.map +0 -1
  153. package/dist/markdown-utils.js +0 -64
  154. package/dist/markdown-utils.js.map +0 -1
  155. package/dist/mcp-client.d.ts +0 -9
  156. package/dist/mcp-client.d.ts.map +0 -1
  157. package/dist/mcp-client.js +0 -11
  158. package/dist/mcp-client.js.map +0 -1
  159. package/dist/mcp-elicitation.d.ts +0 -32
  160. package/dist/mcp-elicitation.d.ts.map +0 -1
  161. package/dist/mcp-elicitation.js +0 -26
  162. package/dist/mcp-elicitation.js.map +0 -1
  163. package/dist/photons/builder-compass.photon.d.ts +0 -167
  164. package/dist/photons/builder-compass.photon.d.ts.map +0 -1
  165. package/dist/photons/builder-compass.photon.js +0 -816
  166. package/dist/photons/builder-compass.photon.js.map +0 -1
  167. package/dist/photons/builder-compass.photon.ts +0 -1129
  168. package/dist/photons/docs/ui/docs.html +0 -441
  169. package/dist/photons/docs.photon.d.ts +0 -237
  170. package/dist/photons/docs.photon.d.ts.map +0 -1
  171. package/dist/photons/docs.photon.js +0 -483
  172. package/dist/photons/docs.photon.js.map +0 -1
  173. package/dist/photons/docs.photon.ts +0 -536
  174. package/dist/photons/slides.photon.d.ts +0 -212
  175. package/dist/photons/slides.photon.d.ts.map +0 -1
  176. package/dist/photons/slides.photon.js +0 -355
  177. package/dist/photons/slides.photon.js.map +0 -1
  178. package/dist/photons/slides.photon.ts +0 -370
  179. package/dist/photons/spreadsheet/ui/spreadsheet.html +0 -779
  180. package/dist/photons/spreadsheet.photon.d.ts +0 -554
  181. package/dist/photons/spreadsheet.photon.d.ts.map +0 -1
  182. package/dist/photons/spreadsheet.photon.js +0 -1050
  183. package/dist/photons/spreadsheet.photon.js.map +0 -1
  184. package/dist/photons/spreadsheet.photon.ts +0 -1239
  185. package/dist/photons/ui/builder-compass.html +0 -1199
  186. package/dist/photons/ui/builder-compass.photon.html +0 -380
  187. package/dist/security-scanner.d.ts +0 -52
  188. package/dist/security-scanner.d.ts.map +0 -1
  189. package/dist/security-scanner.js +0 -181
  190. package/dist/security-scanner.js.map +0 -1
  191. package/dist/shared/performance.d.ts +0 -65
  192. package/dist/shared/performance.d.ts.map +0 -1
  193. package/dist/shared/performance.js +0 -136
  194. package/dist/shared/performance.js.map +0 -1
@@ -0,0 +1,180 @@
1
+ /**
2
+ * MCP Task Executor (spec v2025-11-25)
3
+ *
4
+ * Runs tool execution in the background with support for input resumption.
5
+ * Decoupled from transport — works with both Streamable HTTP and STDIO.
6
+ */
7
+ import { updateTask, unregisterController, taskEvents } from './store.js';
8
+ import { TERMINAL_STATES } from './types.js';
9
+ /**
10
+ * Pending input resolvers — when a task enters input_required,
11
+ * the generator blocks on a promise. resolveTaskInput() resolves it.
12
+ */
13
+ const pendingInputs = new Map();
14
+ /**
15
+ * Resolve pending input for a task, resuming generator execution.
16
+ * Returns true if there was pending input to resolve.
17
+ */
18
+ export function resolveTaskInput(taskId, value) {
19
+ const pending = pendingInputs.get(taskId);
20
+ if (!pending)
21
+ return false;
22
+ pendingInputs.delete(taskId);
23
+ pending.resolve(value);
24
+ return true;
25
+ }
26
+ /**
27
+ * Reject pending input (e.g., on cancellation or timeout).
28
+ */
29
+ export function rejectTaskInput(taskId, reason) {
30
+ const pending = pendingInputs.get(taskId);
31
+ if (!pending)
32
+ return false;
33
+ pendingInputs.delete(taskId);
34
+ pending.reject(new Error(reason));
35
+ return true;
36
+ }
37
+ /**
38
+ * Check if a task has pending input waiting.
39
+ */
40
+ export function hasPendingInput(taskId) {
41
+ return pendingInputs.has(taskId);
42
+ }
43
+ /**
44
+ * Wait for a task to reach a specific state (or any state change).
45
+ * Resolves with the updated task when the condition is met.
46
+ */
47
+ export function waitForStateChange(taskId, predicate, signal) {
48
+ return new Promise((resolve, reject) => {
49
+ // Check abort
50
+ if (signal?.aborted) {
51
+ reject(new Error('Aborted'));
52
+ return;
53
+ }
54
+ const handler = (changedId, newState, task) => {
55
+ if (changedId !== taskId)
56
+ return;
57
+ if (!predicate || predicate(newState)) {
58
+ cleanup();
59
+ resolve(task);
60
+ }
61
+ };
62
+ const onAbort = () => {
63
+ cleanup();
64
+ reject(new Error('Aborted'));
65
+ };
66
+ const cleanup = () => {
67
+ taskEvents.removeListener('stateChange', handler);
68
+ signal?.removeEventListener('abort', onAbort);
69
+ };
70
+ taskEvents.on('stateChange', handler);
71
+ signal?.addEventListener('abort', onAbort);
72
+ });
73
+ }
74
+ /**
75
+ * Wait for a task to reach a terminal state or input_required.
76
+ * Used by tasks/result handler.
77
+ */
78
+ export function waitForTerminalOrInput(taskId, signal) {
79
+ return waitForStateChange(taskId, (state) => TERMINAL_STATES.includes(state) || state === 'input_required', signal);
80
+ }
81
+ /**
82
+ * Run tool execution as a background task.
83
+ *
84
+ * Fire-and-forget — caller does not await this.
85
+ * Updates task state in store as execution progresses.
86
+ * Generator yields { ask } → task enters input_required, blocks until resolveTaskInput().
87
+ */
88
+ export function runTaskExecution(taskId, executeFn, options) {
89
+ const { signal, outputHandler: externalOutputHandler } = options;
90
+ // inputProvider that blocks on pending input
91
+ const inputProvider = async (ask) => {
92
+ // Store the ask payload and transition to input_required
93
+ updateTask(taskId, {
94
+ state: 'input_required',
95
+ statusMessage: ask.message || 'Waiting for user input.',
96
+ input: ask,
97
+ });
98
+ // Block until resolveTaskInput() or rejectTaskInput() is called
99
+ return new Promise((resolve, reject) => {
100
+ pendingInputs.set(taskId, { resolve, reject });
101
+ // If already aborted, reject immediately
102
+ if (signal.aborted) {
103
+ pendingInputs.delete(taskId);
104
+ reject(new Error('Task cancelled'));
105
+ return;
106
+ }
107
+ // Listen for abort to clean up
108
+ const onAbort = () => {
109
+ if (pendingInputs.has(taskId)) {
110
+ pendingInputs.delete(taskId);
111
+ reject(new Error('Task cancelled'));
112
+ }
113
+ };
114
+ signal.addEventListener('abort', onAbort, { once: true });
115
+ });
116
+ };
117
+ // outputHandler that updates task progress
118
+ const outputHandler = (data) => {
119
+ if (data?.emit === 'progress' && typeof data.value === 'number') {
120
+ updateTask(taskId, {
121
+ progress: { percent: data.value, message: data.message },
122
+ statusMessage: data.message || undefined,
123
+ });
124
+ }
125
+ else if (data?.emit === 'status') {
126
+ updateTask(taskId, {
127
+ statusMessage: data.message || 'Processing...',
128
+ });
129
+ }
130
+ // Forward to external handler (e.g., SSE broadcast)
131
+ externalOutputHandler?.(data);
132
+ };
133
+ // Run in background
134
+ void (async () => {
135
+ try {
136
+ if (signal.aborted) {
137
+ updateTask(taskId, { state: 'cancelled', statusMessage: 'Task was cancelled.' });
138
+ return;
139
+ }
140
+ // When input is provided and task resumes, transition back to working
141
+ const wrappedInputProvider = async (ask) => {
142
+ const result = await inputProvider(ask);
143
+ // Resume: transition back to working
144
+ updateTask(taskId, {
145
+ state: 'working',
146
+ statusMessage: 'Resuming execution...',
147
+ input: undefined,
148
+ });
149
+ return result;
150
+ };
151
+ const result = await executeFn(wrappedInputProvider, outputHandler);
152
+ if (!signal.aborted) {
153
+ updateTask(taskId, {
154
+ state: 'completed',
155
+ statusMessage: 'Operation completed successfully.',
156
+ result,
157
+ });
158
+ }
159
+ }
160
+ catch (err) {
161
+ if (signal.aborted) {
162
+ updateTask(taskId, { state: 'cancelled', statusMessage: 'Task was cancelled.' });
163
+ }
164
+ else {
165
+ const message = err instanceof Error ? err.message : String(err);
166
+ updateTask(taskId, {
167
+ state: 'failed',
168
+ statusMessage: message,
169
+ error: message,
170
+ });
171
+ }
172
+ }
173
+ finally {
174
+ // Clean up any lingering pending input
175
+ pendingInputs.delete(taskId);
176
+ unregisterController(taskId);
177
+ }
178
+ })();
179
+ }
180
+ //# sourceMappingURL=executor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"executor.js","sourceRoot":"","sources":["../../src/tasks/executor.ts"],"names":[],"mappings":"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"}
@@ -1,19 +1,26 @@
1
1
  /**
2
- * MCP Task Store
2
+ * MCP Task Store (spec v2025-11-25)
3
3
  *
4
4
  * File-based persistence at ~/.photon/tasks/.
5
5
  * Each task is a JSON file: {taskId}.json
6
- * Consistent with existing photon file-based patterns (audit, runs, state).
6
+ * EventEmitter for state change notifications.
7
7
  */
8
- import type { Task } from './types.js';
8
+ import { EventEmitter } from 'events';
9
+ import { type Task } from './types.js';
10
+ /** Event emitter for task state changes */
11
+ export declare const taskEvents: EventEmitter<[never]>;
9
12
  export declare function registerController(taskId: string, controller: AbortController): void;
10
13
  export declare function unregisterController(taskId: string): void;
11
14
  export declare function getController(taskId: string): AbortController | undefined;
12
- export declare function createTask(photon: string, method: string, params?: Record<string, unknown>): Task;
15
+ export declare function createTask(photon: string, method: string, params?: Record<string, unknown>, ttl?: number): Task;
13
16
  export declare function getTask(id: string): Task | null;
14
- export declare function updateTask(id: string, updates: Partial<Pick<Task, 'state' | 'progress' | 'result' | 'error'>>): Task | null;
17
+ export declare function updateTask(id: string, updates: Partial<Pick<Task, 'state' | 'statusMessage' | 'progress' | 'result' | 'error' | 'input'>>): Task | null;
15
18
  export declare function listTasks(photon?: string): Task[];
16
- export declare function cleanExpiredTasks(maxAgeMs: number): number;
19
+ /**
20
+ * Clean expired tasks — removes terminal tasks past their TTL
21
+ * and also removes non-terminal tasks that have been alive longer than their TTL
22
+ */
23
+ export declare function cleanExpiredTasks(): number;
17
24
  /** Override tasks dir for testing */
18
25
  export declare function _getTasksDir(): string;
19
26
  //# sourceMappingURL=store.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../../src/tasks/store.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAOH,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAgBvC,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,eAAe,GAAG,IAAI,CAEpF;AAED,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAEzD;AAED,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,eAAe,GAAG,SAAS,CAEzE;AAED,wBAAgB,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAcjG;AAED,wBAAgB,OAAO,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI,CAS/C;AAED,wBAAgB,UAAU,CACxB,EAAE,EAAE,MAAM,EACV,OAAO,EAAE,OAAO,CAAC,IAAI,CAAC,IAAI,EAAE,OAAO,GAAG,UAAU,GAAG,QAAQ,GAAG,OAAO,CAAC,CAAC,GACtE,IAAI,GAAG,IAAI,CAMb;AAED,wBAAgB,SAAS,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,EAAE,CAejD;AAED,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAqB1D;AAED,qCAAqC;AACrC,wBAAgB,YAAY,IAAI,MAAM,CAErC"}
1
+ {"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../../src/tasks/store.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAMH,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AACtC,OAAO,EAAE,KAAK,IAAI,EAAuD,MAAM,YAAY,CAAC;AAkB5F,2CAA2C;AAC3C,eAAO,MAAM,UAAU,uBAAqB,CAAC;AAM7C,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,eAAe,GAAG,IAAI,CAEpF;AAED,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAEzD;AAED,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,eAAe,GAAG,SAAS,CAEzE;AAED,wBAAgB,UAAU,CACxB,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,EACd,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAChC,GAAG,CAAC,EAAE,MAAM,GACX,IAAI,CAkBN;AAED,wBAAgB,OAAO,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI,CAS/C;AAED,wBAAgB,UAAU,CACxB,EAAE,EAAE,MAAM,EACV,OAAO,EAAE,OAAO,CACd,IAAI,CAAC,IAAI,EAAE,OAAO,GAAG,eAAe,GAAG,UAAU,GAAG,QAAQ,GAAG,OAAO,GAAG,OAAO,CAAC,CAClF,GACA,IAAI,GAAG,IAAI,CAcb;AAED,wBAAgB,SAAS,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,EAAE,CAejD;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,IAAI,MAAM,CA+B1C;AAED,qCAAqC;AACrC,wBAAgB,YAAY,IAAI,MAAM,CAErC"}
@@ -1,16 +1,22 @@
1
1
  /**
2
- * MCP Task Store
2
+ * MCP Task Store (spec v2025-11-25)
3
3
  *
4
4
  * File-based persistence at ~/.photon/tasks/.
5
5
  * Each task is a JSON file: {taskId}.json
6
- * Consistent with existing photon file-based patterns (audit, runs, state).
6
+ * EventEmitter for state change notifications.
7
7
  */
8
8
  import { mkdirSync, readdirSync, unlinkSync, existsSync } from 'fs';
9
9
  import { readJSONSync, writeJSONSync } from '../shared/io.js';
10
10
  import { join } from 'path';
11
- import { homedir } from 'os';
12
11
  import { randomUUID } from 'crypto';
13
- const TASKS_DIR = join(homedir(), '.photon', 'tasks');
12
+ import { EventEmitter } from 'events';
13
+ import { TERMINAL_STATES, DEFAULT_TTL, DEFAULT_POLL_INTERVAL } from './types.js';
14
+ import { getTasksDir, getLegacyTasksDir } from '@portel/photon-core';
15
+ // Tasks are ephemeral/global — use .data/tasks/
16
+ // Check legacy path for existing tasks during migration
17
+ const newDir = getTasksDir();
18
+ const legacyDir = getLegacyTasksDir();
19
+ const TASKS_DIR = existsSync(newDir) ? newDir : existsSync(legacyDir) ? legacyDir : newDir;
14
20
  /** Ensure tasks directory exists (idempotent) */
15
21
  function ensureDir() {
16
22
  mkdirSync(TASKS_DIR, { recursive: true });
@@ -18,6 +24,9 @@ function ensureDir() {
18
24
  function taskPath(id) {
19
25
  return join(TASKS_DIR, `${id}.json`);
20
26
  }
27
+ /** Event emitter for task state changes */
28
+ export const taskEvents = new EventEmitter();
29
+ taskEvents.setMaxListeners(50); // Multiple SSE sessions may listen
21
30
  /** Active task AbortControllers for cancellation */
22
31
  const activeControllers = new Map();
23
32
  export function registerController(taskId, controller) {
@@ -29,7 +38,7 @@ export function unregisterController(taskId) {
29
38
  export function getController(taskId) {
30
39
  return activeControllers.get(taskId);
31
40
  }
32
- export function createTask(photon, method, params) {
41
+ export function createTask(photon, method, params, ttl) {
33
42
  ensureDir();
34
43
  const now = new Date().toISOString();
35
44
  const task = {
@@ -38,10 +47,14 @@ export function createTask(photon, method, params) {
38
47
  method,
39
48
  params,
40
49
  state: 'working',
50
+ statusMessage: 'The operation is now in progress.',
51
+ ttl: ttl ?? DEFAULT_TTL,
52
+ pollInterval: DEFAULT_POLL_INTERVAL,
41
53
  createdAt: now,
42
54
  updatedAt: now,
43
55
  };
44
56
  writeJSONSync(taskPath(task.id), task);
57
+ taskEvents.emit('stateChange', task.id, task.state, task);
45
58
  return task;
46
59
  }
47
60
  export function getTask(id) {
@@ -60,8 +73,13 @@ export function updateTask(id, updates) {
60
73
  const task = getTask(id);
61
74
  if (!task)
62
75
  return null;
76
+ const oldState = task.state;
63
77
  Object.assign(task, updates, { updatedAt: new Date().toISOString() });
64
78
  writeJSONSync(taskPath(id), task);
79
+ // Emit on any state transition
80
+ if (updates.state && updates.state !== oldState) {
81
+ taskEvents.emit('stateChange', id, task.state, task);
82
+ }
65
83
  return task;
66
84
  }
67
85
  export function listTasks(photon) {
@@ -81,7 +99,11 @@ export function listTasks(photon) {
81
99
  }
82
100
  return tasks.sort((a, b) => b.createdAt.localeCompare(a.createdAt));
83
101
  }
84
- export function cleanExpiredTasks(maxAgeMs) {
102
+ /**
103
+ * Clean expired tasks — removes terminal tasks past their TTL
104
+ * and also removes non-terminal tasks that have been alive longer than their TTL
105
+ */
106
+ export function cleanExpiredTasks() {
85
107
  ensureDir();
86
108
  const files = readdirSync(TASKS_DIR).filter((f) => f.endsWith('.json'));
87
109
  const now = Date.now();
@@ -89,11 +111,24 @@ export function cleanExpiredTasks(maxAgeMs) {
89
111
  for (const file of files) {
90
112
  try {
91
113
  const task = readJSONSync(join(TASKS_DIR, file));
92
- const age = now - new Date(task.updatedAt).getTime();
93
- if (age > maxAgeMs &&
94
- (task.state === 'completed' || task.state === 'failed' || task.state === 'cancelled')) {
95
- unlinkSync(join(TASKS_DIR, file));
96
- cleaned++;
114
+ const age = now - new Date(task.createdAt).getTime();
115
+ const ttl = task.ttl || DEFAULT_TTL;
116
+ if (age > ttl) {
117
+ // Terminal tasks: always clean
118
+ // Non-terminal tasks past TTL: force-cancel and clean
119
+ if (TERMINAL_STATES.includes(task.state)) {
120
+ unlinkSync(join(TASKS_DIR, file));
121
+ cleaned++;
122
+ }
123
+ else {
124
+ // Force-cancel stale non-terminal tasks
125
+ const controller = getController(task.id);
126
+ if (controller)
127
+ controller.abort();
128
+ unregisterController(task.id);
129
+ unlinkSync(join(TASKS_DIR, file));
130
+ cleaned++;
131
+ }
97
132
  }
98
133
  }
99
134
  catch {
@@ -106,4 +141,14 @@ export function cleanExpiredTasks(maxAgeMs) {
106
141
  export function _getTasksDir() {
107
142
  return TASKS_DIR;
108
143
  }
144
+ // Startup cleanup
145
+ try {
146
+ const cleaned = cleanExpiredTasks();
147
+ if (cleaned > 0) {
148
+ console.error(`🗑️ Cleaned ${cleaned} expired task(s)`);
149
+ }
150
+ }
151
+ catch {
152
+ // Best effort
153
+ }
109
154
  //# sourceMappingURL=store.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"store.js","sourceRoot":"","sources":["../../src/tasks/store.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"store.js","sourceRoot":"","sources":["../../src/tasks/store.ts"],"names":[],"mappings":"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"}
@@ -1,24 +1,45 @@
1
1
  /**
2
- * MCP Tasks Types
2
+ * MCP Tasks Types (spec v2025-11-25)
3
3
  *
4
- * Task state machine for async long-running operations (MCP 2025-11-25 spec).
4
+ * Task state machine for async long-running operations.
5
5
  * States: working → completed | failed | cancelled
6
6
  * working → input_required → working (when resuming)
7
7
  */
8
8
  export type TaskState = 'working' | 'input_required' | 'completed' | 'failed' | 'cancelled';
9
+ export declare const TERMINAL_STATES: readonly TaskState[];
10
+ export declare const DEFAULT_TTL: number;
11
+ export declare const DEFAULT_POLL_INTERVAL = 2000;
9
12
  export interface Task {
10
13
  id: string;
11
14
  photon: string;
12
15
  method: string;
13
16
  params?: Record<string, unknown>;
14
17
  state: TaskState;
18
+ statusMessage?: string;
19
+ ttl: number;
20
+ pollInterval: number;
15
21
  progress?: {
16
22
  percent: number;
17
23
  message?: string;
18
24
  };
19
25
  result?: unknown;
20
26
  error?: string;
27
+ input?: unknown;
21
28
  createdAt: string;
22
29
  updatedAt: string;
23
30
  }
31
+ /** MCP wire format — field names match the spec exactly */
32
+ export interface TaskWire {
33
+ taskId: string;
34
+ status: TaskState;
35
+ statusMessage?: string;
36
+ createdAt: string;
37
+ lastUpdatedAt: string;
38
+ ttl: number;
39
+ pollInterval: number;
40
+ }
41
+ /** Convert internal Task to MCP wire format */
42
+ export declare function toWireFormat(task: Task): TaskWire;
43
+ /** The _meta field for task-related messages */
44
+ export declare function relatedTaskMeta(taskId: string): Record<string, unknown>;
24
45
  //# sourceMappingURL=types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/tasks/types.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,MAAM,MAAM,SAAS,GAAG,SAAS,GAAG,gBAAgB,GAAG,WAAW,GAAG,QAAQ,GAAG,WAAW,CAAC;AAE5F,MAAM,WAAW,IAAI;IACnB,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACjC,KAAK,EAAE,SAAS,CAAC;IACjB,QAAQ,CAAC,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IACjD,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;CACnB"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/tasks/types.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,MAAM,MAAM,SAAS,GAAG,SAAS,GAAG,gBAAgB,GAAG,WAAW,GAAG,QAAQ,GAAG,WAAW,CAAC;AAE5F,eAAO,MAAM,eAAe,EAAE,SAAS,SAAS,EAAyC,CAAC;AAE1F,eAAO,MAAM,WAAW,QAA0B,CAAC;AACnD,eAAO,MAAM,qBAAqB,OAAO,CAAC;AAE1C,MAAM,WAAW,IAAI;IACnB,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACjC,KAAK,EAAE,SAAS,CAAC;IACjB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,GAAG,EAAE,MAAM,CAAC;IACZ,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IACjD,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,2DAA2D;AAC3D,MAAM,WAAW,QAAQ;IACvB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,SAAS,CAAC;IAClB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,MAAM,CAAC;IACtB,GAAG,EAAE,MAAM,CAAC;IACZ,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,+CAA+C;AAC/C,wBAAgB,YAAY,CAAC,IAAI,EAAE,IAAI,GAAG,QAAQ,CAUjD;AAED,gDAAgD;AAChD,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAIvE"}
@@ -1,9 +1,29 @@
1
1
  /**
2
- * MCP Tasks Types
2
+ * MCP Tasks Types (spec v2025-11-25)
3
3
  *
4
- * Task state machine for async long-running operations (MCP 2025-11-25 spec).
4
+ * Task state machine for async long-running operations.
5
5
  * States: working → completed | failed | cancelled
6
6
  * working → input_required → working (when resuming)
7
7
  */
8
- export {};
8
+ export const TERMINAL_STATES = ['completed', 'failed', 'cancelled'];
9
+ export const DEFAULT_TTL = 7 * 24 * 60 * 60 * 1000; // 1 week
10
+ export const DEFAULT_POLL_INTERVAL = 2000; // 2 seconds
11
+ /** Convert internal Task to MCP wire format */
12
+ export function toWireFormat(task) {
13
+ return {
14
+ taskId: task.id,
15
+ status: task.state,
16
+ ...(task.statusMessage && { statusMessage: task.statusMessage }),
17
+ createdAt: task.createdAt,
18
+ lastUpdatedAt: task.updatedAt,
19
+ ttl: task.ttl,
20
+ pollInterval: task.pollInterval,
21
+ };
22
+ }
23
+ /** The _meta field for task-related messages */
24
+ export function relatedTaskMeta(taskId) {
25
+ return {
26
+ 'io.modelcontextprotocol/related-task': { taskId },
27
+ };
28
+ }
9
29
  //# sourceMappingURL=types.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/tasks/types.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG"}
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/tasks/types.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH,MAAM,CAAC,MAAM,eAAe,GAAyB,CAAC,WAAW,EAAE,QAAQ,EAAE,WAAW,CAAC,CAAC;AAE1F,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC,SAAS;AAC7D,MAAM,CAAC,MAAM,qBAAqB,GAAG,IAAI,CAAC,CAAC,YAAY;AA8BvD,+CAA+C;AAC/C,MAAM,UAAU,YAAY,CAAC,IAAU;IACrC,OAAO;QACL,MAAM,EAAE,IAAI,CAAC,EAAE;QACf,MAAM,EAAE,IAAI,CAAC,KAAK;QAClB,GAAG,CAAC,IAAI,CAAC,aAAa,IAAI,EAAE,aAAa,EAAE,IAAI,CAAC,aAAa,EAAE,CAAC;QAChE,SAAS,EAAE,IAAI,CAAC,SAAS;QACzB,aAAa,EAAE,IAAI,CAAC,SAAS;QAC7B,GAAG,EAAE,IAAI,CAAC,GAAG;QACb,YAAY,EAAE,IAAI,CAAC,YAAY;KAChC,CAAC;AACJ,CAAC;AAED,gDAAgD;AAChD,MAAM,UAAU,eAAe,CAAC,MAAc;IAC5C,OAAO;QACL,sCAAsC,EAAE,EAAE,MAAM,EAAE;KACnD,CAAC;AACJ,CAAC"}
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Version Upgrade Notification
3
+ *
4
+ * Checks npm registry for newer versions and displays an unobtrusive notice
5
+ * with changelog highlights. Non-blocking — spawns a detached child process
6
+ * on cache miss so CLI startup is never delayed.
7
+ *
8
+ * Cache: .data/.version-check.json (24h TTL)
9
+ * Notice: shown once per new version (tracks notifiedVersion)
10
+ */
11
+ /**
12
+ * Spawn a detached background process that fetches the latest version
13
+ * and changelog, then writes the cache file. The parent process does
14
+ * not wait for this — CLI exits immediately.
15
+ */
16
+ export declare function refreshUpdateCache(): void;
17
+ /**
18
+ * Show update notice to stderr if a newer version is available.
19
+ *
20
+ * Returns silently if:
21
+ * - No cache exists (background refresh hasn't completed yet)
22
+ * - Current version is up to date
23
+ * - Already notified for this version
24
+ * - Running in MCP STDIO mode
25
+ */
26
+ export declare function showUpdateNotice(): void;
27
+ //# sourceMappingURL=version-notify.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"version-notify.d.ts","sourceRoot":"","sources":["../src/version-notify.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AA2DH;;;;GAIG;AACH,wBAAgB,kBAAkB,IAAI,IAAI,CAwCzC;AAED;;;;;;;;GAQG;AACH,wBAAgB,gBAAgB,IAAI,IAAI,CA6BvC"}
@@ -0,0 +1,142 @@
1
+ /**
2
+ * Version Upgrade Notification
3
+ *
4
+ * Checks npm registry for newer versions and displays an unobtrusive notice
5
+ * with changelog highlights. Non-blocking — spawns a detached child process
6
+ * on cache miss so CLI startup is never delayed.
7
+ *
8
+ * Cache: .data/.version-check.json (24h TTL)
9
+ * Notice: shown once per new version (tracks notifiedVersion)
10
+ */
11
+ import * as fs from 'fs';
12
+ import * as path from 'path';
13
+ import { spawn } from 'child_process';
14
+ import { getDataRoot } from '@portel/photon-core';
15
+ import { PHOTON_VERSION } from './version.js';
16
+ const CACHE_TTL_MS = 24 * 60 * 60 * 1000; // 24 hours
17
+ function getCachePath() {
18
+ return path.join(getDataRoot(), '.version-check.json');
19
+ }
20
+ function readCache() {
21
+ try {
22
+ const cachePath = getCachePath();
23
+ if (!fs.existsSync(cachePath))
24
+ return null;
25
+ return JSON.parse(fs.readFileSync(cachePath, 'utf-8'));
26
+ }
27
+ catch {
28
+ return null;
29
+ }
30
+ }
31
+ function writeCache(cache) {
32
+ try {
33
+ const cachePath = getCachePath();
34
+ fs.mkdirSync(path.dirname(cachePath), { recursive: true });
35
+ fs.writeFileSync(cachePath, JSON.stringify(cache, null, 2));
36
+ }
37
+ catch {
38
+ // Best effort
39
+ }
40
+ }
41
+ function isStale(cache) {
42
+ const checkedAt = new Date(cache.checkedAt).getTime();
43
+ return Date.now() - checkedAt > CACHE_TTL_MS;
44
+ }
45
+ /**
46
+ * Compare two semver strings.
47
+ * Returns 1 if a > b, -1 if a < b, 0 if equal.
48
+ */
49
+ function compareSemver(a, b) {
50
+ const pa = a.split('.').map(Number);
51
+ const pb = b.split('.').map(Number);
52
+ for (let i = 0; i < 3; i++) {
53
+ if ((pa[i] || 0) > (pb[i] || 0))
54
+ return 1;
55
+ if ((pa[i] || 0) < (pb[i] || 0))
56
+ return -1;
57
+ }
58
+ return 0;
59
+ }
60
+ /**
61
+ * Spawn a detached background process that fetches the latest version
62
+ * and changelog, then writes the cache file. The parent process does
63
+ * not wait for this — CLI exits immediately.
64
+ */
65
+ export function refreshUpdateCache() {
66
+ const cache = readCache();
67
+ if (cache && !isStale(cache))
68
+ return;
69
+ const cachePath = getCachePath();
70
+ const script = `
71
+ const fs = require('fs');
72
+ const { execSync } = require('child_process');
73
+
74
+ let latest = null;
75
+ try {
76
+ latest = execSync('npm view @portel/photon version', {
77
+ encoding: 'utf-8', timeout: 10000,
78
+ stdio: ['pipe', 'pipe', 'pipe']
79
+ }).trim();
80
+ } catch { process.exit(0); }
81
+
82
+ if (!latest) process.exit(0);
83
+
84
+ const existing = (() => {
85
+ try { return JSON.parse(fs.readFileSync(${JSON.stringify(cachePath)}, 'utf-8')); }
86
+ catch { return {}; }
87
+ })();
88
+ const data = {
89
+ latest,
90
+ checkedAt: new Date().toISOString(),
91
+ notifiedVersion: existing.notifiedVersion || undefined,
92
+ };
93
+ try {
94
+ fs.mkdirSync(require('path').dirname(${JSON.stringify(cachePath)}), { recursive: true });
95
+ fs.writeFileSync(${JSON.stringify(cachePath)}, JSON.stringify(data, null, 2));
96
+ } catch {}
97
+ `;
98
+ // Spawn detached — parent doesn't wait
99
+ const child = spawn(process.execPath, ['-e', script], {
100
+ detached: true,
101
+ stdio: 'ignore',
102
+ });
103
+ child.unref();
104
+ }
105
+ /**
106
+ * Show update notice to stderr if a newer version is available.
107
+ *
108
+ * Returns silently if:
109
+ * - No cache exists (background refresh hasn't completed yet)
110
+ * - Current version is up to date
111
+ * - Already notified for this version
112
+ * - Running in MCP STDIO mode
113
+ */
114
+ export function showUpdateNotice() {
115
+ if (process.env.PHOTON_TRANSPORT === 'stdio')
116
+ return;
117
+ const cache = readCache();
118
+ if (!cache)
119
+ return;
120
+ if (compareSemver(cache.latest, PHOTON_VERSION) <= 0)
121
+ return;
122
+ if (cache.notifiedVersion === cache.latest)
123
+ return;
124
+ const current = PHOTON_VERSION;
125
+ const latest = cache.latest;
126
+ const lines = [];
127
+ lines.push(` Update available: ${current} → ${latest}`);
128
+ lines.push(` Update: photon update`);
129
+ lines.push(` What's new: photon changelog`);
130
+ const width = Math.max(...lines.map((l) => l.length)) + 2;
131
+ const pad = (s) => s + ' '.repeat(Math.max(0, width - s.length));
132
+ console.error('');
133
+ console.error(`╭${'─'.repeat(width)}╮`);
134
+ for (const line of lines) {
135
+ console.error(`│${pad(line)}│`);
136
+ }
137
+ console.error(`╰${'─'.repeat(width)}╯`);
138
+ // Mark as notified so we don't show again for this version
139
+ cache.notifiedVersion = cache.latest;
140
+ writeCache(cache);
141
+ }
142
+ //# sourceMappingURL=version-notify.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"version-notify.js","sourceRoot":"","sources":["../src/version-notify.ts"],"names":[],"mappings":"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"}