@jini-ai/integrations 0.1.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 (191) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +51 -0
  3. package/dist/composio/bounded-data.d.ts +36 -0
  4. package/dist/composio/bounded-data.d.ts.map +1 -0
  5. package/dist/composio/bounded-data.js +181 -0
  6. package/dist/composio/bounded-data.js.map +1 -0
  7. package/dist/composio/catalog.d.ts +147 -0
  8. package/dist/composio/catalog.d.ts.map +1 -0
  9. package/dist/composio/catalog.js +126 -0
  10. package/dist/composio/catalog.js.map +1 -0
  11. package/dist/composio/composio-config.d.ts +42 -0
  12. package/dist/composio/composio-config.d.ts.map +1 -0
  13. package/dist/composio/composio-config.js +145 -0
  14. package/dist/composio/composio-config.js.map +1 -0
  15. package/dist/composio/composio-descriptions.d.ts +16 -0
  16. package/dist/composio/composio-descriptions.d.ts.map +1 -0
  17. package/dist/composio/composio-descriptions.js +766 -0
  18. package/dist/composio/composio-descriptions.js.map +1 -0
  19. package/dist/composio/composio.d.ts +364 -0
  20. package/dist/composio/composio.d.ts.map +1 -0
  21. package/dist/composio/composio.js +1902 -0
  22. package/dist/composio/composio.js.map +1 -0
  23. package/dist/composio/errors.d.ts +15 -0
  24. package/dist/composio/errors.d.ts.map +1 -0
  25. package/dist/composio/errors.js +16 -0
  26. package/dist/composio/errors.js.map +1 -0
  27. package/dist/composio/file-lock.d.ts +13 -0
  28. package/dist/composio/file-lock.d.ts.map +1 -0
  29. package/dist/composio/file-lock.js +92 -0
  30. package/dist/composio/file-lock.js.map +1 -0
  31. package/dist/composio/index.d.ts +18 -0
  32. package/dist/composio/index.d.ts.map +1 -0
  33. package/dist/composio/index.js +7 -0
  34. package/dist/composio/index.js.map +1 -0
  35. package/dist/composio/json-schema.d.ts +93 -0
  36. package/dist/composio/json-schema.d.ts.map +1 -0
  37. package/dist/composio/json-schema.js +498 -0
  38. package/dist/composio/json-schema.js.map +1 -0
  39. package/dist/composio/output-protection.d.ts +32 -0
  40. package/dist/composio/output-protection.d.ts.map +1 -0
  41. package/dist/composio/output-protection.js +105 -0
  42. package/dist/composio/output-protection.js.map +1 -0
  43. package/dist/composio/service.d.ts +181 -0
  44. package/dist/composio/service.d.ts.map +1 -0
  45. package/dist/composio/service.js +758 -0
  46. package/dist/composio/service.js.map +1 -0
  47. package/dist/media-providers/capability-registry.d.ts +28 -0
  48. package/dist/media-providers/capability-registry.d.ts.map +1 -0
  49. package/dist/media-providers/capability-registry.js +27 -0
  50. package/dist/media-providers/capability-registry.js.map +1 -0
  51. package/dist/media-providers/catalog.d.ts +20 -0
  52. package/dist/media-providers/catalog.d.ts.map +1 -0
  53. package/dist/media-providers/catalog.js +20 -0
  54. package/dist/media-providers/catalog.js.map +1 -0
  55. package/dist/media-providers/dispatch/context.d.ts +21 -0
  56. package/dist/media-providers/dispatch/context.d.ts.map +1 -0
  57. package/dist/media-providers/dispatch/context.js +36 -0
  58. package/dist/media-providers/dispatch/context.js.map +1 -0
  59. package/dist/media-providers/dispatch/credentials.d.ts +4 -0
  60. package/dist/media-providers/dispatch/credentials.d.ts.map +1 -0
  61. package/dist/media-providers/dispatch/credentials.js +25 -0
  62. package/dist/media-providers/dispatch/credentials.js.map +1 -0
  63. package/dist/media-providers/dispatch/engine.d.ts +30 -0
  64. package/dist/media-providers/dispatch/engine.d.ts.map +1 -0
  65. package/dist/media-providers/dispatch/engine.js +208 -0
  66. package/dist/media-providers/dispatch/engine.js.map +1 -0
  67. package/dist/media-providers/dispatch/index.d.ts +25 -0
  68. package/dist/media-providers/dispatch/index.d.ts.map +1 -0
  69. package/dist/media-providers/dispatch/index.js +24 -0
  70. package/dist/media-providers/dispatch/index.js.map +1 -0
  71. package/dist/media-providers/dispatch/openai-compatible.d.ts +44 -0
  72. package/dist/media-providers/dispatch/openai-compatible.d.ts.map +1 -0
  73. package/dist/media-providers/dispatch/openai-compatible.js +214 -0
  74. package/dist/media-providers/dispatch/openai-compatible.js.map +1 -0
  75. package/dist/media-providers/dispatch/providers/aihubmix-shared.d.ts +72 -0
  76. package/dist/media-providers/dispatch/providers/aihubmix-shared.d.ts.map +1 -0
  77. package/dist/media-providers/dispatch/providers/aihubmix-shared.js +131 -0
  78. package/dist/media-providers/dispatch/providers/aihubmix-shared.js.map +1 -0
  79. package/dist/media-providers/dispatch/providers/aihubmix.d.ts +4 -0
  80. package/dist/media-providers/dispatch/providers/aihubmix.d.ts.map +1 -0
  81. package/dist/media-providers/dispatch/providers/aihubmix.js +205 -0
  82. package/dist/media-providers/dispatch/providers/aihubmix.js.map +1 -0
  83. package/dist/media-providers/dispatch/providers/custom-image.d.ts +6 -0
  84. package/dist/media-providers/dispatch/providers/custom-image.d.ts.map +1 -0
  85. package/dist/media-providers/dispatch/providers/custom-image.js +94 -0
  86. package/dist/media-providers/dispatch/providers/custom-image.js.map +1 -0
  87. package/dist/media-providers/dispatch/providers/elevenlabs.d.ts +4 -0
  88. package/dist/media-providers/dispatch/providers/elevenlabs.d.ts.map +1 -0
  89. package/dist/media-providers/dispatch/providers/elevenlabs.js +163 -0
  90. package/dist/media-providers/dispatch/providers/elevenlabs.js.map +1 -0
  91. package/dist/media-providers/dispatch/providers/fishaudio.d.ts +3 -0
  92. package/dist/media-providers/dispatch/providers/fishaudio.d.ts.map +1 -0
  93. package/dist/media-providers/dispatch/providers/fishaudio.js +83 -0
  94. package/dist/media-providers/dispatch/providers/fishaudio.js.map +1 -0
  95. package/dist/media-providers/dispatch/providers/grok.d.ts +15 -0
  96. package/dist/media-providers/dispatch/providers/grok.d.ts.map +1 -0
  97. package/dist/media-providers/dispatch/providers/grok.js +150 -0
  98. package/dist/media-providers/dispatch/providers/grok.js.map +1 -0
  99. package/dist/media-providers/dispatch/providers/imagerouter.d.ts +6 -0
  100. package/dist/media-providers/dispatch/providers/imagerouter.d.ts.map +1 -0
  101. package/dist/media-providers/dispatch/providers/imagerouter.js +131 -0
  102. package/dist/media-providers/dispatch/providers/imagerouter.js.map +1 -0
  103. package/dist/media-providers/dispatch/providers/minimax.d.ts +3 -0
  104. package/dist/media-providers/dispatch/providers/minimax.d.ts.map +1 -0
  105. package/dist/media-providers/dispatch/providers/minimax.js +96 -0
  106. package/dist/media-providers/dispatch/providers/minimax.js.map +1 -0
  107. package/dist/media-providers/dispatch/providers/nanobanana.d.ts +3 -0
  108. package/dist/media-providers/dispatch/providers/nanobanana.d.ts.map +1 -0
  109. package/dist/media-providers/dispatch/providers/nanobanana.js +142 -0
  110. package/dist/media-providers/dispatch/providers/nanobanana.js.map +1 -0
  111. package/dist/media-providers/dispatch/providers/openai.d.ts +4 -0
  112. package/dist/media-providers/dispatch/providers/openai.d.ts.map +1 -0
  113. package/dist/media-providers/dispatch/providers/openai.js +231 -0
  114. package/dist/media-providers/dispatch/providers/openai.js.map +1 -0
  115. package/dist/media-providers/dispatch/providers/openrouter.d.ts +13 -0
  116. package/dist/media-providers/dispatch/providers/openrouter.d.ts.map +1 -0
  117. package/dist/media-providers/dispatch/providers/openrouter.js +152 -0
  118. package/dist/media-providers/dispatch/providers/openrouter.js.map +1 -0
  119. package/dist/media-providers/dispatch/providers/senseaudio.d.ts +4 -0
  120. package/dist/media-providers/dispatch/providers/senseaudio.d.ts.map +1 -0
  121. package/dist/media-providers/dispatch/providers/senseaudio.js +190 -0
  122. package/dist/media-providers/dispatch/providers/senseaudio.js.map +1 -0
  123. package/dist/media-providers/dispatch/providers/volcengine.d.ts +3 -0
  124. package/dist/media-providers/dispatch/providers/volcengine.d.ts.map +1 -0
  125. package/dist/media-providers/dispatch/providers/volcengine.js +95 -0
  126. package/dist/media-providers/dispatch/providers/volcengine.js.map +1 -0
  127. package/dist/media-providers/dispatch/response-parsers.d.ts +44 -0
  128. package/dist/media-providers/dispatch/response-parsers.d.ts.map +1 -0
  129. package/dist/media-providers/dispatch/response-parsers.js +103 -0
  130. package/dist/media-providers/dispatch/response-parsers.js.map +1 -0
  131. package/dist/media-providers/dispatch/ssrf-guard.d.ts +51 -0
  132. package/dist/media-providers/dispatch/ssrf-guard.d.ts.map +1 -0
  133. package/dist/media-providers/dispatch/ssrf-guard.js +215 -0
  134. package/dist/media-providers/dispatch/ssrf-guard.js.map +1 -0
  135. package/dist/media-providers/dispatch/stub.d.ts +5 -0
  136. package/dist/media-providers/dispatch/stub.d.ts.map +1 -0
  137. package/dist/media-providers/dispatch/stub.js +98 -0
  138. package/dist/media-providers/dispatch/stub.js.map +1 -0
  139. package/dist/media-providers/dispatch/types.d.ts +133 -0
  140. package/dist/media-providers/dispatch/types.d.ts.map +1 -0
  141. package/dist/media-providers/dispatch/types.js +2 -0
  142. package/dist/media-providers/dispatch/types.js.map +1 -0
  143. package/dist/media-providers/dispatch/vendor-adapter.d.ts +54 -0
  144. package/dist/media-providers/dispatch/vendor-adapter.d.ts.map +1 -0
  145. package/dist/media-providers/dispatch/vendor-adapter.js +68 -0
  146. package/dist/media-providers/dispatch/vendor-adapter.js.map +1 -0
  147. package/dist/media-providers/dispatch/vendor-registry.d.ts +36 -0
  148. package/dist/media-providers/dispatch/vendor-registry.d.ts.map +1 -0
  149. package/dist/media-providers/dispatch/vendor-registry.js +46 -0
  150. package/dist/media-providers/dispatch/vendor-registry.js.map +1 -0
  151. package/dist/media-providers/index.d.ts +22 -0
  152. package/dist/media-providers/index.d.ts.map +1 -0
  153. package/dist/media-providers/index.js +22 -0
  154. package/dist/media-providers/index.js.map +1 -0
  155. package/dist/media-providers/policy.d.ts +49 -0
  156. package/dist/media-providers/policy.d.ts.map +1 -0
  157. package/dist/media-providers/policy.js +39 -0
  158. package/dist/media-providers/policy.js.map +1 -0
  159. package/dist/media-providers/providers.d.ts +33 -0
  160. package/dist/media-providers/providers.d.ts.map +1 -0
  161. package/dist/media-providers/providers.js +200 -0
  162. package/dist/media-providers/providers.js.map +1 -0
  163. package/dist/media-providers/seed.d.ts +14 -0
  164. package/dist/media-providers/seed.d.ts.map +1 -0
  165. package/dist/media-providers/seed.js +109 -0
  166. package/dist/media-providers/seed.js.map +1 -0
  167. package/dist/media-providers/sqlite-task-store.d.ts +29 -0
  168. package/dist/media-providers/sqlite-task-store.d.ts.map +1 -0
  169. package/dist/media-providers/sqlite-task-store.js +234 -0
  170. package/dist/media-providers/sqlite-task-store.js.map +1 -0
  171. package/dist/media-providers/staging.d.ts +29 -0
  172. package/dist/media-providers/staging.d.ts.map +1 -0
  173. package/dist/media-providers/staging.js +141 -0
  174. package/dist/media-providers/staging.js.map +1 -0
  175. package/dist/media-providers/task-store.d.ts +94 -0
  176. package/dist/media-providers/task-store.d.ts.map +1 -0
  177. package/dist/media-providers/task-store.js +160 -0
  178. package/dist/media-providers/task-store.js.map +1 -0
  179. package/dist/media-providers/tokens.d.ts +7 -0
  180. package/dist/media-providers/tokens.d.ts.map +1 -0
  181. package/dist/media-providers/tokens.js +13 -0
  182. package/dist/media-providers/tokens.js.map +1 -0
  183. package/dist/media-providers/types.d.ts +123 -0
  184. package/dist/media-providers/types.d.ts.map +1 -0
  185. package/dist/media-providers/types.js +12 -0
  186. package/dist/media-providers/types.js.map +1 -0
  187. package/dist/media-providers/video-request.d.ts +62 -0
  188. package/dist/media-providers/video-request.d.ts.map +1 -0
  189. package/dist/media-providers/video-request.js +219 -0
  190. package/dist/media-providers/video-request.js.map +1 -0
  191. package/package.json +93 -0
