@ouro.bot/cli 0.1.0-alpha.637 → 0.1.0-alpha.639
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/heart/core.js
CHANGED
|
@@ -344,6 +344,22 @@ function privateReturnAckLeakError(answer, heldTokens) {
|
|
|
344
344
|
}
|
|
345
345
|
return null;
|
|
346
346
|
}
|
|
347
|
+
function claimsPrivateReturnQueued(answer) {
|
|
348
|
+
if (!answer)
|
|
349
|
+
return false;
|
|
350
|
+
const normalized = answer.toLowerCase();
|
|
351
|
+
return /\b(queued|queue|will return|return when|when .*complete|when .*completes|private pass|inner dialog completes|later)\b/.test(normalized)
|
|
352
|
+
&& /\b(private|inner|return|queued|later)\b/.test(normalized);
|
|
353
|
+
}
|
|
354
|
+
function privateReturnMissingPonderError(input) {
|
|
355
|
+
if (input.sawPonder)
|
|
356
|
+
return null;
|
|
357
|
+
if (!looksLikePrivateReturnRequest(input.latestUserRequest))
|
|
358
|
+
return null;
|
|
359
|
+
if (!claimsPrivateReturnQueued(input.answer))
|
|
360
|
+
return null;
|
|
361
|
+
return "private-return acknowledgement claimed work was queued, but no ponder packet was created this turn. Call ponder(action=create, ...) first so the return has a packet, return obligation, and inner wake; then settle with only a queued acknowledgement. If you cannot create the packet, ask a blocking clarification without saying it is queued.";
|
|
362
|
+
}
|
|
347
363
|
function activeReturnObligationId(agentName, obligationId) {
|
|
348
364
|
if (!obligationId)
|
|
349
365
|
return null;
|
|
@@ -996,6 +1012,11 @@ async function runAgent(messages, callbacks, channel, signal, options) {
|
|
|
996
1012
|
}
|
|
997
1013
|
const deliveredAnswer = answer;
|
|
998
1014
|
const retryError = privateReturnAckLeakError(deliveredAnswer, privateReturnHeldTokens)
|
|
1015
|
+
?? privateReturnMissingPonderError({
|
|
1016
|
+
latestUserRequest: latestUserMessageText(messages),
|
|
1017
|
+
answer: deliveredAnswer,
|
|
1018
|
+
sawPonder,
|
|
1019
|
+
})
|
|
999
1020
|
?? getSettleRetryError(mustResolveBeforeHandoffActive, intent, sawSteeringFollowUp, options?.delegationDecision, sawSendMessageSelf, sawPonder, sawQuerySession, options?.currentObligation ?? null, options?.activeWorkFrame?.inner?.job, sawExternalStateQuery);
|
|
1000
1021
|
const validDirectReply = mustResolveBeforeHandoffActive && intent === "direct_reply" && sawSteeringFollowUp;
|
|
1001
1022
|
const validTerminalIntent = intent === "complete" || intent === "blocked";
|
|
@@ -719,6 +719,7 @@ function createDefaultOuroCliDeps(socketPath = socket_client_1.DEFAULT_DAEMON_SO
|
|
|
719
719
|
});
|
|
720
720
|
},
|
|
721
721
|
installCliVersion: async (version) => { (0, ouro_version_manager_1.installVersion)(version, {}); },
|
|
722
|
+
validateCliVersionForActivation: (version) => (0, ouro_version_manager_1.validateInstalledVersionForActivation)(version, {}),
|
|
722
723
|
activateCliVersion: (version) => {
|
|
723
724
|
(0, ouro_version_manager_1.activateVersion)(version, {});
|
|
724
725
|
// Same self-prune as ensureCurrentVersionInstalled — fires from the
|
|
@@ -6112,6 +6112,11 @@ async function runOuroCli(args, deps = (0, cli_defaults_1.createDefaultOuroCliDe
|
|
|
6112
6112
|
return message;
|
|
6113
6113
|
}
|
|
6114
6114
|
}
|
|
6115
|
+
const validation = deps.validateCliVersionForActivation?.(command.version);
|
|
6116
|
+
if (validation && !validation.ok) {
|
|
6117
|
+
const message = `refusing to roll back to ${command.version}: ${validation.message}`;
|
|
6118
|
+
return returnCliFailure(deps, message);
|
|
6119
|
+
}
|
|
6115
6120
|
deps.activateCliVersion(command.version);
|
|
6116
6121
|
}
|
|
6117
6122
|
else {
|
|
@@ -6122,6 +6127,11 @@ async function runOuroCli(args, deps = (0, cli_defaults_1.createDefaultOuroCliDe
|
|
|
6122
6127
|
deps.writeStdout(message);
|
|
6123
6128
|
return message;
|
|
6124
6129
|
}
|
|
6130
|
+
const validation = deps.validateCliVersionForActivation?.(previousVersion);
|
|
6131
|
+
if (validation && !validation.ok) {
|
|
6132
|
+
const message = `refusing to roll back to ${previousVersion}: ${validation.message}`;
|
|
6133
|
+
return returnCliFailure(deps, message);
|
|
6134
|
+
}
|
|
6125
6135
|
deps.activateCliVersion(previousVersion);
|
|
6126
6136
|
command = { ...command, version: previousVersion };
|
|
6127
6137
|
}
|
|
@@ -39,6 +39,7 @@ exports.getCurrentVersion = getCurrentVersion;
|
|
|
39
39
|
exports.getPreviousVersion = getPreviousVersion;
|
|
40
40
|
exports.buildChangelogCommand = buildChangelogCommand;
|
|
41
41
|
exports.listInstalledVersions = listInstalledVersions;
|
|
42
|
+
exports.validateInstalledVersionForActivation = validateInstalledVersionForActivation;
|
|
42
43
|
exports.installVersion = installVersion;
|
|
43
44
|
exports.activateVersion = activateVersion;
|
|
44
45
|
exports.compareCliVersions = compareCliVersions;
|
|
@@ -51,6 +52,31 @@ const path = __importStar(require("path"));
|
|
|
51
52
|
const runtime_1 = require("../../nerves/runtime");
|
|
52
53
|
/** Maximum number of installed CLI versions to retain after pruning. */
|
|
53
54
|
exports.DEFAULT_RETAIN_VERSIONS = 5;
|
|
55
|
+
const INSTALLED_RUNTIME_PACKAGE_PAYLOAD_PATHS = [
|
|
56
|
+
"assets",
|
|
57
|
+
"dist",
|
|
58
|
+
"RepairGuide.ouro",
|
|
59
|
+
"SerpentGuide.ouro",
|
|
60
|
+
"skills",
|
|
61
|
+
"changelog.json",
|
|
62
|
+
"package.json",
|
|
63
|
+
];
|
|
64
|
+
const INSTALLED_RUNTIME_TEXT_EXTENSIONS = new Set([
|
|
65
|
+
".cjs",
|
|
66
|
+
".css",
|
|
67
|
+
".html",
|
|
68
|
+
".js",
|
|
69
|
+
".json",
|
|
70
|
+
".md",
|
|
71
|
+
".mjs",
|
|
72
|
+
".txt",
|
|
73
|
+
]);
|
|
74
|
+
const BLOCKED_INSTALLED_RUNTIME_TEXT_SIGNATURES = [
|
|
75
|
+
{
|
|
76
|
+
label: "removed BlueBubbles timeout notice",
|
|
77
|
+
base64: "bGl2ZSBpTWVzc2FnZSB0dXJuIHRpbWVkIG91dDsgSSBjYXB0dXJlZCBpdCBmb3IgcmVjb3ZlcnkgaW5zdGVhZCBvZiBzaWxlbnRseSBoYW5naW5n",
|
|
78
|
+
},
|
|
79
|
+
];
|
|
54
80
|
function getOuroCliHome(homeDir) {
|
|
55
81
|
/* v8 ignore next -- dep default: tests always inject @preserve */
|
|
56
82
|
const home = homeDir ?? os.homedir();
|
|
@@ -98,6 +124,94 @@ function listInstalledVersions(deps) {
|
|
|
98
124
|
return [];
|
|
99
125
|
}
|
|
100
126
|
}
|
|
127
|
+
function validateInstalledVersionForActivation(version, deps = {}) {
|
|
128
|
+
const cliHome = getOuroCliHome(deps.homeDir);
|
|
129
|
+
/* v8 ignore start -- dep defaults: tests inject @preserve */
|
|
130
|
+
const existsSync = deps.existsSync ?? fs.existsSync;
|
|
131
|
+
const readdirSync = deps.readdirSync ?? ((p, opts) => fs.readdirSync(p, opts));
|
|
132
|
+
const readFileSync = deps.readFileSync ?? fs.readFileSync;
|
|
133
|
+
/* v8 ignore stop */
|
|
134
|
+
const packageRoot = path.join(cliHome, "versions", version, "node_modules", "@ouro.bot", "cli");
|
|
135
|
+
const packageJsonPath = path.join(packageRoot, "package.json");
|
|
136
|
+
if (!existsSync(packageJsonPath)) {
|
|
137
|
+
const message = `installed runtime ${version} is missing its @ouro.bot/cli package; run 'ouro up' to restore the current release`;
|
|
138
|
+
(0, runtime_1.emitNervesEvent)({
|
|
139
|
+
component: "daemon",
|
|
140
|
+
event: "daemon.cli_version_activation_blocked",
|
|
141
|
+
message: "blocked CLI version activation",
|
|
142
|
+
meta: { version, packageRoot, reason: "missing-package" },
|
|
143
|
+
level: "warn",
|
|
144
|
+
});
|
|
145
|
+
return { ok: false, version, packageRoot, violations: ["missing @ouro.bot/cli package"], message };
|
|
146
|
+
}
|
|
147
|
+
const violations = findBlockedInstalledRuntimePayloadText(packageRoot, { existsSync, readdirSync, readFileSync });
|
|
148
|
+
if (violations.length === 0) {
|
|
149
|
+
return { ok: true, version, packageRoot, violations, message: "installed runtime package passed activation guard" };
|
|
150
|
+
}
|
|
151
|
+
const message = `installed runtime ${version} contains blocked package assets (${violations.join(", ")}); run 'ouro up' to stay on the current release`;
|
|
152
|
+
(0, runtime_1.emitNervesEvent)({
|
|
153
|
+
component: "daemon",
|
|
154
|
+
event: "daemon.cli_version_activation_blocked",
|
|
155
|
+
message: "blocked CLI version activation",
|
|
156
|
+
meta: { version, packageRoot, reason: "blocked-package-assets", violations },
|
|
157
|
+
level: "warn",
|
|
158
|
+
});
|
|
159
|
+
return { ok: false, version, packageRoot, violations, message };
|
|
160
|
+
}
|
|
161
|
+
function findBlockedInstalledRuntimePayloadText(packageRoot, deps) {
|
|
162
|
+
const violations = [];
|
|
163
|
+
const blockedText = BLOCKED_INSTALLED_RUNTIME_TEXT_SIGNATURES.map((signature) => ({
|
|
164
|
+
label: signature.label,
|
|
165
|
+
text: Buffer.from(signature.base64, "base64").toString("utf8"),
|
|
166
|
+
}));
|
|
167
|
+
for (const payloadPath of INSTALLED_RUNTIME_PACKAGE_PAYLOAD_PATHS) {
|
|
168
|
+
const absolutePath = path.join(packageRoot, payloadPath);
|
|
169
|
+
if (!deps.existsSync(absolutePath))
|
|
170
|
+
continue;
|
|
171
|
+
collectBlockedTextViolations(packageRoot, absolutePath, payloadPath, blockedText, deps, violations);
|
|
172
|
+
}
|
|
173
|
+
return violations.sort();
|
|
174
|
+
}
|
|
175
|
+
function collectBlockedTextViolations(packageRoot, absolutePath, relativePath, blockedText, deps, violations) {
|
|
176
|
+
let entries = null;
|
|
177
|
+
try {
|
|
178
|
+
entries = deps.readdirSync(absolutePath, { withFileTypes: true });
|
|
179
|
+
}
|
|
180
|
+
catch {
|
|
181
|
+
entries = null;
|
|
182
|
+
}
|
|
183
|
+
if (entries !== null) {
|
|
184
|
+
for (const entry of entries) {
|
|
185
|
+
const childRelativePath = `${relativePath}/${entry.name}`;
|
|
186
|
+
if (entry.isDirectory()) {
|
|
187
|
+
collectBlockedTextViolations(packageRoot, path.join(absolutePath, entry.name), childRelativePath, blockedText, deps, violations);
|
|
188
|
+
}
|
|
189
|
+
else if (entry.isFile()) {
|
|
190
|
+
inspectInstalledRuntimePayloadFile(packageRoot, childRelativePath, blockedText, deps, violations);
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
return;
|
|
194
|
+
}
|
|
195
|
+
inspectInstalledRuntimePayloadFile(packageRoot, relativePath, blockedText, deps, violations);
|
|
196
|
+
}
|
|
197
|
+
function inspectInstalledRuntimePayloadFile(packageRoot, relativePath, blockedText, deps, violations) {
|
|
198
|
+
if (!INSTALLED_RUNTIME_TEXT_EXTENSIONS.has(path.extname(relativePath)))
|
|
199
|
+
return;
|
|
200
|
+
let content = "";
|
|
201
|
+
try {
|
|
202
|
+
content = deps.readFileSync(path.join(packageRoot, relativePath), "utf8");
|
|
203
|
+
}
|
|
204
|
+
catch (error) {
|
|
205
|
+
const reason = error instanceof Error ? error.message : /* v8 ignore next -- defensive: non-Error catch branch @preserve */ String(error);
|
|
206
|
+
violations.push(`${relativePath} could not be inspected: ${reason}`);
|
|
207
|
+
return;
|
|
208
|
+
}
|
|
209
|
+
for (const blocked of blockedText) {
|
|
210
|
+
if (content.includes(blocked.text)) {
|
|
211
|
+
violations.push(`${relativePath} contains ${blocked.label}`);
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
}
|
|
101
215
|
function installVersion(version, deps) {
|
|
102
216
|
const cliHome = getOuroCliHome(deps.homeDir);
|
|
103
217
|
/* v8 ignore start -- dep defaults: tests always inject @preserve */
|