thoth-agents 0.3.8 → 0.3.9
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/.claude-plugin/marketplace.json +1 -1
- package/README.md +27 -0
- package/dist/{chunk-F2K4CS5J.js → chunk-2TLT6WWY.js} +147 -22
- package/dist/{chunk-6GQYMWWT.js → chunk-MY2GIOOH.js} +1 -1
- package/dist/{chunk-3WNTCPVK.js → chunk-XEEYNMPC.js} +1291 -290
- package/dist/cli/commands.d.ts +1 -0
- package/dist/cli/config-io.d.ts +2 -1
- package/dist/cli/index.js +126 -428
- package/dist/cli/install-completion.d.ts +34 -0
- package/dist/cli/install-ledger.d.ts +44 -0
- package/dist/cli/install.d.ts +9 -1
- package/dist/cli/operations/claude-code.d.ts +12 -1
- package/dist/cli/operations/codex.d.ts +16 -0
- package/dist/cli/operations/opencode.d.ts +20 -3
- package/dist/cli/operations/types.d.ts +13 -0
- package/dist/cli/package-version.d.ts +19 -0
- package/dist/cli/tui/index.js +63 -24
- package/dist/hooks/auto-update-checker/checker.d.ts +0 -5
- package/dist/hooks/auto-update-checker/index.d.ts +1 -2
- package/dist/hooks/auto-update-checker/types.d.ts +0 -1
- package/dist/index.js +98 -251
- package/package.json +1 -1
- package/plugin/.claude-plugin/plugin.json +1 -1
- package/plugin/.codex-plugin/plugin.json +1 -1
- package/dist/hooks/auto-update-checker/cache.d.ts +0 -7
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
{
|
|
10
10
|
"name": "thoth-agents",
|
|
11
11
|
"description": "Adaptive root orchestration, six specialist subagents, and a runtime-autonomous Spec Kit-compatible SDD bundle.",
|
|
12
|
-
"version": "0.3.
|
|
12
|
+
"version": "0.3.9",
|
|
13
13
|
"author": {
|
|
14
14
|
"name": "thoth-agents maintainers"
|
|
15
15
|
},
|
package/README.md
CHANGED
|
@@ -56,6 +56,11 @@ npx thoth-agents@latest install --agent=opencode --dry-run
|
|
|
56
56
|
npx thoth-agents@latest install --agent=opencode
|
|
57
57
|
```
|
|
58
58
|
|
|
59
|
+
Here, `@latest` selects which CLI release runs. That CLI writes the exact
|
|
60
|
+
executing release to OpenCode configuration, for example
|
|
61
|
+
`plugin: ["thoth-agents@0.4.8"]`; it never writes a `latest` plugin entry or
|
|
62
|
+
falls back to one when package identity cannot be verified.
|
|
63
|
+
|
|
59
64
|
Restart OpenCode and initialize the current repository:
|
|
60
65
|
|
|
61
66
|
```text
|
|
@@ -393,9 +398,31 @@ npx thoth-agents@latest list
|
|
|
393
398
|
npx thoth-agents@latest install --agent=opencode
|
|
394
399
|
npx thoth-agents@latest install --agent=codex
|
|
395
400
|
npx thoth-agents@latest install --agent=claude
|
|
401
|
+
npx thoth-agents@latest update --harness=opencode
|
|
402
|
+
npx thoth-agents@latest update --harness=opencode --apply
|
|
396
403
|
npx thoth-agents@latest model --harness=codex --role=deep --model=gpt-5.6-sol
|
|
397
404
|
```
|
|
398
405
|
|
|
406
|
+
`update` previews by default. Applying it performs the same complete refresh as
|
|
407
|
+
installation for the selected harness: OpenCode refreshes its exact plugin pin,
|
|
408
|
+
managed configuration, owned skills, external skills, and provider setup;
|
|
409
|
+
Codex runs native plugin setup before its global agent pack, external skills,
|
|
410
|
+
and provider setup; Claude refreshes its native plugin before external skills
|
|
411
|
+
and provider setup. Any required failure makes the operation fail rather than
|
|
412
|
+
claiming a complete update.
|
|
413
|
+
|
|
414
|
+
After every required step succeeds, the CLI records that harness's executing
|
|
415
|
+
version in
|
|
416
|
+
`${XDG_CONFIG_HOME:-~/.config}/thoth-agents/install-state.json`. `status` shows
|
|
417
|
+
the executing CLI version and this last complete CLI-managed version. The three
|
|
418
|
+
harness records are independent: native Codex or Claude marketplace updates do
|
|
419
|
+
not advance them and do not prove that CLI-managed agents, skills,
|
|
420
|
+
configuration, or provider setup are current.
|
|
421
|
+
|
|
422
|
+
OpenCode's runtime release check is notification-only. It does not rewrite the
|
|
423
|
+
exact plugin pin, invalidate package state, or run a package manager. Follow the
|
|
424
|
+
notification by rerunning the latest CLI installer or applying CLI Update.
|
|
425
|
+
|
|
399
426
|
In the interactive `Configure models` flow, `Apply` is always available. When
|
|
400
427
|
no role is dirty, it reapplies every currently displayed role value; after an
|
|
401
428
|
edit, preview and apply remain limited to the dirty roles. In OpenCode, both
|
|
@@ -5,20 +5,135 @@ import * as path from "path";
|
|
|
5
5
|
// src/cli/config-io.ts
|
|
6
6
|
import {
|
|
7
7
|
copyFileSync,
|
|
8
|
-
existsSync as
|
|
9
|
-
readFileSync,
|
|
8
|
+
existsSync as existsSync3,
|
|
9
|
+
readFileSync as readFileSync2,
|
|
10
10
|
renameSync,
|
|
11
11
|
statSync,
|
|
12
12
|
writeFileSync
|
|
13
13
|
} from "fs";
|
|
14
14
|
|
|
15
|
+
// src/cli/package-version.ts
|
|
16
|
+
import { readFileSync } from "fs";
|
|
17
|
+
import { dirname as dirname2, join as join2 } from "path";
|
|
18
|
+
import { fileURLToPath } from "url";
|
|
19
|
+
|
|
20
|
+
// src/cli/package-root.ts
|
|
21
|
+
import { existsSync } from "fs";
|
|
22
|
+
import { dirname, join, parse } from "path";
|
|
23
|
+
function findPackageRoot(startDir) {
|
|
24
|
+
let currentDir = startDir;
|
|
25
|
+
const filesystemRoot = parse(startDir).root;
|
|
26
|
+
while (true) {
|
|
27
|
+
if (existsSync(join(currentDir, "package.json"))) {
|
|
28
|
+
return currentDir;
|
|
29
|
+
}
|
|
30
|
+
if (currentDir === filesystemRoot) {
|
|
31
|
+
return null;
|
|
32
|
+
}
|
|
33
|
+
const parentDir = dirname(currentDir);
|
|
34
|
+
if (parentDir === currentDir) {
|
|
35
|
+
return null;
|
|
36
|
+
}
|
|
37
|
+
currentDir = parentDir;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// src/cli/package-version.ts
|
|
42
|
+
var EXPECTED_PACKAGE_NAME = "thoth-agents";
|
|
43
|
+
var SEMVER_PATTERN = /^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[A-Za-z-][0-9A-Za-z-]*)(?:\.(?:0|[1-9]\d*|\d*[A-Za-z-][0-9A-Za-z-]*))*))?(?:\+([0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*))?$/;
|
|
44
|
+
function isValidPackageVersion(version) {
|
|
45
|
+
return typeof version === "string" && SEMVER_PATTERN.test(version);
|
|
46
|
+
}
|
|
47
|
+
function resolveExecutingPackageVersion(options = {}) {
|
|
48
|
+
const moduleUrl = options.moduleUrl ?? import.meta.url;
|
|
49
|
+
const packageRoot = findPackageRoot(dirname2(fileURLToPath(moduleUrl)));
|
|
50
|
+
if (!packageRoot) {
|
|
51
|
+
return {
|
|
52
|
+
ok: false,
|
|
53
|
+
error: {
|
|
54
|
+
code: "package-root-not-found",
|
|
55
|
+
message: "Could not locate the executing thoth-agents package root."
|
|
56
|
+
}
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
const packageJsonPath = join2(packageRoot, "package.json");
|
|
60
|
+
let serializedMetadata;
|
|
61
|
+
try {
|
|
62
|
+
serializedMetadata = readFileSync(packageJsonPath, "utf8");
|
|
63
|
+
} catch (error) {
|
|
64
|
+
return {
|
|
65
|
+
ok: false,
|
|
66
|
+
error: {
|
|
67
|
+
code: "package-metadata-unreadable",
|
|
68
|
+
message: `Could not read executing package metadata: ${error}`,
|
|
69
|
+
packageJsonPath
|
|
70
|
+
}
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
let metadata;
|
|
74
|
+
try {
|
|
75
|
+
metadata = JSON.parse(serializedMetadata);
|
|
76
|
+
} catch (error) {
|
|
77
|
+
return {
|
|
78
|
+
ok: false,
|
|
79
|
+
error: {
|
|
80
|
+
code: "package-metadata-malformed",
|
|
81
|
+
message: `Could not parse executing package metadata: ${error}`,
|
|
82
|
+
packageJsonPath
|
|
83
|
+
}
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
if (!metadata || typeof metadata !== "object" || Array.isArray(metadata)) {
|
|
87
|
+
return {
|
|
88
|
+
ok: false,
|
|
89
|
+
error: {
|
|
90
|
+
code: "package-metadata-malformed",
|
|
91
|
+
message: "Executing package metadata must be a JSON object.",
|
|
92
|
+
packageJsonPath
|
|
93
|
+
}
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
const { name, version } = metadata;
|
|
97
|
+
if (typeof name !== "string" || name.length === 0) {
|
|
98
|
+
return {
|
|
99
|
+
ok: false,
|
|
100
|
+
error: {
|
|
101
|
+
code: "package-metadata-malformed",
|
|
102
|
+
message: "Executing package metadata has no valid package name.",
|
|
103
|
+
packageJsonPath
|
|
104
|
+
}
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
if (name !== EXPECTED_PACKAGE_NAME) {
|
|
108
|
+
return {
|
|
109
|
+
ok: false,
|
|
110
|
+
error: {
|
|
111
|
+
code: "package-name-mismatch",
|
|
112
|
+
message: `Expected package ${EXPECTED_PACKAGE_NAME}, received ${name}.`,
|
|
113
|
+
packageJsonPath
|
|
114
|
+
}
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
if (!isValidPackageVersion(version)) {
|
|
118
|
+
return {
|
|
119
|
+
ok: false,
|
|
120
|
+
error: {
|
|
121
|
+
code: "package-version-invalid",
|
|
122
|
+
message: "Executing package metadata has no valid semantic version.",
|
|
123
|
+
packageJsonPath
|
|
124
|
+
}
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
return { ok: true, version, packageRoot };
|
|
128
|
+
}
|
|
129
|
+
|
|
15
130
|
// src/cli/paths.ts
|
|
16
|
-
import { existsSync, mkdirSync } from "fs";
|
|
131
|
+
import { existsSync as existsSync2, mkdirSync } from "fs";
|
|
17
132
|
import { homedir } from "os";
|
|
18
|
-
import { dirname, join } from "path";
|
|
133
|
+
import { dirname as dirname3, join as join3 } from "path";
|
|
19
134
|
function getDefaultOpenCodeConfigDir() {
|
|
20
|
-
const userConfigDir = process.env.XDG_CONFIG_HOME ? process.env.XDG_CONFIG_HOME :
|
|
21
|
-
return
|
|
135
|
+
const userConfigDir = process.env.XDG_CONFIG_HOME ? process.env.XDG_CONFIG_HOME : join3(homedir(), ".config");
|
|
136
|
+
return join3(userConfigDir, "opencode");
|
|
22
137
|
}
|
|
23
138
|
function getCustomOpenCodeConfigDir() {
|
|
24
139
|
const configDir = process.env.OPENCODE_CONFIG_DIR?.trim();
|
|
@@ -33,7 +148,7 @@ function getConfigDir() {
|
|
|
33
148
|
}
|
|
34
149
|
function getOpenCodeConfigPaths() {
|
|
35
150
|
const configDir = getDefaultOpenCodeConfigDir();
|
|
36
|
-
return [
|
|
151
|
+
return [join3(configDir, "opencode.json"), join3(configDir, "opencode.jsonc")];
|
|
37
152
|
}
|
|
38
153
|
function getConfigJson() {
|
|
39
154
|
return getOpenCodeConfigPaths()[0];
|
|
@@ -42,37 +157,37 @@ function getConfigJsonc() {
|
|
|
42
157
|
return getOpenCodeConfigPaths()[1];
|
|
43
158
|
}
|
|
44
159
|
function getLiteConfig() {
|
|
45
|
-
return
|
|
160
|
+
return join3(getConfigDir(), "thoth-agents.json");
|
|
46
161
|
}
|
|
47
162
|
function getLiteConfigJsonc() {
|
|
48
|
-
return
|
|
163
|
+
return join3(getConfigDir(), "thoth-agents.jsonc");
|
|
49
164
|
}
|
|
50
165
|
function getOpenCodeManagedModelStatePath() {
|
|
51
|
-
return
|
|
166
|
+
return join3(getConfigDir(), ".thoth-agents-managed-models.json");
|
|
52
167
|
}
|
|
53
168
|
function getExistingLiteConfigPath() {
|
|
54
169
|
const jsonPath = getLiteConfig();
|
|
55
|
-
if (
|
|
170
|
+
if (existsSync2(jsonPath)) return jsonPath;
|
|
56
171
|
const jsoncPath = getLiteConfigJsonc();
|
|
57
|
-
if (
|
|
172
|
+
if (existsSync2(jsoncPath)) return jsoncPath;
|
|
58
173
|
return jsonPath;
|
|
59
174
|
}
|
|
60
175
|
function getExistingConfigPath() {
|
|
61
176
|
const jsonPath = getConfigJson();
|
|
62
|
-
if (
|
|
177
|
+
if (existsSync2(jsonPath)) return jsonPath;
|
|
63
178
|
const jsoncPath = getConfigJsonc();
|
|
64
|
-
if (
|
|
179
|
+
if (existsSync2(jsoncPath)) return jsoncPath;
|
|
65
180
|
return jsonPath;
|
|
66
181
|
}
|
|
67
182
|
function ensureConfigDir() {
|
|
68
183
|
const configDir = getConfigDir();
|
|
69
|
-
if (!
|
|
184
|
+
if (!existsSync2(configDir)) {
|
|
70
185
|
mkdirSync(configDir, { recursive: true });
|
|
71
186
|
}
|
|
72
187
|
}
|
|
73
188
|
function ensureOpenCodeConfigDir() {
|
|
74
|
-
const configDir =
|
|
75
|
-
if (!
|
|
189
|
+
const configDir = dirname3(getConfigJson());
|
|
190
|
+
if (!existsSync2(configDir)) {
|
|
76
191
|
mkdirSync(configDir, { recursive: true });
|
|
77
192
|
}
|
|
78
193
|
}
|
|
@@ -349,10 +464,10 @@ function stripJsonComments(json) {
|
|
|
349
464
|
}
|
|
350
465
|
function parseConfigFile(path2) {
|
|
351
466
|
try {
|
|
352
|
-
if (!
|
|
467
|
+
if (!existsSync3(path2)) return { config: null };
|
|
353
468
|
const stat = statSync(path2);
|
|
354
469
|
if (stat.size === 0) return { config: null };
|
|
355
|
-
const content =
|
|
470
|
+
const content = readFileSync2(path2, "utf-8");
|
|
356
471
|
if (content.trim().length === 0) return { config: null };
|
|
357
472
|
return { config: JSON.parse(stripJsonComments(content)) };
|
|
358
473
|
} catch (err) {
|
|
@@ -378,7 +493,7 @@ function writeConfig(configPath, config) {
|
|
|
378
493
|
const bakPath = `${configPath}.bak`;
|
|
379
494
|
const content = `${JSON.stringify(config, null, 2)}
|
|
380
495
|
`;
|
|
381
|
-
if (
|
|
496
|
+
if (existsSync3(configPath)) {
|
|
382
497
|
copyFileSync(configPath, bakPath);
|
|
383
498
|
}
|
|
384
499
|
writeFileSync(tmpPath, content);
|
|
@@ -391,7 +506,7 @@ function mergeOpenCodeMainConfig(config, update) {
|
|
|
391
506
|
...plugins.filter(
|
|
392
507
|
(plugin) => plugin !== PACKAGE_NAME && !plugin.startsWith(`${PACKAGE_NAME}@`)
|
|
393
508
|
),
|
|
394
|
-
`${PACKAGE_NAME}
|
|
509
|
+
`${PACKAGE_NAME}@${update.pluginVersion}`
|
|
395
510
|
];
|
|
396
511
|
}
|
|
397
512
|
if (update.disableDefaults) {
|
|
@@ -406,6 +521,13 @@ function mergeOpenCodeMainConfig(config, update) {
|
|
|
406
521
|
}
|
|
407
522
|
function updateOpenCodeMainConfig(update) {
|
|
408
523
|
const configPath = getExistingConfigPath();
|
|
524
|
+
if (update.ensurePlugin && !isValidPackageVersion(update.pluginVersion)) {
|
|
525
|
+
return {
|
|
526
|
+
success: false,
|
|
527
|
+
configPath,
|
|
528
|
+
error: "An approved plugin version is required."
|
|
529
|
+
};
|
|
530
|
+
}
|
|
409
531
|
try {
|
|
410
532
|
ensureOpenCodeConfigDir();
|
|
411
533
|
} catch (err) {
|
|
@@ -446,7 +568,7 @@ function writeLiteConfig(installConfig, targetPath) {
|
|
|
446
568
|
const bakPath = `${configPath}.bak`;
|
|
447
569
|
const content = `${JSON.stringify(config, null, 2)}
|
|
448
570
|
`;
|
|
449
|
-
if (
|
|
571
|
+
if (existsSync3(configPath)) {
|
|
450
572
|
copyFileSync(configPath, bakPath);
|
|
451
573
|
}
|
|
452
574
|
writeFileSync(tmpPath, content);
|
|
@@ -1748,6 +1870,9 @@ export {
|
|
|
1748
1870
|
getDefaultOpenCodeModel,
|
|
1749
1871
|
getDefaultOpenCodeVariant,
|
|
1750
1872
|
POLL_INTERVAL_BACKGROUND_MS,
|
|
1873
|
+
findPackageRoot,
|
|
1874
|
+
isValidPackageVersion,
|
|
1875
|
+
resolveExecutingPackageVersion,
|
|
1751
1876
|
getOpenCodeConfigPaths,
|
|
1752
1877
|
getOpenCodeManagedModelStatePath,
|
|
1753
1878
|
getExistingLiteConfigPath,
|