Skip to content

Commit 90356e4

Browse files
authored
feat(desktop): 预信任默认工作流并允许编辑 ApeMind 扩展
- 启动时为 bundled ApeMind 工作流写入已接受 hash,避免默认工作流弹出新工作流警告\n- 只对 apemind bundled extension 放开配置按钮,便于用户修改 URL 和 Authorization Bearer token\n- 保持核心 recipe warning / IPC / goose runtime 逻辑不变
1 parent af63877 commit 90356e4

2 files changed

Lines changed: 29 additions & 4 deletions

File tree

ui/desktop/src/components/settings/extensions/subcomponents/ExtensionItem.tsx

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,9 +80,16 @@ export default function ExtensionItem({
8080
// Bundled extensions and builtins are not editable
8181
// Over time we can take the first part of the conditional away as people have bundled: true in their config.yaml entries
8282

83+
// ApeCloud fork carve-out: the `apemind` bundled extension ships with placeholder URL/token
84+
// that the user MUST be able to edit from the UI before enabling.
85+
const isApeMindBundled =
86+
'bundled' in extension && extension.bundled && extension.name === 'apemind';
87+
8388
// allow configuration editing if extension is not a builtin/bundled extension AND isStatic = false
8489
const editable =
85-
!(extension.type === 'builtin' || ('bundled' in extension && extension.bundled)) && !isStatic;
90+
(!(extension.type === 'builtin' || ('bundled' in extension && extension.bundled)) ||
91+
isApeMindBundled) &&
92+
!isStatic;
8693

8794
return (
8895
<Card

ui/desktop/src/main.ts

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -180,17 +180,35 @@ async function seedDefaultRecipes(): Promise<void> {
180180
? path.join(process.resourcesPath, 'default-recipes')
181181
: path.join(__dirname, '..', 'default-recipes');
182182
const destDir = path.join(os.homedir(), '.config', 'goose', 'recipes');
183+
const hashesDir = path.join(app.getPath('userData'), 'recipe_hashes');
183184

184185
if (!fsSync.existsSync(sourceRoot)) return;
185186

186187
await fs.mkdir(destDir, { recursive: true });
188+
await fs.mkdir(hashesDir, { recursive: true });
187189
const entries = await fs.readdir(sourceRoot);
188190
for (const entry of entries) {
189191
if (!entry.endsWith('.yaml') && !entry.endsWith('.yml')) continue;
192+
const sourcePath = path.join(sourceRoot, entry);
190193
const destPath = path.join(destDir, entry);
191-
if (fsSync.existsSync(destPath)) continue;
192-
await fs.copyFile(path.join(sourceRoot, entry), destPath);
193-
log.info(`[seedDefaultRecipes] seeded ${entry}${destPath}`);
194+
195+
if (!fsSync.existsSync(destPath)) {
196+
await fs.copyFile(sourcePath, destPath);
197+
log.info(`[seedDefaultRecipes] seeded ${entry}${destPath}`);
198+
}
199+
200+
try {
201+
const yamlContent = await fs.readFile(sourcePath, 'utf-8');
202+
const parsed = yaml.parse(yamlContent);
203+
const hash = crypto.createHash('sha256').update(JSON.stringify(parsed)).digest('hex');
204+
const hashFile = path.join(hashesDir, `${hash}.hash`);
205+
if (!fsSync.existsSync(hashFile)) {
206+
await fs.writeFile(hashFile, new Date().toISOString());
207+
log.info(`[seedDefaultRecipes] pre-trusted hash for ${entry}${hash}`);
208+
}
209+
} catch (err) {
210+
log.warn(`[seedDefaultRecipes] failed to pre-trust ${entry}:`, err);
211+
}
194212
}
195213
}
196214

0 commit comments

Comments
 (0)