gooseworks 0.4.2 → 0.4.4

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 (84) hide show
  1. package/README.md +42 -11
  2. package/dist/commands/doctor.d.ts +29 -5
  3. package/dist/commands/doctor.d.ts.map +1 -1
  4. package/dist/commands/doctor.js +107 -63
  5. package/dist/commands/doctor.js.map +1 -1
  6. package/dist/commands/fetch.d.ts +1 -0
  7. package/dist/commands/fetch.d.ts.map +1 -1
  8. package/dist/commands/fetch.js +64 -29
  9. package/dist/commands/fetch.js.map +1 -1
  10. package/dist/commands/install.d.ts.map +1 -1
  11. package/dist/commands/install.js +37 -4
  12. package/dist/commands/install.js.map +1 -1
  13. package/dist/commands/login.d.ts.map +1 -1
  14. package/dist/commands/login.js +8 -3
  15. package/dist/commands/login.js.map +1 -1
  16. package/dist/commands/skills.d.ts +34 -0
  17. package/dist/commands/skills.d.ts.map +1 -0
  18. package/dist/commands/skills.js +109 -0
  19. package/dist/commands/skills.js.map +1 -0
  20. package/dist/commands/update.d.ts.map +1 -1
  21. package/dist/commands/update.js +17 -6
  22. package/dist/commands/update.js.map +1 -1
  23. package/dist/commands/video-local.d.ts +9 -0
  24. package/dist/commands/video-local.d.ts.map +1 -0
  25. package/dist/commands/video-local.js +83 -0
  26. package/dist/commands/video-local.js.map +1 -0
  27. package/dist/commands/video-save.d.ts +3 -0
  28. package/dist/commands/video-save.d.ts.map +1 -0
  29. package/dist/commands/video-save.js +83 -0
  30. package/dist/commands/video-save.js.map +1 -0
  31. package/dist/index.js +7 -0
  32. package/dist/index.js.map +1 -1
  33. package/dist/lib/video-local-captions.d.ts +83 -0
  34. package/dist/lib/video-local-captions.d.ts.map +1 -0
  35. package/dist/lib/video-local-captions.js +261 -0
  36. package/dist/lib/video-local-captions.js.map +1 -0
  37. package/dist/lib/video-local-runtime.d.ts +8 -0
  38. package/dist/lib/video-local-runtime.d.ts.map +1 -0
  39. package/dist/lib/video-local-runtime.js +201 -0
  40. package/dist/lib/video-local-runtime.js.map +1 -0
  41. package/dist/lib/video-save-mcp.d.ts +9 -0
  42. package/dist/lib/video-save-mcp.d.ts.map +1 -0
  43. package/dist/lib/video-save-mcp.js +162 -0
  44. package/dist/lib/video-save-mcp.js.map +1 -0
  45. package/dist/lib/video-save.d.ts +77 -0
  46. package/dist/lib/video-save.d.ts.map +1 -0
  47. package/dist/lib/video-save.js +440 -0
  48. package/dist/lib/video-save.js.map +1 -0
  49. package/dist/skills/custom-video-skill.d.ts +3 -0
  50. package/dist/skills/custom-video-skill.d.ts.map +1 -0
  51. package/dist/skills/custom-video-skill.js +6 -0
  52. package/dist/skills/custom-video-skill.js.map +1 -0
  53. package/dist/skills/installer.d.ts +12 -6
  54. package/dist/skills/installer.d.ts.map +1 -1
  55. package/dist/skills/installer.js +41 -15
  56. package/dist/skills/installer.js.map +1 -1
  57. package/dist/skills/master-skill.d.ts +22 -19
  58. package/dist/skills/master-skill.d.ts.map +1 -1
  59. package/dist/skills/master-skill.js +1472 -551
  60. package/dist/skills/master-skill.js.map +1 -1
  61. package/dist/skills/package-freshness.d.ts +16 -0
  62. package/dist/skills/package-freshness.d.ts.map +1 -0
  63. package/dist/skills/package-freshness.js +36 -0
  64. package/dist/skills/package-freshness.js.map +1 -0
  65. package/dist/skills/releases.d.ts +12 -0
  66. package/dist/skills/releases.d.ts.map +1 -0
  67. package/dist/skills/releases.js +152 -0
  68. package/dist/skills/releases.js.map +1 -0
  69. package/dist/skills/routes.d.ts.map +1 -1
  70. package/dist/skills/routes.js +7 -1
  71. package/dist/skills/routes.js.map +1 -1
  72. package/dist/utils/browser-preflight.d.ts +29 -0
  73. package/dist/utils/browser-preflight.d.ts.map +1 -0
  74. package/dist/utils/browser-preflight.js +338 -0
  75. package/dist/utils/browser-preflight.js.map +1 -0
  76. package/package.json +2 -2
  77. package/skills/goose-ads/SKILL.md +124 -16
  78. package/skills/goose-product-photos/SKILL.md +55 -3
  79. package/skills/goose-video/SKILL.md +322 -253
  80. package/skills/goose-video-local/SKILL.md +1199 -234
  81. package/skills/gooseworks/SKILL.md +199 -13
  82. package/skills/make-custom-video/SKILL.md +490 -0
  83. package/skills/manifest.json +12 -0
  84. package/skills/routes.json +8 -1
