@technomoron/agent-run 0.99.37 → 0.99.39
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/CHANGES +15 -0
- package/README.md +27 -9
- package/dist/brain/cli.js +14 -7
- package/dist/brain/git.js +47 -34
- package/dist/brain/server.js +2 -2
- package/package.json +1 -1
- package/scripts/update-ai-tools.sh +6 -9
package/CHANGES
CHANGED
|
@@ -1,6 +1,21 @@
|
|
|
1
1
|
CHANGES
|
|
2
2
|
=======
|
|
3
3
|
|
|
4
|
+
Version 0.99.39 (2026-09-11)
|
|
5
|
+
----------------------------
|
|
6
|
+
* Fix the AI tools updater failing under sudo or a root shell with inherited
|
|
7
|
+
SUDO_USER when configuring root-owned pnpm paths.
|
|
8
|
+
* Allow Claude, Grok, and esbuild install hooks during global npm updates,
|
|
9
|
+
and remove the duplicate manual Claude install step.
|
|
10
|
+
|
|
11
|
+
Version 0.99.38 (2026-09-11)
|
|
12
|
+
----------------------------
|
|
13
|
+
* Add agent-brain pull, push, and save commands without --confirmed. Save
|
|
14
|
+
generates a commit message and pushes the saved changes.
|
|
15
|
+
* Make agent-brain sync commit, pull, and push; move the preview to sync status.
|
|
16
|
+
* Report completed sync steps and preserve useful progress details on failure.
|
|
17
|
+
* Allow prompt-driven MCP sync without a supplied message or confirmation field.
|
|
18
|
+
|
|
4
19
|
Version 0.99.37 (2026-09-11)
|
|
5
20
|
----------------------------
|
|
6
21
|
* Skip brain lookups for ordinary questions unless saved knowledge is needed,
|
package/README.md
CHANGED
|
@@ -939,15 +939,25 @@ a local task does not close a GitHub issue or modify a Trello card.
|
|
|
939
939
|
### Git portability
|
|
940
940
|
|
|
941
941
|
```sh
|
|
942
|
-
agent-brain sync
|
|
943
|
-
agent-brain sync init
|
|
944
|
-
agent-brain
|
|
945
|
-
agent-brain
|
|
946
|
-
agent-brain
|
|
942
|
+
agent-brain sync status # Preview Git status and eligible files
|
|
943
|
+
agent-brain sync init # Initialize the configuration Git repository
|
|
944
|
+
agent-brain save # Commit local brain changes and push
|
|
945
|
+
agent-brain pull # Pull remote changes with rebase
|
|
946
|
+
agent-brain push # Push existing commits
|
|
947
|
+
agent-brain sync # Commit local changes, pull, then push
|
|
947
948
|
```
|
|
948
949
|
|
|
949
|
-
|
|
950
|
-
|
|
950
|
+
Commands need no `--confirmed` flag. Saving generates a commit message from the
|
|
951
|
+
number of changed files; use `--message "Your message"` to override it. Output
|
|
952
|
+
reports completed steps, including a local commit if a later pull or push fails.
|
|
953
|
+
Existing `agent-brain sync save|pull|push` forms remain supported. Bare
|
|
954
|
+
`agent-brain sync` now performs synchronization; use `sync status` for a preview.
|
|
955
|
+
|
|
956
|
+
From an agent prompt, ask to "save brain changes" or "sync brain". The MCP `sync`
|
|
957
|
+
tool accepts the same actions and an optional message, without a confirmation
|
|
958
|
+
parameter. Agents still need a user request or standing authorization to sync.
|
|
959
|
+
|
|
960
|
+
Saving includes Markdown knowledge, skills, tasks, project metadata, and `.gitignore`.
|
|
951
961
|
It also includes all regular files under each scope's `templates/` directory,
|
|
952
962
|
including nested Nunjucks templates and supporting files. Template additions,
|
|
953
963
|
edits, and deletions are synced; symlinks are rejected.
|
|
@@ -961,8 +971,10 @@ profile markers and shared templates, then update source roots in `config.yaml`
|
|
|
961
971
|
to match that machine.
|
|
962
972
|
|
|
963
973
|
The configuration directory must itself be the repository root. Pull uses rebase
|
|
964
|
-
and reports conflicted files; resolve
|
|
965
|
-
|
|
974
|
+
and reports conflicted files; resolve the rebase before syncing again. Sync stops
|
|
975
|
+
on failure without pushing. Commands apply across all scopes in the configuration
|
|
976
|
+
repository, not just the current code project. Background commits and pushes are
|
|
977
|
+
not performed; the service can optionally pull at startup as described below.
|
|
966
978
|
|
|
967
979
|
### Persistent service under apicore-server
|
|
968
980
|
|
|
@@ -1058,6 +1070,12 @@ npm, pnpm, corepack, fallow, ripgrep, pm2, tsx, typescript,
|
|
|
1058
1070
|
@xai-official/grok, and @technomoron/agent-run
|
|
1059
1071
|
```
|
|
1060
1072
|
|
|
1073
|
+
The updater clears inherited `SUDO_USER` for its root-owned pnpm configuration
|
|
1074
|
+
writes, so it works both under sudo and from a root shell. It explicitly allows
|
|
1075
|
+
the Claude, Grok, esbuild, and pnpm install hooks. Optional native build hooks
|
|
1076
|
+
such as keytar and node-pty remain subject to npm's script policy; the updater
|
|
1077
|
+
does not enable native compilation or require a working node-gyp installation.
|
|
1078
|
+
|
|
1061
1079
|
The optional apt package list still defaults to `gh` and can be changed with
|
|
1062
1080
|
`AI_TOOLS_APT_PACKAGES`.
|
|
1063
1081
|
|
package/dist/brain/cli.js
CHANGED
|
@@ -50,7 +50,8 @@ async function brainMain(argv, wrapperCommand) {
|
|
|
50
50
|
'agent-brain todo update <id> --revision <hash> --json <changes>',
|
|
51
51
|
'agent-brain todo complete <id> --revision <hash>',
|
|
52
52
|
'agent-brain todo import|sync <connector> --scope <scope>',
|
|
53
|
-
'agent-brain
|
|
53
|
+
'agent-brain pull | push | save | sync [--message <commit-message>]',
|
|
54
|
+
'agent-brain sync status | init',
|
|
54
55
|
'agent-brain serve [--pull] [--socket <path>] | mcp [--socket <path>]',
|
|
55
56
|
'agent-run create <name> [--quick | --guided]',
|
|
56
57
|
'agent-run project list | info | bootstrap',
|
|
@@ -169,17 +170,23 @@ async function brainMain(argv, wrapperCommand) {
|
|
|
169
170
|
throw new Error('Usage: agent-brain review list | resolve <id> --revision <hash> --state fixed|wontfix');
|
|
170
171
|
break;
|
|
171
172
|
}
|
|
173
|
+
case 'pull':
|
|
174
|
+
case 'push':
|
|
175
|
+
case 'save':
|
|
172
176
|
case 'sync': {
|
|
173
|
-
const action = positionals
|
|
174
|
-
if (
|
|
177
|
+
const action = command === 'sync' ? positionals.shift() ?? 'sync' : command;
|
|
178
|
+
if (positionals.length)
|
|
179
|
+
throw new Error('Unexpected arguments; use agent-brain --help');
|
|
180
|
+
if (action === 'status') {
|
|
175
181
|
report((0, git_1.gitPreview)(store));
|
|
176
182
|
break;
|
|
177
183
|
}
|
|
178
|
-
if (!['init', 'save', 'pull', 'push'].includes(action))
|
|
184
|
+
if (!['init', 'save', 'pull', 'push', 'sync'].includes(action))
|
|
179
185
|
throw new Error('Unknown sync action');
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
186
|
+
const result = (0, git_1.syncGit)(store, action, values.message);
|
|
187
|
+
process.stdout.write(`${result.steps.join('\n')}\n`);
|
|
188
|
+
if (result.files.length)
|
|
189
|
+
process.stdout.write(`Other local changes remain. Use agent-brain sync status to inspect them.\n`);
|
|
183
190
|
break;
|
|
184
191
|
}
|
|
185
192
|
case 'todo': {
|
package/dist/brain/git.js
CHANGED
|
@@ -59,44 +59,57 @@ function syncableFiles(store) {
|
|
|
59
59
|
}
|
|
60
60
|
function syncGit(store, action, message) {
|
|
61
61
|
return store.writeLocked(() => {
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
git(store.configRoot, ['
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
62
|
+
const steps = [];
|
|
63
|
+
try {
|
|
64
|
+
if (action === 'init') {
|
|
65
|
+
if (!fs.existsSync(path.join(store.configRoot, '.git')))
|
|
66
|
+
git(store.configRoot, ['init', '--initial-branch=main']);
|
|
67
|
+
return { ...gitStatus(store), steps: ['Configuration Git repository initialized.'] };
|
|
68
|
+
}
|
|
69
|
+
requireRepository(store);
|
|
70
|
+
const status = gitStatus(store);
|
|
71
|
+
if (status.state === 'conflicted')
|
|
72
|
+
throw new Error(`Resolve Git conflicts before syncing: ${status.conflicts.join(', ')}`);
|
|
73
|
+
if (action === 'save' || action === 'sync') {
|
|
74
|
+
if (message !== undefined && !message.trim())
|
|
75
|
+
throw new Error('The commit message must not be empty.');
|
|
76
|
+
if (git(store.configRoot, ['diff', '--cached', '--name-only']))
|
|
77
|
+
throw new Error('The Git index already has staged changes. Commit or unstage them before saving brain knowledge.');
|
|
78
|
+
const files = syncableFiles(store);
|
|
79
|
+
if (files.length)
|
|
80
|
+
git(store.configRoot, ['add', '--', ...files]);
|
|
81
|
+
const changed = git(store.configRoot, ['diff', '--cached', '--name-only', '-z']).split('\0').filter(Boolean);
|
|
82
|
+
if (changed.length) {
|
|
83
|
+
const commitMessage = message ?? `Update brain knowledge (${changed.length} ${changed.length === 1 ? 'file' : 'files'})`;
|
|
84
|
+
git(store.configRoot, ['commit', '-m', commitMessage]);
|
|
85
|
+
steps.push(`Saved ${changed.length} ${changed.length === 1 ? 'file' : 'files'} in commit ${git(store.configRoot, ['rev-parse', '--short', 'HEAD'])}: ${commitMessage}`);
|
|
86
|
+
}
|
|
87
|
+
else
|
|
88
|
+
steps.push('No local brain changes to save.');
|
|
89
|
+
}
|
|
90
|
+
if (action === 'pull' || action === 'sync') {
|
|
91
|
+
if (git(store.configRoot, ['diff', '--name-only']) || git(store.configRoot, ['diff', '--cached', '--name-only']))
|
|
92
|
+
throw new Error('Save or resolve local tracked configuration changes before pulling.');
|
|
93
|
+
try {
|
|
94
|
+
git(store.configRoot, ['-c', 'merge.autoStash=false', '-c', 'rebase.autoStash=false', 'pull', '--rebase']);
|
|
95
|
+
}
|
|
96
|
+
catch (error) {
|
|
97
|
+
const after = gitStatus(store);
|
|
98
|
+
if (after.state === 'conflicted')
|
|
99
|
+
throw new Error(`Pull stopped with conflicts: ${after.conflicts.join(', ')}. Resolve the rebase before syncing again.`);
|
|
100
|
+
throw new Error(`Pull failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
101
|
+
}
|
|
102
|
+
steps.push('Pulled remote changes.');
|
|
88
103
|
}
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
return after;
|
|
93
|
-
throw error;
|
|
104
|
+
if (action === 'push' || action === 'save' || action === 'sync') {
|
|
105
|
+
git(store.configRoot, ['push']);
|
|
106
|
+
steps.push('Push completed; remote is up to date.');
|
|
94
107
|
}
|
|
108
|
+
return { ...gitStatus(store), steps };
|
|
95
109
|
}
|
|
96
|
-
|
|
97
|
-
|
|
110
|
+
catch (error) {
|
|
111
|
+
throw new Error([...steps, error instanceof Error ? error.message : String(error)].join('\n'));
|
|
98
112
|
}
|
|
99
|
-
return gitStatus(store);
|
|
100
113
|
});
|
|
101
114
|
}
|
|
102
115
|
function gitPreview(store) {
|
package/dist/brain/server.js
CHANGED
|
@@ -42,8 +42,8 @@ function createBrainServer(store) {
|
|
|
42
42
|
const revision = zod_1.z.string().regex(/^[a-f0-9]{64}$/);
|
|
43
43
|
tool('brain_status', 'Show the active project and available scopes.', {}, true, () => ({ profile: store.profile, scopes: store.scopes.map((entry) => entry.scope) }));
|
|
44
44
|
tool('sync_status', 'Preview Git state and the canonical files eligible for saving. Runtime files, indexes, credentials, and native agent state are excluded.', {}, true, () => (0, git_1.gitPreview)(store));
|
|
45
|
-
server.registerTool('sync', { description: '
|
|
46
|
-
inputSchema: { action: zod_1.z.enum(['init', 'save', 'pull', 'push']), confirmed: zod_1.z.literal(true), message: zod_1.z.string().min(1).max(1000).optional() },
|
|
45
|
+
server.registerTool('sync', { description: 'Synchronize the configuration Git repository when the user requests it. save commits and pushes; sync commits, pulls with rebase, then pushes; pull and push only transfer existing commits. Commit messages are generated unless supplied. Use sync_status to inspect eligible files.',
|
|
46
|
+
inputSchema: { action: zod_1.z.enum(['init', 'save', 'pull', 'push', 'sync']), confirmed: zod_1.z.literal(true).optional(), message: zod_1.z.string().min(1).max(1000).optional() },
|
|
47
47
|
annotations: { readOnlyHint: false, destructiveHint: false, openWorldHint: true }
|
|
48
48
|
}, async ({ action, message }) => {
|
|
49
49
|
try {
|
package/package.json
CHANGED
|
@@ -51,22 +51,19 @@ if [ "${1:-}" = --agent-brain ]; then
|
|
|
51
51
|
exit 0
|
|
52
52
|
fi
|
|
53
53
|
|
|
54
|
-
"$NPM_BIN" install -g --force "${packages[@]}"
|
|
54
|
+
"$NPM_BIN" install -g --force "${packages[@]}" --allow-scripts=@anthropic-ai/claude-code,@xai-official/grok,esbuild
|
|
55
55
|
ensure_brain
|
|
56
56
|
|
|
57
57
|
# corepack and pnpm both own the pnpm/pnpx shims; install pnpm last so npm's
|
|
58
58
|
# current pnpm package remains the command users execute.
|
|
59
59
|
"$NPM_BIN" install -g --force pnpm@latest --allow-scripts=pnpm
|
|
60
60
|
|
|
61
|
+
# This updater deliberately manages root-owned tooling. pnpm rejects inherited
|
|
62
|
+
# sudo identity even in a root shell; clear it only for these configuration writes.
|
|
61
63
|
install -d -o root -g root -m 0755 /usr/local/share/pnpm/global /usr/local/share/pnpm/store /usr/local/bin
|
|
62
|
-
"$PNPM_BIN" config set --global global-dir /usr/local/share/pnpm/global
|
|
63
|
-
"$PNPM_BIN" config set --global global-bin-dir /usr/local/bin
|
|
64
|
-
"$PNPM_BIN" config set --global store-dir /usr/local/share/pnpm/store
|
|
65
|
-
|
|
66
|
-
CLAUDE_INSTALL="$("$NPM_BIN" root -g)/@anthropic-ai/claude-code/install.cjs"
|
|
67
|
-
if [ -f "$CLAUDE_INSTALL" ]; then
|
|
68
|
-
"$NODE_BIN" "$CLAUDE_INSTALL"
|
|
69
|
-
fi
|
|
64
|
+
env -u SUDO_USER "$PNPM_BIN" config set --global global-dir /usr/local/share/pnpm/global
|
|
65
|
+
env -u SUDO_USER "$PNPM_BIN" config set --global global-bin-dir /usr/local/bin
|
|
66
|
+
env -u SUDO_USER "$PNPM_BIN" config set --global store-dir /usr/local/share/pnpm/store
|
|
70
67
|
|
|
71
68
|
if [ -n "$AI_TOOLS_APT_PACKAGES" ] && command -v "$APT_GET_BIN" >/dev/null 2>&1; then
|
|
72
69
|
read -r -a apt_packages <<<"$AI_TOOLS_APT_PACKAGES"
|