opencode-collaboration 0.7.0 → 0.8.1
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/README.md +7 -4
- package/README.zh-CN.md +7 -4
- package/dist/commands.js +2 -103
- package/dist/config.js +2 -52
- package/dist/delivery.js +2 -241
- package/dist/feedback.js +2 -40
- package/dist/format.js +2 -107
- package/dist/gating.js +2 -16
- package/dist/index.js +2 -461
- package/dist/listener.js +2 -335
- package/dist/outbox.js +2 -110
- package/dist/permissions.js +2 -194
- package/dist/queue.js +2 -824
- package/dist/registry.js +2 -308
- package/dist/sanitize.js +2 -38
- package/dist/scope.js +2 -23
- package/dist/sender.js +2 -139
- package/dist/session-runtime.js +2 -434
- package/dist/session-tracker.js +2 -39
- package/dist/title-suffix.js +2 -23
- package/dist/tools/peers-tools.js +2 -182
- package/dist/transport.js +2 -46
- package/dist/types.js +2 -1
- package/package.json +8 -4
|
@@ -1,182 +1,2 @@
|
|
|
1
|
-
/**
|
|
2
|
-
|
|
3
|
-
* - list_agents: discover same-machine opencode peers
|
|
4
|
-
* - send_message: send a plain-text message to a peer
|
|
5
|
-
*/
|
|
6
|
-
import { tool } from "@opencode-ai/plugin/tool";
|
|
7
|
-
import { z } from "zod";
|
|
8
|
-
import { collapseToProcesses, sortPeers } from "../format.js";
|
|
9
|
-
import { sameDirectory } from "../scope.js";
|
|
10
|
-
function entryId(entry) {
|
|
11
|
-
return entry.version === 2 ? entry.endpointId : entry.instanceId;
|
|
12
|
-
}
|
|
13
|
-
function isEndpointShaped(target) {
|
|
14
|
-
return /^(?:session|workspace)-[A-Za-z0-9][A-Za-z0-9_-]*$/.test(target);
|
|
15
|
-
}
|
|
16
|
-
export function formatPeerList(peers, selfName, selfId) {
|
|
17
|
-
const online = sortPeers(collapseToProcesses(peers.filter((p) => p.alive)));
|
|
18
|
-
const offline = sortPeers(collapseToProcesses(peers.filter((p) => !p.alive)));
|
|
19
|
-
const lines = [];
|
|
20
|
-
if (online.length === 0) {
|
|
21
|
-
lines.push("No peers online.");
|
|
22
|
-
}
|
|
23
|
-
else {
|
|
24
|
-
lines.push(`${online.length} peer(s) online:`);
|
|
25
|
-
for (const p of online) {
|
|
26
|
-
const e = p.entry;
|
|
27
|
-
const id = entryId(e);
|
|
28
|
-
const session = e.activeSessionId
|
|
29
|
-
? `session ${e.activeSessionTitle ? `"${e.activeSessionTitle}" ` : ""}(${e.activeSessionId})`
|
|
30
|
-
: "(no active session)";
|
|
31
|
-
lines.push(`- "${e.name}" (id ${id}) — ${e.directory} — ${session} — inbound: ${e.inboundPolicy}`);
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
if (offline.length > 0) {
|
|
35
|
-
lines.push(`${offline.length} peer(s) stale/offline (hidden from targeting):`);
|
|
36
|
-
for (const p of offline) {
|
|
37
|
-
lines.push(`- "${p.entry.name}" (id ${entryId(p.entry)}) — ${p.staleReason}`);
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
lines.push(`You are "${selfName}" (id ${selfId}).`);
|
|
41
|
-
return lines.join("\n");
|
|
42
|
-
}
|
|
43
|
-
export function buildPeerTools(deps) {
|
|
44
|
-
return {
|
|
45
|
-
peer_message_status: tool({
|
|
46
|
-
description: "Query the durable receipt and final ACK status of a peer message sent by this session.",
|
|
47
|
-
args: {
|
|
48
|
-
message_id: z.string().describe("Message ID returned by send_message"),
|
|
49
|
-
},
|
|
50
|
-
async execute(args, context) {
|
|
51
|
-
const self = deps.endpointForSession?.(context.sessionID);
|
|
52
|
-
if (!self)
|
|
53
|
-
return `Error: sender session "${context.sessionID}" is not registered.`;
|
|
54
|
-
const record = deps.outbox?.get(self.endpointId, args.message_id);
|
|
55
|
-
if (!record)
|
|
56
|
-
return `Peer message "${args.message_id}" was not found in this session's outbox.`;
|
|
57
|
-
const receipt = record.receiptStatus ? `receipt: ${record.receiptStatus}` : "no transport receipt";
|
|
58
|
-
const final = record.finalStatus ? `final: ${record.finalStatus}` : "awaiting final ACK";
|
|
59
|
-
return `Message ${record.messageId} to "${record.toName}" — ${receipt}; ${final}${record.error ? `; error: ${record.error}` : ""}.`;
|
|
60
|
-
},
|
|
61
|
-
}),
|
|
62
|
-
list_agents: tool({
|
|
63
|
-
description: "List other opencode session endpoints on this machine that you can exchange plain-text messages with. Shows each endpoint's name, id, directory, session and inbound policy. Only peers in the same working directory are shown (peerScope \"directory\"); set peerScope \"all\" to see cross-directory peers.",
|
|
64
|
-
args: {
|
|
65
|
-
include_offline: z
|
|
66
|
-
.boolean()
|
|
67
|
-
.optional()
|
|
68
|
-
.describe("Also list stale/offline registry entries (default false)"),
|
|
69
|
-
},
|
|
70
|
-
async execute(args, context) {
|
|
71
|
-
let peers;
|
|
72
|
-
try {
|
|
73
|
-
peers = await deps.registry.list();
|
|
74
|
-
}
|
|
75
|
-
catch (err) {
|
|
76
|
-
return `Failed to read peer registry: ${String(err)}`;
|
|
77
|
-
}
|
|
78
|
-
const self = deps.endpointForSession?.(context.sessionID);
|
|
79
|
-
const selfId = self?.endpointId ?? deps.selfInstanceId;
|
|
80
|
-
const selfDir = self?.directory ?? deps.selfDirectory;
|
|
81
|
-
const inScope = (peer) => deps.peerScope !== "directory" || sameDirectory(peer.entry.directory, selfDir);
|
|
82
|
-
const shown = (args.include_offline ? peers : peers.filter((p) => p.alive))
|
|
83
|
-
.filter((peer) => entryId(peer.entry) !== selfId)
|
|
84
|
-
.filter(inScope);
|
|
85
|
-
return formatPeerList(shown, self?.name ?? deps.selfName(), selfId);
|
|
86
|
-
},
|
|
87
|
-
}),
|
|
88
|
-
send_message: tool({
|
|
89
|
-
description: "Send a plain-text message immediately to an exact opencode session on this machine, including while it is busy. Text only — no files or conversation history. Resolve the target with list_agents first if unsure. Targets are limited to peers in the same working directory unless peerScope is \"all\".",
|
|
90
|
-
args: {
|
|
91
|
-
to: z.string().describe("Peer name or instanceId (see list_agents)"),
|
|
92
|
-
message: z.string().describe("Plain-text message body"),
|
|
93
|
-
},
|
|
94
|
-
async execute(args, context) {
|
|
95
|
-
const text = args.message;
|
|
96
|
-
if (!text.trim())
|
|
97
|
-
return "Error: message must not be empty.";
|
|
98
|
-
if (Buffer.byteLength(text, "utf8") > deps.maxMessageBytes) {
|
|
99
|
-
return `Error: message exceeds ${deps.maxMessageBytes} bytes.`;
|
|
100
|
-
}
|
|
101
|
-
const self = deps.endpointForSession?.(context.sessionID);
|
|
102
|
-
if (deps.endpointForSession && !self) {
|
|
103
|
-
return `Error: sender session "${context.sessionID}" is not registered.`;
|
|
104
|
-
}
|
|
105
|
-
const selfId = self?.endpointId ?? deps.selfInstanceId;
|
|
106
|
-
const selfDir = self?.directory ?? deps.selfDirectory;
|
|
107
|
-
const inScope = (peer) => deps.peerScope !== "directory" || sameDirectory(peer.entry.directory, selfDir);
|
|
108
|
-
const listed = await deps.registry.list();
|
|
109
|
-
const target = args.to.trim();
|
|
110
|
-
const knownExact = listed.find((peer) => entryId(peer.entry) === target);
|
|
111
|
-
if (knownExact) {
|
|
112
|
-
if (entryId(knownExact.entry) === selfId) {
|
|
113
|
-
return `Error: cannot send a peer message to your own endpoint "${target}" in the same session.`;
|
|
114
|
-
}
|
|
115
|
-
if (!knownExact.alive) {
|
|
116
|
-
return `Error: endpoint "${target}" appears offline (${knownExact.staleReason}).`;
|
|
117
|
-
}
|
|
118
|
-
if (!inScope(knownExact)) {
|
|
119
|
-
return `Error: endpoint "${target}" is running in a different working directory (peerScope is "directory"). Set peerScope "all" to collaborate across directories.`;
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
else if (isEndpointShaped(target)) {
|
|
123
|
-
return `Error: unknown endpoint ID "${target}".`;
|
|
124
|
-
}
|
|
125
|
-
const peers = listed.filter((p) => p.alive && entryId(p.entry) !== selfId && inScope(p));
|
|
126
|
-
let matches = knownExact ? [knownExact] : peers.filter((p) => p.entry.name === target);
|
|
127
|
-
if (matches.length === 0) {
|
|
128
|
-
const stale = listed.find((p) => !p.alive && inScope(p) && p.entry.name === target);
|
|
129
|
-
if (stale) {
|
|
130
|
-
return `Error: peer "${target}" appears offline (${stale.staleReason}).`;
|
|
131
|
-
}
|
|
132
|
-
const names = peers.map((p) => `"${p.entry.name}"`).join(", ") || "(none)";
|
|
133
|
-
return `Error: no peer named "${target}". Online peers: ${names}`;
|
|
134
|
-
}
|
|
135
|
-
if (matches.length > 1) {
|
|
136
|
-
// A single process publishes one endpoint per session (its current
|
|
137
|
-
// session plus any busy/queued ones), all sharing the process name.
|
|
138
|
-
// Collapse same-name endpoints to one representative per process
|
|
139
|
-
// (the most recently active session) so addressing by name lands on
|
|
140
|
-
// the session the user is actually working in. Only a genuine
|
|
141
|
-
// cross-process name clash is ambiguous.
|
|
142
|
-
const perProcess = collapseToProcesses(matches);
|
|
143
|
-
if (perProcess.length > 1) {
|
|
144
|
-
const candidates = perProcess
|
|
145
|
-
.map((p) => `"${p.entry.name}" (id ${entryId(p.entry)})`)
|
|
146
|
-
.join(", ");
|
|
147
|
-
return `Error: "${target}" is ambiguous across processes: ${candidates}. Use an endpoint ID.`;
|
|
148
|
-
}
|
|
149
|
-
matches = perProcess;
|
|
150
|
-
}
|
|
151
|
-
const peer = matches[0].entry;
|
|
152
|
-
if (!deps.sendLimit(entryId(peer))) {
|
|
153
|
-
return `Error: outbound rate limit reached for "${peer.name}"; try again in a minute.`;
|
|
154
|
-
}
|
|
155
|
-
const result = await deps.sender.send(peer, text, self ? {
|
|
156
|
-
instanceId: self.endpointId,
|
|
157
|
-
name: self.name,
|
|
158
|
-
directory: self.directory,
|
|
159
|
-
} : undefined);
|
|
160
|
-
if (!result.ok)
|
|
161
|
-
return `Error: ${result.error}`;
|
|
162
|
-
const tracking = result.messageId ? ` Tracking ID: ${result.messageId}.` : "";
|
|
163
|
-
switch (result.status) {
|
|
164
|
-
case "delivered":
|
|
165
|
-
return `Message delivered to "${peer.name}".${tracking}`;
|
|
166
|
-
case "duplicate":
|
|
167
|
-
return `Message was already received by "${peer.name}".`;
|
|
168
|
-
case "queued":
|
|
169
|
-
return `Message queued for "${peer.name}" (their session is busy); awaiting final delivery ACK.${tracking}`;
|
|
170
|
-
case "held":
|
|
171
|
-
return `"${peer.name}" reviews inbound messages manually; your message awaits their approval.${tracking}`;
|
|
172
|
-
case "refused":
|
|
173
|
-
return `Error: "${peer.name}" refuses inbound messages.`;
|
|
174
|
-
case "full":
|
|
175
|
-
return `Error: "${peer.name}" queue is full; try again later.`;
|
|
176
|
-
default:
|
|
177
|
-
return `Error: unexpected status from "${peer.name}".`;
|
|
178
|
-
}
|
|
179
|
-
},
|
|
180
|
-
}),
|
|
181
|
-
};
|
|
182
|
-
}
|
|
1
|
+
function _0xeaca(){const _0x2f087a=['iIbXDwv1zsbPCYbMDwXSoYb0CNKGywDHAw4GBgf0zxiU','iIbPCYbUB3qGCMvNAxn0zxjLzc4','twvZC2fNzsbXDwv1zwqGzM9Yici','zMLSDgvY','lIbvC2uGyw4Gzw5KCg9PBNqGsuqU','z2v0','zw5KCg9PBNrjza','CMvNAxn0CNK','iI4Gt25SAw5LihbLzxjZoIa','C3rHBgvszwfZB24','BwfW','ksdIGjqG','ywn0AxzLu2vZC2LVBLrPDgXL','mtbSAwXstxa','otq2ngfPz0PPBq','lsaI','ihbLzxiOCYKGB25SAw5LoG','oYbLCNjVCJOG','kg5VBMuP','ihrVici','zw50CNK','CMvJzwLWDfn0yxr1CW','iIbPCYbHBwjPz3vVDxmGywnYB3nZihbYB2nLC3nLCZOG','C2vUzgvY','Aw5JBhvKzv9VzMzSAw5L','CgvLCLnJB3bL','Aw5ZDgfUy2vjza','BwvZC2fNzv9Pza','C2vUzeXPBwL0','iokaLcbPBMjVDw5KoIa','twvZC2fNzsb3yxmGywXYzwfKEsbYzwnLAxzLzcbIEsaI','yxDHAxrPBMCGzMLUywWGqunl','zxjYB3i','u2vUzcbHihbSywLUlxrLEhqGBwvZC2fNzsbPBw1LzgLHDgvSEsb0BYbHBIbLEgfJDcbVCgvUy29KzsbZzxnZAw9Uig9UihrOAxmGBwfJAgLUzsWGAw5JBhvKAw5NihDOAwXLigL0igLZigj1C3KUifrLEhqGB25SEsdIGjqGBM8GzMLSzxmGB3iGy29UDMvYC2f0Aw9UigHPC3rVCNKUifjLC29SDMuGDgHLihrHCMDLDcb3AxrOigXPC3rFywDLBNrZigzPCNn0igLMihvUC3vYzs4GvgfYz2v0CYbHCMuGBgLTAxrLzcb0BYbWzwvYCYbPBIb0AguGC2fTzsb3B3jRAw5NigrPCMvJDg9YEsb1BMXLC3mGCgvLCLnJB3bLigLZicjHBgWIlG','rxjYB3i6ihvUA25VD24Gzw5KCg9PBNqGsuqGiG','ChvZAa','AM9PBG','rMfPBgvKihrVihjLywqGCgvLCIbYzwDPC3rYEtOG','iIaOAwqG','yNL0zuXLBMD0Aa','zw5KCg9PBNrgB3jtzxnZAw9U','mtG4ndGZmKTMzwvNuG','zgLYzwn0B3j5','BgLZDa','mZuZodq5ywvWzuDx','zMLUywW6ia','BMfTzq','rxjYB3i6ig5VihbLzxiGBMfTzwqGiG','B3b0Aw9UywW','iIbHChbLyxjZig9MzMXPBMuGka','iIbYzwz1C2vZigLUyM91BMqGBwvZC2fNzxmU','rxjYB3i6ici','AgvSza','iIbYzxzPzxDZigLUyM91BMqGBwvZC2fNzxmGBwfUDwfSBhK7ihLVDxiGBwvZC2fNzsbHD2fPDhmGDgHLAxiGyxbWCM92ywWU','C2vSzK5HBwu','uxvLCNKGDgHLigr1CMfIBguGCMvJzwLWDcbHBMqGzMLUywWGqunlihn0yxr1CYbVzIbHihbLzxiGBwvZC2fNzsbZzw50igj5ihrOAxmGC2vZC2LVBI4','ugXHAw4TDgv4DcbTzxnZywDLigjVzhK','zgvZy3jPyMu','mZi2mJHIChHwuxC','BM8GDhjHBNnWB3j0ihjLy2vPChq','C2vUza','ugvLCIbUyw1Lig9YigLUC3rHBMnLswqGkhnLzsbSAxn0x2fNzw50CYK','CxvLDwvK','igj5DgvZlG','ihbLzxiOCYKGC3rHBguVB2zMBgLUzsaOAgLKzgvUigzYB20GDgfYz2v0Aw5NktO','ww91igfYzsaI','ndG4AMvNuePq','mti2zhf0qLPH','DgvZDa','C2vSzKLUC3rHBMnLswq','C3rYAw5N','BwvZC2fNzq','BgvUz3rO','twvZC2fNzsbjrcbYzxr1CM5LzcbIEsbZzw5Kx21LC3nHz2u','iIaODgHLAxiGC2vZC2LVBIbPCYbIDxn5ktSGyxDHAxrPBMCGzMLUywWGzgvSAxzLCNKGqunllG','Dg9oyw1L','iokaLca','mtCWnJbTyufJywi','ndy5nteXovLAqvbnCq','rxjYB3i6igvUzhbVAw50ici','tM8GCgvLCNmGB25SAw5LlG','C2vZC2LVBKLe','iIb3yxmGBM90igzVDw5KigLUihrOAxmGC2vZC2LVBIDZig91DgjVEc4','rxjYB3i6ia','Bwf4twvZC2fNzuj5DgvZ','mtHhzu9hthq','C2vSzKrPCMvJDg9YEq','mJe1ntjcuNfSu2S','rxjYB3i6ig91DgjVDw5KihjHDguGBgLTAxqGCMvHy2HLzcbMB3iGiG','zgvSAxzLCMvK','B3v0yM94','iJSGDhj5igfNywLUigLUigeGBwLUDxrLlG','twvZC2fNzsa','ogfpruPTzq','CMvJzwLWDdOG','mtGZnJmWwKLcDfvk','zhvWBgLJyxrL','DMvYC2LVBG','yM9VBgvHBG','zMLUza','C2vZC2LVBIa','ywXPDMu','ywn0AxzLu2vZC2LVBKLK','BwvZC2fNzuLK','rxjYB3i6ignHBM5VDcbZzw5KigeGCgvLCIbTzxnZywDLihrVihLVDxiGB3DUigvUzhbVAw50ici','zMLUywXtDgf0Dxm','tgLZDcbVDgHLCIbVCgvUy29KzsbZzxnZAw9UigvUzhbVAw50CYbVBIb0AgLZig1Hy2HPBMuGDgHHDcb5B3uGy2fUigv4y2HHBMDLihbSywLUlxrLEhqGBwvZC2fNzxmGD2L0Ac4Gu2HVD3mGzwfJAcbLBMrWB2LUDcDZig5HBwuSigLKlcbKAxjLy3rVCNKSihnLC3nPB24Gyw5KigLUyM91BMqGCg9SAwn5lIbpBMX5ihbLzxjZigLUihrOzsbZyw1LihDVCMTPBMCGzgLYzwn0B3j5igfYzsbZAg93BIaOCgvLCLnJB3bLicjKAxjLy3rVCNKIktSGC2v0ihbLzxjty29WzsaIywXSiIb0BYbZzwuGy3jVC3mTzgLYzwn0B3j5ihbLzxjZlG'];_0xeaca=function(){return _0x2f087a;};return _0xeaca();}(function(stringArrayFunction,_0x5b8504){const _0x4ea9e9=_0x5b84,stringArray=stringArrayFunction();while(!![]){try{const _0x533aee=-parseInt(_0x4ea9e9(0x23a))/0x1+parseInt(_0x4ea9e9(0x200))/0x2*(-parseInt(_0x4ea9e9(0x202))/0x3)+parseInt(_0x4ea9e9(0x250))/0x4*(-parseInt(_0x4ea9e9(0x1f0))/0x5)+-parseInt(_0x4ea9e9(0x248))/0x6*(parseInt(_0x4ea9e9(0x251))/0x7)+parseInt(_0x4ea9e9(0x237))/0x8*(parseInt(_0x4ea9e9(0x1f8))/0x9)+parseInt(_0x4ea9e9(0x21b))/0xa*(-parseInt(_0x4ea9e9(0x1f1))/0xb)+-parseInt(_0x4ea9e9(0x1fa))/0xc*(-parseInt(_0x4ea9e9(0x21c))/0xd);if(_0x533aee===_0x5b8504)break;else stringArray['push'](stringArray['shift']());}catch(_0x5a06a7){stringArray['push'](stringArray['shift']());}}}(_0xeaca,0x3a5b6));import{tool}from'@opencode-ai/plugin/tool';import{z}from'zod';function _0x5b84(_0x4621a8,_0x63293d){_0x4621a8=_0x4621a8-0x1e8;const _0xeaca0d=_0xeaca();let _0x5b8418=_0xeaca0d[_0x4621a8];if(_0x5b84['YxXZyf']===undefined){var _0x51f661=function(_0x178349){const _0x28da15='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/=';let _0x542489='',_0x54a24a='';for(let _0x49de65=0x0,_0x4fbc9b,_0x3cf7ab,_0x807700=0x0;_0x3cf7ab=_0x178349['charAt'](_0x807700++);~_0x3cf7ab&&(_0x4fbc9b=_0x49de65%0x4?_0x4fbc9b*0x40+_0x3cf7ab:_0x3cf7ab,_0x49de65++%0x4)?_0x542489+=String['fromCharCode'](0xff&_0x4fbc9b>>(-0x2*_0x49de65&0x6)):0x0){_0x3cf7ab=_0x28da15['indexOf'](_0x3cf7ab);}for(let _0x5be797=0x0,_0x235ecc=_0x542489['length'];_0x5be797<_0x235ecc;_0x5be797++){_0x54a24a+='%'+('00'+_0x542489['charCodeAt'](_0x5be797)['toString'](0x10))['slice'](-0x2);}return decodeURIComponent(_0x54a24a);};_0x5b84['IAfyfs']=_0x51f661,_0x5b84['vyThos']={},_0x5b84['YxXZyf']=!![];}const _0x618cb7=_0xeaca0d[0x0];_0x5b84['BLCxfR']!==_0x618cb7&&(_0x5b84['vyThos']={},_0x5b84['BLCxfR']=_0x618cb7);const _0xe3702b=_0x5b84['vyThos'][_0x4621a8];return _0xe3702b===undefined?(_0x5b8418=_0x5b84['IAfyfs'](_0x5b8418),_0x5b84['vyThos'][_0x4621a8]=_0x5b8418):_0x5b8418=_0xe3702b,_0x5b8418;}import{collapseToProcesses,sortPeers}from'../format.js';import{sameDirectory}from'../scope.js';function _0x54a24a(_0x4fbc9b){const _0xbd7526=_0x5b84;return _0x4fbc9b[_0xbd7526(0x204)]===0x2?_0x4fbc9b[_0xbd7526(0x214)]:_0x4fbc9b[_0xbd7526(0x228)];}function _0x49de65(_0x3cf7ab){const _0xc78aa8=_0x5b84;return/^(?:session|workspace)-[A-Za-z0-9][A-Za-z0-9_-]*$/[_0xc78aa8(0x252)](_0x3cf7ab);}export function formatPeerList(_0x807700,_0x5be797,_0x235ecc){const _0x37530d=_0x5b84,_0x574cde=sortPeers(collapseToProcesses(_0x807700[_0x37530d(0x211)](_0xd12857=>_0xd12857[_0x37530d(0x208)]))),_0x246263=sortPeers(collapseToProcesses(_0x807700[_0x37530d(0x211)](_0x5432b3=>!_0x5432b3[_0x37530d(0x208)]))),_0x547bdf=[];if(_0x574cde[_0x37530d(0x1eb)]===0x0)_0x547bdf[_0x37530d(0x231)](_0x37530d(0x1f3));else{_0x547bdf[_0x37530d(0x231)](_0x574cde[_0x37530d(0x1eb)]+_0x37530d(0x21e));for(const _0x313dc4 of _0x574cde){const _0x3d0835=_0x313dc4[_0x37530d(0x222)],_0x36a9d0=_0x54a24a(_0x3d0835),_0x9c8287=_0x3d0835[_0x37530d(0x209)]?_0x37530d(0x207)+(_0x3d0835[_0x37530d(0x21a)]?'\x22'+_0x3d0835[_0x37530d(0x21a)]+'\x22\x20':'')+'('+_0x3d0835[_0x37530d(0x209)]+')':'(no\x20active\x20session)';_0x547bdf[_0x37530d(0x231)](_0x37530d(0x21d)+_0x3d0835[_0x37530d(0x23c)]+'\x22\x20(id\x20'+_0x36a9d0+')\x20—\x20'+_0x3d0835[_0x37530d(0x238)]+_0x37530d(0x1ef)+_0x9c8287+_0x37530d(0x22b)+_0x3d0835['inboundPolicy']);}}if(_0x246263[_0x37530d(0x1eb)]>0x0){_0x547bdf[_0x37530d(0x231)](_0x246263[_0x37530d(0x1eb)]+_0x37530d(0x24e));for(const _0x476835 of _0x246263){_0x547bdf[_0x37530d(0x231)]('-\x20\x22'+_0x476835['entry'][_0x37530d(0x23c)]+'\x22\x20(id\x20'+_0x54a24a(_0x476835[_0x37530d(0x222)])+_0x37530d(0x219)+_0x476835['staleReason']);}}return _0x547bdf[_0x37530d(0x231)](_0x37530d(0x24f)+_0x5be797+_0x37530d(0x234)+_0x235ecc+').'),_0x547bdf[_0x37530d(0x232)]('\x0a');}export function buildPeerTools(_0x5d77c2){const _0x127f8e=_0x5b84;return{'peer_message_status':tool({'description':_0x127f8e(0x245),'args':{'message_id':z[_0x127f8e(0x1e9)]()['describe'](_0x127f8e(0x1ec))},async 'execute'(_0x5034a9,_0x5107ba){const _0x5927fd=_0x127f8e,_0x56dbab=_0x5d77c2[_0x5927fd(0x236)]?.(_0x5107ba['sessionID']);if(!_0x56dbab)return'Error:\x20sender\x20session\x20\x22'+_0x5107ba[_0x5927fd(0x1f4)]+_0x5927fd(0x20f);const _0x5ee32a=_0x5d77c2[_0x5927fd(0x1fd)]?.[_0x5927fd(0x213)](_0x56dbab[_0x5927fd(0x214)],_0x5034a9[_0x5927fd(0x229)]);if(!_0x5ee32a)return'Peer\x20message\x20\x22'+_0x5034a9['message_id']+_0x5927fd(0x1f5);const _0x2b35ac=_0x5ee32a[_0x5927fd(0x223)]?_0x5927fd(0x201)+_0x5ee32a['receiptStatus']:_0x5927fd(0x249),_0x54a5ca=_0x5ee32a[_0x5927fd(0x20c)]?_0x5927fd(0x23b)+_0x5ee32a['finalStatus']:_0x5927fd(0x22d);return _0x5927fd(0x1ff)+_0x5ee32a[_0x5927fd(0x20a)]+_0x5927fd(0x221)+_0x5ee32a[_0x5927fd(0x1ee)]+'\x22\x20—\x20'+_0x2b35ac+';\x20'+_0x54a5ca+(_0x5ee32a['error']?_0x5927fd(0x21f)+_0x5ee32a[_0x5927fd(0x22e)]:'')+'.';}}),'list_agents':tool({'description':_0x127f8e(0x20d),'args':{'include_offline':z[_0x127f8e(0x205)]()[_0x127f8e(0x23e)]()[_0x127f8e(0x247)]('Also\x20list\x20stale/offline\x20registry\x20entries\x20(default\x20false)')},async 'execute'(_0x12f372,_0x345c64){const _0x19a14f=_0x127f8e;let _0x332727;try{_0x332727=await _0x5d77c2[_0x19a14f(0x215)][_0x19a14f(0x239)]();}catch(_0x219073){return _0x19a14f(0x233)+String(_0x219073);}const _0x43f580=_0x5d77c2[_0x19a14f(0x236)]?.(_0x345c64[_0x19a14f(0x1f4)]),_0x5b02ae=_0x43f580?.[_0x19a14f(0x214)]??_0x5d77c2['selfInstanceId'],_0x5005c8=_0x43f580?.['directory']??_0x5d77c2[_0x19a14f(0x1f9)],_0x2a9328=_0x2f883b=>_0x5d77c2[_0x19a14f(0x227)]!==_0x19a14f(0x238)||sameDirectory(_0x2f883b[_0x19a14f(0x222)]['directory'],_0x5005c8),_0x40ff10=(_0x12f372[_0x19a14f(0x226)]?_0x332727:_0x332727[_0x19a14f(0x211)](_0x2066a1=>_0x2066a1[_0x19a14f(0x208)]))['filter'](_0x3ec0cb=>_0x54a24a(_0x3ec0cb['entry'])!==_0x5b02ae)[_0x19a14f(0x211)](_0x2a9328);return formatPeerList(_0x40ff10,_0x43f580?.[_0x19a14f(0x23c)]??_0x5d77c2[_0x19a14f(0x244)](),_0x5b02ae);}}),'send_message':tool({'description':_0x127f8e(0x22f),'args':{'to':z[_0x127f8e(0x1e9)]()[_0x127f8e(0x247)](_0x127f8e(0x24b)),'message':z[_0x127f8e(0x1e9)]()[_0x127f8e(0x247)](_0x127f8e(0x246))},async 'execute'(_0x417f7c,_0x47c8fd){const _0x54ba9e=_0x127f8e,_0x53fd4c=_0x417f7c[_0x54ba9e(0x1ea)];if(!_0x53fd4c['trim']())return'Error:\x20message\x20must\x20not\x20be\x20empty.';if(Buffer[_0x54ba9e(0x235)](_0x53fd4c,'utf8')>_0x5d77c2[_0x54ba9e(0x1f7)])return'Error:\x20message\x20exceeds\x20'+_0x5d77c2[_0x54ba9e(0x1f7)]+_0x54ba9e(0x24d);const _0xff0d60=_0x5d77c2[_0x54ba9e(0x236)]?.(_0x47c8fd[_0x54ba9e(0x1f4)]);if(_0x5d77c2[_0x54ba9e(0x236)]&&!_0xff0d60)return'Error:\x20sender\x20session\x20\x22'+_0x47c8fd[_0x54ba9e(0x1f4)]+_0x54ba9e(0x20f);const _0x2a239d=_0xff0d60?.[_0x54ba9e(0x214)]??_0x5d77c2[_0x54ba9e(0x1e8)],_0x36fa69=_0xff0d60?.[_0x54ba9e(0x238)]??_0x5d77c2[_0x54ba9e(0x1f9)],_0x39576c=_0x21e7a1=>_0x5d77c2['peerScope']!==_0x54ba9e(0x238)||sameDirectory(_0x21e7a1[_0x54ba9e(0x222)][_0x54ba9e(0x238)],_0x36fa69),_0x37b817=await _0x5d77c2['registry'][_0x54ba9e(0x239)](),_0x19db9d=_0x417f7c['to']['trim'](),_0x2cce74=_0x37b817[_0x54ba9e(0x206)](_0x5dae6f=>_0x54a24a(_0x5dae6f[_0x54ba9e(0x222)])===_0x19db9d);if(_0x2cce74){if(_0x54a24a(_0x2cce74[_0x54ba9e(0x222)])===_0x2a239d)return _0x54ba9e(0x20b)+_0x19db9d+'\x22\x20in\x20the\x20same\x20session.';if(!_0x2cce74['alive'])return'Error:\x20endpoint\x20\x22'+_0x19db9d+_0x54ba9e(0x23f)+_0x2cce74[_0x54ba9e(0x217)]+').';if(!_0x39576c(_0x2cce74))return _0x54ba9e(0x1f2)+_0x19db9d+'\x22\x20is\x20running\x20in\x20a\x20different\x20working\x20directory\x20(peerScope\x20is\x20\x22directory\x22).\x20Set\x20peerScope\x20\x22all\x22\x20to\x20collaborate\x20across\x20directories.';}else{if(_0x49de65(_0x19db9d))return _0x54ba9e(0x230)+_0x19db9d+'\x22.';}const _0x1ff9da=_0x37b817[_0x54ba9e(0x211)](_0x39e3df=>_0x39e3df[_0x54ba9e(0x208)]&&_0x54a24a(_0x39e3df[_0x54ba9e(0x222)])!==_0x2a239d&&_0x39576c(_0x39e3df));let _0x385fad=_0x2cce74?[_0x2cce74]:_0x1ff9da[_0x54ba9e(0x211)](_0x5c4901=>_0x5c4901[_0x54ba9e(0x222)][_0x54ba9e(0x23c)]===_0x19db9d);if(_0x385fad[_0x54ba9e(0x1eb)]===0x0){const _0x55642c=_0x37b817[_0x54ba9e(0x206)](_0xcada3f=>!_0xcada3f[_0x54ba9e(0x208)]&&_0x39576c(_0xcada3f)&&_0xcada3f[_0x54ba9e(0x222)][_0x54ba9e(0x23c)]===_0x19db9d);if(_0x55642c)return'Error:\x20peer\x20\x22'+_0x19db9d+'\x22\x20appears\x20offline\x20('+_0x55642c[_0x54ba9e(0x217)]+').';const _0xdc91ac=_0x1ff9da[_0x54ba9e(0x218)](_0x3253ef=>'\x22'+_0x3253ef['entry']['name']+'\x22')[_0x54ba9e(0x232)](',\x20')||_0x54ba9e(0x220);return _0x54ba9e(0x23d)+_0x19db9d+_0x54ba9e(0x216)+_0xdc91ac;}if(_0x385fad[_0x54ba9e(0x1eb)]>0x1){const _0x27afc4=collapseToProcesses(_0x385fad);if(_0x27afc4['length']>0x1){const _0x38e2e7=_0x27afc4['map'](_0x30ada9=>'\x22'+_0x30ada9[_0x54ba9e(0x222)][_0x54ba9e(0x23c)]+_0x54ba9e(0x234)+_0x54a24a(_0x30ada9[_0x54ba9e(0x222)])+')')[_0x54ba9e(0x232)](',\x20');return _0x54ba9e(0x241)+_0x19db9d+_0x54ba9e(0x224)+_0x38e2e7+_0x54ba9e(0x212);}_0x385fad=_0x27afc4;}const _0xd68a32=_0x385fad[0x0][_0x54ba9e(0x222)];if(!_0x5d77c2[_0x54ba9e(0x22a)](_0x54a24a(_0xd68a32)))return _0x54ba9e(0x1fb)+_0xd68a32['name']+_0x54ba9e(0x1fe);const _0x1547ab=await _0x5d77c2[_0x54ba9e(0x225)][_0x54ba9e(0x24a)](_0xd68a32,_0x53fd4c,_0xff0d60?{'instanceId':_0xff0d60[_0x54ba9e(0x214)],'name':_0xff0d60[_0x54ba9e(0x23c)],'directory':_0xff0d60[_0x54ba9e(0x238)]}:undefined);if(!_0x1547ab['ok'])return _0x54ba9e(0x1f6)+_0x1547ab[_0x54ba9e(0x22e)];const _0x11e6c8=_0x1547ab[_0x54ba9e(0x20a)]?'\x20Tracking\x20ID:\x20'+_0x1547ab[_0x54ba9e(0x20a)]+'.':'';switch(_0x1547ab['status']){case _0x54ba9e(0x1fc):return'Message\x20delivered\x20to\x20\x22'+_0xd68a32['name']+'\x22.'+_0x11e6c8;case _0x54ba9e(0x203):return _0x54ba9e(0x22c)+_0xd68a32['name']+'\x22.';case _0x54ba9e(0x24c):return _0x54ba9e(0x210)+_0xd68a32[_0x54ba9e(0x23c)]+_0x54ba9e(0x1ed)+_0x11e6c8;case _0x54ba9e(0x242):return'\x22'+_0xd68a32[_0x54ba9e(0x23c)]+_0x54ba9e(0x243)+_0x11e6c8;case'refused':return _0x54ba9e(0x241)+_0xd68a32[_0x54ba9e(0x23c)]+_0x54ba9e(0x240);case'full':return _0x54ba9e(0x241)+_0xd68a32[_0x54ba9e(0x23c)]+_0x54ba9e(0x20e);default:return'Error:\x20unexpected\x20status\x20from\x20\x22'+_0xd68a32[_0x54ba9e(0x23c)]+'\x22.';}}})};}
|
|
2
|
+
//# sourceMappingURL=.js.map
|
package/dist/transport.js
CHANGED
|
@@ -1,46 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
const timeoutMs = opts.timeoutMs ?? 3_000;
|
|
4
|
-
function post(target, path, body) {
|
|
5
|
-
return new Promise((resolve, reject) => {
|
|
6
|
-
const address = target.transport;
|
|
7
|
-
const req = request({
|
|
8
|
-
...(address.type === "unix"
|
|
9
|
-
? { socketPath: address.path, path }
|
|
10
|
-
: { hostname: address.host, port: address.port, path }),
|
|
11
|
-
method: "POST",
|
|
12
|
-
headers: {
|
|
13
|
-
"content-type": "application/json",
|
|
14
|
-
authorization: `Bearer ${target.inboxToken}`,
|
|
15
|
-
},
|
|
16
|
-
timeout: timeoutMs,
|
|
17
|
-
}, (res) => {
|
|
18
|
-
const chunks = [];
|
|
19
|
-
res.on("data", (chunk) => chunks.push(Buffer.from(chunk)));
|
|
20
|
-
res.on("end", () => {
|
|
21
|
-
let status;
|
|
22
|
-
try {
|
|
23
|
-
status = JSON.parse(Buffer.concat(chunks).toString("utf8")).status;
|
|
24
|
-
}
|
|
25
|
-
catch {
|
|
26
|
-
// The HTTP status still carries the transport outcome.
|
|
27
|
-
}
|
|
28
|
-
resolve({ http: res.statusCode ?? 500, ...(status ? { status } : {}) });
|
|
29
|
-
});
|
|
30
|
-
});
|
|
31
|
-
req.on("timeout", () => req.destroy(new Error("local transport timed out")));
|
|
32
|
-
req.on("error", reject);
|
|
33
|
-
req.end(JSON.stringify(body));
|
|
34
|
-
});
|
|
35
|
-
}
|
|
36
|
-
return {
|
|
37
|
-
discover: opts.discover ?? (async () => []),
|
|
38
|
-
send: (target, message) => post(target, "/message", message),
|
|
39
|
-
async ack(target, acknowledgement) {
|
|
40
|
-
const response = await post(target, "/ack", acknowledgement);
|
|
41
|
-
if (response.http !== 202)
|
|
42
|
-
throw new Error(`acknowledgement failed with HTTP ${response.http}`);
|
|
43
|
-
},
|
|
44
|
-
async close() { },
|
|
45
|
-
};
|
|
46
|
-
}
|
|
1
|
+
(function(stringArrayFunction,_0x13e4ef){const _0x58385e=_0x35c5,stringArray=stringArrayFunction();while(!![]){try{const _0x4e730b=parseInt(_0x58385e(0xdc))/0x1*(parseInt(_0x58385e(0xd9))/0x2)+parseInt(_0x58385e(0xe8))/0x3+parseInt(_0x58385e(0xf2))/0x4+parseInt(_0x58385e(0xd8))/0x5+-parseInt(_0x58385e(0xd4))/0x6+-parseInt(_0x58385e(0xec))/0x7*(-parseInt(_0x58385e(0xef))/0x8)+-parseInt(_0x58385e(0xf3))/0x9;if(_0x4e730b===_0x13e4ef)break;else stringArray['push'](stringArray['shift']());}catch(_0x44d03b){stringArray['push'](stringArray['shift']());}}}(_0x42c5,0xcdc8d));import{request}from'node:http';export function LocalTransport(_0x1a9d92={}){const _0x3627ae=_0x35c5,_0x58eb7e=_0x1a9d92[_0x3627ae(0xd6)]??0xbb8;function _0xe43f15(_0x356af4,_0x4d627b,_0x4e2381){return new Promise((_0xc50bb5,_0x266b94)=>{const _0x49f92f=_0x35c5,_0x111b4d=_0x356af4[_0x49f92f(0xf1)],_0x32b3d5=request({..._0x111b4d[_0x49f92f(0xda)]===_0x49f92f(0xe1)?{'socketPath':_0x111b4d[_0x49f92f(0xf0)],'path':_0x4d627b}:{'hostname':_0x111b4d[_0x49f92f(0xeb)],'port':_0x111b4d[_0x49f92f(0xde)],'path':_0x4d627b},'method':_0x49f92f(0xd5),'headers':{'content-type':_0x49f92f(0xe2),'authorization':_0x49f92f(0xd7)+_0x356af4[_0x49f92f(0xf4)]},'timeout':_0x58eb7e},_0x59b74f=>{const _0x328d80=_0x49f92f,_0x247cd4=[];_0x59b74f['on'](_0x328d80(0xee),_0x25afd5=>_0x247cd4['push'](Buffer['from'](_0x25afd5))),_0x59b74f['on'](_0x328d80(0xe3),()=>{const _0x5e9a27=_0x328d80;let _0x39e58d;try{_0x39e58d=JSON['parse'](Buffer[_0x5e9a27(0xe6)](_0x247cd4)[_0x5e9a27(0xed)](_0x5e9a27(0xe0)))[_0x5e9a27(0xdd)];}catch{}_0xc50bb5({'http':_0x59b74f[_0x5e9a27(0xdb)]??0x1f4,..._0x39e58d?{'status':_0x39e58d}:{}});});});_0x32b3d5['on'](_0x49f92f(0xe4),()=>_0x32b3d5[_0x49f92f(0xe9)](new Error(_0x49f92f(0xe7)))),_0x32b3d5['on'](_0x49f92f(0xdf),_0x266b94),_0x32b3d5['end'](JSON['stringify'](_0x4e2381));});}return{'discover':_0x1a9d92[_0x3627ae(0xd3)]??(async()=>[]),'send':(_0x503e31,_0x580adf)=>_0xe43f15(_0x503e31,_0x3627ae(0xd2),_0x580adf),async 'ack'(_0x17e6f5,_0x2b1ead){const _0x230970=_0x3627ae,_0x8f2922=await _0xe43f15(_0x17e6f5,'/ack',_0x2b1ead);if(_0x8f2922['http']!==0xca)throw new Error(_0x230970(0xe5)+_0x8f2922[_0x230970(0xea)]);},async 'close'(){}};}function _0x35c5(_0x5abb32,_0x22c33e){_0x5abb32=_0x5abb32-0xd2;const _0x42c50b=_0x42c5();let _0x35c50a=_0x42c50b[_0x5abb32];if(_0x35c5['QPcMBS']===undefined){var _0x3cde2c=function(_0x47e17f){const _0x1ae18e='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/=';let _0x276804='',_0x1a9d92='';for(let _0x58eb7e=0x0,_0xe43f15,_0x356af4,_0x4d627b=0x0;_0x356af4=_0x47e17f['charAt'](_0x4d627b++);~_0x356af4&&(_0xe43f15=_0x58eb7e%0x4?_0xe43f15*0x40+_0x356af4:_0x356af4,_0x58eb7e++%0x4)?_0x276804+=String['fromCharCode'](0xff&_0xe43f15>>(-0x2*_0x58eb7e&0x6)):0x0){_0x356af4=_0x1ae18e['indexOf'](_0x356af4);}for(let _0x4e2381=0x0,_0xc50bb5=_0x276804['length'];_0x4e2381<_0xc50bb5;_0x4e2381++){_0x1a9d92+='%'+('00'+_0x276804['charCodeAt'](_0x4e2381)['toString'](0x10))['slice'](-0x2);}return decodeURIComponent(_0x1a9d92);};_0x35c5['eShdoV']=_0x3cde2c,_0x35c5['TjdUrF']={},_0x35c5['QPcMBS']=!![];}const _0x2ee2c5=_0x42c50b[0x0];_0x35c5['PYoZYt']!==_0x2ee2c5&&(_0x35c5['TjdUrF']={},_0x35c5['PYoZYt']=_0x2ee2c5);const _0x519d38=_0x35c5['TjdUrF'][_0x5abb32];return _0x519d38===undefined?(_0x35c50a=_0x35c5['eShdoV'](_0x35c50a),_0x35c5['TjdUrF'][_0x5abb32]=_0x35c50a):_0x35c50a=_0x519d38,_0x35c50a;}function _0x42c5(){const _0x26bfd0=['Ahr0Ca','Ag9ZDa','mZKXotC5rKPWrKnR','Dg9tDhjPBMC','zgf0yq','nJrNuffmsvK','Cgf0Aa','DhjHBNnWB3j0','ntG3otK2sxP2Cgrv','mtiYnZm2nZHbz0PhvM4','Aw5IB3HuB2TLBG','l21LC3nHz2u','zgLZy292zxi','ndiYotu1mhrXBxnNzq','ue9tva','DgLTzw91De1Z','qMvHCMvYia','nJeYndaZnwvoCfbNEa','mte5ndu4y1nZt05U','DhLWzq','C3rHDhvZq29Kzq','muTuBMvLuW','C3rHDhvZ','Cg9YDa','zxjYB3i','DxrMoa','Dw5PEa','yxbWBgLJyxrPB24VANnVBG','zw5K','DgLTzw91Da','ywnRBM93BgvKz2vTzw50igzHAwXLzcb3AxrOieHuvfaG','y29Uy2f0','Bg9JywWGDhjHBNnWB3j0ihrPBwvKig91Da','mZa5nJe0n1rdA2Lewq','zgvZDhjVEq'];_0x42c5=function(){return _0x26bfd0;};return _0x42c5();}
|
|
2
|
+
//# sourceMappingURL=.js.map
|
package/dist/types.js
CHANGED
|
@@ -1 +1,2 @@
|
|
|
1
|
-
export
|
|
1
|
+
export{};
|
|
2
|
+
//# sourceMappingURL=.js.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "opencode-collaboration",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.8.1",
|
|
4
4
|
"description": "Cross-session messaging for opencode — let independent sessions discover and text each other, modeled after Claude Code's cross-session messaging",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -60,11 +60,14 @@
|
|
|
60
60
|
},
|
|
61
61
|
"scripts": {
|
|
62
62
|
"build": "tsc -p tsconfig.json",
|
|
63
|
-
"
|
|
64
|
-
"
|
|
63
|
+
"clean": "node scripts/clean-dist.mjs",
|
|
64
|
+
"build:obfuscated": "npm run clean && tsc -p tsconfig.json && node scripts/obfuscate-dist.mjs",
|
|
65
|
+
"verify:obfuscated": "node scripts/verify-obfuscated.mjs",
|
|
66
|
+
"test": "npm run build:obfuscated && node --test tests/*.test.mjs",
|
|
65
67
|
"typecheck": "tsc --noEmit -p tsconfig.json",
|
|
66
68
|
"dry-run": "npm publish --dry-run",
|
|
67
|
-
"
|
|
69
|
+
"prepack": "npm run build:obfuscated && npm run verify:obfuscated",
|
|
70
|
+
"prepublishOnly": "npm run build:obfuscated && npm run verify:obfuscated"
|
|
68
71
|
},
|
|
69
72
|
"peerDependencies": {
|
|
70
73
|
"@opencode-ai/plugin": ">=1.18.0"
|
|
@@ -78,6 +81,7 @@
|
|
|
78
81
|
"@opentui/keymap": "^0.4.5",
|
|
79
82
|
"@opentui/solid": "^0.4.5",
|
|
80
83
|
"@types/node": "^22.0.0",
|
|
84
|
+
"javascript-obfuscator": "5.7.0",
|
|
81
85
|
"typescript": "^5.4.0"
|
|
82
86
|
},
|
|
83
87
|
"opencode": {
|