agent-takkub 1.6.21 → 1.6.23
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.
|
Binary file
|
package/npm/bin/agent-takkub.js
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
const { spawnSync } = require('child_process');
|
|
5
5
|
const {
|
|
6
6
|
venvPythonIfExists,
|
|
7
|
-
|
|
7
|
+
pythonExecutableProblem,
|
|
8
8
|
brokenInterpreterMessage,
|
|
9
9
|
agentTakkubHome,
|
|
10
10
|
} = require('../scripts/lib');
|
|
@@ -14,8 +14,9 @@ if (!py) {
|
|
|
14
14
|
console.error('agent-takkub is not provisioned. Run: npm install -g agent-takkub');
|
|
15
15
|
process.exit(1);
|
|
16
16
|
}
|
|
17
|
-
|
|
18
|
-
|
|
17
|
+
const problem = pythonExecutableProblem(py);
|
|
18
|
+
if (problem) {
|
|
19
|
+
console.error(brokenInterpreterMessage(py, agentTakkubHome(), problem));
|
|
19
20
|
process.exit(1);
|
|
20
21
|
}
|
|
21
22
|
const r = spawnSync(py, ['-m', 'agent_takkub', ...process.argv.slice(2)], { stdio: 'inherit' });
|
package/npm/bin/takkub.js
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
const { spawnSync } = require('child_process');
|
|
5
5
|
const {
|
|
6
6
|
venvPythonIfExists,
|
|
7
|
-
|
|
7
|
+
pythonExecutableProblem,
|
|
8
8
|
brokenInterpreterMessage,
|
|
9
9
|
agentTakkubHome,
|
|
10
10
|
} = require('../scripts/lib');
|
|
@@ -14,8 +14,9 @@ if (!py) {
|
|
|
14
14
|
console.error('takkub is not provisioned. Run: npm install -g agent-takkub');
|
|
15
15
|
process.exit(1);
|
|
16
16
|
}
|
|
17
|
-
|
|
18
|
-
|
|
17
|
+
const problem = pythonExecutableProblem(py);
|
|
18
|
+
if (problem) {
|
|
19
|
+
console.error(brokenInterpreterMessage(py, agentTakkubHome(), problem));
|
|
19
20
|
process.exit(1);
|
|
20
21
|
}
|
|
21
22
|
const r = spawnSync(py, ['-m', 'agent_takkub.cli', ...process.argv.slice(2)], { stdio: 'inherit' });
|
package/npm/scripts/lib.js
CHANGED
|
@@ -53,41 +53,84 @@ function findWheelForVersion(distDir, version) {
|
|
|
53
53
|
// header bytes, no attempt to execute the file) so a broken interpreter is
|
|
54
54
|
// never spawned at all — spawning it is exactly the risky step that can
|
|
55
55
|
// leave the file locked/hard to overwrite during recovery.
|
|
56
|
-
|
|
56
|
+
//
|
|
57
|
+
// The floor only needs to catch truncation (#341's 29-byte case), not judge
|
|
58
|
+
// what a "normal-sized" interpreter looks like — a pyenv/python.org
|
|
59
|
+
// framework build's `bin/pythonX.Y` is a tiny Mach-O stub that re-execs into
|
|
60
|
+
// Python.framework and can be well under 40KB while still being completely
|
|
61
|
+
// runnable (#446). Magic-byte sniffing is what actually distinguishes it
|
|
62
|
+
// from garbage; size only rules out an empty/near-empty file.
|
|
63
|
+
const MIN_PYTHON_EXE_BYTES = 1024;
|
|
64
|
+
|
|
65
|
+
const ELF_MAGIC = 0x7f454c46; // '\x7fELF', big-endian read of the 4 header bytes
|
|
66
|
+
const MACHO_MAGICS = new Set([
|
|
67
|
+
0xfeedface, // MH_MAGIC (32-bit)
|
|
68
|
+
0xcefaedfe, // MH_CIGAM (32-bit, byte-swapped)
|
|
69
|
+
0xfeedfacf, // MH_MAGIC_64
|
|
70
|
+
0xcffaedfe, // MH_CIGAM_64 (byte-swapped)
|
|
71
|
+
0xcafebabe, // FAT_MAGIC (universal/fat binary)
|
|
72
|
+
0xbebafeca, // FAT_CIGAM (universal/fat binary, byte-swapped)
|
|
73
|
+
]);
|
|
57
74
|
|
|
58
75
|
// Opens the path exactly once and stats/reads that same descriptor for the
|
|
59
76
|
// rest of the check — never stat a path and then separately open it, which
|
|
60
77
|
// leaves a window for the file at that name to change between the two
|
|
61
78
|
// syscalls (CodeQL js/file-system-race, alert #29).
|
|
62
|
-
|
|
79
|
+
//
|
|
80
|
+
// Returns null when `py` looks like a real, runnable interpreter, otherwise
|
|
81
|
+
// a short machine-readable reason so callers can explain what specifically
|
|
82
|
+
// failed instead of a single opaque "not a real executable".
|
|
83
|
+
function pythonExecutableProblem(py) {
|
|
63
84
|
let fd;
|
|
64
85
|
try {
|
|
65
86
|
fd = fs.openSync(py, 'r');
|
|
66
87
|
} catch (_e) {
|
|
67
|
-
return
|
|
88
|
+
return 'missing';
|
|
68
89
|
}
|
|
69
90
|
try {
|
|
70
91
|
const stat = fs.fstatSync(fd);
|
|
71
|
-
if (!stat.isFile()
|
|
92
|
+
if (!stat.isFile()) return 'not-a-file';
|
|
93
|
+
if (stat.size < MIN_PYTHON_EXE_BYTES) return 'too-small';
|
|
94
|
+
const buf = Buffer.alloc(4);
|
|
95
|
+
const n = fs.readSync(fd, buf, 0, 4, 0);
|
|
72
96
|
if (process.platform === 'win32') {
|
|
73
97
|
// Windows PE executables always start with the 'MZ' DOS-header magic.
|
|
74
|
-
|
|
75
|
-
fs.readSync(fd, buf, 0, 2, 0);
|
|
76
|
-
return buf[0] === 0x4d && buf[1] === 0x5a; // 'M', 'Z'
|
|
98
|
+
return n >= 2 && buf[0] === 0x4d && buf[1] === 0x5a ? null : 'bad-magic';
|
|
77
99
|
}
|
|
78
|
-
|
|
100
|
+
// POSIX: accept a real ELF or Mach-O binary, or a shebang script — a
|
|
101
|
+
// pyenv shim / venv `python` wrapper is a text file starting with `#!`,
|
|
102
|
+
// not a compiled executable, and is just as valid an interpreter path.
|
|
103
|
+
if (n >= 2 && buf[0] === 0x23 && buf[1] === 0x21) return null; // '#!'
|
|
104
|
+
if (n < 4) return 'bad-magic';
|
|
105
|
+
const magic = buf.readUInt32BE(0);
|
|
106
|
+
if (magic === ELF_MAGIC || MACHO_MAGICS.has(magic)) return null;
|
|
107
|
+
return 'bad-magic';
|
|
79
108
|
} catch (_e) {
|
|
80
|
-
return
|
|
109
|
+
return 'read-error';
|
|
81
110
|
} finally {
|
|
82
111
|
fs.closeSync(fd);
|
|
83
112
|
}
|
|
84
113
|
}
|
|
85
114
|
|
|
86
|
-
function
|
|
115
|
+
function pythonLooksExecutable(py) {
|
|
116
|
+
return pythonExecutableProblem(py) === null;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
const PROBLEM_DESCRIPTIONS = {
|
|
120
|
+
missing: "the file doesn't exist",
|
|
121
|
+
'not-a-file': 'the path exists but is not a regular file (e.g. a directory)',
|
|
122
|
+
'too-small': `the file is smaller than ${MIN_PYTHON_EXE_BYTES} bytes — too small to be a real interpreter`,
|
|
123
|
+
'bad-magic': "the file's header does not match a known executable format (PE/ELF/Mach-O) or a shebang script",
|
|
124
|
+
'read-error': 'the file could not be read to check its header',
|
|
125
|
+
};
|
|
126
|
+
|
|
127
|
+
function brokenInterpreterMessage(py, home, problem) {
|
|
87
128
|
const venvDirPath = path.join(home, 'venv');
|
|
129
|
+
const why = PROBLEM_DESCRIPTIONS[problem] || PROBLEM_DESCRIPTIONS['bad-magic'];
|
|
88
130
|
return (
|
|
89
131
|
`[agent-takkub] the cockpit interpreter looks broken (exists but is not a real executable):\n` +
|
|
90
132
|
` ${py}\n` +
|
|
133
|
+
` Reason: ${why}.\n` +
|
|
91
134
|
' Something outside agent-takkub overwrote or truncated this file — the cockpit\n' +
|
|
92
135
|
' did not do this to itself. Fix:\n' +
|
|
93
136
|
' 1) close every running cockpit/takkub window and process for this install\n' +
|
|
@@ -116,5 +159,6 @@ module.exports = {
|
|
|
116
159
|
venvPythonw,
|
|
117
160
|
findWheelForVersion,
|
|
118
161
|
pythonLooksExecutable,
|
|
162
|
+
pythonExecutableProblem,
|
|
119
163
|
brokenInterpreterMessage,
|
|
120
164
|
};
|
package/package.json
CHANGED
|
@@ -1,50 +1,50 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "agent-takkub",
|
|
3
|
-
"version": "1.6.
|
|
4
|
-
"description": "Desktop cockpit for orchestrating a team of Claude Code agents (Windows + macOS). Install globally: npm i -g agent-takkub",
|
|
5
|
-
"keywords": [
|
|
6
|
-
"claude",
|
|
7
|
-
"claude-code",
|
|
8
|
-
"ai-agents",
|
|
9
|
-
"agent-orchestration",
|
|
10
|
-
"cockpit",
|
|
11
|
-
"desktop",
|
|
12
|
-
"cli",
|
|
13
|
-
"developer-tools"
|
|
14
|
-
],
|
|
15
|
-
"author": "takkub",
|
|
16
|
-
"repository": {
|
|
17
|
-
"type": "git",
|
|
18
|
-
"url": "git+https://github.com/takkub/agent-takkub.git"
|
|
19
|
-
},
|
|
20
|
-
"homepage": "https://github.com/takkub/agent-takkub#readme",
|
|
21
|
-
"bugs": {
|
|
22
|
-
"url": "https://github.com/takkub/agent-takkub/issues"
|
|
23
|
-
},
|
|
24
|
-
"bin": {
|
|
25
|
-
"agent-takkub": "npm/bin/agent-takkub.js",
|
|
26
|
-
"takkub": "npm/bin/takkub.js"
|
|
27
|
-
},
|
|
28
|
-
"scripts": {
|
|
29
|
-
"postinstall": "node npm/scripts/postinstall.js",
|
|
30
|
-
"prepublishOnly": "node npm/scripts/preflight-publish.js",
|
|
31
|
-
"test": "node --test npm/scripts/*.test.js"
|
|
32
|
-
},
|
|
33
|
-
"files": [
|
|
34
|
-
"npm/",
|
|
35
|
-
"!npm/scripts/*.test.js",
|
|
36
|
-
"dist/*.whl",
|
|
37
|
-
"assets/icon.ico",
|
|
38
|
-
"assets/icon.png",
|
|
39
|
-
"assets/cockpit-main.png"
|
|
40
|
-
],
|
|
41
|
-
"os": [
|
|
42
|
-
"win32",
|
|
43
|
-
"darwin"
|
|
44
|
-
],
|
|
45
|
-
"engines": {
|
|
46
|
-
"node": ">=18"
|
|
47
|
-
},
|
|
48
|
-
"engines-note": "This floor is for agent-takkub itself. The OPTIONAL graft code-intelligence feature (installed separately via `takkub doctor --fix`, not an npm dependency of this package) needs Node >=20 — see README's Requirements section. Not raised here because it would force the >=20 floor onto every user even though graft stays off until explicitly enabled.",
|
|
49
|
-
"license": "MIT"
|
|
50
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "agent-takkub",
|
|
3
|
+
"version": "1.6.23",
|
|
4
|
+
"description": "Desktop cockpit for orchestrating a team of Claude Code agents (Windows + macOS). Install globally: npm i -g agent-takkub",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"claude",
|
|
7
|
+
"claude-code",
|
|
8
|
+
"ai-agents",
|
|
9
|
+
"agent-orchestration",
|
|
10
|
+
"cockpit",
|
|
11
|
+
"desktop",
|
|
12
|
+
"cli",
|
|
13
|
+
"developer-tools"
|
|
14
|
+
],
|
|
15
|
+
"author": "takkub",
|
|
16
|
+
"repository": {
|
|
17
|
+
"type": "git",
|
|
18
|
+
"url": "git+https://github.com/takkub/agent-takkub.git"
|
|
19
|
+
},
|
|
20
|
+
"homepage": "https://github.com/takkub/agent-takkub#readme",
|
|
21
|
+
"bugs": {
|
|
22
|
+
"url": "https://github.com/takkub/agent-takkub/issues"
|
|
23
|
+
},
|
|
24
|
+
"bin": {
|
|
25
|
+
"agent-takkub": "npm/bin/agent-takkub.js",
|
|
26
|
+
"takkub": "npm/bin/takkub.js"
|
|
27
|
+
},
|
|
28
|
+
"scripts": {
|
|
29
|
+
"postinstall": "node npm/scripts/postinstall.js",
|
|
30
|
+
"prepublishOnly": "node npm/scripts/preflight-publish.js",
|
|
31
|
+
"test": "node --test npm/scripts/*.test.js"
|
|
32
|
+
},
|
|
33
|
+
"files": [
|
|
34
|
+
"npm/",
|
|
35
|
+
"!npm/scripts/*.test.js",
|
|
36
|
+
"dist/*.whl",
|
|
37
|
+
"assets/icon.ico",
|
|
38
|
+
"assets/icon.png",
|
|
39
|
+
"assets/cockpit-main.png"
|
|
40
|
+
],
|
|
41
|
+
"os": [
|
|
42
|
+
"win32",
|
|
43
|
+
"darwin"
|
|
44
|
+
],
|
|
45
|
+
"engines": {
|
|
46
|
+
"node": ">=18"
|
|
47
|
+
},
|
|
48
|
+
"engines-note": "This floor is for agent-takkub itself. The OPTIONAL graft code-intelligence feature (installed separately via `takkub doctor --fix`, not an npm dependency of this package) needs Node >=20 — see README's Requirements section. Not raised here because it would force the >=20 floor onto every user even though graft stays off until explicitly enabled.",
|
|
49
|
+
"license": "MIT"
|
|
50
|
+
}
|