@@ -0,0 +1,83 @@
1
+ export declare const MAX_CAPTION_SOURCE_BYTES: number;
2
+ export interface CaptionsPackage {
3
+ version: 1;
4
+ operation: 'captions';
5
+ source_video_url: string;
6
+ source_video_sha256: string;
7
+ ass_text: string;
8
+ edl: {
9
+ width: number;
10
+ height: number;
11
+ segments: Array<{
12
+ dur_s: number;
13
+ }>;
14
+ };
15
+ [key: string]: unknown;
16
+ }
17
+ export interface CaptionClaim {
18
+ claim_id: string;
19
+ lease_token: string;
20
+ lease_expires_at: string;
21
+ package_digest: string;
22
+ package: CaptionsPackage;
23
+ }
24
+ export interface CaptionTransport {
25
+ next(projectId: string, workerId: string): Promise<CaptionClaim | null>;
26
+ status(claimId: string, leaseToken: string): Promise<CaptionClaimStatus>;
27
+ heartbeat(claimId: string, leaseToken: string): Promise<void>;
28
+ complete(claimId: string, leaseToken: string, outputPath: string, sha256: string): Promise<void>;
29
+ }
30
+ export type CaptionClaimStatus = {
31
+ status: 'claimed';
32
+ package_digest: string;
33
+ package: CaptionsPackage;
34
+ lease_expires_at: string;
35
+ } | {
36
+ status: 'completed';
37
+ output_sha256: string;
38
+ output_url: string;
39
+ } | {
40
+ status: 'offered' | 'fallback';
41
+ };
42
+ export interface MediaProbe {
43
+ width: number;
44
+ height: number;
45
+ duration_s: number;
46
+ }
47
+ export interface CaptionRuntime {
48
+ download(url: string, target: string, expectedSha256?: string): Promise<string>;
49
+ preflight(): Promise<string>;
50
+ render(source: string, ass: string, output: string): Promise<void>;
51
+ probe(output: string): Promise<MediaProbe>;
52
+ }
53
+ export type CaptionPhase = 'claimed' | 'downloaded' | 'rendered' | 'completed';
54
+ export interface CaptionJournal {
55
+ claim_id: string;
56
+ project_id: string;
57
+ package_digest: string;
58
+ lease_token: string;
59
+ lease_expires_at: string;
60
+ ffmpeg_version: string;
61
+ phase: CaptionPhase;
62
+ source_sha256?: string;
63
+ output_sha256?: string;
64
+ }
65
+ export declare function validateCaptionClaim(claim: CaptionClaim): {
66
+ expectedDuration: number;
67
+ };
68
+ export declare function sha256File(filePath: string): Promise<string>;
69
+ /** Recover the prior lease/output before asking for new work. Never silently rerender an
70
+ * uncertain completion or let /next hide a still-active claim. */
71
+ export declare function executeNextCaptionClaim(args: {
72
+ projectId: string;
73
+ workerId: string;
74
+ workRoot: string;
75
+ transport: CaptionTransport;
76
+ runtime: CaptionRuntime;
77
+ heartbeatMs?: number;
78
+ }): Promise<{
79
+ claimId: string;
80
+ outputSha256: string;
81
+ journalPath: string;
82
+ } | null>;
83
+ //# sourceMappingURL=video-local-captions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"video-local-captions.d.ts","sourceRoot":"","sources":["../../src/lib/video-local-captions.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,261 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.MAX_CAPTION_SOURCE_BYTES = void 0;
37
+ exports.validateCaptionClaim = validateCaptionClaim;
38
+ exports.sha256File = sha256File;
39
+ exports.executeNextCaptionClaim = executeNextCaptionClaim;
40
+ /** One server-vetted local operation. This module never invokes a media provider. */
41
+ const crypto_1 = require("crypto");
42
+ const fs_1 = require("fs");
43
+ const promises_1 = require("fs/promises");
44
+ const path = __importStar(require("path"));
45
+ const SHA256 = /^[a-f0-9]{64}$/i;
46
+ const ID = /^[a-zA-Z0-9_-]{1,160}$/;
47
+ exports.MAX_CAPTION_SOURCE_BYTES = 150 * 1024 * 1024;
48
+ async function findPendingJournal(workRoot, projectId) {
49
+ let dirs;
50
+ try {
51
+ dirs = await (0, promises_1.readdir)(workRoot);
52
+ }
53
+ catch (error) {
54
+ if (error.code === 'ENOENT')
55
+ return null;
56
+ throw error;
57
+ }
58
+ const matches = [];
59
+ const unscoped = [];
60
+ for (const dir of dirs) {
61
+ if (!ID.test(dir))
62
+ continue;
63
+ const filePath = path.join(workRoot, dir, 'journal.json');
64
+ try {
65
+ const journal = JSON.parse(await (0, promises_1.readFile)(filePath, 'utf8'));
66
+ if (journal.project_id === projectId && journal.phase !== 'completed')
67
+ matches.push({ filePath, journal });
68
+ else if (!journal.project_id && journal.phase !== 'completed')
69
+ unscoped.push(filePath);
70
+ }
71
+ catch (error) {
72
+ if (error.code !== 'ENOENT')
73
+ throw error;
74
+ }
75
+ }
76
+ if (matches.length > 1)
77
+ throw new Error('Multiple unfinished caption claims exist; inspect the private journals before continuing');
78
+ if (unscoped.length)
79
+ throw new Error(`An older caption journal has no project binding; inspect it before requesting new work: ${unscoped[0]}`);
80
+ return matches[0] ?? null;
81
+ }
82
+ function validateCaptionClaim(claim) {
83
+ if (!claim || !ID.test(claim.claim_id) || !claim.lease_token ||
84
+ !SHA256.test(claim.package_digest) || !Number.isFinite(Date.parse(claim.lease_expires_at))) {
85
+ throw new Error('Invalid local caption claim identity or lease');
86
+ }
87
+ const pack = claim.package;
88
+ if (!pack || pack.version !== 1 || pack.operation !== 'captions' ||
89
+ typeof pack.source_video_url !== 'string' || !pack.source_video_url ||
90
+ typeof pack.ass_text !== 'string' || !pack.ass_text || pack.ass_text.length > 1024 * 1024 ||
91
+ !pack.ass_text.includes('[Script Info]') || !pack.ass_text.includes('[Events]')) {
92
+ throw new Error('Incomplete or unsupported local captions package');
93
+ }
94
+ const sourceUrl = new URL(pack.source_video_url);
95
+ if (sourceUrl.protocol !== 'https:' && !(sourceUrl.protocol === 'http:' &&
96
+ ['localhost', '127.0.0.1', '[::1]'].includes(sourceUrl.hostname))) {
97
+ throw new Error('Caption source must use HTTPS (or local development HTTP)');
98
+ }
99
+ if (!SHA256.test(pack.source_video_sha256)) {
100
+ throw new Error('Missing or invalid source checksum');
101
+ }
102
+ const edl = pack.edl;
103
+ if (!edl || !Number.isInteger(edl.width) || !Number.isInteger(edl.height) ||
104
+ edl.width < 16 || edl.height < 16 || edl.width > 8192 || edl.height > 8192 ||
105
+ !Array.isArray(edl.segments) || !edl.segments.length) {
106
+ throw new Error('Invalid expected caption dimensions or timeline');
107
+ }
108
+ const expectedDuration = edl.segments.reduce((sum, segment) => sum + segment.dur_s, 0);
109
+ if (!Number.isFinite(expectedDuration) || expectedDuration < 0.25 || expectedDuration > 70) {
110
+ throw new Error('Invalid expected caption duration');
111
+ }
112
+ return { expectedDuration };
113
+ }
114
+ async function sha256File(filePath) {
115
+ const hash = (0, crypto_1.createHash)('sha256');
116
+ for await (const chunk of (0, fs_1.createReadStream)(filePath))
117
+ hash.update(chunk);
118
+ return hash.digest('hex');
119
+ }
120
+ async function saveJournal(filePath, journal) {
121
+ const pending = `${filePath}.pending`;
122
+ await (0, promises_1.writeFile)(pending, JSON.stringify(journal, null, 2), { mode: 0o600 });
123
+ await (0, promises_1.rename)(pending, filePath);
124
+ }
125
+ /** Recover the prior lease/output before asking for new work. Never silently rerender an
126
+ * uncertain completion or let /next hide a still-active claim. */
127
+ async function executeNextCaptionClaim(args) {
128
+ if (!ID.test(args.projectId) || !ID.test(args.workerId))
129
+ throw new Error('Invalid project or worker ID');
130
+ const pending = await findPendingJournal(args.workRoot, args.projectId);
131
+ let claim;
132
+ let resumedJournal = null;
133
+ if (pending) {
134
+ const journal = pending.journal;
135
+ if (!ID.test(journal.claim_id) || !SHA256.test(journal.package_digest) || !journal.lease_token) {
136
+ throw new Error('Local caption recovery journal is invalid; inspect it before requesting new work');
137
+ }
138
+ let status;
139
+ try {
140
+ status = await args.transport.status(journal.claim_id, journal.lease_token);
141
+ }
142
+ catch (error) {
143
+ const reason = error instanceof Error ? error.message : String(error);
144
+ throw new Error(`Could not verify prior caption claim ${journal.claim_id} (${reason}). Do not request new work; retain the journal and rerun after server recovery: ${pending.filePath}`);
145
+ }
146
+ if (status.status === 'completed') {
147
+ if (!SHA256.test(status.output_sha256) ||
148
+ (journal.output_sha256 && journal.output_sha256 !== status.output_sha256)) {
149
+ throw new Error('Completed caption receipt does not match the recovery journal');
150
+ }
151
+ journal.output_sha256 = status.output_sha256;
152
+ journal.phase = 'completed';
153
+ await saveJournal(pending.filePath, journal);
154
+ return { claimId: journal.claim_id, outputSha256: status.output_sha256, journalPath: pending.filePath };
155
+ }
156
+ if (status.status === 'offered') {
157
+ const renewed = await args.transport.next(args.projectId, args.workerId);
158
+ if (!renewed)
159
+ throw new Error(`Caption claim ${journal.claim_id} is not reclaimable yet. Rerun after the server offers it. Recovery journal: ${pending.filePath}`);
160
+ if (renewed.claim_id !== journal.claim_id || renewed.package_digest !== journal.package_digest) {
161
+ throw new Error(`Server offered a different caption claim; inspect the old recovery journal: ${pending.filePath}`);
162
+ }
163
+ claim = renewed;
164
+ journal.lease_token = renewed.lease_token;
165
+ resumedJournal = journal;
166
+ }
167
+ else if (status.status === 'claimed') {
168
+ if (status.package_digest !== journal.package_digest ||
169
+ !Number.isFinite(Date.parse(status.lease_expires_at)) || Date.parse(status.lease_expires_at) <= Date.now()) {
170
+ throw new Error(`Caption claim ${journal.claim_id} changed or its lease expired; stop and inspect the recovery journal: ${pending.filePath}`);
171
+ }
172
+ await args.transport.heartbeat(journal.claim_id, journal.lease_token);
173
+ claim = { claim_id: journal.claim_id, lease_token: journal.lease_token,
174
+ lease_expires_at: status.lease_expires_at, package_digest: status.package_digest, package: status.package };
175
+ resumedJournal = journal;
176
+ }
177
+ else {
178
+ throw new Error(`Caption claim ${journal.claim_id} is in server fallback; no local upload is allowed. Recovery journal: ${pending.filePath}`);
179
+ }
180
+ }
181
+ else {
182
+ claim = await args.transport.next(args.projectId, args.workerId);
183
+ }
184
+ if (!claim)
185
+ return null;
186
+ const { expectedDuration } = validateCaptionClaim(claim);
187
+ const claimDir = path.join(args.workRoot, claim.claim_id);
188
+ await (0, promises_1.mkdir)(claimDir, { recursive: true, mode: 0o700 });
189
+ const journalPath = path.join(claimDir, 'journal.json');
190
+ try {
191
+ const existing = JSON.parse(await (0, promises_1.readFile)(journalPath, 'utf8'));
192
+ if (existing.package_digest !== claim.package_digest)
193
+ throw new Error('Claim package changed; refusing old local state');
194
+ }
195
+ catch (error) {
196
+ if (error.code !== 'ENOENT')
197
+ throw error;
198
+ }
199
+ const journal = resumedJournal ?? {
200
+ claim_id: claim.claim_id, project_id: args.projectId, package_digest: claim.package_digest,
201
+ lease_token: claim.lease_token, lease_expires_at: claim.lease_expires_at,
202
+ ffmpeg_version: 'pending preflight', phase: 'claimed',
203
+ };
204
+ journal.lease_expires_at = claim.lease_expires_at;
205
+ await saveJournal(journalPath, journal);
206
+ if (journal.phase !== 'rendered') {
207
+ journal.ffmpeg_version = await args.runtime.preflight();
208
+ await saveJournal(journalPath, journal);
209
+ }
210
+ let heartbeatError = null;
211
+ let heartbeatBusy = false;
212
+ const timer = setInterval(() => {
213
+ if (heartbeatBusy || heartbeatError)
214
+ return;
215
+ heartbeatBusy = true;
216
+ void args.transport.heartbeat(claim.claim_id, claim.lease_token)
217
+ .catch((error) => { heartbeatError = error instanceof Error ? error : new Error(String(error)); })
218
+ .finally(() => { heartbeatBusy = false; });
219
+ }, args.heartbeatMs ?? 60_000);
220
+ try {
221
+ const sourcePath = path.join(claimDir, 'source.mp4');
222
+ const assPath = path.join(claimDir, 'captions.ass');
223
+ const outputPath = path.join(claimDir, 'captioned.mp4');
224
+ if (journal.phase !== 'rendered') {
225
+ journal.source_sha256 = await args.runtime.download(claim.package.source_video_url, sourcePath, claim.package.source_video_sha256);
226
+ journal.phase = 'downloaded';
227
+ await saveJournal(journalPath, journal);
228
+ await (0, promises_1.writeFile)(assPath, claim.package.ass_text, { mode: 0o600 });
229
+ await args.runtime.render(sourcePath, assPath, outputPath);
230
+ }
231
+ else {
232
+ const info = await (0, promises_1.stat)(outputPath).catch(() => null);
233
+ if (!info?.isFile() || !journal.output_sha256 ||
234
+ await sha256File(outputPath) !== journal.output_sha256) {
235
+ throw new Error('Rendered caption output is missing or differs from its journal; refusing upload');
236
+ }
237
+ }
238
+ if (heartbeatError)
239
+ throw heartbeatError;
240
+ const probe = await args.runtime.probe(outputPath);
241
+ if (probe.width !== claim.package.edl.width || probe.height !== claim.package.edl.height ||
242
+ probe.duration_s < Math.max(0.25, expectedDuration - 1) ||
243
+ probe.duration_s > Math.min(70, expectedDuration + 2)) {
244
+ throw new Error('Caption output dimensions or duration do not match the server package');
245
+ }
246
+ journal.output_sha256 = await sha256File(outputPath);
247
+ journal.phase = 'rendered';
248
+ await saveJournal(journalPath, journal);
249
+ await args.transport.heartbeat(claim.claim_id, claim.lease_token);
250
+ if (heartbeatError)
251
+ throw heartbeatError;
252
+ await args.transport.complete(claim.claim_id, claim.lease_token, outputPath, journal.output_sha256);
253
+ journal.phase = 'completed';
254
+ await saveJournal(journalPath, journal);
255
+ return { claimId: claim.claim_id, outputSha256: journal.output_sha256, journalPath };
256
+ }
257
+ finally {
258
+ clearInterval(timer);
259
+ }
260
+ }
261
+ //# sourceMappingURL=video-local-captions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"video-local-captions.js","sourceRoot":"","sources":["../../src/lib/video-local-captions.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ import type { CaptionRuntime, CaptionTransport } from './video-local-captions';
2
+ export declare const LOCAL_UPLOAD_TIMEOUT_MS: number;
3
+ /** HTTP transport uses only the scoped, authenticated local-node route. */
4
+ export declare function createCaptionTransport(apiBase: string, apiKey: string): CaptionTransport;
5
+ /** Reviewed, fixed ffmpeg flags. Neither the server package nor the user supplies flags. */
6
+ export declare const ffmpegCaptionArgs: (sourceName?: string) => string[];
7
+ export declare function createCaptionRuntime(ffmpeg?: string, ffprobe?: string): CaptionRuntime;
8
+ //# sourceMappingURL=video-local-runtime.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"video-local-runtime.d.ts","sourceRoot":"","sources":["../../src/lib/video-local-runtime.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAoC,cAAc,EAAE,gBAAgB,EAAc,MAAM,wBAAwB,CAAC;AAwB7H,eAAO,MAAM,uBAAuB,QAAc,CAAC;AAcnD,2EAA2E;AAC3E,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,gBAAgB,CA6CxF;AAED,4FAA4F;AAC5F,eAAO,MAAM,iBAAiB,GAAI,mBAAyB,KAAG,MAAM,EAKnE,CAAC;AAEF,wBAAgB,oBAAoB,CAAC,MAAM,SAAW,EAAE,OAAO,SAAY,GAAG,cAAc,CAyD3F"}
@@ -0,0 +1,201 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.ffmpegCaptionArgs = exports.LOCAL_UPLOAD_TIMEOUT_MS = void 0;
37
+ exports.createCaptionTransport = createCaptionTransport;
38
+ exports.createCaptionRuntime = createCaptionRuntime;
39
+ const crypto_1 = require("crypto");
40
+ const child_process_1 = require("child_process");
41
+ const fs_1 = require("fs");
42
+ const promises_1 = require("fs/promises");
43
+ const path = __importStar(require("path"));
44
+ const stream_1 = require("stream");
45
+ const video_local_captions_1 = require("./video-local-captions");
46
+ const MAX_OUTPUT_BYTES = 150 * 1024 * 1024;
47
+ function run(bin, args, cwd, timeoutMs = 10 * 60_000) {
48
+ return new Promise((resolve, reject) => {
49
+ const child = (0, child_process_1.spawn)(bin, args, { cwd, shell: false, stdio: ['ignore', 'pipe', 'pipe'] });
50
+ let output = '';
51
+ const timeout = setTimeout(() => child.kill('SIGKILL'), timeoutMs);
52
+ const append = (chunk) => {
53
+ output = (output + chunk.toString('utf8')).slice(-1024 * 1024);
54
+ };
55
+ child.stdout.on('data', append);
56
+ child.stderr.on('data', append);
57
+ child.on('error', (error) => { clearTimeout(timeout); reject(error); });
58
+ child.on('close', (code) => {
59
+ clearTimeout(timeout);
60
+ if (code === 0)
61
+ resolve(output);
62
+ else
63
+ reject(new Error(`${bin} failed (${code ?? 'timeout'}): ${output.slice(-500)}`));
64
+ });
65
+ });
66
+ }
67
+ exports.LOCAL_UPLOAD_TIMEOUT_MS = 10 * 60_000;
68
+ async function fetchJson(url, apiKey, init, timeoutMs = 30_000) {
69
+ const response = await fetch(url, {
70
+ ...init,
71
+ headers: { Authorization: `Bearer ${apiKey}`, Accept: 'application/json', ...init.headers },
72
+ signal: AbortSignal.timeout(timeoutMs),
73
+ });
74
+ if (!response.ok)
75
+ throw new Error(`Video-local API returned HTTP ${response.status}`);
76
+ const parsed = await response.json();
77
+ if (parsed.status !== 'success')
78
+ throw new Error('Video-local API returned an unsuccessful response');
79
+ return parsed.data;
80
+ }
81
+ /** HTTP transport uses only the scoped, authenticated local-node route. */
82
+ function createCaptionTransport(apiBase, apiKey) {
83
+ if (!apiKey.startsWith('cal_'))
84
+ throw new Error('A cal_ GooseWorks token is required for local video claims');
85
+ const base = `${apiBase.replace(/\/$/, '')}/api/ads/video-local`;
86
+ return {
87
+ async next(projectId, workerId) {
88
+ const query = new URLSearchParams({ project_id: projectId, worker_id: workerId });
89
+ return fetchJson(`${base}/claims/next?${query}`, apiKey, { method: 'GET' });
90
+ },
91
+ async status(claimId, leaseToken) {
92
+ return fetchJson(`${base}/claims/${encodeURIComponent(claimId)}`, apiKey, {
93
+ method: 'GET', headers: { 'X-Video-Local-Lease': leaseToken },
94
+ });
95
+ },
96
+ async heartbeat(claimId, leaseToken) {
97
+ await fetchJson(`${base}/claims/${encodeURIComponent(claimId)}/heartbeat`, apiKey, {
98
+ method: 'POST', headers: { 'Content-Type': 'application/json' },
99
+ body: JSON.stringify({ lease_token: leaseToken }),
100
+ });
101
+ },
102
+ async complete(claimId, leaseToken, outputPath, sha256) {
103
+ const info = await (0, promises_1.stat)(outputPath);
104
+ if (!info.isFile() || info.size < 1024 || info.size > MAX_OUTPUT_BYTES) {
105
+ throw new Error('Caption output exceeds the allowed upload size');
106
+ }
107
+ const boundary = `goose-local-${(0, crypto_1.randomBytes)(16).toString('hex')}`;
108
+ const head = Buffer.from(`--${boundary}\r\nContent-Disposition: form-data; name="lease_token"\r\n\r\n${leaseToken}\r\n` +
109
+ `--${boundary}\r\nContent-Disposition: form-data; name="sha256"\r\n\r\n${sha256}\r\n` +
110
+ `--${boundary}\r\nContent-Disposition: form-data; name="file"; filename="captioned.mp4"\r\n` +
111
+ 'Content-Type: video/mp4\r\n\r\n');
112
+ const tail = Buffer.from(`\r\n--${boundary}--\r\n`);
113
+ const body = stream_1.Readable.from((async function* () {
114
+ yield head;
115
+ for await (const chunk of (0, fs_1.createReadStream)(outputPath))
116
+ yield chunk;
117
+ yield tail;
118
+ })());
119
+ await fetchJson(`${base}/claims/${encodeURIComponent(claimId)}/complete`, apiKey, {
120
+ method: 'POST', body: body,
121
+ headers: { 'Content-Type': `multipart/form-data; boundary=${boundary}`,
122
+ 'Content-Length': String(head.length + info.size + tail.length) },
123
+ duplex: 'half',
124
+ }, exports.LOCAL_UPLOAD_TIMEOUT_MS);
125
+ },
126
+ };
127
+ }
128
+ /** Reviewed, fixed ffmpeg flags. Neither the server package nor the user supplies flags. */
129
+ const ffmpegCaptionArgs = (sourceName = 'source.mp4') => [
130
+ '-hide_banner', '-nostdin', '-loglevel', 'error', '-y', '-i', sourceName,
131
+ '-map', '0:v:0', '-map', '0:a?', '-vf', 'ass=captions.ass',
132
+ '-c:v', 'libx264', '-preset', 'medium', '-crf', '18', '-pix_fmt', 'yuv420p',
133
+ '-c:a', 'copy', '-sn', '-dn', '-movflags', '+faststart', 'captioned.mp4',
134
+ ];
135
+ exports.ffmpegCaptionArgs = ffmpegCaptionArgs;
136
+ function createCaptionRuntime(ffmpeg = 'ffmpeg', ffprobe = 'ffprobe') {
137
+ return {
138
+ async preflight() {
139
+ const version = (await run(ffmpeg, ['-version'])).split('\n')[0];
140
+ const encoders = await run(ffmpeg, ['-hide_banner', '-encoders']);
141
+ const filters = await run(ffmpeg, ['-hide_banner', '-filters']);
142
+ if (!/\blibx264\b/.test(encoders) || !/\bass\b/.test(filters)) {
143
+ throw new Error('ffmpeg requires libx264 and the libass ass filter');
144
+ }
145
+ await run(ffprobe, ['-version']);
146
+ return version;
147
+ },
148
+ async download(url, target, expectedSha256) {
149
+ const response = await fetch(url, {
150
+ redirect: 'error', signal: AbortSignal.timeout(180_000),
151
+ });
152
+ if (!response.ok || !response.body)
153
+ throw new Error(`Caption source download failed (HTTP ${response.status})`);
154
+ const length = Number(response.headers.get('content-length'));
155
+ if (Number.isFinite(length) && length > video_local_captions_1.MAX_CAPTION_SOURCE_BYTES)
156
+ throw new Error('Caption source exceeds size cap');
157
+ const file = await (0, promises_1.open)(target, 'w', 0o600);
158
+ const hash = (0, crypto_1.createHash)('sha256');
159
+ let size = 0;
160
+ try {
161
+ const reader = response.body.getReader();
162
+ for (;;) {
163
+ const { done, value } = await reader.read();
164
+ if (done)
165
+ break;
166
+ size += value.byteLength;
167
+ if (size > video_local_captions_1.MAX_CAPTION_SOURCE_BYTES)
168
+ throw new Error('Caption source exceeds size cap');
169
+ hash.update(value);
170
+ await file.write(value);
171
+ }
172
+ }
173
+ finally {
174
+ await file.close();
175
+ }
176
+ if (size < 1024)
177
+ throw new Error('Caption source is too small');
178
+ const actual = hash.digest('hex');
179
+ if (expectedSha256 && actual !== expectedSha256.toLowerCase())
180
+ throw new Error('Caption source checksum mismatch');
181
+ return actual;
182
+ },
183
+ async render(source, ass, output) {
184
+ const dir = path.dirname(output);
185
+ if (path.dirname(source) !== dir || path.dirname(ass) !== dir ||
186
+ path.basename(source) !== 'source.mp4' || path.basename(ass) !== 'captions.ass' ||
187
+ path.basename(output) !== 'captioned.mp4') {
188
+ throw new Error('Caption renderer requires its private claim directory');
189
+ }
190
+ await run(ffmpeg, (0, exports.ffmpegCaptionArgs)(), dir);
191
+ },
192
+ async probe(output) {
193
+ const raw = await run(ffprobe, ['-v', 'error', '-select_streams', 'v:0',
194
+ '-show_entries', 'stream=width,height:format=duration', '-of', 'json', output]);
195
+ const data = JSON.parse(raw);
196
+ return { width: Number(data.streams?.[0]?.width), height: Number(data.streams?.[0]?.height),
197
+ duration_s: Number(data.format?.duration) };
198
+ },
199
+ };
200
+ }
201
+ //# sourceMappingURL=video-local-runtime.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"video-local-runtime.js","sourceRoot":"","sources":["../../src/lib/video-local-runtime.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ /** Uses the normal saved CLI login and canonical MCP tools, never raw Ads REST. */
2
+ import type { Credentials } from '../auth/credentials';
3
+ import type { SaveTransport } from './video-save';
4
+ export declare class SaveToolError extends Error {
5
+ readonly code: string;
6
+ constructor(code: string);
7
+ }
8
+ export declare function createSaveTransport(creds: Credentials): Promise<SaveTransport>;
9
+ //# sourceMappingURL=video-save-mcp.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"video-save-mcp.d.ts","sourceRoot":"","sources":["../../src/lib/video-save-mcp.ts"],"names":[],"mappings":"AAAA,mFAAmF;AACnF,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AACvD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAElD,qBAAa,aAAc,SAAQ,KAAK;aACV,IAAI,EAAE,MAAM;gBAAZ,IAAI,EAAE,MAAM;CACzC;AAyBD,wBAAsB,mBAAmB,CAAC,KAAK,EAAE,WAAW,GAAG,OAAO,CAAC,aAAa,CAAC,CAmFpF"}