@ouro.bot/cli 0.1.0-alpha.152 → 0.1.0-alpha.154
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 +23 -0
- package/dist/heart/daemon/daemon-cli.js +20 -2
- package/dist/heart/daemon/daemon-health.js +136 -0
- package/dist/heart/daemon/daemon-tombstone.js +19 -2
- package/dist/heart/daemon/habit-scheduler.js +114 -0
- package/dist/heart/daemon/safe-mode.js +161 -0
- package/dist/heart/tool-activity-callbacks.js +30 -0
- package/dist/heart/tool-description.js +84 -0
- package/dist/nerves/event-buffer.js +111 -0
- package/dist/senses/bluebubbles.js +73 -58
- package/dist/senses/cli.js +45 -23
- package/dist/senses/commands.js +32 -0
- package/dist/senses/inner-dialog.js +12 -0
- package/dist/senses/pipeline.js +36 -0
- package/dist/senses/teams.js +46 -35
- package/package.json +1 -1
- package/dist/senses/debug-activity.js +0 -154
package/dist/senses/teams.js
CHANGED
|
@@ -70,6 +70,8 @@ const turn_coordinator_1 = require("../heart/turn-coordinator");
|
|
|
70
70
|
const identity_1 = require("../heart/identity");
|
|
71
71
|
const mcp_manager_1 = require("../repertoire/mcp-manager");
|
|
72
72
|
const progress_story_1 = require("../heart/progress-story");
|
|
73
|
+
const tool_activity_callbacks_1 = require("../heart/tool-activity-callbacks");
|
|
74
|
+
const commands_2 = require("./commands");
|
|
73
75
|
const http = __importStar(require("http"));
|
|
74
76
|
const path = __importStar(require("path"));
|
|
75
77
|
const trust_gate_1 = require("./trust-gate");
|
|
@@ -425,35 +427,37 @@ function createTeamsCallbacks(stream, controller, sendMessage, options) {
|
|
|
425
427
|
onClearText: () => {
|
|
426
428
|
textBuffer = "";
|
|
427
429
|
},
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
430
|
+
...(() => {
|
|
431
|
+
const toolCbs = (0, tool_activity_callbacks_1.createToolActivityCallbacks)({
|
|
432
|
+
onDescription: (text) => safeUpdate(text),
|
|
433
|
+
/* v8 ignore next -- onResult only called in debug mode; tested via tool-activity-callbacks.test.ts @preserve */
|
|
434
|
+
onResult: (text) => safeUpdate(text),
|
|
435
|
+
/* v8 ignore next -- onFailure tested via onToolEnd failure test @preserve */
|
|
436
|
+
onFailure: (text) => safeUpdate(`\u2717 ${text}`),
|
|
437
|
+
isDebug: (0, commands_2.getDebugMode)(),
|
|
438
|
+
});
|
|
439
|
+
return {
|
|
440
|
+
onToolStart: (name, args) => {
|
|
441
|
+
stopPhraseRotation();
|
|
442
|
+
// Force-flush any accumulated text, bypassing MIN_INITIAL_CHARS threshold
|
|
443
|
+
firstContentEmitted = true;
|
|
444
|
+
flushTextBuffer();
|
|
445
|
+
// Emit a placeholder to satisfy the 15s Copilot timeout for initial
|
|
446
|
+
// stream.emit(). Without this, long tool chains (e.g. ADO batch ops)
|
|
447
|
+
// never emit before the timeout and the user sees "this response was
|
|
448
|
+
// stopped". The placeholder is replaced by actual content on next emit.
|
|
449
|
+
// https://learn.microsoft.com/en-us/answers/questions/2288017/m365-custom-engine-agents-timeout-message-after-15
|
|
450
|
+
if (!streamHasContent)
|
|
451
|
+
safeEmit("\u23f3");
|
|
452
|
+
toolCbs.onToolStart(name, args);
|
|
453
|
+
hadToolRun = true;
|
|
454
|
+
},
|
|
455
|
+
onToolEnd: (name, summary, success) => {
|
|
456
|
+
stopPhraseRotation();
|
|
457
|
+
toolCbs.onToolEnd(name, summary, success);
|
|
458
|
+
},
|
|
459
|
+
};
|
|
460
|
+
})(),
|
|
457
461
|
onKick: () => {
|
|
458
462
|
stopPhraseRotation();
|
|
459
463
|
const msg = (0, format_1.formatKick)();
|
|
@@ -568,6 +572,7 @@ function createTeamsCommandRegistry() {
|
|
|
568
572
|
(0, commands_1.registerDefaultCommands)(registry);
|
|
569
573
|
return registry;
|
|
570
574
|
}
|
|
575
|
+
/* v8 ignore start -- superseding follow-up slash command handler; tested via startTeamsApp integration tests @preserve */
|
|
571
576
|
function handleTeamsSlashCommand(text, registry, friendId, conversationId, stream, emitResponse = true) {
|
|
572
577
|
const parsed = (0, commands_1.parseSlashCommand)(text);
|
|
573
578
|
if (!parsed)
|
|
@@ -591,6 +596,7 @@ function handleTeamsSlashCommand(text, registry, friendId, conversationId, strea
|
|
|
591
596
|
}
|
|
592
597
|
return null;
|
|
593
598
|
}
|
|
599
|
+
/* v8 ignore stop */
|
|
594
600
|
// Handle an incoming Teams message
|
|
595
601
|
async function handleTeamsMessage(text, stream, conversationId, teamsContext, sendMessage, reactionOverrides) {
|
|
596
602
|
const turnKey = teamsTurnKey(conversationId);
|
|
@@ -619,11 +625,6 @@ async function handleTeamsMessage(text, stream, conversationId, teamsContext, se
|
|
|
619
625
|
// Pre-resolve friend for session path + slash commands (pipeline will re-use the cached result)
|
|
620
626
|
const resolvedContext = await resolver.resolve();
|
|
621
627
|
const friendId = resolvedContext.friend.id;
|
|
622
|
-
const registry = createTeamsCommandRegistry();
|
|
623
|
-
// Check for slash commands (before pipeline -- these are transport-level concerns)
|
|
624
|
-
if (handleTeamsSlashCommand(text, registry, friendId, conversationId, stream)) {
|
|
625
|
-
return;
|
|
626
|
-
}
|
|
627
628
|
// ── Teams adapter concerns: controller, callbacks, session path ──────────
|
|
628
629
|
const controller = new AbortController();
|
|
629
630
|
const channelConfig = (0, config_2.getTeamsChannelConfig)();
|
|
@@ -729,6 +730,16 @@ async function handleTeamsMessage(text, stream, conversationId, teamsContext, se
|
|
|
729
730
|
runAgentOptions: agentOptions,
|
|
730
731
|
failoverState: teamsFailoverState,
|
|
731
732
|
});
|
|
733
|
+
// ── Handle pipeline-intercepted commands ────────────────────────
|
|
734
|
+
if (result.turnOutcome === "command") {
|
|
735
|
+
if (result.commandAction === "new") {
|
|
736
|
+
(0, context_1.deleteSession)(sessPath);
|
|
737
|
+
stream.emit("session cleared");
|
|
738
|
+
}
|
|
739
|
+
// For "response" commands: pipeline already emitted the response via onTextChunk
|
|
740
|
+
await callbacks.flush();
|
|
741
|
+
return;
|
|
742
|
+
}
|
|
732
743
|
/* v8 ignore start -- failover display: tested via pipeline integration tests @preserve */
|
|
733
744
|
if (result.failoverMessage) {
|
|
734
745
|
stream.emit(result.failoverMessage);
|
|
@@ -776,7 +787,7 @@ async function handleTeamsMessage(text, stream, conversationId, teamsContext, se
|
|
|
776
787
|
currentText = replayTail;
|
|
777
788
|
continue;
|
|
778
789
|
}
|
|
779
|
-
if (handleTeamsSlashCommand(supersedingFollowUp.text,
|
|
790
|
+
if (handleTeamsSlashCommand(supersedingFollowUp.text, createTeamsCommandRegistry(), friendId, conversationId, stream, false)) {
|
|
780
791
|
return;
|
|
781
792
|
}
|
|
782
793
|
currentText = supersedingFollowUp.text;
|
package/package.json
CHANGED
|
@@ -1,154 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.createDebugActivityController = createDebugActivityController;
|
|
4
|
-
const format_1 = require("../mind/format");
|
|
5
|
-
const phrases_1 = require("../mind/phrases");
|
|
6
|
-
const runtime_1 = require("../nerves/runtime");
|
|
7
|
-
const progress_story_1 = require("../heart/progress-story");
|
|
8
|
-
function createDebugActivityController(options) {
|
|
9
|
-
let queue = Promise.resolve();
|
|
10
|
-
let statusMessageGuid;
|
|
11
|
-
let typingActive = false;
|
|
12
|
-
let hadToolRun = false;
|
|
13
|
-
let followupShown = false;
|
|
14
|
-
let lastPhrase = "";
|
|
15
|
-
function reportTransportError(operation, error) {
|
|
16
|
-
(0, runtime_1.emitNervesEvent)({
|
|
17
|
-
level: "warn",
|
|
18
|
-
component: "senses",
|
|
19
|
-
event: "senses.debug_activity_transport_error",
|
|
20
|
-
message: "debug activity transport failed",
|
|
21
|
-
meta: {
|
|
22
|
-
operation,
|
|
23
|
-
reason: error instanceof Error ? error.message : String(error),
|
|
24
|
-
},
|
|
25
|
-
});
|
|
26
|
-
options.onTransportError?.(operation, error);
|
|
27
|
-
}
|
|
28
|
-
function enqueue(operation, task) {
|
|
29
|
-
queue = queue
|
|
30
|
-
.then(task)
|
|
31
|
-
.catch((error) => {
|
|
32
|
-
reportTransportError(operation, error);
|
|
33
|
-
});
|
|
34
|
-
}
|
|
35
|
-
function nextPhrase(pool) {
|
|
36
|
-
const phrase = (0, phrases_1.pickPhrase)(pool, lastPhrase);
|
|
37
|
-
lastPhrase = phrase;
|
|
38
|
-
return phrase;
|
|
39
|
-
}
|
|
40
|
-
function startTypingNow() {
|
|
41
|
-
if (typingActive) {
|
|
42
|
-
return;
|
|
43
|
-
}
|
|
44
|
-
typingActive = true;
|
|
45
|
-
enqueue("typing_start", async () => {
|
|
46
|
-
await options.transport.setTyping(true);
|
|
47
|
-
});
|
|
48
|
-
}
|
|
49
|
-
function setStatus(text) {
|
|
50
|
-
(0, runtime_1.emitNervesEvent)({
|
|
51
|
-
component: "senses",
|
|
52
|
-
event: "senses.debug_activity_update",
|
|
53
|
-
message: "debug activity status updated",
|
|
54
|
-
meta: {
|
|
55
|
-
hasStatusGuid: Boolean(statusMessageGuid),
|
|
56
|
-
textLength: text.length,
|
|
57
|
-
},
|
|
58
|
-
});
|
|
59
|
-
const shouldStartTyping = !typingActive;
|
|
60
|
-
if (shouldStartTyping) {
|
|
61
|
-
typingActive = true;
|
|
62
|
-
}
|
|
63
|
-
enqueue("status_update", async () => {
|
|
64
|
-
if (statusMessageGuid) {
|
|
65
|
-
await options.transport.editStatus(statusMessageGuid, text);
|
|
66
|
-
}
|
|
67
|
-
else {
|
|
68
|
-
statusMessageGuid = await options.transport.sendStatus(text);
|
|
69
|
-
}
|
|
70
|
-
if (shouldStartTyping) {
|
|
71
|
-
await options.transport.setTyping(true);
|
|
72
|
-
}
|
|
73
|
-
});
|
|
74
|
-
}
|
|
75
|
-
return {
|
|
76
|
-
onModelStart() {
|
|
77
|
-
const pool = hadToolRun ? options.followupPhrases : options.thinkingPhrases;
|
|
78
|
-
if (options.startTypingOnModelStart) {
|
|
79
|
-
startTypingNow();
|
|
80
|
-
}
|
|
81
|
-
if (options.suppressInitialModelStatus && !statusMessageGuid && !hadToolRun) {
|
|
82
|
-
nextPhrase(pool);
|
|
83
|
-
return;
|
|
84
|
-
}
|
|
85
|
-
setStatus((0, progress_story_1.renderProgressStory)((0, progress_story_1.buildProgressStory)({
|
|
86
|
-
scope: "shared-work",
|
|
87
|
-
phase: "processing",
|
|
88
|
-
objective: `${nextPhrase(pool)}...`,
|
|
89
|
-
})));
|
|
90
|
-
},
|
|
91
|
-
onToolStart(name, args) {
|
|
92
|
-
hadToolRun = true;
|
|
93
|
-
followupShown = false;
|
|
94
|
-
const argSummary = Object.values(args).join(", ");
|
|
95
|
-
const detail = argSummary ? ` (${argSummary})` : "";
|
|
96
|
-
setStatus((0, progress_story_1.renderProgressStory)((0, progress_story_1.buildProgressStory)({
|
|
97
|
-
scope: "shared-work",
|
|
98
|
-
phase: "processing",
|
|
99
|
-
objective: `running ${name}${detail}...`,
|
|
100
|
-
})));
|
|
101
|
-
},
|
|
102
|
-
onToolEnd(name, summary, success) {
|
|
103
|
-
hadToolRun = true;
|
|
104
|
-
followupShown = false;
|
|
105
|
-
setStatus((0, progress_story_1.renderProgressStory)((0, progress_story_1.buildProgressStory)({
|
|
106
|
-
scope: "shared-work",
|
|
107
|
-
phase: "processing",
|
|
108
|
-
objective: (0, format_1.formatToolResult)(name, summary, success),
|
|
109
|
-
})));
|
|
110
|
-
},
|
|
111
|
-
onTextChunk(text) {
|
|
112
|
-
if (!text) {
|
|
113
|
-
return;
|
|
114
|
-
}
|
|
115
|
-
if (!hadToolRun && options.startTypingOnFirstTextChunk) {
|
|
116
|
-
startTypingNow();
|
|
117
|
-
}
|
|
118
|
-
if (!hadToolRun || followupShown) {
|
|
119
|
-
return;
|
|
120
|
-
}
|
|
121
|
-
followupShown = true;
|
|
122
|
-
if (options.suppressFollowupPhraseStatus) {
|
|
123
|
-
return;
|
|
124
|
-
}
|
|
125
|
-
setStatus((0, progress_story_1.renderProgressStory)((0, progress_story_1.buildProgressStory)({
|
|
126
|
-
scope: "shared-work",
|
|
127
|
-
phase: "processing",
|
|
128
|
-
objective: `${nextPhrase(options.followupPhrases)}...`,
|
|
129
|
-
})));
|
|
130
|
-
},
|
|
131
|
-
onError(error) {
|
|
132
|
-
setStatus((0, progress_story_1.renderProgressStory)((0, progress_story_1.buildProgressStory)({
|
|
133
|
-
scope: "shared-work",
|
|
134
|
-
phase: "errored",
|
|
135
|
-
outcomeText: (0, format_1.formatError)(error),
|
|
136
|
-
})));
|
|
137
|
-
this.finish();
|
|
138
|
-
},
|
|
139
|
-
async drain() {
|
|
140
|
-
await queue;
|
|
141
|
-
},
|
|
142
|
-
async finish() {
|
|
143
|
-
if (!typingActive) {
|
|
144
|
-
await queue;
|
|
145
|
-
return;
|
|
146
|
-
}
|
|
147
|
-
typingActive = false;
|
|
148
|
-
enqueue("typing_stop", async () => {
|
|
149
|
-
await options.transport.setTyping(false);
|
|
150
|
-
});
|
|
151
|
-
await queue;
|
|
152
|
-
},
|
|
153
|
-
};
|
|
154
|
-
}
|