@jungjaehoon/mama-os 0.8.3 → 0.9.0
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/CHANGELOG.md +10 -0
- package/dist/agent/agent-loop.d.ts +1 -8
- package/dist/agent/agent-loop.d.ts.map +1 -1
- package/dist/agent/agent-loop.js +44 -159
- package/dist/agent/agent-loop.js.map +1 -1
- package/dist/agent/claude-cli-wrapper.d.ts +6 -0
- package/dist/agent/claude-cli-wrapper.d.ts.map +1 -1
- package/dist/agent/claude-cli-wrapper.js +6 -0
- package/dist/agent/claude-cli-wrapper.js.map +1 -1
- package/dist/agent/codex-mcp-process.d.ts +85 -0
- package/dist/agent/codex-mcp-process.d.ts.map +1 -0
- package/dist/agent/codex-mcp-process.js +357 -0
- package/dist/agent/codex-mcp-process.js.map +1 -0
- package/dist/agent/session-pool.d.ts +17 -2
- package/dist/agent/session-pool.d.ts.map +1 -1
- package/dist/agent/session-pool.js +51 -26
- package/dist/agent/session-pool.js.map +1 -1
- package/dist/agent/types.d.ts +9 -24
- package/dist/agent/types.d.ts.map +1 -1
- package/dist/agent/types.js.map +1 -1
- package/dist/api/graph-api.d.ts.map +1 -1
- package/dist/api/graph-api.js +133 -45
- package/dist/api/graph-api.js.map +1 -1
- package/dist/cli/commands/init.d.ts +1 -1
- package/dist/cli/commands/init.d.ts.map +1 -1
- package/dist/cli/commands/init.js +14 -25
- package/dist/cli/commands/init.js.map +1 -1
- package/dist/cli/commands/run.d.ts.map +1 -1
- package/dist/cli/commands/run.js +3 -10
- package/dist/cli/commands/run.js.map +1 -1
- package/dist/cli/commands/start.d.ts.map +1 -1
- package/dist/cli/commands/start.js +143 -54
- package/dist/cli/commands/start.js.map +1 -1
- package/dist/cli/commands/status.d.ts.map +1 -1
- package/dist/cli/commands/status.js +2 -7
- package/dist/cli/commands/status.js.map +1 -1
- package/dist/cli/config/config-manager.d.ts.map +1 -1
- package/dist/cli/config/config-manager.js +9 -17
- package/dist/cli/config/config-manager.js.map +1 -1
- package/dist/cli/config/types.d.ts +19 -25
- package/dist/cli/config/types.d.ts.map +1 -1
- package/dist/cli/config/types.js.map +1 -1
- package/dist/cli/index.js +2 -2
- package/dist/cli/index.js.map +1 -1
- package/dist/gateways/context-injector.d.ts.map +1 -1
- package/dist/gateways/context-injector.js +6 -3
- package/dist/gateways/context-injector.js.map +1 -1
- package/dist/gateways/discord.d.ts +4 -0
- package/dist/gateways/discord.d.ts.map +1 -1
- package/dist/gateways/discord.js +39 -16
- package/dist/gateways/discord.js.map +1 -1
- package/dist/gateways/message-router.d.ts +6 -1
- package/dist/gateways/message-router.d.ts.map +1 -1
- package/dist/gateways/message-router.js +92 -7
- package/dist/gateways/message-router.js.map +1 -1
- package/dist/multi-agent/agent-process-manager.d.ts.map +1 -1
- package/dist/multi-agent/agent-process-manager.js +36 -9
- package/dist/multi-agent/agent-process-manager.js.map +1 -1
- package/dist/multi-agent/runtime-process.d.ts +4 -4
- package/dist/multi-agent/runtime-process.d.ts.map +1 -1
- package/dist/multi-agent/runtime-process.js +9 -20
- package/dist/multi-agent/runtime-process.js.map +1 -1
- package/dist/multi-agent/types.d.ts +13 -8
- package/dist/multi-agent/types.d.ts.map +1 -1
- package/dist/multi-agent/types.js.map +1 -1
- package/dist/setup/setup-prompt.d.ts +1 -1
- package/dist/setup/setup-prompt.d.ts.map +1 -1
- package/dist/setup/setup-prompt.js +19 -0
- package/dist/setup/setup-prompt.js.map +1 -1
- package/dist/setup/setup-server.d.ts.map +1 -1
- package/dist/setup/setup-server.js +39 -16
- package/dist/setup/setup-server.js.map +1 -1
- package/dist/skills/skill-registry.d.ts.map +1 -1
- package/dist/skills/skill-registry.js +5 -2
- package/dist/skills/skill-registry.js.map +1 -1
- package/package.json +5 -3
- package/public/setup.html +12 -1
- package/public/viewer/js/modules/chat.js +1760 -1976
- package/public/viewer/js/modules/dashboard.js +613 -695
- package/public/viewer/js/modules/graph.js +857 -970
- package/public/viewer/js/modules/memory.js +357 -312
- package/public/viewer/js/modules/settings.js +1009 -1026
- package/public/viewer/js/modules/skills.js +336 -355
- package/public/viewer/js/utils/api.js +255 -255
- package/public/viewer/js/utils/debug-logger.js +20 -26
- package/public/viewer/js/utils/dom.js +73 -60
- package/public/viewer/js/utils/format.js +182 -228
- package/public/viewer/js/utils/markdown.js +40 -0
- package/public/viewer/src/modules/chat.ts +2258 -0
- package/public/viewer/src/modules/dashboard.ts +1052 -0
- package/public/viewer/src/modules/graph.ts +1080 -0
- package/public/viewer/src/modules/memory.ts +453 -0
- package/public/viewer/src/modules/settings.ts +1398 -0
- package/public/viewer/src/modules/skills.ts +457 -0
- package/public/viewer/src/types/global.d.ts +168 -0
- package/public/viewer/src/utils/api.ts +650 -0
- package/public/viewer/src/utils/debug-logger.ts +36 -0
- package/public/viewer/src/utils/dom.ts +138 -0
- package/public/viewer/src/utils/format.ts +331 -0
- package/public/viewer/src/utils/markdown.ts +46 -0
- package/public/viewer/tsconfig.viewer.json +18 -0
- package/public/viewer/viewer.html +214 -311
- package/dist/agent/codex-cli-wrapper.d.ts +0 -85
- package/dist/agent/codex-cli-wrapper.d.ts.map +0 -1
- package/dist/agent/codex-cli-wrapper.js +0 -295
- package/dist/agent/codex-cli-wrapper.js.map +0 -1
|
@@ -0,0 +1,650 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* API Utility Functions
|
|
3
|
+
* @module utils/api
|
|
4
|
+
* @version 1.0.0
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
/* eslint-env browser */
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* API client for MAMA viewer
|
|
11
|
+
*/
|
|
12
|
+
export type QueryValue = string | number | boolean | null | undefined;
|
|
13
|
+
export type QueryParams = Record<string, QueryValue>;
|
|
14
|
+
export type ApiErrorPayload = { message?: string; error?: string };
|
|
15
|
+
export type JsonRecord = Record<string, unknown>;
|
|
16
|
+
|
|
17
|
+
export interface GraphNode {
|
|
18
|
+
id: string | number;
|
|
19
|
+
topic?: string;
|
|
20
|
+
outcome?: string;
|
|
21
|
+
[key: string]: unknown;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export interface GraphEdge {
|
|
25
|
+
from: string | number;
|
|
26
|
+
to: string | number;
|
|
27
|
+
relationship?: string;
|
|
28
|
+
[key: string]: unknown;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export interface GraphResponse {
|
|
32
|
+
nodes: GraphNode[];
|
|
33
|
+
edges: GraphEdge[];
|
|
34
|
+
meta?: JsonRecord;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export interface SimilarDecision {
|
|
38
|
+
id?: string | number;
|
|
39
|
+
topic?: string;
|
|
40
|
+
decision?: string;
|
|
41
|
+
reasoning?: string;
|
|
42
|
+
relationship?: string;
|
|
43
|
+
similarity?: number;
|
|
44
|
+
[key: string]: unknown;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export interface SimilarDecisionsResponse {
|
|
48
|
+
similar: SimilarDecision[];
|
|
49
|
+
[key: string]: unknown;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export type GraphSimilarResponse = GraphResponse & SimilarDecisionsResponse;
|
|
53
|
+
|
|
54
|
+
export interface CheckpointSummary {
|
|
55
|
+
id?: string;
|
|
56
|
+
timestamp?: string;
|
|
57
|
+
summary?: string;
|
|
58
|
+
[key: string]: unknown;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export interface CheckpointListResponse {
|
|
62
|
+
checkpoints: CheckpointSummary[];
|
|
63
|
+
[key: string]: unknown;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export interface MemorySearchItem {
|
|
67
|
+
id?: string;
|
|
68
|
+
topic?: string;
|
|
69
|
+
decision?: string;
|
|
70
|
+
reasoning?: string;
|
|
71
|
+
outcome?: string;
|
|
72
|
+
similarity?: number;
|
|
73
|
+
created_at?: string;
|
|
74
|
+
[key: string]: unknown;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
export interface MemorySearchResponse {
|
|
78
|
+
results: MemorySearchItem[];
|
|
79
|
+
[key: string]: unknown;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
export interface MamaDecisionPayload {
|
|
83
|
+
topic: string;
|
|
84
|
+
decision: string;
|
|
85
|
+
reasoning?: string;
|
|
86
|
+
confidence?: number;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
export interface ApiConfigResponse {
|
|
90
|
+
discord?: ApiGatewayConfig;
|
|
91
|
+
slack?: ApiGatewayConfig;
|
|
92
|
+
telegram?: ApiGatewayConfig;
|
|
93
|
+
chatwork?: ApiGatewayConfig;
|
|
94
|
+
heartbeat?: ApiHeartbeatConfig;
|
|
95
|
+
agent?: ApiAgentConfig;
|
|
96
|
+
roles?: ApiRolesConfig;
|
|
97
|
+
token_budget?: ApiTokenBudgetConfig;
|
|
98
|
+
[key: string]: unknown;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
export interface ApiGatewayConfig {
|
|
102
|
+
enabled?: boolean;
|
|
103
|
+
token?: string;
|
|
104
|
+
default_channel_id?: string;
|
|
105
|
+
bot_token?: string;
|
|
106
|
+
app_token?: string;
|
|
107
|
+
api_token?: string;
|
|
108
|
+
[key: string]: unknown;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
export interface ApiHeartbeatConfig {
|
|
112
|
+
enabled?: boolean;
|
|
113
|
+
interval?: number;
|
|
114
|
+
quiet_start?: number;
|
|
115
|
+
quiet_end?: number;
|
|
116
|
+
quietStart?: number;
|
|
117
|
+
quietEnd?: number;
|
|
118
|
+
[key: string]: unknown;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
export interface ApiAgentToolsConfig {
|
|
122
|
+
gateway?: string[];
|
|
123
|
+
mcp?: string[];
|
|
124
|
+
[key: string]: unknown;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
export type EffortLevel = 'low' | 'medium' | 'high';
|
|
128
|
+
|
|
129
|
+
export interface ApiAgentConfig {
|
|
130
|
+
backend?: 'claude' | 'codex-mcp';
|
|
131
|
+
model?: string;
|
|
132
|
+
effort?: EffortLevel;
|
|
133
|
+
tools?: ApiAgentToolsConfig;
|
|
134
|
+
use_persistent_cli?: boolean;
|
|
135
|
+
max_turns?: number;
|
|
136
|
+
timeout?: number;
|
|
137
|
+
[key: string]: unknown;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
export interface ApiRoleDefinition {
|
|
141
|
+
allowedTools?: string[];
|
|
142
|
+
blockedTools?: string[];
|
|
143
|
+
systemControl?: boolean;
|
|
144
|
+
sensitiveAccess?: boolean;
|
|
145
|
+
model?: string;
|
|
146
|
+
maxTurns?: number;
|
|
147
|
+
[key: string]: unknown;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
export interface ApiRolesConfig {
|
|
151
|
+
definitions?: Record<string, ApiRoleDefinition>;
|
|
152
|
+
sourceMapping?: Record<string, string>;
|
|
153
|
+
[key: string]: unknown;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
export interface ApiTokenBudgetConfig {
|
|
157
|
+
daily_limit?: number;
|
|
158
|
+
alert_threshold?: number;
|
|
159
|
+
[key: string]: unknown;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
export interface McpServer {
|
|
163
|
+
name?: string;
|
|
164
|
+
type?: string;
|
|
165
|
+
url?: string;
|
|
166
|
+
hasUrl?: boolean;
|
|
167
|
+
command?: string;
|
|
168
|
+
hasCommand?: boolean;
|
|
169
|
+
hasArgs?: boolean;
|
|
170
|
+
argCount?: number;
|
|
171
|
+
enabled?: boolean;
|
|
172
|
+
[key: string]: unknown;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
export interface McpServersResponse {
|
|
176
|
+
servers: McpServer[];
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
export interface MultiAgentAgent {
|
|
180
|
+
id?: string;
|
|
181
|
+
enabled?: boolean;
|
|
182
|
+
name?: string;
|
|
183
|
+
display_name?: string;
|
|
184
|
+
tier?: number;
|
|
185
|
+
status?: string;
|
|
186
|
+
model?: string;
|
|
187
|
+
backend?: 'claude' | 'codex-mcp';
|
|
188
|
+
bot_token?: string;
|
|
189
|
+
slack_bot_token?: string | null;
|
|
190
|
+
slack_app_token?: string | null;
|
|
191
|
+
lastActivity?: number | string;
|
|
192
|
+
last_activity?: number | string;
|
|
193
|
+
max_turns?: number;
|
|
194
|
+
timeout?: number;
|
|
195
|
+
use_persistent_cli?: boolean;
|
|
196
|
+
persona_file?: string | null;
|
|
197
|
+
trigger_prefix?: string | null;
|
|
198
|
+
can_delegate?: boolean;
|
|
199
|
+
cooldown_ms?: number;
|
|
200
|
+
outcome?: string;
|
|
201
|
+
tools?: {
|
|
202
|
+
gateway?: string[];
|
|
203
|
+
mcp?: string[];
|
|
204
|
+
mcp_config?: string;
|
|
205
|
+
};
|
|
206
|
+
auto_respond_keywords?: string[];
|
|
207
|
+
tool_permissions?: {
|
|
208
|
+
allowed?: string[];
|
|
209
|
+
blocked?: string[];
|
|
210
|
+
};
|
|
211
|
+
[key: string]: unknown;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
export interface MultiAgentAgentsResponse {
|
|
215
|
+
enabled?: boolean;
|
|
216
|
+
agents: MultiAgentAgent[];
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
export interface MultiAgentDashboardStatus {
|
|
220
|
+
enabled: boolean;
|
|
221
|
+
agents: MultiAgentAgent[];
|
|
222
|
+
recentDelegations?: {
|
|
223
|
+
id?: string;
|
|
224
|
+
description?: string;
|
|
225
|
+
category?: string;
|
|
226
|
+
wave?: number;
|
|
227
|
+
status?: string;
|
|
228
|
+
claimedBy?: string | null;
|
|
229
|
+
claimedAt?: number | null;
|
|
230
|
+
completedAt?: number | null;
|
|
231
|
+
}[];
|
|
232
|
+
activeChains?: number;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
export interface SkillItem {
|
|
236
|
+
id: string;
|
|
237
|
+
source: string;
|
|
238
|
+
name: string;
|
|
239
|
+
description?: string;
|
|
240
|
+
enabled?: boolean;
|
|
241
|
+
[key: string]: unknown;
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
export interface SkillsResponse {
|
|
245
|
+
skills: SkillItem[];
|
|
246
|
+
[key: string]: unknown;
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
export interface TokenSummaryPeriod {
|
|
250
|
+
input_tokens?: number;
|
|
251
|
+
output_tokens?: number;
|
|
252
|
+
cache_read_tokens?: number;
|
|
253
|
+
cost_usd?: number;
|
|
254
|
+
request_count?: number;
|
|
255
|
+
[key: string]: unknown;
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
export interface TokenSummaryResponse {
|
|
259
|
+
today?: TokenSummaryPeriod;
|
|
260
|
+
week?: TokenSummaryPeriod;
|
|
261
|
+
month?: TokenSummaryPeriod;
|
|
262
|
+
[key: string]: unknown;
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
export interface TokenByAgentRecord {
|
|
266
|
+
agent_id?: string;
|
|
267
|
+
agent_name?: string;
|
|
268
|
+
input_tokens?: number;
|
|
269
|
+
output_tokens?: number;
|
|
270
|
+
cache_read_tokens?: number;
|
|
271
|
+
cost_usd?: number;
|
|
272
|
+
request_count?: number;
|
|
273
|
+
[key: string]: unknown;
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
export interface TokensByAgentResponse {
|
|
277
|
+
agents: TokenByAgentRecord[];
|
|
278
|
+
[key: string]: unknown;
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
export interface CronJob {
|
|
282
|
+
id: string;
|
|
283
|
+
name: string;
|
|
284
|
+
schedule?: string;
|
|
285
|
+
cronExpr?: string;
|
|
286
|
+
prompt?: string;
|
|
287
|
+
enabled?: boolean;
|
|
288
|
+
nextRun?: string;
|
|
289
|
+
[key: string]: unknown;
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
export interface CronJobsResponse {
|
|
293
|
+
jobs: CronJob[];
|
|
294
|
+
[key: string]: unknown;
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
export interface SessionInfo {
|
|
298
|
+
id: string;
|
|
299
|
+
isAlive?: boolean;
|
|
300
|
+
[key: string]: unknown;
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
export interface SessionsResponse {
|
|
304
|
+
sessions: SessionInfo[];
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
export type LastActiveSessionResponse = SessionInfo;
|
|
308
|
+
|
|
309
|
+
export interface CreateSessionResponse {
|
|
310
|
+
sessionId: string;
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
export interface CronLogEntry {
|
|
314
|
+
ts?: string;
|
|
315
|
+
message?: string;
|
|
316
|
+
[key: string]: unknown;
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
export interface CronLogResponse {
|
|
320
|
+
logs: CronLogEntry[];
|
|
321
|
+
[key: string]: unknown;
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
export class API {
|
|
325
|
+
/**
|
|
326
|
+
* Base URL for API requests (empty for same origin)
|
|
327
|
+
*/
|
|
328
|
+
static baseUrl: string = '';
|
|
329
|
+
|
|
330
|
+
/**
|
|
331
|
+
* Parse JSON response safely with explicit error context.
|
|
332
|
+
*/
|
|
333
|
+
static async parseJsonResponse<T = unknown>(response: Response, context = '요청'): Promise<T> {
|
|
334
|
+
const contentType = response.headers.get('content-type') || '';
|
|
335
|
+
const text = await response.text();
|
|
336
|
+
|
|
337
|
+
if (!contentType.includes('application/json')) {
|
|
338
|
+
const snippet = text.slice(0, 80).replace(/\n/g, ' ');
|
|
339
|
+
throw new Error(
|
|
340
|
+
`${context}에서 JSON 응답이 아닙니다. content-type: ${
|
|
341
|
+
contentType || '없음'
|
|
342
|
+
}, body: ${snippet}`
|
|
343
|
+
);
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
try {
|
|
347
|
+
if (!text) {
|
|
348
|
+
throw new Error(
|
|
349
|
+
`${context} 응답 본문이 비어 있습니다. status=${response.status}, url=${response.url}`
|
|
350
|
+
);
|
|
351
|
+
}
|
|
352
|
+
return JSON.parse(text) as T;
|
|
353
|
+
} catch (error) {
|
|
354
|
+
const snippet = text.slice(0, 120).replace(/\n/g, ' ');
|
|
355
|
+
const cause = error instanceof Error ? error.message : String(error);
|
|
356
|
+
throw new Error(`${context} 응답 JSON 파싱 실패: ${cause} (샘플: ${snippet})`);
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
/**
|
|
361
|
+
* Perform GET request
|
|
362
|
+
*/
|
|
363
|
+
static async get<T = unknown>(endpoint: string, params: QueryParams | null = null): Promise<T> {
|
|
364
|
+
const url = new URL(endpoint, window.location.origin);
|
|
365
|
+
if (params) {
|
|
366
|
+
Object.entries(params).forEach(([key, value]) => {
|
|
367
|
+
if (value !== null && value !== undefined) {
|
|
368
|
+
url.searchParams.set(key, String(value));
|
|
369
|
+
}
|
|
370
|
+
});
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
const response = await fetch(url);
|
|
374
|
+
if (!response.ok) {
|
|
375
|
+
let errorMessage = `HTTP ${response.status}`;
|
|
376
|
+
try {
|
|
377
|
+
const errorData = await this.parseJsonResponse<ApiErrorPayload>(
|
|
378
|
+
response,
|
|
379
|
+
`GET ${endpoint}`
|
|
380
|
+
);
|
|
381
|
+
errorMessage = errorData.message || errorData.error || errorMessage;
|
|
382
|
+
} catch (parseError: unknown) {
|
|
383
|
+
errorMessage = parseError instanceof Error ? parseError.message : String(parseError);
|
|
384
|
+
}
|
|
385
|
+
throw new Error(errorMessage);
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
return this.parseJsonResponse(response, `GET ${endpoint}`);
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
/**
|
|
392
|
+
* Perform POST request
|
|
393
|
+
* @param {string} endpoint - API endpoint
|
|
394
|
+
* @param {Object} body - Request body
|
|
395
|
+
* @returns {Promise<Object>} Response data
|
|
396
|
+
*/
|
|
397
|
+
static async post<T = unknown, B = unknown>(endpoint: string, body: B): Promise<T> {
|
|
398
|
+
const response = await fetch(endpoint, {
|
|
399
|
+
method: 'POST',
|
|
400
|
+
headers: { 'Content-Type': 'application/json' },
|
|
401
|
+
body: JSON.stringify(body),
|
|
402
|
+
});
|
|
403
|
+
|
|
404
|
+
if (!response.ok) {
|
|
405
|
+
let errorMessage = `HTTP ${response.status}`;
|
|
406
|
+
try {
|
|
407
|
+
const errorData = await this.parseJsonResponse<ApiErrorPayload>(
|
|
408
|
+
response,
|
|
409
|
+
`POST ${endpoint}`
|
|
410
|
+
);
|
|
411
|
+
errorMessage = errorData.message || errorData.error || errorMessage;
|
|
412
|
+
} catch (parseError: unknown) {
|
|
413
|
+
errorMessage = parseError instanceof Error ? parseError.message : String(parseError);
|
|
414
|
+
}
|
|
415
|
+
throw new Error(errorMessage);
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
return this.parseJsonResponse(response, `POST ${endpoint}`);
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
/**
|
|
422
|
+
* Perform PUT request
|
|
423
|
+
*/
|
|
424
|
+
static async put<T = unknown, B = unknown>(endpoint: string, body: B): Promise<T> {
|
|
425
|
+
const response = await fetch(endpoint, {
|
|
426
|
+
method: 'PUT',
|
|
427
|
+
headers: { 'Content-Type': 'application/json' },
|
|
428
|
+
body: JSON.stringify(body),
|
|
429
|
+
});
|
|
430
|
+
if (!response.ok) {
|
|
431
|
+
let errorMessage = `HTTP ${response.status}`;
|
|
432
|
+
try {
|
|
433
|
+
const errorData = await this.parseJsonResponse<ApiErrorPayload>(
|
|
434
|
+
response,
|
|
435
|
+
`PUT ${endpoint}`
|
|
436
|
+
);
|
|
437
|
+
errorMessage = errorData.message || errorData.error || errorMessage;
|
|
438
|
+
} catch (parseError: unknown) {
|
|
439
|
+
errorMessage = parseError instanceof Error ? parseError.message : String(parseError);
|
|
440
|
+
}
|
|
441
|
+
throw new Error(errorMessage);
|
|
442
|
+
}
|
|
443
|
+
return this.parseJsonResponse(response, `PUT ${endpoint}`);
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
/**
|
|
447
|
+
* Perform DELETE request
|
|
448
|
+
*/
|
|
449
|
+
static async del<T = unknown>(endpoint: string): Promise<T> {
|
|
450
|
+
const response = await fetch(endpoint, { method: 'DELETE' });
|
|
451
|
+
if (!response.ok) {
|
|
452
|
+
let errorMessage = `HTTP ${response.status}`;
|
|
453
|
+
try {
|
|
454
|
+
const errorData = await this.parseJsonResponse<ApiErrorPayload>(
|
|
455
|
+
response,
|
|
456
|
+
`DELETE ${endpoint}`
|
|
457
|
+
);
|
|
458
|
+
errorMessage = errorData.message || errorData.error || errorMessage;
|
|
459
|
+
} catch (parseError: unknown) {
|
|
460
|
+
errorMessage = parseError instanceof Error ? parseError.message : String(parseError);
|
|
461
|
+
}
|
|
462
|
+
throw new Error(errorMessage);
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
return this.parseJsonResponse(response, `DELETE ${endpoint}`);
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
// =============================================
|
|
469
|
+
// Graph API
|
|
470
|
+
// =============================================
|
|
471
|
+
|
|
472
|
+
/**
|
|
473
|
+
* Get graph data
|
|
474
|
+
* @param {Object} params - Query parameters
|
|
475
|
+
* @returns {Promise<Object>} Graph data
|
|
476
|
+
*/
|
|
477
|
+
static async getGraph(params: QueryParams = {}): Promise<GraphResponse> {
|
|
478
|
+
// cluster: false by default to avoid slow embedding calculations
|
|
479
|
+
return this.get<GraphResponse>('/graph', { cluster: 'false', ...params });
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
/**
|
|
483
|
+
* Get similar decisions for a node
|
|
484
|
+
* @param {string} nodeId - Node ID
|
|
485
|
+
* @returns {Promise<Object>} Similar decisions
|
|
486
|
+
*/
|
|
487
|
+
static async getSimilarDecisions(nodeId: string): Promise<GraphSimilarResponse> {
|
|
488
|
+
return this.get<GraphSimilarResponse>('/graph/similar', { id: nodeId });
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
/**
|
|
492
|
+
* Update decision outcome
|
|
493
|
+
* @param {string} id - Decision ID
|
|
494
|
+
* @param {string} outcome - Outcome value
|
|
495
|
+
* @param {string} reason - Optional reason
|
|
496
|
+
* @returns {Promise<Object>} Update result
|
|
497
|
+
*/
|
|
498
|
+
static async updateOutcome(
|
|
499
|
+
id: string,
|
|
500
|
+
outcome: string,
|
|
501
|
+
reason: string | null = null
|
|
502
|
+
): Promise<JsonRecord> {
|
|
503
|
+
return this.post<JsonRecord, { id: string; outcome: string; reason: string | null }>(
|
|
504
|
+
'/graph/update',
|
|
505
|
+
{ id, outcome, reason }
|
|
506
|
+
);
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
// =============================================
|
|
510
|
+
// Checkpoint API
|
|
511
|
+
// =============================================
|
|
512
|
+
|
|
513
|
+
/**
|
|
514
|
+
* Get all checkpoints
|
|
515
|
+
* @returns {Promise<Object>} Checkpoints data
|
|
516
|
+
*/
|
|
517
|
+
static async getCheckpoints(): Promise<CheckpointListResponse> {
|
|
518
|
+
return this.get<CheckpointListResponse>('/checkpoints');
|
|
519
|
+
}
|
|
520
|
+
|
|
521
|
+
// =============================================
|
|
522
|
+
// MAMA Memory API
|
|
523
|
+
// =============================================
|
|
524
|
+
|
|
525
|
+
/**
|
|
526
|
+
* Search MAMA decisions
|
|
527
|
+
* @param {string} query - Search query
|
|
528
|
+
* @param {number} limit - Maximum results
|
|
529
|
+
* @returns {Promise<Object>} Search results
|
|
530
|
+
*/
|
|
531
|
+
static async searchMemory(query: string, limit = 10): Promise<MemorySearchResponse> {
|
|
532
|
+
return this.get<MemorySearchResponse>('/api/mama/search', { q: query, limit });
|
|
533
|
+
}
|
|
534
|
+
|
|
535
|
+
/**
|
|
536
|
+
* Save a new decision to MAMA
|
|
537
|
+
* @param {Object} data - Decision data
|
|
538
|
+
* @param {string} data.topic - Decision topic
|
|
539
|
+
* @param {string} data.decision - Decision text
|
|
540
|
+
* @param {string} data.reasoning - Reasoning text
|
|
541
|
+
* @param {number} data.confidence - Confidence (0-1)
|
|
542
|
+
* @returns {Promise<Object>} Save result
|
|
543
|
+
*/
|
|
544
|
+
static async saveDecision(data: MamaDecisionPayload): Promise<JsonRecord> {
|
|
545
|
+
return this.post<JsonRecord, MamaDecisionPayload>('/api/mama/save', data);
|
|
546
|
+
}
|
|
547
|
+
|
|
548
|
+
// =============================================
|
|
549
|
+
// Session API
|
|
550
|
+
// =============================================
|
|
551
|
+
|
|
552
|
+
/**
|
|
553
|
+
* Create a new chat session
|
|
554
|
+
* @param {string} projectDir - Project directory
|
|
555
|
+
* @returns {Promise<Object>} Session data
|
|
556
|
+
*/
|
|
557
|
+
static async createSession(projectDir = '.'): Promise<CreateSessionResponse> {
|
|
558
|
+
return this.post<CreateSessionResponse, { projectDir: string }>('/api/sessions', {
|
|
559
|
+
projectDir,
|
|
560
|
+
});
|
|
561
|
+
}
|
|
562
|
+
|
|
563
|
+
/**
|
|
564
|
+
* Get the last active session
|
|
565
|
+
* @returns {Promise<Object>} Last active session
|
|
566
|
+
*/
|
|
567
|
+
static async getLastActiveSession(): Promise<LastActiveSessionResponse> {
|
|
568
|
+
return this.get<LastActiveSessionResponse>('/api/sessions/last-active');
|
|
569
|
+
}
|
|
570
|
+
|
|
571
|
+
/**
|
|
572
|
+
* Get all active sessions
|
|
573
|
+
* @returns {Promise<Object>} Sessions list
|
|
574
|
+
*/
|
|
575
|
+
static async getSessions(): Promise<SessionsResponse> {
|
|
576
|
+
return this.get<SessionsResponse>('/api/sessions');
|
|
577
|
+
}
|
|
578
|
+
|
|
579
|
+
// =============================================
|
|
580
|
+
// Cron API
|
|
581
|
+
// =============================================
|
|
582
|
+
|
|
583
|
+
static async getCronJobs(): Promise<CronJobsResponse> {
|
|
584
|
+
return this.get<CronJobsResponse>('/api/cron');
|
|
585
|
+
}
|
|
586
|
+
|
|
587
|
+
static async updateCronJob(id: string, data: JsonRecord): Promise<JsonRecord> {
|
|
588
|
+
return this.put<JsonRecord, JsonRecord>(`/api/cron/${encodeURIComponent(id)}`, data);
|
|
589
|
+
}
|
|
590
|
+
|
|
591
|
+
static async runCronJob(id: string): Promise<JsonRecord> {
|
|
592
|
+
return this.post<JsonRecord, JsonRecord>(`/api/cron/${encodeURIComponent(id)}/run`, {});
|
|
593
|
+
}
|
|
594
|
+
|
|
595
|
+
static async getCronLogs(id: string, limit = 5): Promise<CronLogResponse> {
|
|
596
|
+
return this.get<CronLogResponse>(`/api/cron/${encodeURIComponent(id)}/logs`, { limit });
|
|
597
|
+
}
|
|
598
|
+
|
|
599
|
+
// =============================================
|
|
600
|
+
// Token API
|
|
601
|
+
// =============================================
|
|
602
|
+
|
|
603
|
+
static async getTokenSummary(): Promise<TokenSummaryResponse> {
|
|
604
|
+
return this.get<TokenSummaryResponse>('/api/tokens/summary');
|
|
605
|
+
}
|
|
606
|
+
|
|
607
|
+
static async getTokensByAgent(): Promise<TokensByAgentResponse> {
|
|
608
|
+
return this.get<TokensByAgentResponse>('/api/tokens/by-agent');
|
|
609
|
+
}
|
|
610
|
+
|
|
611
|
+
static async getTokensDaily(days = 30): Promise<JsonRecord> {
|
|
612
|
+
return this.get<JsonRecord>('/api/tokens/daily', { days });
|
|
613
|
+
}
|
|
614
|
+
|
|
615
|
+
// =============================================
|
|
616
|
+
// Skills API
|
|
617
|
+
// =============================================
|
|
618
|
+
|
|
619
|
+
static async getSkills(): Promise<SkillsResponse> {
|
|
620
|
+
return this.get<SkillsResponse>('/api/skills');
|
|
621
|
+
}
|
|
622
|
+
|
|
623
|
+
static async getSkillCatalog(source = 'all'): Promise<SkillsResponse> {
|
|
624
|
+
return this.get<SkillsResponse>('/api/skills/catalog', { source });
|
|
625
|
+
}
|
|
626
|
+
|
|
627
|
+
static async searchSkills(query: string, source = 'all'): Promise<SkillsResponse> {
|
|
628
|
+
return this.get<SkillsResponse>('/api/skills/search', { q: query, source });
|
|
629
|
+
}
|
|
630
|
+
|
|
631
|
+
static async installSkill(source: string, name: string): Promise<JsonRecord> {
|
|
632
|
+
return this.post('/api/skills/install', { source, name });
|
|
633
|
+
}
|
|
634
|
+
|
|
635
|
+
static async uninstallSkill(name: string, source = 'mama'): Promise<JsonRecord> {
|
|
636
|
+
return this.del(`/api/skills/${encodeURIComponent(name)}?source=${encodeURIComponent(source)}`);
|
|
637
|
+
}
|
|
638
|
+
|
|
639
|
+
static async toggleSkill(name: string, enabled: boolean, source = 'mama'): Promise<JsonRecord> {
|
|
640
|
+
return this.put(`/api/skills/${encodeURIComponent(name)}`, { enabled, source });
|
|
641
|
+
}
|
|
642
|
+
|
|
643
|
+
static async getSkillContent(name: string, source = 'mama'): Promise<JsonRecord> {
|
|
644
|
+
return this.get(`/api/skills/${encodeURIComponent(name)}/readme`, { source });
|
|
645
|
+
}
|
|
646
|
+
|
|
647
|
+
static async installSkillFromUrl(url: string): Promise<JsonRecord> {
|
|
648
|
+
return this.post('/api/skills/install-url', { url });
|
|
649
|
+
}
|
|
650
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/* eslint-env browser */
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Lightweight DebugLogger for viewer modules.
|
|
5
|
+
* Mirrors mama-core DebugLogger behavior (no console.log usage).
|
|
6
|
+
*/
|
|
7
|
+
export class DebugLogger {
|
|
8
|
+
context: string;
|
|
9
|
+
|
|
10
|
+
constructor(context = 'Viewer') {
|
|
11
|
+
this.context = String(context);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
private _format(level: string, args: unknown[]) {
|
|
15
|
+
const ts = new Date().toISOString();
|
|
16
|
+
return [`[${ts}] [${this.context}] [${level}]`, ...args];
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
debug(...args: unknown[]) {
|
|
20
|
+
console.debug(...this._format('DEBUG', args));
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
info(...args: unknown[]) {
|
|
24
|
+
console.info(...this._format('INFO', args));
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
warn(...args: unknown[]) {
|
|
28
|
+
console.warn(...this._format('WARN', args));
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
error(...args: unknown[]) {
|
|
32
|
+
console.error(...this._format('ERROR', args));
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export default DebugLogger;
|