create-metamynd-agent 0.10.3 → 0.10.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +8 -2
- package/index.mjs +49 -38
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -104,7 +104,11 @@ Answer a few prompts (API, owner email/password, agent name, scope, per-transact
|
|
|
104
104
|
|
|
105
105
|
```
|
|
106
106
|
my-agent/
|
|
107
|
-
├─ agent.metamynd.json # portable guard config — HOLDS THE AGENT SECRET KEY (gitignored)
|
|
107
|
+
├─ agent.metamynd.json # portable guard config — HOLDS THE AGENT SECRET KEY (gitignored). This
|
|
108
|
+
│ # is the freshly-minted key from THIS scaffold, not a re-download — the
|
|
109
|
+
│ # dashboard's own "Redownload config" for an EXISTING agent never re-issues
|
|
110
|
+
│ # the key into a downloaded file (it's excluded there by design). --byok /
|
|
111
|
+
│ # --daemon-socket instead keep the key off this CLI's process entirely.
|
|
108
112
|
├─ index.mjs # runnable example: signs + calls ./gateway; guardTool() here is a
|
|
109
113
|
│ # fast local pre-check, NOT the enforcement boundary
|
|
110
114
|
├─ package.json # depends on @metamynd/agentsafe-guard
|
|
@@ -220,10 +224,12 @@ METAMYND_PASSWORD='…' npx create-metamynd-agent --yes …
|
|
|
220
224
|
| Flag | Env | Default |
|
|
221
225
|
|---|---|---|
|
|
222
226
|
| `--harness` | — | off (no login/KYB/network at all; free local governance — see above) |
|
|
227
|
+
| `--gateway` | — | off — `--harness` only; ALSO scaffold a second local process (still zero network, zero account) that independently re-verifies every request via the real `@metamynd/agentsafe-mcp-guard`. Does not close nonce replay/cumulative spend — see the generated `harness-gateway/README.md#--gateway`. |
|
|
223
228
|
| `--sandbox` | — | off (skips login/KYB; shared sandbox agent, still hosted) |
|
|
224
229
|
| `--config <file>` | — | a JSON policy file — see [Policy config file](#policy-config-file---config) |
|
|
225
230
|
| `--no-gateway` | — | off — hosted flow only; skips the default separate tool gateway (see above) |
|
|
226
|
-
| `--gateway-port <n>` | — | `4401` — hosted flow
|
|
231
|
+
| `--gateway-port <n>` | — | `4401` — hosted flow or `--harness --gateway`, the gateway process's port |
|
|
232
|
+
| `--force`, `-f` | — | off — scaffold into a non-empty directory, overwriting existing files |
|
|
227
233
|
| `--port <n>` | — | `4400` — `--harness` only, the local dashboard's port |
|
|
228
234
|
| `--api <url>` | `METAMYND_API` | `https://metamynd.ai/api/v1` |
|
|
229
235
|
| `--email <email>` | `METAMYND_EMAIL` | — (required) |
|
package/index.mjs
CHANGED
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
// npx create-metamynd-agent
|
|
15
15
|
// npx create-metamynd-agent --api http://localhost:9926/api/v1 --email you@x.com \
|
|
16
16
|
// --name "Support Bot" --scope flight-purchase --per-txn-max 500 --out ./support-bot --yes
|
|
17
|
-
import { readFileSync, writeFileSync, mkdirSync, existsSync, readdirSync } from 'node:fs';
|
|
17
|
+
import { readFileSync, writeFileSync, mkdirSync, existsSync, readdirSync, chmodSync } from 'node:fs';
|
|
18
18
|
import { join, resolve } from 'node:path';
|
|
19
19
|
import readline from 'node:readline';
|
|
20
20
|
import crypto from 'node:crypto';
|
|
@@ -71,7 +71,10 @@ const GATEWAY_PKG = '@metamynd/agentsafe-http-gateway';
|
|
|
71
71
|
// is the actual fix: requires amount/merchant specifically, whenever the signature names a real
|
|
72
72
|
// value for them. Re-tested live and closed same day; ^0.3.0 here would still resolve to the
|
|
73
73
|
// broken version.
|
|
74
|
-
|
|
74
|
+
// 0.5.0 adds the OPTIONAL Credential Vault `resolveCredential` hook on createHttpGateway (Module
|
|
75
|
+
// G) — additive and backward-compatible (every existing consumer sees zero behavior change), but
|
|
76
|
+
// the floor must still cover the real current version per this repo's own package-version check.
|
|
77
|
+
const GATEWAY_VERSION = '^0.5.0';
|
|
75
78
|
const DEFAULT_API = 'https://metamynd.ai/api/v1';
|
|
76
79
|
const DEFAULT_GATEWAY_PORT = 4401; // distinct from --harness's dashboard (4400)
|
|
77
80
|
|
|
@@ -438,7 +441,7 @@ async function apiPost(base, path, body, token) {
|
|
|
438
441
|
* it — the same shape of gap --harness's README documents. See exampleIndex() below, which is
|
|
439
442
|
* what the real (non-sandbox) flow scaffolds by default instead.
|
|
440
443
|
*/
|
|
441
|
-
function exampleIndexNoGateway(scope, perTxnMax) {
|
|
444
|
+
function exampleIndexNoGateway(scope, perTxnMax, currency, merchant) {
|
|
442
445
|
const under = Math.max(1, Math.round(perTxnMax * 0.5));
|
|
443
446
|
const over = Math.round(perTxnMax + 100);
|
|
444
447
|
return `// index.mjs — your agent, governed by MetaMynd/AgentSafe.
|
|
@@ -464,7 +467,7 @@ const gatedBookFlight = guard.guardTool(
|
|
|
464
467
|
bookFlight,
|
|
465
468
|
(a) => ({ // map tool args → gate inputs
|
|
466
469
|
amount: a.amount,
|
|
467
|
-
currency: '
|
|
470
|
+
currency: '${currency}',
|
|
468
471
|
merchant: a.merchant,
|
|
469
472
|
context: { tool: 'book-flight', riskLevel: a.riskLevel ?? 'low' },
|
|
470
473
|
}),
|
|
@@ -481,7 +484,7 @@ const gatedRaiseOwnLimit = guard.guardTool(
|
|
|
481
484
|
raiseOwnLimit,
|
|
482
485
|
(a) => ({
|
|
483
486
|
amount: a.amount,
|
|
484
|
-
currency: '
|
|
487
|
+
currency: '${currency}',
|
|
485
488
|
merchant: a.merchant,
|
|
486
489
|
context: { tool: 'permissions-update' },
|
|
487
490
|
}),
|
|
@@ -494,7 +497,7 @@ const rule = (n) => ' ' + '-'.repeat(n);
|
|
|
494
497
|
// Plain-English meaning for the reason codes this demo can produce.
|
|
495
498
|
const WHY = {
|
|
496
499
|
AUTHORIZED: 'inside the mandate and under the SOP spend cap',
|
|
497
|
-
SOP_SPEND_CAP: 'your SOP caps a single transaction at
|
|
500
|
+
SOP_SPEND_CAP: 'your SOP caps a single transaction at ${currency} ${perTxnMax}',
|
|
498
501
|
RISK_REVIEW: 'your SOP sends high-risk actions to a human first',
|
|
499
502
|
MERCHANT_NOT_ALLOWED: 'the mandate lists which merchants this agent may pay',
|
|
500
503
|
// Both say the same thing from where you are standing: the mandate does not cover that
|
|
@@ -525,7 +528,7 @@ console.log(dim(' 4. each attempt is signed here, then decided by MetaMynd rem
|
|
|
525
528
|
console.log(dim(' 5. your tool runs ONLY if that decision is ALLOW'));
|
|
526
529
|
console.log('');
|
|
527
530
|
console.log(dim(' scope ${scope}'));
|
|
528
|
-
console.log(dim(' cap
|
|
531
|
+
console.log(dim(' cap ${currency} ${perTxnMax} per transaction, set by your SOP'));
|
|
529
532
|
|
|
530
533
|
// ---------------------------------------------------------------- 3. THE STEPS
|
|
531
534
|
async function attempt(n, intent, args, tool = gatedBookFlight) {
|
|
@@ -553,13 +556,13 @@ async function attempt(n, intent, args, tool = gatedBookFlight) {
|
|
|
553
556
|
|
|
554
557
|
console.log('');
|
|
555
558
|
console.log(rule(66));
|
|
556
|
-
await attempt(1, 'a
|
|
557
|
-
await attempt(2, 'a
|
|
558
|
-
await attempt(3, 'a
|
|
559
|
+
await attempt(1, 'a ${currency} ${under} booking, low risk. Expected to pass.', { amount: ${under}, currency: '${currency}', merchant: '${merchant}', riskLevel: 'low' });
|
|
560
|
+
await attempt(2, 'a ${currency} ${over} booking, deliberately over the cap.', { amount: ${over}, currency: '${currency}', merchant: '${merchant}', riskLevel: 'low' });
|
|
561
|
+
await attempt(3, 'a ${currency} ${under} booking, but flagged high risk.', { amount: ${under}, currency: '${currency}', merchant: '${merchant}', riskLevel: 'high' });
|
|
559
562
|
await attempt(
|
|
560
563
|
4,
|
|
561
564
|
'the agent stops booking flights and asks to raise its OWN limit.',
|
|
562
|
-
{ amount: 100000, merchant: '
|
|
565
|
+
{ amount: 100000, currency: '${currency}', merchant: '${merchant}' },
|
|
563
566
|
gatedRaiseOwnLimit,
|
|
564
567
|
);
|
|
565
568
|
console.log('');
|
|
@@ -595,7 +598,7 @@ console.log('');
|
|
|
595
598
|
* directly: it only exists in ./gateway, which independently re-verifies every request against
|
|
596
599
|
* this agent's own policy bundle before it runs, and holds any real credentials the tool needs.
|
|
597
600
|
*/
|
|
598
|
-
function exampleIndex(scope, perTxnMax, gatewayPort) {
|
|
601
|
+
function exampleIndex(scope, perTxnMax, gatewayPort, currency, merchant) {
|
|
599
602
|
const under = Math.max(1, Math.round(perTxnMax * 0.5));
|
|
600
603
|
const over = Math.round(perTxnMax + 100);
|
|
601
604
|
return `// index.mjs — your agent, governed by MetaMynd/AgentSafe.
|
|
@@ -620,7 +623,7 @@ async function bookFlightViaGateway(args, decision) {
|
|
|
620
623
|
const signed = await guard.buildSignedRequest({
|
|
621
624
|
action: '${scope}',
|
|
622
625
|
amount: args.amount,
|
|
623
|
-
currency: '
|
|
626
|
+
currency: args.currency ?? '${currency}',
|
|
624
627
|
merchant: args.merchant,
|
|
625
628
|
context: { tool: 'book-flight', riskLevel: args.riskLevel ?? 'low' },
|
|
626
629
|
});
|
|
@@ -647,7 +650,7 @@ const gatedBookFlight = guard.guardTool(
|
|
|
647
650
|
bookFlightViaGateway,
|
|
648
651
|
(a) => ({ // map tool args → gate inputs
|
|
649
652
|
amount: a.amount,
|
|
650
|
-
currency: '
|
|
653
|
+
currency: a.currency ?? '${currency}',
|
|
651
654
|
merchant: a.merchant,
|
|
652
655
|
context: { tool: 'book-flight', riskLevel: a.riskLevel ?? 'low' },
|
|
653
656
|
}),
|
|
@@ -664,7 +667,7 @@ const gatedRaiseOwnLimit = guard.guardTool(
|
|
|
664
667
|
raiseOwnLimit,
|
|
665
668
|
(a) => ({
|
|
666
669
|
amount: a.amount,
|
|
667
|
-
currency: '
|
|
670
|
+
currency: a.currency ?? '${currency}',
|
|
668
671
|
merchant: a.merchant,
|
|
669
672
|
context: { tool: 'permissions-update' },
|
|
670
673
|
}),
|
|
@@ -711,7 +714,7 @@ console.log(dim(' 5. the gateway independently re-verifies before your tool ru
|
|
|
711
714
|
console.log(dim(' 6. there is no local bookFlight() to call directly - only the gateway has it'));
|
|
712
715
|
console.log('');
|
|
713
716
|
console.log(dim(' scope ${scope}'));
|
|
714
|
-
console.log(dim(' cap
|
|
717
|
+
console.log(dim(' cap ${currency} ${perTxnMax} per transaction, set by your SOP'));
|
|
715
718
|
console.log(dim(' gateway ' + GATEWAY + ' (run it in a separate terminal - see ./gateway)'));
|
|
716
719
|
|
|
717
720
|
// ---------------------------------------------------------------- 3. THE STEPS
|
|
@@ -740,13 +743,13 @@ async function attempt(n, intent, args, tool = gatedBookFlight) {
|
|
|
740
743
|
|
|
741
744
|
console.log('');
|
|
742
745
|
console.log(rule(66));
|
|
743
|
-
await attempt(1, 'a
|
|
744
|
-
await attempt(2, 'a
|
|
745
|
-
await attempt(3, 'a
|
|
746
|
+
await attempt(1, 'a ${currency} ${under} booking, low risk. Expected to pass.', { amount: ${under}, currency: '${currency}', merchant: '${merchant}', riskLevel: 'low' });
|
|
747
|
+
await attempt(2, 'a ${currency} ${over} booking, deliberately over the cap.', { amount: ${over}, currency: '${currency}', merchant: '${merchant}', riskLevel: 'low' });
|
|
748
|
+
await attempt(3, 'a ${currency} ${under} booking, but flagged high risk.', { amount: ${under}, currency: '${currency}', merchant: '${merchant}', riskLevel: 'high' });
|
|
746
749
|
await attempt(
|
|
747
750
|
4,
|
|
748
751
|
'the agent stops booking flights and asks to raise its OWN limit.',
|
|
749
|
-
{ amount: 100000, merchant: '
|
|
752
|
+
{ amount: 100000, currency: '${currency}', merchant: '${merchant}' },
|
|
750
753
|
gatedRaiseOwnLimit,
|
|
751
754
|
);
|
|
752
755
|
console.log('');
|
|
@@ -1108,11 +1111,16 @@ and \`demo/duffel-mcp-gateway\` in the AgentSafe repo for the fuller pattern thi
|
|
|
1108
1111
|
`;
|
|
1109
1112
|
}
|
|
1110
1113
|
|
|
1111
|
-
function writeFileSafe(dir, name, content, force = false) {
|
|
1114
|
+
function writeFileSafe(dir, name, content, force = false, mode) {
|
|
1112
1115
|
const p = join(dir, name);
|
|
1113
1116
|
const exists = existsSync(p);
|
|
1114
1117
|
if (exists && !force) { console.log(` ${c.yellow('skip')} ${name} ${c.dim('(exists)')}`); return; }
|
|
1115
|
-
|
|
1118
|
+
// `mode` (e.g. 0o600 for a private-key-bearing file) only narrows perms at CREATE time —
|
|
1119
|
+
// writeFileSync ignores its own `mode` option on an existing file, so an --force overwrite
|
|
1120
|
+
// needs an explicit chmod or a stale world-readable mode from the file's first creation
|
|
1121
|
+
// would otherwise survive untouched.
|
|
1122
|
+
writeFileSync(p, content, mode !== undefined ? { mode } : undefined);
|
|
1123
|
+
if (mode !== undefined) chmodSync(p, mode);
|
|
1116
1124
|
console.log(` ${exists ? c.yellow('overwrite') : c.green('create')} ${name}`);
|
|
1117
1125
|
}
|
|
1118
1126
|
|
|
@@ -1146,12 +1154,12 @@ function assertScaffoldTarget(outDir, force) {
|
|
|
1146
1154
|
* enforcement boundary. Off for --sandbox (shared demo identity, never real credentials
|
|
1147
1155
|
* anyway) and --no-gateway (opt out, e.g. you're already running your own separate gateway).
|
|
1148
1156
|
*/
|
|
1149
|
-
function scaffoldProject({ outDir, config, slug, scope, perTxnMax, sandbox, withGateway, gatewayPort = DEFAULT_GATEWAY_PORT, force = false }) {
|
|
1157
|
+
function scaffoldProject({ outDir, config, slug, scope, perTxnMax, currency = 'USD', merchant = 'skyward-air', sandbox, withGateway, gatewayPort = DEFAULT_GATEWAY_PORT, force = false }) {
|
|
1150
1158
|
assertScaffoldTarget(outDir, force);
|
|
1151
1159
|
console.log(`\n ${c.b('Scaffolding')} ${c.dim(outDir)}`);
|
|
1152
1160
|
if (!existsSync(outDir)) mkdirSync(outDir, { recursive: true });
|
|
1153
|
-
writeFileSafe(outDir, 'agent.metamynd.json', JSON.stringify(config, null, 2) + '\n', force);
|
|
1154
|
-
writeFileSafe(outDir, 'index.mjs', withGateway ? exampleIndex(scope, perTxnMax, gatewayPort) : exampleIndexNoGateway(scope, perTxnMax), force);
|
|
1161
|
+
writeFileSafe(outDir, 'agent.metamynd.json', JSON.stringify(config, null, 2) + '\n', force, 0o600);
|
|
1162
|
+
writeFileSafe(outDir, 'index.mjs', withGateway ? exampleIndex(scope, perTxnMax, gatewayPort, currency, merchant) : exampleIndexNoGateway(scope, perTxnMax, currency, merchant), force);
|
|
1155
1163
|
writeFileSafe(outDir, 'package.json', examplePackageJson(slug), force);
|
|
1156
1164
|
writeFileSafe(outDir, '.gitignore', gitignore(), force);
|
|
1157
1165
|
writeFileSafe(outDir, 'README.md', exampleReadme(slug, scope, withGateway, gatewayPort, config.keyProvider === 'daemon'), force);
|
|
@@ -1792,7 +1800,7 @@ setInterval(refresh, 3000);
|
|
|
1792
1800
|
`;
|
|
1793
1801
|
}
|
|
1794
1802
|
|
|
1795
|
-
function harnessIndexFile(scope, perTxnMax, port, withGateway, gatewayPort) {
|
|
1803
|
+
function harnessIndexFile(scope, perTxnMax, port, withGateway, gatewayPort, currency, merchant) {
|
|
1796
1804
|
const under = Math.max(1, Math.round(perTxnMax * 0.5));
|
|
1797
1805
|
const over = Math.round(perTxnMax + 100);
|
|
1798
1806
|
return `// index.mjs — your agent, governed entirely on this machine. No account, no network call
|
|
@@ -1831,7 +1839,7 @@ const GATEWAY = process.env.HARNESS_GATEWAY_URL || 'http://localhost:${gatewayPo
|
|
|
1831
1839
|
// issuer): it builds and signs the same canonical message a real gate would verify, entirely
|
|
1832
1840
|
// offline, using this agent's own did:key — the gateway verifies that signature for itself.
|
|
1833
1841
|
async function callGateway(path, action, args) {
|
|
1834
|
-
const signed = await guard.buildSignedRequest({ action, amount: args.amount, currency: '
|
|
1842
|
+
const signed = await guard.buildSignedRequest({ action, amount: args.amount, currency: args.currency ?? '${currency}', merchant: args.merchant, context: { tool: '${scope}', riskLevel: args.riskLevel ?? 'low' } });
|
|
1835
1843
|
const res = await fetch(GATEWAY + path, { method: 'POST', headers: { 'content-type': 'application/json' }, body: JSON.stringify({ signed, args }) });
|
|
1836
1844
|
const body = await res.json().catch(() => null);
|
|
1837
1845
|
if (!res.ok) {
|
|
@@ -1854,6 +1862,7 @@ const gatedBookFlight = guard.guardToolLocal(
|
|
|
1854
1862
|
${withGateway ? `(args) => callGateway('/book-flight', '${scope}', args)` : 'bookFlight'},
|
|
1855
1863
|
(a) => ({ // map tool args → gate inputs
|
|
1856
1864
|
amount: a.amount,
|
|
1865
|
+
currency: a.currency ?? '${currency}',
|
|
1857
1866
|
merchant: a.merchant,
|
|
1858
1867
|
context: { tool: 'book-flight', riskLevel: a.riskLevel ?? 'low' },
|
|
1859
1868
|
}),
|
|
@@ -1869,7 +1878,7 @@ async function raiseOwnLimit(args) {
|
|
|
1869
1878
|
const gatedRaiseOwnLimit = guard.guardToolLocal(
|
|
1870
1879
|
'permissions.update', // an action NOT in the mandate
|
|
1871
1880
|
${withGateway ? `(args) => callGateway('/raise-limit', 'permissions.update', args)` : 'raiseOwnLimit'},
|
|
1872
|
-
(a) => ({ amount: a.amount, merchant: a.merchant, context: { tool: 'permissions-update' } }),
|
|
1881
|
+
(a) => ({ amount: a.amount, currency: a.currency ?? '${currency}', merchant: a.merchant, context: { tool: 'permissions-update' } }),
|
|
1873
1882
|
getBundle,
|
|
1874
1883
|
);
|
|
1875
1884
|
|
|
@@ -1879,7 +1888,7 @@ const rule = (n) => ' ' + '-'.repeat(n);
|
|
|
1879
1888
|
|
|
1880
1889
|
const WHY = {
|
|
1881
1890
|
AUTHORIZED: 'inside the mandate and under the SOP spend cap',
|
|
1882
|
-
SOP_SPEND_CAP: 'your SOP caps a single transaction at
|
|
1891
|
+
SOP_SPEND_CAP: 'your SOP caps a single transaction at ${currency} ${perTxnMax}',
|
|
1883
1892
|
RISK_REVIEW: 'your SOP sends high-risk actions to a human first',
|
|
1884
1893
|
MERCHANT_NOT_ALLOWED: 'the mandate lists which merchants this agent may pay',
|
|
1885
1894
|
NO_PERMISSION_FOR_ACTION: 'the mandate never granted this action - at any amount',
|
|
@@ -1925,14 +1934,14 @@ console.log(' for something never granted at all - the one a prompt could not h
|
|
|
1925
1934
|
console.log(' because the decision is not made inside your program, and not on a server either.');
|
|
1926
1935
|
console.log('');
|
|
1927
1936
|
console.log(dim(' scope ${scope}'));
|
|
1928
|
-
console.log(dim(' cap
|
|
1937
|
+
console.log(dim(' cap ${currency} ${perTxnMax} per transaction, from ./metamynd-rules.json'));
|
|
1929
1938
|
|
|
1930
1939
|
console.log('');
|
|
1931
1940
|
console.log(rule(66));
|
|
1932
|
-
await attempt(1, 'a
|
|
1933
|
-
await attempt(2, 'a
|
|
1934
|
-
await attempt(3, 'a
|
|
1935
|
-
await attempt(4, 'the agent stops booking flights and asks to raise its OWN limit.', 'permissions.update', { amount: 100000, merchant: '
|
|
1941
|
+
await attempt(1, 'a ${currency} ${under} booking, low risk. Expected to pass.', '${scope}', { amount: ${under}, currency: '${currency}', merchant: '${merchant}', riskLevel: 'low' });
|
|
1942
|
+
await attempt(2, 'a ${currency} ${over} booking, deliberately over the cap.', '${scope}', { amount: ${over}, currency: '${currency}', merchant: '${merchant}', riskLevel: 'low' });
|
|
1943
|
+
await attempt(3, 'a ${currency} ${under} booking, but flagged high risk.', '${scope}', { amount: ${under}, currency: '${currency}', merchant: '${merchant}', riskLevel: 'high' });
|
|
1944
|
+
await attempt(4, 'the agent stops booking flights and asks to raise its OWN limit.', 'permissions.update', { amount: 100000, currency: '${currency}', merchant: '${merchant}' }, gatedRaiseOwnLimit);
|
|
1936
1945
|
console.log('');
|
|
1937
1946
|
console.log(rule(66));
|
|
1938
1947
|
|
|
@@ -2109,10 +2118,10 @@ async function runHarness(args) {
|
|
|
2109
2118
|
|
|
2110
2119
|
console.log(`\n ${c.b('Scaffolding')} ${c.dim(outDir)}`);
|
|
2111
2120
|
if (!existsSync(outDir)) mkdirSync(outDir, { recursive: true });
|
|
2112
|
-
writeFileSafe(outDir, 'agent.metamynd.json', JSON.stringify({ agentDid, agentKey: privateKeyHex, mode: 'harness' }, null, 2) + '\n', !!args.force);
|
|
2121
|
+
writeFileSafe(outDir, 'agent.metamynd.json', JSON.stringify({ agentDid, agentKey: privateKeyHex, mode: 'harness' }, null, 2) + '\n', !!args.force, 0o600);
|
|
2113
2122
|
writeFileSafe(outDir, 'metamynd-rules.json', harnessRulesFile(mandate, sopDocument), !!args.force);
|
|
2114
2123
|
writeFileSafe(outDir, 'harness-server.mjs', harnessServerFile(), !!args.force);
|
|
2115
|
-
writeFileSafe(outDir, 'index.mjs', harnessIndexFile(scope, perTxnMax, port, withGateway, gatewayPort), !!args.force);
|
|
2124
|
+
writeFileSafe(outDir, 'index.mjs', harnessIndexFile(scope, perTxnMax, port, withGateway, gatewayPort, currency, merchants[0] || 'demo-merchant'), !!args.force);
|
|
2116
2125
|
writeFileSafe(outDir, 'package.json', harnessPackageJson(slug), !!args.force);
|
|
2117
2126
|
writeFileSafe(outDir, '.gitignore', gitignore(), !!args.force);
|
|
2118
2127
|
writeFileSafe(outDir, 'README.md', harnessReadme(slug, scope, port, withGateway, gatewayPort), !!args.force);
|
|
@@ -2204,7 +2213,9 @@ async function runRequest(args) {
|
|
|
2204
2213
|
const d = res.data;
|
|
2205
2214
|
const state = { api: base, requestId: d.requestId, claimToken: d.claimToken, byok: !!generated, privateKey: generated?.privateKeyHex ?? null, name, scope, perTxnMax };
|
|
2206
2215
|
const file = resolve(String(args.out || '.'), REQUEST_STATE_FILE);
|
|
2207
|
-
|
|
2216
|
+
// May carry a BYOK private key (state.privateKey) — same 0600 treatment as agent.metamynd.json.
|
|
2217
|
+
writeFileSync(file, JSON.stringify(state, null, 2) + '\n', { mode: 0o600 });
|
|
2218
|
+
if (existsSync(file)) chmodSync(file, 0o600);
|
|
2208
2219
|
|
|
2209
2220
|
console.log(` ${c.green('✓')} request ${c.b(d.requestId)} submitted — awaiting ${owner}'s approval`);
|
|
2210
2221
|
console.log(` ${c.yellow('⚠ saved the one-time claim token to')} ${file.replace(resolve('.'), '.').replace(/\\/g, '/')} ${c.dim('(secret — do not commit)')}\n`);
|
|
@@ -2413,7 +2424,7 @@ async function main() {
|
|
|
2413
2424
|
}
|
|
2414
2425
|
|
|
2415
2426
|
// 4. Scaffold + next steps
|
|
2416
|
-
scaffoldProject({ outDir, config, slug, scope, perTxnMax, sandbox: false, withGateway: !args['no-gateway'], gatewayPort: Number(args['gateway-port']) || DEFAULT_GATEWAY_PORT, force: !!args.force });
|
|
2427
|
+
scaffoldProject({ outDir, config, slug, scope, perTxnMax, currency, merchant: merchants[0] || 'demo-merchant', sandbox: false, withGateway: !args['no-gateway'], gatewayPort: Number(args['gateway-port']) || DEFAULT_GATEWAY_PORT, force: !!args.force });
|
|
2417
2428
|
}
|
|
2418
2429
|
|
|
2419
2430
|
main().catch((e) => fail(e?.stack || e?.message || String(e)));
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-metamynd-agent",
|
|
3
|
-
"version": "0.10.
|
|
3
|
+
"version": "0.10.5",
|
|
4
4
|
"description": "Scaffold a MetaMynd/AgentSafe-governed AI agent in one command — logs in, provisions the agent (identity + mandate + SOP + Standards) in a single call, writes agent.metamynd.json plus a runnable agent + separate tool-gateway process that closes direct-call, confused-deputy, replay, and cumulative-spend bypasses. --harness scaffolds a free, local, zero-network governance harness instead.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|