@memfork/cli 0.1.22 → 0.1.24
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/commands/init.js +5 -1
- package/dist/commands/ops.js +23 -3
- package/dist/config.d.ts +2 -0
- package/dist/config.js +1 -1
- package/package.json +1 -1
- package/plugins/codex/README.md +25 -13
package/dist/commands/init.js
CHANGED
|
@@ -79,11 +79,15 @@ async function cmdInitQuick() {
|
|
|
79
79
|
network,
|
|
80
80
|
existingKey: existingKey || undefined,
|
|
81
81
|
});
|
|
82
|
-
// Persist
|
|
82
|
+
// Persist — include sponsor URL on mainnet so all subsequent commands
|
|
83
|
+
// (branch, commit, merge) use sponsored gas automatically.
|
|
84
|
+
const sponsorBase = (process.env.MEMFORK_SPONSOR_URL ?? "https://memforks-sponsor-production.up.railway.app")
|
|
85
|
+
.replace(/\/sponsor\/?$/, "");
|
|
83
86
|
writeProjectConfig({
|
|
84
87
|
treeId: result.treeId,
|
|
85
88
|
network: result.network,
|
|
86
89
|
defaultBranch: "main",
|
|
90
|
+
...(result.network === "mainnet" ? { sponsorUrl: `${sponsorBase}/sponsor` } : {}),
|
|
87
91
|
});
|
|
88
92
|
upsertCredential(result.treeId, {
|
|
89
93
|
privateKey: result.privateKey,
|
package/dist/commands/ops.js
CHANGED
|
@@ -14,6 +14,26 @@ async function getClient() {
|
|
|
14
14
|
const client = await MemForksClient.connect(toClientConfig(cfg));
|
|
15
15
|
return { client, cfg };
|
|
16
16
|
}
|
|
17
|
+
function isTransientSuiError(e) {
|
|
18
|
+
const msg = String(e);
|
|
19
|
+
return (msg.includes("needs to be rebuilt") ||
|
|
20
|
+
msg.includes("unavailable for consumption") ||
|
|
21
|
+
msg.includes("object version"));
|
|
22
|
+
}
|
|
23
|
+
async function withRetry(fn, retries = 2, delayMs = 1500) {
|
|
24
|
+
for (let attempt = 1;; attempt++) {
|
|
25
|
+
try {
|
|
26
|
+
return await fn();
|
|
27
|
+
}
|
|
28
|
+
catch (e) {
|
|
29
|
+
if (isTransientSuiError(e) && attempt < retries) {
|
|
30
|
+
await new Promise((r) => setTimeout(r, delayMs));
|
|
31
|
+
continue;
|
|
32
|
+
}
|
|
33
|
+
throw e;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
17
37
|
function currentGitBranch() {
|
|
18
38
|
try {
|
|
19
39
|
return execSync("git rev-parse --abbrev-ref HEAD", { encoding: "utf8" }).trim();
|
|
@@ -112,7 +132,7 @@ export async function cmdCommit(opts) {
|
|
|
112
132
|
console.error(chalk.red("No facts to commit. Pass --facts or --from-response."));
|
|
113
133
|
process.exit(1);
|
|
114
134
|
}
|
|
115
|
-
const { blobId } = await client.commit(branch, { facts, message: opts.message });
|
|
135
|
+
const { blobId } = await withRetry(() => client.commit(branch, { facts, message: opts.message }));
|
|
116
136
|
const out = { blobId, branch };
|
|
117
137
|
if (process.stdout.isTTY) {
|
|
118
138
|
console.log("");
|
|
@@ -138,7 +158,7 @@ export async function cmdMerge(from, into, opts) {
|
|
|
138
158
|
process.stdout.write(chalk.dim(`Merging ${chalk.green(from)} → ${chalk.green(into)}`) +
|
|
139
159
|
chalk.dim(governed ? " (governed — awaiting resolver…)" : " (LWW — self-finalizing…)") +
|
|
140
160
|
" ");
|
|
141
|
-
const { digest, mergedCount, blobId, proposalId } = await client.merge(from, into);
|
|
161
|
+
const { digest, mergedCount, blobId, proposalId } = await withRetry(() => client.merge(from, into));
|
|
142
162
|
console.log(chalk.green("done"));
|
|
143
163
|
console.log("");
|
|
144
164
|
console.log(chalk.dim(` facts merged: ${mergedCount}`));
|
|
@@ -574,7 +594,7 @@ export async function cmdBranch(name, opts = {}) {
|
|
|
574
594
|
const { client, cfg } = await getClient();
|
|
575
595
|
const from = opts.from ?? cfg.defaultBranch ?? currentGitBranch();
|
|
576
596
|
process.stdout.write(chalk.dim(`Creating branch ${chalk.green(name)} from ${chalk.green(from)} … `));
|
|
577
|
-
const digest = await client.branch(name, { from });
|
|
597
|
+
const digest = await withRetry(() => client.branch(name, { from }));
|
|
578
598
|
console.log(chalk.green("done"));
|
|
579
599
|
console.log("");
|
|
580
600
|
console.log(chalk.dim(` tx: ${digest}`));
|
package/dist/config.d.ts
CHANGED
|
@@ -47,6 +47,8 @@ export interface ProjectConfig {
|
|
|
47
47
|
rpcUrl?: string;
|
|
48
48
|
/** Override package ID (post-upgrade). */
|
|
49
49
|
packageId?: string;
|
|
50
|
+
/** Gas sponsor URL. When set, all on-chain txs are sponsored (no SUI balance needed). */
|
|
51
|
+
sponsorUrl?: string;
|
|
50
52
|
}
|
|
51
53
|
export interface TreeCredential {
|
|
52
54
|
/** Ed25519 private key in bech32 suiprivkey1… format. */
|
package/dist/config.js
CHANGED
|
@@ -180,7 +180,7 @@ export function resolveConfig(opts = {}) {
|
|
|
180
180
|
rpcUrl: env['MEMFORK_RPC_URL'] ?? project?.rpcUrl,
|
|
181
181
|
packageId: env['MEMFORK_PACKAGE_ID'] ?? project?.packageId,
|
|
182
182
|
sponsorUrl: env['MEMFORK_SPONSOR_URL'] ??
|
|
183
|
-
project?.
|
|
183
|
+
project?.sponsorUrl,
|
|
184
184
|
};
|
|
185
185
|
}
|
|
186
186
|
/**
|
package/package.json
CHANGED
package/plugins/codex/README.md
CHANGED
|
@@ -11,27 +11,25 @@ cryptographically anchored to Sui with branch context and a full commit DAG.
|
|
|
11
11
|
## Setup (one time, per machine)
|
|
12
12
|
|
|
13
13
|
```bash
|
|
14
|
+
# 1. Install the MemForks CLI
|
|
14
15
|
npm install -g @memfork/cli
|
|
15
16
|
|
|
16
|
-
#
|
|
17
|
+
# 2. Initialise your on-chain tree (provisions a Sui key + MemWal account)
|
|
17
18
|
memfork init --quick
|
|
18
|
-
|
|
19
|
-
# Or manual if you already have a Sui key + MemWal account:
|
|
20
|
-
memfork init
|
|
21
19
|
```
|
|
22
20
|
|
|
23
|
-
## Install the plugin
|
|
21
|
+
## Install the plugin in Codex
|
|
24
22
|
|
|
25
23
|
```bash
|
|
26
24
|
memfork install codex
|
|
27
25
|
```
|
|
28
26
|
|
|
29
|
-
This does two things:
|
|
27
|
+
This reads the credentials provisioned by `memfork init` and does two things:
|
|
30
28
|
|
|
31
|
-
1. **Writes `~/.codex/config.toml`** — adds
|
|
32
|
-
|
|
29
|
+
1. **Writes `~/.codex/config.toml`** — adds `[mcp_servers.memwal]` using the delegate key
|
|
30
|
+
already on disk. No browser login, no extra auth step.
|
|
33
31
|
|
|
34
|
-
2. **Copies
|
|
32
|
+
2. **Copies the plugin skills** into `.codex-plugin/` in the current project.
|
|
35
33
|
|
|
36
34
|
Then register with Codex:
|
|
37
35
|
|
|
@@ -61,21 +59,35 @@ Memory is namespaced by Git branch — `namespace="branch/<branch-name>"`.
|
|
|
61
59
|
## What gets installed
|
|
62
60
|
|
|
63
61
|
```
|
|
64
|
-
~/.codex/config.toml ←
|
|
62
|
+
~/.codex/config.toml ← [mcp_servers.memwal] entry (HTTP relayer + delegate key)
|
|
65
63
|
.codex-plugin/
|
|
66
64
|
plugin.json ← plugin metadata
|
|
67
65
|
skills/
|
|
68
66
|
memory-recall/ ← when/how to use memwal_recall
|
|
69
67
|
memforks-status/ ← when/how to use memfork commit/merge/status
|
|
68
|
+
memory-fork/ ← multi-hypothesis branch forking
|
|
70
69
|
```
|
|
71
70
|
|
|
72
|
-
|
|
71
|
+
MCP credentials come from `~/.memfork/credentials.json` (written by `memfork init`).
|
|
72
|
+
No separate browser login. No bearer tokens to copy-paste.
|
|
73
|
+
|
|
74
|
+
## Architecture
|
|
75
|
+
|
|
76
|
+
```
|
|
77
|
+
Codex agent
|
|
78
|
+
│
|
|
79
|
+
├── memwal_recall / memwal_remember → @mysten-incubation/memwal-mcp
|
|
80
|
+
│ (Walrus-backed encrypted memory)
|
|
81
|
+
│
|
|
82
|
+
└── memfork commit / merge / branch → @memfork/cli
|
|
83
|
+
(on-chain version control on Sui)
|
|
84
|
+
```
|
|
73
85
|
|
|
74
86
|
## Override for CI / headless use
|
|
75
87
|
|
|
76
88
|
```bash
|
|
77
89
|
MEMFORK_TREE_ID=0x…
|
|
78
90
|
MEMFORK_PRIVATE_KEY=suiprivkey1…
|
|
79
|
-
|
|
80
|
-
|
|
91
|
+
MEMWAL_ACCOUNT_ID=0x…
|
|
92
|
+
MEMWAL_API_TOKEN=<token>
|
|
81
93
|
```
|