@stage-labs/metro 0.1.0-beta.226 → 0.1.0-beta.227
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/package.json +1 -1
- package/runtime/marketplace/plugin/.claude-plugin/plugin.json +1 -1
- package/runtime/node_modules/@metro-labs/xmtp/src/actions.ts +31 -3
- package/runtime/node_modules/@metro-labs/xmtp/src/codecs.ts +27 -0
- package/runtime/node_modules/@metro-labs/xmtp/src/station.ts +1 -1
- package/runtime/runtime.json +1 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "metro",
|
|
3
|
-
"version": "0.1.0-beta.
|
|
3
|
+
"version": "0.1.0-beta.227",
|
|
4
4
|
"description": "Metro for Claude Code, installed by the metro daemon on this machine: every connector the agent holds as its own MCP server relayed through the daemon, the orchestrator-only guard on the main thread, and the standing rules loaded at each session start. No vendor credential ever sits in a config file.",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Bonustrack",
|
|
@@ -1,13 +1,18 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
GroupMessageKind,
|
|
3
|
+
ReactionAction,
|
|
4
|
+
ReactionSchema,
|
|
5
|
+
type Conversation,
|
|
6
|
+
} from '@xmtp/node-sdk';
|
|
2
7
|
import type { Reply } from '@xmtp/node-bindings';
|
|
3
8
|
import {
|
|
4
9
|
AttachmentCodec,
|
|
5
10
|
type Attachment,
|
|
6
11
|
} from '@xmtp/content-type-remote-attachment';
|
|
7
|
-
import { convOf } from './accounts.js';
|
|
12
|
+
import { convOf, type Account } from './accounts.js';
|
|
8
13
|
import { resolveMsgId } from './wire.js';
|
|
9
14
|
import { emitOutbound } from './emit.js';
|
|
10
|
-
import { PollCodec, buildPollContent } from './codecs.js';
|
|
15
|
+
import { PollCodec, buildPollContent, encodeDeleteMessage } from './codecs.js';
|
|
11
16
|
import { convHandlers } from './actions-conv.js';
|
|
12
17
|
import { messagingAliases } from '@metro-labs/core/stations/messaging-normalize';
|
|
13
18
|
import { TrainError } from '@metro-labs/core/train-error';
|
|
@@ -106,6 +111,28 @@ async function reply(id: string, args: Args): Promise<void> {
|
|
|
106
111
|
respond(id, { result: { messageId: sentId } });
|
|
107
112
|
}
|
|
108
113
|
|
|
114
|
+
const UNDELETABLE = new Set(['deleteMessage', 'deletedMessage']);
|
|
115
|
+
|
|
116
|
+
function assertDeletable(acct: Account, conv: Conversation, messageId: string): void {
|
|
117
|
+
const msg = acct.client.conversations.getMessageById(messageId);
|
|
118
|
+
if (msg?.conversationId !== conv.id)
|
|
119
|
+
throw new TrainError('NOT_FOUND', `message ${messageId} is not in this conversation`);
|
|
120
|
+
if (msg.senderInboxId !== acct.inboxId)
|
|
121
|
+
throw badArgs(`message ${messageId} was not sent by this account; only your own messages can be deleted`);
|
|
122
|
+
if (msg.kind !== GroupMessageKind.Application || UNDELETABLE.has(msg.contentType?.typeId ?? ''))
|
|
123
|
+
throw badArgs(`message ${messageId} cannot be deleted`);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
async function remove(id: string, args: Args): Promise<void> {
|
|
127
|
+
const { line, messageId } = args as { line: string; messageId: string };
|
|
128
|
+
const { acct, conv } = await convOf(line);
|
|
129
|
+
if (!conv) throw noConv(line);
|
|
130
|
+
const target = resolveMsgId(messageId);
|
|
131
|
+
assertDeletable(acct, conv, target);
|
|
132
|
+
const sentId = await conv.send(encodeDeleteMessage(target), { shouldPush: false });
|
|
133
|
+
respond(id, { result: { messageId: sentId } });
|
|
134
|
+
}
|
|
135
|
+
|
|
109
136
|
async function sendAttachment(id: string, args: Args): Promise<void> {
|
|
110
137
|
const { line, name, mime, dataB64 } = args as {
|
|
111
138
|
line: string;
|
|
@@ -186,6 +213,7 @@ const handlers: Record<string, (id: string, args: Args) => Promise<void>> = {
|
|
|
186
213
|
ask,
|
|
187
214
|
react,
|
|
188
215
|
reply,
|
|
216
|
+
delete: remove,
|
|
189
217
|
sendAttachment,
|
|
190
218
|
sendImage,
|
|
191
219
|
...convHandlers,
|
|
@@ -164,6 +164,33 @@ export const SignatureReferenceCodec =
|
|
|
164
164
|
c.signature ? `[Signature] ${c.signature}` : '[Signature]',
|
|
165
165
|
);
|
|
166
166
|
|
|
167
|
+
const ContentTypeDeleteMessage: ContentTypeId = {
|
|
168
|
+
authorityId: 'xmtp.org',
|
|
169
|
+
typeId: 'deleteMessage',
|
|
170
|
+
versionMajor: 1,
|
|
171
|
+
versionMinor: 0,
|
|
172
|
+
};
|
|
173
|
+
|
|
174
|
+
const varint = (value: number): number[] => {
|
|
175
|
+
const out: number[] = [];
|
|
176
|
+
let rest = value;
|
|
177
|
+
while (rest > 0x7f) {
|
|
178
|
+
out.push((rest & 0x7f) | 0x80);
|
|
179
|
+
rest = Math.floor(rest / 0x80);
|
|
180
|
+
}
|
|
181
|
+
out.push(rest);
|
|
182
|
+
return out;
|
|
183
|
+
};
|
|
184
|
+
|
|
185
|
+
export function encodeDeleteMessage(messageId: string): EncodedContent {
|
|
186
|
+
const id = new TextEncoder().encode(messageId);
|
|
187
|
+
return {
|
|
188
|
+
type: ContentTypeDeleteMessage,
|
|
189
|
+
parameters: {},
|
|
190
|
+
content: new Uint8Array([0x0a, ...varint(id.length), ...id]),
|
|
191
|
+
};
|
|
192
|
+
}
|
|
193
|
+
|
|
167
194
|
export const CODECS = (): ContentCodec[] => [
|
|
168
195
|
new PollCodec(),
|
|
169
196
|
new SignatureRequestCodec(),
|
|
@@ -6,7 +6,7 @@ export const xmtpStation: Station = {
|
|
|
6
6
|
name: 'xmtp',
|
|
7
7
|
hasAccounts: true,
|
|
8
8
|
hasTrain: true,
|
|
9
|
-
messageVerbs: new Set<Verb>(['send', 'reply', 'react', 'unreact', 'read']),
|
|
9
|
+
messageVerbs: new Set<Verb>(['send', 'reply', 'react', 'unreact', 'delete', 'read']),
|
|
10
10
|
groupOps: new Set<GroupOp>(['create_group', 'add_members', 'remove_members']),
|
|
11
11
|
attachmentMode: 'native',
|
|
12
12
|
profileFields: new Set<ProfileField>(PROFILE_FIELDS),
|
package/runtime/runtime.json
CHANGED