@@ -0,0 +1,234 @@
1
+ const VALID_STATUSES = new Set([
2
+ 'queued',
3
+ 'running',
4
+ 'done',
5
+ 'failed',
6
+ 'interrupted',
7
+ ]);
8
+ const TERMINAL_STATUSES = new Set(['done', 'failed', 'interrupted']);
9
+ // Mirrors task-store.ts's own ALLOWED_TRANSITIONS exactly (CR-013: enum
10
+ // membership alone doesn't prove a transition is legal, e.g. done -> running).
11
+ const ALLOWED_TRANSITIONS = {
12
+ queued: new Set(['queued', 'running', 'done', 'failed', 'interrupted']),
13
+ running: new Set(['running', 'done', 'failed', 'interrupted']),
14
+ done: new Set(['done']),
15
+ failed: new Set(['failed']),
16
+ interrupted: new Set(['interrupted']),
17
+ };
18
+ const INTERRUPTED_ERROR = {
19
+ message: 'media task interrupted by daemon restart',
20
+ code: 'DAEMON_RESTART',
21
+ };
22
+ function assertValidStatus(status) {
23
+ if (!VALID_STATUSES.has(status)) {
24
+ throw new RangeError(`Invalid media task status: "${status}"`);
25
+ }
26
+ }
27
+ /**
28
+ * Reconstructs a `MediaTask` from a stored row. `surface`/`model` are
29
+ * conditionally spread — matching `task-store.ts`'s own in-memory adapter,
30
+ * which never assigns `undefined` to an optional field (this package's
31
+ * `exactOptionalPropertyTypes: true` tsconfig would reject that) — a task
32
+ * created without a `surface`/`model` has no key at all, not a key set to
33
+ * `undefined`.
34
+ */
35
+ function rowToTask(row) {
36
+ return {
37
+ id: row.id,
38
+ ownerRef: row.owner_ref,
39
+ status: row.status,
40
+ progress: JSON.parse(row.progress),
41
+ file: row.file === null ? null : JSON.parse(row.file),
42
+ error: row.error === null ? null : JSON.parse(row.error),
43
+ startedAt: row.started_at,
44
+ endedAt: row.ended_at,
45
+ createdAt: row.created_at,
46
+ updatedAt: row.updated_at,
47
+ ...(row.surface !== null ? { surface: row.surface } : {}),
48
+ ...(row.model !== null ? { model: row.model } : {}),
49
+ };
50
+ }
51
+ /**
52
+ * Opens (creating if absent) a `better-sqlite3` database at `dbPath` and
53
+ * returns a `MediaTaskStore` backed by it. Pass `':memory:'` for a
54
+ * non-durable in-process database (useful in tests that want SQL semantics
55
+ * without a file). Schema creation is idempotent (`CREATE TABLE IF NOT
56
+ * EXISTS`), so re-opening the same file resumes from whatever was durably
57
+ * committed — this is what makes an in-flight job's state survive a
58
+ * process restart: a fresh `createSqliteMediaTaskStore(dbPath)` call after
59
+ * the process comes back up sees every task exactly as it was left, and
60
+ * `reconcileOnBoot` can then mark anything still `queued`/`running` as
61
+ * `interrupted`.
62
+ *
63
+ * `better-sqlite3` (a native compiled addon) is dynamically imported here
64
+ * rather than statically at module scope (mirroring `@jini-ai/daemon`'s
65
+ * `loadRealSpawnPty`/`node-pty` pattern) — this package's root barrel
66
+ * re-exports this module unconditionally, so a static top-level import would
67
+ * force every consumer of `@jini-ai/integrations/media-providers`, even one wanting only
68
+ * `renderStub`, to load the native binary at module-evaluation time. Now
69
+ * only an actual `createSqliteMediaTaskStore` call pays that cost, and it
70
+ * fails cleanly (a rejected promise) rather than crashing unrelated imports
71
+ * if the platform/environment lacks a usable prebuild.
72
+ */
73
+ export async function createSqliteMediaTaskStore(dbPath) {
74
+ const { default: Database } = await import('better-sqlite3');
75
+ const db = new Database(dbPath);
76
+ db.pragma('journal_mode = WAL');
77
+ db.exec(`
78
+ CREATE TABLE IF NOT EXISTS jini_media_tasks (
79
+ id TEXT PRIMARY KEY,
80
+ owner_ref TEXT NOT NULL,
81
+ status TEXT NOT NULL,
82
+ surface TEXT,
83
+ model TEXT,
84
+ progress TEXT NOT NULL,
85
+ file TEXT,
86
+ error TEXT,
87
+ started_at INTEGER NOT NULL,
88
+ ended_at INTEGER,
89
+ created_at INTEGER NOT NULL,
90
+ updated_at INTEGER NOT NULL
91
+ );
92
+
93
+ CREATE INDEX IF NOT EXISTS idx_jini_media_tasks_owner
94
+ ON jini_media_tasks (owner_ref, status);
95
+ `);
96
+ const getStmt = db.prepare('SELECT * FROM jini_media_tasks WHERE id = ?');
97
+ const insertStmt = db.prepare(`
98
+ INSERT INTO jini_media_tasks
99
+ (id, owner_ref, status, surface, model, progress, file, error, started_at, ended_at, created_at, updated_at)
100
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
101
+ `);
102
+ const updateStmt = db.prepare(`
103
+ UPDATE jini_media_tasks
104
+ SET status = ?, surface = ?, model = ?, progress = ?, file = ?, error = ?, ended_at = ?, updated_at = ?
105
+ WHERE id = ?
106
+ `);
107
+ const deleteStmt = db.prepare('DELETE FROM jini_media_tasks WHERE id = ?');
108
+ const listAllForOwnerStmt = db.prepare('SELECT * FROM jini_media_tasks WHERE owner_ref = ? ORDER BY started_at DESC');
109
+ const listInFlightForOwnerStmt = db.prepare(`SELECT * FROM jini_media_tasks WHERE owner_ref = ? AND status NOT IN ('done', 'failed', 'interrupted') ORDER BY started_at DESC`);
110
+ const selectAllStmt = db.prepare('SELECT * FROM jini_media_tasks');
111
+ function writeRow(task, isInsert) {
112
+ const progressJson = JSON.stringify(task.progress);
113
+ const fileJson = task.file == null ? null : JSON.stringify(task.file);
114
+ const errorJson = task.error == null ? null : JSON.stringify(task.error);
115
+ const surface = task.surface ?? null;
116
+ const model = task.model ?? null;
117
+ if (isInsert) {
118
+ insertStmt.run(task.id, task.ownerRef, task.status, surface, model, progressJson, fileJson, errorJson, task.startedAt, task.endedAt, task.createdAt, task.updatedAt);
119
+ }
120
+ else {
121
+ updateStmt.run(task.status, surface, model, progressJson, fileJson, errorJson, task.endedAt, task.updatedAt, task.id);
122
+ }
123
+ }
124
+ const createTxn = db.transaction((input) => {
125
+ if (getStmt.get(input.id)) {
126
+ throw new Error(`media task "${input.id}" already exists`);
127
+ }
128
+ const status = input.status ?? 'queued';
129
+ assertValidStatus(status);
130
+ const now = Date.now();
131
+ const startedAt = input.startedAt ?? now;
132
+ const task = {
133
+ id: input.id,
134
+ ownerRef: input.ownerRef,
135
+ status,
136
+ progress: input.progress ? [...input.progress] : [],
137
+ file: input.file == null ? null : structuredClone(input.file),
138
+ error: input.error == null ? null : { ...input.error },
139
+ startedAt,
140
+ endedAt: null,
141
+ createdAt: now,
142
+ updatedAt: now,
143
+ ...(input.surface !== undefined ? { surface: input.surface } : {}),
144
+ ...(input.model !== undefined ? { model: input.model } : {}),
145
+ };
146
+ writeRow(task, true);
147
+ return task;
148
+ });
149
+ const updateTxn = db.transaction((id, patch) => {
150
+ const row = getStmt.get(id);
151
+ if (!row)
152
+ return null;
153
+ const existing = rowToTask(row);
154
+ const status = patch.status ?? existing.status;
155
+ assertValidStatus(status);
156
+ if (!ALLOWED_TRANSITIONS[existing.status].has(status)) {
157
+ throw new RangeError(`Invalid media task transition: "${existing.status}" -> "${status}"`);
158
+ }
159
+ const surface = 'surface' in patch ? (patch.surface ?? undefined) : existing.surface;
160
+ const model = 'model' in patch ? (patch.model ?? undefined) : existing.model;
161
+ const next = {
162
+ id: existing.id,
163
+ ownerRef: existing.ownerRef,
164
+ status,
165
+ progress: patch.progress ? [...patch.progress] : existing.progress,
166
+ file: 'file' in patch ? (patch.file == null ? null : structuredClone(patch.file)) : existing.file,
167
+ error: 'error' in patch ? (patch.error == null ? null : { ...patch.error }) : existing.error,
168
+ startedAt: existing.startedAt,
169
+ endedAt: 'endedAt' in patch ? (patch.endedAt ?? null) : existing.endedAt,
170
+ createdAt: existing.createdAt,
171
+ updatedAt: Date.now(),
172
+ ...(surface !== undefined ? { surface } : {}),
173
+ ...(model !== undefined ? { model } : {}),
174
+ };
175
+ writeRow(next, false);
176
+ return next;
177
+ });
178
+ const reconcileTxn = db.transaction((options) => {
179
+ const now = options.now ?? Date.now();
180
+ const cutoff = now - options.terminalTtlMs;
181
+ let interrupted = 0;
182
+ let deleted = 0;
183
+ for (const row of selectAllStmt.all()) {
184
+ const task = rowToTask(row);
185
+ if (task.status === 'queued' || task.status === 'running') {
186
+ const next = {
187
+ ...task,
188
+ status: 'interrupted',
189
+ error: INTERRUPTED_ERROR,
190
+ endedAt: task.endedAt ?? now,
191
+ updatedAt: now,
192
+ };
193
+ writeRow(next, false);
194
+ interrupted += 1;
195
+ continue;
196
+ }
197
+ if (TERMINAL_STATUSES.has(task.status) && (task.endedAt ?? task.updatedAt) < cutoff) {
198
+ deleteStmt.run(task.id);
199
+ deleted += 1;
200
+ }
201
+ }
202
+ return { interrupted, deleted };
203
+ });
204
+ return {
205
+ async create(input) {
206
+ return createTxn(input);
207
+ },
208
+ async get(id) {
209
+ const row = getStmt.get(id);
210
+ return row ? rowToTask(row) : null;
211
+ },
212
+ async update(id, patch) {
213
+ return updateTxn(id, patch);
214
+ },
215
+ async listByOwner(ownerRef, options = {}) {
216
+ const includeTerminal = options.includeTerminal === true;
217
+ const rows = includeTerminal ? listAllForOwnerStmt.all(ownerRef) : listInFlightForOwnerStmt.all(ownerRef);
218
+ return rows.map(rowToTask);
219
+ },
220
+ async delete(id) {
221
+ deleteStmt.run(id);
222
+ },
223
+ async reconcileOnBoot(options) {
224
+ if (!Number.isFinite(options.terminalTtlMs) || options.terminalTtlMs < 0) {
225
+ throw new RangeError(`Invalid terminalTtlMs: ${options.terminalTtlMs} must be a non-negative finite number`);
226
+ }
227
+ return reconcileTxn(options);
228
+ },
229
+ async close() {
230
+ db.close();
231
+ },
232
+ };
233
+ }
234
+ //# sourceMappingURL=sqlite-task-store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sqlite-task-store.js","sourceRoot":"","sources":["../../src/media-providers/sqlite-task-store.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,29 @@
1
+ export interface AttachmentStagingOptions {
2
+ /** Directory name created under `cwd` to hold staged copies. Defaults to `.media-attachments`. Must be a single safe path component (no separators, no `..`). */
3
+ readonly stagingDirName?: string;
4
+ /** Max age (ms) a staged file is retained before opportunistic pruning removes it. Defaults to 24h. */
5
+ readonly maxAgeMs?: number;
6
+ /** Max number of paths accepted per `stage()` call. Defaults to 50. */
7
+ readonly maxItems?: number;
8
+ /** Max bytes copied for a single staged file. Defaults to 100 MiB. */
9
+ readonly maxBytesPerFile?: number;
10
+ }
11
+ /**
12
+ * Stages a host-supplied list of local file paths for submission: a path
13
+ * already inside `cwd` is used as-is; a path outside `cwd` is copied into a
14
+ * `.media-attachments`-style staging directory under `cwd` with a random
15
+ * prefix, avoiding collisions and leaving the original untouched, but ONLY
16
+ * when it also resolves inside the caller-supplied `uploadRoot` — copying a
17
+ * file from outside `cwd` with no `uploadRoot` (or an `uploadRoot` that
18
+ * fails to resolve) throws rather than silently disabling the containment
19
+ * check, since that would let a caller stage an arbitrary host-readable file
20
+ * (SEC-RB-003). Malformed or missing paths are silently skipped —
21
+ * attachments are advisory input, not a validated contract. Opportunistically
22
+ * prunes staged files older than `maxAgeMs` on each call.
23
+ */
24
+ export interface AttachmentStaging {
25
+ stage(imagePaths: readonly string[], uploadRoot?: string | null): Promise<string[]>;
26
+ }
27
+ /** Creates a filesystem-backed `AttachmentStaging` rooted at `cwd`. */
28
+ export declare function createFsAttachmentStaging(cwd: string, options?: AttachmentStagingOptions): AttachmentStaging;
29
+ //# sourceMappingURL=staging.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"staging.d.ts","sourceRoot":"","sources":["../../src/media-providers/staging.ts"],"names":[],"mappings":"AAeA,MAAM,WAAW,wBAAwB;IACvC,iKAAiK;IACjK,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,CAAC;IACjC,uGAAuG;IACvG,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,uEAAuE;IACvE,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,sEAAsE;IACtE,QAAQ,CAAC,eAAe,CAAC,EAAE,MAAM,CAAC;CACnC;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,WAAW,iBAAiB;IAChC,KAAK,CAAC,UAAU,EAAE,SAAS,MAAM,EAAE,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;CACrF;AAiDD,uEAAuE;AACvE,wBAAgB,yBAAyB,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,GAAE,wBAA6B,GAAG,iBAAiB,CA6EhH"}
@@ -0,0 +1,141 @@
1
+ /**
2
+ * Attachment staging — a generic "temp-store a local file before it's
3
+ * submitted to a remote generation request" port. Generalized from Open
4
+ * Design's `apps/daemon/src/media/amr-image-staging.ts`. Despite the
5
+ * origin's AMR/vela-vendor-specific filename and its narrow "image paths for
6
+ * an agent turn" framing, its actual logic carries zero OD/vendor coupling —
7
+ * root-containment checks, copy-into-a-staging-dir, and TTL-based pruning
8
+ * are all generic filesystem concerns. Ported as a real, testable port +
9
+ * reference implementation (not just an interface) per the task brief,
10
+ * mirroring this package's other port/in-memory-or-fs-reference pairs.
11
+ */
12
+ import { randomUUID } from 'node:crypto';
13
+ import fs from 'node:fs';
14
+ import path from 'node:path';
15
+ const DEFAULT_STAGING_DIRNAME = '.media-attachments';
16
+ const DEFAULT_MAX_AGE_MS = 24 * 60 * 60 * 1000;
17
+ const DEFAULT_MAX_ITEMS = 50;
18
+ const DEFAULT_MAX_BYTES_PER_FILE = 100 * 1024 * 1024;
19
+ function isWithinRoot(root, candidate) {
20
+ const relativePath = path.relative(root, candidate);
21
+ return relativePath === '' || (relativePath.length > 0 && !relativePath.startsWith('..') && !path.isAbsolute(relativePath));
22
+ }
23
+ function assertSafeStagingDirName(stagingDirName) {
24
+ if (stagingDirName.length === 0 ||
25
+ path.isAbsolute(stagingDirName) ||
26
+ stagingDirName === '.' ||
27
+ stagingDirName === '..' ||
28
+ stagingDirName.includes('/') ||
29
+ stagingDirName.includes('\\')) {
30
+ throw new Error(`attachment staging: stagingDirName must be a single safe path component, got ${JSON.stringify(stagingDirName)}`);
31
+ }
32
+ }
33
+ async function pruneStagedAttachments(stagingDir, maxAgeMs) {
34
+ let entries;
35
+ try {
36
+ entries = await fs.promises.readdir(stagingDir, { withFileTypes: true });
37
+ }
38
+ catch {
39
+ return;
40
+ }
41
+ const cutoff = Date.now() - maxAgeMs;
42
+ await Promise.all(entries.map(async (entry) => {
43
+ if (!entry.isFile())
44
+ return;
45
+ const filePath = path.join(stagingDir, entry.name);
46
+ try {
47
+ const stat = await fs.promises.stat(filePath);
48
+ if (stat.mtimeMs < cutoff) {
49
+ await fs.promises.rm(filePath, { force: true });
50
+ }
51
+ }
52
+ catch {
53
+ // Best-effort cleanup only.
54
+ }
55
+ }));
56
+ }
57
+ /** Creates a filesystem-backed `AttachmentStaging` rooted at `cwd`. */
58
+ export function createFsAttachmentStaging(cwd, options = {}) {
59
+ const stagingDirName = options.stagingDirName ?? DEFAULT_STAGING_DIRNAME;
60
+ assertSafeStagingDirName(stagingDirName);
61
+ const maxAgeMs = options.maxAgeMs ?? DEFAULT_MAX_AGE_MS;
62
+ const maxItems = options.maxItems ?? DEFAULT_MAX_ITEMS;
63
+ const maxBytesPerFile = options.maxBytesPerFile ?? DEFAULT_MAX_BYTES_PER_FILE;
64
+ const root = path.resolve(cwd);
65
+ const stagingDir = path.join(root, stagingDirName);
66
+ return {
67
+ async stage(imagePaths, uploadRoot) {
68
+ if (!Array.isArray(imagePaths) || imagePaths.length === 0)
69
+ return [];
70
+ if (imagePaths.length > maxItems) {
71
+ throw new Error(`attachment staging: ${imagePaths.length} paths exceeds the ${maxItems}-item limit`);
72
+ }
73
+ // Fail closed, not open: an explicitly-supplied uploadRoot that doesn't
74
+ // resolve is a caller configuration error, not an "unrestricted" signal
75
+ // (SEC-RB-003 — the prior behavior collapsed "no uploadRoot" and
76
+ // "unresolvable uploadRoot" into the same no-restriction case, letting
77
+ // any host-readable file be staged when uploadRoot merely failed to
78
+ // resolve). Omitting uploadRoot entirely is still allowed, but then only
79
+ // paths already inside `cwd` can be staged — nothing outside `cwd` can
80
+ // be copied in without a resolvable uploadRoot to authorize it.
81
+ let uploadRootReal = null;
82
+ if (uploadRoot != null) {
83
+ try {
84
+ uploadRootReal = await fs.promises.realpath(uploadRoot);
85
+ }
86
+ catch (error) {
87
+ throw new Error(`attachment staging: uploadRoot ${JSON.stringify(uploadRoot)} could not be resolved: ${error.message}`);
88
+ }
89
+ }
90
+ await fs.promises.mkdir(stagingDir, { recursive: true });
91
+ // The staging directory is a destination this component writes into
92
+ // and later prunes/deletes from — refuse to operate through a symlink
93
+ // here, since a pre-planted symlink would redirect writes/deletes
94
+ // outside `root` (SEC-RB-003).
95
+ const stagingDirLstat = await fs.promises.lstat(stagingDir);
96
+ if (stagingDirLstat.isSymbolicLink()) {
97
+ throw new Error(`attachment staging: staging directory ${stagingDir} is a symlink, refusing to use it`);
98
+ }
99
+ await pruneStagedAttachments(stagingDir, maxAgeMs);
100
+ // `root` is guaranteed to exist at this point (the recursive mkdir above
101
+ // created it if it didn't already). Resolve its real path once so the
102
+ // "already inside cwd" check below compares like-for-like against
103
+ // `real` (itself always realpath'd) — comparing a realpath'd candidate
104
+ // against a raw `root` misfires whenever `cwd` sits under a symlinked
105
+ // prefix (e.g. macOS's /tmp -> /private/tmp, /var -> /private/var),
106
+ // causing an unnecessary copy instead of returning the path as-is.
107
+ const rootReal = await fs.promises.realpath(root).catch(() => root);
108
+ const staged = [];
109
+ for (const inputPath of imagePaths) {
110
+ if (typeof inputPath !== 'string' || inputPath.trim().length === 0)
111
+ continue;
112
+ try {
113
+ const resolved = path.resolve(inputPath);
114
+ const real = await fs.promises.realpath(resolved);
115
+ const stat = await fs.promises.stat(real);
116
+ if (!stat.isFile())
117
+ continue;
118
+ if (isWithinRoot(rootReal, real)) {
119
+ staged.push(real);
120
+ continue;
121
+ }
122
+ // Outside cwd: this is the "copy an external file into staging"
123
+ // path, which requires an authorized uploadRoot — deny by default.
124
+ if (uploadRootReal == null || !isWithinRoot(uploadRootReal, real))
125
+ continue;
126
+ if (stat.size > maxBytesPerFile)
127
+ continue;
128
+ const basename = path.basename(real);
129
+ const destination = path.join(stagingDir, `${randomUUID()}-${basename}`);
130
+ await fs.promises.copyFile(real, destination);
131
+ staged.push(destination);
132
+ }
133
+ catch {
134
+ // Ignore malformed or missing files; attachments are advisory input.
135
+ }
136
+ }
137
+ return staged;
138
+ },
139
+ };
140
+ }
141
+ //# sourceMappingURL=staging.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"staging.js","sourceRoot":"","sources":["../../src/media-providers/staging.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,94 @@
1
+ /**
2
+ * `MediaTaskStore` — the async task-tracking port for request-now,
3
+ * poll-later media generation. Generalized from OD's
4
+ * `apps/daemon/src/media/tasks.ts`, which is a `better-sqlite3`-coupled,
5
+ * synchronous CRUD module keyed on `projectId` (an OD domain noun) with a
6
+ * hardcoded SQL schema. Per extraction-plan.md §2.6 ("ports are async-only
7
+ * from day one") and the pattern already established by
8
+ * `@jini-ai/daemon`'s `EventLog` (see `packages/daemon/src/event-log.ts`), this
9
+ * is a from-scratch storage-agnostic port + in-memory reference
10
+ * implementation — not a lift — reproducing the same lifecycle semantics
11
+ * (queued → running → done|failed|interrupted, boot-time reconciliation of
12
+ * orphaned in-flight tasks, TTL-based terminal-task pruning) without a SQL
13
+ * schema or an OD project reference. A durable adapter (a future
14
+ * `@jini-ai/sqlite` addition) implements the same interface — see
15
+ * `source-map.md`.
16
+ */
17
+ export type MediaTaskStatus = 'queued' | 'running' | 'done' | 'failed' | 'interrupted';
18
+ export interface MediaTaskError {
19
+ readonly message: string;
20
+ readonly status?: number;
21
+ readonly code?: string;
22
+ }
23
+ /** One tracked media-generation task. `ownerRef` is an opaque host-supplied scoping key (e.g. a run id) — never an OD `projectId`. */
24
+ export interface MediaTask {
25
+ readonly id: string;
26
+ readonly ownerRef: string;
27
+ readonly status: MediaTaskStatus;
28
+ readonly surface?: string;
29
+ readonly model?: string;
30
+ readonly progress: readonly string[];
31
+ readonly file: unknown | null;
32
+ readonly error: MediaTaskError | null;
33
+ readonly startedAt: number;
34
+ readonly endedAt: number | null;
35
+ readonly createdAt: number;
36
+ readonly updatedAt: number;
37
+ }
38
+ export interface MediaTaskCreateInput {
39
+ readonly id: string;
40
+ readonly ownerRef: string;
41
+ readonly status?: MediaTaskStatus;
42
+ readonly surface?: string;
43
+ readonly model?: string;
44
+ readonly progress?: readonly string[];
45
+ readonly file?: unknown | null;
46
+ readonly error?: MediaTaskError | null;
47
+ readonly startedAt?: number;
48
+ }
49
+ export interface MediaTaskPatch {
50
+ readonly status?: MediaTaskStatus;
51
+ readonly surface?: string | null;
52
+ readonly model?: string | null;
53
+ readonly progress?: readonly string[];
54
+ readonly file?: unknown | null;
55
+ readonly error?: MediaTaskError | null;
56
+ readonly endedAt?: number | null;
57
+ }
58
+ export interface MediaTaskListOptions {
59
+ /** Include terminal (done/failed/interrupted) tasks. Defaults to `false` (in-flight only). */
60
+ readonly includeTerminal?: boolean;
61
+ }
62
+ export interface MediaTaskReconcileOptions {
63
+ /** How long a terminal task is retained before `reconcileOnBoot` deletes it. */
64
+ readonly terminalTtlMs: number;
65
+ /** Injectable clock for deterministic tests; defaults to `Date.now()`. */
66
+ readonly now?: number;
67
+ }
68
+ export interface MediaTaskReconcileResult {
69
+ readonly interrupted: number;
70
+ readonly deleted: number;
71
+ }
72
+ /**
73
+ * A replayable, ownerRef-scoped store for async media-generation tasks.
74
+ * `@jini-ai/integrations/media-providers` ships `createInMemoryMediaTaskStore` as the reference
75
+ * implementation; a durable adapter implements the same interface.
76
+ */
77
+ export interface MediaTaskStore {
78
+ create(input: MediaTaskCreateInput): Promise<MediaTask>;
79
+ get(id: string): Promise<MediaTask | null>;
80
+ /** Applies `patch` to an existing task and returns the updated row, or `null` if `id` is unknown. */
81
+ update(id: string, patch: MediaTaskPatch): Promise<MediaTask | null>;
82
+ listByOwner(ownerRef: string, options?: MediaTaskListOptions): Promise<MediaTask[]>;
83
+ delete(id: string): Promise<void>;
84
+ /**
85
+ * Boot-time reconciliation: marks every still-`queued`/`running` task
86
+ * `'interrupted'` (a restart mid-flight has no way to resume it) and
87
+ * deletes terminal tasks older than `terminalTtlMs`. Mirrors the origin's
88
+ * `reconcileMediaTasksOnBoot`.
89
+ */
90
+ reconcileOnBoot(options: MediaTaskReconcileOptions): Promise<MediaTaskReconcileResult>;
91
+ }
92
+ /** Creates the in-memory reference `MediaTaskStore`. No persistence — state is lost on process exit. */
93
+ export declare function createInMemoryMediaTaskStore(): MediaTaskStore;
94
+ //# sourceMappingURL=task-store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"task-store.d.ts","sourceRoot":"","sources":["../../src/media-providers/task-store.ts"],"names":[],"mappings":"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"}