multiclaws 0.4.42 → 0.4.43

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.
Files changed (38) hide show
  1. package/README.md +2 -0
  2. package/dist/gateway/handlers.d.ts +4 -4
  3. package/dist/gateway/handlers.js +239 -239
  4. package/dist/index.d.ts +8 -8
  5. package/dist/index.js +710 -710
  6. package/dist/infra/frp.d.ts +55 -55
  7. package/dist/infra/frp.js +398 -398
  8. package/dist/infra/gateway-client.d.ts +27 -27
  9. package/dist/infra/gateway-client.js +136 -136
  10. package/dist/infra/json-store.d.ts +4 -4
  11. package/dist/infra/json-store.js +57 -57
  12. package/dist/infra/logger.d.ts +14 -14
  13. package/dist/infra/logger.js +25 -25
  14. package/dist/infra/rate-limiter.d.ts +19 -19
  15. package/dist/infra/rate-limiter.js +69 -69
  16. package/dist/infra/tailscale.d.ts +19 -19
  17. package/dist/infra/tailscale.js +120 -120
  18. package/dist/infra/telemetry.d.ts +3 -3
  19. package/dist/infra/telemetry.js +17 -17
  20. package/dist/infra/version.d.ts +1 -1
  21. package/dist/infra/version.js +19 -19
  22. package/dist/service/a2a-adapter.d.ts +80 -80
  23. package/dist/service/a2a-adapter.js +505 -505
  24. package/dist/service/agent-profile.d.ts +17 -17
  25. package/dist/service/agent-profile.js +58 -58
  26. package/dist/service/agent-registry.d.ts +29 -29
  27. package/dist/service/agent-registry.js +131 -131
  28. package/dist/service/multiclaws-service.d.ts +150 -150
  29. package/dist/service/multiclaws-service.js +1137 -1137
  30. package/dist/service/session-store.d.ts +46 -46
  31. package/dist/service/session-store.js +143 -143
  32. package/dist/task/tracker.d.ts +46 -46
  33. package/dist/task/tracker.js +191 -191
  34. package/dist/team/team-store.d.ts +42 -42
  35. package/dist/team/team-store.js +195 -195
  36. package/dist/types/openclaw.d.ts +109 -109
  37. package/dist/types/openclaw.js +2 -2
  38. package/package.json +1 -1
