git-vibe-setup 4.1.0 → 5.1.1
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/README.md +5 -4
- package/dist/install.js +152 -1
- package/package.json +4 -1
package/README.md
CHANGED
|
@@ -20,10 +20,11 @@ npx git-vibe-setup update
|
|
|
20
20
|
```
|
|
21
21
|
|
|
22
22
|
The `update` command fetches `examples/consumer` from the latest stable
|
|
23
|
-
`markhuangai/git-vibe` release,
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
overwrite workflow files that do not
|
|
23
|
+
`markhuangai/git-vibe` release, migrates supported `.github/git-vibe.yml`
|
|
24
|
+
settings in place, rewrites `.github/workflows/*.yml` GitVibe wrapper files,
|
|
25
|
+
and pins workflow refs to that release. It does not update `.git-vibe`,
|
|
26
|
+
secrets, or variables, and it refuses to overwrite workflow files that do not
|
|
27
|
+
look like GitVibe wrappers.
|
|
27
28
|
|
|
28
29
|
To test a specific release or prerelease from a consumer repository, pass the
|
|
29
30
|
release tag explicitly:
|
package/dist/install.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { existsSync, mkdirSync, readdirSync, readFileSync, rmSync, writeFileSync } from "node:fs";
|
|
2
2
|
import { basename, dirname, join, relative } from "node:path";
|
|
3
|
+
import { isMap, isScalar, parseDocument, YAMLMap } from "yaml";
|
|
3
4
|
const requiredInstallSourcePaths = [
|
|
4
5
|
".github/git-vibe.yml",
|
|
5
6
|
".github/workflows/investigate.yml",
|
|
@@ -91,7 +92,9 @@ export function pinWorkflowReleaseRefs(content, releaseTag) {
|
|
|
91
92
|
}
|
|
92
93
|
export function migrateGitVibeConfigContent(content) {
|
|
93
94
|
const migratedComments = migrateLegacyEventDeliveryComments(content);
|
|
94
|
-
|
|
95
|
+
const migratedAuth = migrateGithubAuthConfig(migratedComments);
|
|
96
|
+
const migratedSafety = migratePromptInjectionSafetyConfig(migratedAuth);
|
|
97
|
+
return ensureTrailingNewline(migrateLegacyAiProfiles(migratedSafety));
|
|
95
98
|
}
|
|
96
99
|
function isManagedWorkflowTarget(file) {
|
|
97
100
|
return isManagedWorkflowFile(file.targetPath, basename(file.targetPath));
|
|
@@ -260,6 +263,154 @@ function migrateGithubAuthConfig(content) {
|
|
|
260
263
|
}
|
|
261
264
|
return `${content.trimEnd()}\n\n${githubAppAuth}`;
|
|
262
265
|
}
|
|
266
|
+
function migratePromptInjectionSafetyConfig(content) {
|
|
267
|
+
const document = parseDocument(content);
|
|
268
|
+
if (document.errors.length > 0) {
|
|
269
|
+
throw new Error(`git-vibe-setup could not migrate .github/git-vibe.yml because it is not valid YAML: ${document.errors[0]?.message}`);
|
|
270
|
+
}
|
|
271
|
+
const root = document.contents;
|
|
272
|
+
if (!isMap(root) || root.has("safety"))
|
|
273
|
+
return content;
|
|
274
|
+
return `${content.trimEnd()}\n\nsafety:\n prompt_injection_gate: true\n`;
|
|
275
|
+
}
|
|
276
|
+
function migrateLegacyAiProfiles(content) {
|
|
277
|
+
const document = parseDocument(content);
|
|
278
|
+
if (document.errors.length > 0) {
|
|
279
|
+
throw new Error(`git-vibe-setup could not migrate .github/git-vibe.yml because it is not valid YAML: ${document.errors[0]?.message}`);
|
|
280
|
+
}
|
|
281
|
+
const root = document.contents;
|
|
282
|
+
if (!isMap(root))
|
|
283
|
+
return content;
|
|
284
|
+
const ai = root.get("ai", true);
|
|
285
|
+
if (!isMap(ai))
|
|
286
|
+
return content;
|
|
287
|
+
const profiles = ai.get("profiles", true);
|
|
288
|
+
if (!isMap(profiles))
|
|
289
|
+
return content;
|
|
290
|
+
let changed = false;
|
|
291
|
+
for (const pair of profiles.items) {
|
|
292
|
+
if (isMap(pair.value))
|
|
293
|
+
changed = migrateLegacyAiProfile(pair.value) || changed;
|
|
294
|
+
}
|
|
295
|
+
return changed ? document.toString() : content;
|
|
296
|
+
}
|
|
297
|
+
function migrateLegacyAiProfile(profile) {
|
|
298
|
+
const adapter = stringNodeValue(profile.get("adapter"));
|
|
299
|
+
if (adapter === "ai-sdk-agentool") {
|
|
300
|
+
migrateAgentoolProfile(profile);
|
|
301
|
+
return true;
|
|
302
|
+
}
|
|
303
|
+
if (adapter === "cli-claude-code") {
|
|
304
|
+
profile.set("adapter", "claude-code-sdk");
|
|
305
|
+
ensureClaudeModel(profile);
|
|
306
|
+
orderProfileKeys(profile);
|
|
307
|
+
return true;
|
|
308
|
+
}
|
|
309
|
+
if (adapter === "cli-codex") {
|
|
310
|
+
profile.set("adapter", "codex-sdk");
|
|
311
|
+
return true;
|
|
312
|
+
}
|
|
313
|
+
return false;
|
|
314
|
+
}
|
|
315
|
+
function migrateAgentoolProfile(profile) {
|
|
316
|
+
const provider = profile.get("provider", true);
|
|
317
|
+
profile.set("adapter", "claude-code-sdk");
|
|
318
|
+
syncClaudeEnvFromProvider(profile, provider);
|
|
319
|
+
syncReasoningEffort(profile);
|
|
320
|
+
trimProviderOptions(profile);
|
|
321
|
+
ensureClaudeModel(profile);
|
|
322
|
+
profile.delete("context_window_tokens");
|
|
323
|
+
profile.delete("provider");
|
|
324
|
+
orderProfileKeys(profile);
|
|
325
|
+
}
|
|
326
|
+
function syncClaudeEnvFromProvider(profile, provider) {
|
|
327
|
+
const env = ensureMap(profile, "env");
|
|
328
|
+
if (isMap(provider)) {
|
|
329
|
+
copyMapValue(provider, "api_key", env, "ANTHROPIC_API_KEY");
|
|
330
|
+
copyMapValue(provider, "base_url", env, "ANTHROPIC_BASE_URL");
|
|
331
|
+
const providerModel = stringNodeValue(provider.get("model"));
|
|
332
|
+
if (providerModel) {
|
|
333
|
+
setIfMissing(env, "ANTHROPIC_DEFAULT_OPUS_MODEL", providerModel);
|
|
334
|
+
setIfMissing(env, "ANTHROPIC_DEFAULT_SONNET_MODEL", providerModel);
|
|
335
|
+
setIfMissing(env, "ANTHROPIC_DEFAULT_HAIKU_MODEL", providerModel);
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
setIfMissing(env, "ANTHROPIC_MODEL", "opus");
|
|
339
|
+
setIfMissing(env, "CLAUDE_CODE_SUBAGENT_MODEL", "opus");
|
|
340
|
+
}
|
|
341
|
+
function syncReasoningEffort(profile) {
|
|
342
|
+
const effort = nodeAt(profile, ["reasoning", "effort"]) ||
|
|
343
|
+
nodeAt(profile, ["provider_options", "anthropic", "effort"]);
|
|
344
|
+
if (!effort)
|
|
345
|
+
return;
|
|
346
|
+
const reasoning = ensureMap(profile, "reasoning");
|
|
347
|
+
if (!reasoning.has("effort"))
|
|
348
|
+
reasoning.set("effort", effort);
|
|
349
|
+
}
|
|
350
|
+
function trimProviderOptions(profile) {
|
|
351
|
+
const providerOptions = profile.get("provider_options", true);
|
|
352
|
+
if (!isMap(providerOptions))
|
|
353
|
+
return;
|
|
354
|
+
providerOptions.delete("openai");
|
|
355
|
+
if (providerOptions.items.length === 0)
|
|
356
|
+
profile.delete("provider_options");
|
|
357
|
+
}
|
|
358
|
+
function ensureClaudeModel(profile) {
|
|
359
|
+
setIfMissing(profile, "model", "opus");
|
|
360
|
+
}
|
|
361
|
+
function ensureMap(parent, key) {
|
|
362
|
+
const value = parent.get(key, true);
|
|
363
|
+
if (isMap(value))
|
|
364
|
+
return value;
|
|
365
|
+
const map = new YAMLMap();
|
|
366
|
+
parent.set(key, map);
|
|
367
|
+
return map;
|
|
368
|
+
}
|
|
369
|
+
function copyMapValue(source, sourceKey, target, targetKey) {
|
|
370
|
+
if (target.has(targetKey))
|
|
371
|
+
return;
|
|
372
|
+
const value = source.get(sourceKey, true);
|
|
373
|
+
if (value !== undefined)
|
|
374
|
+
target.set(targetKey, value);
|
|
375
|
+
}
|
|
376
|
+
function setIfMissing(map, key, value) {
|
|
377
|
+
if (!map.has(key))
|
|
378
|
+
map.set(key, value);
|
|
379
|
+
}
|
|
380
|
+
function nodeAt(map, path) {
|
|
381
|
+
let current = map;
|
|
382
|
+
for (const segment of path) {
|
|
383
|
+
if (!isMap(current))
|
|
384
|
+
return undefined;
|
|
385
|
+
current = current.get(segment, true);
|
|
386
|
+
}
|
|
387
|
+
return current;
|
|
388
|
+
}
|
|
389
|
+
function stringNodeValue(value) {
|
|
390
|
+
if (typeof value === "string")
|
|
391
|
+
return value;
|
|
392
|
+
if (isScalar(value) && typeof value.value === "string")
|
|
393
|
+
return value.value;
|
|
394
|
+
return undefined;
|
|
395
|
+
}
|
|
396
|
+
function orderProfileKeys(profile) {
|
|
397
|
+
const priorities = new Map([
|
|
398
|
+
["adapter", 0],
|
|
399
|
+
["env", 1],
|
|
400
|
+
["model", 2],
|
|
401
|
+
["reasoning", 3],
|
|
402
|
+
["provider_options", 4],
|
|
403
|
+
]);
|
|
404
|
+
profile.items.sort((left, right) => {
|
|
405
|
+
return profileKeyPriority(left, priorities) - profileKeyPriority(right, priorities);
|
|
406
|
+
});
|
|
407
|
+
}
|
|
408
|
+
function profileKeyPriority(pair, priorities) {
|
|
409
|
+
return priorities.get(pairKey(pair)) ?? 100;
|
|
410
|
+
}
|
|
411
|
+
function pairKey(pair) {
|
|
412
|
+
return stringNodeValue(pair.key) || "";
|
|
413
|
+
}
|
|
263
414
|
function ensureTrailingNewline(content) {
|
|
264
415
|
return content.endsWith("\n") ? content : `${content}\n`;
|
|
265
416
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "git-vibe-setup",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "5.1.1",
|
|
4
4
|
"private": false,
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -16,6 +16,9 @@
|
|
|
16
16
|
"test": "vitest run",
|
|
17
17
|
"typecheck": "tsc --project tsconfig.json --noEmit"
|
|
18
18
|
},
|
|
19
|
+
"dependencies": {
|
|
20
|
+
"yaml": "^2.8.4"
|
|
21
|
+
},
|
|
19
22
|
"devDependencies": {
|
|
20
23
|
"@types/node": "^25.6.0",
|
|
21
24
|
"typescript": "^6.0.3",
|