@technomoron/agent-run 0.99.24 → 0.99.26

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/tools.js ADDED
@@ -0,0 +1,119 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.runCodex = runCodex;
4
+ exports.runClaude = runClaude;
5
+ exports.getDangerArgs = getDangerArgs;
6
+ exports.getPermissionArgs = getPermissionArgs;
7
+ const fs = require("fs");
8
+ const path = require("path");
9
+ const process_1 = require("./process");
10
+ const project_1 = require("./project");
11
+ function runCodex(realBinary, permissionArgs, context, args, wrapperArgs) {
12
+ const liveDir = context.paths.liveDir;
13
+ const codexHomeDir = context.paths.codexHomeDir;
14
+ const projectRoot = context.projectRoot;
15
+ if (!fs.existsSync(path.join(codexHomeDir, 'AGENTS.md'))) {
16
+ failMissingConfig('codex', context.profileDir);
17
+ }
18
+ const realPath = process.env.AGENT_RUN_REAL_PATH ?? process.env.PATH ?? '';
19
+ fs.mkdirSync(codexHomeDir, { recursive: true });
20
+ const env = {
21
+ ...process.env,
22
+ CODEX_HOME: codexHomeDir,
23
+ AGENT_DIR: liveDir,
24
+ AGENT_PROFILE_DIR: context.profileDir,
25
+ AGENT_RUN_PROJECT_ROOT: projectRoot,
26
+ AGENT_RUN_REAL_PATH: realPath,
27
+ PATH: `${path.join(liveDir, 'bin')}${path.delimiter}${realPath}`
28
+ };
29
+ const runtimeArgs = wrapperArgs.sandboxMode === 'danger' ? getDangerArgs('codex') : ['-a', 'on-request', '-s', 'workspace-write'];
30
+ (0, process_1.execCommand)(realBinary, [
31
+ ...permissionArgs,
32
+ ...runtimeArgs,
33
+ '-C',
34
+ projectRoot,
35
+ ...(wrapperArgs.sandboxMode !== 'danger' && wrapperArgs.codexNetwork
36
+ ? ['--config', 'sandbox_workspace_write.network_access=true']
37
+ : []),
38
+ ...args
39
+ ], env, codexHomeDir, (code) => postflightProjectCheck(context, wrapperArgs.local, code));
40
+ }
41
+ function runClaude(realBinary, permissionArgs, context, args, wrapperArgs) {
42
+ const liveDir = context.paths.liveDir;
43
+ const claudePath = path.join(liveDir, 'CLAUDE.md');
44
+ if (!fs.existsSync(claudePath)) {
45
+ failMissingConfig('claude', context.profileDir);
46
+ }
47
+ const claudeConfigDir = path.join(liveDir, '.claude');
48
+ const realPath = process.env.AGENT_RUN_REAL_PATH ?? process.env.PATH ?? '';
49
+ const env = {
50
+ ...process.env,
51
+ AGENT_DIR: liveDir,
52
+ AGENT_PROFILE_DIR: context.profileDir,
53
+ AGENT_RUN_PROJECT_ROOT: context.projectRoot,
54
+ AGENT_RUN_REAL_PATH: realPath,
55
+ PATH: `${path.join(liveDir, 'bin')}${path.delimiter}${realPath}`
56
+ };
57
+ const runtimeArgs = wrapperArgs.sandboxMode === 'danger' ? getDangerArgs('claude') : permissionArgs;
58
+ (0, process_1.execCommand)(realBinary, [
59
+ ...runtimeArgs,
60
+ '--append-system-prompt-file',
61
+ claudePath,
62
+ '--settings',
63
+ path.join(claudeConfigDir, 'agent-run-settings.json'),
64
+ '--plugin-dir',
65
+ claudeConfigDir,
66
+ ...args
67
+ ], env, context.projectRoot, (code) => postflightProjectCheck(context, wrapperArgs.local, code));
68
+ }
69
+ function postflightProjectCheck(context, allowLocal, code) {
70
+ if (!context.guardrails.forbidRepoAiFiles) {
71
+ return code;
72
+ }
73
+ if (!allowLocal) {
74
+ removeClaudeLocalSettings(context.projectRoot);
75
+ }
76
+ const localAiFiles = (0, project_1.findLocalAiFiles)(context.projectRoot, context.profileDir);
77
+ if (localAiFiles.length === 0) {
78
+ return code;
79
+ }
80
+ (0, project_1.warnForLocalAiFiles)(null, context.projectRoot, localAiFiles);
81
+ return allowLocal ? code : 1;
82
+ }
83
+ function removeClaudeLocalSettings(projectRoot) {
84
+ const claudeDir = path.join(projectRoot, '.claude');
85
+ const localSettingsPath = path.join(claudeDir, 'settings.local.json');
86
+ if (!fs.existsSync(localSettingsPath)) {
87
+ return;
88
+ }
89
+ fs.rmSync(localSettingsPath);
90
+ try {
91
+ fs.rmdirSync(claudeDir);
92
+ }
93
+ catch (error) {
94
+ if (!isDirectoryNotEmptyError(error)) {
95
+ throw error;
96
+ }
97
+ }
98
+ process.stderr.write(`agent-run: removed Claude's project-local settings: ${localSettingsPath}\n`);
99
+ }
100
+ function isDirectoryNotEmptyError(error) {
101
+ return error instanceof Error && 'code' in error && error.code === 'ENOTEMPTY';
102
+ }
103
+ function failMissingConfig(tool, agentDir) {
104
+ process.stderr.write(`agent-run: no ${tool} config found for this project: ${agentDir}\n`);
105
+ process.stderr.write(`agent-run: run \`agent-run ${tool} --none\` to bypass agent setup, or \`agent-run ${tool} --create\` to create profile files.\n`);
106
+ process.exit(1);
107
+ }
108
+ function getDangerArgs(tool) {
109
+ return tool === 'codex' ? ['-a', 'never', '-s', 'danger-full-access'] : ['--dangerously-skip-permissions'];
110
+ }
111
+ function getPermissionArgs(tool) {
112
+ if (process.env.AGENT_WRAPPER_FORCE_PERMISSIVE !== '1') {
113
+ return [];
114
+ }
115
+ if (tool === 'claude' && typeof process.getuid === 'function' && process.getuid() !== 0) {
116
+ return ['--permission-mode', 'bypassPermissions'];
117
+ }
118
+ return [];
119
+ }
package/dist/utils.js ADDED
@@ -0,0 +1,117 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.isSamePathOrDescendant = isSamePathOrDescendant;
4
+ exports.parseBooleanEnv = parseBooleanEnv;
5
+ exports.localDateString = localDateString;
6
+ exports.formatError = formatError;
7
+ exports.verbose = verbose;
8
+ exports.formatCommand = formatCommand;
9
+ exports.fail = fail;
10
+ exports.uniqueSorted = uniqueSorted;
11
+ exports.formatPathList = formatPathList;
12
+ exports.getExecutableExtensions = getExecutableExtensions;
13
+ exports.isExecutable = isExecutable;
14
+ exports.findExecutable = findExecutable;
15
+ exports.isSymlink = isSymlink;
16
+ exports.nextBackupPath = nextBackupPath;
17
+ const fs = require("fs");
18
+ const path = require("path");
19
+ const constants_1 = require("./constants");
20
+ function isSamePathOrDescendant(candidatePath, parentPath) {
21
+ const relative = path.relative(parentPath, candidatePath);
22
+ return relative === '' || (!relative.startsWith(`..${path.sep}`) && relative !== '..' && !path.isAbsolute(relative));
23
+ }
24
+ function parseBooleanEnv(value) {
25
+ if (value === undefined) {
26
+ return false;
27
+ }
28
+ return ['1', 'true', 'yes', 'on'].includes(value.trim().toLowerCase());
29
+ }
30
+ function localDateString() {
31
+ const now = new Date();
32
+ const year = String(now.getFullYear()).padStart(4, '0');
33
+ const month = String(now.getMonth() + 1).padStart(2, '0');
34
+ const day = String(now.getDate()).padStart(2, '0');
35
+ return `${year}-${month}-${day}`;
36
+ }
37
+ function formatError(error) {
38
+ return error instanceof Error ? error.message : String(error);
39
+ }
40
+ function verbose(message) {
41
+ if (parseBooleanEnv(process.env[constants_1.VERBOSE_ENV])) {
42
+ process.stderr.write(`agent-run: ${message}\n`);
43
+ }
44
+ }
45
+ function formatCommand(command, args) {
46
+ return [command, ...args].map(quoteArg).join(' ');
47
+ }
48
+ function quoteArg(value) {
49
+ if (value === '') {
50
+ return '""';
51
+ }
52
+ if (/^[A-Za-z0-9_./:=+-]+$/.test(value)) {
53
+ return value;
54
+ }
55
+ return JSON.stringify(value);
56
+ }
57
+ function fail(message) {
58
+ process.stderr.write(`agent-run: ${message}\n`);
59
+ process.exit(1);
60
+ }
61
+ function uniqueSorted(values) {
62
+ return [...new Set(values.map((value) => path.resolve(value)))].sort((a, b) => a.localeCompare(b));
63
+ }
64
+ function formatPathList(paths) {
65
+ return paths.length === 0 ? [' (none)'] : paths.map((entry) => ` ${entry}`);
66
+ }
67
+ function getExecutableExtensions(tool) {
68
+ if (!constants_1.IS_WINDOWS || path.extname(tool)) {
69
+ return [''];
70
+ }
71
+ return (process.env.PATHEXT || '.EXE;.CMD;.BAT;.COM')
72
+ .split(';')
73
+ .filter(Boolean)
74
+ .map((entry) => entry.toLowerCase());
75
+ }
76
+ function isExecutable(filePath) {
77
+ try {
78
+ if (constants_1.IS_WINDOWS) {
79
+ return fs.statSync(filePath).isFile();
80
+ }
81
+ fs.accessSync(filePath, fs.constants.X_OK);
82
+ return true;
83
+ }
84
+ catch {
85
+ return false;
86
+ }
87
+ }
88
+ function findExecutable(command) {
89
+ const pathDirs = (process.env.PATH || '').split(path.delimiter).filter(Boolean);
90
+ for (const dir of pathDirs) {
91
+ for (const extension of getExecutableExtensions(command)) {
92
+ const candidate = path.join(dir, `${command}${extension}`);
93
+ if (fs.existsSync(candidate) && isExecutable(candidate)) {
94
+ return candidate;
95
+ }
96
+ }
97
+ }
98
+ return null;
99
+ }
100
+ function isSymlink(filePath) {
101
+ try {
102
+ return fs.lstatSync(filePath).isSymbolicLink();
103
+ }
104
+ catch {
105
+ return false;
106
+ }
107
+ }
108
+ function nextBackupPath(filePath) {
109
+ const timestamp = new Date().toISOString().replace(/[-:TZ.]/g, '').slice(0, 14);
110
+ let candidate = `${filePath}.bak.${timestamp}`;
111
+ let index = 1;
112
+ while (fs.existsSync(candidate) || isSymlink(candidate)) {
113
+ candidate = `${filePath}.bak.${timestamp}.${index}`;
114
+ index += 1;
115
+ }
116
+ return candidate;
117
+ }
@@ -0,0 +1,24 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.walkTree = walkTree;
4
+ const fs = require("fs");
5
+ const path = require("path");
6
+ function walkTree(dir, visitor, options = {}) {
7
+ if (options.shouldSkipDirectory?.(dir)) {
8
+ return;
9
+ }
10
+ const entries = fs.readdirSync(dir, { withFileTypes: true }).sort((a, b) => a.name.localeCompare(b.name));
11
+ for (const entry of entries) {
12
+ if (options.shouldPrune?.(entry)) {
13
+ continue;
14
+ }
15
+ const fullPath = path.join(dir, entry.name);
16
+ if (entry.isDirectory() && options.shouldSkipDirectory?.(fullPath)) {
17
+ continue;
18
+ }
19
+ const result = visitor(fullPath, entry);
20
+ if (entry.isDirectory() && result !== 'skip') {
21
+ walkTree(fullPath, visitor, options);
22
+ }
23
+ }
24
+ }
@@ -7,9 +7,9 @@ It contains two pieces:
7
7
 
