assistme 0.3.0 → 0.3.2
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/PLAN.md +14 -3
- package/dist/{chunk-UWE5WVQI.js → chunk-KX7ITO55.js} +20 -11
- package/dist/index.js +1791 -572
- package/dist/{job-runner-N4XAAWLJ.js → job-runner-P2L6MOOX.js} +1 -1
- package/package.json +5 -3
- package/src/agent/job-runner.ts +9 -13
- package/src/agent/mcp-servers.ts +6 -1020
- package/src/agent/memory.ts +2 -11
- package/src/agent/processor.ts +18 -108
- package/src/agent/scheduler.ts +2 -3
- package/src/agent/session.ts +20 -36
- package/src/agent/skills.ts +167 -61
- package/src/agent/system-prompt.ts +126 -0
- package/src/browser/chrome-launcher.ts +555 -0
- package/src/browser/controller.ts +1386 -0
- package/src/browser/types.ts +70 -0
- package/src/commands/credential.ts +190 -0
- package/src/commands/job.ts +14 -45
- package/src/commands/memory.ts +16 -29
- package/src/commands/schedule.ts +15 -37
- package/src/commands/start.ts +11 -43
- package/src/credentials/credential-store.test.ts +162 -0
- package/src/credentials/credential-store.ts +266 -0
- package/src/credentials/encryption.test.ts +98 -0
- package/src/credentials/encryption.ts +82 -0
- package/src/credentials/index.ts +15 -0
- package/src/credentials/local-store.ts +89 -0
- package/src/db/action.ts +19 -0
- package/src/db/api-client.ts +3 -32
- package/src/db/auth-store.ts +41 -0
- package/src/db/auth.ts +38 -0
- package/src/db/conversation.ts +39 -0
- package/src/db/event.ts +52 -0
- package/src/db/job-poll.ts +18 -0
- package/src/db/session.ts +60 -0
- package/src/db/supabase.ts +40 -383
- package/src/db/task.ts +69 -0
- package/src/db/types.ts +54 -0
- package/src/index.ts +2 -0
- package/src/mcp/agent-tools-server.ts +1047 -0
- package/src/mcp/browser-server.ts +258 -0
- package/src/tools/browser.ts +28 -1208
- package/src/tools/index.ts +32 -263
- package/src/tools/web.ts +0 -73
package/src/db/supabase.ts
CHANGED
|
@@ -1,386 +1,43 @@
|
|
|
1
|
-
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "fs";
|
|
2
|
-
import { join } from "path";
|
|
3
|
-
import { homedir } from "os";
|
|
4
|
-
import { callMcpHandler } from "./api-client.js";
|
|
5
|
-
import { log } from "../utils/logger.js";
|
|
6
|
-
|
|
7
|
-
// ── Auth Store (persists am_ token to disk) ──────────────────────────
|
|
8
|
-
|
|
9
|
-
const AUTH_DIR = join(homedir(), ".config", "assistme");
|
|
10
|
-
const AUTH_FILE = join(AUTH_DIR, "auth.json");
|
|
11
|
-
|
|
12
|
-
function ensureAuthDir() {
|
|
13
|
-
if (!existsSync(AUTH_DIR)) {
|
|
14
|
-
mkdirSync(AUTH_DIR, { recursive: true, mode: 0o700 });
|
|
15
|
-
}
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
function readAuthStore(): Record<string, string> {
|
|
19
|
-
try {
|
|
20
|
-
if (existsSync(AUTH_FILE)) {
|
|
21
|
-
return JSON.parse(readFileSync(AUTH_FILE, "utf-8"));
|
|
22
|
-
}
|
|
23
|
-
} catch {
|
|
24
|
-
// Corrupted file — start fresh
|
|
25
|
-
}
|
|
26
|
-
return {};
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
function writeAuthStore(data: Record<string, string>) {
|
|
30
|
-
ensureAuthDir();
|
|
31
|
-
writeFileSync(AUTH_FILE, JSON.stringify(data, null, 2), { mode: 0o600 });
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
// ── Auth ─────────────────────────────────────────────────────────────
|
|
35
|
-
|
|
36
|
-
/**
|
|
37
|
-
* Login using an am_ MCP token.
|
|
38
|
-
* Validates against DB via edge function, stores locally.
|
|
39
|
-
*/
|
|
40
|
-
export async function loginWithToken(mcpToken: string): Promise<string> {
|
|
41
|
-
if (!mcpToken.startsWith("am_")) {
|
|
42
|
-
throw new Error(
|
|
43
|
-
"Invalid token format. Use an am_ token from the web page."
|
|
44
|
-
);
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
const result = await callMcpHandler<{ user_id: string; email: string | null }>(
|
|
48
|
-
"auth.validate_token",
|
|
49
|
-
{},
|
|
50
|
-
mcpToken,
|
|
51
|
-
);
|
|
52
|
-
|
|
53
|
-
// Persist token
|
|
54
|
-
const store = readAuthStore();
|
|
55
|
-
store["mcp_token"] = mcpToken;
|
|
56
|
-
writeAuthStore(store);
|
|
57
|
-
|
|
58
|
-
return result.user_id;
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
export async function getCurrentUserId(): Promise<string> {
|
|
62
|
-
const result = await callMcpHandler<{ user_id: string }>(
|
|
63
|
-
"auth.validate_token",
|
|
64
|
-
);
|
|
65
|
-
return result.user_id;
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
export async function logout(): Promise<void> {
|
|
69
|
-
try {
|
|
70
|
-
writeAuthStore({});
|
|
71
|
-
} catch {
|
|
72
|
-
// ignore
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
// ── Session Management ─────────────────────────────────────────────
|
|
77
|
-
|
|
78
|
-
export interface AgentSession {
|
|
79
|
-
id: string;
|
|
80
|
-
user_id: string;
|
|
81
|
-
session_name: string;
|
|
82
|
-
status: "online" | "offline" | "busy";
|
|
83
|
-
workspace_path: string | null;
|
|
84
|
-
agent_version: string | null;
|
|
85
|
-
started_at: string;
|
|
86
|
-
last_heartbeat_at: string;
|
|
87
|
-
ended_at: string | null;
|
|
88
|
-
metadata: Record<string, unknown>;
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
export async function createSession(
|
|
92
|
-
_userId: string,
|
|
93
|
-
sessionName: string,
|
|
94
|
-
workspacePath: string,
|
|
95
|
-
version: string
|
|
96
|
-
): Promise<AgentSession> {
|
|
97
|
-
const { getConfig } = await import("../utils/config.js");
|
|
98
|
-
const data = await callMcpHandler<AgentSession>("session.create", {
|
|
99
|
-
session_name: sessionName,
|
|
100
|
-
workspace_path: workspacePath,
|
|
101
|
-
version,
|
|
102
|
-
model: getConfig().model || null,
|
|
103
|
-
});
|
|
104
|
-
return data;
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
export async function updateHeartbeat(sessionId: string): Promise<void> {
|
|
108
|
-
try {
|
|
109
|
-
await callMcpHandler("session.heartbeat", { session_id: sessionId });
|
|
110
|
-
} catch (err) {
|
|
111
|
-
log.warn(`Heartbeat update failed: ${err instanceof Error ? err.message : err}`);
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
export async function endSession(sessionId: string): Promise<void> {
|
|
116
|
-
try {
|
|
117
|
-
await callMcpHandler("session.end", { session_id: sessionId });
|
|
118
|
-
} catch (err) {
|
|
119
|
-
log.error(`Failed to end session: ${err instanceof Error ? err.message : err}`);
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
export async function setSessionBusy(
|
|
124
|
-
sessionId: string,
|
|
125
|
-
busy: boolean
|
|
126
|
-
): Promise<void> {
|
|
127
|
-
await callMcpHandler("session.set_busy", {
|
|
128
|
-
session_id: sessionId,
|
|
129
|
-
busy,
|
|
130
|
-
});
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
export async function cleanupStaleSessions(
|
|
134
|
-
currentSessionId: string,
|
|
135
|
-
thresholdMs = 120_000
|
|
136
|
-
): Promise<number> {
|
|
137
|
-
try {
|
|
138
|
-
const result = await callMcpHandler<{ cleaned: number }>(
|
|
139
|
-
"session.cleanup_stale",
|
|
140
|
-
{ current_session_id: currentSessionId, threshold_ms: thresholdMs },
|
|
141
|
-
);
|
|
142
|
-
return result.cleaned;
|
|
143
|
-
} catch {
|
|
144
|
-
return 0;
|
|
145
|
-
}
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
export async function getActiveSessions(
|
|
149
|
-
limit = 5
|
|
150
|
-
): Promise<AgentSession[]> {
|
|
151
|
-
return callMcpHandler<AgentSession[]>("session.get_active", { limit });
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
// ── Conversation Management ─────────────────────────────────────────
|
|
155
|
-
|
|
156
|
-
export async function getOrCreateCliConversation(
|
|
157
|
-
_userId: string,
|
|
158
|
-
_sessionId: string
|
|
159
|
-
): Promise<string> {
|
|
160
|
-
const data = await callMcpHandler<string>("conversation.get_or_create");
|
|
161
|
-
return data;
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
// ── Message / Task Management ────────────────────────────────────────
|
|
165
|
-
|
|
166
|
-
export interface ConversationMessage {
|
|
167
|
-
id: string;
|
|
168
|
-
conversation_id: string;
|
|
169
|
-
sender_id: string;
|
|
170
|
-
role: "user" | "assistant" | "system";
|
|
171
|
-
content: string;
|
|
172
|
-
status: "pending" | "running" | "completed" | "failed" | "cancelled" | null;
|
|
173
|
-
session_id: string | null;
|
|
174
|
-
tool_calls: Record<string, unknown> | null;
|
|
175
|
-
tool_results: Record<string, unknown> | null;
|
|
176
|
-
metadata: Record<string, unknown>;
|
|
177
|
-
created_at: string;
|
|
178
|
-
updated_at: string;
|
|
179
|
-
prompt: string;
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
export type AgentTask = ConversationMessage;
|
|
183
|
-
|
|
184
|
-
export async function createTask(
|
|
185
|
-
conversationId: string,
|
|
186
|
-
_userId: string,
|
|
187
|
-
sessionId: string,
|
|
188
|
-
prompt: string
|
|
189
|
-
): Promise<ConversationMessage> {
|
|
190
|
-
const data = await callMcpHandler<Record<string, unknown>>("task.create", {
|
|
191
|
-
conversation_id: conversationId,
|
|
192
|
-
session_id: sessionId,
|
|
193
|
-
prompt,
|
|
194
|
-
});
|
|
195
|
-
return { ...data, prompt } as ConversationMessage;
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
/**
|
|
199
|
-
* Atomically poll ONE pending task and claim it in a single call.
|
|
200
|
-
* Uses FOR UPDATE SKIP LOCKED — concurrent CLIs will never grab the same task.
|
|
201
|
-
* Returns null if no pending task exists.
|
|
202
|
-
*/
|
|
203
|
-
export async function pollAndClaimTask(
|
|
204
|
-
sessionId: string
|
|
205
|
-
): Promise<ConversationMessage | null> {
|
|
206
|
-
try {
|
|
207
|
-
const data = await callMcpHandler<Record<string, unknown> | null>(
|
|
208
|
-
"task.poll_and_claim",
|
|
209
|
-
{ session_id: sessionId },
|
|
210
|
-
);
|
|
211
|
-
|
|
212
|
-
if (!data) return null;
|
|
213
|
-
|
|
214
|
-
return {
|
|
215
|
-
...data,
|
|
216
|
-
prompt:
|
|
217
|
-
(data.metadata as Record<string, unknown>)?.prompt || data.content || "",
|
|
218
|
-
} as ConversationMessage;
|
|
219
|
-
} catch (err) {
|
|
220
|
-
log.warn(`Poll-and-claim failed: ${err instanceof Error ? err.message : err}`);
|
|
221
|
-
return null;
|
|
222
|
-
}
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
export async function claimTask(messageId: string): Promise<boolean> {
|
|
226
|
-
const data = await callMcpHandler<boolean>("task.claim", {
|
|
227
|
-
message_id: messageId,
|
|
228
|
-
});
|
|
229
|
-
return data;
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
export async function completeTask(
|
|
233
|
-
messageId: string,
|
|
234
|
-
resultSummary: string,
|
|
235
|
-
tokenUsage?: Record<string, number>
|
|
236
|
-
): Promise<void> {
|
|
237
|
-
await callMcpHandler("task.complete", {
|
|
238
|
-
message_id: messageId,
|
|
239
|
-
result: resultSummary,
|
|
240
|
-
token_usage: tokenUsage || null,
|
|
241
|
-
});
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
export async function failTask(
|
|
245
|
-
messageId: string,
|
|
246
|
-
errorMessage: string
|
|
247
|
-
): Promise<void> {
|
|
248
|
-
try {
|
|
249
|
-
await callMcpHandler("task.fail", {
|
|
250
|
-
message_id: messageId,
|
|
251
|
-
error: errorMessage,
|
|
252
|
-
});
|
|
253
|
-
} catch (err) {
|
|
254
|
-
log.error(`Failed to update task status: ${err instanceof Error ? err.message : err}`);
|
|
255
|
-
}
|
|
256
|
-
}
|
|
257
|
-
|
|
258
|
-
// ── Job Run Polling ─────────────────────────────────────────────────
|
|
259
|
-
|
|
260
|
-
export interface PendingJobRun {
|
|
261
|
-
id: string;
|
|
262
|
-
job_id: string;
|
|
263
|
-
job_name: string;
|
|
264
|
-
trigger_type: string;
|
|
265
|
-
}
|
|
266
|
-
|
|
267
1
|
/**
|
|
268
|
-
*
|
|
269
|
-
*
|
|
270
|
-
*
|
|
2
|
+
* Re-export barrel — all consumers import from "db/supabase.js" today.
|
|
3
|
+
* This file preserves backward compatibility while the actual logic
|
|
4
|
+
* lives in focused modules under db/.
|
|
271
5
|
*/
|
|
272
|
-
export async function pollAndClaimJobRun(
|
|
273
|
-
_userId: string
|
|
274
|
-
): Promise<PendingJobRun | null> {
|
|
275
|
-
try {
|
|
276
|
-
const data = await callMcpHandler<PendingJobRun | null>(
|
|
277
|
-
"job.claim_pending_run",
|
|
278
|
-
);
|
|
279
|
-
return data;
|
|
280
|
-
} catch (err) {
|
|
281
|
-
log.debug(`Job run poll failed: ${err instanceof Error ? err.message : err}`);
|
|
282
|
-
return null;
|
|
283
|
-
}
|
|
284
|
-
}
|
|
285
|
-
|
|
286
|
-
// ── Conversation History ─────────────────────────────────────────────
|
|
287
|
-
|
|
288
|
-
export interface HistoryEntry {
|
|
289
|
-
prompt: string;
|
|
290
|
-
response: string;
|
|
291
|
-
}
|
|
292
|
-
|
|
293
|
-
/**
|
|
294
|
-
* Fetch completed messages from a conversation to build history context.
|
|
295
|
-
* Returns messages in chronological order (oldest first).
|
|
296
|
-
*/
|
|
297
|
-
export async function getConversationHistory(
|
|
298
|
-
conversationId: string,
|
|
299
|
-
excludeMessageId: string,
|
|
300
|
-
limit: number = 20
|
|
301
|
-
): Promise<HistoryEntry[]> {
|
|
302
|
-
try {
|
|
303
|
-
const rows = await callMcpHandler<Array<Record<string, unknown>>>(
|
|
304
|
-
"conversation.get_history",
|
|
305
|
-
{
|
|
306
|
-
conversation_id: conversationId,
|
|
307
|
-
exclude_message_id: excludeMessageId,
|
|
308
|
-
limit,
|
|
309
|
-
},
|
|
310
|
-
);
|
|
311
|
-
|
|
312
|
-
return (rows || [])
|
|
313
|
-
.reverse() // chronological order (oldest first)
|
|
314
|
-
.map((row) => {
|
|
315
|
-
const prompt =
|
|
316
|
-
((row.metadata as Record<string, unknown>)?.prompt as string) || "";
|
|
317
|
-
const content = (row.content as string) || "";
|
|
318
|
-
const response =
|
|
319
|
-
row.status === "failed"
|
|
320
|
-
? `[Task failed] ${content}`
|
|
321
|
-
: content;
|
|
322
|
-
return { prompt, response };
|
|
323
|
-
})
|
|
324
|
-
.filter((entry) => entry.prompt && entry.response);
|
|
325
|
-
} catch (err) {
|
|
326
|
-
log.debug(`Failed to fetch conversation history: ${err instanceof Error ? err.message : err}`);
|
|
327
|
-
return [];
|
|
328
|
-
}
|
|
329
|
-
}
|
|
330
|
-
|
|
331
|
-
// ── Event Streaming ─────────────────────────────────────────────────
|
|
332
|
-
|
|
333
|
-
export type EventType =
|
|
334
|
-
| "text_delta"
|
|
335
|
-
| "tool_use_start"
|
|
336
|
-
| "tool_use_input"
|
|
337
|
-
| "tool_result"
|
|
338
|
-
| "thinking"
|
|
339
|
-
| "error"
|
|
340
|
-
| "status_change"
|
|
341
|
-
| "user_action_request";
|
|
342
|
-
|
|
343
|
-
let eventSequence = 0;
|
|
344
|
-
|
|
345
|
-
export function resetEventSequence() {
|
|
346
|
-
eventSequence = 0;
|
|
347
|
-
}
|
|
348
|
-
|
|
349
|
-
export async function emitEvent(
|
|
350
|
-
messageId: string,
|
|
351
|
-
eventType: EventType,
|
|
352
|
-
eventData: Record<string, unknown>
|
|
353
|
-
): Promise<void> {
|
|
354
|
-
eventSequence++;
|
|
355
|
-
try {
|
|
356
|
-
await callMcpHandler("event.emit", {
|
|
357
|
-
message_id: messageId,
|
|
358
|
-
event_type: eventType,
|
|
359
|
-
event_data: eventData,
|
|
360
|
-
seq: eventSequence,
|
|
361
|
-
});
|
|
362
|
-
} catch (err) {
|
|
363
|
-
log.warn(`Failed to emit event: ${err instanceof Error ? err.message : err}`);
|
|
364
|
-
}
|
|
365
|
-
}
|
|
366
|
-
|
|
367
|
-
// ── Action Request Helpers ──────────────────────────────────────────
|
|
368
|
-
|
|
369
|
-
export async function setActionRequest(
|
|
370
|
-
messageId: string,
|
|
371
|
-
actionData: Record<string, unknown>
|
|
372
|
-
): Promise<void> {
|
|
373
|
-
await callMcpHandler("action.set_request", {
|
|
374
|
-
message_id: messageId,
|
|
375
|
-
action_data: actionData,
|
|
376
|
-
});
|
|
377
|
-
}
|
|
378
6
|
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
7
|
+
// Types
|
|
8
|
+
export type {
|
|
9
|
+
AgentSession,
|
|
10
|
+
ConversationMessage,
|
|
11
|
+
AgentTask,
|
|
12
|
+
PendingJobRun,
|
|
13
|
+
HistoryEntry,
|
|
14
|
+
EventType,
|
|
15
|
+
} from "./types.js";
|
|
16
|
+
|
|
17
|
+
// Auth
|
|
18
|
+
export { loginWithToken, getCurrentUserId, logout } from "./auth.js";
|
|
19
|
+
|
|
20
|
+
// Session
|
|
21
|
+
export {
|
|
22
|
+
createSession,
|
|
23
|
+
updateHeartbeat,
|
|
24
|
+
endSession,
|
|
25
|
+
setSessionBusy,
|
|
26
|
+
cleanupStaleSessions,
|
|
27
|
+
getActiveSessions,
|
|
28
|
+
} from "./session.js";
|
|
29
|
+
|
|
30
|
+
// Task
|
|
31
|
+
export { createTask, pollAndClaimTask, claimTask, completeTask, failTask } from "./task.js";
|
|
32
|
+
|
|
33
|
+
// Conversation
|
|
34
|
+
export { getOrCreateCliConversation, getConversationHistory } from "./conversation.js";
|
|
35
|
+
|
|
36
|
+
// Event
|
|
37
|
+
export { TaskEventEmitter, resetEventSequence, emitEvent } from "./event.js";
|
|
38
|
+
|
|
39
|
+
// Action
|
|
40
|
+
export { setActionRequest, pollActionResponse } from "./action.js";
|
|
41
|
+
|
|
42
|
+
// Job polling
|
|
43
|
+
export { pollAndClaimJobRun } from "./job-poll.js";
|
package/src/db/task.ts
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { callMcpHandler } from "./api-client.js";
|
|
2
|
+
import { log } from "../utils/logger.js";
|
|
3
|
+
import type { ConversationMessage } from "./types.js";
|
|
4
|
+
|
|
5
|
+
export async function createTask(
|
|
6
|
+
conversationId: string,
|
|
7
|
+
sessionId: string,
|
|
8
|
+
prompt: string
|
|
9
|
+
): Promise<ConversationMessage> {
|
|
10
|
+
const data = await callMcpHandler<Record<string, unknown>>("task.create", {
|
|
11
|
+
conversation_id: conversationId,
|
|
12
|
+
session_id: sessionId,
|
|
13
|
+
prompt,
|
|
14
|
+
});
|
|
15
|
+
return { ...data, prompt } as ConversationMessage;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Atomically poll ONE pending task and claim it in a single call.
|
|
20
|
+
* Uses FOR UPDATE SKIP LOCKED — concurrent CLIs will never grab the same task.
|
|
21
|
+
* Returns null if no pending task exists.
|
|
22
|
+
*/
|
|
23
|
+
export async function pollAndClaimTask(sessionId: string): Promise<ConversationMessage | null> {
|
|
24
|
+
try {
|
|
25
|
+
const data = await callMcpHandler<Record<string, unknown> | null>("task.poll_and_claim", {
|
|
26
|
+
session_id: sessionId,
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
if (!data) return null;
|
|
30
|
+
|
|
31
|
+
return {
|
|
32
|
+
...data,
|
|
33
|
+
prompt: (data.metadata as Record<string, unknown>)?.prompt || data.content || "",
|
|
34
|
+
} as ConversationMessage;
|
|
35
|
+
} catch (err) {
|
|
36
|
+
log.warn(`Poll-and-claim failed: ${err instanceof Error ? err.message : err}`);
|
|
37
|
+
return null;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export async function claimTask(messageId: string): Promise<boolean> {
|
|
42
|
+
const data = await callMcpHandler<boolean>("task.claim", {
|
|
43
|
+
message_id: messageId,
|
|
44
|
+
});
|
|
45
|
+
return data;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export async function completeTask(
|
|
49
|
+
messageId: string,
|
|
50
|
+
resultSummary: string,
|
|
51
|
+
tokenUsage?: Record<string, number>
|
|
52
|
+
): Promise<void> {
|
|
53
|
+
await callMcpHandler("task.complete", {
|
|
54
|
+
message_id: messageId,
|
|
55
|
+
result: resultSummary,
|
|
56
|
+
token_usage: tokenUsage || null,
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export async function failTask(messageId: string, errorMessage: string): Promise<void> {
|
|
61
|
+
try {
|
|
62
|
+
await callMcpHandler("task.fail", {
|
|
63
|
+
message_id: messageId,
|
|
64
|
+
error: errorMessage,
|
|
65
|
+
});
|
|
66
|
+
} catch (err) {
|
|
67
|
+
log.error(`Failed to update task status: ${err instanceof Error ? err.message : err}`);
|
|
68
|
+
}
|
|
69
|
+
}
|
package/src/db/types.ts
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
// ── Shared Types ─────────────────────────────────────────────────────
|
|
2
|
+
|
|
3
|
+
export interface AgentSession {
|
|
4
|
+
id: string;
|
|
5
|
+
user_id: string;
|
|
6
|
+
session_name: string;
|
|
7
|
+
status: "online" | "offline" | "busy";
|
|
8
|
+
workspace_path: string | null;
|
|
9
|
+
agent_version: string | null;
|
|
10
|
+
started_at: string;
|
|
11
|
+
last_heartbeat_at: string;
|
|
12
|
+
ended_at: string | null;
|
|
13
|
+
metadata: Record<string, unknown>;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export interface ConversationMessage {
|
|
17
|
+
id: string;
|
|
18
|
+
conversation_id: string;
|
|
19
|
+
sender_id: string;
|
|
20
|
+
role: "user" | "assistant" | "system";
|
|
21
|
+
content: string;
|
|
22
|
+
status: "pending" | "running" | "completed" | "failed" | "cancelled" | null;
|
|
23
|
+
session_id: string | null;
|
|
24
|
+
tool_calls: Record<string, unknown> | null;
|
|
25
|
+
tool_results: Record<string, unknown> | null;
|
|
26
|
+
metadata: Record<string, unknown>;
|
|
27
|
+
created_at: string;
|
|
28
|
+
updated_at: string;
|
|
29
|
+
prompt: string;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export type AgentTask = ConversationMessage;
|
|
33
|
+
|
|
34
|
+
export interface PendingJobRun {
|
|
35
|
+
id: string;
|
|
36
|
+
job_id: string;
|
|
37
|
+
job_name: string;
|
|
38
|
+
trigger_type: string;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export interface HistoryEntry {
|
|
42
|
+
prompt: string;
|
|
43
|
+
response: string;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export type EventType =
|
|
47
|
+
| "text_delta"
|
|
48
|
+
| "tool_use_start"
|
|
49
|
+
| "tool_use_input"
|
|
50
|
+
| "tool_result"
|
|
51
|
+
| "thinking"
|
|
52
|
+
| "error"
|
|
53
|
+
| "status_change"
|
|
54
|
+
| "user_action_request";
|
package/src/index.ts
CHANGED
|
@@ -12,6 +12,7 @@ import { registerScheduleCommands } from "./commands/schedule.js";
|
|
|
12
12
|
import { registerMemoryCommands } from "./commands/memory.js";
|
|
13
13
|
import { registerSkillCommands } from "./commands/skill.js";
|
|
14
14
|
import { registerJobCommands } from "./commands/job.js";
|
|
15
|
+
import { registerCredentialCommands } from "./commands/credential.js";
|
|
15
16
|
|
|
16
17
|
loadEnv();
|
|
17
18
|
|
|
@@ -35,5 +36,6 @@ registerScheduleCommands(program); // schedule add/list/toggle/remove
|
|
|
35
36
|
registerMemoryCommands(program); // memory list/add/search/remove/clear
|
|
36
37
|
registerSkillCommands(program); // skill list/search/create/show/remove
|
|
37
38
|
registerJobCommands(program); // job list/status/schedule
|
|
39
|
+
registerCredentialCommands(program); // credential list/set/get/remove/clear
|
|
38
40
|
|
|
39
41
|
program.parse();
|