melchizedek-agents 1.1.0 → 1.2.0
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/.env.example +10 -0
- package/AGENT_SETUP.md +3 -1
- package/CHANGELOG.md +232 -0
- package/DOCUMENTATION.md +91 -16
- package/ONBOARDING.md +339 -0
- package/QUICKSTART.md +15 -2
- package/README.md +5 -2
- package/config/agents/examples/council.yaml +1 -1
- package/config/agents/examples/critic.yaml +8 -8
- package/config/agents/examples/image_production.yaml +4 -3
- package/config/agents/syndicate.schema.json +65 -7
- package/config/agents/syndicateSchema.yaml +18 -6
- package/config/agents/templates/intake_extractor.yaml +3 -2
- package/config/agents/templates/systems_operator.yaml +5 -2
- package/dist/lib/a2a/app.d.ts +12 -0
- package/dist/lib/a2a/app.js +22 -11
- package/dist/lib/a2a/executor.js +14 -6
- package/dist/lib/a2a/oauthSetup.d.ts +16 -0
- package/dist/lib/a2a/oauthSetup.js +57 -3
- package/dist/lib/agentDialect.d.ts +18 -8
- package/dist/lib/agentDialect.js +36 -19
- package/dist/lib/compile.d.ts +38 -7
- package/dist/lib/compile.js +57 -37
- package/dist/lib/compileNative.d.ts +11 -3
- package/dist/lib/compileNative.js +18 -1
- package/dist/lib/doctor.d.ts +76 -0
- package/dist/lib/doctor.js +159 -7
- package/dist/lib/loadSyndicate.d.ts +9 -0
- package/dist/lib/models/capabilities.d.ts +9 -0
- package/dist/lib/models/capabilities.js +24 -0
- package/dist/lib/models/chatCompletionsAdapter.d.ts +11 -3
- package/dist/lib/models/chatCompletionsAdapter.js +19 -5
- package/dist/lib/models/claudeAdapter.js +4 -0
- package/dist/lib/models/contract.d.ts +5 -2
- package/dist/lib/models/gateway.d.ts +2 -1
- package/dist/lib/models/gateway.js +4 -2
- package/dist/lib/models/gatewayAdapter.d.ts +7 -1
- package/dist/lib/models/gatewayAdapter.js +8 -0
- package/dist/lib/models/geminiAdapter.js +8 -2
- package/dist/lib/models/genaiMapping.d.ts +8 -4
- package/dist/lib/models/genaiMapping.js +23 -9
- package/dist/lib/models/gptAdapter.d.ts +4 -2
- package/dist/lib/models/gptAdapter.js +11 -4
- package/dist/lib/models/grokAdapter.d.ts +3 -1
- package/dist/lib/models/grokAdapter.js +11 -3
- package/dist/lib/models/kimiAdapter.d.ts +2 -1
- package/dist/lib/models/kimiAdapter.js +3 -3
- package/dist/lib/models/reasoning.d.ts +30 -2
- package/dist/lib/models/reasoning.js +56 -5
- package/dist/lib/onboarding.d.ts +134 -0
- package/dist/lib/onboarding.js +539 -0
- package/dist/lib/runtime/approvals.d.ts +2 -0
- package/dist/lib/runtime/approvals.js +4 -3
- package/dist/lib/runtime/credentials.d.ts +6 -0
- package/dist/lib/runtime/native/agentLoop.d.ts +5 -2
- package/dist/lib/runtime/native/agentLoop.js +2 -0
- package/dist/lib/runtime/native/checkpoint.d.ts +12 -5
- package/dist/lib/runtime/native/checkpoint.js +13 -19
- package/dist/lib/runtime/native/delegate.d.ts +82 -1
- package/dist/lib/runtime/native/delegate.js +157 -2
- package/dist/lib/runtime/native/interrupts.d.ts +88 -5
- package/dist/lib/runtime/native/interrupts.js +220 -30
- package/dist/lib/runtime/syndicateTurn.d.ts +4 -2
- package/dist/lib/runtime/syndicateTurn.js +295 -62
- package/dist/lib/runtime/turnControl.d.ts +41 -0
- package/dist/lib/session/transcript.d.ts +9 -0
- package/dist/lib/session/transcript.js +20 -1
- package/dist/lib/skills.d.ts +18 -0
- package/dist/lib/skills.js +73 -1
- package/dist/lib/storage/postgres/index.d.ts +6 -1
- package/dist/lib/storage/postgres/index.js +1 -1
- package/dist/lib/storage/postgres/taskQueue.d.ts +7 -3
- package/dist/lib/storage/postgres/taskQueue.js +10 -3
- package/dist/lib/syndicateSchema.d.ts +38 -1
- package/dist/lib/syndicateSchema.js +25 -18
- package/dist/lib/tools/auth.d.ts +13 -1
- package/dist/lib/tools/auth.js +10 -2
- package/dist/lib/tools/credentialHosts.d.ts +88 -0
- package/dist/lib/tools/credentialHosts.js +165 -0
- package/dist/lib/tools/credentialUses.d.ts +92 -0
- package/dist/lib/tools/credentialUses.js +112 -0
- package/dist/lib/tools/mcpToolFactory.js +1 -1
- package/dist/lib/tools/oauthConsent.js +8 -1
- package/dist/lib/tools/oauthHosts.d.ts +2 -0
- package/dist/lib/tools/oauthHosts.js +2 -2
- package/dist/lib/tools/oauthTools.d.ts +10 -1
- package/dist/lib/tools/oauthTools.js +29 -3
- package/dist/lib/tools/openapiTools.d.ts +7 -0
- package/dist/lib/tools/openapiTools.js +49 -3
- package/dist/lib/tools/taskTools.d.ts +32 -2
- package/dist/lib/tools/taskTools.js +93 -33
- package/dist/lib/workflow/turn.d.ts +22 -3
- package/dist/lib/workflow/turn.js +151 -31
- package/dist/lib/workflow.d.ts +10 -7
- package/dist/lib/workflow.js +10 -7
- package/dist/scripts/a2a_server.d.ts +2 -2
- package/dist/scripts/a2a_server.js +11 -2
- package/dist/scripts/assistant_worker.d.ts +2 -0
- package/dist/scripts/assistant_worker.js +13 -4
- package/dist/scripts/doctor.d.ts +4 -2
- package/dist/scripts/doctor.js +6 -4
- package/dist/scripts/setup.d.ts +23 -0
- package/dist/scripts/setup.js +154 -0
- package/dist/scripts/skills_install.d.ts +3 -1
- package/dist/scripts/skills_install.js +17 -2
- package/dist/scripts/yaml_codemod.d.ts +12 -2
- package/dist/scripts/yaml_codemod.js +115 -33
- package/package.json +4 -1
- package/skills/README.md +11 -2
- package/skills/briefs/_shared.md +1 -1
- package/skills/briefs/melchizedek-models.md +4 -2
- package/skills/briefs/skills-readme.md +3 -1
- package/skills/melchizedek-models/SKILL.md +6 -2
- package/skills/melchizedek-onboard/SKILL.md +49 -0
- package/skills/melchizedek-onboard-cloud/SKILL.md +38 -0
- package/skills/melchizedek-onboard-keys/SKILL.md +35 -0
- package/skills/melchizedek-onboard-local/SKILL.md +41 -0
- package/skills/melchizedek-onboard-serve/SKILL.md +43 -0
package/dist/scripts/doctor.d.ts
CHANGED
|
@@ -11,7 +11,9 @@
|
|
|
11
11
|
* removed that runtime). Lists the tools that need an OAuth grant (an
|
|
12
12
|
* `auth: { oauth2 }` or `mcp_auth`, ADR 0112): each user's consent, or the
|
|
13
13
|
* server's own client credentials and whether their variables are set
|
|
14
|
-
* (names only).
|
|
14
|
+
* (names only). When any A2A identity or billing variable is set, a
|
|
15
|
+
* `serving` line names the A2A_AUTH mode and A2A_KEY_MODE and what the
|
|
16
|
+
* server would refuse to start on. Closes with the env vars that would
|
|
15
17
|
* unlock the most, where to get each, and the first command to try.
|
|
16
18
|
*
|
|
17
19
|
* Read-only: never edits .env, never sends a request, never prints a key
|
|
@@ -20,7 +22,7 @@
|
|
|
20
22
|
* Usage:
|
|
21
23
|
* npm run doctor
|
|
22
24
|
* npm run doctor -- --json # machine-readable
|
|
23
|
-
* npm run doctor -- --check # exit 1
|
|
25
|
+
* npm run doctor -- --check # exit 1 on a blocked syndicate, a runtime problem, or an OAuth or credential host problem
|
|
24
26
|
* npm run doctor -- --matrix # the provider × capability matrix
|
|
25
27
|
* npm run doctor -- --fix-namespaces [file…] # give long-term syndicates a memory_namespace
|
|
26
28
|
* MELCHIZEDEK_AGENTS_DIR=/path npm run doctor
|
package/dist/scripts/doctor.js
CHANGED
|
@@ -11,7 +11,9 @@
|
|
|
11
11
|
* removed that runtime). Lists the tools that need an OAuth grant (an
|
|
12
12
|
* `auth: { oauth2 }` or `mcp_auth`, ADR 0112): each user's consent, or the
|
|
13
13
|
* server's own client credentials and whether their variables are set
|
|
14
|
-
* (names only).
|
|
14
|
+
* (names only). When any A2A identity or billing variable is set, a
|
|
15
|
+
* `serving` line names the A2A_AUTH mode and A2A_KEY_MODE and what the
|
|
16
|
+
* server would refuse to start on. Closes with the env vars that would
|
|
15
17
|
* unlock the most, where to get each, and the first command to try.
|
|
16
18
|
*
|
|
17
19
|
* Read-only: never edits .env, never sends a request, never prints a key
|
|
@@ -20,7 +22,7 @@
|
|
|
20
22
|
* Usage:
|
|
21
23
|
* npm run doctor
|
|
22
24
|
* npm run doctor -- --json # machine-readable
|
|
23
|
-
* npm run doctor -- --check # exit 1
|
|
25
|
+
* npm run doctor -- --check # exit 1 on a blocked syndicate, a runtime problem, or an OAuth or credential host problem
|
|
24
26
|
* npm run doctor -- --matrix # the provider × capability matrix
|
|
25
27
|
* npm run doctor -- --fix-namespaces [file…] # give long-term syndicates a memory_namespace
|
|
26
28
|
* MELCHIZEDEK_AGENTS_DIR=/path npm run doctor
|
|
@@ -28,7 +30,7 @@
|
|
|
28
30
|
import fs from 'node:fs';
|
|
29
31
|
import path from 'node:path';
|
|
30
32
|
import { loadEnv } from '../lib/loadEnv.js';
|
|
31
|
-
import { renderDoctor, runDoctor } from '../lib/doctor.js';
|
|
33
|
+
import { checkProblems, renderDoctor, runDoctor } from '../lib/doctor.js';
|
|
32
34
|
import { renderCapabilityMatrix } from '../lib/models/capabilities.js';
|
|
33
35
|
import { assignMemoryNamespace, LEGACY_MEMORY_APP_NAME } from '../lib/memory/namespace.js';
|
|
34
36
|
loadEnv();
|
|
@@ -91,5 +93,5 @@ if (json) {
|
|
|
91
93
|
else {
|
|
92
94
|
console.log(renderDoctor(result, { color: !noColor }));
|
|
93
95
|
}
|
|
94
|
-
if (check && (result.
|
|
96
|
+
if (check && checkProblems(result).length)
|
|
95
97
|
process.exit(1);
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* scripts/setup.ts — the `melchizedek-setup` bin and `npm run setup`.
|
|
4
|
+
*
|
|
5
|
+
* The onboarding command: a menu of authentication levels (no key, one
|
|
6
|
+
* provider, several, a gateway, a cloud platform, per-caller keys, caller
|
|
7
|
+
* tokens, OAuth tool grants, and an honest entry for subscription sign-ins),
|
|
8
|
+
* each with a startup guide: the variables to set (names and shapes only),
|
|
9
|
+
* the doctor command that confirms it, the shipped files that run there and
|
|
10
|
+
* the first commands to try. The levels and guides live in lib/onboarding.ts;
|
|
11
|
+
* ONBOARDING.md is generated from the same function.
|
|
12
|
+
*
|
|
13
|
+
* npx melchizedek-setup # the menu (interactive terminal)
|
|
14
|
+
* npx melchizedek-setup --auto # detect from the environment, names only
|
|
15
|
+
* npx melchizedek-setup --level gateway # one guide, by id or number
|
|
16
|
+
* npx melchizedek-setup --level 2 --write-env # also create .env from .env.example
|
|
17
|
+
* npx melchizedek-setup --list
|
|
18
|
+
* npx melchizedek-setup --markdown # ONBOARDING.md, regenerated
|
|
19
|
+
*
|
|
20
|
+
* Never prints a value. `--write-env` never overwrites `.env`, leaves every
|
|
21
|
+
* name blank, and refuses unless `git check-ignore` confirms `.env` is ignored.
|
|
22
|
+
*/
|
|
23
|
+
export declare function main(argv?: string[]): Promise<number>;
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* scripts/setup.ts — the `melchizedek-setup` bin and `npm run setup`.
|
|
4
|
+
*
|
|
5
|
+
* The onboarding command: a menu of authentication levels (no key, one
|
|
6
|
+
* provider, several, a gateway, a cloud platform, per-caller keys, caller
|
|
7
|
+
* tokens, OAuth tool grants, and an honest entry for subscription sign-ins),
|
|
8
|
+
* each with a startup guide: the variables to set (names and shapes only),
|
|
9
|
+
* the doctor command that confirms it, the shipped files that run there and
|
|
10
|
+
* the first commands to try. The levels and guides live in lib/onboarding.ts;
|
|
11
|
+
* ONBOARDING.md is generated from the same function.
|
|
12
|
+
*
|
|
13
|
+
* npx melchizedek-setup # the menu (interactive terminal)
|
|
14
|
+
* npx melchizedek-setup --auto # detect from the environment, names only
|
|
15
|
+
* npx melchizedek-setup --level gateway # one guide, by id or number
|
|
16
|
+
* npx melchizedek-setup --level 2 --write-env # also create .env from .env.example
|
|
17
|
+
* npx melchizedek-setup --list
|
|
18
|
+
* npx melchizedek-setup --markdown # ONBOARDING.md, regenerated
|
|
19
|
+
*
|
|
20
|
+
* Never prints a value. `--write-env` never overwrites `.env`, leaves every
|
|
21
|
+
* name blank, and refuses unless `git check-ignore` confirms `.env` is ignored.
|
|
22
|
+
*/
|
|
23
|
+
import { realpathSync } from 'node:fs';
|
|
24
|
+
import { createInterface } from 'node:readline/promises';
|
|
25
|
+
import { fileURLToPath, pathToFileURL } from 'node:url';
|
|
26
|
+
import { loadEnv } from '../lib/loadEnv.js';
|
|
27
|
+
import { runDoctor } from '../lib/doctor.js';
|
|
28
|
+
import { detectLevels, highestLevel, LEVELS, levelById, renderAuto, renderGuide, renderMenu, renderOnboardingDoc, writeEnvForLevel, } from '../lib/onboarding.js';
|
|
29
|
+
const USAGE = `melchizedek-setup — start from what you have
|
|
30
|
+
|
|
31
|
+
melchizedek-setup the menu of authentication levels
|
|
32
|
+
melchizedek-setup --auto detect the highest level from the environment (names only)
|
|
33
|
+
melchizedek-setup --level <id|number> print one level's startup guide
|
|
34
|
+
melchizedek-setup --list the levels
|
|
35
|
+
melchizedek-setup --markdown every guide as Markdown (ONBOARDING.md)
|
|
36
|
+
|
|
37
|
+
--write-env with --level or --auto: create .env from .env.example with the level's
|
|
38
|
+
names left blank (never overwrites; requires git to ignore .env)
|
|
39
|
+
--clone | --package spell commands for a clone or an installed package (default: detected)
|
|
40
|
+
|
|
41
|
+
Levels:
|
|
42
|
+
${renderMenu()}
|
|
43
|
+
`;
|
|
44
|
+
function pickLevel(raw) {
|
|
45
|
+
const n = Number(raw);
|
|
46
|
+
if (Number.isInteger(n) && n >= 1 && n <= LEVELS.length)
|
|
47
|
+
return LEVELS[n - 1];
|
|
48
|
+
return levelById(raw.trim());
|
|
49
|
+
}
|
|
50
|
+
function writeEnv(level) {
|
|
51
|
+
const r = writeEnvForLevel(level);
|
|
52
|
+
switch (r.status) {
|
|
53
|
+
case 'written':
|
|
54
|
+
console.log(`\n✓ wrote ${r.path} (mode 600) from .env.example${r.added.length ? `, adding blank: ${r.added.join(', ')}` : ''}. Fill in the values yourself, in your editor.`);
|
|
55
|
+
return 0;
|
|
56
|
+
case 'exists':
|
|
57
|
+
console.log(`\n· kept ${r.path}: it exists, and setup never overwrites it. Add the names above to it yourself.`);
|
|
58
|
+
return 0;
|
|
59
|
+
case 'not-ignored':
|
|
60
|
+
console.error(`\n✗ did not write .env: ${r.reason}`);
|
|
61
|
+
return 1;
|
|
62
|
+
case 'no-template':
|
|
63
|
+
console.error('\n✗ did not write .env: .env.example was not found beside the package');
|
|
64
|
+
return 1;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
export async function main(argv = process.argv.slice(2)) {
|
|
68
|
+
const args = argv.filter((a) => a !== '--');
|
|
69
|
+
const flag = (name) => {
|
|
70
|
+
const i = args.indexOf(`--${name}`);
|
|
71
|
+
return i >= 0 && i + 1 < args.length ? args[i + 1] : undefined;
|
|
72
|
+
};
|
|
73
|
+
const inPackage = fileURLToPath(import.meta.url).includes('node_modules');
|
|
74
|
+
const form = args.includes('--clone') ? 'clone' : args.includes('--package') ? 'package' : inPackage ? 'package' : 'clone';
|
|
75
|
+
if (args.includes('--help') || args.includes('-h')) {
|
|
76
|
+
console.log(USAGE);
|
|
77
|
+
return 0;
|
|
78
|
+
}
|
|
79
|
+
if (args.includes('--list')) {
|
|
80
|
+
console.log(renderMenu());
|
|
81
|
+
return 0;
|
|
82
|
+
}
|
|
83
|
+
if (args.includes('--markdown')) {
|
|
84
|
+
process.stdout.write(renderOnboardingDoc());
|
|
85
|
+
return 0;
|
|
86
|
+
}
|
|
87
|
+
let level;
|
|
88
|
+
if (args.includes('--auto')) {
|
|
89
|
+
loadEnv();
|
|
90
|
+
const result = runDoctor();
|
|
91
|
+
console.log(renderAuto(result, form));
|
|
92
|
+
if (!args.includes('--write-env'))
|
|
93
|
+
return 0;
|
|
94
|
+
return writeEnv(highestLevel(detectLevels(result)));
|
|
95
|
+
}
|
|
96
|
+
const raw = flag('level');
|
|
97
|
+
if (raw !== undefined) {
|
|
98
|
+
level = pickLevel(raw);
|
|
99
|
+
if (!level) {
|
|
100
|
+
console.error(`✗ unknown level "${raw}"\n\n${USAGE}`);
|
|
101
|
+
return 2;
|
|
102
|
+
}
|
|
103
|
+
console.log(renderGuide(level, form));
|
|
104
|
+
return args.includes('--write-env') ? writeEnv(level) : 0;
|
|
105
|
+
}
|
|
106
|
+
if (!process.stdin.isTTY || !process.stdout.isTTY) {
|
|
107
|
+
console.log(USAGE);
|
|
108
|
+
return 0;
|
|
109
|
+
}
|
|
110
|
+
// The interactive menu.
|
|
111
|
+
const rl = createInterface({ input: process.stdin, output: process.stdout });
|
|
112
|
+
try {
|
|
113
|
+
console.log(`What do you have? Pick the closest; you can come back for another.\n\n${renderMenu()}\n`);
|
|
114
|
+
const answer = (await rl.question(`Level [1-${LEVELS.length}], a = detect from my environment, q = quit: `)).trim().toLowerCase();
|
|
115
|
+
if (answer === 'q' || answer === '')
|
|
116
|
+
return 0;
|
|
117
|
+
if (answer === 'a') {
|
|
118
|
+
loadEnv();
|
|
119
|
+
console.log(`\n${renderAuto(runDoctor(), form)}`);
|
|
120
|
+
return 0;
|
|
121
|
+
}
|
|
122
|
+
level = pickLevel(answer);
|
|
123
|
+
if (!level) {
|
|
124
|
+
console.error(`✗ "${answer}" is not a level`);
|
|
125
|
+
return 2;
|
|
126
|
+
}
|
|
127
|
+
console.log(`\n${renderGuide(level, form)}\n`);
|
|
128
|
+
if (level.detectable) {
|
|
129
|
+
const write = (await rl.question('Create .env from .env.example with these names left blank? (never overwrites) [y/N]: ')).trim().toLowerCase();
|
|
130
|
+
if (write === 'y' || write === 'yes')
|
|
131
|
+
return writeEnv(level);
|
|
132
|
+
}
|
|
133
|
+
return 0;
|
|
134
|
+
}
|
|
135
|
+
finally {
|
|
136
|
+
rl.close();
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
const invokedAsMain = (() => {
|
|
140
|
+
if (!process.argv[1])
|
|
141
|
+
return false;
|
|
142
|
+
try {
|
|
143
|
+
return import.meta.url === pathToFileURL(realpathSync(process.argv[1])).href;
|
|
144
|
+
}
|
|
145
|
+
catch {
|
|
146
|
+
return false;
|
|
147
|
+
}
|
|
148
|
+
})();
|
|
149
|
+
if (invokedAsMain) {
|
|
150
|
+
main().then((code) => process.exit(code), (err) => {
|
|
151
|
+
console.error(`✗ ${err instanceof Error ? err.message : String(err)}`);
|
|
152
|
+
process.exit(1);
|
|
153
|
+
});
|
|
154
|
+
}
|
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
import { type InstallOptions } from '../lib/skills.ts';
|
|
3
3
|
export declare function parseArgs(argv: string[]): {
|
|
4
4
|
command: string;
|
|
5
|
-
opts: InstallOptions
|
|
5
|
+
opts: InstallOptions & {
|
|
6
|
+
agentsMd?: boolean;
|
|
7
|
+
};
|
|
6
8
|
};
|
|
7
9
|
export declare function main(argv?: string[]): number;
|
|
@@ -16,6 +16,7 @@
|
|
|
16
16
|
* melchizedek-skills install --only melchizedek,melchizedek-scribe
|
|
17
17
|
* melchizedek-skills install --force # overwrite files that differ
|
|
18
18
|
* melchizedek-skills install --dry-run
|
|
19
|
+
* melchizedek-skills install --agents-md # also point AGENTS.md at the skills
|
|
19
20
|
*
|
|
20
21
|
* Clone equivalent: npm run skills:install -- <same flags>.
|
|
21
22
|
* Nothing is read from the network; nothing is written outside the chosen
|
|
@@ -23,12 +24,12 @@
|
|
|
23
24
|
*/
|
|
24
25
|
import { realpathSync } from 'node:fs';
|
|
25
26
|
import { pathToFileURL } from 'node:url';
|
|
26
|
-
import { DEFAULT_TARGETS, SKILL_TARGETS, destinationsFor, installSkills, listSkills, } from '../lib/skills.js';
|
|
27
|
+
import { DEFAULT_TARGETS, SKILL_TARGETS, destinationsFor, installSkills, listSkills, writeAgentsMdPointer, } from '../lib/skills.js';
|
|
27
28
|
const USAGE = `melchizedek-skills — install the Melchizedek agent-skills suite into your coding agent
|
|
28
29
|
|
|
29
30
|
melchizedek-skills list
|
|
30
31
|
melchizedek-skills paths
|
|
31
|
-
melchizedek-skills install [--for <targets>] [--global] [--dir <path>] [--only <skills>] [--force] [--dry-run]
|
|
32
|
+
melchizedek-skills install [--for <targets>] [--global] [--dir <path>] [--only <skills>] [--force] [--dry-run] [--agents-md]
|
|
32
33
|
|
|
33
34
|
--for comma list of: ${Object.keys(SKILL_TARGETS).join(', ')}, all (default: ${DEFAULT_TARGETS.join(',')})
|
|
34
35
|
--global write to the home-directory locations instead of this project's
|
|
@@ -36,6 +37,10 @@ const USAGE = `melchizedek-skills — install the Melchizedek agent-skills suite
|
|
|
36
37
|
--only comma list of skill names (default: every skill)
|
|
37
38
|
--force overwrite a file that exists with different content
|
|
38
39
|
--dry-run print what would be written, write nothing
|
|
40
|
+
--agents-md also write a pointer block into ./AGENTS.md (created if absent; only the
|
|
41
|
+
block between its markers is ever rewritten). Project installs only.
|
|
42
|
+
|
|
43
|
+
Onboarding starts with the melchizedek-onboard skill, or: npx melchizedek-setup
|
|
39
44
|
`;
|
|
40
45
|
export function parseArgs(argv) {
|
|
41
46
|
const [command = 'help', ...rest] = argv.filter((a) => a !== '--');
|
|
@@ -62,6 +67,8 @@ export function parseArgs(argv) {
|
|
|
62
67
|
opts.force = true;
|
|
63
68
|
else if (a === '--dry-run')
|
|
64
69
|
opts.dryRun = true;
|
|
70
|
+
else if (a === '--agents-md')
|
|
71
|
+
opts.agentsMd = true;
|
|
65
72
|
else if (a === '-h' || a === '--help')
|
|
66
73
|
return { command: 'help', opts };
|
|
67
74
|
else
|
|
@@ -117,6 +124,14 @@ export function main(argv = process.argv.slice(2)) {
|
|
|
117
124
|
for (const f of r.skipped)
|
|
118
125
|
console.log(` ! ${f} exists with different content (use --force to overwrite)`);
|
|
119
126
|
}
|
|
127
|
+
if (opts.agentsMd) {
|
|
128
|
+
if (opts.global || opts.dir) {
|
|
129
|
+
console.error('✗ --agents-md writes ./AGENTS.md beside a project install; it is not used with --global or --dir');
|
|
130
|
+
return 2;
|
|
131
|
+
}
|
|
132
|
+
const r = writeAgentsMdPointer(process.cwd(), destinationsFor(opts), { dryRun: opts.dryRun });
|
|
133
|
+
console.log(`${opts.dryRun ? '○' : '✓'} ${r.path}: ${r.status}${opts.dryRun ? ' (dry run)' : ''}`);
|
|
134
|
+
}
|
|
120
135
|
if (!opts.dir) {
|
|
121
136
|
const sample = destinationsFor(opts);
|
|
122
137
|
console.log(`\nOpen your coding agent in ${opts.global ? 'any project' : 'this project'} and ask it about a Melchizedek syndicate; the skills load from ${sample.map((d) => d).join(' and ')}.`);
|
|
@@ -19,8 +19,18 @@
|
|
|
19
19
|
* generateContentConfig.thinkingConfig / reasoningEffort → reasoning:, ONLY
|
|
20
20
|
* when the engine reads the same ReasoningSetting before and after for
|
|
21
21
|
* the agent's model (reasoningOf over the old config equals reasoningOf
|
|
22
|
-
* over what reasoningConfig makes of the new key).
|
|
23
|
-
*
|
|
22
|
+
* over what reasoningConfig makes of the new key). `xhigh` and `max`
|
|
23
|
+
* included (ADR 0117).
|
|
24
|
+
* generateContentConfig.thinkingConfig.includeThoughts → dropped: the
|
|
25
|
+
* engine reads it nowhere, and the Gemini adapter asks for the thought
|
|
26
|
+
* trace itself whenever reasoning is not `none` (ADR 0117); `true` gets a
|
|
27
|
+
* note saying so.
|
|
28
|
+
* generateContentConfig.toolConfig → tool_choice: (ADR 0117), when it holds
|
|
29
|
+
* only functionCallingConfig (mode AUTO, NONE or ANY, and
|
|
30
|
+
* allowedFunctionNames) and includeServerSideToolInvocations, which the
|
|
31
|
+
* compiler sets on every agent: AUTO is `auto`, NONE `none`, ANY with
|
|
32
|
+
* one name `{ name }`, and ANY with none or several `required`, which is
|
|
33
|
+
* what the engine reads (genaiMapping toolChoiceOf) either way.
|
|
24
34
|
*
|
|
25
35
|
* Anything else stays under generateContentConfig with a note naming its key
|
|
26
36
|
* path (never its value); an emptied generateContentConfig is removed. An
|
|
@@ -19,8 +19,18 @@
|
|
|
19
19
|
* generateContentConfig.thinkingConfig / reasoningEffort → reasoning:, ONLY
|
|
20
20
|
* when the engine reads the same ReasoningSetting before and after for
|
|
21
21
|
* the agent's model (reasoningOf over the old config equals reasoningOf
|
|
22
|
-
* over what reasoningConfig makes of the new key).
|
|
23
|
-
*
|
|
22
|
+
* over what reasoningConfig makes of the new key). `xhigh` and `max`
|
|
23
|
+
* included (ADR 0117).
|
|
24
|
+
* generateContentConfig.thinkingConfig.includeThoughts → dropped: the
|
|
25
|
+
* engine reads it nowhere, and the Gemini adapter asks for the thought
|
|
26
|
+
* trace itself whenever reasoning is not `none` (ADR 0117); `true` gets a
|
|
27
|
+
* note saying so.
|
|
28
|
+
* generateContentConfig.toolConfig → tool_choice: (ADR 0117), when it holds
|
|
29
|
+
* only functionCallingConfig (mode AUTO, NONE or ANY, and
|
|
30
|
+
* allowedFunctionNames) and includeServerSideToolInvocations, which the
|
|
31
|
+
* compiler sets on every agent: AUTO is `auto`, NONE `none`, ANY with
|
|
32
|
+
* one name `{ name }`, and ANY with none or several `required`, which is
|
|
33
|
+
* what the engine reads (genaiMapping toolChoiceOf) either way.
|
|
24
34
|
*
|
|
25
35
|
* Anything else stays under generateContentConfig with a note naming its key
|
|
26
36
|
* path (never its value); an emptied generateContentConfig is removed. An
|
|
@@ -41,7 +51,8 @@ import { join } from 'node:path';
|
|
|
41
51
|
import { pathToFileURL } from 'node:url';
|
|
42
52
|
import { isDeepStrictEqual } from 'node:util';
|
|
43
53
|
import { isMap, isPair, isScalar, isSeq, parseDocument } from 'yaml';
|
|
44
|
-
import {
|
|
54
|
+
import { functionCallingConfigOf } from '../lib/agentDialect.js';
|
|
55
|
+
import { reasoningOf, toolChoiceOf } from '../lib/models/genaiMapping.js';
|
|
45
56
|
import { reasoningConfig } from '../lib/models/reasoning.js';
|
|
46
57
|
/** generateContentConfig keys with a `sampling:` form, and the check its value must pass. */
|
|
47
58
|
const SAMPLING = new Map([
|
|
@@ -51,9 +62,11 @@ const SAMPLING = new Map([
|
|
|
51
62
|
['stopSequences', { key: 'stop', ok: (v) => Array.isArray(v) && v.length > 0 && v.every((s) => typeof s === 'string') }],
|
|
52
63
|
]);
|
|
53
64
|
const OUTPUT_MIMES = new Set(['application/json', 'text/plain']);
|
|
54
|
-
const THINKING_LEVEL = new Map([['MINIMAL', 'none'], ['LOW', 'low'], ['MEDIUM', 'medium'], ['HIGH', 'high']]);
|
|
55
|
-
const EFFORT_WORD = new Map([['none', 'none'], ['minimal', 'none'], ['low', 'low'], ['medium', 'medium'], ['high', 'high']]);
|
|
56
65
|
const THINKING_KEYS = new Set(['thinkingLevel', 'thinkingBudget', 'includeThoughts']);
|
|
66
|
+
/** toolConfig keys the codemod can account for: the choice, and the flag the compiler sets on every agent. */
|
|
67
|
+
const TOOL_CONFIG_KEYS = new Set(['functionCallingConfig', 'includeServerSideToolInvocations']);
|
|
68
|
+
const FUNCTION_CALLING_KEYS = new Set(['mode', 'allowedFunctionNames']);
|
|
69
|
+
const FUNCTION_CALLING_MODES = new Set(['AUTO', 'NONE', 'ANY']);
|
|
57
70
|
// ── The source, by line ──────────────────────────────────────────────────────
|
|
58
71
|
class Source {
|
|
59
72
|
text;
|
|
@@ -256,11 +269,17 @@ function planAgent(doc, src, map, path, notes) {
|
|
|
256
269
|
const re = chunks.find((c) => c.name === 'reasoningEffort');
|
|
257
270
|
if (tc || re)
|
|
258
271
|
planThinking(plan, map, tc, re, valueOf, notes);
|
|
272
|
+
// Tool choice.
|
|
273
|
+
const toolConfig = chunks.find((c) => c.name === 'toolConfig');
|
|
274
|
+
if (toolConfig)
|
|
275
|
+
planToolChoice(plan, map, toolConfig, valueOf(toolConfig), notes);
|
|
259
276
|
// Leftovers: everything not moved, converted or dropped.
|
|
260
277
|
const handled = new Set([...plan.sampling, ...(plan.mime ? [plan.mime] : []), ...(plan.reasoning?.remove ?? [])]);
|
|
261
278
|
if (plan.dropInclude?.empties)
|
|
262
279
|
handled.add(plan.dropInclude.tc);
|
|
263
|
-
|
|
280
|
+
if (plan.toolChoice)
|
|
281
|
+
handled.add(plan.toolChoice.chunk);
|
|
282
|
+
const noted = new Set(['thinkingConfig', 'reasoningEffort', 'responseMimeType', 'toolConfig', ...SAMPLING.keys()]);
|
|
264
283
|
for (const c of chunks) {
|
|
265
284
|
if (handled.has(c) || noted.has(c.name))
|
|
266
285
|
continue;
|
|
@@ -268,27 +287,74 @@ function planAgent(doc, src, map, path, notes) {
|
|
|
268
287
|
}
|
|
269
288
|
}
|
|
270
289
|
}
|
|
271
|
-
const changes = plan.sampling.length > 0 || plan.mime || plan.schema || plan.reasoning || plan.dropInclude;
|
|
290
|
+
const changes = plan.sampling.length > 0 || plan.mime || plan.schema || plan.reasoning || plan.dropInclude || plan.toolChoice;
|
|
272
291
|
return changes ? plan : undefined;
|
|
273
292
|
}
|
|
293
|
+
/**
|
|
294
|
+
* toolConfig → tool_choice, when the engine reads the same ToolChoice before
|
|
295
|
+
* and after (genaiMapping toolChoiceOf) and nothing else in it would be lost.
|
|
296
|
+
*/
|
|
297
|
+
function planToolChoice(plan, map, chunk, value, notes) {
|
|
298
|
+
const where = `${plan.path}.generateContentConfig.toolConfig`;
|
|
299
|
+
const leave = (why) => {
|
|
300
|
+
notes.push(`${where}: ${why}; left in place`);
|
|
301
|
+
};
|
|
302
|
+
if (findPair(map, 'tool_choice'))
|
|
303
|
+
return leave(`${plan.path}.tool_choice is already set (the loader refuses both)`);
|
|
304
|
+
if (!value || typeof value !== 'object' || Array.isArray(value))
|
|
305
|
+
return leave('not a mapping');
|
|
306
|
+
const tc = value;
|
|
307
|
+
if (Object.keys(tc).some((k) => !TOOL_CONFIG_KEYS.has(k)))
|
|
308
|
+
return leave('it holds a key with no v2 form');
|
|
309
|
+
const fcc = tc.functionCallingConfig;
|
|
310
|
+
if (fcc !== undefined) {
|
|
311
|
+
if (!fcc || typeof fcc !== 'object' || Array.isArray(fcc))
|
|
312
|
+
return leave('functionCallingConfig is not a mapping');
|
|
313
|
+
const f = fcc;
|
|
314
|
+
if (Object.keys(f).some((k) => !FUNCTION_CALLING_KEYS.has(k)))
|
|
315
|
+
return leave('functionCallingConfig holds a key with no tool_choice form');
|
|
316
|
+
if (f.mode === 'VALIDATED')
|
|
317
|
+
return leave('mode VALIDATED (strict tool schemas) has no tool_choice form');
|
|
318
|
+
if (!FUNCTION_CALLING_MODES.has(f.mode))
|
|
319
|
+
return leave('its mode is not AUTO, NONE or ANY');
|
|
320
|
+
const names = f.allowedFunctionNames;
|
|
321
|
+
if (names !== undefined && !(Array.isArray(names) && names.every((n) => typeof n === 'string')))
|
|
322
|
+
return leave('allowedFunctionNames is not a list of names');
|
|
323
|
+
if (f.mode === 'ANY' && Array.isArray(names) && names.length > 1) {
|
|
324
|
+
notes.push(`${where}.functionCallingConfig.allowedFunctionNames: several names, which the engine sends as required (any tool); tool_choice: required says the same`);
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
// What the engine reads today is the v2 setting; the proof is that the v2
|
|
328
|
+
// key's engine form reads back the same.
|
|
329
|
+
const before = toolChoiceOf({ toolConfig: tc });
|
|
330
|
+
const setting = before.toolChoice ?? 'auto';
|
|
331
|
+
const after = toolChoiceOf({ toolConfig: { functionCallingConfig: functionCallingConfigOf(setting) } });
|
|
332
|
+
if (!isDeepStrictEqual(before, after))
|
|
333
|
+
return leave('tool_choice: would change what the engine reads');
|
|
334
|
+
plan.toolChoice = { setting, chunk };
|
|
335
|
+
}
|
|
274
336
|
function planThinking(plan, map, tc, re, valueOf, notes) {
|
|
275
337
|
const gccPath = `${plan.path}.generateContentConfig`;
|
|
276
338
|
const where = [tc, re].filter((c) => !!c).map((c) => `${gccPath}.${c.name}`).join(', ');
|
|
277
339
|
const tcValue = tc ? valueOf(tc) : undefined;
|
|
278
340
|
const tcObject = tcValue && typeof tcValue === 'object' && !Array.isArray(tcValue) ? tcValue : undefined;
|
|
279
341
|
const model = scalarString(map, 'model');
|
|
280
|
-
// includeThoughts
|
|
281
|
-
//
|
|
342
|
+
// includeThoughts is read by nothing: the Gemini adapter asks for the
|
|
343
|
+
// thought trace whenever reasoning is not `none` (ADR 0117). Drop it from
|
|
344
|
+
// a block thinkingConfig whatever else happens to the thinking keys.
|
|
282
345
|
const incPair = tc && isMap(tc.pair.value) && !tc.pair.value.flow ? findPair(tc.pair.value, 'includeThoughts') : undefined;
|
|
283
|
-
const
|
|
346
|
+
const incValue = incPair && isScalar(incPair.value) ? incPair.value.value : undefined;
|
|
347
|
+
const incBool = typeof incValue === 'boolean';
|
|
348
|
+
if (incValue === true) {
|
|
349
|
+
notes.push(`${gccPath}.thinkingConfig.includeThoughts: read by nothing (the Gemini adapter asks for the thought trace whenever reasoning is not none); dropped`);
|
|
350
|
+
}
|
|
351
|
+
const dropInclude = () => {
|
|
352
|
+
if (tc && incBool)
|
|
353
|
+
plan.dropInclude = { tc, inc: incPair, empties: tc.pair.value.items.length === 1 };
|
|
354
|
+
};
|
|
284
355
|
const leave = (why) => {
|
|
285
356
|
notes.push(`${where}: ${why}; left in place`);
|
|
286
|
-
|
|
287
|
-
const tcMap = tc.pair.value;
|
|
288
|
-
plan.dropInclude = { tc, inc: incPair, empties: tcMap.items.length === 1 };
|
|
289
|
-
}
|
|
290
|
-
if (tcObject?.includeThoughts === true)
|
|
291
|
-
notes.push(`${gccPath}.thinkingConfig.includeThoughts: no v2 form; left in place`);
|
|
357
|
+
dropInclude();
|
|
292
358
|
};
|
|
293
359
|
if (findPair(map, 'reasoning'))
|
|
294
360
|
return leave(`${plan.path}.reasoning is already set (the loader refuses both)`);
|
|
@@ -298,35 +364,39 @@ function planThinking(plan, map, tc, re, valueOf, notes) {
|
|
|
298
364
|
return leave('thinkingConfig is not a mapping');
|
|
299
365
|
if (tcObject && Object.keys(tcObject).some((k) => !THINKING_KEYS.has(k)))
|
|
300
366
|
return leave('thinkingConfig holds a key with no reasoning: form');
|
|
301
|
-
if (tcObject && tcObject.includeThoughts !== undefined && tcObject.includeThoughts !== false)
|
|
302
|
-
return leave('includeThoughts has no reasoning: form');
|
|
303
367
|
const v1 = {};
|
|
304
368
|
if (tc)
|
|
305
369
|
v1.thinkingConfig = tcValue;
|
|
306
370
|
if (re)
|
|
307
371
|
v1.reasoningEffort = valueOf(re);
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
const budget = tcObject?.thinkingBudget;
|
|
311
|
-
if (level)
|
|
312
|
-
candidate = level;
|
|
313
|
-
else if (typeof budget === 'number' && Number.isInteger(budget) && budget >= 0)
|
|
314
|
-
candidate = { budget_tokens: budget };
|
|
315
|
-
else if (EFFORT_WORD.has(v1.reasoningEffort))
|
|
316
|
-
candidate = EFFORT_WORD.get(v1.reasoningEffort);
|
|
317
|
-
if (candidate === undefined)
|
|
318
|
-
return leave('no reasoning: setting reads the same');
|
|
372
|
+
// The setting is what the engine reads today; it converts when the v2
|
|
373
|
+
// key's engine form reads back the same for the agent's model.
|
|
319
374
|
const before = reasoningOf(v1);
|
|
320
|
-
|
|
375
|
+
if (before === undefined) {
|
|
376
|
+
// A thinkingConfig holding includeThoughts alone: nothing to convert, and nothing left.
|
|
377
|
+
if (!re && tcObject && Object.keys(tcObject).every((k) => k === 'includeThoughts'))
|
|
378
|
+
return dropInclude();
|
|
379
|
+
return leave('no reasoning: setting reads the same');
|
|
380
|
+
}
|
|
381
|
+
const after = reasoningOf(reasoningConfig(model, before));
|
|
321
382
|
if (!isDeepStrictEqual(before, after))
|
|
322
383
|
return leave(`reasoning: would change what the engine reads for ${providerWord(model)}`);
|
|
323
|
-
plan.reasoning = { setting:
|
|
384
|
+
plan.reasoning = { setting: before, remove: [tc, re].filter((c) => !!c) };
|
|
324
385
|
}
|
|
325
386
|
/** A model family word for a note: never the id's value beyond its prefix. */
|
|
326
387
|
function providerWord(model) {
|
|
327
388
|
return model.startsWith('gemini-') ? 'this Gemini model' : 'this model';
|
|
328
389
|
}
|
|
329
390
|
const reasoningText = (s) => (typeof s === 'string' ? s : `{ budget_tokens: ${s.budget_tokens} }`);
|
|
391
|
+
/** A tool name YAML reads back as that string unquoted: an identifier that is not a YAML keyword. */
|
|
392
|
+
const PLAIN_NAME = /^[A-Za-z_][A-Za-z0-9_-]*$/;
|
|
393
|
+
const YAML_WORDS = new Set(['true', 'false', 'null', 'yes', 'no', 'on', 'off', 'y', 'n']);
|
|
394
|
+
const toolChoiceText = (s) => {
|
|
395
|
+
if (typeof s === 'string')
|
|
396
|
+
return s;
|
|
397
|
+
const plain = PLAIN_NAME.test(s.name) && !YAML_WORDS.has(s.name.toLowerCase());
|
|
398
|
+
return `{ name: ${plain ? s.name : JSON.stringify(s.name)} }`;
|
|
399
|
+
};
|
|
330
400
|
function chunkLines(src, c) {
|
|
331
401
|
return src.lines.slice(c.from, c.to + 1);
|
|
332
402
|
}
|
|
@@ -343,12 +413,14 @@ function renderGcc(src, plan) {
|
|
|
343
413
|
const g = plan.gcc;
|
|
344
414
|
if (!g)
|
|
345
415
|
return undefined;
|
|
346
|
-
if (!(plan.sampling.length || plan.mime || plan.reasoning || plan.dropInclude))
|
|
416
|
+
if (!(plan.sampling.length || plan.mime || plan.reasoning || plan.dropInclude || plan.toolChoice))
|
|
347
417
|
return undefined;
|
|
348
418
|
const pad = ' '.repeat(g.indent);
|
|
349
419
|
const removed = new Set([...plan.sampling, ...(plan.mime ? [plan.mime] : []), ...(plan.reasoning?.remove ?? [])]);
|
|
350
420
|
if (plan.dropInclude?.empties)
|
|
351
421
|
removed.add(plan.dropInclude.tc);
|
|
422
|
+
if (plan.toolChoice)
|
|
423
|
+
removed.add(plan.toolChoice.chunk);
|
|
352
424
|
const leftovers = g.chunks.filter((c) => !removed.has(c));
|
|
353
425
|
const out = [];
|
|
354
426
|
if (leftovers.length === 0) {
|
|
@@ -367,6 +439,12 @@ function renderGcc(src, plan) {
|
|
|
367
439
|
out.push(pad + comment);
|
|
368
440
|
out.push(`${pad}reasoning: ${reasoningText(plan.reasoning.setting)}`);
|
|
369
441
|
}
|
|
442
|
+
if (plan.toolChoice) {
|
|
443
|
+
const c = plan.toolChoice.chunk;
|
|
444
|
+
for (const comment of commentsIn(src, c.from, c.to, c.pair))
|
|
445
|
+
out.push(pad + comment);
|
|
446
|
+
out.push(`${pad}tool_choice: ${toolChoiceText(plan.toolChoice.setting)}`);
|
|
447
|
+
}
|
|
370
448
|
if (plan.mime && !plan.schema) {
|
|
371
449
|
out.push(`${pad}output:`);
|
|
372
450
|
out.push(...renamed(src, plan.mime, 'mime'));
|
|
@@ -444,6 +522,10 @@ function expectAgent(agent, plan) {
|
|
|
444
522
|
delete gcc[c.name];
|
|
445
523
|
agent.reasoning = plan.reasoning.setting;
|
|
446
524
|
}
|
|
525
|
+
if (plan.toolChoice) {
|
|
526
|
+
delete gcc.toolConfig;
|
|
527
|
+
agent.tool_choice = plan.toolChoice.setting;
|
|
528
|
+
}
|
|
447
529
|
if (plan.dropInclude) {
|
|
448
530
|
const tc = gcc.thinkingConfig;
|
|
449
531
|
delete tc.includeThoughts;
|
|
@@ -522,7 +604,7 @@ function yamlFiles(path) {
|
|
|
522
604
|
}
|
|
523
605
|
const USAGE = `usage: yaml_codemod [--check] <file|dir>...
|
|
524
606
|
Rewrites agent v1 spellings (generateContentConfig, outputSchema) into the
|
|
525
|
-
v2 keys (sampling, output, reasoning), in place. A directory means every
|
|
607
|
+
v2 keys (sampling, output, reasoning, tool_choice), in place. A directory means every
|
|
526
608
|
*.yaml below it. --check writes nothing and exits 1 if any file would change.`;
|
|
527
609
|
export function main(argv) {
|
|
528
610
|
const check = argv.includes('--check');
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "melchizedek-agents",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.2.0",
|
|
4
4
|
"description": "A multi-model, multi-agent orchestration framework — YAML-defined syndicates on the engine's own agent loop, Supabase or Postgres session persistence, pgvector long-term memory. Companion repo to the lyceumagents.com curriculum.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -54,6 +54,7 @@
|
|
|
54
54
|
"melchizedek-worker": "./dist/scripts/assistant_worker.js",
|
|
55
55
|
"melchizedek-db": "./dist/scripts/db.js",
|
|
56
56
|
"melchizedek-init": "./dist/scripts/init.js",
|
|
57
|
+
"melchizedek-setup": "./dist/scripts/setup.js",
|
|
57
58
|
"melchizedek-registry": "./dist/scripts/registry.js",
|
|
58
59
|
"melchizedek-codemod": "./dist/scripts/yaml_codemod.js"
|
|
59
60
|
},
|
|
@@ -69,6 +70,7 @@
|
|
|
69
70
|
".env.example",
|
|
70
71
|
"CHANGELOG.md",
|
|
71
72
|
"QUICKSTART.md",
|
|
73
|
+
"ONBOARDING.md",
|
|
72
74
|
"DOCUMENTATION.md",
|
|
73
75
|
"AGENT_SETUP.md",
|
|
74
76
|
"skills"
|
|
@@ -117,6 +119,7 @@
|
|
|
117
119
|
"yaml:codemod": "node --disable-warning=DEP0040 --experimental-strip-types scripts/yaml_codemod.ts",
|
|
118
120
|
"start:a2a": "node --disable-warning=DEP0040 --experimental-strip-types scripts/a2a_server.ts",
|
|
119
121
|
"test": "node --disable-warning=DEP0040 --experimental-strip-types --test tests/**/*.test.ts",
|
|
122
|
+
"setup": "node --disable-warning=DEP0040 --experimental-strip-types scripts/setup.ts",
|
|
120
123
|
"init": "node --disable-warning=DEP0040 --experimental-strip-types scripts/init.ts",
|
|
121
124
|
"db": "node --disable-warning=DEP0040 --experimental-strip-types scripts/db.ts",
|
|
122
125
|
"registry": "node --disable-warning=DEP0040 --experimental-strip-types scripts/registry.ts",
|
package/skills/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
## What this is
|
|
4
4
|
|
|
5
|
-
This directory contains a suite of
|
|
5
|
+
This directory contains a suite of eleven Agent Skills built to the open SKILL.md standard: one directory per skill, a SKILL.md file with `name` and `description` frontmatter, and optional supporting files. The skills teach a coding agent how to onboard a person from the credentials they have, and how to find, run, author, serve, remember with, and write with Melchizedek syndicates. They ship in the npm package melchizedek-agents and in the public repository, inside `skills/`.
|
|
6
6
|
|
|
7
7
|
## The skills
|
|
8
8
|
|
|
@@ -13,6 +13,14 @@ This directory contains a suite of six Agent Skills built to the open SKILL.md s
|
|
|
13
13
|
- `melchizedek-models`: Teaches model ids and providers, keys, keyless Ollama, the gateway fallback, per-agent settings, and the errors.
|
|
14
14
|
- `melchizedek-scribe`: Teaches writing documents from a brief with the Scribe syndicate.
|
|
15
15
|
|
|
16
|
+
Five onboarding skills route a person by what they have and walk the startup guide for it (`npx melchizedek-setup --level <id>` prints each guide):
|
|
17
|
+
|
|
18
|
+
- `melchizedek-onboard`: The triage. Asks what the person has and routes to one of nine authentication levels and the skill below that owns it.
|
|
19
|
+
- `melchizedek-onboard-local`: No key: Ollama and the keyless syndicates.
|
|
20
|
+
- `melchizedek-onboard-keys`: One provider's key, several, a gateway key, and the honest answer for a ChatGPT / Codex, Claude.ai or Gemini CLI sign-in.
|
|
21
|
+
- `melchizedek-onboard-cloud`: Vertex AI, Amazon Bedrock and Azure OpenAI credentials.
|
|
22
|
+
- `melchizedek-onboard-serve`: Serving to others: per-caller keys (BYOK), caller identities (`A2A_AUTH`), and OAuth tool grants.
|
|
23
|
+
|
|
16
24
|
## Install
|
|
17
25
|
|
|
18
26
|
Install the skills using any of three methods.
|
|
@@ -37,6 +45,7 @@ The command accepts these flags:
|
|
|
37
45
|
- `--only <names>` installs a subset.
|
|
38
46
|
- `--force` overwrites a file that differs.
|
|
39
47
|
- `--dry-run` prints without writing.
|
|
48
|
+
- `--agents-md` also writes a pointer block into the project's `AGENTS.md` (created when absent; only the block between its markers is ever rewritten).
|
|
40
49
|
|
|
41
50
|
You can inspect target paths and available skills:
|
|
42
51
|
|
|
@@ -69,6 +78,6 @@ Install by hand by copying any `skills/<name>/` directory into a target location
|
|
|
69
78
|
|
|
70
79
|
## How the prose was written
|
|
71
80
|
|
|
72
|
-
The Scribe syndicate (`config/agents/examples/scribe.yaml`, a Gemini agent that writes a document from a technical brief and audits it against the brief) wrote
|
|
81
|
+
The five onboarding skills are short procedures written by hand: they print their facts from `melchizedek-setup` instead of restating them, so the facts live in one place (`lib/onboarding.ts`). The Scribe syndicate (`config/agents/examples/scribe.yaml`, a Gemini agent that writes a document from a technical brief and audits it against the brief) wrote every other SKILL.md body from one brief per skill. A person then reviewed each file. The briefs carry the facts; the Scribe carries the voice. To change a skill, change the facts and rerun with the melchizedek-scribe skill.
|
|
73
82
|
|
|
74
83
|
The suite shares the MIT license of the package.
|