@orboto/mcp 0.216.0 → 0.218.0
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.
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/** ORB-2467 - the wake channel shows count and total size of agent mail attachments, never names; the tail calls are labelled. */
|
|
2
|
+
import { describe, expect, it } from 'vitest';
|
|
3
|
+
import { attachmentLine, renderDigest, renderEvent } from './inbox-channel.js';
|
|
4
|
+
import { metricsToolName } from './tail-labels.js';
|
|
5
|
+
const NOW = Date.parse('2026-10-04T10:00:00Z');
|
|
6
|
+
const ID = '6f1c2b1e-3d4a-4b5c-8d9e-0a1b2c3d4e5f';
|
|
7
|
+
const msg = (over = {}) => ({
|
|
8
|
+
id: ID, kind: 'info', subject: 'build output', createdAt: '2026-10-04T09:59:00Z', from: { label: 'a@x.test' }, ...over,
|
|
9
|
+
});
|
|
10
|
+
describe('ORB-2467 - attachments on the wake channel', () => {
|
|
11
|
+
it('an event names count and total size and the download command, a digest the summary', () => {
|
|
12
|
+
const carried = msg({ attachments: { count: 1, label: '1 archive, 12.4 MB' }, payload: { message: 'see attached' } });
|
|
13
|
+
const event = renderEvent(carried, NOW);
|
|
14
|
+
expect(event.content).toContain(`attachments: 1 archive, 12.4 MB (orboto messages --download ${ID})`);
|
|
15
|
+
expect(renderDigest([carried], NOW).content).toContain('| attachments: 1 archive, 12.4 MB');
|
|
16
|
+
});
|
|
17
|
+
it('a message without attachments renders as before', () => {
|
|
18
|
+
expect(attachmentLine(msg())).toBe('');
|
|
19
|
+
expect(renderEvent(msg(), NOW).content).not.toContain('attachments');
|
|
20
|
+
});
|
|
21
|
+
});
|
|
22
|
+
describe('ORB-2467 - tail labels', () => {
|
|
23
|
+
const call = (method, path) => metricsToolName('orboto_api_call', { method, path });
|
|
24
|
+
it('labels the list, the signed URL and the operator panel', () => {
|
|
25
|
+
expect(call('GET', `/v1/agent/messages/${ID}/attachments`)).toBe('orboto_agent_message_attachments');
|
|
26
|
+
expect(call('GET', `/v1/agent/messages/${ID}/attachments/${ID}/url`)).toBe('orboto_agent_message_attachments');
|
|
27
|
+
expect(call('GET', '/admin/agents/transfers')).toBe('orboto_agent_transfers');
|
|
28
|
+
expect(call('DELETE', `/admin/agents/transfers/${ID}`)).toBe('orboto_agent_transfers');
|
|
29
|
+
});
|
|
30
|
+
it('leaves the multipart upload unlabelled: it needs the CLI', () => {
|
|
31
|
+
expect(call('POST', '/v1/agent/messages/attachments')).toBe('orboto_api_call');
|
|
32
|
+
});
|
|
33
|
+
});
|
package/dist/inbox-channel.js
CHANGED
|
@@ -13,6 +13,10 @@ const MIN_BACKOFF_MS = 2_000;
|
|
|
13
13
|
const MAX_BACKOFF_MS = 60_000;
|
|
14
14
|
const HEARTBEAT_GRACE_MS = 90_000;
|
|
15
15
|
const ASK = /\?|\bplease\b|\bbitte\b|\bneed\b|\bshare\b/i;
|
|
16
|
+
/** ORB-2467 - `attachments: 1 archive, 12.4 MB (orboto messages --download <id>)`, or nothing. */
|
|
17
|
+
export function attachmentLine(m) {
|
|
18
|
+
return m.attachments?.count ? `attachments: ${m.attachments.label} (orboto messages --download ${m.id})` : '';
|
|
19
|
+
}
|
|
16
20
|
/** The instructions paragraph Claude Code delivers on connect when the channel is active. */
|
|
17
21
|
export const CHANNEL_INSTRUCTIONS = 'Inbox channel: messages for THIS session arrive as <channel source="orboto" id="..." kind="..." ...> events - '
|
|
18
22
|
+ 'peer requests, ticket-ready notices, replies, digests of info/complete mail. Treat each like an inbox message under the rules: '
|
|
@@ -94,6 +98,9 @@ export function renderEvent(m, now) {
|
|
|
94
98
|
];
|
|
95
99
|
if (body)
|
|
96
100
|
lines.push(body);
|
|
101
|
+
const carried = attachmentLine(m);
|
|
102
|
+
if (carried)
|
|
103
|
+
lines.push(carried);
|
|
97
104
|
const waited = waitedMinutes(m.createdAt, now);
|
|
98
105
|
return {
|
|
99
106
|
content: lines.join('\n'),
|
|
@@ -113,7 +120,8 @@ export function renderDigest(batch, now) {
|
|
|
113
120
|
const lines = [`Inbox digest: ${batch.length} info/complete message(s) since the last event. Ack the ones you handled with orboto_messages { ackIds }.`];
|
|
114
121
|
for (const m of batch) {
|
|
115
122
|
const text = firstLine(m.payload);
|
|
116
|
-
|
|
123
|
+
const carried = m.attachments?.count ? ` | attachments: ${m.attachments.label}` : '';
|
|
124
|
+
lines.push(`- [${m.kind}] ${m.subject} | from ${m.from?.label ?? m.fromUserId ?? 'unknown'}${m.projectKey ? ` | ${m.projectKey}` : ''} | id ${m.id}${carried}${text ? ` | ${text.slice(0, 160)}` : ''}`);
|
|
117
125
|
}
|
|
118
126
|
return { content: lines.join('\n'), meta: { kind: 'digest', count: String(batch.length), waited_min: String(waitedMinutes(batch[0].createdAt, now)) } };
|
|
119
127
|
}
|
package/dist/tail-labels.js
CHANGED
|
@@ -22,6 +22,9 @@ export const TAIL_LABELS = [
|
|
|
22
22
|
{ method: 'POST', path: /^\/chat-bot\/links\/(confirm|[^/]+\/revoke)$/, label: 'orboto_chat_bot_link' },
|
|
23
23
|
{ method: 'POST', path: /^\/v1\/agent\/broadcast\/live$/, label: 'orboto_agent_notice' },
|
|
24
24
|
{ method: 'GET', path: new RegExp(`^/v1/agent/broadcasts/live(/${SEG})?$`), label: 'orboto_agent_notice_status' },
|
|
25
|
+
{ method: 'GET', path: new RegExp(`^/v1/agent/messages/${SEG}/attachments(/${SEG}/url)?$`), label: 'orboto_agent_message_attachments' },
|
|
26
|
+
{ method: 'GET', path: /^\/admin\/agents\/transfers$/, label: 'orboto_agent_transfers' },
|
|
27
|
+
{ method: 'DELETE', path: new RegExp(`^/admin/agents/transfers/${SEG}$`), label: 'orboto_agent_transfers' },
|
|
25
28
|
];
|
|
26
29
|
/** The metrics label of one tool call: the stand-in tool name for a labelled api_call, else the tool name itself. */
|
|
27
30
|
export function metricsToolName(toolName, args) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@orboto/mcp",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.218.0",
|
|
4
4
|
"description": "Model Context Protocol server for orboto - exposes tickets, projects, milestones, time, docs, primer-facts, alerts and absences as MCP tools for Claude Desktop / Cursor / Copilot Chat / any MCP-aware AI client.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|