8
8
  - `project/`: a minimal project with `.agent-run.env` pointing at the bundled
9
9
  config root.
10
- - `agent-config/`: a complete config root with global templates, snippets,
11
- skill templates, a personal memory skill, a profile manifest, profile-local
12
- instructions, and profile overrides.
10
+ - `agent-config/`: a complete config root with shared manifest defaults, global
11
+ templates, snippets, skill templates, a personal memory skill, a sparse
12
+ profile manifest, profile-local instructions, and profile overrides.
13
13
 
14
14
  Try it from this repository after building:
15
15
 
@@ -0,0 +1,38 @@
1
+ {
2
+ // Shared defaults; profile manifests contain only differences.
3
+ "kind": "code",
4
+ "agent": {
5
+ "base": "global/agents/code.md.njk",
6
+ "includes": [
7
+ "{{ profile }}/local.md.njk"
8
+ ]
9
+ },
10
+ "skills": {
11
+ "install": [
12
+ "commit-workflow",
13
+ "github-release",
14
+ "release-package-check",
15
+ "code-review-organizer"
16
+ ]
17
+ },
18
+ "tools": {
19
+ "codex": true,
20
+ "claude": true
21
+ },
22
+ "checks": [
23
+ "agent-run check .",
24
+ "pnpm run cleanbuild"
25
+ ],
26
+ "guardrails": {
27
+ "blockGitWrite": true,
28
+ "blockPublish": true,
29
+ "blockGithubRelease": true,
30
+ "forbidRepoAiFiles": true
31
+ },
32
+ "paths": {
33
+ "changesFile": "{{ projectRoot }}/CHANGES",
34
+ "reviewDir": "{{ profileDir }}/reviews",
35
+ "reviewFile": "{{ profileDir }}/reviews/REVIEW-{{ date }}.md",
36
+ "memoriesDir": "{{ agentDir }}/memories"
37
+ }
38
+ }
@@ -1,6 +1,6 @@
1
1
  # Starter AGENTS for {{ profile }}
