@ouro.bot/cli 0.1.0-alpha.552 → 0.1.0-alpha.554
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/README.md +2 -2
- package/RepairGuide.ouro/psyche/IDENTITY.md +1 -1
- package/RepairGuide.ouro/psyche/SOUL.md +1 -1
- package/RepairGuide.ouro/skills/diagnose-stacked-typed-issues.md +4 -4
- package/changelog.json +35 -43
- package/dist/heart/auth/auth-flow.js +3 -3
- package/dist/heart/core.js +0 -12
- package/dist/heart/daemon/agent-config-check.js +75 -168
- package/dist/heart/daemon/agentic-repair.js +2 -9
- package/dist/heart/daemon/cli-defaults.js +72 -42
- package/dist/heart/daemon/cli-exec.js +67 -230
- package/dist/heart/daemon/cli-help.js +1 -1
- package/dist/heart/daemon/cli-render.js +2 -14
- package/dist/heart/daemon/daemon-entry.js +0 -30
- package/dist/heart/daemon/daemon-health.js +0 -7
- package/dist/heart/daemon/daemon-rollup.js +1 -2
- package/dist/heart/daemon/doctor.js +0 -18
- package/dist/heart/daemon/inner-status.js +0 -13
- package/dist/heart/hatch/hatch-flow.js +0 -20
- package/dist/heart/provider-binding-resolver.js +109 -97
- package/dist/heart/provider-credentials.js +2 -2
- package/dist/heart/provider-failover.js +1 -1
- package/dist/heart/provider-readiness-cache.js +40 -0
- package/dist/heart/provider-visibility.js +2 -2
- package/dist/heart/start-of-turn-packet.js +1 -1
- package/dist/senses/pipeline.js +18 -37
- package/package.json +1 -1
- package/RepairGuide.ouro/skills/diagnose-bootstrap-drift.md +0 -54
- package/dist/heart/daemon/drift-detection.js +0 -146
- package/dist/heart/provider-state.js +0 -216
|
@@ -1,146 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
-
if (k2 === undefined) k2 = k;
|
|
4
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
-
}
|
|
8
|
-
Object.defineProperty(o, k2, desc);
|
|
9
|
-
}) : (function(o, m, k, k2) {
|
|
10
|
-
if (k2 === undefined) k2 = k;
|
|
11
|
-
o[k2] = m[k];
|
|
12
|
-
}));
|
|
13
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
-
}) : function(o, v) {
|
|
16
|
-
o["default"] = v;
|
|
17
|
-
});
|
|
18
|
-
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
-
var ownKeys = function(o) {
|
|
20
|
-
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
-
var ar = [];
|
|
22
|
-
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
-
return ar;
|
|
24
|
-
};
|
|
25
|
-
return ownKeys(o);
|
|
26
|
-
};
|
|
27
|
-
return function (mod) {
|
|
28
|
-
if (mod && mod.__esModule) return mod;
|
|
29
|
-
var result = {};
|
|
30
|
-
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
-
__setModuleDefault(result, mod);
|
|
32
|
-
return result;
|
|
33
|
-
};
|
|
34
|
-
})();
|
|
35
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
-
exports.detectProviderBindingDrift = detectProviderBindingDrift;
|
|
37
|
-
exports.loadDriftInputsForAgent = loadDriftInputsForAgent;
|
|
38
|
-
const fs = __importStar(require("fs"));
|
|
39
|
-
const path = __importStar(require("path"));
|
|
40
|
-
const provider_state_1 = require("../provider-state");
|
|
41
|
-
/**
|
|
42
|
-
* Pull the per-lane intent out of an agent.json view, preferring the new
|
|
43
|
-
* `outward`/`inner` keys over the legacy `humanFacing`/`agentFacing` keys
|
|
44
|
-
* when both are present. Returns `null` if neither set carries a usable
|
|
45
|
-
* binding for this lane (the comparator treats that as "no intent to
|
|
46
|
-
* compare against" and emits no drift for that lane).
|
|
47
|
-
*/
|
|
48
|
-
function resolveLaneIntent(agentJson, lane) {
|
|
49
|
-
const newKey = lane === "outward" ? agentJson.outward : agentJson.inner;
|
|
50
|
-
if (newKey && typeof newKey.provider === "string" && typeof newKey.model === "string") {
|
|
51
|
-
return { provider: newKey.provider, model: newKey.model };
|
|
52
|
-
}
|
|
53
|
-
const legacy = lane === "outward" ? agentJson.humanFacing : agentJson.agentFacing;
|
|
54
|
-
if (legacy && typeof legacy.provider === "string" && typeof legacy.model === "string") {
|
|
55
|
-
return { provider: legacy.provider, model: legacy.model };
|
|
56
|
-
}
|
|
57
|
-
return null;
|
|
58
|
-
}
|
|
59
|
-
function buildRepairCommand(agentName, lane, provider, model) {
|
|
60
|
-
return `ouro use --agent ${agentName} --lane ${lane} --provider ${provider} --model ${model}`;
|
|
61
|
-
}
|
|
62
|
-
/**
|
|
63
|
-
* Pure intent-vs-observed comparator. Emits one `DriftFinding` per lane
|
|
64
|
-
* whose intent (agent.json) does not match its observation
|
|
65
|
-
* (state/providers.json).
|
|
66
|
-
*
|
|
67
|
-
* Returns `[]` when:
|
|
68
|
-
* - `providerState === null` (fresh install, nothing to drift against), OR
|
|
69
|
-
* - both lanes match, OR
|
|
70
|
-
* - a lane has no intent in agent.json AND no observation in providerState
|
|
71
|
-
* (deferred to other layers — drift detection is silent on that lane).
|
|
72
|
-
*/
|
|
73
|
-
function detectProviderBindingDrift(input) {
|
|
74
|
-
if (input.providerState === null) {
|
|
75
|
-
return [];
|
|
76
|
-
}
|
|
77
|
-
const findings = [];
|
|
78
|
-
const lanes = ["outward", "inner"];
|
|
79
|
-
for (const lane of lanes) {
|
|
80
|
-
const intent = resolveLaneIntent(input.agentJson, lane);
|
|
81
|
-
if (!intent)
|
|
82
|
-
continue;
|
|
83
|
-
const observed = input.providerState.lanes[lane];
|
|
84
|
-
if (intent.provider === observed.provider && intent.model === observed.model) {
|
|
85
|
-
continue;
|
|
86
|
-
}
|
|
87
|
-
findings.push({
|
|
88
|
-
agent: input.agentName,
|
|
89
|
-
lane,
|
|
90
|
-
intentProvider: intent.provider,
|
|
91
|
-
intentModel: intent.model,
|
|
92
|
-
observedProvider: observed.provider,
|
|
93
|
-
observedModel: observed.model,
|
|
94
|
-
reason: "provider-model-changed",
|
|
95
|
-
repairCommand: buildRepairCommand(input.agentName, lane, intent.provider, intent.model),
|
|
96
|
-
});
|
|
97
|
-
}
|
|
98
|
-
return findings;
|
|
99
|
-
}
|
|
100
|
-
function agentRootFor(bundlesRoot, agentName) {
|
|
101
|
-
return path.join(bundlesRoot, `${agentName}.ouro`);
|
|
102
|
-
}
|
|
103
|
-
function readAgentJson(agentJsonPath) {
|
|
104
|
-
let raw;
|
|
105
|
-
try {
|
|
106
|
-
raw = fs.readFileSync(agentJsonPath, "utf-8");
|
|
107
|
-
}
|
|
108
|
-
catch {
|
|
109
|
-
throw new Error(`agent.json not found at ${agentJsonPath}`);
|
|
110
|
-
}
|
|
111
|
-
let parsed;
|
|
112
|
-
try {
|
|
113
|
-
parsed = JSON.parse(raw);
|
|
114
|
-
}
|
|
115
|
-
catch (error) {
|
|
116
|
-
throw new Error(`agent.json at ${agentJsonPath} contains invalid JSON: ${String(error)}`);
|
|
117
|
-
}
|
|
118
|
-
// The drift loader is intentionally permissive: it parses the file as a
|
|
119
|
-
// typed `AgentConfig` view but does not validate every field. The
|
|
120
|
-
// comparator (Unit 1) is the one that decides which intent fields are
|
|
121
|
-
// usable; non-conforming bindings just silently skip drift detection
|
|
122
|
-
// on that lane. Stricter validation belongs to `loadAgentConfig` in
|
|
123
|
-
// identity.ts (which also has side effects we don't want here).
|
|
124
|
-
return parsed;
|
|
125
|
-
}
|
|
126
|
-
/**
|
|
127
|
-
* Loader for the drift comparator. Reads the per-agent `agent.json` and
|
|
128
|
-
* `state/providers.json` off disk, returning typed inputs ready to feed
|
|
129
|
-
* into `detectProviderBindingDrift`.
|
|
130
|
-
*
|
|
131
|
-
* - Throws when `agent.json` is missing or unparseable. The caller decides
|
|
132
|
-
* whether to swallow (drift detection has no opinion on a broken
|
|
133
|
-
* `agent.json` — that's the existing `agent-config-check` flow's job).
|
|
134
|
-
* - Returns `providerState: null` when `state/providers.json` is missing
|
|
135
|
-
* (fresh install) or invalid (the comparator interprets `null` as "no
|
|
136
|
-
* observation, nothing to drift against").
|
|
137
|
-
* - Never writes to disk.
|
|
138
|
-
*/
|
|
139
|
-
function loadDriftInputsForAgent(bundlesRoot, agentName) {
|
|
140
|
-
const agentRoot = agentRootFor(bundlesRoot, agentName);
|
|
141
|
-
const agentJsonPath = path.join(agentRoot, "agent.json");
|
|
142
|
-
const agentJson = readAgentJson(agentJsonPath);
|
|
143
|
-
const stateResult = (0, provider_state_1.readProviderState)(agentRoot);
|
|
144
|
-
const providerState = stateResult.ok ? stateResult.state : null;
|
|
145
|
-
return { agentJson, providerState };
|
|
146
|
-
}
|
|
@@ -1,216 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
-
if (k2 === undefined) k2 = k;
|
|
4
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
-
}
|
|
8
|
-
Object.defineProperty(o, k2, desc);
|
|
9
|
-
}) : (function(o, m, k, k2) {
|
|
10
|
-
if (k2 === undefined) k2 = k;
|
|
11
|
-
o[k2] = m[k];
|
|
12
|
-
}));
|
|
13
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
-
}) : function(o, v) {
|
|
16
|
-
o["default"] = v;
|
|
17
|
-
});
|
|
18
|
-
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
-
var ownKeys = function(o) {
|
|
20
|
-
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
-
var ar = [];
|
|
22
|
-
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
-
return ar;
|
|
24
|
-
};
|
|
25
|
-
return ownKeys(o);
|
|
26
|
-
};
|
|
27
|
-
return function (mod) {
|
|
28
|
-
if (mod && mod.__esModule) return mod;
|
|
29
|
-
var result = {};
|
|
30
|
-
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
-
__setModuleDefault(result, mod);
|
|
32
|
-
return result;
|
|
33
|
-
};
|
|
34
|
-
})();
|
|
35
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
-
exports.validateProviderState = validateProviderState;
|
|
37
|
-
exports.getProviderStatePath = getProviderStatePath;
|
|
38
|
-
exports.readProviderState = readProviderState;
|
|
39
|
-
exports.writeProviderState = writeProviderState;
|
|
40
|
-
exports.bootstrapProviderStateFromAgentConfig = bootstrapProviderStateFromAgentConfig;
|
|
41
|
-
const fs = __importStar(require("fs"));
|
|
42
|
-
const path = __importStar(require("path"));
|
|
43
|
-
const runtime_1 = require("../nerves/runtime");
|
|
44
|
-
const identity_1 = require("./identity");
|
|
45
|
-
const LANES = ["outward", "inner"];
|
|
46
|
-
const VALID_SOURCES = new Set(["bootstrap", "local"]);
|
|
47
|
-
const VALID_READINESS = new Set(["ready", "failed", "stale", "unknown"]);
|
|
48
|
-
function isProvider(value) {
|
|
49
|
-
return typeof value === "string" && Object.prototype.hasOwnProperty.call(identity_1.PROVIDER_CREDENTIALS, value);
|
|
50
|
-
}
|
|
51
|
-
function isNonEmptyString(value) {
|
|
52
|
-
return typeof value === "string" && value.trim().length > 0;
|
|
53
|
-
}
|
|
54
|
-
function validateBinding(value, label) {
|
|
55
|
-
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
56
|
-
throw new Error(`${label} must be an object`);
|
|
57
|
-
}
|
|
58
|
-
const record = value;
|
|
59
|
-
if (!isProvider(record.provider))
|
|
60
|
-
throw new Error(`${label}.provider must be a valid provider`);
|
|
61
|
-
if (!isNonEmptyString(record.model))
|
|
62
|
-
throw new Error(`${label}.model must be a non-empty string`);
|
|
63
|
-
if (!VALID_SOURCES.has(record.source)) {
|
|
64
|
-
throw new Error(`${label}.source must be bootstrap or local`);
|
|
65
|
-
}
|
|
66
|
-
if (!isNonEmptyString(record.updatedAt))
|
|
67
|
-
throw new Error(`${label}.updatedAt must be a non-empty string`);
|
|
68
|
-
return {
|
|
69
|
-
provider: record.provider,
|
|
70
|
-
model: record.model,
|
|
71
|
-
source: record.source,
|
|
72
|
-
updatedAt: record.updatedAt,
|
|
73
|
-
};
|
|
74
|
-
}
|
|
75
|
-
function validateReadiness(value, label) {
|
|
76
|
-
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
77
|
-
throw new Error(`${label} must be an object`);
|
|
78
|
-
}
|
|
79
|
-
const record = value;
|
|
80
|
-
if (!VALID_READINESS.has(record.status)) {
|
|
81
|
-
throw new Error(`${label}.status must be ready, failed, stale, or unknown`);
|
|
82
|
-
}
|
|
83
|
-
if (!isProvider(record.provider))
|
|
84
|
-
throw new Error(`${label}.provider must be a valid provider`);
|
|
85
|
-
if (!isNonEmptyString(record.model))
|
|
86
|
-
throw new Error(`${label}.model must be a non-empty string`);
|
|
87
|
-
if (record.checkedAt !== undefined && typeof record.checkedAt !== "string") {
|
|
88
|
-
throw new Error(`${label}.checkedAt must be a string when present`);
|
|
89
|
-
}
|
|
90
|
-
if (record.credentialRevision !== undefined && typeof record.credentialRevision !== "string") {
|
|
91
|
-
throw new Error(`${label}.credentialRevision must be a string when present`);
|
|
92
|
-
}
|
|
93
|
-
if (record.error !== undefined && typeof record.error !== "string") {
|
|
94
|
-
throw new Error(`${label}.error must be a string when present`);
|
|
95
|
-
}
|
|
96
|
-
if (record.attempts !== undefined && typeof record.attempts !== "number") {
|
|
97
|
-
throw new Error(`${label}.attempts must be a number when present`);
|
|
98
|
-
}
|
|
99
|
-
return {
|
|
100
|
-
status: record.status,
|
|
101
|
-
provider: record.provider,
|
|
102
|
-
model: record.model,
|
|
103
|
-
...(record.checkedAt !== undefined ? { checkedAt: record.checkedAt } : {}),
|
|
104
|
-
...(record.credentialRevision !== undefined ? { credentialRevision: record.credentialRevision } : {}),
|
|
105
|
-
...(record.error !== undefined ? { error: record.error } : {}),
|
|
106
|
-
...(record.attempts !== undefined ? { attempts: record.attempts } : {}),
|
|
107
|
-
};
|
|
108
|
-
}
|
|
109
|
-
function validateProviderState(value) {
|
|
110
|
-
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
111
|
-
throw new Error("provider state must be an object");
|
|
112
|
-
}
|
|
113
|
-
const record = value;
|
|
114
|
-
if (record.schemaVersion !== 1)
|
|
115
|
-
throw new Error("schemaVersion must be 1");
|
|
116
|
-
if (!isNonEmptyString(record.machineId))
|
|
117
|
-
throw new Error("machineId must be a non-empty string");
|
|
118
|
-
if (!isNonEmptyString(record.updatedAt))
|
|
119
|
-
throw new Error("updatedAt must be a non-empty string");
|
|
120
|
-
if (!record.lanes || typeof record.lanes !== "object" || Array.isArray(record.lanes)) {
|
|
121
|
-
throw new Error("lanes must be an object");
|
|
122
|
-
}
|
|
123
|
-
const rawLanes = record.lanes;
|
|
124
|
-
const lanes = {
|
|
125
|
-
outward: validateBinding(rawLanes.outward, "outward"),
|
|
126
|
-
inner: validateBinding(rawLanes.inner, "inner"),
|
|
127
|
-
};
|
|
128
|
-
if (!record.readiness || typeof record.readiness !== "object" || Array.isArray(record.readiness)) {
|
|
129
|
-
throw new Error("readiness must be an object");
|
|
130
|
-
}
|
|
131
|
-
const rawReadiness = record.readiness;
|
|
132
|
-
const readiness = {};
|
|
133
|
-
for (const lane of LANES) {
|
|
134
|
-
if (rawReadiness[lane] !== undefined) {
|
|
135
|
-
readiness[lane] = validateReadiness(rawReadiness[lane], `${lane}.readiness`);
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
return {
|
|
139
|
-
schemaVersion: 1,
|
|
140
|
-
machineId: record.machineId,
|
|
141
|
-
updatedAt: record.updatedAt,
|
|
142
|
-
lanes,
|
|
143
|
-
readiness,
|
|
144
|
-
};
|
|
145
|
-
}
|
|
146
|
-
function getProviderStatePath(agentRoot) {
|
|
147
|
-
return path.join(agentRoot, "state", "providers.json");
|
|
148
|
-
}
|
|
149
|
-
function readProviderState(agentRoot) {
|
|
150
|
-
const statePath = getProviderStatePath(agentRoot);
|
|
151
|
-
let raw;
|
|
152
|
-
try {
|
|
153
|
-
if (!fs.existsSync(statePath)) {
|
|
154
|
-
return { ok: false, reason: "missing", statePath, error: "provider state not found" };
|
|
155
|
-
}
|
|
156
|
-
}
|
|
157
|
-
catch (error) {
|
|
158
|
-
return { ok: false, reason: "invalid", statePath, error: String(error) };
|
|
159
|
-
}
|
|
160
|
-
try {
|
|
161
|
-
raw = fs.readFileSync(statePath, "utf-8");
|
|
162
|
-
}
|
|
163
|
-
catch (error) {
|
|
164
|
-
const code = error.code;
|
|
165
|
-
if (code === "ENOENT") {
|
|
166
|
-
return { ok: false, reason: "missing", statePath, error: "provider state not found" };
|
|
167
|
-
}
|
|
168
|
-
return { ok: false, reason: "invalid", statePath, error: String(error) };
|
|
169
|
-
}
|
|
170
|
-
try {
|
|
171
|
-
const state = validateProviderState(JSON.parse(raw));
|
|
172
|
-
(0, runtime_1.emitNervesEvent)({
|
|
173
|
-
component: "config/identity",
|
|
174
|
-
event: "config.provider_state_read",
|
|
175
|
-
message: "read provider state",
|
|
176
|
-
meta: { statePath, machineId: state.machineId },
|
|
177
|
-
});
|
|
178
|
-
return { ok: true, statePath, state };
|
|
179
|
-
}
|
|
180
|
-
catch (error) {
|
|
181
|
-
return { ok: false, reason: "invalid", statePath, error: String(error) };
|
|
182
|
-
}
|
|
183
|
-
}
|
|
184
|
-
function writeProviderState(agentRoot, state) {
|
|
185
|
-
const statePath = getProviderStatePath(agentRoot);
|
|
186
|
-
const validated = validateProviderState(state);
|
|
187
|
-
fs.mkdirSync(path.dirname(statePath), { recursive: true });
|
|
188
|
-
fs.writeFileSync(statePath, `${JSON.stringify(validated, null, 2)}\n`, "utf-8");
|
|
189
|
-
(0, runtime_1.emitNervesEvent)({
|
|
190
|
-
component: "config/identity",
|
|
191
|
-
event: "config.provider_state_written",
|
|
192
|
-
message: "wrote provider state",
|
|
193
|
-
meta: { statePath, machineId: validated.machineId },
|
|
194
|
-
});
|
|
195
|
-
}
|
|
196
|
-
function binding(provider, model, updatedAt) {
|
|
197
|
-
return {
|
|
198
|
-
provider,
|
|
199
|
-
model,
|
|
200
|
-
source: "bootstrap",
|
|
201
|
-
updatedAt,
|
|
202
|
-
};
|
|
203
|
-
}
|
|
204
|
-
function bootstrapProviderStateFromAgentConfig(input) {
|
|
205
|
-
const updatedAt = input.now.toISOString();
|
|
206
|
-
return {
|
|
207
|
-
schemaVersion: 1,
|
|
208
|
-
machineId: input.machineId,
|
|
209
|
-
updatedAt,
|
|
210
|
-
lanes: {
|
|
211
|
-
outward: binding(input.agentConfig.humanFacing.provider, input.agentConfig.humanFacing.model, updatedAt),
|
|
212
|
-
inner: binding(input.agentConfig.agentFacing.provider, input.agentConfig.agentFacing.model, updatedAt),
|
|
213
|
-
},
|
|
214
|
-
readiness: {},
|
|
215
|
-
};
|
|
216
|
-
}
|