gooseworks 0.3.8 → 0.3.9
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/agents/claude.d.ts.map +1 -1
- package/dist/agents/claude.js +4 -58
- package/dist/agents/claude.js.map +1 -1
- package/dist/agents/codex.d.ts.map +1 -1
- package/dist/agents/codex.js +4 -58
- package/dist/agents/codex.js.map +1 -1
- package/dist/agents/skill-links.d.ts +18 -0
- package/dist/agents/skill-links.d.ts.map +1 -0
- package/dist/agents/skill-links.js +192 -0
- package/dist/agents/skill-links.js.map +1 -0
- package/dist/commands/install.d.ts.map +1 -1
- package/dist/commands/install.js +16 -2
- package/dist/commands/install.js.map +1 -1
- package/dist/skills/master-skill.d.ts.map +1 -1
- package/dist/skills/master-skill.js +104 -17
- package/dist/skills/master-skill.js.map +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"claude.d.ts","sourceRoot":"","sources":["../../src/agents/claude.ts"],"names":[],"mappings":"AAQA,wBAAgB,kBAAkB,IAAI,MAAM,CAE3C;AAED,wBAAgB,eAAe,IAAI,MAAM,
|
|
1
|
+
{"version":3,"file":"claude.d.ts","sourceRoot":"","sources":["../../src/agents/claude.ts"],"names":[],"mappings":"AAQA,wBAAgB,kBAAkB,IAAI,MAAM,CAE3C;AAED,wBAAgB,eAAe,IAAI,MAAM,CAOxC;AAED,wBAAgB,YAAY,IAAI,IAAI,CAEnC"}
|
package/dist/agents/claude.js
CHANGED
|
@@ -40,7 +40,7 @@ const fs = __importStar(require("fs"));
|
|
|
40
40
|
const path = __importStar(require("path"));
|
|
41
41
|
const os = __importStar(require("os"));
|
|
42
42
|
const installer_1 = require("../skills/installer");
|
|
43
|
-
const
|
|
43
|
+
const skill_links_1 = require("./skill-links");
|
|
44
44
|
const CLAUDE_SKILLS_DIR = path.join(os.homedir(), '.claude', 'skills');
|
|
45
45
|
function getClaudeSkillsDir() {
|
|
46
46
|
return CLAUDE_SKILLS_DIR;
|
|
@@ -50,64 +50,10 @@ function configureClaude() {
|
|
|
50
50
|
if (!fs.existsSync(skillsBase)) {
|
|
51
51
|
return 0;
|
|
52
52
|
}
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
try {
|
|
56
|
-
const existing = fs.readdirSync(CLAUDE_SKILLS_DIR);
|
|
57
|
-
for (const entry of existing) {
|
|
58
|
-
if (!(0, names_1.isManagedGooseworksSkill)(entry))
|
|
59
|
-
continue;
|
|
60
|
-
const target = path.join(CLAUDE_SKILLS_DIR, entry);
|
|
61
|
-
try {
|
|
62
|
-
const stat = fs.lstatSync(target);
|
|
63
|
-
if (stat.isSymbolicLink()) {
|
|
64
|
-
fs.unlinkSync(target);
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
catch {
|
|
68
|
-
// Ignore
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
catch {
|
|
73
|
-
// Directory might not exist yet
|
|
74
|
-
}
|
|
75
|
-
// Symlink only what's currently in ~/.agents/skills/
|
|
76
|
-
const skillDirs = fs.readdirSync(skillsBase)
|
|
77
|
-
.filter(names_1.isManagedGooseworksSkill);
|
|
78
|
-
let linked = 0;
|
|
79
|
-
for (const skillDir of skillDirs) {
|
|
80
|
-
const source = path.join(skillsBase, skillDir);
|
|
81
|
-
const target = path.join(CLAUDE_SKILLS_DIR, skillDir);
|
|
82
|
-
try {
|
|
83
|
-
fs.symlinkSync(source, target, 'dir');
|
|
84
|
-
}
|
|
85
|
-
catch {
|
|
86
|
-
// If it somehow still exists, remove and retry
|
|
87
|
-
fs.rmSync(target, { recursive: true, force: true });
|
|
88
|
-
fs.symlinkSync(source, target, 'dir');
|
|
89
|
-
}
|
|
90
|
-
linked++;
|
|
91
|
-
}
|
|
92
|
-
return linked;
|
|
53
|
+
// Cross-platform, privilege-free, resilient linking (GOOSE-2418).
|
|
54
|
+
return (0, skill_links_1.syncManagedSkillLinks)(skillsBase, CLAUDE_SKILLS_DIR).linked;
|
|
93
55
|
}
|
|
94
56
|
function removeClaude() {
|
|
95
|
-
|
|
96
|
-
return;
|
|
97
|
-
const entries = fs.readdirSync(CLAUDE_SKILLS_DIR);
|
|
98
|
-
for (const entry of entries) {
|
|
99
|
-
if (!(0, names_1.isManagedGooseworksSkill)(entry))
|
|
100
|
-
continue;
|
|
101
|
-
const target = path.join(CLAUDE_SKILLS_DIR, entry);
|
|
102
|
-
try {
|
|
103
|
-
const stat = fs.lstatSync(target);
|
|
104
|
-
if (stat.isSymbolicLink()) {
|
|
105
|
-
fs.unlinkSync(target);
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
catch {
|
|
109
|
-
// Ignore
|
|
110
|
-
}
|
|
111
|
-
}
|
|
57
|
+
(0, skill_links_1.removeManagedSkillLinks)(CLAUDE_SKILLS_DIR);
|
|
112
58
|
}
|
|
113
59
|
//# sourceMappingURL=claude.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"claude.js","sourceRoot":"","sources":["../../src/agents/claude.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAQA,gDAEC;AAED,
|
|
1
|
+
{"version":3,"file":"claude.js","sourceRoot":"","sources":["../../src/agents/claude.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAQA,gDAEC;AAED,0CAOC;AAED,oCAEC;AAvBD,uCAAyB;AACzB,2CAA6B;AAC7B,uCAAyB;AACzB,mDAAwD;AACxD,+CAA+E;AAE/E,MAAM,iBAAiB,GAAG,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,QAAQ,CAAC,CAAC;AAEvE,SAAgB,kBAAkB;IAChC,OAAO,iBAAiB,CAAC;AAC3B,CAAC;AAED,SAAgB,eAAe;IAC7B,MAAM,UAAU,GAAG,IAAA,6BAAiB,GAAE,CAAC;IACvC,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;QAC/B,OAAO,CAAC,CAAC;IACX,CAAC;IACD,kEAAkE;IAClE,OAAO,IAAA,mCAAqB,EAAC,UAAU,EAAE,iBAAiB,CAAC,CAAC,MAAM,CAAC;AACrE,CAAC;AAED,SAAgB,YAAY;IAC1B,IAAA,qCAAuB,EAAC,iBAAiB,CAAC,CAAC;AAC7C,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"codex.d.ts","sourceRoot":"","sources":["../../src/agents/codex.ts"],"names":[],"mappings":"AAUA,wBAAgB,iBAAiB,IAAI,MAAM,CAE1C;AAED,wBAAgB,cAAc,IAAI,MAAM,
|
|
1
|
+
{"version":3,"file":"codex.d.ts","sourceRoot":"","sources":["../../src/agents/codex.ts"],"names":[],"mappings":"AAUA,wBAAgB,iBAAiB,IAAI,MAAM,CAE1C;AAED,wBAAgB,cAAc,IAAI,MAAM,CAOvC;AAED,wBAAgB,WAAW,IAAI,IAAI,CAElC;AAwCD;;;;GAIG;AACH,wBAAgB,iBAAiB,IAAI,OAAO,CAiB3C"}
|
package/dist/agents/codex.js
CHANGED
|
@@ -42,7 +42,7 @@ const path = __importStar(require("path"));
|
|
|
42
42
|
const os = __importStar(require("os"));
|
|
43
43
|
const credentials_1 = require("../auth/credentials");
|
|
44
44
|
const installer_1 = require("../skills/installer");
|
|
45
|
-
const
|
|
45
|
+
const skill_links_1 = require("./skill-links");
|
|
46
46
|
const CODEX_SKILLS_DIR = path.join(os.homedir(), '.codex', 'skills');
|
|
47
47
|
const CODEX_CONFIG_PATH = path.join(os.homedir(), '.codex', 'config.toml');
|
|
48
48
|
function getCodexSkillsDir() {
|
|
@@ -53,65 +53,11 @@ function configureCodex() {
|
|
|
53
53
|
if (!fs.existsSync(skillsBase)) {
|
|
54
54
|
return 0;
|
|
55
55
|
}
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
try {
|
|
59
|
-
const existing = fs.readdirSync(CODEX_SKILLS_DIR);
|
|
60
|
-
for (const entry of existing) {
|
|
61
|
-
if (!(0, names_1.isManagedGooseworksSkill)(entry))
|
|
62
|
-
continue;
|
|
63
|
-
const target = path.join(CODEX_SKILLS_DIR, entry);
|
|
64
|
-
try {
|
|
65
|
-
const stat = fs.lstatSync(target);
|
|
66
|
-
if (stat.isSymbolicLink()) {
|
|
67
|
-
fs.unlinkSync(target);
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
catch {
|
|
71
|
-
// Ignore
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
catch {
|
|
76
|
-
// Directory might not exist yet
|
|
77
|
-
}
|
|
78
|
-
// Symlink only what's currently in ~/.agents/skills/
|
|
79
|
-
const skillDirs = fs.readdirSync(skillsBase)
|
|
80
|
-
.filter(names_1.isManagedGooseworksSkill);
|
|
81
|
-
let linked = 0;
|
|
82
|
-
for (const skillDir of skillDirs) {
|
|
83
|
-
const source = path.join(skillsBase, skillDir);
|
|
84
|
-
const target = path.join(CODEX_SKILLS_DIR, skillDir);
|
|
85
|
-
try {
|
|
86
|
-
fs.symlinkSync(source, target, 'dir');
|
|
87
|
-
}
|
|
88
|
-
catch {
|
|
89
|
-
// If it somehow still exists, remove and retry
|
|
90
|
-
fs.rmSync(target, { recursive: true, force: true });
|
|
91
|
-
fs.symlinkSync(source, target, 'dir');
|
|
92
|
-
}
|
|
93
|
-
linked++;
|
|
94
|
-
}
|
|
95
|
-
return linked;
|
|
56
|
+
// Cross-platform, privilege-free, resilient linking (GOOSE-2418).
|
|
57
|
+
return (0, skill_links_1.syncManagedSkillLinks)(skillsBase, CODEX_SKILLS_DIR).linked;
|
|
96
58
|
}
|
|
97
59
|
function removeCodex() {
|
|
98
|
-
|
|
99
|
-
return;
|
|
100
|
-
const entries = fs.readdirSync(CODEX_SKILLS_DIR);
|
|
101
|
-
for (const entry of entries) {
|
|
102
|
-
if (!(0, names_1.isManagedGooseworksSkill)(entry))
|
|
103
|
-
continue;
|
|
104
|
-
const target = path.join(CODEX_SKILLS_DIR, entry);
|
|
105
|
-
try {
|
|
106
|
-
const stat = fs.lstatSync(target);
|
|
107
|
-
if (stat.isSymbolicLink()) {
|
|
108
|
-
fs.unlinkSync(target);
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
catch {
|
|
112
|
-
// Ignore
|
|
113
|
-
}
|
|
114
|
-
}
|
|
60
|
+
(0, skill_links_1.removeManagedSkillLinks)(CODEX_SKILLS_DIR);
|
|
115
61
|
}
|
|
116
62
|
function normalizeMcpUrl(base) {
|
|
117
63
|
const stripped = base.replace(/\/$/, '');
|
package/dist/agents/codex.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"codex.js","sourceRoot":"","sources":["../../src/agents/codex.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAUA,8CAEC;AAED,
|
|
1
|
+
{"version":3,"file":"codex.js","sourceRoot":"","sources":["../../src/agents/codex.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/** Drop every managed link under `targetDir` (leaving real directories alone). */
|
|
2
|
+
export declare function removeManagedSkillLinks(targetDir: string): void;
|
|
3
|
+
/**
|
|
4
|
+
* Link every managed skill under `skillsBase` into `targetDir`.
|
|
5
|
+
*
|
|
6
|
+
* - win32 → directory JUNCTIONS (no admin / Developer Mode needed).
|
|
7
|
+
* - a link already resolving to the wanted source is PRESERVED, so a manually
|
|
8
|
+
* repaired junction survives repeated `install` / `update` runs.
|
|
9
|
+
* - a per-skill failure is warned (with an actionable Windows hint) and
|
|
10
|
+
* skipped, never thrown — the caller must still reach MCP registration.
|
|
11
|
+
*
|
|
12
|
+
* Returns { linked, failed }; never throws.
|
|
13
|
+
*/
|
|
14
|
+
export declare function syncManagedSkillLinks(skillsBase: string, targetDir: string): {
|
|
15
|
+
linked: number;
|
|
16
|
+
failed: number;
|
|
17
|
+
};
|
|
18
|
+
//# sourceMappingURL=skill-links.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"skill-links.d.ts","sourceRoot":"","sources":["../../src/agents/skill-links.ts"],"names":[],"mappings":"AAwEA,kFAAkF;AAClF,wBAAgB,uBAAuB,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAa/D;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,qBAAqB,CACnC,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,MAAM,GAChB;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAkDpC"}
|
|
@@ -0,0 +1,192 @@
|
|
|
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.removeManagedSkillLinks = removeManagedSkillLinks;
|
|
37
|
+
exports.syncManagedSkillLinks = syncManagedSkillLinks;
|
|
38
|
+
const fs = __importStar(require("fs"));
|
|
39
|
+
const path = __importStar(require("path"));
|
|
40
|
+
const names_1 = require("../skills/names");
|
|
41
|
+
const logger = __importStar(require("../utils/logger"));
|
|
42
|
+
/**
|
|
43
|
+
* Cross-platform skill linking (GOOSE-2418).
|
|
44
|
+
*
|
|
45
|
+
* On Windows, `fs.symlinkSync(src, dst, 'dir')` requires Administrator rights or
|
|
46
|
+
* Developer Mode — a fresh, non-elevated user hits EPERM, the exception aborts
|
|
47
|
+
* `install`, and the GooseWorks MCP server never gets registered. Directory
|
|
48
|
+
* JUNCTIONS need no privileges and Claude Code / Codex follow them identically,
|
|
49
|
+
* so we use junctions on win32 and dir symlinks everywhere else. Every operation
|
|
50
|
+
* here is best-effort and NEVER throws to its caller — a single bad link must not
|
|
51
|
+
* take down MCP registration.
|
|
52
|
+
*/
|
|
53
|
+
const LINK_TYPE = process.platform === 'win32' ? 'junction' : 'dir';
|
|
54
|
+
/**
|
|
55
|
+
* True when `target` is one of OUR links (a POSIX symlink or a Windows junction),
|
|
56
|
+
* not a real directory. `readlinkSync` succeeds on both link kinds and throws on
|
|
57
|
+
* a regular file/dir — unlike `lstat().isSymbolicLink()`, which reports `false`
|
|
58
|
+
* for junctions and so can't be trusted on Windows.
|
|
59
|
+
*/
|
|
60
|
+
function isLink(target) {
|
|
61
|
+
try {
|
|
62
|
+
fs.readlinkSync(target);
|
|
63
|
+
return true;
|
|
64
|
+
}
|
|
65
|
+
catch {
|
|
66
|
+
return false;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Does `target` already resolve to `source`? A real directory resolves to
|
|
71
|
+
* itself, so this is false for a non-link — safe to use as a "keep this link"
|
|
72
|
+
* check without risking a match on a user's own folder.
|
|
73
|
+
*/
|
|
74
|
+
function resolvesTo(target, source) {
|
|
75
|
+
try {
|
|
76
|
+
return path.resolve(fs.realpathSync(target)) === path.resolve(source);
|
|
77
|
+
}
|
|
78
|
+
catch {
|
|
79
|
+
return false;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Remove a link/junction WITHOUT ever deleting its target contents or a real
|
|
84
|
+
* directory. Callers gate on `isLink()` first. `unlinkSync` handles POSIX
|
|
85
|
+
* symlinks; a Windows junction is a directory reparse point, removed with
|
|
86
|
+
* `rmdirSync` (which drops the junction, not the linked folder).
|
|
87
|
+
*/
|
|
88
|
+
function removeLink(target) {
|
|
89
|
+
try {
|
|
90
|
+
fs.unlinkSync(target);
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
catch {
|
|
94
|
+
// not a plain symlink (e.g. a win32 junction) — fall through
|
|
95
|
+
}
|
|
96
|
+
try {
|
|
97
|
+
fs.rmdirSync(target);
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
catch {
|
|
101
|
+
// last resort
|
|
102
|
+
}
|
|
103
|
+
try {
|
|
104
|
+
fs.rmSync(target, { recursive: false, force: true });
|
|
105
|
+
}
|
|
106
|
+
catch {
|
|
107
|
+
// ignore — nothing more we can safely do
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
/** Drop every managed link under `targetDir` (leaving real directories alone). */
|
|
111
|
+
function removeManagedSkillLinks(targetDir) {
|
|
112
|
+
if (!fs.existsSync(targetDir))
|
|
113
|
+
return;
|
|
114
|
+
let entries = [];
|
|
115
|
+
try {
|
|
116
|
+
entries = fs.readdirSync(targetDir);
|
|
117
|
+
}
|
|
118
|
+
catch {
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
121
|
+
for (const entry of entries) {
|
|
122
|
+
if (!(0, names_1.isManagedGooseworksSkill)(entry))
|
|
123
|
+
continue;
|
|
124
|
+
const target = path.join(targetDir, entry);
|
|
125
|
+
if (isLink(target))
|
|
126
|
+
removeLink(target);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Link every managed skill under `skillsBase` into `targetDir`.
|
|
131
|
+
*
|
|
132
|
+
* - win32 → directory JUNCTIONS (no admin / Developer Mode needed).
|
|
133
|
+
* - a link already resolving to the wanted source is PRESERVED, so a manually
|
|
134
|
+
* repaired junction survives repeated `install` / `update` runs.
|
|
135
|
+
* - a per-skill failure is warned (with an actionable Windows hint) and
|
|
136
|
+
* skipped, never thrown — the caller must still reach MCP registration.
|
|
137
|
+
*
|
|
138
|
+
* Returns { linked, failed }; never throws.
|
|
139
|
+
*/
|
|
140
|
+
function syncManagedSkillLinks(skillsBase, targetDir) {
|
|
141
|
+
fs.mkdirSync(targetDir, { recursive: true });
|
|
142
|
+
let sources = [];
|
|
143
|
+
try {
|
|
144
|
+
sources = fs.readdirSync(skillsBase).filter(names_1.isManagedGooseworksSkill);
|
|
145
|
+
}
|
|
146
|
+
catch {
|
|
147
|
+
return { linked: 0, failed: 0 };
|
|
148
|
+
}
|
|
149
|
+
const wanted = new Map(sources.map((s) => [s, path.join(skillsBase, s)]));
|
|
150
|
+
// Drop stale managed links, but KEEP any that already point at a wanted source
|
|
151
|
+
// (so a working junction a Windows user repaired by hand isn't destroyed).
|
|
152
|
+
try {
|
|
153
|
+
for (const entry of fs.readdirSync(targetDir)) {
|
|
154
|
+
if (!(0, names_1.isManagedGooseworksSkill)(entry))
|
|
155
|
+
continue;
|
|
156
|
+
const target = path.join(targetDir, entry);
|
|
157
|
+
const source = wanted.get(entry);
|
|
158
|
+
if (source && resolvesTo(target, source))
|
|
159
|
+
continue;
|
|
160
|
+
if (isLink(target))
|
|
161
|
+
removeLink(target);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
catch {
|
|
165
|
+
// targetDir race — links are (re)created below regardless
|
|
166
|
+
}
|
|
167
|
+
let linked = 0;
|
|
168
|
+
let failed = 0;
|
|
169
|
+
for (const [skillDir, source] of wanted) {
|
|
170
|
+
const target = path.join(targetDir, skillDir);
|
|
171
|
+
if (resolvesTo(target, source)) {
|
|
172
|
+
linked++; // already correct — preserved, no privilege needed
|
|
173
|
+
continue;
|
|
174
|
+
}
|
|
175
|
+
try {
|
|
176
|
+
if (isLink(target))
|
|
177
|
+
removeLink(target);
|
|
178
|
+
fs.symlinkSync(source, target, LINK_TYPE);
|
|
179
|
+
linked++;
|
|
180
|
+
}
|
|
181
|
+
catch (err) {
|
|
182
|
+
failed++;
|
|
183
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
184
|
+
logger.warn(`Could not link skill "${skillDir}" into ${targetDir}: ${msg}` +
|
|
185
|
+
(process.platform === 'win32'
|
|
186
|
+
? ' — enable Windows Developer Mode or run the terminal as Administrator, then re-run `gooseworks install`.'
|
|
187
|
+
: ''));
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
return { linked, failed };
|
|
191
|
+
}
|
|
192
|
+
//# sourceMappingURL=skill-links.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"skill-links.js","sourceRoot":"","sources":["../../src/agents/skill-links.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"install.d.ts","sourceRoot":"","sources":["../../src/commands/install.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAuBpC,wBAAgB,oBAAoB,IAAI,OAAO,
|
|
1
|
+
{"version":3,"file":"install.d.ts","sourceRoot":"","sources":["../../src/commands/install.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAuBpC,wBAAgB,oBAAoB,IAAI,OAAO,CAoK9C;AAED,eAAO,MAAM,cAAc,SAAyB,CAAC"}
|
package/dist/commands/install.js
CHANGED
|
@@ -105,7 +105,15 @@ Examples:
|
|
|
105
105
|
for (const agent of targetAgents) {
|
|
106
106
|
if (agent === 'claude') {
|
|
107
107
|
logger.info('Creating symlinks in ~/.claude/skills/');
|
|
108
|
-
|
|
108
|
+
// Skill linking must never abort MCP registration — on Windows a symlink
|
|
109
|
+
// privilege error used to throw here and skip MCP entirely (GOOSE-2418).
|
|
110
|
+
try {
|
|
111
|
+
(0, claude_1.configureClaude)();
|
|
112
|
+
}
|
|
113
|
+
catch (err) {
|
|
114
|
+
logger.warn(`Skill linking failed: ${err instanceof Error ? err.message : String(err)}. ` +
|
|
115
|
+
'Continuing — the MCP server will still be registered.');
|
|
116
|
+
}
|
|
109
117
|
if (wantMcp) {
|
|
110
118
|
if ((0, claude_mcp_1.configureClaudeMcp)()) {
|
|
111
119
|
logger.success("Registered 'gooseworks' MCP server in ~/.claude.json");
|
|
@@ -127,7 +135,13 @@ Examples:
|
|
|
127
135
|
}
|
|
128
136
|
if (agent === 'codex') {
|
|
129
137
|
logger.info('Creating symlinks in ~/.codex/skills/');
|
|
130
|
-
|
|
138
|
+
try {
|
|
139
|
+
(0, codex_1.configureCodex)();
|
|
140
|
+
}
|
|
141
|
+
catch (err) {
|
|
142
|
+
logger.warn(`Skill linking failed: ${err instanceof Error ? err.message : String(err)}. ` +
|
|
143
|
+
'Continuing — the MCP server will still be registered.');
|
|
144
|
+
}
|
|
131
145
|
if (wantMcp) {
|
|
132
146
|
if ((0, codex_1.configureCodexMcp)()) {
|
|
133
147
|
logger.success("Registered 'gooseworks' MCP server in ~/.codex/config.toml");
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"install.js","sourceRoot":"","sources":["../../src/commands/install.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAuBA,
|
|
1
|
+
{"version":3,"file":"install.js","sourceRoot":"","sources":["../../src/commands/install.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
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,
|
|
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,CAsUhD;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,yBAAyB,IAAI,MAAM,CAyQlD"}
|
|
@@ -226,7 +226,7 @@ description: >
|
|
|
226
226
|
app uses) — credits are reserved and billed server-side. Analytics recipes are fetched from
|
|
227
227
|
goose-skills on demand.
|
|
228
228
|
category: ads
|
|
229
|
-
version: 2.
|
|
229
|
+
version: 2.2.0
|
|
230
230
|
author: GooseWorks
|
|
231
231
|
tags: [gooseworks, ads, remix, static-ad, brand, creative, image, analytics, meta-ads, performance]
|
|
232
232
|
---
|
|
@@ -309,6 +309,29 @@ decide — fine, but prefer sending the app defaults for predictable parity.
|
|
|
309
309
|
the template; \`"edit"\` makes a targeted change to a specific render (\`prompt\` + \`source_render_id\`
|
|
310
310
|
required); \`"exact"\` runs \`prompt\` verbatim against that render's references. Returns a
|
|
311
311
|
single-item batch — poll it with \`get_remix_batch\`.
|
|
312
|
+
- \`set_creative_feedback { render_id, rating?, comment?, reasons? }\` — record the user's reaction
|
|
313
|
+
to a generated image (the SAME happy/neutral/sad + comment + reason chips the app captures). Use
|
|
314
|
+
it whenever the user reacts ("love this one" / "the logo is wrong"). \`render_id\` is a RENDER id
|
|
315
|
+
from \`get_remix_batch\` / \`list_brand_creatives\`, not a project/batch id. \`reasons\` are quick
|
|
316
|
+
chips (wrong_product, brand_or_logo_wrong, off_brand, text_garbled, weak_copy, ai_or_distorted).
|
|
317
|
+
|
|
318
|
+
### Plan mode — review the plan BEFORE generating (optional)
|
|
319
|
+
|
|
320
|
+
For users who want to approve each ad's plan before spending credits (the app's "Plan it" flow):
|
|
321
|
+
|
|
322
|
+
- \`submit_remix_batch { ..., requires_approval: true }\` — composes each creative's plan and PAUSES.
|
|
323
|
+
**No credits are reserved and no image renders** until you approve.
|
|
324
|
+
- \`list_ad_approvals { brand_id? }\` — poll this; returns \`{ items, counts }\`. While a creative is
|
|
325
|
+
\`composing\`, wait; once \`awaiting_approval\`, show its \`plan\` (composed prompt + refs + quality)
|
|
326
|
+
to the user.
|
|
327
|
+
- \`revise_ad_plan { project_id, message?, variant_label? }\` — recompose from a chat steer, still
|
|
328
|
+
free. Poll \`list_ad_approvals\` until it's \`awaiting_approval\` again.
|
|
329
|
+
- \`approve_ad_plan { project_id | batch_id }\` — approve ONE creative (\`project_id\`) or the whole
|
|
330
|
+
batch (\`batch_id\`). **This is the step that reserves credits and renders.** Then poll
|
|
331
|
+
\`get_remix_batch\` and hand back links as usual.
|
|
332
|
+
|
|
333
|
+
Only offer plan mode when the user asks to review/approve first — the default path generates
|
|
334
|
+
immediately.
|
|
312
335
|
|
|
313
336
|
## Reading the brand & picking inputs (still MCP, read-only)
|
|
314
337
|
|
|
@@ -327,6 +350,33 @@ decide — fine, but prefer sending the app defaults for predictable parity.
|
|
|
327
350
|
image as a private template, then remix it like any other.
|
|
328
351
|
- \`get_ad_project\` / \`append_project_message\` — inspect a creative / leave a note on its thread.
|
|
329
352
|
|
|
353
|
+
## Keep the brand kit in sync — reconcile, then update (ASK first)
|
|
354
|
+
|
|
355
|
+
The brand kit is the source of truth every generation reads. During ANY task, when the user
|
|
356
|
+
**tells you something about the brand or asks to change something brand-level** — a different
|
|
357
|
+
tagline, audience, voice, a product's name/price/description, "our logo is X", "we don't sell Y
|
|
358
|
+
anymore", a new product photo — treat it as a possible kit update, don't just use it for this one
|
|
359
|
+
ad and forget it:
|
|
360
|
+
|
|
361
|
+
1. **Check it against the kit.** \`get_brand_kit { brand_id }\` and see whether what the user said
|
|
362
|
+
matches, is missing from, or contradicts the kit.
|
|
363
|
+
2. **If it's already in the kit and matches** — nothing to do; proceed.
|
|
364
|
+
3. **If it's new or different — ASK before writing.** Confirm in one line: *"Want me to update
|
|
365
|
+
the brand kit so this sticks for future ads?"* Only persist on a yes (or when the user clearly
|
|
366
|
+
asked you to change the brand). Don't silently mutate the kit, and don't nag on trivia.
|
|
367
|
+
4. **Persist with the write tools** (partial — only the fields you pass are touched; each edit is
|
|
368
|
+
recorded as a user override that later re-research won't clobber):
|
|
369
|
+
- \`update_brand_kit { brand_id, description?, audience?, voice?, instructions?, brand_type?,
|
|
370
|
+
value_props?, primary_color?, accent_color? }\` — the structured kit fields.
|
|
371
|
+
- \`upsert_brand_product { brand_id, ... }\` / \`delete_brand_product\` — manage products.
|
|
372
|
+
- \`add_brand_product_image { brand_id, ... }\` / \`remove_brand_reference_image\` — product /
|
|
373
|
+
reference photos.
|
|
374
|
+
5. **Confirm what changed** and continue the task. (Logo, colors, and fonts are owned by the
|
|
375
|
+
backend research pass — prefer \`update_ad_brand\` / the research flow for those, not free text.)
|
|
376
|
+
|
|
377
|
+
This is the parity gap the app closes in-product: a brand fact the user gives mid-task should be
|
|
378
|
+
able to flow back into the kit — with their ok — instead of being lost.
|
|
379
|
+
|
|
330
380
|
## Picking templates — ASK the user; don't freelance from the catalog
|
|
331
381
|
|
|
332
382
|
When the user wants to make ads but has NOT named a specific template (id/slug/Community
|
|
@@ -475,6 +525,15 @@ run through the \`gooseworks\` CLI (\`gooseworks fetch\` / \`gooseworks call\`),
|
|
|
475
525
|
Generate when they paste the app's copyable remix prompt back (or submit the surprise picks
|
|
476
526
|
directly if they'd rather not review).
|
|
477
527
|
- **Ask the styling** — Keep original (default) vs Match brand — before you submit.
|
|
528
|
+
- **Reconcile brand facts into the kit** — when the user states or changes something brand-level
|
|
529
|
+
mid-task, check it against \`get_brand_kit\` and, with their ok, persist it via \`update_brand_kit\`
|
|
530
|
+
/ \`upsert_brand_product\` / \`add_brand_product_image\` so it sticks for future ads. Ask first;
|
|
531
|
+
never silently mutate the kit.
|
|
532
|
+
- **Record feedback** — when the user reacts to a generated image, capture it with
|
|
533
|
+
\`set_creative_feedback { render_id, rating/comment/reasons }\` so the quality loop learns.
|
|
534
|
+
- **Plan mode is opt-in** — only compose-and-pause (\`requires_approval: true\` → \`list_ad_approvals\`
|
|
535
|
+
→ \`approve_ad_plan\`) when the user wants to review before spending credits; otherwise generate
|
|
536
|
+
immediately.
|
|
478
537
|
- **Don't busy-loop** — poll \`get_remix_batch\` on a sensible interval (~20-30s); a \`queued\`
|
|
479
538
|
batch is waiting on research and will start on its own.
|
|
480
539
|
`;
|
|
@@ -503,7 +562,7 @@ description: >
|
|
|
503
562
|
template, or asks to remix a video ad. Unlike goose-ads (static images, generated server-side),
|
|
504
563
|
video renders locally and reports progress + the result back through the gooseworks MCP tools.
|
|
505
564
|
category: ads
|
|
506
|
-
version: 0.
|
|
565
|
+
version: 0.2.0
|
|
507
566
|
author: GooseWorks
|
|
508
567
|
tags: [gooseworks, ads, video, remix, imessage, local-render, byoa]
|
|
509
568
|
---
|
|
@@ -639,13 +698,35 @@ ingredients out one at a time.
|
|
|
639
698
|
\`update_render_status { render_id, status: "running" }\`. The render row tracks status only
|
|
640
699
|
(queued / running / complete / failed) — narrate fine-grained progress with
|
|
641
700
|
\`append_project_message\` instead.
|
|
642
|
-
3.
|
|
643
|
-
the
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
701
|
+
3. **MANDATORY final-video review gate — review EVERY finished master before \`set_final_render\`,
|
|
702
|
+
whatever the format (UGC or not).** The render credit is already spent (\`submit_render\` in 4.2);
|
|
703
|
+
this gate stands between a rendered master and PINNING/publishing it, so a bad render never gets
|
|
704
|
+
set as final. A master that looks fine on a still can still have a mis-voiced word, a caption
|
|
705
|
+
drifting off its line, a beat out of order, or a deformation — review the actual VIDEO, not
|
|
706
|
+
stills. Run the passes that APPLY to this format:
|
|
707
|
+
- **Audio ↔ script** — any master with SPEECH (VO or native/Seedance voice); **skip for
|
|
708
|
+
music-only / no-speech formats.** \`review-ugc-render\` is format-agnostic despite the name —
|
|
709
|
+
a deterministic Whisper transcript-vs-script diff, not UGC-specific: persist the approved
|
|
710
|
+
spoken lines to \`working/approved-script.txt\`, then \`gooseworks fetch review-ugc-render\` and
|
|
711
|
+
run \`review_render.py --video <master>.mp4 --script-file working/approved-script.txt --json
|
|
712
|
+
working/review-verdict.json\` (exit 0 PASS / 2 FAIL / 3 ERROR). It blocks a mis-voiced word
|
|
713
|
+
(approved "human-vetted" → "human witted"), a dropped phrase, or silence. It routes Whisper
|
|
714
|
+
through the gooseworks proxy when \`OPENAI_BASE_URL\` is set; with no backend at all, run
|
|
715
|
+
\`fal-ai/whisper\` via \`fal-proxy\` (upload the audio, pass its \`get_download_url\` as \`audio_url\`)
|
|
716
|
+
and diff the transcript yourself.
|
|
717
|
+
- **Captions / subtitles** — ANY captioned format (the most common non-UGC defect); **skip for
|
|
718
|
+
UGC/Seedance masters, which carry no subtitle track.** Concrete check: diff the caption file
|
|
719
|
+
you burned (SRT/ASS) against the SAME Whisper transcript + word timings from the audio pass —
|
|
720
|
+
every caption line must match the heard/scripted words and sit within ~0.3s of when they're
|
|
721
|
+
spoken; then in the visual pass below, OCR-read the burned caption off 4–5 sampled frames to
|
|
722
|
+
confirm it's actually on screen at that time and not colliding with a hyperframe or the end
|
|
723
|
+
card. Mismatched text or >0.3s drift fails the gate.
|
|
724
|
+
- **Visual + structure** — always: run the \`watch\` skill on the master — beat/scene order + SFX,
|
|
725
|
+
the brand's product (not the source's) is shown, the end card has the real wordmark + code, no
|
|
726
|
+
deformation/artifact, duration within ~20% of the source.
|
|
727
|
+
If ANY applicable pass fails, FIX it (regenerate/stitch the offending window, rebuild captions)
|
|
728
|
+
and re-review — only a clean pass proceeds to \`set_final_render\`. **This gate is universal: it
|
|
729
|
+
runs from the master skill for every format, so a recipe never has to opt in.**
|
|
649
730
|
4. Publish: \`get_upload_url { target: { type: "agent", agent_id: ADS_AGENT } }\` → PUT the master
|
|
650
731
|
and poster **under the project folder** (see Identity's path-prefix rule) — to
|
|
651
732
|
\`agent-config/brands/<brand_slug>/projects/<project_id>/working/final.mp4\` and
|
|
@@ -667,8 +748,10 @@ content }\` — never sit silent on a queue > 90s.
|
|
|
667
748
|
|
|
668
749
|
Media APIs go through GooseWorks proxies with your agent token; do NOT use an SDK's default host
|
|
669
750
|
(your token isn't a FAL/ElevenLabs token → 401). Base = \`<api_base>/api/internal/<proxy>\`; pass
|
|
670
|
-
\`?token=<api_key>&agent_id=<agent_id>\` (agent_id bills the Ads agent
|
|
671
|
-
\`
|
|
751
|
+
\`?token=<api_key>&agent_id=<agent_id>&project_id=<project_id>\` (agent_id bills the Ads agent;
|
|
752
|
+
\`project_id\` = the id of the project you're rendering — it attributes this generation's credits to
|
|
753
|
+
that ad project so the user sees per-project spend in the app. ALWAYS pass it). FAL = \`fal-proxy\`
|
|
754
|
+
(+ \`fal-storage-proxy\` to host a local image and get a CDN URL); ElevenLabs = \`elevenlabs-proxy\`
|
|
672
755
|
(VO / music bed).
|
|
673
756
|
|
|
674
757
|
**FAL queue gotcha** (#1 waste of generations): submit returns \`status_url\`/\`response_url\` on
|
|
@@ -684,24 +767,26 @@ def _cfg():
|
|
|
684
767
|
c = json.loads(pathlib.Path(os.path.expanduser("~/.gooseworks/credentials.json")).read_text())
|
|
685
768
|
return c["api_base"].rstrip("/"), c["api_key"], c.get("agent_id")
|
|
686
769
|
|
|
687
|
-
def _params(tok, agent):
|
|
770
|
+
def _params(tok, agent, project_id=None):
|
|
688
771
|
p = {"token": tok}
|
|
689
772
|
if agent: p["agent_id"] = agent
|
|
773
|
+
if project_id: p["project_id"] = project_id # attributes the spend to this ad project
|
|
690
774
|
return p
|
|
691
775
|
|
|
692
|
-
def fal_generate(model_path, payload, timeout_s=180, poll_s=3):
|
|
776
|
+
def fal_generate(model_path, payload, project_id=None, timeout_s=180, poll_s=3):
|
|
693
777
|
"""model_path e.g. 'fal-ai/nano-banana-2/edit' (the recipe names the model).
|
|
778
|
+
Pass project_id = the ad project you're rendering so credits attribute to it.
|
|
694
779
|
Returns the result image URL (a public *.fal.media CDN URL)."""
|
|
695
780
|
api_base, tok, agent = _cfg()
|
|
696
781
|
base = api_base + "/api/internal/fal-proxy"
|
|
697
|
-
sub = requests.post(f"{base}/{model_path}", params=_params(tok, agent), json=payload).json()
|
|
782
|
+
sub = requests.post(f"{base}/{model_path}", params=_params(tok, agent, project_id), json=payload).json()
|
|
698
783
|
to_proxy = lambda u: base + urlparse(u).path
|
|
699
784
|
status_url, response_url = to_proxy(sub["status_url"]), to_proxy(sub["response_url"])
|
|
700
785
|
deadline = time.time() + timeout_s
|
|
701
786
|
while time.time() < deadline:
|
|
702
|
-
st = requests.get(status_url, params=_params(tok, agent)).json()
|
|
787
|
+
st = requests.get(status_url, params=_params(tok, agent, project_id)).json()
|
|
703
788
|
if st.get("status") == "COMPLETED":
|
|
704
|
-
return requests.get(response_url, params=_params(tok, agent)).json()["images"][0]["url"]
|
|
789
|
+
return requests.get(response_url, params=_params(tok, agent, project_id)).json()["images"][0]["url"]
|
|
705
790
|
if st.get("status") in ("FAILED", "ERROR"):
|
|
706
791
|
raise RuntimeError(f"FAL failed: {st}")
|
|
707
792
|
time.sleep(poll_s)
|
|
@@ -709,7 +794,7 @@ def fal_generate(model_path, payload, timeout_s=180, poll_s=3):
|
|
|
709
794
|
\`\`\`
|
|
710
795
|
|
|
711
796
|
ElevenLabs (VO / music) is the same shape against \`<api_base>/api/internal/elevenlabs-proxy\`
|
|
712
|
-
with \`?token=&agent_id=\`. Feed FAL a local image by storing it (\`get_upload_url\`) and passing its
|
|
797
|
+
with \`?token=&agent_id=&project_id=\`. Feed FAL a local image by storing it (\`get_upload_url\`) and passing its
|
|
713
798
|
\`get_download_url\` presigned URL as an \`image_urls\` / \`audio_url\` entry — this is the reliable
|
|
714
799
|
path. (\`fal-storage-proxy\` may 404 depending on the install; don't block on it — prefer the
|
|
715
800
|
\`get_download_url\` presigned URL.)
|
|
@@ -722,6 +807,8 @@ path. (\`fal-storage-proxy\` may 404 depending on the install; don't block on it
|
|
|
722
807
|
the template needs), mirror the whole set with \`update_ad_project_script\`, and get the user's
|
|
723
808
|
approval in-session BEFORE rendering — always (review-once).
|
|
724
809
|
- **submit_render LAST**; \`output_url\` = the durable render-file URL, never a CDN URL.
|
|
810
|
+
- **Always pass \`project_id\` on media-proxy calls** (fal / ElevenLabs) so the credits attribute
|
|
811
|
+
to this ad project — that's what lets the user see per-project spend in the app.
|
|
725
812
|
- **Verify a real, non-empty MP4** (watch it) before marking the render complete.
|
|
726
813
|
- **Reuse the brand** when its research is complete; never re-research.
|
|
727
814
|
- On a hard error (auth/quota/model/timeout) set the render \`failed\` with a short
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"master-skill.js","sourceRoot":"","sources":["../../src/skills/master-skill.ts"],"names":[],"mappings":";;AA4BA,wCAMC;AAWD,sDA8KC;AAiBD,
|
|
1
|
+
{"version":3,"file":"master-skill.js","sourceRoot":"","sources":["../../src/skills/master-skill.ts"],"names":[],"mappings":";;AA4BA,wCAMC;AAWD,sDA8KC;AAiBD,0DAsUC;AAcD,8DAyQC;AA9yBD,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;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAoUR,CAAC;AACF,CAAC;AAED;;;;;;;;;;;GAWG;AACH,SAAgB,yBAAyB;IACvC,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAuQR,CAAC;AACF,CAAC"}
|