@ouro.bot/cli 0.1.0-alpha.350 → 0.1.0-alpha.351
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 +10 -0
- package/dist/mind/prompt.js +4 -3
- package/dist/repertoire/tools-surface.js +3 -3
- package/dist/senses/attention-queue.js +1 -1
- package/dist/senses/bluebubbles/index.js +26 -0
- package/dist/senses/habit-turn-message.js +1 -1
- package/dist/senses/proactive-content-guard.js +51 -0
- package/dist/senses/teams.js +25 -0
- package/package.json +1 -1
package/changelog.json
CHANGED
|
@@ -1,6 +1,16 @@
|
|
|
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.351",
|
|
6
|
+
"changes": [
|
|
7
|
+
"Surface tool description rewritten from 'surface progress' to 'send a message to someone' — makes it clear the tool is for interpersonal messaging, not status reporting.",
|
|
8
|
+
"Inner dialog prompt contract now guides agents to use rest(note) for heartbeat state and ponder(reflection) for deeper thoughts, keeping surface strictly for words meant for another person.",
|
|
9
|
+
"Removed [surfaced from inner dialog] prefix from synthetic session messages — provenance is tracked via captureKind: 'synthetic', the prefix was redundant and created echo loops.",
|
|
10
|
+
"Obligation summaries and attention queue headers reframed as structured internal data ([internal] tags) instead of surface-ready prose.",
|
|
11
|
+
"Shared proactive-content-guard module blocks internal content (heartbeat, check-in, task board, obligation status, meta markers) from BlueBubbles and Teams proactive sends."
|
|
12
|
+
]
|
|
13
|
+
},
|
|
4
14
|
{
|
|
5
15
|
"version": "0.1.0-alpha.350",
|
|
6
16
|
"changes": [
|
package/dist/mind/prompt.js
CHANGED
|
@@ -380,7 +380,7 @@ function runtimeInfoSection(channel, options) {
|
|
|
380
380
|
lines.push("i introduce myself on boot with a fun random greeting.");
|
|
381
381
|
}
|
|
382
382
|
else if (channel === "inner") {
|
|
383
|
-
lines.push("this is my inner session. when
|
|
383
|
+
lines.push("this is my inner session. when i have something to say to someone, i surface it. when i'm done thinking and the queue is clear, i rest.");
|
|
384
384
|
}
|
|
385
385
|
else if (channel === "mcp") {
|
|
386
386
|
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. respond via settle. 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.");
|
|
@@ -599,9 +599,10 @@ function toolContractsSection(channel, options) {
|
|
|
599
599
|
lines.push(`## tool behavior`);
|
|
600
600
|
lines.push(`tool_choice is set to "required" -- I must call a tool on every turn.`);
|
|
601
601
|
if (channel === "inner") {
|
|
602
|
-
lines.push(`- When
|
|
602
|
+
lines.push(`- When I have something to say to a person, I call \`surface\` with the content and, when available, its delegationId.`);
|
|
603
603
|
lines.push(`- \`surface\` does not end the inner turn; after surfacing everything that needs delivery, I call \`rest\`.`);
|
|
604
|
-
lines.push(`- \`rest\` must be the only tool call in that turn
|
|
604
|
+
lines.push(`- \`rest\` must be the only tool call in that turn. Internal state notes go in \`rest(note: "...")\` — that is my scratchpad, not \`surface\`.`);
|
|
605
|
+
lines.push(`- For deeper reflection I want to preserve, I use \`ponder\` with kind \`reflection\`.`);
|
|
605
606
|
lines.push(`- I do not call \`send_message\` or \`settle\` from inner dialogue; those are not inner-session delivery tools.`);
|
|
606
607
|
}
|
|
607
608
|
else {
|
|
@@ -45,7 +45,7 @@ exports.surfaceToolDef = {
|
|
|
45
45
|
type: "function",
|
|
46
46
|
function: {
|
|
47
47
|
name: "surface",
|
|
48
|
-
description: "
|
|
48
|
+
description: "send a message to someone — write it the way you'd text a friend. pass delegationId to address a held thought (see your attention queue above), or friendId for spontaneous outreach. does not end your turn.",
|
|
49
49
|
parameters: {
|
|
50
50
|
type: "object",
|
|
51
51
|
properties: {
|
|
@@ -124,7 +124,7 @@ exports.surfaceToolDefinition = {
|
|
|
124
124
|
// Inject surfaced content into the target session so it knows what was delivered
|
|
125
125
|
const { appendSyntheticAssistantMessage } = await Promise.resolve().then(() => __importStar(require("../mind/context")));
|
|
126
126
|
const sessionFilePath = path.join(sessionsDir, bridgeTarget.friendId, bridgeTarget.channel, `${bridgeTarget.key}.json`);
|
|
127
|
-
appendSyntheticAssistantMessage(sessionFilePath,
|
|
127
|
+
appendSyntheticAssistantMessage(sessionFilePath, content);
|
|
128
128
|
return { status: "delivered", detail: "via iMessage" };
|
|
129
129
|
}
|
|
130
130
|
}
|
|
@@ -158,7 +158,7 @@ exports.surfaceToolDefinition = {
|
|
|
158
158
|
if (proactiveResult.delivered) {
|
|
159
159
|
const { appendSyntheticAssistantMessage } = await Promise.resolve().then(() => __importStar(require("../mind/context")));
|
|
160
160
|
const sessionFilePath = path.join(sessionsDir, bbSession.friendId, bbSession.channel, `${bbSession.key}.json`);
|
|
161
|
-
appendSyntheticAssistantMessage(sessionFilePath,
|
|
161
|
+
appendSyntheticAssistantMessage(sessionFilePath, content);
|
|
162
162
|
return { status: "delivered", detail: "via iMessage" };
|
|
163
163
|
}
|
|
164
164
|
}
|
|
@@ -101,7 +101,7 @@ const CONTENT_PREVIEW_MAX = 80;
|
|
|
101
101
|
function buildAttentionQueueSummary(queue) {
|
|
102
102
|
if (queue.length === 0)
|
|
103
103
|
return "";
|
|
104
|
-
const lines = ["
|
|
104
|
+
const lines = ["[internal: held work items — not messages to send]"];
|
|
105
105
|
for (const item of queue) {
|
|
106
106
|
if (item.packetKind && item.packetObjective) {
|
|
107
107
|
lines.push(`- [${item.id}] ${item.friendName} -> ${item.packetKind}: ${item.packetObjective}`);
|
|
@@ -61,6 +61,7 @@ const prompt_1 = require("../../mind/prompt");
|
|
|
61
61
|
const mcp_manager_1 = require("../../repertoire/mcp-manager");
|
|
62
62
|
// getPhrases removed — no longer needed after debug-activity cleanup
|
|
63
63
|
const runtime_1 = require("../../nerves/runtime");
|
|
64
|
+
const proactive_content_guard_1 = require("../proactive-content-guard");
|
|
64
65
|
const model_1 = require("./model");
|
|
65
66
|
const client_1 = require("./client");
|
|
66
67
|
const inbound_log_1 = require("./inbound-log");
|
|
@@ -1368,6 +1369,17 @@ async function sendProactiveBlueBubblesMessageToSession(params, deps = {}) {
|
|
|
1368
1369
|
return { delivered: false, reason: "group_blocked" };
|
|
1369
1370
|
}
|
|
1370
1371
|
/* v8 ignore stop */
|
|
1372
|
+
const internalContentBlockReason = (0, proactive_content_guard_1.getProactiveInternalContentBlockReason)(params.text);
|
|
1373
|
+
if (internalContentBlockReason) {
|
|
1374
|
+
(0, proactive_content_guard_1.emitProactiveInternalContentBlocked)({
|
|
1375
|
+
friendId: params.friendId,
|
|
1376
|
+
sessionKey: params.sessionKey,
|
|
1377
|
+
reason: internalContentBlockReason,
|
|
1378
|
+
source: "session_send",
|
|
1379
|
+
intent: params.intent ?? "generic_outreach",
|
|
1380
|
+
});
|
|
1381
|
+
return { delivered: false, reason: "internal_content_blocked" };
|
|
1382
|
+
}
|
|
1371
1383
|
try {
|
|
1372
1384
|
await client.sendText({ chat, text: params.text });
|
|
1373
1385
|
(0, runtime_1.emitNervesEvent)({
|
|
@@ -1468,6 +1480,20 @@ async function drainAndSendPendingBlueBubbles(deps = {}, pendingRoot) {
|
|
|
1468
1480
|
catch { /* ignore */ }
|
|
1469
1481
|
continue;
|
|
1470
1482
|
}
|
|
1483
|
+
const internalBlockReason = (0, proactive_content_guard_1.getProactiveInternalContentBlockReason)(messageText);
|
|
1484
|
+
if (internalBlockReason) {
|
|
1485
|
+
result.skipped++;
|
|
1486
|
+
try {
|
|
1487
|
+
fs.unlinkSync(filePath);
|
|
1488
|
+
}
|
|
1489
|
+
catch { /* ignore */ }
|
|
1490
|
+
(0, proactive_content_guard_1.emitProactiveInternalContentBlocked)({
|
|
1491
|
+
friendId,
|
|
1492
|
+
reason: internalBlockReason,
|
|
1493
|
+
source: "pending_drain",
|
|
1494
|
+
});
|
|
1495
|
+
continue;
|
|
1496
|
+
}
|
|
1471
1497
|
let friend;
|
|
1472
1498
|
try {
|
|
1473
1499
|
friend = await store.get(friendId);
|
|
@@ -92,7 +92,7 @@ function appendTrailingExtras(sections, alsoDue, staleObligations, parseErrors,
|
|
|
92
92
|
}
|
|
93
93
|
// 5. Stale obligations
|
|
94
94
|
if (staleObligations.length > 0) {
|
|
95
|
-
const lines = staleObligations.map((o) => `
|
|
95
|
+
const lines = staleObligations.map((o) => `[internal] obligation: ${o.friendName} — waiting ${formatElapsed(o.stalenessMs)}`);
|
|
96
96
|
sections.push(lines.join("\n"));
|
|
97
97
|
}
|
|
98
98
|
// 6. Parse errors
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getProactiveInternalContentBlockReason = getProactiveInternalContentBlockReason;
|
|
4
|
+
exports.emitProactiveInternalContentBlocked = emitProactiveInternalContentBlocked;
|
|
5
|
+
const runtime_1 = require("../nerves/runtime");
|
|
6
|
+
// ── Patterns ────────────────────────────────────────────────────
|
|
7
|
+
const PROACTIVE_INTERNAL_CONTENT_PATTERNS = [
|
|
8
|
+
// PR 447 patterns: raw meta markers
|
|
9
|
+
{ reason: "raw_meta_marker", pattern: /<\s*\/?\s*(think|analysis|commentary)\b[^>]*>/i },
|
|
10
|
+
{ reason: "raw_meta_marker", pattern: /\[\s*surfaced from inner dialog\s*\]/i },
|
|
11
|
+
// Inner dialog / attention / obligation references
|
|
12
|
+
{ reason: "inner_dialog_reference", pattern: /\binner (dialog|dialogue)\b/i },
|
|
13
|
+
{ reason: "attention_queue_reference", pattern: /\battention queues?\b/i },
|
|
14
|
+
{ reason: "return_obligation_reference", pattern: /\b(return|held|heart|inner)\s+obligations?\b/i },
|
|
15
|
+
// Surfacing mechanics
|
|
16
|
+
{ reason: "surfacing_mechanics_reference", pattern: /\b(surface tool|surfacing (mechanics|itself)|surfaced? outward|call `?surface`?|delegationId|delegation id)\b/i },
|
|
17
|
+
// Prompt references
|
|
18
|
+
{ reason: "prompt_reference", pattern: /\b(system|developer|inner|tool|orientation)\s+prompts?\b|\bprompt\/orientation\b|\bprompt wording\b/i },
|
|
19
|
+
// Routing references
|
|
20
|
+
{ reason: "routing_reference", pattern: /\b(routing target|reply target|route through surface|routed through surface|proactive bluebubbles delivery)\b/i },
|
|
21
|
+
// Heartbeat / status patterns
|
|
22
|
+
{ reason: "heartbeat_status", pattern: /\bheartbeat\b/i },
|
|
23
|
+
{ reason: "heartbeat_status", pattern: /\bcheck-in\b/i },
|
|
24
|
+
{ reason: "heartbeat_status", pattern: /\btask board\b/i },
|
|
25
|
+
{ reason: "heartbeat_status", pattern: /\ball else settled\b/i },
|
|
26
|
+
{ reason: "heartbeat_status", pattern: /\bobligations?\s+showing\b/i },
|
|
27
|
+
{ reason: "heartbeat_status", pattern: /\bsame state\b/i },
|
|
28
|
+
];
|
|
29
|
+
// ── Public API ──────────────────────────────────────────────────
|
|
30
|
+
function getProactiveInternalContentBlockReason(text) {
|
|
31
|
+
for (const { reason, pattern } of PROACTIVE_INTERNAL_CONTENT_PATTERNS) {
|
|
32
|
+
if (pattern.test(text))
|
|
33
|
+
return reason;
|
|
34
|
+
}
|
|
35
|
+
return null;
|
|
36
|
+
}
|
|
37
|
+
function emitProactiveInternalContentBlocked(params) {
|
|
38
|
+
(0, runtime_1.emitNervesEvent)({
|
|
39
|
+
level: "warn",
|
|
40
|
+
component: "senses",
|
|
41
|
+
event: "senses.proactive_internal_content_blocked",
|
|
42
|
+
message: "proactive send blocked: internal content",
|
|
43
|
+
meta: {
|
|
44
|
+
friendId: params.friendId,
|
|
45
|
+
source: params.source,
|
|
46
|
+
reason: params.reason,
|
|
47
|
+
...(params.sessionKey ? { sessionKey: params.sessionKey } : {}),
|
|
48
|
+
...(params.intent ? { intent: params.intent } : {}),
|
|
49
|
+
},
|
|
50
|
+
});
|
|
51
|
+
}
|
package/dist/senses/teams.js
CHANGED
|
@@ -61,6 +61,7 @@ const context_1 = require("../mind/context");
|
|
|
61
61
|
const commands_1 = require("./commands");
|
|
62
62
|
const nerves_1 = require("../nerves");
|
|
63
63
|
const runtime_1 = require("../nerves/runtime");
|
|
64
|
+
const proactive_content_guard_1 = require("./proactive-content-guard");
|
|
64
65
|
const store_file_1 = require("../mind/friends/store-file");
|
|
65
66
|
const types_1 = require("../mind/friends/types");
|
|
66
67
|
const resolver_1 = require("../mind/friends/resolver");
|
|
@@ -1103,6 +1104,16 @@ async function sendProactiveTeamsMessageToSession(params, deps) {
|
|
|
1103
1104
|
});
|
|
1104
1105
|
return { delivered: false, reason: "missing_target" };
|
|
1105
1106
|
}
|
|
1107
|
+
const internalContentBlockReason = (0, proactive_content_guard_1.getProactiveInternalContentBlockReason)(params.text);
|
|
1108
|
+
if (internalContentBlockReason) {
|
|
1109
|
+
(0, proactive_content_guard_1.emitProactiveInternalContentBlocked)({
|
|
1110
|
+
friendId: params.friendId,
|
|
1111
|
+
sessionKey: params.sessionKey,
|
|
1112
|
+
reason: internalContentBlockReason,
|
|
1113
|
+
source: "session_send",
|
|
1114
|
+
});
|
|
1115
|
+
return { delivered: false, reason: "internal_content_blocked" };
|
|
1116
|
+
}
|
|
1106
1117
|
try {
|
|
1107
1118
|
const conversation = await conversations.create({
|
|
1108
1119
|
bot: { id: deps.botApi.id },
|
|
@@ -1205,6 +1216,20 @@ async function drainAndSendPendingTeams(store, botApi, pendingRoot) {
|
|
|
1205
1216
|
catch { /* ignore */ }
|
|
1206
1217
|
continue;
|
|
1207
1218
|
}
|
|
1219
|
+
const internalBlockReason = (0, proactive_content_guard_1.getProactiveInternalContentBlockReason)(messageText);
|
|
1220
|
+
if (internalBlockReason) {
|
|
1221
|
+
result.skipped++;
|
|
1222
|
+
try {
|
|
1223
|
+
fs.unlinkSync(filePath);
|
|
1224
|
+
}
|
|
1225
|
+
catch { /* ignore */ }
|
|
1226
|
+
(0, proactive_content_guard_1.emitProactiveInternalContentBlocked)({
|
|
1227
|
+
friendId,
|
|
1228
|
+
reason: internalBlockReason,
|
|
1229
|
+
source: "pending_drain",
|
|
1230
|
+
});
|
|
1231
|
+
continue;
|
|
1232
|
+
}
|
|
1208
1233
|
const sendResult = await sendProactiveTeamsMessageToSession({
|
|
1209
1234
|
friendId,
|
|
1210
1235
|
sessionKey: key,
|