2
2
 
3
- Do not edit this generated file. Edit `agent-run.jsonc` and `local.md.njk`.
3
+ Do not edit this generated file. Edit root defaults or profile-specific source files.
4
4
 
5
5
  {% for section in renderedAgentSections %}
6
6
  {{ section }}
@@ -1,8 +1,5 @@
1
1
  {
2
- "profile": "starter/basic-project",
3
- "kind": "code",
4
2
  "agent": {
5
- "base": "global/agents/code.md.njk",
6
3
  "includes": [
7
4
  "{{ profile }}/local.md.njk",
8
5
  "{{ profile }}/project-rules.md.njk"
@@ -20,25 +17,8 @@
20
17
  "triage": "{{ profile }}/overrides/triage.SKILL.md.njk"
21
18
  }
22
19
  },
23
- "tools": {
24
- "codex": true,
25
- "claude": true
26
- },
27
20
  "checks": [
28
21
  "agent-run check .",
29
- "pnpm run cleanbuild",
30
22
  "pnpm test"
31
- ],
32
- "guardrails": {
33
- "blockGitWrite": true,
34
- "blockPublish": true,
35
- "blockGithubRelease": true,
36
- "forbidRepoAiFiles": true
37
- },
38
- "paths": {
39
- "changesFile": "{{ projectRoot }}/CHANGES",
40
- "reviewDir": "{{ profileDir }}/reviews",
41
- "reviewFile": "{{ profileDir }}/reviews/REVIEW-{{ date }}.md",
42
- "memoriesDir": "{{ agentDir }}/memories"
43
- }
23
+ ]
44
24
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@technomoron/agent-run",
3
- "version": "0.99.24",
3
+ "version": "0.99.26",
4
4
  "packageManager": "pnpm@10.28.1",
5
5
  "bin": {
6
6
  "agent-run": "dist/agent-run.js"