letagents 0.12.23 → 0.12.24
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/dist/mcp/local-state/local-chat.js +24 -371
- package/dist/mcp/local-state/storage.js +4 -48
- package/package.json +1 -1
- package/shared/claude-tool-operation.d.mts +1 -0
- package/shared/claude-tool-operation.mjs +8 -0
- package/shared/conversation-contracts.d.mts +62 -0
- package/shared/local-board-owner.d.mts +9 -0
- package/shared/local-board-owner.mjs +80 -0
- package/shared/local-task-revisions.d.mts +4 -0
- package/shared/local-task-revisions.mjs +97 -0
- package/shared/local-task-store.d.mts +43 -0
- package/shared/local-task-store.mjs +374 -0
- package/shared/local-worker-state-fence.d.mts +2 -0
- package/shared/local-worker-state-fence.mjs +69 -0
- package/shared/ui/ConversationIcon.vue +28 -0
- package/shared/ui/PrivateMessages.vue +1001 -0
- package/shared/ui/private-messages.css +817 -0
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { closeSync, mkdirSync, openSync, readFileSync, rmSync, statSync } from 'node:fs';
|
|
2
|
+
import { dirname } from 'node:path';
|
|
3
|
+
import { isAbsolute } from 'node:path';
|
|
4
|
+
|
|
5
|
+
/** Remote MCP board requests retain their exact registered connection fence. */
|
|
6
|
+
export function withRegisteredWorkerStateFence(statePath, supplied, callback) {
|
|
7
|
+
if (typeof statePath !== "string" || !isAbsolute(statePath)
|
|
8
|
+
|| !supplied || typeof supplied.session_token !== "string"
|
|
9
|
+
|| ![supplied.agent_instance_id, supplied.session_id, supplied.agent_key, supplied.room_id]
|
|
10
|
+
.every(value => typeof value === "string" && value.trim())) {
|
|
11
|
+
throw new Error("Register this MCP worker before changing the local board.");
|
|
12
|
+
}
|
|
13
|
+
return withStateFileLock(statePath, () => {
|
|
14
|
+
let state;
|
|
15
|
+
try { state = JSON.parse(readFileSync(statePath, "utf8")); } catch { state = null; }
|
|
16
|
+
const current = state?.agent_sessions?.[supplied.session_id];
|
|
17
|
+
if (!current || current.ended_at || current.session_token !== supplied.session_token
|
|
18
|
+
|| current.agent_instance_id !== supplied.agent_instance_id || current.room_id !== supplied.room_id
|
|
19
|
+
|| current.agent_key !== supplied.agent_key
|
|
20
|
+
|| state?.mcp_workers?.[current.agent_instance_id]?.rooms?.[current.room_id]?.pending) {
|
|
21
|
+
throw new Error("Local worker authority ended or this connection was replaced. Reconnect explicitly with its worker_id.");
|
|
22
|
+
}
|
|
23
|
+
return callback(current);
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
const STATE_LOCK_WAIT_MS = 25;
|
|
27
|
+
const STATE_LOCK_TIMEOUT_MS = 2_000;
|
|
28
|
+
const STATE_LOCK_STALE_MS = 10_000;
|
|
29
|
+
const STATE_LOCK_SLEEP_BUFFER = new Int32Array(new SharedArrayBuffer(4));
|
|
30
|
+
function sleepSync(ms) { if (ms > 0)
|
|
31
|
+
Atomics.wait(STATE_LOCK_SLEEP_BUFFER, 0, 0, ms); }
|
|
32
|
+
export function withStateFileLock(statePath, callback) {
|
|
33
|
+
mkdirSync(dirname(statePath), { recursive: true });
|
|
34
|
+
const lockPath = `${statePath}.lock`;
|
|
35
|
+
const startedAt = Date.now();
|
|
36
|
+
while (true) {
|
|
37
|
+
let lockFd = null;
|
|
38
|
+
try {
|
|
39
|
+
lockFd = openSync(lockPath, "wx");
|
|
40
|
+
return callback(statePath);
|
|
41
|
+
}
|
|
42
|
+
catch (error) {
|
|
43
|
+
const err = error;
|
|
44
|
+
if (err.code !== "EEXIST") {
|
|
45
|
+
throw error;
|
|
46
|
+
}
|
|
47
|
+
try {
|
|
48
|
+
const stats = statSync(lockPath);
|
|
49
|
+
if (Date.now() - stats.mtimeMs > STATE_LOCK_STALE_MS) {
|
|
50
|
+
rmSync(lockPath, { force: true });
|
|
51
|
+
continue;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
catch {
|
|
55
|
+
continue;
|
|
56
|
+
}
|
|
57
|
+
if (Date.now() - startedAt >= STATE_LOCK_TIMEOUT_MS) {
|
|
58
|
+
throw new Error(`Timed out acquiring local state lock at ${lockPath}`);
|
|
59
|
+
}
|
|
60
|
+
sleepSync(STATE_LOCK_WAIT_MS);
|
|
61
|
+
}
|
|
62
|
+
finally {
|
|
63
|
+
if (lockFd !== null) {
|
|
64
|
+
closeSync(lockFd);
|
|
65
|
+
rmSync(lockPath, { force: true });
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<svg
|
|
3
|
+
viewBox="0 0 24 24"
|
|
4
|
+
fill="none"
|
|
5
|
+
stroke="currentColor"
|
|
6
|
+
stroke-width="1.6"
|
|
7
|
+
stroke-linecap="round"
|
|
8
|
+
stroke-linejoin="round"
|
|
9
|
+
aria-hidden="true"
|
|
10
|
+
>
|
|
11
|
+
<path :d="paths[name]" />
|
|
12
|
+
</svg>
|
|
13
|
+
</template>
|
|
14
|
+
<script setup lang="ts">
|
|
15
|
+
defineProps<{ name: keyof typeof paths }>();
|
|
16
|
+
const paths = {
|
|
17
|
+
chat: "M21 11.5a8.5 8.5 0 0 1-8.5 8.5H4l-2 2v-10A9 9 0 0 1 11 3h1.5a8.5 8.5 0 0 1 8.5 8.5ZM7 9h10M7 14h6",
|
|
18
|
+
plus: "M12 5v14M5 12h14",
|
|
19
|
+
search: "m21 21-5-5M18 10a8 8 0 1 1-16 0 8 8 0 0 1 16 0",
|
|
20
|
+
back: "m14 6-6 6 6 6",
|
|
21
|
+
close: "m6 6 12 12M6 18 18 6",
|
|
22
|
+
send: "m5 12 7-7 7 7M12 5v15",
|
|
23
|
+
users:
|
|
24
|
+
"M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2M16 3a4 4 0 0 1 0 8M22 21v-2a4 4 0 0 0-3-3.87M13 7a4 4 0 1 1-8 0 4 4 0 0 1 8 0",
|
|
25
|
+
more: "M5 12h.01M12 12h.01M19 12h.01",
|
|
26
|
+
check: "m5 12 4 4L19 6",
|
|
27
|
+
};
|
|
28
|
+
</script>
|