gooseworks 0.3.3 → 0.3.5
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.
- package/dist/commands/doctor.d.ts +10 -0
- package/dist/commands/doctor.d.ts.map +1 -0
- package/dist/commands/doctor.js +118 -0
- package/dist/commands/doctor.js.map +1 -0
- package/dist/commands/login.d.ts.map +1 -1
- package/dist/commands/login.js +17 -0
- package/dist/commands/login.js.map +1 -1
- package/dist/commands/logout.d.ts.map +1 -1
- package/dist/commands/logout.js +7 -1
- package/dist/commands/logout.js.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/skills/master-skill.d.ts +16 -1
- package/dist/skills/master-skill.d.ts.map +1 -1
- package/dist/skills/master-skill.js +247 -2
- package/dist/skills/master-skill.js.map +1 -1
- package/package.json +1 -1
- package/skills/gooseworks/SKILL.md +4 -3
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { Command } from 'commander';
|
|
2
|
+
/**
|
|
3
|
+
* `gooseworks doctor` — verify the local prerequisites for making VIDEO ads
|
|
4
|
+
* (the goose-video skill renders locally: Playwright records the mockup, ffmpeg
|
|
5
|
+
* stitches/mixes). Also checks auth + that the GooseWorks MCP server is wired,
|
|
6
|
+
* since the skill reads/writes the project over MCP. Exits non-zero if anything
|
|
7
|
+
* is missing so the agent's Phase-0 preflight can relay the fix and stop.
|
|
8
|
+
*/
|
|
9
|
+
export declare const doctorCommand: Command;
|
|
10
|
+
//# sourceMappingURL=doctor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"doctor.d.ts","sourceRoot":"","sources":["../../src/commands/doctor.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAmCpC;;;;;;GAMG;AACH,eAAO,MAAM,aAAa,SAiDtB,CAAC"}
|
|
@@ -0,0 +1,118 @@
|
|
|
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.doctorCommand = void 0;
|
|
37
|
+
const commander_1 = require("commander");
|
|
38
|
+
const child_process_1 = require("child_process");
|
|
39
|
+
const credentials_1 = require("../auth/credentials");
|
|
40
|
+
const logger = __importStar(require("../utils/logger"));
|
|
41
|
+
/** True if `bin` resolves on PATH (cross-platform). */
|
|
42
|
+
function onPath(bin) {
|
|
43
|
+
const probe = process.platform === 'win32' ? 'where' : 'which';
|
|
44
|
+
try {
|
|
45
|
+
return (0, child_process_1.spawnSync)(probe, [bin], { stdio: 'ignore' }).status === 0;
|
|
46
|
+
}
|
|
47
|
+
catch {
|
|
48
|
+
return false;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
/** Playwright is usable either as a global bin or via `npx playwright`. */
|
|
52
|
+
function hasPlaywright() {
|
|
53
|
+
if (onPath('playwright'))
|
|
54
|
+
return true;
|
|
55
|
+
try {
|
|
56
|
+
return ((0, child_process_1.spawnSync)('npx', ['--no-install', 'playwright', '--version'], {
|
|
57
|
+
stdio: 'ignore',
|
|
58
|
+
}).status === 0);
|
|
59
|
+
}
|
|
60
|
+
catch {
|
|
61
|
+
return false;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* `gooseworks doctor` — verify the local prerequisites for making VIDEO ads
|
|
66
|
+
* (the goose-video skill renders locally: Playwright records the mockup, ffmpeg
|
|
67
|
+
* stitches/mixes). Also checks auth + that the GooseWorks MCP server is wired,
|
|
68
|
+
* since the skill reads/writes the project over MCP. Exits non-zero if anything
|
|
69
|
+
* is missing so the agent's Phase-0 preflight can relay the fix and stop.
|
|
70
|
+
*/
|
|
71
|
+
exports.doctorCommand = new commander_1.Command('doctor')
|
|
72
|
+
.description('Check local prerequisites for video ad rendering (ffmpeg, Playwright) + auth/MCP')
|
|
73
|
+
.action(() => {
|
|
74
|
+
const creds = (0, credentials_1.getCredentials)();
|
|
75
|
+
const checks = [
|
|
76
|
+
{ label: 'Logged in', ok: !!creds, fix: 'gooseworks login' },
|
|
77
|
+
{
|
|
78
|
+
label: 'GooseWorks MCP configured',
|
|
79
|
+
ok: !!creds?.mcp_server_url,
|
|
80
|
+
fix: 'gooseworks install --claude --mcp (then restart Claude Code)',
|
|
81
|
+
},
|
|
82
|
+
{
|
|
83
|
+
label: 'ffmpeg on PATH',
|
|
84
|
+
ok: onPath('ffmpeg'),
|
|
85
|
+
fix: 'brew install ffmpeg (macOS) / apt-get install ffmpeg (Linux)',
|
|
86
|
+
},
|
|
87
|
+
{
|
|
88
|
+
label: 'ffprobe on PATH',
|
|
89
|
+
ok: onPath('ffprobe'),
|
|
90
|
+
fix: 'bundled with ffmpeg — install ffmpeg',
|
|
91
|
+
},
|
|
92
|
+
{
|
|
93
|
+
label: 'Playwright (Chromium renderer)',
|
|
94
|
+
ok: hasPlaywright(),
|
|
95
|
+
fix: 'npx playwright install chromium',
|
|
96
|
+
},
|
|
97
|
+
];
|
|
98
|
+
logger.info('GooseWorks doctor — prerequisites for local video ad rendering\n');
|
|
99
|
+
let allOk = true;
|
|
100
|
+
for (const c of checks) {
|
|
101
|
+
if (c.ok) {
|
|
102
|
+
logger.success(c.label);
|
|
103
|
+
}
|
|
104
|
+
else {
|
|
105
|
+
logger.error(`${c.label} → fix: ${c.fix}`);
|
|
106
|
+
allOk = false;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
logger.info('');
|
|
110
|
+
if (allOk) {
|
|
111
|
+
logger.success('All set — you can make video ads locally (goose-video).');
|
|
112
|
+
}
|
|
113
|
+
else {
|
|
114
|
+
logger.warn('Some prerequisites are missing. Fix the items above, then re-run: gooseworks doctor');
|
|
115
|
+
process.exitCode = 1;
|
|
116
|
+
}
|
|
117
|
+
});
|
|
118
|
+
//# sourceMappingURL=doctor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"doctor.js","sourceRoot":"","sources":["../../src/commands/doctor.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,yCAAoC;AACpC,iDAA0C;AAC1C,qDAAqD;AACrD,wDAA0C;AAE1C,uDAAuD;AACvD,SAAS,MAAM,CAAC,GAAW;IACzB,MAAM,KAAK,GAAG,OAAO,CAAC,QAAQ,KAAK,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC;IAC/D,IAAI,CAAC;QACH,OAAO,IAAA,yBAAS,EAAC,KAAK,EAAE,CAAC,GAAG,CAAC,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC;IACnE,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED,2EAA2E;AAC3E,SAAS,aAAa;IACpB,IAAI,MAAM,CAAC,YAAY,CAAC;QAAE,OAAO,IAAI,CAAC;IACtC,IAAI,CAAC;QACH,OAAO,CACL,IAAA,yBAAS,EAAC,KAAK,EAAE,CAAC,cAAc,EAAE,YAAY,EAAE,WAAW,CAAC,EAAE;YAC5D,KAAK,EAAE,QAAQ;SAChB,CAAC,CAAC,MAAM,KAAK,CAAC,CAChB,CAAC;IACJ,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAQD;;;;;;GAMG;AACU,QAAA,aAAa,GAAG,IAAI,mBAAO,CAAC,QAAQ,CAAC;KAC/C,WAAW,CACV,kFAAkF,CACnF;KACA,MAAM,CAAC,GAAG,EAAE;IACX,MAAM,KAAK,GAAG,IAAA,4BAAc,GAAE,CAAC;IAC/B,MAAM,MAAM,GAAY;QACtB,EAAE,KAAK,EAAE,WAAW,EAAE,EAAE,EAAE,CAAC,CAAC,KAAK,EAAE,GAAG,EAAE,kBAAkB,EAAE;QAC5D;YACE,KAAK,EAAE,2BAA2B;YAClC,EAAE,EAAE,CAAC,CAAC,KAAK,EAAE,cAAc;YAC3B,GAAG,EAAE,+DAA+D;SACrE;QACD;YACE,KAAK,EAAE,gBAAgB;YACvB,EAAE,EAAE,MAAM,CAAC,QAAQ,CAAC;YACpB,GAAG,EAAE,8DAA8D;SACpE;QACD;YACE,KAAK,EAAE,iBAAiB;YACxB,EAAE,EAAE,MAAM,CAAC,SAAS,CAAC;YACrB,GAAG,EAAE,sCAAsC;SAC5C;QACD;YACE,KAAK,EAAE,gCAAgC;YACvC,EAAE,EAAE,aAAa,EAAE;YACnB,GAAG,EAAE,iCAAiC;SACvC;KACF,CAAC;IAEF,MAAM,CAAC,IAAI,CAAC,kEAAkE,CAAC,CAAC;IAChF,IAAI,KAAK,GAAG,IAAI,CAAC;IACjB,KAAK,MAAM,CAAC,IAAI,MAAM,EAAE,CAAC;QACvB,IAAI,CAAC,CAAC,EAAE,EAAE,CAAC;YACT,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;QAC1B,CAAC;aAAM,CAAC;YACN,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,KAAK,aAAa,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC;YAC7C,KAAK,GAAG,KAAK,CAAC;QAChB,CAAC;IACH,CAAC;IACD,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAChB,IAAI,KAAK,EAAE,CAAC;QACV,MAAM,CAAC,OAAO,CAAC,yDAAyD,CAAC,CAAC;IAC5E,CAAC;SAAM,CAAC;QACN,MAAM,CAAC,IAAI,CACT,qFAAqF,CACtF,CAAC;QACF,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;IACvB,CAAC;AACH,CAAC,CAAC,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"login.d.ts","sourceRoot":"","sources":["../../src/commands/login.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"login.d.ts","sourceRoot":"","sources":["../../src/commands/login.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AA2CpC,eAAO,MAAM,YAAY,SAuBrB,CAAC;AAEL;;;GAGG;AACH,wBAAsB,cAAc,CAAC,OAAO,GAAE,MAAiB,sDAW9D"}
|
package/dist/commands/login.js
CHANGED
|
@@ -41,6 +41,7 @@ const oauth_server_1 = require("../auth/oauth-server");
|
|
|
41
41
|
const installer_1 = require("../skills/installer");
|
|
42
42
|
const master_skill_1 = require("../skills/master-skill");
|
|
43
43
|
const claude_1 = require("../agents/claude");
|
|
44
|
+
const claude_mcp_1 = require("../agents/claude-mcp");
|
|
44
45
|
const detect_1 = require("../agents/detect");
|
|
45
46
|
const logger = __importStar(require("../utils/logger"));
|
|
46
47
|
const config_1 = require("../config");
|
|
@@ -63,6 +64,20 @@ function refreshEntrySkillsOnLogin() {
|
|
|
63
64
|
if ((0, detect_1.isAgentInstalled)('claude'))
|
|
64
65
|
(0, claude_1.configureClaude)();
|
|
65
66
|
}
|
|
67
|
+
/**
|
|
68
|
+
* Re-point the `gooseworks` MCP registration at the backend we just logged into
|
|
69
|
+
* (from `creds.mcp_server_url`). `install`/`update` already do this, but plain
|
|
70
|
+
* `login` didn't — so switching backends (e.g. prod → local dev) left the MCP
|
|
71
|
+
* tools pointed at the OLD backend even though the CLI creds were correct. That
|
|
72
|
+
* mismatch reads as "project not found" / wrong org on every `mcp__gooseworks__*`
|
|
73
|
+
* call, while `doctor` (creds-only) still passes — a confusing trap.
|
|
74
|
+
*/
|
|
75
|
+
function syncMcpRegistration() {
|
|
76
|
+
if ((0, claude_mcp_1.configureClaudeMcp)()) {
|
|
77
|
+
const creds = (0, credentials_1.getCredentials)();
|
|
78
|
+
logger.info(`Synced the gooseworks MCP → ${creds?.mcp_server_url ?? 'the configured server'}`);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
66
81
|
exports.loginCommand = new commander_1.Command('login')
|
|
67
82
|
.description('Sign in to GooseWorks with Google')
|
|
68
83
|
.option('--api-base <url>', 'API base URL', config_1.API_BASE)
|
|
@@ -71,6 +86,7 @@ exports.loginCommand = new commander_1.Command('login')
|
|
|
71
86
|
if (existing) {
|
|
72
87
|
logger.success(`Already logged in as ${existing.email}`);
|
|
73
88
|
refreshEntrySkillsOnLogin();
|
|
89
|
+
syncMcpRegistration();
|
|
74
90
|
logger.info('Run "gooseworks logout" first to switch accounts.');
|
|
75
91
|
return;
|
|
76
92
|
}
|
|
@@ -78,6 +94,7 @@ exports.loginCommand = new commander_1.Command('login')
|
|
|
78
94
|
const result = await (0, oauth_server_1.runOAuthFlow)(opts.apiBase);
|
|
79
95
|
logger.success(`Logged in as ${result.email}`);
|
|
80
96
|
refreshEntrySkillsOnLogin();
|
|
97
|
+
syncMcpRegistration();
|
|
81
98
|
}
|
|
82
99
|
catch (err) {
|
|
83
100
|
const message = err instanceof Error ? err.message : 'Login failed';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"login.js","sourceRoot":"","sources":["../../src/commands/login.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"login.js","sourceRoot":"","sources":["../../src/commands/login.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"logout.d.ts","sourceRoot":"","sources":["../../src/commands/logout.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"logout.d.ts","sourceRoot":"","sources":["../../src/commands/logout.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAKpC,eAAO,MAAM,aAAa,SAgBtB,CAAC"}
|
package/dist/commands/logout.js
CHANGED
|
@@ -36,6 +36,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
36
36
|
exports.logoutCommand = void 0;
|
|
37
37
|
const commander_1 = require("commander");
|
|
38
38
|
const credentials_1 = require("../auth/credentials");
|
|
39
|
+
const claude_mcp_1 = require("../agents/claude-mcp");
|
|
39
40
|
const logger = __importStar(require("../utils/logger"));
|
|
40
41
|
exports.logoutCommand = new commander_1.Command('logout')
|
|
41
42
|
.description('Sign out and clear saved credentials')
|
|
@@ -46,6 +47,11 @@ exports.logoutCommand = new commander_1.Command('logout')
|
|
|
46
47
|
return;
|
|
47
48
|
}
|
|
48
49
|
(0, credentials_1.clearCredentials)();
|
|
49
|
-
|
|
50
|
+
// Also drop the `gooseworks` MCP registration from ~/.claude.json. Otherwise
|
|
51
|
+
// it lingers pointing at the logged-out backend with a now-dead token — the
|
|
52
|
+
// classic "project not found" / wrong-org trap when you later log into a
|
|
53
|
+
// different backend (e.g. local dev) without re-registering.
|
|
54
|
+
(0, claude_mcp_1.removeClaudeMcp)();
|
|
55
|
+
logger.success(`Logged out (was ${existing.email}) — cleared credentials + MCP registration`);
|
|
50
56
|
});
|
|
51
57
|
//# sourceMappingURL=logout.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"logout.js","sourceRoot":"","sources":["../../src/commands/logout.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,yCAAoC;AACpC,qDAAuE;AACvE,wDAA0C;AAE7B,QAAA,aAAa,GAAG,IAAI,mBAAO,CAAC,QAAQ,CAAC;KAC/C,WAAW,CAAC,sCAAsC,CAAC;KACnD,MAAM,CAAC,KAAK,IAAI,EAAE;IACjB,MAAM,QAAQ,GAAG,IAAA,4BAAc,GAAE,CAAC;IAClC,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,MAAM,CAAC,IAAI,CAAC,0BAA0B,CAAC,CAAC;QACxC,OAAO;IACT,CAAC;IAED,IAAA,8BAAgB,GAAE,CAAC;IACnB,MAAM,CAAC,OAAO,CAAC,mBAAmB,QAAQ,CAAC,KAAK,
|
|
1
|
+
{"version":3,"file":"logout.js","sourceRoot":"","sources":["../../src/commands/logout.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,yCAAoC;AACpC,qDAAuE;AACvE,qDAAuD;AACvD,wDAA0C;AAE7B,QAAA,aAAa,GAAG,IAAI,mBAAO,CAAC,QAAQ,CAAC;KAC/C,WAAW,CAAC,sCAAsC,CAAC;KACnD,MAAM,CAAC,KAAK,IAAI,EAAE;IACjB,MAAM,QAAQ,GAAG,IAAA,4BAAc,GAAE,CAAC;IAClC,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,MAAM,CAAC,IAAI,CAAC,0BAA0B,CAAC,CAAC;QACxC,OAAO;IACT,CAAC;IAED,IAAA,8BAAgB,GAAE,CAAC;IACnB,6EAA6E;IAC7E,4EAA4E;IAC5E,yEAAyE;IACzE,6DAA6D;IAC7D,IAAA,4BAAe,GAAE,CAAC;IAClB,MAAM,CAAC,OAAO,CAAC,mBAAmB,QAAQ,CAAC,KAAK,4CAA4C,CAAC,CAAC;AAChG,CAAC,CAAC,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -14,6 +14,7 @@ const call_1 = require("./commands/call");
|
|
|
14
14
|
const orthogonal_1 = require("./commands/orthogonal");
|
|
15
15
|
const styles_1 = require("./commands/styles");
|
|
16
16
|
const formats_1 = require("./commands/formats");
|
|
17
|
+
const doctor_1 = require("./commands/doctor");
|
|
17
18
|
const version_1 = require("./version");
|
|
18
19
|
const program = new commander_1.Command();
|
|
19
20
|
program
|
|
@@ -32,5 +33,6 @@ program.addCommand(call_1.callCommand);
|
|
|
32
33
|
program.addCommand(orthogonal_1.orthogonalCommand);
|
|
33
34
|
program.addCommand(styles_1.stylesCommand);
|
|
34
35
|
program.addCommand(formats_1.formatsCommand);
|
|
36
|
+
program.addCommand(doctor_1.doctorCommand);
|
|
35
37
|
program.parse();
|
|
36
38
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AACA,yCAAoC;AACpC,gDAAoD;AACpD,4CAAgD;AAChD,8CAAkD;AAClD,8CAAkD;AAClD,gDAAoD;AACpD,8CAAkD;AAClD,4CAAgD;AAChD,wCAA4C;AAC5C,0CAA8C;AAC9C,sDAA0D;AAC1D,8CAAkD;AAClD,gDAAoD;AACpD,uCAAuC;AAEvC,MAAM,OAAO,GAAG,IAAI,mBAAO,EAAE,CAAC;AAC9B,OAAO;KACJ,IAAI,CAAC,YAAY,CAAC;KAClB,WAAW,CAAC,yDAAyD,CAAC;KACtE,OAAO,CAAC,IAAA,oBAAU,GAAE,CAAC,CAAC;AAEzB,OAAO,CAAC,UAAU,CAAC,wBAAc,CAAC,CAAC;AACnC,OAAO,CAAC,UAAU,CAAC,oBAAY,CAAC,CAAC;AACjC,OAAO,CAAC,UAAU,CAAC,sBAAa,CAAC,CAAC;AAClC,OAAO,CAAC,UAAU,CAAC,sBAAa,CAAC,CAAC;AAClC,OAAO,CAAC,UAAU,CAAC,wBAAc,CAAC,CAAC;AACnC,OAAO,CAAC,UAAU,CAAC,sBAAa,CAAC,CAAC;AAClC,OAAO,CAAC,UAAU,CAAC,oBAAY,CAAC,CAAC;AACjC,OAAO,CAAC,UAAU,CAAC,gBAAU,CAAC,CAAC;AAC/B,OAAO,CAAC,UAAU,CAAC,kBAAW,CAAC,CAAC;AAChC,OAAO,CAAC,UAAU,CAAC,8BAAiB,CAAC,CAAC;AACtC,OAAO,CAAC,UAAU,CAAC,sBAAa,CAAC,CAAC;AAClC,OAAO,CAAC,UAAU,CAAC,wBAAc,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AACA,yCAAoC;AACpC,gDAAoD;AACpD,4CAAgD;AAChD,8CAAkD;AAClD,8CAAkD;AAClD,gDAAoD;AACpD,8CAAkD;AAClD,4CAAgD;AAChD,wCAA4C;AAC5C,0CAA8C;AAC9C,sDAA0D;AAC1D,8CAAkD;AAClD,gDAAoD;AACpD,8CAAkD;AAClD,uCAAuC;AAEvC,MAAM,OAAO,GAAG,IAAI,mBAAO,EAAE,CAAC;AAC9B,OAAO;KACJ,IAAI,CAAC,YAAY,CAAC;KAClB,WAAW,CAAC,yDAAyD,CAAC;KACtE,OAAO,CAAC,IAAA,oBAAU,GAAE,CAAC,CAAC;AAEzB,OAAO,CAAC,UAAU,CAAC,wBAAc,CAAC,CAAC;AACnC,OAAO,CAAC,UAAU,CAAC,oBAAY,CAAC,CAAC;AACjC,OAAO,CAAC,UAAU,CAAC,sBAAa,CAAC,CAAC;AAClC,OAAO,CAAC,UAAU,CAAC,sBAAa,CAAC,CAAC;AAClC,OAAO,CAAC,UAAU,CAAC,wBAAc,CAAC,CAAC;AACnC,OAAO,CAAC,UAAU,CAAC,sBAAa,CAAC,CAAC;AAClC,OAAO,CAAC,UAAU,CAAC,oBAAY,CAAC,CAAC;AACjC,OAAO,CAAC,UAAU,CAAC,gBAAU,CAAC,CAAC;AAC/B,OAAO,CAAC,UAAU,CAAC,kBAAW,CAAC,CAAC;AAChC,OAAO,CAAC,UAAU,CAAC,8BAAiB,CAAC,CAAC;AACtC,OAAO,CAAC,UAAU,CAAC,sBAAa,CAAC,CAAC;AAClC,OAAO,CAAC,UAAU,CAAC,wBAAc,CAAC,CAAC;AACnC,OAAO,CAAC,UAAU,CAAC,sBAAa,CAAC,CAAC;AAElC,OAAO,CAAC,KAAK,EAAE,CAAC"}
|
|
@@ -11,7 +11,9 @@
|
|
|
11
11
|
* Sibling domain skills NOT vendored here (fetched live from goose-skills):
|
|
12
12
|
* - `goose-graphics` — charts/slides/infographics/branded visuals. Installed via
|
|
13
13
|
* `gooseworks install --with goose-graphics` or fetched on demand.
|
|
14
|
-
* - `goose-video` — ad
|
|
14
|
+
* - `goose-video` — video ad remix: fetches the per-format recipe by slug,
|
|
15
|
+
* renders LOCALLY (Playwright + ffmpeg + media proxies), mirrors a script for
|
|
16
|
+
* in-app review, saves the MP4 back over MCP (getGooseVideoSkillContent).
|
|
15
17
|
*
|
|
16
18
|
* Recipe skills (remix-graphic-ad-from-reference, brand-research, meta-ads-analyzer,
|
|
17
19
|
* …) are NOT vendored here — they live in goose-skills and are fetched live on
|
|
@@ -50,4 +52,17 @@ export declare function getMasterSkillContent(): string;
|
|
|
50
52
|
* ad, research a brand for ads, or analyze ad performance.
|
|
51
53
|
*/
|
|
52
54
|
export declare function getGooseAdsSkillContent(): string;
|
|
55
|
+
/**
|
|
56
|
+
* Returns the goose-video entry SKILL.md content (the `goose-video` entry skill).
|
|
57
|
+
*
|
|
58
|
+
* Unlike `goose-ads` (static images, generated 100% server-side via the remix
|
|
59
|
+
* batch tools), VIDEO ads render LOCALLY in the user's own Claude Code: the app
|
|
60
|
+
* pre-creates the project and hands the user a paste prompt; this skill fetches
|
|
61
|
+
* the per-format recipe by slug from goose-skills, renders on the user's machine
|
|
62
|
+
* (Playwright + ffmpeg + the GooseWorks media proxies), mirrors the script for a
|
|
63
|
+
* free in-app review, then saves the finished MP4 back over MCP. The app is the
|
|
64
|
+
* viewer + review surface. The `gooseworks` parent router hands video here; Claude
|
|
65
|
+
* also loads it by description.
|
|
66
|
+
*/
|
|
67
|
+
export declare function getGooseVideoSkillContent(): string;
|
|
53
68
|
//# sourceMappingURL=master-skill.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"master-skill.d.ts","sourceRoot":"","sources":["../../src/skills/master-skill.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"master-skill.d.ts","sourceRoot":"","sources":["../../src/skills/master-skill.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,WAAW,UAAU;IACzB,qEAAqE;IACrE,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,oDAAoD;AACpD,wBAAgB,cAAc,IAAI,UAAU,EAAE,CAM7C;AAED;;;;;;;;GAQG;AACH,wBAAgB,qBAAqB,IAAI,MAAM,CA8K9C;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,uBAAuB,IAAI,MAAM,CAsLhD;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,yBAAyB,IAAI,MAAM,CA+MlD"}
|
|
@@ -3,11 +3,13 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.getEntrySkills = getEntrySkills;
|
|
4
4
|
exports.getMasterSkillContent = getMasterSkillContent;
|
|
5
5
|
exports.getGooseAdsSkillContent = getGooseAdsSkillContent;
|
|
6
|
+
exports.getGooseVideoSkillContent = getGooseVideoSkillContent;
|
|
6
7
|
/** Every entry skill the CLI vendors + installs. */
|
|
7
8
|
function getEntrySkills() {
|
|
8
9
|
return [
|
|
9
10
|
{ name: 'gooseworks', content: getMasterSkillContent() },
|
|
10
11
|
{ name: 'goose-ads', content: getGooseAdsSkillContent() },
|
|
12
|
+
{ name: 'goose-video', content: getGooseVideoSkillContent() },
|
|
11
13
|
];
|
|
12
14
|
}
|
|
13
15
|
/**
|
|
@@ -28,7 +30,8 @@ description: >
|
|
|
28
30
|
Find people, emails, and company info. Enrich contacts and companies.
|
|
29
31
|
GTM tasks: lead generation, prospect research, ICP identification, competitor analysis, outbound list building.
|
|
30
32
|
LinkedIn scraping: extract post engagers, commenters, profile data, and job postings.
|
|
31
|
-
|
|
33
|
+
Reach for it when you need data at scale, sources behind auth, or a specific provider — not as
|
|
34
|
+
a replacement for your built-in web search/fetch on quick, one-off lookups.
|
|
32
35
|
category: general
|
|
33
36
|
version: 1.0.0
|
|
34
37
|
author: GooseWorks
|
|
@@ -49,7 +52,7 @@ Before anything else, check whether the request belongs to a specialized domain.
|
|
|
49
52
|
| --- | --- | --- |
|
|
50
53
|
| Remix/make an ad, research a brand for ads, OR analyze ad performance — Meta/Google ad campaigns, creative fatigue, CAC/lead quality, competitor ad intel, ad angles & hooks | **\`goose-ads\`** | Installed locally as an entry skill. Just use it. If unavailable, run \`gooseworks install --claude\`. |
|
|
51
54
|
| Charts, infographics, slides, social graphics, branded visual designs from a style/format | **\`goose-graphics\`** | If installed locally, use it. Otherwise \`gooseworks fetch goose-graphics\` (or \`gooseworks install --claude --with goose-graphics\`). |
|
|
52
|
-
|
|
|
55
|
+
| Make a **video** ad — remix a video ad template (e.g. iMessage chat-reveal), or "make the video for project <id>" | **\`goose-video\`** | Installed locally as an entry skill. Just use it. If unavailable, run \`gooseworks install --claude\`. |
|
|
53
56
|
| Anything else — scraping, research, lead gen, enrichment, any data lookup | (stay here) | Follow "How to Use" below. |
|
|
54
57
|
|
|
55
58
|
Examples — all of these route to \`goose-ads\`, not the data flow: "remix this ad with project id 123", "make an ad for my product", "research my brand", "why is my Meta campaign underperforming", "which creatives should I cut".
|
|
@@ -160,6 +163,28 @@ gooseworks call apify acts/parseforge~reddit-posts-scraper/runs --body='{"subred
|
|
|
160
163
|
4. Organize outputs in subfolders by task type when it makes sense (e.g. \`~/Gooseworks/reddit-scrapes/\`, \`~/Gooseworks/research/\`)
|
|
161
164
|
- **Never overwrite existing files** without asking. If a file already exists, append a timestamp or ask the user
|
|
162
165
|
|
|
166
|
+
## External Endpoints
|
|
167
|
+
|
|
168
|
+
The \`gooseworks\` CLI sends authenticated requests (Bearer \`GOOSEWORKS_API_KEY\`) to:
|
|
169
|
+
|
|
170
|
+
| Endpoint | Method | Wrapped by |
|
|
171
|
+
|----------|--------|------------|
|
|
172
|
+
| \`$GOOSEWORKS_API_BASE/api/skills/search\` | POST | \`gooseworks search\` |
|
|
173
|
+
| \`$GOOSEWORKS_API_BASE/api/skills/catalog/:slug\` | GET | \`gooseworks fetch\` |
|
|
174
|
+
| \`$GOOSEWORKS_API_BASE/v1/credits\` | GET | \`gooseworks credits\` |
|
|
175
|
+
| \`$GOOSEWORKS_API_BASE/v1/proxy/orthogonal/search\` | POST | \`gooseworks orthogonal find\` |
|
|
176
|
+
| \`$GOOSEWORKS_API_BASE/v1/proxy/orthogonal/details\` | POST | \`gooseworks orthogonal describe\` |
|
|
177
|
+
| \`$GOOSEWORKS_API_BASE/v1/proxy/orthogonal/run\` | POST | \`gooseworks call\` (orthogonal-routed providers) |
|
|
178
|
+
| \`$GOOSEWORKS_API_BASE/v1/proxy/{apify,apollo,crustdata}/*\` | Various | \`gooseworks call\` (direct-proxy providers) |
|
|
179
|
+
|
|
180
|
+
## Security & Privacy
|
|
181
|
+
|
|
182
|
+
- All API calls are authenticated via Bearer token stored locally in \`~/.gooseworks/credentials.json\` (file mode 0600)
|
|
183
|
+
- No credentials are hardcoded or sent to third parties
|
|
184
|
+
- API keys for external services (Apify, Apollo, etc.) are managed server-side — your token never touches them
|
|
185
|
+
- Scripts run locally on your machine; only API requests go through GooseWorks servers. Skill scripts are open source (github.com/gooseworks-ai/goose-skills) — read or pin them before running
|
|
186
|
+
- Credit usage is tracked per-call and visible via \`gooseworks credits\`
|
|
187
|
+
|
|
163
188
|
## Rules
|
|
164
189
|
|
|
165
190
|
1. **Consider a GooseWorks skill when it fits the task** — scraping, research, lead gen, enrichment, especially at scale, behind auth, or from a specific source. For a quick lookup your built-in tools are fine; use your judgement and pick the best tool for the user.
|
|
@@ -369,4 +394,224 @@ run through the \`gooseworks\` CLI (\`gooseworks fetch\` / \`gooseworks call\`),
|
|
|
369
394
|
batch is waiting on research and will start on its own.
|
|
370
395
|
`;
|
|
371
396
|
}
|
|
397
|
+
/**
|
|
398
|
+
* Returns the goose-video entry SKILL.md content (the `goose-video` entry skill).
|
|
399
|
+
*
|
|
400
|
+
* Unlike `goose-ads` (static images, generated 100% server-side via the remix
|
|
401
|
+
* batch tools), VIDEO ads render LOCALLY in the user's own Claude Code: the app
|
|
402
|
+
* pre-creates the project and hands the user a paste prompt; this skill fetches
|
|
403
|
+
* the per-format recipe by slug from goose-skills, renders on the user's machine
|
|
404
|
+
* (Playwright + ffmpeg + the GooseWorks media proxies), mirrors the script for a
|
|
405
|
+
* free in-app review, then saves the finished MP4 back over MCP. The app is the
|
|
406
|
+
* viewer + review surface. The `gooseworks` parent router hands video here; Claude
|
|
407
|
+
* also loads it by description.
|
|
408
|
+
*/
|
|
409
|
+
function getGooseVideoSkillContent() {
|
|
410
|
+
return `---
|
|
411
|
+
name: goose-video
|
|
412
|
+
slug: goose-video
|
|
413
|
+
description: >
|
|
414
|
+
GooseWorks video ads — remix a video ad template (iMessage chat-reveal, more coming) into a
|
|
415
|
+
branded video ad for the user's product. Renders LOCALLY on the user's machine (Playwright +
|
|
416
|
+
ffmpeg + GooseWorks media proxies) and saves the finished MP4 back to the project over MCP.
|
|
417
|
+
Use when the user says "make the video for project <id>", references a video ad project or
|
|
418
|
+
template, or asks to remix a video ad. Unlike goose-ads (static images, generated server-side),
|
|
419
|
+
video renders locally and reports progress + the result back through the gooseworks MCP tools.
|
|
420
|
+
category: ads
|
|
421
|
+
version: 0.1.0
|
|
422
|
+
author: GooseWorks
|
|
423
|
+
tags: [gooseworks, ads, video, remix, imessage, local-render, byoa]
|
|
424
|
+
---
|
|
425
|
+
|
|
426
|
+
# GooseWorks Video Ads — local remix runtime
|
|
427
|
+
|
|
428
|
+
You produce **video** ad creative on the user's OWN machine and sync the result back to the
|
|
429
|
+
GooseWorks app over MCP. This document is the **runtime contract** (auth, credits, the media
|
|
430
|
+
proxies, data I/O, the review gate). A separate **recipe skill** — fetched per format — tells
|
|
431
|
+
you *what to make*; read both, and this doc wins on any conflict about the environment.
|
|
432
|
+
|
|
433
|
+
You run inside the user's own Claude Code session (they pasted an instruction with a project
|
|
434
|
+
id). The app NEVER runs you — it is the viewer + review surface; you are the renderer.
|
|
435
|
+
|
|
436
|
+
## Prerequisite — MCP + a local toolchain (Phase 0 preflight)
|
|
437
|
+
|
|
438
|
+
- The \`mcp__gooseworks__*\` tools are REQUIRED. If they're unavailable, stop and tell the user
|
|
439
|
+
to run \`gooseworks install --claude --mcp\` and restart Claude Code. There is no REST fallback.
|
|
440
|
+
- This is a LOCAL render. Run \`gooseworks doctor\` FIRST — it checks login, the MCP server,
|
|
441
|
+
**ffmpeg** + **ffprobe**, and **Playwright Chromium** in one shot. If it reports any ✗, relay
|
|
442
|
+
the exact fix it prints (e.g. \`brew install ffmpeg\`, \`npx playwright install chromium\`) and
|
|
443
|
+
stop — don't half-render.
|
|
444
|
+
|
|
445
|
+
## Identity, token, credits
|
|
446
|
+
|
|
447
|
+
- Read \`~/.gooseworks/credentials.json\` → \`api_key\` (your agent token), \`api_base\`, \`agent_id\`.
|
|
448
|
+
Never print the token.
|
|
449
|
+
- **CRITICAL — target the org-default Ads agent on EVERY file op.** The app serves project files
|
|
450
|
+
(the render-file route) from the org's DEFAULT agent, but MCP file writes default to your
|
|
451
|
+
token's pinned agent — which can be a DIFFERENT agent, so a render written with the default
|
|
452
|
+
scope is **invisible in the app**. First resolve the Ads agent: \`list_accessible_scopes\` → the
|
|
453
|
+
scope with \`is_org_default: true\` → its \`agent_id\` is \`ADS_AGENT\`. Then pass
|
|
454
|
+
\`target: { type: "agent", agent_id: ADS_AGENT }\` on EVERY \`get_upload_url\` / \`get_download_url\`
|
|
455
|
+
/ \`write_file\` / \`list_directory\` / \`read_file\` — NEVER omit \`target\`.
|
|
456
|
+
- Media generation (FAL / ElevenLabs) is billed to the agent through the GooseWorks proxies.
|
|
457
|
+
\`submit_render { kind: "full" }\` debits **1 ad credit at row creation** — so sequence it LAST
|
|
458
|
+
(render + verify a good MP4 first), and never re-submit on a guess (that double-bills). Call
|
|
459
|
+
\`get_ad_credits\` first; the user can check \`gooseworks credits\`.
|
|
460
|
+
|
|
461
|
+
## Step 1 — resolve the project, source, brand
|
|
462
|
+
|
|
463
|
+
1. \`get_ad_project { project_id }\` → keep \`brand_id\`, \`source_sample_id\`, \`name\`, \`status\`.
|
|
464
|
+
2. \`get_ad_template { template_id: source_sample_id }\` → the source video: \`media_url\`,
|
|
465
|
+
\`recipe\`, \`format\` (e.g. "imessage"), \`extracted_script\`, \`how_to\`, \`remix_spec\`.
|
|
466
|
+
3. Brand gate: \`get_brand_kit { brand_id }\`. If \`researchStatus\` is \`complete\`, REUSE it —
|
|
467
|
+
never re-research. If not, run brand research first (\`gooseworks fetch brand-research\`,
|
|
468
|
+
follow it, then \`finalize_brand_research { brand_id }\`) before continuing.
|
|
469
|
+
|
|
470
|
+
## Step 2 — fetch the recipe + its pack skills for the format
|
|
471
|
+
|
|
472
|
+
The video-ad format skills live in the goose-skills **\`video-ad-formats\`** pack. Map the project's
|
|
473
|
+
\`format\` to its recipe slug:
|
|
474
|
+
|
|
475
|
+
| format | recipe slug | renderer + atoms it drives |
|
|
476
|
+
| --- | --- | --- |
|
|
477
|
+
| \`imessage\` | \`remix-imessage-ad-from-sample\` | create-imessage-video-ad, create-imessage-mockup, stitch-videos-ffmpeg, mix-master, watch |
|
|
478
|
+
| \`chatgpt\` | \`remix-chatgpt-ad-from-sample\` | create-chatgpt-video-ad, create-chatgpt-mockup, render-ios-keyboard, stitch-videos-ffmpeg, watch |
|
|
479
|
+
| \`apple-notes\` | \`remix-apple-notes-ad-from-sample\` | create-apple-notes-video-ad, create-apple-notes-mockup, stitch-videos-ffmpeg, watch |
|
|
480
|
+
|
|
481
|
+
(photo-grid + music-video coming.) Pack skills are fetchable individually by slug but do NOT
|
|
482
|
+
auto-resolve dependencies (no \`dependencySkills\`), so \`gooseworks fetch\` the recipe **and** each
|
|
483
|
+
skill in its row — e.g. for iMessage:
|
|
484
|
+
|
|
485
|
+
\`\`\`bash
|
|
486
|
+
for s in remix-imessage-ad-from-sample create-imessage-video-ad create-imessage-mockup \\
|
|
487
|
+
stitch-videos-ffmpeg mix-master watch; do gooseworks fetch "$s"; done
|
|
488
|
+
\`\`\`
|
|
489
|
+
|
|
490
|
+
Each prints \`{ content, scripts, files }\`. Save each skill's scripts + files under
|
|
491
|
+
\`/tmp/gooseworks-scripts/<slug>/\` and FOLLOW the recipe's SKILL.md — it orchestrates the others.
|
|
492
|
+
The renderer (the \`create-*-mockup\` atom for the format) is a Node package —
|
|
493
|
+
\`npm install\` in its folder so its \`generate.js\` + Playwright resolve, and point the recorder's
|
|
494
|
+
\`NODE_PATH\` at it.
|
|
495
|
+
|
|
496
|
+
## Step 3 — prepare ALL the ingredients, then review ONCE (always, before any paid render)
|
|
497
|
+
|
|
498
|
+
This is a **review-once** flow: prepare every ingredient the video needs, show the whole set to
|
|
499
|
+
the user in the app, get ONE approval, then render. Never render before approval, and don't drip
|
|
500
|
+
ingredients out one at a time.
|
|
501
|
+
|
|
502
|
+
1. **Generate every ingredient the format needs — not just the script.** For an iMessage video
|
|
503
|
+
that's typically: the **script** (the bubble thread), the **image(s)** shown in the conversation
|
|
504
|
+
(one or more), and the **end card**. Richer templates add more (hook frame, background, product
|
|
505
|
+
shots, music bed…). Read the recipe for the exact ingredient list. Generate the visuals NOW
|
|
506
|
+
(media proxies / recipe), and \`get_upload_url\` each preview asset to \`working/review/<name>\`.
|
|
507
|
+
You may ask the user a couple of clarifying questions about the generation first if the recipe
|
|
508
|
+
calls for it (angle, which product, offer/code) — batch them, then prepare everything.
|
|
509
|
+
2. **Mirror the whole ingredient set for review** — \`update_ad_project_script { project_id,
|
|
510
|
+
script_drafts, script }\`. \`script_drafts\` is a structured payload of **container-tagged
|
|
511
|
+
ingredients** so the app renders each piece the right way:
|
|
512
|
+
\`{ format, scenes?, ingredients: [{ container, label, subtitle?, path?, text? }] }\`. Each
|
|
513
|
+
ingredient's \`container\` tells the app HOW to show it:
|
|
514
|
+
- \`image\` (a frame shown in the video), \`endcard\` (the end card), \`avatar\` (a character
|
|
515
|
+
headshot), \`background\` → rendered as an image tile.
|
|
516
|
+
- \`voice\` (a voiceover clip — put the voice NAME in \`subtitle\`), \`music\` (the bed),
|
|
517
|
+
\`audio\` → rendered as an audio player.
|
|
518
|
+
- \`video\` (a clip) → a video player. \`text\` (a copy line like the CTA) → a text tile.
|
|
519
|
+
- \`script\` / \`thread\` / \`note\` / \`conversation\` → the written script (or set \`scenes[]\`
|
|
520
|
+
for the podcast shape, or pass the readable \`script\` string).
|
|
521
|
+
\`path\` = \`working/review/<name>\` (upload the preview asset first via \`get_upload_url\`); \`url\`
|
|
522
|
+
works too. **Label every ingredient** ("Hook image", "End card", "Voiceover", "Background
|
|
523
|
+
music", "HER"). This writes NO render and costs NO credits — it populates the review panel.
|
|
524
|
+
3. **STOP and ask the user to approve the ingredients in THIS Claude Code session.** Do not render
|
|
525
|
+
until they say go. If they want changes, regenerate the affected ingredient, call
|
|
526
|
+
\`update_ad_project_script\` again, and re-ask. Only AFTER approval do Step 4.
|
|
527
|
+
|
|
528
|
+
## Step 4 — render locally, report stages, publish
|
|
529
|
+
|
|
530
|
+
1. Render per the recipe (Playwright record → ffmpeg stitch → \`mix-master\` audio). Generate any
|
|
531
|
+
hook / background / end-card assets through the media proxies (below).
|
|
532
|
+
2. Open the row LAST: \`submit_render { project_id, kind: "full" }\` → keep \`render_id\`, then
|
|
533
|
+
\`update_render_status { render_id, status: "running" }\`. The render row tracks status only
|
|
534
|
+
(queued / running / complete / failed) — narrate fine-grained progress with
|
|
535
|
+
\`append_project_message\` instead.
|
|
536
|
+
3. QC by watching: run the \`watch\` skill on the master — verify bubble/beat order + SFX, that
|
|
537
|
+
the brand's product (not the source's) is shown, the end card has the real wordmark + code,
|
|
538
|
+
and the duration is within ~20% of the source.
|
|
539
|
+
4. Publish: \`get_upload_url { target: { type: "agent", agent_id: ADS_AGENT } }\` → PUT the master
|
|
540
|
+
to \`working/final.mp4\` and a poster to \`working/final-thumb.jpg\`. **Always target ADS_AGENT**
|
|
541
|
+
(see Identity — a file on your token's own agent is invisible to the app). Verify servable:
|
|
542
|
+
\`get_download_url { target: ADS_AGENT, path: "working/final.mp4" }\` must return a non-empty URL.
|
|
543
|
+
Then \`update_render_status { render_id, status: "complete", output_url, thumbnail_url }\` where
|
|
544
|
+
**output_url MUST be the durable render-file URL**
|
|
545
|
+
\`/api/ads/projects/<project_id>/render-file?path=working/final.mp4\` (the app re-presigns it on
|
|
546
|
+
every view) — NEVER a raw proxy/CDN URL (those expire). Same for \`thumbnail_url\`.
|
|
547
|
+
5. \`set_final_render { project_id, render_id }\` to pin it, then return the \`app_url\` +
|
|
548
|
+
\`brand_url\` (from the project/links) verbatim. Never end on just "done" or a file path.
|
|
549
|
+
|
|
550
|
+
Narrate each long step in one line via \`append_project_message { project_id, role: "agent",
|
|
551
|
+
content }\` — never sit silent on a queue > 90s.
|
|
552
|
+
|
|
553
|
+
## Media generation — the GooseWorks proxies (queue loop)
|
|
554
|
+
|
|
555
|
+
Media APIs go through GooseWorks proxies with your agent token; do NOT use an SDK's default host
|
|
556
|
+
(your token isn't a FAL/ElevenLabs token → 401). Base = \`<api_base>/api/internal/<proxy>\`; pass
|
|
557
|
+
\`?token=<api_key>&agent_id=<agent_id>\` (agent_id bills the Ads agent). FAL = \`fal-proxy\` (+
|
|
558
|
+
\`fal-storage-proxy\` to host a local image and get a CDN URL); ElevenLabs = \`elevenlabs-proxy\`
|
|
559
|
+
(VO / music bed).
|
|
560
|
+
|
|
561
|
+
**FAL queue gotcha** (#1 waste of generations): submit returns \`status_url\`/\`response_url\` on
|
|
562
|
+
\`queue.fal.run\` (the real host, not the proxy). Polling those 401s forever — rewrite their host
|
|
563
|
+
to the proxy base (keep the path), re-add \`?token=&agent_id=\`. Only the final \`*.fal.media\`
|
|
564
|
+
image is a real public URL. Helper:
|
|
565
|
+
|
|
566
|
+
\`\`\`python
|
|
567
|
+
import json, os, pathlib, time, requests
|
|
568
|
+
from urllib.parse import urlparse
|
|
569
|
+
|
|
570
|
+
def _cfg():
|
|
571
|
+
c = json.loads(pathlib.Path(os.path.expanduser("~/.gooseworks/credentials.json")).read_text())
|
|
572
|
+
return c["api_base"].rstrip("/"), c["api_key"], c.get("agent_id")
|
|
573
|
+
|
|
574
|
+
def _params(tok, agent):
|
|
575
|
+
p = {"token": tok}
|
|
576
|
+
if agent: p["agent_id"] = agent
|
|
577
|
+
return p
|
|
578
|
+
|
|
579
|
+
def fal_generate(model_path, payload, timeout_s=180, poll_s=3):
|
|
580
|
+
"""model_path e.g. 'fal-ai/nano-banana-2/edit' (the recipe names the model).
|
|
581
|
+
Returns the result image URL (a public *.fal.media CDN URL)."""
|
|
582
|
+
api_base, tok, agent = _cfg()
|
|
583
|
+
base = api_base + "/api/internal/fal-proxy"
|
|
584
|
+
sub = requests.post(f"{base}/{model_path}", params=_params(tok, agent), json=payload).json()
|
|
585
|
+
to_proxy = lambda u: base + urlparse(u).path
|
|
586
|
+
status_url, response_url = to_proxy(sub["status_url"]), to_proxy(sub["response_url"])
|
|
587
|
+
deadline = time.time() + timeout_s
|
|
588
|
+
while time.time() < deadline:
|
|
589
|
+
st = requests.get(status_url, params=_params(tok, agent)).json()
|
|
590
|
+
if st.get("status") == "COMPLETED":
|
|
591
|
+
return requests.get(response_url, params=_params(tok, agent)).json()["images"][0]["url"]
|
|
592
|
+
if st.get("status") in ("FAILED", "ERROR"):
|
|
593
|
+
raise RuntimeError(f"FAL failed: {st}")
|
|
594
|
+
time.sleep(poll_s)
|
|
595
|
+
raise TimeoutError("FAL polling exceeded timeout")
|
|
596
|
+
\`\`\`
|
|
597
|
+
|
|
598
|
+
ElevenLabs (VO / music) is the same shape against \`<api_base>/api/internal/elevenlabs-proxy\`
|
|
599
|
+
with \`?token=&agent_id=\`. Feed FAL a local image by storing it (\`get_upload_url\`) and passing its
|
|
600
|
+
\`get_download_url\` presigned URL as an \`image_urls\` entry, or POST the bytes to \`fal-storage-proxy\`.
|
|
601
|
+
|
|
602
|
+
## Rules
|
|
603
|
+
|
|
604
|
+
- **MCP + ffmpeg + Playwright required** — run \`gooseworks doctor\` in Phase 0; stop with the
|
|
605
|
+
exact fix it prints if anything is ✗.
|
|
606
|
+
- **Prepare ALL ingredients first** (script + every visual: image(s) + end card + whatever else
|
|
607
|
+
the template needs), mirror the whole set with \`update_ad_project_script\`, and get the user's
|
|
608
|
+
approval in-session BEFORE rendering — always (review-once).
|
|
609
|
+
- **submit_render LAST**; \`output_url\` = the durable render-file URL, never a CDN URL.
|
|
610
|
+
- **Verify a real, non-empty MP4** (watch it) before marking the render complete.
|
|
611
|
+
- **Reuse the brand** when its research is complete; never re-research.
|
|
612
|
+
- On a hard error (auth/quota/model/timeout) set the render \`failed\` with a short
|
|
613
|
+
\`error_message\` and stop — don't ship the source unchanged.
|
|
614
|
+
- Always end a successful run with \`app_url\` + \`brand_url\`, verbatim.
|
|
615
|
+
`;
|
|
616
|
+
}
|
|
372
617
|
//# sourceMappingURL=master-skill.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"master-skill.js","sourceRoot":"","sources":["../../src/skills/master-skill.ts"],"names":[],"mappings":";;
|
|
1
|
+
{"version":3,"file":"master-skill.js","sourceRoot":"","sources":["../../src/skills/master-skill.ts"],"names":[],"mappings":";;AA4BA,wCAMC;AAWD,sDA8KC;AAiBD,0DAsLC;AAcD,8DA+MC;AApmBD,oDAAoD;AACpD,SAAgB,cAAc;IAC5B,OAAO;QACL,EAAE,IAAI,EAAE,YAAY,EAAE,OAAO,EAAE,qBAAqB,EAAE,EAAE;QACxD,EAAE,IAAI,EAAE,WAAW,EAAE,OAAO,EAAE,uBAAuB,EAAE,EAAE;QACzD,EAAE,IAAI,EAAE,aAAa,EAAE,OAAO,EAAE,yBAAyB,EAAE,EAAE;KAC9D,CAAC;AACJ,CAAC;AAED;;;;;;;;GAQG;AACH,SAAgB,qBAAqB;IACnC,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA4KR,CAAC;AACF,CAAC;AAED;;;;;;;;;;;;;;GAcG;AACH,SAAgB,uBAAuB;IACrC,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAoLR,CAAC;AACF,CAAC;AAED;;;;;;;;;;;GAWG;AACH,SAAgB,yBAAyB;IACvC,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA6MR,CAAC;AACF,CAAC"}
|
package/package.json
CHANGED
|
@@ -5,7 +5,8 @@ description: >
|
|
|
5
5
|
Find people, emails, and company info. Enrich contacts and companies.
|
|
6
6
|
GTM tasks: lead generation, prospect research, ICP identification, competitor analysis, outbound list building.
|
|
7
7
|
LinkedIn scraping: extract post engagers, commenters, profile data, and job postings.
|
|
8
|
-
|
|
8
|
+
Reach for it when you need data at scale, sources behind auth, or a specific provider — not as
|
|
9
|
+
a replacement for your built-in web search/fetch on quick, one-off lookups.
|
|
9
10
|
version: 1.0.0
|
|
10
11
|
author: GooseWorks
|
|
11
12
|
tags: [gooseworks, data, scraping, search, reddit, twitter, linkedin, email, people, research, gtm, leads, prospecting]
|
|
@@ -159,10 +160,10 @@ The `gooseworks` CLI sends authenticated requests (Bearer `GOOSEWORKS_API_KEY`)
|
|
|
159
160
|
|
|
160
161
|
## Security & Privacy
|
|
161
162
|
|
|
162
|
-
- All API calls are authenticated via Bearer token stored locally in `~/.gooseworks/credentials.json`
|
|
163
|
+
- All API calls are authenticated via Bearer token stored locally in `~/.gooseworks/credentials.json` (file mode 0600)
|
|
163
164
|
- No credentials are hardcoded or sent to third parties
|
|
164
165
|
- API keys for external services (Apify, Apollo, etc.) are managed server-side — your token never touches them
|
|
165
|
-
- Scripts run locally on your machine; only API requests go through GooseWorks servers
|
|
166
|
+
- Scripts run locally on your machine; only API requests go through GooseWorks servers. Skill scripts are open source (github.com/gooseworks-ai/goose-skills) — read or pin them before running
|
|
166
167
|
- Credit usage is tracked per-call and visible via `gooseworks credits`
|
|
167
168
|
|
|
168
169
|
## Rules
|