@massa-ai/opencode-plugin 1.35.1 → 1.37.0
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/config-cli.js +58 -42
- package/dist/index.js +2 -1
- package/package.json +3 -3
package/dist/config-cli.js
CHANGED
|
@@ -995,7 +995,8 @@ var defaultConfig = {
|
|
|
995
995
|
},
|
|
996
996
|
logging: {
|
|
997
997
|
level: process.env.LOG_LEVEL || fileConfig.logging?.level || "info",
|
|
998
|
-
enableMetrics: process.env.ENABLE_METRICS === "true" || process.env.ENABLE_METRICS === undefined && !!fileConfig.logging?.enableMetrics
|
|
998
|
+
enableMetrics: process.env.ENABLE_METRICS === "true" || process.env.ENABLE_METRICS === undefined && !!fileConfig.logging?.enableMetrics,
|
|
999
|
+
file: process.env.MASSA_AI_LOG_FILE || fileConfig.logging?.file || undefined
|
|
999
1000
|
},
|
|
1000
1001
|
synapse: {
|
|
1001
1002
|
enabled: process.env.SYNAPSE_ENABLED !== "false",
|
|
@@ -1276,6 +1277,7 @@ var TaskStatus;
|
|
|
1276
1277
|
TaskStatus2["PAUSED"] = "paused";
|
|
1277
1278
|
})(TaskStatus || (TaskStatus = {}));
|
|
1278
1279
|
// ../../packages/shared/dist/utils/logger.js
|
|
1280
|
+
import fs2 from "fs";
|
|
1279
1281
|
var LogLevel;
|
|
1280
1282
|
(function(LogLevel2) {
|
|
1281
1283
|
LogLevel2[LogLevel2["DEBUG"] = 0] = "DEBUG";
|
|
@@ -1287,17 +1289,20 @@ var LogLevel;
|
|
|
1287
1289
|
class Logger {
|
|
1288
1290
|
_level;
|
|
1289
1291
|
_enableMetrics;
|
|
1292
|
+
_logFilePath;
|
|
1290
1293
|
_initialized = false;
|
|
1291
1294
|
constructor() {}
|
|
1292
1295
|
ensureInitialized() {
|
|
1293
1296
|
if (!this._initialized) {
|
|
1294
1297
|
try {
|
|
1295
|
-
const
|
|
1296
|
-
this._level = this.parseLogLevel(
|
|
1297
|
-
this._enableMetrics =
|
|
1298
|
+
const loggingConfig = config.get("logging");
|
|
1299
|
+
this._level = this.parseLogLevel(loggingConfig.level);
|
|
1300
|
+
this._enableMetrics = loggingConfig.enableMetrics;
|
|
1301
|
+
this._logFilePath = loggingConfig.file;
|
|
1298
1302
|
} catch {
|
|
1299
1303
|
this._level = LogLevel.INFO;
|
|
1300
1304
|
this._enableMetrics = false;
|
|
1305
|
+
this._logFilePath = undefined;
|
|
1301
1306
|
}
|
|
1302
1307
|
this._initialized = true;
|
|
1303
1308
|
}
|
|
@@ -1310,6 +1315,10 @@ class Logger {
|
|
|
1310
1315
|
this.ensureInitialized();
|
|
1311
1316
|
return this._enableMetrics;
|
|
1312
1317
|
}
|
|
1318
|
+
get logFilePath() {
|
|
1319
|
+
this.ensureInitialized();
|
|
1320
|
+
return this._logFilePath;
|
|
1321
|
+
}
|
|
1313
1322
|
parseLogLevel(level) {
|
|
1314
1323
|
const levels = {
|
|
1315
1324
|
debug: LogLevel.DEBUG,
|
|
@@ -1329,6 +1338,13 @@ class Logger {
|
|
|
1329
1338
|
}
|
|
1330
1339
|
write(message, _level) {
|
|
1331
1340
|
console.error(message);
|
|
1341
|
+
const filePath = this.logFilePath;
|
|
1342
|
+
if (filePath) {
|
|
1343
|
+
try {
|
|
1344
|
+
fs2.appendFileSync(filePath, message + `
|
|
1345
|
+
`);
|
|
1346
|
+
} catch {}
|
|
1347
|
+
}
|
|
1332
1348
|
}
|
|
1333
1349
|
debug(message, meta) {
|
|
1334
1350
|
if (this.shouldLog(LogLevel.DEBUG)) {
|
|
@@ -1532,7 +1548,7 @@ function detectRoute(platform) {
|
|
|
1532
1548
|
};
|
|
1533
1549
|
}
|
|
1534
1550
|
// ../../packages/shared/dist/profile-switch/state.js
|
|
1535
|
-
import
|
|
1551
|
+
import fs3 from "fs";
|
|
1536
1552
|
import path6 from "path";
|
|
1537
1553
|
|
|
1538
1554
|
class InstallStateError extends Error {
|
|
@@ -1569,7 +1585,7 @@ function validateShape(raw, filePath) {
|
|
|
1569
1585
|
function readInstallState(filePath) {
|
|
1570
1586
|
let text;
|
|
1571
1587
|
try {
|
|
1572
|
-
text =
|
|
1588
|
+
text = fs3.readFileSync(filePath, "utf-8");
|
|
1573
1589
|
} catch (err) {
|
|
1574
1590
|
const code = err.code;
|
|
1575
1591
|
if (code === "ENOENT")
|
|
@@ -1589,8 +1605,8 @@ function writeInstallState(filePath, state) {
|
|
|
1589
1605
|
const text = `${JSON.stringify(validated, null, 2)}
|
|
1590
1606
|
`;
|
|
1591
1607
|
try {
|
|
1592
|
-
|
|
1593
|
-
|
|
1608
|
+
fs3.mkdirSync(path6.dirname(filePath), { recursive: true });
|
|
1609
|
+
fs3.writeFileSync(filePath, text);
|
|
1594
1610
|
} catch (err) {
|
|
1595
1611
|
throw UnwritableInstallStateError(filePath, err.message);
|
|
1596
1612
|
}
|
|
@@ -1607,7 +1623,7 @@ function updatePlatform(filePath, host, patch) {
|
|
|
1607
1623
|
return next;
|
|
1608
1624
|
}
|
|
1609
1625
|
// ../../packages/shared/dist/profile-switch/lock.js
|
|
1610
|
-
import
|
|
1626
|
+
import fs4 from "fs";
|
|
1611
1627
|
import path7 from "path";
|
|
1612
1628
|
import os4 from "os";
|
|
1613
1629
|
import crypto2 from "crypto";
|
|
@@ -1645,7 +1661,7 @@ var DEFAULT_IDENTITY = {
|
|
|
1645
1661
|
function readOwner(ownerPath) {
|
|
1646
1662
|
let raw;
|
|
1647
1663
|
try {
|
|
1648
|
-
raw = JSON.parse(
|
|
1664
|
+
raw = JSON.parse(fs4.readFileSync(ownerPath, "utf-8"));
|
|
1649
1665
|
} catch {
|
|
1650
1666
|
return null;
|
|
1651
1667
|
}
|
|
@@ -1661,7 +1677,7 @@ function releaseIfOwned(lockDir, ownerPath, token) {
|
|
|
1661
1677
|
const owner = readOwner(ownerPath);
|
|
1662
1678
|
if (owner === null || owner.token !== token)
|
|
1663
1679
|
return;
|
|
1664
|
-
|
|
1680
|
+
fs4.rmSync(lockDir, { recursive: true, force: true });
|
|
1665
1681
|
}
|
|
1666
1682
|
function acquireLock(stateFilePath, options = {}) {
|
|
1667
1683
|
const lockDir = `${stateFilePath}.switch.lock`;
|
|
@@ -1670,11 +1686,11 @@ function acquireLock(stateFilePath, options = {}) {
|
|
|
1670
1686
|
const identity = options.identity ?? DEFAULT_IDENTITY;
|
|
1671
1687
|
const staleAfterMs = options.staleAfterMs ?? DEFAULT_STALE_AFTER_MS;
|
|
1672
1688
|
const createFresh = () => {
|
|
1673
|
-
|
|
1689
|
+
fs4.mkdirSync(lockDir);
|
|
1674
1690
|
const pid = identity.pid();
|
|
1675
1691
|
const startedAt = identity.processStart(pid);
|
|
1676
1692
|
if (startedAt == null) {
|
|
1677
|
-
|
|
1693
|
+
fs4.rmSync(lockDir, { recursive: true, force: true });
|
|
1678
1694
|
throw LockAcquireError(lockDir, "could not determine this process's start-time identity");
|
|
1679
1695
|
}
|
|
1680
1696
|
const token = crypto2.randomUUID();
|
|
@@ -1685,8 +1701,8 @@ function acquireLock(stateFilePath, options = {}) {
|
|
|
1685
1701
|
token,
|
|
1686
1702
|
timestamp: clock.now()
|
|
1687
1703
|
};
|
|
1688
|
-
|
|
1689
|
-
|
|
1704
|
+
fs4.mkdirSync(path7.dirname(ownerPath), { recursive: true });
|
|
1705
|
+
fs4.writeFileSync(ownerPath, JSON.stringify(record));
|
|
1690
1706
|
return { lockDir, release: () => releaseIfOwned(lockDir, ownerPath, token) };
|
|
1691
1707
|
};
|
|
1692
1708
|
try {
|
|
@@ -1701,11 +1717,11 @@ function acquireLock(stateFilePath, options = {}) {
|
|
|
1701
1717
|
throw LockHeldError(lockDir);
|
|
1702
1718
|
const reclaimDir = `${lockDir}.reclaim.${owner.token}`;
|
|
1703
1719
|
try {
|
|
1704
|
-
|
|
1720
|
+
fs4.renameSync(lockDir, reclaimDir);
|
|
1705
1721
|
} catch {
|
|
1706
1722
|
throw LockHeldError(lockDir);
|
|
1707
1723
|
}
|
|
1708
|
-
|
|
1724
|
+
fs4.rmSync(reclaimDir, { recursive: true, force: true });
|
|
1709
1725
|
try {
|
|
1710
1726
|
return createFresh();
|
|
1711
1727
|
} catch {
|
|
@@ -1713,7 +1729,7 @@ function acquireLock(stateFilePath, options = {}) {
|
|
|
1713
1729
|
}
|
|
1714
1730
|
}
|
|
1715
1731
|
// ../../packages/shared/dist/profile-switch/engine.js
|
|
1716
|
-
import
|
|
1732
|
+
import fs5 from "fs";
|
|
1717
1733
|
import path8 from "path";
|
|
1718
1734
|
import os5 from "os";
|
|
1719
1735
|
import crypto3 from "crypto";
|
|
@@ -1755,7 +1771,7 @@ function listProfiles(opts = {}) {
|
|
|
1755
1771
|
availableProfiles: []
|
|
1756
1772
|
};
|
|
1757
1773
|
}
|
|
1758
|
-
const installed =
|
|
1774
|
+
const installed = fs5.existsSync(layout.activeDir);
|
|
1759
1775
|
const availableProfiles = listVariantProfiles(layout);
|
|
1760
1776
|
const platform = state.platforms[host];
|
|
1761
1777
|
return {
|
|
@@ -1771,9 +1787,9 @@ function listProfiles(opts = {}) {
|
|
|
1771
1787
|
return { hosts };
|
|
1772
1788
|
}
|
|
1773
1789
|
function listVariantProfiles(layout) {
|
|
1774
|
-
if (!
|
|
1790
|
+
if (!fs5.existsSync(layout.variantsRoot))
|
|
1775
1791
|
return [];
|
|
1776
|
-
return
|
|
1792
|
+
return fs5.readdirSync(layout.variantsRoot, { withFileTypes: true }).filter((e) => e.isDirectory()).map((e) => e.name).sort();
|
|
1777
1793
|
}
|
|
1778
1794
|
function matchesGlob(filename, glob) {
|
|
1779
1795
|
const starIdx = glob.indexOf("*");
|
|
@@ -1786,32 +1802,32 @@ function matchesGlob(filename, glob) {
|
|
|
1786
1802
|
function assertStateWritable(stateFilePath) {
|
|
1787
1803
|
const dir = path8.dirname(stateFilePath);
|
|
1788
1804
|
try {
|
|
1789
|
-
|
|
1805
|
+
fs5.mkdirSync(dir, { recursive: true });
|
|
1790
1806
|
} catch (err) {
|
|
1791
1807
|
throw UnwritableInstallStateError(stateFilePath, err.message);
|
|
1792
1808
|
}
|
|
1793
|
-
const checkPath =
|
|
1809
|
+
const checkPath = fs5.existsSync(stateFilePath) ? stateFilePath : dir;
|
|
1794
1810
|
try {
|
|
1795
|
-
|
|
1811
|
+
fs5.accessSync(checkPath, fs5.constants.W_OK);
|
|
1796
1812
|
} catch (err) {
|
|
1797
1813
|
throw UnwritableInstallStateError(stateFilePath, err.message);
|
|
1798
1814
|
}
|
|
1799
1815
|
}
|
|
1800
1816
|
function copyFileRouteVariant(layout, variantDir) {
|
|
1801
|
-
|
|
1817
|
+
fs5.mkdirSync(layout.activeDir, { recursive: true });
|
|
1802
1818
|
let changed = 0;
|
|
1803
|
-
for (const entry of
|
|
1819
|
+
for (const entry of fs5.readdirSync(variantDir, { withFileTypes: true })) {
|
|
1804
1820
|
if (!entry.isFile() || !matchesGlob(entry.name, layout.activeGlob))
|
|
1805
1821
|
continue;
|
|
1806
|
-
|
|
1822
|
+
fs5.copyFileSync(path8.join(variantDir, entry.name), path8.join(layout.activeDir, entry.name));
|
|
1807
1823
|
changed++;
|
|
1808
1824
|
}
|
|
1809
1825
|
return changed;
|
|
1810
1826
|
}
|
|
1811
1827
|
function repointOpencodeVariant(layout, variantDir) {
|
|
1812
|
-
|
|
1828
|
+
fs5.mkdirSync(layout.activeDir, { recursive: true });
|
|
1813
1829
|
let changed = 0;
|
|
1814
|
-
for (const entry of
|
|
1830
|
+
for (const entry of fs5.readdirSync(variantDir, { withFileTypes: true })) {
|
|
1815
1831
|
if (!entry.isFile() || !matchesGlob(entry.name, layout.activeGlob))
|
|
1816
1832
|
continue;
|
|
1817
1833
|
const dest = path8.join(layout.activeDir, entry.name);
|
|
@@ -1819,15 +1835,15 @@ function repointOpencodeVariant(layout, variantDir) {
|
|
|
1819
1835
|
let destExists = true;
|
|
1820
1836
|
let destIsSymlink = false;
|
|
1821
1837
|
try {
|
|
1822
|
-
destIsSymlink =
|
|
1838
|
+
destIsSymlink = fs5.lstatSync(dest).isSymbolicLink();
|
|
1823
1839
|
} catch {
|
|
1824
1840
|
destExists = false;
|
|
1825
1841
|
}
|
|
1826
1842
|
if (destExists && !destIsSymlink)
|
|
1827
1843
|
continue;
|
|
1828
1844
|
const tmp = `${dest}.massa-ai-switch.${crypto3.randomUUID()}`;
|
|
1829
|
-
|
|
1830
|
-
|
|
1845
|
+
fs5.symlinkSync(target, tmp);
|
|
1846
|
+
fs5.renameSync(tmp, dest);
|
|
1831
1847
|
changed++;
|
|
1832
1848
|
}
|
|
1833
1849
|
return changed;
|
|
@@ -1849,13 +1865,13 @@ function switchProfile(opts) {
|
|
|
1849
1865
|
if (fileHosts.length === 0) {
|
|
1850
1866
|
return { profile: opts.profile, dryRun, hosts: orderRows(universe, skipRows), restartRequired: false };
|
|
1851
1867
|
}
|
|
1852
|
-
const installedFileHosts = fileHosts.filter((h) =>
|
|
1868
|
+
const installedFileHosts = fileHosts.filter((h) => fs5.existsSync(h.layout.activeDir));
|
|
1853
1869
|
if (installedFileHosts.length === 0)
|
|
1854
1870
|
throw NoHostsDetectedError();
|
|
1855
1871
|
const withAvailability = fileHosts.map((h) => {
|
|
1856
|
-
const variantsRootExists =
|
|
1872
|
+
const variantsRootExists = fs5.existsSync(h.layout.variantsRoot);
|
|
1857
1873
|
const variantDir = h.layout.variantDir(opts.profile);
|
|
1858
|
-
const available = variantsRootExists &&
|
|
1874
|
+
const available = variantsRootExists && fs5.existsSync(variantDir) && fs5.statSync(variantDir).isDirectory();
|
|
1859
1875
|
return { ...h, variantsRootExists, variantDir, available };
|
|
1860
1876
|
});
|
|
1861
1877
|
if (!withAvailability.some((h) => h.available)) {
|
|
@@ -1920,7 +1936,7 @@ function reportSucceeded(report) {
|
|
|
1920
1936
|
return report.hosts.every((h) => h.status === "switched" || h.status === "skipped");
|
|
1921
1937
|
}
|
|
1922
1938
|
// src/config-cli.ts
|
|
1923
|
-
import { promises as
|
|
1939
|
+
import { promises as fs6 } from "fs";
|
|
1924
1940
|
import path9 from "path";
|
|
1925
1941
|
import os6 from "os";
|
|
1926
1942
|
import { fileURLToPath } from "url";
|
|
@@ -2129,15 +2145,15 @@ Using defaults:`);
|
|
|
2129
2145
|
const agentsDir = scope === "project" ? path9.join(process.cwd(), ".opencode/agents") : path9.join(process.env.XDG_CONFIG_HOME && process.env.XDG_CONFIG_HOME.trim() || path9.join(os6.homedir(), ".config"), "opencode", "agents");
|
|
2130
2146
|
const sourceAgentsDir = path9.resolve(__dirname2, "..", "agents");
|
|
2131
2147
|
if (subcommand === "install") {
|
|
2132
|
-
await
|
|
2148
|
+
await fs6.mkdir(agentsDir, { recursive: true });
|
|
2133
2149
|
let count = 0;
|
|
2134
|
-
const entries = await
|
|
2150
|
+
const entries = await fs6.readdir(sourceAgentsDir);
|
|
2135
2151
|
for (const entry of entries) {
|
|
2136
2152
|
if (!entry.startsWith("massa-ai-") || !entry.endsWith(".md"))
|
|
2137
2153
|
continue;
|
|
2138
2154
|
const src = path9.join(sourceAgentsDir, entry);
|
|
2139
2155
|
const dest = path9.join(agentsDir, entry);
|
|
2140
|
-
await
|
|
2156
|
+
await fs6.copyFile(src, dest);
|
|
2141
2157
|
count++;
|
|
2142
2158
|
}
|
|
2143
2159
|
console.log(`+ ${count} subagent specialists (generated from skills/agents/*/SKILL.md)`);
|
|
@@ -2145,14 +2161,14 @@ Using defaults:`);
|
|
|
2145
2161
|
} else {
|
|
2146
2162
|
let removed = 0;
|
|
2147
2163
|
try {
|
|
2148
|
-
const entries = await
|
|
2164
|
+
const entries = await fs6.readdir(agentsDir);
|
|
2149
2165
|
for (const entry of entries) {
|
|
2150
2166
|
if (!entry.startsWith("massa-ai-") || !entry.endsWith(".md"))
|
|
2151
2167
|
continue;
|
|
2152
2168
|
const filePath = path9.join(agentsDir, entry);
|
|
2153
|
-
const content = await
|
|
2169
|
+
const content = await fs6.readFile(filePath, "utf8");
|
|
2154
2170
|
if (content.includes("massa-ai-owned: true")) {
|
|
2155
|
-
await
|
|
2171
|
+
await fs6.unlink(filePath);
|
|
2156
2172
|
removed++;
|
|
2157
2173
|
}
|
|
2158
2174
|
}
|
package/dist/index.js
CHANGED
|
@@ -994,7 +994,8 @@ var defaultConfig = {
|
|
|
994
994
|
},
|
|
995
995
|
logging: {
|
|
996
996
|
level: process.env.LOG_LEVEL || fileConfig.logging?.level || "info",
|
|
997
|
-
enableMetrics: process.env.ENABLE_METRICS === "true" || process.env.ENABLE_METRICS === undefined && !!fileConfig.logging?.enableMetrics
|
|
997
|
+
enableMetrics: process.env.ENABLE_METRICS === "true" || process.env.ENABLE_METRICS === undefined && !!fileConfig.logging?.enableMetrics,
|
|
998
|
+
file: process.env.MASSA_AI_LOG_FILE || fileConfig.logging?.file || undefined
|
|
998
999
|
},
|
|
999
1000
|
synapse: {
|
|
1000
1001
|
enabled: process.env.SYNAPSE_ENABLED !== "false",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@massa-ai/opencode-plugin",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.37.0",
|
|
4
4
|
"description": "massa-ai plugin for OpenCode - Semantic code search, memory, and context compression",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -24,8 +24,8 @@
|
|
|
24
24
|
"dependencies": {
|
|
25
25
|
"@opencode-ai/plugin": "^1.2.15",
|
|
26
26
|
"@opencode-ai/sdk": "^1.2.15",
|
|
27
|
-
"@massa-ai/core": "^1.
|
|
28
|
-
"@massa-ai/shared": "^1.
|
|
27
|
+
"@massa-ai/core": "^1.37.0",
|
|
28
|
+
"@massa-ai/shared": "^1.37.0"
|
|
29
29
|
},
|
|
30
30
|
"devDependencies": {
|
|
31
31
|
"@types/node": "^22.10.5",
|