@@ -1,46 +1,46 @@
1
- import type { BasicLogger } from "../infra/logger";
2
- export type SessionStatus = "active" | "input-required" | "completed" | "failed" | "canceled";
3
- export type SessionMessage = {
4
- role: "user" | "agent";
5
- content: string;
6
- timestampMs: number;
7
- taskId?: string;
8
- };
9
- export type ConversationSession = {
10
- sessionId: string;
11
- agentUrl: string;
12
- agentName: string;
13
- contextId: string;
14
- currentTaskId?: string;
15
- status: SessionStatus;
16
- messages: SessionMessage[];
17
- createdAtMs: number;
18
- updatedAtMs: number;
19
- error?: string;
20
- };
21
- export declare class SessionStore {
22
- private readonly filePath;
23
- private readonly ttlMs;
24
- private readonly logger?;
25
- private store;
26
- private persistPending;
27
- constructor(opts: {
28
- filePath: string;
29
- ttlMs?: number;
30
- logger?: BasicLogger;
31
- });
32
- create(params: {
33
- agentUrl: string;
34
- agentName: string;
35
- contextId: string;
36
- }): ConversationSession;
37
- get(sessionId: string): ConversationSession | null;
38
- list(): ConversationSession[];
39
- update(sessionId: string, patch: Partial<Omit<ConversationSession, "sessionId" | "createdAtMs">>): ConversationSession | null;
40
- appendMessage(sessionId: string, msg: SessionMessage): ConversationSession | null;
41
- private loadSync;
42
- private schedulePersist;
43
- private persistAsync;
44
- private prune;
45
- private evictOldest;
46
- }
1
+ import type { BasicLogger } from "../infra/logger";
2
+ export type SessionStatus = "active" | "input-required" | "completed" | "failed" | "canceled";
3
+ export type SessionMessage = {
4
+ role: "user" | "agent";
5
+ content: string;
6
+ timestampMs: number;
7
+ taskId?: string;
8
+ };
9
+ export type ConversationSession = {
10
+ sessionId: string;
11
+ agentUrl: string;
12
+ agentName: string;
13
+ contextId: string;
14
+ currentTaskId?: string;
15
+ status: SessionStatus;
16
+ messages: SessionMessage[];
17
+ createdAtMs: number;
18
+ updatedAtMs: number;
19
+ error?: string;
20
+ };
21
+ export declare class SessionStore {
22
+ private readonly filePath;
23
+ private readonly ttlMs;
24
+ private readonly logger?;
25
+ private store;
26
+ private persistPending;
27
+ constructor(opts: {
28
+ filePath: string;
29
+ ttlMs?: number;
30
+ logger?: BasicLogger;
31
+ });
32
+ create(params: {
33
+ agentUrl: string;
34
+ agentName: string;
35
+ contextId: string;
36
+ }): ConversationSession;
37
+ get(sessionId: string): ConversationSession | null;
38
+ list(): ConversationSession[];
39
+ update(sessionId: string, patch: Partial<Omit<ConversationSession, "sessionId" | "createdAtMs">>): ConversationSession | null;
40
+ appendMessage(sessionId: string, msg: SessionMessage): ConversationSession | null;
41
+ private loadSync;
42
+ private schedulePersist;
43
+ private persistAsync;
44
+ private prune;
45
+ private evictOldest;
46
+ }
@@ -1,143 +1,143 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.SessionStore = void 0;
7
- const node_crypto_1 = require("node:crypto");
8
- const node_fs_1 = __importDefault(require("node:fs"));
9
- const promises_1 = __importDefault(require("node:fs/promises"));
10
- const node_path_1 = __importDefault(require("node:path"));
11
- const DEFAULT_TTL_MS = 7 * 24 * 60 * 60 * 1000; // 7 days
12
- const MAX_SESSIONS = 1_000;
13
- const MAX_MESSAGES_PER_SESSION = 200;
14
- function emptyStore() {
15
- return { version: 1, sessions: [] };
16
- }
17
- function normalizeStore(raw) {
18
- if (raw.version !== 1 || !Array.isArray(raw.sessions)) {
19
- return emptyStore();
20
- }
21
- return {
22
- version: 1,
23
- sessions: raw.sessions.filter((s) => s &&
24
- typeof s.sessionId === "string" &&
25
- typeof s.agentUrl === "string" &&
26
- typeof s.status === "string" &&
27
- typeof s.createdAtMs === "number" &&
28
- Array.isArray(s.messages)),
29
- };
30
- }
31
- class SessionStore {
32
- filePath;
33
- ttlMs;
34
- logger;
35
- store;
36
- persistPending = false;
37
- constructor(opts) {
38
- this.filePath = opts.filePath;
39
- this.ttlMs = opts.ttlMs ?? DEFAULT_TTL_MS;
40
- this.logger = opts.logger;
41
- this.store = this.loadSync();
42
- }
43
- create(params) {
44
- this.prune();
45
- const now = Date.now();
46
- const session = {
47
- sessionId: (0, node_crypto_1.randomUUID)(),
48
- agentUrl: params.agentUrl,
49
- agentName: params.agentName,
50
- contextId: params.contextId,
51
- status: "active",
52
- messages: [],
53
- createdAtMs: now,
54
- updatedAtMs: now,
55
- };
56
- if (this.store.sessions.length >= MAX_SESSIONS) {
57
- this.evictOldest();
58
- }
59
- this.store.sessions.push(session);
60
- this.schedulePersist();
61
- return session;
62
- }
63
- get(sessionId) {
64
- return this.store.sessions.find((s) => s.sessionId === sessionId) ?? null;
65
- }
66
- list() {
67
- return [...this.store.sessions].sort((a, b) => b.updatedAtMs - a.updatedAtMs);
68
- }
69
- update(sessionId, patch) {
70
- const idx = this.store.sessions.findIndex((s) => s.sessionId === sessionId);
71
- if (idx < 0)
72
- return null;
73
- const next = {
74
- ...this.store.sessions[idx],
75
- ...patch,
76
- updatedAtMs: Date.now(),
77
- };
78
- this.store.sessions[idx] = next;
79
- this.schedulePersist();
80
- return next;
81
- }
82
- appendMessage(sessionId, msg) {
83
- const session = this.get(sessionId);
84
- if (!session)
85
- return null;
86
- let messages = [...session.messages, msg];
87
- // Truncate old messages, keeping the most recent ones
88
- if (messages.length > MAX_MESSAGES_PER_SESSION) {
89
- messages = messages.slice(-MAX_MESSAGES_PER_SESSION);
90
- }
91
- return this.update(sessionId, { messages });
92
- }
93
- loadSync() {
94
- node_fs_1.default.mkdirSync(node_path_1.default.dirname(this.filePath), { recursive: true });
95
- try {
96
- const raw = JSON.parse(node_fs_1.default.readFileSync(this.filePath, "utf8"));
97
- return normalizeStore(raw);
98
- }
99
- catch {
100
- const store = emptyStore();
101
- node_fs_1.default.writeFileSync(this.filePath, JSON.stringify(store, null, 2), "utf8");
102
- return store;
103
- }
104
- }
105
- schedulePersist() {
106
- if (this.persistPending)
107
- return;
108
- this.persistPending = true;
109
- queueMicrotask(() => {
110
- this.persistPending = false;
111
- void this.persistAsync();
112
- });
113
- }
114
- async persistAsync() {
115
- try {
116
- await promises_1.default.mkdir(node_path_1.default.dirname(this.filePath), { recursive: true });
117
- const tmp = `${this.filePath}.${process.pid}.${Date.now()}.tmp`;
118
- await promises_1.default.writeFile(tmp, JSON.stringify(this.store, null, 2), "utf8");
119
- await promises_1.default.rename(tmp, this.filePath);
120
- }
121
- catch (err) {
122
- // best-effort
123
- this.logger?.warn?.(`[session-store] persistAsync failed: ${err instanceof Error ? err.message : String(err)}`);
124
- }
125
- }
126
- prune() {
127
- const cutoff = Date.now() - this.ttlMs;
128
- this.store.sessions = this.store.sessions.filter((s) => {
129
- if (s.updatedAtMs >= cutoff)
130
- return true;
131
- return s.status !== "completed" && s.status !== "failed" && s.status !== "canceled";
132
- });
133
- }
134
- evictOldest() {
135
- const removable = [...this.store.sessions]
136
- .filter((s) => s.status === "completed" || s.status === "failed" || s.status === "canceled")
137
- .sort((a, b) => a.updatedAtMs - b.updatedAtMs)
138
- .slice(0, Math.max(1, Math.floor(MAX_SESSIONS / 4)));
139
- const ids = new Set(removable.map((s) => s.sessionId));
140
- this.store.sessions = this.store.sessions.filter((s) => !ids.has(s.sessionId));
141
- }
142
- }
143
- exports.SessionStore = SessionStore;
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.SessionStore = void 0;
7
+ const node_crypto_1 = require("node:crypto");
8
+ const node_fs_1 = __importDefault(require("node:fs"));
9
+ const promises_1 = __importDefault(require("node:fs/promises"));
10
+ const node_path_1 = __importDefault(require("node:path"));
11
+ const DEFAULT_TTL_MS = 7 * 24 * 60 * 60 * 1000; // 7 days
12
+ const MAX_SESSIONS = 1_000;
13
+ const MAX_MESSAGES_PER_SESSION = 200;
14
+ function emptyStore() {
15
+ return { version: 1, sessions: [] };
16
+ }
17
+ function normalizeStore(raw) {
18
+ if (raw.version !== 1 || !Array.isArray(raw.sessions)) {
19
+ return emptyStore();
20
+ }
21
+ return {
22
+ version: 1,
23
+ sessions: raw.sessions.filter((s) => s &&
24
+ typeof s.sessionId === "string" &&
25
+ typeof s.agentUrl === "string" &&
26
+ typeof s.status === "string" &&
27
+ typeof s.createdAtMs === "number" &&
28
+ Array.isArray(s.messages)),
29
+ };
30
+ }
31
+ class SessionStore {
32
+ filePath;
33
+ ttlMs;
34
+ logger;
35
+ store;
36
+ persistPending = false;
37
+ constructor(opts) {
38
+ this.filePath = opts.filePath;
39
+ this.ttlMs = opts.ttlMs ?? DEFAULT_TTL_MS;
40
+ this.logger = opts.logger;
41
+ this.store = this.loadSync();
42
+ }
43
+ create(params) {
44
+ this.prune();
45
+ const now = Date.now();
46
+ const session = {
47
+ sessionId: (0, node_crypto_1.randomUUID)(),
48
+ agentUrl: params.agentUrl,
49
+ agentName: params.agentName,
50
+ contextId: params.contextId,
51
+ status: "active",
52
+ messages: [],
53
+ createdAtMs: now,
54
+ updatedAtMs: now,
55
+ };
56
+ if (this.store.sessions.length >= MAX_SESSIONS) {
57
+ this.evictOldest();
58
+ }
59
+ this.store.sessions.push(session);
60
+ this.schedulePersist();
61
+ return session;
62
+ }
63
+ get(sessionId) {
64
+ return this.store.sessions.find((s) => s.sessionId === sessionId) ?? null;
65
+ }
66
+ list() {
67
+ return [...this.store.sessions].sort((a, b) => b.updatedAtMs - a.updatedAtMs);
68
+ }
69
+ update(sessionId, patch) {
70
+ const idx = this.store.sessions.findIndex((s) => s.sessionId === sessionId);
71
+ if (idx < 0)
72
+ return null;
73
+ const next = {
74
+ ...this.store.sessions[idx],
75
+ ...patch,
76
+ updatedAtMs: Date.now(),
77
+ };
78
+ this.store.sessions[idx] = next;
79
+ this.schedulePersist();
80
+ return next;
81
+ }
82
+ appendMessage(sessionId, msg) {
83
+ const session = this.get(sessionId);
84
+ if (!session)
85
+ return null;
86
+ let messages = [...session.messages, msg];
87
+ // Truncate old messages, keeping the most recent ones
88
+ if (messages.length > MAX_MESSAGES_PER_SESSION) {
89
+ messages = messages.slice(-MAX_MESSAGES_PER_SESSION);
90
+ }
91
+ return this.update(sessionId, { messages });
92
+ }
93
+ loadSync() {
94
+ node_fs_1.default.mkdirSync(node_path_1.default.dirname(this.filePath), { recursive: true });
95
+ try {
96
+ const raw = JSON.parse(node_fs_1.default.readFileSync(this.filePath, "utf8"));
97
+ return normalizeStore(raw);
98
+ }
99
+ catch {
100
+ const store = emptyStore();
101
+ node_fs_1.default.writeFileSync(this.filePath, JSON.stringify(store, null, 2), "utf8");
102
+ return store;
103
+ }
104
+ }
105
+ schedulePersist() {
106
+ if (this.persistPending)
107
+ return;
108
+ this.persistPending = true;
109
+ queueMicrotask(() => {
110
+ this.persistPending = false;
111
+ void this.persistAsync();
112
+ });
113
+ }
114
+ async persistAsync() {
115
+ try {
116
+ await promises_1.default.mkdir(node_path_1.default.dirname(this.filePath), { recursive: true });
117
+ const tmp = `${this.filePath}.${process.pid}.${Date.now()}.tmp`;
118
+ await promises_1.default.writeFile(tmp, JSON.stringify(this.store, null, 2), "utf8");
119
+ await promises_1.default.rename(tmp, this.filePath);
120
+ }
121
+ catch (err) {
122
+ // best-effort
123
+ this.logger?.warn?.(`[session-store] persistAsync failed: ${err instanceof Error ? err.message : String(err)}`);
124
+ }
125
+ }
126
+ prune() {
127
+ const cutoff = Date.now() - this.ttlMs;
128
+ this.store.sessions = this.store.sessions.filter((s) => {
129
+ if (s.updatedAtMs >= cutoff)
130
+ return true;
131
+ return s.status !== "completed" && s.status !== "failed" && s.status !== "canceled";
132
+ });
133
+ }
134
+ evictOldest() {
135
+ const removable = [...this.store.sessions]
136
+ .filter((s) => s.status === "completed" || s.status === "failed" || s.status === "canceled")
137
+ .sort((a, b) => a.updatedAtMs - b.updatedAtMs)
138
+ .slice(0, Math.max(1, Math.floor(MAX_SESSIONS / 4)));
139
+ const ids = new Set(removable.map((s) => s.sessionId));
140
+ this.store.sessions = this.store.sessions.filter((s) => !ids.has(s.sessionId));
141
+ }
142
+ }
143
+ exports.SessionStore = SessionStore;
@@ -1,46 +1,46 @@
1
- import type { BasicLogger } from "../infra/logger";
2
- export type TaskStatus = "queued" | "running" | "completed" | "failed";
3
- export type TaskRecord = {
4
- taskId: string;
5
- fromPeerId: string;
6
- toPeerId: string;
7
- task: string;
8
- context?: string;
9
- status: TaskStatus;
10
- createdAtMs: number;
11
- updatedAtMs: number;
12
- result?: string;
13
- error?: string;
14
- };
15
- export declare class TaskTracker {
16
- private readonly filePath;
17
- private readonly ttlMs;
18
- private readonly maxTasks;
19
- private readonly store;
20
- private readonly logger?;
21
- private pruneTimer;
22
- private persistPending;
23
- constructor(opts?: {
24
- ttlMs?: number;
25
- maxTasks?: number;
26
- filePath?: string;
27
- logger?: BasicLogger;
28
- });
29
- create(params: {
30
- fromPeerId: string;
31
- toPeerId: string;
32
- task: string;
33
- context?: string;
34
- }): TaskRecord;
35
- update(taskId: string, patch: Partial<Omit<TaskRecord, "taskId" | "createdAtMs">>): TaskRecord | null;
36
- get(taskId: string): TaskRecord | null;
37
- list(): TaskRecord[];
38
- destroy(): void;
39
- /** Sync load at startup — runs once before the event loop is busy. */
40
- private loadStoreSync;
41
- /** Coalesce rapid writes into a single async flush. */
42
- private schedulePersist;
43
- private persistAsync;
44
- private prune;
45
- private evictOldest;
46
- }
1
+ import type { BasicLogger } from "../infra/logger";
2
+ export type TaskStatus = "queued" | "running" | "completed" | "failed";
3
+ export type TaskRecord = {
4
+ taskId: string;
5
+ fromPeerId: string;
6
+ toPeerId: string;
7
+ task: string;
8
+ context?: string;
9
+ status: TaskStatus;
10
+ createdAtMs: number;
11
+ updatedAtMs: number;
12
+ result?: string;
13
+ error?: string;
14
+ };
15
+ export declare class TaskTracker {
16
+ private readonly filePath;
17
+ private readonly ttlMs;
18
+ private readonly maxTasks;
19
+ private readonly store;
20
+ private readonly logger?;
21
+ private pruneTimer;
22
+ private persistPending;
23
+ constructor(opts?: {
24
+ ttlMs?: number;
25
+ maxTasks?: number;
26
+ filePath?: string;
27
+ logger?: BasicLogger;
28
+ });
29
+ create(params: {
30
+ fromPeerId: string;
31
+ toPeerId: string;
32
+ task: string;
33
+ context?: string;
34
+ }): TaskRecord;
35
+ update(taskId: string, patch: Partial<Omit<TaskRecord, "taskId" | "createdAtMs">>): TaskRecord | null;
36
+ get(taskId: string): TaskRecord | null;
37
+ list(): TaskRecord[];
38
+ destroy(): void;
39
+ /** Sync load at startup — runs once before the event loop is busy. */
40
+ private loadStoreSync;
41
+ /** Coalesce rapid writes into a single async flush. */
42
+ private schedulePersist;
43
+ private persistAsync;
44
+ private prune;
45
+ private evictOldest;
46
+ }