@ouro.bot/cli 0.1.0-alpha.796 → 0.1.0-alpha.799
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/changelog.json +21 -0
- package/deploy/unraid/Dockerfile +2 -2
- package/deploy/unraid/README.txt +693 -215
- package/deploy/unraid/docker-man-template-transaction.mjs +526 -0
- package/deploy/unraid/docker-man-template-xml.cjs +105 -0
- package/deploy/unraid/migrate-sanctuary-bundle.mjs +56 -17
- package/deploy/unraid/sanctuary.ouro/bundle-meta.json +1 -1
- package/deploy/unraid/sanctuary.ouro/psyche/SOUL.md +4 -0
- package/deploy/unraid/sanctuary.ouro/tool-profiles.json +2 -2
- package/deploy/unraid/sanctuary.xml +2 -2
- package/dist/heart/daemon/container-healthcheck.js +16 -0
- package/dist/heart/daemon/container-spec-auditor-main.js +23 -13
- package/dist/heart/daemon/container-spec-auditor.js +93 -33
- package/dist/heart/daemon/daemon-bootstrap-startup.js +38 -8
- package/dist/heart/daemon/daemon-entry.js +12 -1
- package/dist/heart/daemon/sanctuary-bundle-migration.js +411 -81
- package/dist/heart/daemon/sanctuary-package-management.js +103 -0
- package/dist/mind/prompt.js +1 -1
- package/dist/repertoire/tools-unraid.js +2 -1
- package/dist/senses/sanctuary-media-catalog-contract.js +3 -0
- package/dist/senses/sanctuary-runtime.js +7 -0
- package/dist/senses/telegram-effect-adapter.js +7 -6
- package/npm-shrinkwrap.json +2 -2
- package/package.json +1 -1
|
@@ -0,0 +1,103 @@
|
|
|
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.resolveSanctuaryPackageManagedRoots = resolveSanctuaryPackageManagedRoots;
|
|
37
|
+
exports.resolveSanctuaryPackageManagementActivation = resolveSanctuaryPackageManagementActivation;
|
|
38
|
+
exports.requireSanctuaryPackageManagementDecision = requireSanctuaryPackageManagementDecision;
|
|
39
|
+
exports.prepareSanctuaryPackageManagedBundle = prepareSanctuaryPackageManagedBundle;
|
|
40
|
+
const path = __importStar(require("node:path"));
|
|
41
|
+
const runtime_1 = require("../../nerves/runtime");
|
|
42
|
+
const sanctuary_bundle_migration_1 = require("./sanctuary-bundle-migration");
|
|
43
|
+
const daemon_bootstrap_startup_1 = require("./daemon-bootstrap-startup");
|
|
44
|
+
function resolveSanctuaryPackageManagedRoots(input) {
|
|
45
|
+
return {
|
|
46
|
+
packageRoot: path.join(input.repoRoot, "deploy", "unraid", "sanctuary.ouro"),
|
|
47
|
+
agentRoot: path.join(input.bundlesRoot, "sanctuary.ouro"),
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
function invalidDecision() {
|
|
51
|
+
return { kind: "invalid", failure: (0, daemon_bootstrap_startup_1.createSanctuaryBundlePreparationFailure)("roll_back_or_install_verified_release") };
|
|
52
|
+
}
|
|
53
|
+
function resolveSanctuaryPackageManagementActivation(input) {
|
|
54
|
+
if (input.mode !== "production")
|
|
55
|
+
return { kind: "inactive" };
|
|
56
|
+
const indices = input.argv.flatMap((value, index) => value === "--package-managed-agent" ? [index] : []);
|
|
57
|
+
if (indices.length === 0)
|
|
58
|
+
return { kind: "inactive" };
|
|
59
|
+
if (indices.length !== 1)
|
|
60
|
+
return invalidDecision();
|
|
61
|
+
const value = input.argv[indices[0] + 1];
|
|
62
|
+
if (value !== "sanctuary" || input.managedAgents.length !== 1 || input.managedAgents[0] !== "sanctuary")
|
|
63
|
+
return invalidDecision();
|
|
64
|
+
if (!path.isAbsolute(input.repoRoot) || !path.isAbsolute(input.bundlesRoot) || input.runtimePackageVersion.trim() !== input.runtimePackageVersion || input.runtimePackageVersion.length === 0)
|
|
65
|
+
return invalidDecision();
|
|
66
|
+
const roots = resolveSanctuaryPackageManagedRoots(input);
|
|
67
|
+
try {
|
|
68
|
+
const packageIdentity = (0, sanctuary_bundle_migration_1.inspectSanctuaryDirectoryFromBase)(input.repoRoot, ["deploy", "unraid", "sanctuary.ouro"]);
|
|
69
|
+
const agentIdentity = (0, sanctuary_bundle_migration_1.inspectSanctuaryDirectoryFromBase)(input.bundlesRoot, ["sanctuary.ouro"]);
|
|
70
|
+
if (!packageIdentity || !agentIdentity || (0, sanctuary_bundle_migration_1.sanctuaryDirectoriesShareIdentity)(packageIdentity, agentIdentity))
|
|
71
|
+
return invalidDecision();
|
|
72
|
+
}
|
|
73
|
+
catch {
|
|
74
|
+
return invalidDecision();
|
|
75
|
+
}
|
|
76
|
+
return { kind: "active", ...roots, runtimePackageVersion: input.runtimePackageVersion };
|
|
77
|
+
}
|
|
78
|
+
function requireSanctuaryPackageManagementDecision(decision) {
|
|
79
|
+
if (decision.kind === "invalid")
|
|
80
|
+
throw decision.failure;
|
|
81
|
+
}
|
|
82
|
+
function prepareSanctuaryPackageManagedBundle(decision, deps = {}) {
|
|
83
|
+
requireSanctuaryPackageManagementDecision(decision);
|
|
84
|
+
if (decision.kind === "inactive")
|
|
85
|
+
return undefined;
|
|
86
|
+
let inspection;
|
|
87
|
+
try {
|
|
88
|
+
inspection = (deps.ensure ?? sanctuary_bundle_migration_1.ensureSanctuaryPackageManagedBundle)({
|
|
89
|
+
packageRoot: decision.packageRoot,
|
|
90
|
+
agentRoot: decision.agentRoot,
|
|
91
|
+
runtimePackageVersion: decision.runtimePackageVersion,
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
catch {
|
|
95
|
+
throw (0, daemon_bootstrap_startup_1.createSanctuaryBundlePreparationFailure)("run_verified_update_recovery");
|
|
96
|
+
}
|
|
97
|
+
if (!inspection.ok || !inspection.data.ready) {
|
|
98
|
+
const action = inspection.ok ? inspection.data.repair.action : inspection.error.repair.action;
|
|
99
|
+
throw (0, daemon_bootstrap_startup_1.createSanctuaryBundlePreparationFailure)(action === "none" ? "run_verified_update_recovery" : action);
|
|
100
|
+
}
|
|
101
|
+
(0, runtime_1.emitNervesEvent)({ component: "daemon", event: "daemon.sanctuary_package_management_prepared", message: "prepared Sanctuary package-managed bundle", meta: { runtimePackageVersion: inspection.data.runtimePackageVersion, journalState: inspection.data.journalState } });
|
|
102
|
+
return inspection;
|
|
103
|
+
}
|
package/dist/mind/prompt.js
CHANGED
|
@@ -411,7 +411,7 @@ function runtimeInfoSection(channel, options) {
|
|
|
411
411
|
lines.push("this message arrived via a dev tool (e.g. claude code, codex) on behalf of a friend in a sense session. the user can see our conversation. if the dev-tool user asks a direct question, requests stop/pause/confirmation, or the work is complete, i answer with settle. during an active browser/tool/task flow, process comments are feedback to absorb; i keep using tools instead of settling for status. if friction appears, i first look for ad-hoc repairs with the tools i already have. if the friction reveals a harness gap, i create or revise a ponder packet and keep working. ponder does not create an outward deferral by itself.");
|
|
412
412
|
}
|
|
413
413
|
else if (channel === "telegram") {
|
|
414
|
-
lines.push("i am responding in Telegram. i keep replies concise and phone-native. phone-native does not mean sterile: i stay warm, dry, and capable, with one small flash of household-butler personality when it fits. i may use only
|
|
414
|
+
lines.push("i am responding in Telegram. i keep replies concise and phone-native. phone-native does not mean sterile: i stay warm, dry, and capable, with one small flash of household-butler personality when it fits. i may use only Telegram-native *bold*, _italic_, and `inline code` markdown; no markdown links; i write necessary urls in full; no headings, tables, or raw html. i do not introduce myself on boot.");
|
|
415
415
|
}
|
|
416
416
|
else if (channel === "bluebubbles") {
|
|
417
417
|
lines.push("i am responding in iMessage through BlueBubbles. i keep replies short and phone-native. i do not use markdown. i do not introduce myself on boot.");
|
|
@@ -415,6 +415,7 @@ exports.unraidToolDefinitions = [
|
|
|
415
415
|
readDefinition("unraid_get_disks", "Read bounded Sanctuary disk SMART, temperature, and parity health.", "getDisks"),
|
|
416
416
|
readDefinition("unraid_get_notifications", "Read bounded unacknowledged Sanctuary notifications.", "getNotifications"),
|
|
417
417
|
readDefinition("unraid_get_system", "Read bounded Sanctuary system and version health.", "getSystem"),
|
|
418
|
+
readDefinition("sanctuary_get_install_state", "Check whether this Butler installation matches its verified release and report any repair needed.", "getInstallState"),
|
|
418
419
|
readDefinition("unraid_check_services", "Freshly check the fixed public Sanctuary service endpoints and return bounded status with an observation timestamp.", "checkServices"),
|
|
419
420
|
readDefinition("sanctuary_get_download_queue", "Read the bounded live household download queue state, including whether the spend guard has paused it.", "getDownloadQueue"),
|
|
420
421
|
{
|
|
@@ -479,5 +480,5 @@ exports.unraidToolDefinitions = [
|
|
|
479
480
|
component: "repertoire",
|
|
480
481
|
event: "repertoire.unraid_tools_loaded",
|
|
481
482
|
message: "typed Unraid tools loaded",
|
|
482
|
-
meta: { operations:
|
|
483
|
+
meta: { operations: exports.unraidToolDefinitions.length },
|
|
483
484
|
});
|
|
@@ -7,6 +7,7 @@ const REQUIRED_TOOL_NAMES = ["sanctuary_search_media_catalog"];
|
|
|
7
7
|
const HOUSEHOLD_JARGON = /\b(?:bounded|catalog|inventory|endpoint|backend|data shape|pars(?:e|ed|ing)|json|jellyfin|unmanic|sanctuary_search_media_catalog)\b/iu;
|
|
8
8
|
const NEGATED_MEDIA_ACCESS = /\b(?:not|never|none|nothing|zero|inaccessible|invisible|unavailable|broken|failed|failing)\b|\b(?:isn[’']t|won[’']t)\b|\bno\s+access\b|\b(?:lost|lacks?|lacking|without)\s+access\b|\bonly\s+\d|\bfewer\s+than\b|\bsome\s+of\b|\b(?:part|portion|subset)\s+of\b|\bi\s+(?:can(?:not|[’']t)|do\s+not|don[’']t|have\s+no)\b|\bi[’']m\s+not\b/iu;
|
|
9
9
|
const UNSOLICITED_PIVOT = /\b(?:what would you like|what are you in the mood for|would you like me to|do you want me to|want me to|recommend we add)\b/iu;
|
|
10
|
+
const REPORT_LABEL = /(?:^|\n)\s*(?:version|house|the house|render check|status|result)\s*:/iu;
|
|
10
11
|
const TITLE_LIST_GLUE = new Set(["and", "are", "catalog", "film", "films", "from", "have", "here", "in", "is", "library", "movie", "movies", "on", "shelf", "show", "shows", "the", "these", "titles", "we"]);
|
|
11
12
|
const COUNT_ANSWER_GLUE = new Set(["and", "are", "currently", "episodes", "film", "films", "have", "in", "items", "library", "movie", "movies", "on", "shelf", "show", "shows", "the", "there", "tv", "we"]);
|
|
12
13
|
function requestKind(request, titleQuery) {
|
|
@@ -118,6 +119,8 @@ function commonAnswerRejection(answer, technicalDetailRequested) {
|
|
|
118
119
|
}
|
|
119
120
|
if (UNSOLICITED_PIVOT.test(answer))
|
|
120
121
|
return "Answer the media question that was asked, then stop; do not append an unsolicited question or recommendation pivot.";
|
|
122
|
+
if (REPORT_LABEL.test(answer))
|
|
123
|
+
return "Answer conversationally; do not use status-report labels such as version:, house:, render check:, status:, or result:.";
|
|
121
124
|
if (!technicalDetailRequested && HOUSEHOLD_JARGON.test(answer))
|
|
122
125
|
return "Use household language such as shelf or library; omit implementation jargon unless technical detail was requested.";
|
|
123
126
|
return undefined;
|
|
@@ -42,6 +42,8 @@ const path = __importStar(require("node:path"));
|
|
|
42
42
|
const node_crypto_1 = require("node:crypto");
|
|
43
43
|
const node_async_hooks_1 = require("node:async_hooks");
|
|
44
44
|
const identity_1 = require("../heart/identity");
|
|
45
|
+
const sanctuary_bundle_migration_1 = require("../heart/daemon/sanctuary-bundle-migration");
|
|
46
|
+
const sanctuary_package_management_1 = require("../heart/daemon/sanctuary-package-management");
|
|
45
47
|
const machine_identity_1 = require("../heart/machine-identity");
|
|
46
48
|
const runtime_credentials_1 = require("../heart/runtime-credentials");
|
|
47
49
|
const unraid_restart_1 = require("../repertoire/unraid-restart");
|
|
@@ -54,6 +56,7 @@ const sanctuary_grounding_1 = require("./sanctuary-grounding");
|
|
|
54
56
|
const sanctuary_health_1 = require("./sanctuary-health");
|
|
55
57
|
const sanctuary_sab_1 = require("./sanctuary-sab");
|
|
56
58
|
const sanctuary_media_optimization_1 = require("./sanctuary-media-optimization");
|
|
59
|
+
const bundle_manifest_1 = require("../mind/bundle-manifest");
|
|
57
60
|
const sanctuaryToolReceipts = new node_async_hooks_1.AsyncLocalStorage();
|
|
58
61
|
const sanctuaryToolGroundings = new node_async_hooks_1.AsyncLocalStorage();
|
|
59
62
|
const acceptanceLedgerTails = new Map();
|
|
@@ -281,6 +284,10 @@ function createSanctuaryToolContext(agentName) {
|
|
|
281
284
|
getDisks: acceptanceRead("unraid_get_disks", reads.getDisks),
|
|
282
285
|
getNotifications: acceptanceRead("unraid_get_notifications", reads.getNotifications),
|
|
283
286
|
getSystem: acceptanceRead("unraid_get_system", reads.getSystem),
|
|
287
|
+
getInstallState: acceptanceRead("sanctuary_get_install_state", async () => (0, sanctuary_bundle_migration_1.inspectSanctuaryPackageManagedBundle)({
|
|
288
|
+
...(0, sanctuary_package_management_1.resolveSanctuaryPackageManagedRoots)({ repoRoot: (0, identity_1.getRepoRoot)(), bundlesRoot: (0, identity_1.getAgentBundlesRoot)() }),
|
|
289
|
+
runtimePackageVersion: (0, bundle_manifest_1.getPackageVersion)(),
|
|
290
|
+
})),
|
|
284
291
|
checkServices: acceptanceRead("unraid_check_services", async () => {
|
|
285
292
|
const services = await Promise.all(sanctuary_health_1.SANCTUARY_PUBLIC_ENDPOINTS.map(async (url) => ({ name: new URL(url).hostname.split(".")[0], ...await (0, sanctuary_health_1.probeSanctuaryEndpoint)(url) })));
|
|
286
293
|
return { ok: true, data: { observedAt: new Date().toISOString(), services, degraded: services.some((service) => !service.ok) } };
|
|
@@ -79,21 +79,22 @@ function preparedTexts(effect) {
|
|
|
79
79
|
function renderTelegramButlerHtml(text) {
|
|
80
80
|
let html = "";
|
|
81
81
|
let cursor = 0;
|
|
82
|
-
|
|
82
|
+
const styledText = /`([^`\n]+)`|\*\*([\p{L}\p{N}](?:[^*_`\n]*\S)?)\*\*|\*([\p{L}\p{N}](?:[^*_`\n]*\S)?)\*|_([\p{L}\p{N}](?:[^*_`\n]*\S)?)_/gu;
|
|
83
|
+
for (const match of text.matchAll(styledText)) {
|
|
83
84
|
const gap = text.slice(cursor, match.index);
|
|
84
|
-
if (/[
|
|
85
|
+
if (/[*_`]/u.test(gap))
|
|
85
86
|
return (0, telegram_client_1.escapeTelegramHtml)(text);
|
|
86
87
|
html += (0, telegram_client_1.escapeTelegramHtml)(gap);
|
|
87
88
|
if (match[1] !== undefined)
|
|
88
89
|
html += `<code>${(0, telegram_client_1.escapeTelegramHtml)(match[1])}</code>`;
|
|
89
|
-
else if (match[2] !== undefined)
|
|
90
|
-
html += `<b>${(0, telegram_client_1.escapeTelegramHtml)(match[2])}</b>`;
|
|
90
|
+
else if (match[2] !== undefined || match[3] !== undefined)
|
|
91
|
+
html += `<b>${(0, telegram_client_1.escapeTelegramHtml)((match[2] ?? match[3]))}</b>`;
|
|
91
92
|
else
|
|
92
|
-
html += `<i>${(0, telegram_client_1.escapeTelegramHtml)(match[
|
|
93
|
+
html += `<i>${(0, telegram_client_1.escapeTelegramHtml)(match[4])}</i>`;
|
|
93
94
|
cursor = match.index + match[0].length;
|
|
94
95
|
}
|
|
95
96
|
const tail = text.slice(cursor);
|
|
96
|
-
return /[
|
|
97
|
+
return /[*_`]/u.test(tail) ? (0, telegram_client_1.escapeTelegramHtml)(text) : html + (0, telegram_client_1.escapeTelegramHtml)(tail);
|
|
97
98
|
}
|
|
98
99
|
function assertEffectTarget(target, effect, idempotencyKey) {
|
|
99
100
|
if (target.kind === "admission_gate") {
|
package/npm-shrinkwrap.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ouro.bot/cli",
|
|
3
|
-
"version": "0.1.0-alpha.
|
|
3
|
+
"version": "0.1.0-alpha.799",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "@ouro.bot/cli",
|
|
9
|
-
"version": "0.1.0-alpha.
|
|
9
|
+
"version": "0.1.0-alpha.799",
|
|
10
10
|
"dependencies": {
|
|
11
11
|
"@anthropic-ai/sdk": "^0.78.0",
|
|
12
12
|
"@azure/identity": "^4.13.0",
|