@ouro.bot/cli 0.1.0-alpha.288 → 0.1.0-alpha.289
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 +6 -0
- package/dist/senses/inner-dialog.js +30 -0
- package/package.json +1 -1
package/changelog.json
CHANGED
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"_note": "This changelog is maintained as part of the PR/version-bump workflow. Agent-curated, not auto-generated. Agents read this file directly via read_file to understand what changed between versions.",
|
|
3
3
|
"versions": [
|
|
4
|
+
{
|
|
5
|
+
"version": "0.1.0-alpha.289",
|
|
6
|
+
"changes": [
|
|
7
|
+
"feat(senses): enforce per-habit tool restrictions during inner dialog turns. When a habit file declares a `tools` field in its frontmatter (e.g., `tools: [read, web_fetch, send_message]`), the inner dialog adapter now filters the full tool repertoire to only those declared tools before passing them to the turn runner. Habits without a `tools` field retain the full repertoire (backwards compatible). Fail-closed design: unknown tool names in the `tools` array are silently excluded rather than causing errors. Two nerves events provide observability: `habit.tools_restricted` (emitted with declared vs resolved tool lists) and `habit.tools_unrestricted` (emitted when a successfully-parsed habit runs with full repertoire). Existing guardrails (protected paths, destructive command blocking) still apply at execution time. 6 new test cases cover restriction, unknown tool exclusion, unrestricted event emission, no event on parse failure, tools passthrough to turn runner, and empty tools array behavior."
|
|
8
|
+
]
|
|
9
|
+
},
|
|
4
10
|
{
|
|
5
11
|
"version": "0.1.0-alpha.288",
|
|
6
12
|
"changes": [
|
|
@@ -53,6 +53,7 @@ const identity_1 = require("../heart/identity");
|
|
|
53
53
|
const context_1 = require("../mind/context");
|
|
54
54
|
const prompt_1 = require("../mind/prompt");
|
|
55
55
|
const mcp_manager_1 = require("../repertoire/mcp-manager");
|
|
56
|
+
const tools_1 = require("../repertoire/tools");
|
|
56
57
|
const bundle_manifest_1 = require("../mind/bundle-manifest");
|
|
57
58
|
const pending_1 = require("../mind/pending");
|
|
58
59
|
const obligations_1 = require("../arc/obligations");
|
|
@@ -535,6 +536,8 @@ async function runInnerDialogTurn(options) {
|
|
|
535
536
|
};
|
|
536
537
|
// ── Adapter concern: build user message ──────────────────────────
|
|
537
538
|
let userContent;
|
|
539
|
+
let habitTools;
|
|
540
|
+
let habitParsedSuccessfully = false;
|
|
538
541
|
if (existingMessages.length === 0) {
|
|
539
542
|
// Fresh session: bootstrap message with non-canonical cleanup nudge
|
|
540
543
|
const aspirations = readAspirations((0, identity_1.getAgentRoot)());
|
|
@@ -568,6 +571,7 @@ async function runInnerDialogTurn(options) {
|
|
|
568
571
|
habitBody = parsed.body || undefined;
|
|
569
572
|
habitTitle = parsed.title || habitName;
|
|
570
573
|
habitLastRun = parsed.lastRun;
|
|
574
|
+
habitTools = parsed.tools;
|
|
571
575
|
}
|
|
572
576
|
catch {
|
|
573
577
|
// Habit file missing or unreadable
|
|
@@ -577,6 +581,7 @@ async function runInnerDialogTurn(options) {
|
|
|
577
581
|
userContent = `habit "${habitName}" could not be read (file not found or unreadable). check habits/${habitName}.md exists.`;
|
|
578
582
|
}
|
|
579
583
|
else {
|
|
584
|
+
habitParsedSuccessfully = true;
|
|
580
585
|
// Unified path: gather context for ALL habits (heartbeat included)
|
|
581
586
|
const obligations = (0, obligations_1.listActiveReturnObligations)(agentName);
|
|
582
587
|
const nowMs = now().getTime();
|
|
@@ -631,6 +636,30 @@ async function runInnerDialogTurn(options) {
|
|
|
631
636
|
const selfFriend = createSelfFriend(agentName);
|
|
632
637
|
const selfContext = { friend: selfFriend, channel: innerCapabilities };
|
|
633
638
|
const mcpManager = await (0, mcp_manager_1.getSharedMcpManager)() ?? undefined;
|
|
639
|
+
// ── Habit tool enforcement ───────────────────────────────────────
|
|
640
|
+
let habitToolsResolved;
|
|
641
|
+
if (habitTools !== undefined) {
|
|
642
|
+
const fullTools = (0, tools_1.getToolsForChannel)(innerCapabilities);
|
|
643
|
+
habitToolsResolved = fullTools.filter((t) => habitTools.includes(t.function.name));
|
|
644
|
+
(0, runtime_1.emitNervesEvent)({
|
|
645
|
+
event: "habit.tools_restricted",
|
|
646
|
+
component: "senses",
|
|
647
|
+
message: "habit running with restricted tools",
|
|
648
|
+
meta: {
|
|
649
|
+
habitName: options?.habitName,
|
|
650
|
+
declared: habitTools,
|
|
651
|
+
resolved: habitToolsResolved.map((t) => t.function.name),
|
|
652
|
+
},
|
|
653
|
+
});
|
|
654
|
+
}
|
|
655
|
+
else if (reason === "habit" && options?.habitName && habitParsedSuccessfully) {
|
|
656
|
+
(0, runtime_1.emitNervesEvent)({
|
|
657
|
+
event: "habit.tools_unrestricted",
|
|
658
|
+
component: "senses",
|
|
659
|
+
message: "habit running with full tool repertoire",
|
|
660
|
+
meta: { habitName: options.habitName },
|
|
661
|
+
});
|
|
662
|
+
}
|
|
634
663
|
const sessionLoader = {
|
|
635
664
|
loadOrCreate: async () => {
|
|
636
665
|
if (existingMessages.length > 0) {
|
|
@@ -694,6 +723,7 @@ async function runInnerDialogTurn(options) {
|
|
|
694
723
|
traceId,
|
|
695
724
|
toolChoiceRequired: true,
|
|
696
725
|
mcpManager,
|
|
726
|
+
...(habitToolsResolved !== undefined && { tools: habitToolsResolved }),
|
|
697
727
|
toolContext: {
|
|
698
728
|
signin: async () => undefined,
|
|
699
729
|
delegatedOrigins: attentionQueue,
|