@massa-ai/opencode-plugin 1.60.1 → 1.61.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/agent-profiles/balanced/massa-ai-judge.md +3 -3
- package/agent-profiles/balanced/massa-ai-meta-judge.md +3 -2
- package/agent-profiles/cheap/massa-ai-judge.md +3 -3
- package/agent-profiles/cheap/massa-ai-meta-judge.md +3 -2
- package/agent-profiles/heavy/massa-ai-judge.md +3 -3
- package/agent-profiles/heavy/massa-ai-meta-judge.md +3 -2
- package/agent-profiles/home/massa-ai-judge.md +3 -3
- package/agent-profiles/home/massa-ai-meta-judge.md +3 -2
- package/agent-profiles/local_models/massa-ai-judge.md +3 -3
- package/agent-profiles/local_models/massa-ai-meta-judge.md +3 -2
- package/agent-profiles/open_models/massa-ai-judge.md +3 -3
- package/agent-profiles/open_models/massa-ai-meta-judge.md +3 -2
- package/agent-profiles/work/massa-ai-judge.md +3 -3
- package/agent-profiles/work/massa-ai-meta-judge.md +3 -2
- package/agents/massa-ai-judge.md +3 -3
- package/agents/massa-ai-meta-judge.md +3 -2
- package/dist/config-cli.js +181 -14
- package/dist/index.js +2 -2
- package/package.json +3 -3
|
@@ -80,9 +80,9 @@ next_step: <string>
|
|
|
80
80
|
- References (paths relative to the `massa-ai` skill directory): `references/agent-orchestration.md`, `references/audit-report-io.md` (Judge With Debate Report Contracts).
|
|
81
81
|
|
|
82
82
|
## Model Hint
|
|
83
|
-
See `references/agent-orchestration.md` (Model Diversity Fallback): `
|
|
84
|
-
|
|
85
|
-
assignments.
|
|
83
|
+
See `references/agent-orchestration.md` (Model Diversity Fallback): `judge` carries no
|
|
84
|
+
per-agent override in `skills/model-profiles.json`, so the active profile's host default is
|
|
85
|
+
the per-slot fallback; `workflows/judge-with-debate.md` owns the live slot assignments.
|
|
86
86
|
|
|
87
87
|
## Validation Sensors
|
|
88
88
|
- Every criterion score carries an exact quotation from the artifact.
|
|
@@ -71,8 +71,9 @@ overall: weighted-mean
|
|
|
71
71
|
- References (paths relative to the `massa-ai` skill directory): `references/agent-orchestration.md`, `references/audit-report-io.md` (Judge With Debate Report Contracts).
|
|
72
72
|
|
|
73
73
|
## Model Hint
|
|
74
|
-
See `references/agent-orchestration.md` (Model Diversity Fallback): `
|
|
75
|
-
|
|
74
|
+
See `references/agent-orchestration.md` (Model Diversity Fallback): `meta-judge` carries no
|
|
75
|
+
per-agent override in `skills/model-profiles.json`, so the active profile's host default is
|
|
76
|
+
the fallback; `workflows/judge-with-debate.md` owns the live model assignment.
|
|
76
77
|
|
|
77
78
|
## Validation Sensors
|
|
78
79
|
- Output parses as YAML; weights sum to 1.0 (±0.001); every criterion carries id, name, weight, scale (min 1, max 5), rubric anchors for 1/3/5, and a non-empty checklist.
|
|
@@ -80,9 +80,9 @@ next_step: <string>
|
|
|
80
80
|
- References (paths relative to the `massa-ai` skill directory): `references/agent-orchestration.md`, `references/audit-report-io.md` (Judge With Debate Report Contracts).
|
|
81
81
|
|
|
82
82
|
## Model Hint
|
|
83
|
-
See `references/agent-orchestration.md` (Model Diversity Fallback): `
|
|
84
|
-
|
|
85
|
-
assignments.
|
|
83
|
+
See `references/agent-orchestration.md` (Model Diversity Fallback): `judge` carries no
|
|
84
|
+
per-agent override in `skills/model-profiles.json`, so the active profile's host default is
|
|
85
|
+
the per-slot fallback; `workflows/judge-with-debate.md` owns the live slot assignments.
|
|
86
86
|
|
|
87
87
|
## Validation Sensors
|
|
88
88
|
- Every criterion score carries an exact quotation from the artifact.
|
|
@@ -71,8 +71,9 @@ overall: weighted-mean
|
|
|
71
71
|
- References (paths relative to the `massa-ai` skill directory): `references/agent-orchestration.md`, `references/audit-report-io.md` (Judge With Debate Report Contracts).
|
|
72
72
|
|
|
73
73
|
## Model Hint
|
|
74
|
-
See `references/agent-orchestration.md` (Model Diversity Fallback): `
|
|
75
|
-
|
|
74
|
+
See `references/agent-orchestration.md` (Model Diversity Fallback): `meta-judge` carries no
|
|
75
|
+
per-agent override in `skills/model-profiles.json`, so the active profile's host default is
|
|
76
|
+
the fallback; `workflows/judge-with-debate.md` owns the live model assignment.
|
|
76
77
|
|
|
77
78
|
## Validation Sensors
|
|
78
79
|
- Output parses as YAML; weights sum to 1.0 (±0.001); every criterion carries id, name, weight, scale (min 1, max 5), rubric anchors for 1/3/5, and a non-empty checklist.
|
|
@@ -80,9 +80,9 @@ next_step: <string>
|
|
|
80
80
|
- References (paths relative to the `massa-ai` skill directory): `references/agent-orchestration.md`, `references/audit-report-io.md` (Judge With Debate Report Contracts).
|
|
81
81
|
|
|
82
82
|
## Model Hint
|
|
83
|
-
See `references/agent-orchestration.md` (Model Diversity Fallback): `
|
|
84
|
-
|
|
85
|
-
assignments.
|
|
83
|
+
See `references/agent-orchestration.md` (Model Diversity Fallback): `judge` carries no
|
|
84
|
+
per-agent override in `skills/model-profiles.json`, so the active profile's host default is
|
|
85
|
+
the per-slot fallback; `workflows/judge-with-debate.md` owns the live slot assignments.
|
|
86
86
|
|
|
87
87
|
## Validation Sensors
|
|
88
88
|
- Every criterion score carries an exact quotation from the artifact.
|
|
@@ -71,8 +71,9 @@ overall: weighted-mean
|
|
|
71
71
|
- References (paths relative to the `massa-ai` skill directory): `references/agent-orchestration.md`, `references/audit-report-io.md` (Judge With Debate Report Contracts).
|
|
72
72
|
|
|
73
73
|
## Model Hint
|
|
74
|
-
See `references/agent-orchestration.md` (Model Diversity Fallback): `
|
|
75
|
-
|
|
74
|
+
See `references/agent-orchestration.md` (Model Diversity Fallback): `meta-judge` carries no
|
|
75
|
+
per-agent override in `skills/model-profiles.json`, so the active profile's host default is
|
|
76
|
+
the fallback; `workflows/judge-with-debate.md` owns the live model assignment.
|
|
76
77
|
|
|
77
78
|
## Validation Sensors
|
|
78
79
|
- Output parses as YAML; weights sum to 1.0 (±0.001); every criterion carries id, name, weight, scale (min 1, max 5), rubric anchors for 1/3/5, and a non-empty checklist.
|
|
@@ -80,9 +80,9 @@ next_step: <string>
|
|
|
80
80
|
- References (paths relative to the `massa-ai` skill directory): `references/agent-orchestration.md`, `references/audit-report-io.md` (Judge With Debate Report Contracts).
|
|
81
81
|
|
|
82
82
|
## Model Hint
|
|
83
|
-
See `references/agent-orchestration.md` (Model Diversity Fallback): `
|
|
84
|
-
|
|
85
|
-
assignments.
|
|
83
|
+
See `references/agent-orchestration.md` (Model Diversity Fallback): `judge` carries no
|
|
84
|
+
per-agent override in `skills/model-profiles.json`, so the active profile's host default is
|
|
85
|
+
the per-slot fallback; `workflows/judge-with-debate.md` owns the live slot assignments.
|
|
86
86
|
|
|
87
87
|
## Validation Sensors
|
|
88
88
|
- Every criterion score carries an exact quotation from the artifact.
|
|
@@ -71,8 +71,9 @@ overall: weighted-mean
|
|
|
71
71
|
- References (paths relative to the `massa-ai` skill directory): `references/agent-orchestration.md`, `references/audit-report-io.md` (Judge With Debate Report Contracts).
|
|
72
72
|
|
|
73
73
|
## Model Hint
|
|
74
|
-
See `references/agent-orchestration.md` (Model Diversity Fallback): `
|
|
75
|
-
|
|
74
|
+
See `references/agent-orchestration.md` (Model Diversity Fallback): `meta-judge` carries no
|
|
75
|
+
per-agent override in `skills/model-profiles.json`, so the active profile's host default is
|
|
76
|
+
the fallback; `workflows/judge-with-debate.md` owns the live model assignment.
|
|
76
77
|
|
|
77
78
|
## Validation Sensors
|
|
78
79
|
- Output parses as YAML; weights sum to 1.0 (±0.001); every criterion carries id, name, weight, scale (min 1, max 5), rubric anchors for 1/3/5, and a non-empty checklist.
|
|
@@ -80,9 +80,9 @@ next_step: <string>
|
|
|
80
80
|
- References (paths relative to the `massa-ai` skill directory): `references/agent-orchestration.md`, `references/audit-report-io.md` (Judge With Debate Report Contracts).
|
|
81
81
|
|
|
82
82
|
## Model Hint
|
|
83
|
-
See `references/agent-orchestration.md` (Model Diversity Fallback): `
|
|
84
|
-
|
|
85
|
-
assignments.
|
|
83
|
+
See `references/agent-orchestration.md` (Model Diversity Fallback): `judge` carries no
|
|
84
|
+
per-agent override in `skills/model-profiles.json`, so the active profile's host default is
|
|
85
|
+
the per-slot fallback; `workflows/judge-with-debate.md` owns the live slot assignments.
|
|
86
86
|
|
|
87
87
|
## Validation Sensors
|
|
88
88
|
- Every criterion score carries an exact quotation from the artifact.
|
|
@@ -71,8 +71,9 @@ overall: weighted-mean
|
|
|
71
71
|
- References (paths relative to the `massa-ai` skill directory): `references/agent-orchestration.md`, `references/audit-report-io.md` (Judge With Debate Report Contracts).
|
|
72
72
|
|
|
73
73
|
## Model Hint
|
|
74
|
-
See `references/agent-orchestration.md` (Model Diversity Fallback): `
|
|
75
|
-
|
|
74
|
+
See `references/agent-orchestration.md` (Model Diversity Fallback): `meta-judge` carries no
|
|
75
|
+
per-agent override in `skills/model-profiles.json`, so the active profile's host default is
|
|
76
|
+
the fallback; `workflows/judge-with-debate.md` owns the live model assignment.
|
|
76
77
|
|
|
77
78
|
## Validation Sensors
|
|
78
79
|
- Output parses as YAML; weights sum to 1.0 (±0.001); every criterion carries id, name, weight, scale (min 1, max 5), rubric anchors for 1/3/5, and a non-empty checklist.
|
|
@@ -80,9 +80,9 @@ next_step: <string>
|
|
|
80
80
|
- References (paths relative to the `massa-ai` skill directory): `references/agent-orchestration.md`, `references/audit-report-io.md` (Judge With Debate Report Contracts).
|
|
81
81
|
|
|
82
82
|
## Model Hint
|
|
83
|
-
See `references/agent-orchestration.md` (Model Diversity Fallback): `
|
|
84
|
-
|
|
85
|
-
assignments.
|
|
83
|
+
See `references/agent-orchestration.md` (Model Diversity Fallback): `judge` carries no
|
|
84
|
+
per-agent override in `skills/model-profiles.json`, so the active profile's host default is
|
|
85
|
+
the per-slot fallback; `workflows/judge-with-debate.md` owns the live slot assignments.
|
|
86
86
|
|
|
87
87
|
## Validation Sensors
|
|
88
88
|
- Every criterion score carries an exact quotation from the artifact.
|
|
@@ -71,8 +71,9 @@ overall: weighted-mean
|
|
|
71
71
|
- References (paths relative to the `massa-ai` skill directory): `references/agent-orchestration.md`, `references/audit-report-io.md` (Judge With Debate Report Contracts).
|
|
72
72
|
|
|
73
73
|
## Model Hint
|
|
74
|
-
See `references/agent-orchestration.md` (Model Diversity Fallback): `
|
|
75
|
-
|
|
74
|
+
See `references/agent-orchestration.md` (Model Diversity Fallback): `meta-judge` carries no
|
|
75
|
+
per-agent override in `skills/model-profiles.json`, so the active profile's host default is
|
|
76
|
+
the fallback; `workflows/judge-with-debate.md` owns the live model assignment.
|
|
76
77
|
|
|
77
78
|
## Validation Sensors
|
|
78
79
|
- Output parses as YAML; weights sum to 1.0 (±0.001); every criterion carries id, name, weight, scale (min 1, max 5), rubric anchors for 1/3/5, and a non-empty checklist.
|
|
@@ -80,9 +80,9 @@ next_step: <string>
|
|
|
80
80
|
- References (paths relative to the `massa-ai` skill directory): `references/agent-orchestration.md`, `references/audit-report-io.md` (Judge With Debate Report Contracts).
|
|
81
81
|
|
|
82
82
|
## Model Hint
|
|
83
|
-
See `references/agent-orchestration.md` (Model Diversity Fallback): `
|
|
84
|
-
|
|
85
|
-
assignments.
|
|
83
|
+
See `references/agent-orchestration.md` (Model Diversity Fallback): `judge` carries no
|
|
84
|
+
per-agent override in `skills/model-profiles.json`, so the active profile's host default is
|
|
85
|
+
the per-slot fallback; `workflows/judge-with-debate.md` owns the live slot assignments.
|
|
86
86
|
|
|
87
87
|
## Validation Sensors
|
|
88
88
|
- Every criterion score carries an exact quotation from the artifact.
|
|
@@ -71,8 +71,9 @@ overall: weighted-mean
|
|
|
71
71
|
- References (paths relative to the `massa-ai` skill directory): `references/agent-orchestration.md`, `references/audit-report-io.md` (Judge With Debate Report Contracts).
|
|
72
72
|
|
|
73
73
|
## Model Hint
|
|
74
|
-
See `references/agent-orchestration.md` (Model Diversity Fallback): `
|
|
75
|
-
|
|
74
|
+
See `references/agent-orchestration.md` (Model Diversity Fallback): `meta-judge` carries no
|
|
75
|
+
per-agent override in `skills/model-profiles.json`, so the active profile's host default is
|
|
76
|
+
the fallback; `workflows/judge-with-debate.md` owns the live model assignment.
|
|
76
77
|
|
|
77
78
|
## Validation Sensors
|
|
78
79
|
- Output parses as YAML; weights sum to 1.0 (±0.001); every criterion carries id, name, weight, scale (min 1, max 5), rubric anchors for 1/3/5, and a non-empty checklist.
|
package/agents/massa-ai-judge.md
CHANGED
|
@@ -80,9 +80,9 @@ next_step: <string>
|
|
|
80
80
|
- References (paths relative to the `massa-ai` skill directory): `references/agent-orchestration.md`, `references/audit-report-io.md` (Judge With Debate Report Contracts).
|
|
81
81
|
|
|
82
82
|
## Model Hint
|
|
83
|
-
See `references/agent-orchestration.md` (Model Diversity Fallback): `
|
|
84
|
-
|
|
85
|
-
assignments.
|
|
83
|
+
See `references/agent-orchestration.md` (Model Diversity Fallback): `judge` carries no
|
|
84
|
+
per-agent override in `skills/model-profiles.json`, so the active profile's host default is
|
|
85
|
+
the per-slot fallback; `workflows/judge-with-debate.md` owns the live slot assignments.
|
|
86
86
|
|
|
87
87
|
## Validation Sensors
|
|
88
88
|
- Every criterion score carries an exact quotation from the artifact.
|
|
@@ -71,8 +71,9 @@ overall: weighted-mean
|
|
|
71
71
|
- References (paths relative to the `massa-ai` skill directory): `references/agent-orchestration.md`, `references/audit-report-io.md` (Judge With Debate Report Contracts).
|
|
72
72
|
|
|
73
73
|
## Model Hint
|
|
74
|
-
See `references/agent-orchestration.md` (Model Diversity Fallback): `
|
|
75
|
-
|
|
74
|
+
See `references/agent-orchestration.md` (Model Diversity Fallback): `meta-judge` carries no
|
|
75
|
+
per-agent override in `skills/model-profiles.json`, so the active profile's host default is
|
|
76
|
+
the fallback; `workflows/judge-with-debate.md` owns the live model assignment.
|
|
76
77
|
|
|
77
78
|
## Validation Sensors
|
|
78
79
|
- Output parses as YAML; weights sum to 1.0 (±0.001); every criterion carries id, name, weight, scale (min 1, max 5), rubric anchors for 1/3/5, and a non-empty checklist.
|
package/dist/config-cli.js
CHANGED
|
@@ -985,7 +985,7 @@ function getConfigForEnv() {
|
|
|
985
985
|
} else {
|
|
986
986
|
console.error(`[getConfigForEnv] embedding.provider "${provider}" has no env-projection branch \u2014 no embedding env vars were set`);
|
|
987
987
|
}
|
|
988
|
-
env.
|
|
988
|
+
env.MASSA_AI_LOG_LEVEL = config.logging.level;
|
|
989
989
|
env.ENABLE_METRICS = String(config.logging.enableMetrics);
|
|
990
990
|
return env;
|
|
991
991
|
}
|
|
@@ -1383,7 +1383,7 @@ var defaultConfig = {
|
|
|
1383
1383
|
corsOrigins: envList("MASSA_AI_API_CORS_ORIGINS", fileConfig.security?.corsOrigins ?? [])
|
|
1384
1384
|
},
|
|
1385
1385
|
logging: {
|
|
1386
|
-
level: process.env.
|
|
1386
|
+
level: process.env.MASSA_AI_LOG_LEVEL || fileConfig.logging?.level || "info",
|
|
1387
1387
|
enableMetrics: process.env.ENABLE_METRICS === "true" || process.env.ENABLE_METRICS === undefined && !!fileConfig.logging?.enableMetrics,
|
|
1388
1388
|
file: process.env.MASSA_AI_LOG_FILE || fileConfig.logging?.file || path4.join(resolvedDataDir, "logs", "massa-ai.log"),
|
|
1389
1389
|
enableFileSink: envBool("MASSA_AI_LOG_ENABLE_FILE_SINK", fileConfig.logging?.enableFileSink ?? true),
|
|
@@ -1864,6 +1864,34 @@ var LOG_LEVEL_BUFFER_TAGS = {
|
|
|
1864
1864
|
[LogLevel.WARN]: "warn",
|
|
1865
1865
|
[LogLevel.ERROR]: "error"
|
|
1866
1866
|
};
|
|
1867
|
+
var REPEAT_WINDOW_MS = 15 * 60 * 1000;
|
|
1868
|
+
var MAX_REPEAT_KEYS = 500;
|
|
1869
|
+
function formatAgo(ms) {
|
|
1870
|
+
const totalSeconds = Math.floor(ms / 1000);
|
|
1871
|
+
if (totalSeconds < 60)
|
|
1872
|
+
return `${totalSeconds}s`;
|
|
1873
|
+
return `${Math.floor(totalSeconds / 60)}m`;
|
|
1874
|
+
}
|
|
1875
|
+
var MAX_ERROR_TEXT_CHARS = 300;
|
|
1876
|
+
function capErrorText(value) {
|
|
1877
|
+
if (value.length <= MAX_ERROR_TEXT_CHARS)
|
|
1878
|
+
return value;
|
|
1879
|
+
const truncatedChars = value.length - MAX_ERROR_TEXT_CHARS;
|
|
1880
|
+
return `${value.slice(0, MAX_ERROR_TEXT_CHARS)}\u2026(truncated ${truncatedChars} chars)`;
|
|
1881
|
+
}
|
|
1882
|
+
function pickErrorFields(err, includeStack) {
|
|
1883
|
+
const out = { name: err.name, message: capErrorText(err.message) };
|
|
1884
|
+
if (includeStack)
|
|
1885
|
+
out.stack = err.stack;
|
|
1886
|
+
const code = err.code;
|
|
1887
|
+
if (code !== undefined)
|
|
1888
|
+
out.code = code;
|
|
1889
|
+
const cause = err.cause;
|
|
1890
|
+
if (cause !== undefined) {
|
|
1891
|
+
out.cause = capErrorText(cause instanceof Error ? cause.message : String(cause));
|
|
1892
|
+
}
|
|
1893
|
+
return out;
|
|
1894
|
+
}
|
|
1867
1895
|
|
|
1868
1896
|
class Logger {
|
|
1869
1897
|
_level;
|
|
@@ -1873,6 +1901,7 @@ class Logger {
|
|
|
1873
1901
|
_maxFileSizeBytes;
|
|
1874
1902
|
_maxFiles;
|
|
1875
1903
|
_initialized = false;
|
|
1904
|
+
repeats = new Map;
|
|
1876
1905
|
constructor() {}
|
|
1877
1906
|
ensureInitialized() {
|
|
1878
1907
|
if (!this._initialized) {
|
|
@@ -1933,13 +1962,70 @@ class Logger {
|
|
|
1933
1962
|
shouldLog(level) {
|
|
1934
1963
|
return level >= this.level;
|
|
1935
1964
|
}
|
|
1965
|
+
serializeMetaErrors(meta) {
|
|
1966
|
+
if (!meta)
|
|
1967
|
+
return meta;
|
|
1968
|
+
let out;
|
|
1969
|
+
for (const [key, value] of Object.entries(meta)) {
|
|
1970
|
+
if (value instanceof Error) {
|
|
1971
|
+
if (!out)
|
|
1972
|
+
out = { ...meta };
|
|
1973
|
+
out[key] = pickErrorFields(value, false);
|
|
1974
|
+
}
|
|
1975
|
+
}
|
|
1976
|
+
return out ?? meta;
|
|
1977
|
+
}
|
|
1978
|
+
applyRepeatAccounting(level, message, meta) {
|
|
1979
|
+
if (level !== LogLevel.WARN && level !== LogLevel.ERROR)
|
|
1980
|
+
return meta;
|
|
1981
|
+
const label = typeof meta?.label === "string" ? meta.label : "";
|
|
1982
|
+
const key = `${level}|${message}|${label}`;
|
|
1983
|
+
const now = Date.now();
|
|
1984
|
+
const existing = this.repeats.get(key);
|
|
1985
|
+
if (!existing || now - existing.firstSeenAt > REPEAT_WINDOW_MS) {
|
|
1986
|
+
if (this.repeats.size >= MAX_REPEAT_KEYS)
|
|
1987
|
+
this.repeats.clear();
|
|
1988
|
+
this.repeats.set(key, { firstSeenAt: now, count: 1 });
|
|
1989
|
+
return meta;
|
|
1990
|
+
}
|
|
1991
|
+
existing.count += 1;
|
|
1992
|
+
return {
|
|
1993
|
+
...meta,
|
|
1994
|
+
occurrences: existing.count,
|
|
1995
|
+
firstSeenAgo: formatAgo(now - existing.firstSeenAt)
|
|
1996
|
+
};
|
|
1997
|
+
}
|
|
1998
|
+
_resetRepeatsForTesting() {
|
|
1999
|
+
this.repeats.clear();
|
|
2000
|
+
}
|
|
2001
|
+
safeStringifyMeta(meta) {
|
|
2002
|
+
const seen = new WeakSet;
|
|
2003
|
+
try {
|
|
2004
|
+
return JSON.stringify(meta, (_key, value) => {
|
|
2005
|
+
if (typeof value === "bigint")
|
|
2006
|
+
return value.toString();
|
|
2007
|
+
if (typeof value === "object" && value !== null) {
|
|
2008
|
+
if (seen.has(value))
|
|
2009
|
+
return "[Circular]";
|
|
2010
|
+
seen.add(value);
|
|
2011
|
+
}
|
|
2012
|
+
return value;
|
|
2013
|
+
});
|
|
2014
|
+
} catch (err) {
|
|
2015
|
+
return JSON.stringify({
|
|
2016
|
+
metaUnserializable: err instanceof Error ? err.message : String(err)
|
|
2017
|
+
});
|
|
2018
|
+
}
|
|
2019
|
+
}
|
|
1936
2020
|
formatMessage(level, message, meta, timestamp = new Date().toISOString()) {
|
|
1937
|
-
const metaStr = meta ? ` ${
|
|
2021
|
+
const metaStr = meta ? ` ${this.safeStringifyMeta(meta)}` : "";
|
|
1938
2022
|
return `[${timestamp}] [${level}] ${message}${metaStr}`;
|
|
1939
2023
|
}
|
|
1940
2024
|
emit(level, message, meta) {
|
|
2025
|
+
const serializedMeta = this.serializeMetaErrors(meta);
|
|
2026
|
+
const finalMeta = this.applyRepeatAccounting(level, message, serializedMeta);
|
|
1941
2027
|
const ts = new Date().toISOString();
|
|
1942
|
-
const line = this.formatMessage(LOG_LEVEL_LABELS[level], message,
|
|
2028
|
+
const line = this.formatMessage(LOG_LEVEL_LABELS[level], message, finalMeta, ts);
|
|
1943
2029
|
console.error(line);
|
|
1944
2030
|
if (this.enableFileSink) {
|
|
1945
2031
|
const filePath = this.logFilePath;
|
|
@@ -1951,7 +2037,7 @@ class Logger {
|
|
|
1951
2037
|
ts,
|
|
1952
2038
|
level: LOG_LEVEL_BUFFER_TAGS[level],
|
|
1953
2039
|
message,
|
|
1954
|
-
...
|
|
2040
|
+
...finalMeta ? { meta: finalMeta } : {}
|
|
1955
2041
|
});
|
|
1956
2042
|
}
|
|
1957
2043
|
debug(message, meta) {
|
|
@@ -1973,11 +2059,7 @@ class Logger {
|
|
|
1973
2059
|
if (this.shouldLog(LogLevel.ERROR)) {
|
|
1974
2060
|
const errorMeta = error ? {
|
|
1975
2061
|
...meta,
|
|
1976
|
-
error: {
|
|
1977
|
-
name: error.name,
|
|
1978
|
-
message: error.message,
|
|
1979
|
-
stack: error.stack
|
|
1980
|
-
}
|
|
2062
|
+
error: error instanceof Error ? pickErrorFields(error, true) : { message: String(error) }
|
|
1981
2063
|
} : meta;
|
|
1982
2064
|
this.emit(LogLevel.ERROR, message, errorMeta);
|
|
1983
2065
|
}
|
|
@@ -2071,7 +2153,9 @@ class SmartRateLimiter {
|
|
|
2071
2153
|
const hasRequestCapacity = this.requestLimiter.tryConsume(1);
|
|
2072
2154
|
const hasTokenCapacity = this.tokenLimiter.tryConsume(estimatedTokens);
|
|
2073
2155
|
if (!hasRequestCapacity) {
|
|
2074
|
-
logger.warn("Request rate limit exceeded"
|
|
2156
|
+
logger.warn("Request rate limit exceeded", {
|
|
2157
|
+
availableTokens: this.requestLimiter.getAvailableTokens()
|
|
2158
|
+
});
|
|
2075
2159
|
return false;
|
|
2076
2160
|
}
|
|
2077
2161
|
if (!hasTokenCapacity) {
|
|
@@ -2603,6 +2687,7 @@ function readRoles(liveRoot, activeProfile) {
|
|
|
2603
2687
|
}
|
|
2604
2688
|
function runtimeDriftReport(opts = {}) {
|
|
2605
2689
|
const targetHome = opts.targetHome ?? os6.homedir();
|
|
2690
|
+
const host = opts.host ?? "claude";
|
|
2606
2691
|
const stateFilePath = opts.stateFilePath ?? path10.join(targetHome, ".config", "massa-ai", "install-state.json");
|
|
2607
2692
|
let state = opts.state ?? null;
|
|
2608
2693
|
if (state === null) {
|
|
@@ -2612,9 +2697,24 @@ function runtimeDriftReport(opts = {}) {
|
|
|
2612
2697
|
state = null;
|
|
2613
2698
|
}
|
|
2614
2699
|
}
|
|
2615
|
-
const platform = state?.platforms?.
|
|
2700
|
+
const platform = state?.platforms?.[host];
|
|
2616
2701
|
const stateVersion = typeof platform?.plugin?.version === "string" ? platform.plugin.version : null;
|
|
2617
2702
|
const activeProfile = platform?.modelProfile?.profile ?? null;
|
|
2703
|
+
if (host !== "claude") {
|
|
2704
|
+
return {
|
|
2705
|
+
host,
|
|
2706
|
+
route: "unresolved",
|
|
2707
|
+
liveRoot: null,
|
|
2708
|
+
sourceVersion: null,
|
|
2709
|
+
stateVersion,
|
|
2710
|
+
pinnedVersion: null,
|
|
2711
|
+
activeProfile,
|
|
2712
|
+
roles: [],
|
|
2713
|
+
envOverride: detectEnvOverride(opts.env ?? process.env),
|
|
2714
|
+
versionDrift: false,
|
|
2715
|
+
profileMaterialized: false
|
|
2716
|
+
};
|
|
2717
|
+
}
|
|
2618
2718
|
const install = resolveClaudeMarketplaceInstall({ targetHome, pluginKey: opts.pluginKey });
|
|
2619
2719
|
const liveRoot = install?.root ?? null;
|
|
2620
2720
|
const sourceVersion = liveRoot === null ? null : readPluginVersion(liveRoot);
|
|
@@ -2683,7 +2783,7 @@ function listProfiles(opts = {}) {
|
|
|
2683
2783
|
installed: false,
|
|
2684
2784
|
skipped: false,
|
|
2685
2785
|
skipReason: null,
|
|
2686
|
-
activeProfile: platform2.modelProfile?.profile ??
|
|
2786
|
+
activeProfile: platform2.modelProfile?.profile ?? "balanced",
|
|
2687
2787
|
bundleVersion: platform2.plugin?.version ?? null,
|
|
2688
2788
|
availableProfiles: [],
|
|
2689
2789
|
...claudeDriftFields(host)
|
|
@@ -2710,7 +2810,7 @@ function listProfiles(opts = {}) {
|
|
|
2710
2810
|
installed,
|
|
2711
2811
|
skipped: false,
|
|
2712
2812
|
skipReason: null,
|
|
2713
|
-
activeProfile: platform?.modelProfile?.profile ??
|
|
2813
|
+
activeProfile: platform?.modelProfile?.profile ?? "balanced",
|
|
2714
2814
|
bundleVersion: platform?.plugin?.version ?? null,
|
|
2715
2815
|
availableProfiles,
|
|
2716
2816
|
...claudeDriftFields(host)
|
|
@@ -3676,6 +3776,14 @@ Commands:
|
|
|
3676
3776
|
profile set <name> [--host <h>] [--dry-run]
|
|
3677
3777
|
Switch installed agents to a profile (restart required after)
|
|
3678
3778
|
|
|
3779
|
+
doctor [--fix] [--host <h>] [--target <dir>]
|
|
3780
|
+
Report agent model/profile drift: live-tree vs recorded
|
|
3781
|
+
versions, per-role models, variant staleness, env
|
|
3782
|
+
overrides. --fix re-runs the profile switch for the
|
|
3783
|
+
recorded active profile (restart required after).
|
|
3784
|
+
--target redirects the home the state/registries are
|
|
3785
|
+
read from (test seam, same convention as bootstrap)
|
|
3786
|
+
|
|
3679
3787
|
bootstrap list List every startup-contract rule: state, default, description
|
|
3680
3788
|
bootstrap show Same as 'bootstrap list'
|
|
3681
3789
|
bootstrap enable <rule-id> [--target <dir> --yes] [--dry-run]
|
|
@@ -3693,6 +3801,8 @@ Examples:
|
|
|
3693
3801
|
massa-ai-config set embedding.dimensions 1024
|
|
3694
3802
|
massa-ai-config agents install --user
|
|
3695
3803
|
massa-ai-config profile set work --dry-run
|
|
3804
|
+
massa-ai-config doctor
|
|
3805
|
+
massa-ai-config doctor --fix
|
|
3696
3806
|
massa-ai-config bootstrap list
|
|
3697
3807
|
massa-ai-config bootstrap disable caveman
|
|
3698
3808
|
`);
|
|
@@ -3736,6 +3846,30 @@ function formatSwitchReport(report) {
|
|
|
3736
3846
|
A host session restart is required for the change to take effect.`);
|
|
3737
3847
|
}
|
|
3738
3848
|
}
|
|
3849
|
+
function formatDriftReport(report) {
|
|
3850
|
+
console.log(`doctor (${report.host}, route: ${report.route})`);
|
|
3851
|
+
console.log(` live root: ${report.liveRoot ?? "n/a"}`);
|
|
3852
|
+
console.log(` source version: ${report.sourceVersion ?? "n/a"} (live tree)`);
|
|
3853
|
+
console.log(` state version: ${report.stateVersion ?? "n/a"} (install-state)`);
|
|
3854
|
+
console.log(` pinned version: ${report.pinnedVersion ?? "n/a"} (installed_plugins)`);
|
|
3855
|
+
console.log(` active profile: ${report.activeProfile ?? "n/a"}`);
|
|
3856
|
+
for (const role of report.roles) {
|
|
3857
|
+
const stale = role.staleVariant ? " \u2014 STALE vs the recorded profile's variant" : "";
|
|
3858
|
+
console.log(` ${role.name}: model=${role.model ?? "unknown"} effort=${role.effort ?? "unknown"}${stale}`);
|
|
3859
|
+
}
|
|
3860
|
+
if (report.versionDrift) {
|
|
3861
|
+
console.log(` drift: live tree ${report.sourceVersion} != recorded ${report.stateVersion} \u2014 update the plugin (or re-run the installer)`);
|
|
3862
|
+
}
|
|
3863
|
+
if (report.profileMaterialized) {
|
|
3864
|
+
console.log(" drift: active agent files differ from the recorded profile's variants \u2014 run `massa-ai-config doctor --fix` (re-runs the profile switch)");
|
|
3865
|
+
}
|
|
3866
|
+
if (report.envOverride) {
|
|
3867
|
+
console.log(` override: ${report.envOverride.name}=${report.envOverride.value} wins over every per-agent model at runtime \u2014 remove it from the host env to let profiles govern`);
|
|
3868
|
+
}
|
|
3869
|
+
if (report.route !== "unresolved" && !report.versionDrift && !report.profileMaterialized && !report.envOverride) {
|
|
3870
|
+
console.log(" healthy: every recording agrees.");
|
|
3871
|
+
}
|
|
3872
|
+
}
|
|
3739
3873
|
async function runCli(argv) {
|
|
3740
3874
|
const args = argv;
|
|
3741
3875
|
const command = args[0];
|
|
@@ -3990,6 +4124,39 @@ Using defaults:`);
|
|
|
3990
4124
|
console.error("Usage: massa-ai-config profile <list|show|set> ...");
|
|
3991
4125
|
return 1;
|
|
3992
4126
|
}
|
|
4127
|
+
case "doctor": {
|
|
4128
|
+
const fix = options["fix"] === true;
|
|
4129
|
+
const hostOpt = typeof options.host === "string" ? options.host : undefined;
|
|
4130
|
+
if (hostOpt !== undefined && !isHost(hostOpt)) {
|
|
4131
|
+
console.error(`Error: unknown host "${hostOpt}"`);
|
|
4132
|
+
return 1;
|
|
4133
|
+
}
|
|
4134
|
+
const host = hostOpt ?? "claude";
|
|
4135
|
+
const targetHome = typeof options.target === "string" ? options.target : os9.homedir();
|
|
4136
|
+
try {
|
|
4137
|
+
let report = runtimeDriftReport({ targetHome, host });
|
|
4138
|
+
if (fix) {
|
|
4139
|
+
const profile = report.activeProfile;
|
|
4140
|
+
if (!profile) {
|
|
4141
|
+
console.error("Error: no recorded active profile in install-state.json \u2014 run " + "`massa-ai-config profile set <name>` first; there is nothing to fix from.");
|
|
4142
|
+
return 1;
|
|
4143
|
+
}
|
|
4144
|
+
const sourceRoot = findRepoRootWithMarker(__dirname2, GENERATOR_MARKER, GENERATOR_MARKER_MAX_LEVELS);
|
|
4145
|
+
formatVariantSync(syncGeneratedVariants({ sourceRoot, targetHome }));
|
|
4146
|
+
const switchReport = switchProfile({ profile, host, targetHome });
|
|
4147
|
+
formatSwitchReport(switchReport);
|
|
4148
|
+
if (!reportSucceeded(switchReport)) {
|
|
4149
|
+
return 1;
|
|
4150
|
+
}
|
|
4151
|
+
report = runtimeDriftReport({ targetHome, host });
|
|
4152
|
+
}
|
|
4153
|
+
formatDriftReport(report);
|
|
4154
|
+
return 0;
|
|
4155
|
+
} catch (e) {
|
|
4156
|
+
console.error(`Error: ${e.message}`);
|
|
4157
|
+
return 1;
|
|
4158
|
+
}
|
|
4159
|
+
}
|
|
3993
4160
|
case "bootstrap": {
|
|
3994
4161
|
const subcommand = args[1];
|
|
3995
4162
|
if (subcommand === "list" || subcommand === "show") {
|
package/dist/index.js
CHANGED
|
@@ -984,7 +984,7 @@ function getConfigForEnv() {
|
|
|
984
984
|
} else {
|
|
985
985
|
console.error(`[getConfigForEnv] embedding.provider "${provider}" has no env-projection branch \u2014 no embedding env vars were set`);
|
|
986
986
|
}
|
|
987
|
-
env.
|
|
987
|
+
env.MASSA_AI_LOG_LEVEL = config.logging.level;
|
|
988
988
|
env.ENABLE_METRICS = String(config.logging.enableMetrics);
|
|
989
989
|
return env;
|
|
990
990
|
}
|
|
@@ -1382,7 +1382,7 @@ var defaultConfig = {
|
|
|
1382
1382
|
corsOrigins: envList("MASSA_AI_API_CORS_ORIGINS", fileConfig.security?.corsOrigins ?? [])
|
|
1383
1383
|
},
|
|
1384
1384
|
logging: {
|
|
1385
|
-
level: process.env.
|
|
1385
|
+
level: process.env.MASSA_AI_LOG_LEVEL || fileConfig.logging?.level || "info",
|
|
1386
1386
|
enableMetrics: process.env.ENABLE_METRICS === "true" || process.env.ENABLE_METRICS === undefined && !!fileConfig.logging?.enableMetrics,
|
|
1387
1387
|
file: process.env.MASSA_AI_LOG_FILE || fileConfig.logging?.file || path4.join(resolvedDataDir, "logs", "massa-ai.log"),
|
|
1388
1388
|
enableFileSink: envBool("MASSA_AI_LOG_ENABLE_FILE_SINK", fileConfig.logging?.enableFileSink ?? true),
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@massa-ai/opencode-plugin",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.61.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.61.0",
|
|
28
|
+
"@massa-ai/shared": "^1.61.0"
|
|
29
29
|
},
|
|
30
30
|
"devDependencies": {
|
|
31
31
|
"@types/node": "^22.10.5",
|