@realseek/mmflow 0.1.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.
Files changed (46) hide show
  1. package/.claude/commands/mmf-analyze.md +49 -0
  2. package/.claude/commands/mmf-codex.md +51 -0
  3. package/.claude/commands/mmf-gemini.md +51 -0
  4. package/.claude/commands/mmf-review.md +53 -0
  5. package/.claude/commands/mmf-workflow.md +104 -0
  6. package/.claude/skills/codex-task/SKILL.md +59 -0
  7. package/.claude/skills/gemini-task/SKILL.md +59 -0
  8. package/.claude/skills/multi-model-task/SKILL.md +94 -0
  9. package/CLAUDE.md +60 -0
  10. package/dist/cli.d.ts +3 -0
  11. package/dist/cli.d.ts.map +1 -0
  12. package/dist/cli.js +183 -0
  13. package/dist/cli.js.map +1 -0
  14. package/dist/client.d.ts +4 -0
  15. package/dist/client.d.ts.map +1 -0
  16. package/dist/client.js +20 -0
  17. package/dist/client.js.map +1 -0
  18. package/dist/completion.d.ts +15 -0
  19. package/dist/completion.d.ts.map +1 -0
  20. package/dist/completion.js +86 -0
  21. package/dist/completion.js.map +1 -0
  22. package/dist/config.d.ts +5 -0
  23. package/dist/config.d.ts.map +1 -0
  24. package/dist/config.js +64 -0
  25. package/dist/config.js.map +1 -0
  26. package/dist/errors.d.ts +3 -0
  27. package/dist/errors.d.ts.map +1 -0
  28. package/dist/errors.js +35 -0
  29. package/dist/errors.js.map +1 -0
  30. package/dist/index.d.ts +3 -0
  31. package/dist/index.d.ts.map +1 -0
  32. package/dist/index.js +187 -0
  33. package/dist/index.js.map +1 -0
  34. package/dist/session.d.ts +18 -0
  35. package/dist/session.d.ts.map +1 -0
  36. package/dist/session.js +67 -0
  37. package/dist/session.js.map +1 -0
  38. package/dist/task.d.ts +19 -0
  39. package/dist/task.d.ts.map +1 -0
  40. package/dist/task.js +138 -0
  41. package/dist/task.js.map +1 -0
  42. package/dist/types.d.ts +86 -0
  43. package/dist/types.d.ts.map +1 -0
  44. package/dist/types.js +2 -0
  45. package/dist/types.js.map +1 -0
  46. package/package.json +48 -0
package/dist/index.js ADDED
@@ -0,0 +1,187 @@
1
+ #!/usr/bin/env node
2
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
3
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
4
+ import { z } from "zod";
5
+ import { resolveModelRoute, routeByDomain, MODEL_ROUTES } from "./config.js";
6
+ import { getClient } from "./client.js";
7
+ import { OpenAICompletionProvider, formatUsageLine } from "./completion.js";
8
+ import { mapErrorToResponse } from "./errors.js";
9
+ import { SessionStore } from "./session.js";
10
+ import { TaskStore, launchTask, formatTaskStatus, formatTaskResult } from "./task.js";
11
+ const sessionStore = new SessionStore();
12
+ const taskStore = new TaskStore();
13
+ const text = (s) => ({ content: [{ type: "text", text: s }] });
14
+ function getProviderForModel(model) {
15
+ const route = resolveModelRoute(model);
16
+ const client = getClient(route);
17
+ return {
18
+ route,
19
+ provider: new OpenAICompletionProvider(client, { defaultTimeoutMs: route.defaultTimeout }),
20
+ };
21
+ }
22
+ /** Resolve model + system prompt from domain or explicit model */
23
+ function resolveModelAndPrompt(args) {
24
+ let model;
25
+ let systemPrompt = args.system_prompt;
26
+ let providerName;
27
+ if (args.domain) {
28
+ const decision = routeByDomain(args.domain);
29
+ model = args.model ?? decision.model;
30
+ if (!systemPrompt)
31
+ systemPrompt = decision.systemPrompt;
32
+ providerName = decision.provider;
33
+ }
34
+ else {
35
+ // No domain specified — use explicit model or default Codex model from env
36
+ const codexRoute = MODEL_ROUTES[MODEL_ROUTES.length - 1];
37
+ model = args.model ?? process.env[codexRoute.modelEnv] ?? codexRoute.defaultModel;
38
+ const route = resolveModelRoute(model);
39
+ providerName = route.provider;
40
+ }
41
+ return { model, systemPrompt, providerName };
42
+ }
43
+ // ============================================================
44
+ // MCP Server
45
+ // ============================================================
46
+ const server = new McpServer({ name: "mmf", version: "0.1.0" });
47
+ // ============================================================
48
+ // Tool 1: chat — synchronous single/multi-turn
49
+ // ============================================================
50
+ server.tool("chat", "Send a prompt to Codex (OpenAI) or Gemini. Supports session reuse for multi-turn conversations. " +
51
+ "Use `domain` for smart routing (frontend→Gemini, backend→Codex) or specify `model` directly. " +
52
+ "External models are READ-ONLY — they return analysis/diffs only.", {
53
+ prompt: z.string().min(1).describe("The prompt to send"),
54
+ system_prompt: z.string().optional().describe("System prompt (overrides domain default)"),
55
+ model: z.string().optional().describe("Model name (e.g. gpt-4o, gemini-2.5-pro). If omitted, uses domain routing."),
56
+ domain: z.enum(["frontend", "backend", "review", "general"]).optional().describe("Smart routing domain"),
57
+ session_id: z.string().optional().describe("Session ID for multi-turn conversation. Omit to start new."),
58
+ }, async (args) => {
59
+ try {
60
+ const { model, systemPrompt, providerName } = resolveModelAndPrompt(args);
61
+ const { route, provider } = getProviderForModel(model);
62
+ let messages;
63
+ let sessionId = args.session_id;
64
+ if (sessionId) {
65
+ // Resume existing session
66
+ const history = sessionStore.addUserMessage(sessionId, args.prompt);
67
+ if (!history)
68
+ return text(`Session not found: ${sessionId}`);
69
+ messages = history;
70
+ }
71
+ else {
72
+ // New session
73
+ sessionId = sessionStore.create(providerName, model, systemPrompt);
74
+ messages = sessionStore.addUserMessage(sessionId, args.prompt);
75
+ }
76
+ const result = await provider.complete({
77
+ model,
78
+ messages: messages,
79
+ });
80
+ sessionStore.addAssistantMessage(sessionId, result.content);
81
+ const usageLine = formatUsageLine(result);
82
+ return text(`[Session: ${sessionId} | Provider: ${providerName}]\n\n${result.content}${usageLine}`);
83
+ }
84
+ catch (error) {
85
+ const { providerName } = resolveModelAndPrompt(args);
86
+ return mapErrorToResponse(error, { serviceName: providerName, model: args.model });
87
+ }
88
+ });
89
+ // ============================================================
90
+ // Tool 2: task_submit — async long-running task
91
+ // ============================================================
92
+ server.tool("task_submit", "Submit a long-running task to Codex or Gemini. Returns immediately with a task ID. " +
93
+ "Use task_status to poll progress (shows partial streaming output). " +
94
+ "Use task_result to get the final result when completed.", {
95
+ prompt: z.string().min(1).describe("The prompt/goal for the task"),
96
+ system_prompt: z.string().optional().describe("System prompt (overrides domain default)"),
97
+ model: z.string().optional().describe("Model name"),
98
+ domain: z.enum(["frontend", "backend", "review", "general"]).optional().describe("Smart routing domain"),
99
+ session_id: z.string().optional().describe("Session ID for multi-turn context"),
100
+ }, async (args) => {
101
+ try {
102
+ const { model, systemPrompt, providerName } = resolveModelAndPrompt(args);
103
+ const { provider } = getProviderForModel(model);
104
+ let messages;
105
+ let sessionId = args.session_id;
106
+ if (sessionId) {
107
+ const history = sessionStore.addUserMessage(sessionId, args.prompt);
108
+ if (!history)
109
+ return text(`Session not found: ${sessionId}`);
110
+ messages = history;
111
+ }
112
+ else {
113
+ sessionId = sessionStore.create(providerName, model, systemPrompt);
114
+ messages = sessionStore.addUserMessage(sessionId, args.prompt);
115
+ }
116
+ const task = taskStore.create(args.prompt, providerName, model, sessionId);
117
+ launchTask(taskStore, sessionStore, provider, task, messages);
118
+ return text(`Task submitted.\n` +
119
+ `Task ID: ${task.taskId}\n` +
120
+ `Session: ${sessionId}\n` +
121
+ `Provider: ${providerName} | Model: ${model}\n\n` +
122
+ `Poll progress with task_status. Get result with task_result when completed.`);
123
+ }
124
+ catch (error) {
125
+ const { providerName } = resolveModelAndPrompt(args);
126
+ return mapErrorToResponse(error, { serviceName: providerName, model: args.model });
127
+ }
128
+ });
129
+ // ============================================================
130
+ // Tool 3: task_status — poll progress
131
+ // ============================================================
132
+ server.tool("task_status", "Check the progress of a running task. Returns status, elapsed time, and partial streaming output.", {
133
+ task_id: z.string().describe("The task ID returned by task_submit"),
134
+ }, async (args) => {
135
+ const task = taskStore.get(args.task_id);
136
+ if (!task)
137
+ return text(`Task not found: ${args.task_id}`);
138
+ return text(formatTaskStatus(task));
139
+ });
140
+ // ============================================================
141
+ // Tool 4: task_result — get completed result
142
+ // ============================================================
143
+ server.tool("task_result", "Get the full result of a completed task, including token usage.", {
144
+ task_id: z.string().describe("The task ID returned by task_submit"),
145
+ }, async (args) => {
146
+ const task = taskStore.get(args.task_id);
147
+ if (!task)
148
+ return text(`Task not found: ${args.task_id}`);
149
+ if (task.status === "running") {
150
+ return text(`Task is still running. Use task_status to check progress.\n\n${formatTaskStatus(task)}`);
151
+ }
152
+ if (task.status === "failed") {
153
+ return text(`Task failed: ${task.error ?? "unknown error"}`);
154
+ }
155
+ if (task.status === "cancelled") {
156
+ return text("Task was cancelled.");
157
+ }
158
+ return text(formatTaskResult(task));
159
+ });
160
+ // ============================================================
161
+ // Tool 5: task_cancel — cancel running task
162
+ // ============================================================
163
+ server.tool("task_cancel", "Cancel a running task.", {
164
+ task_id: z.string().describe("The task ID to cancel"),
165
+ }, async (args) => {
166
+ const cancelled = taskStore.cancel(args.task_id);
167
+ if (cancelled) {
168
+ return text(`Task ${args.task_id} cancelled.`);
169
+ }
170
+ const task = taskStore.get(args.task_id);
171
+ if (!task)
172
+ return text(`Task not found: ${args.task_id}`);
173
+ return text(`Task is already ${task.status}, cannot cancel.`);
174
+ });
175
+ // ============================================================
176
+ // Start Server
177
+ // ============================================================
178
+ async function main() {
179
+ const transport = new StdioServerTransport();
180
+ await server.connect(transport);
181
+ console.error("[mmf] Server started");
182
+ }
183
+ main().catch((err) => {
184
+ console.error("[mmf] Fatal error:", err);
185
+ process.exit(1);
186
+ });
187
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ import type { Session, SessionMessage } from "./types.js";
2
+ export declare class SessionStore {
3
+ private sessions;
4
+ create(provider: string, model: string, systemPrompt?: string): string;
5
+ get(id: string): Session | undefined;
6
+ addUserMessage(id: string, content: string): SessionMessage[] | undefined;
7
+ addAssistantMessage(id: string, content: string): void;
8
+ list(): Array<{
9
+ id: string;
10
+ provider: string;
11
+ model: string;
12
+ messageCount: number;
13
+ lastUsed: number;
14
+ }>;
15
+ private trimMessages;
16
+ private cleanup;
17
+ }
18
+ //# sourceMappingURL=session.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session.d.ts","sourceRoot":"","sources":["../src/session.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAK1D,qBAAa,YAAY;IACvB,OAAO,CAAC,QAAQ,CAA8B;IAE9C,MAAM,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,YAAY,CAAC,EAAE,MAAM,GAAG,MAAM;IAkBtE,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,GAAG,SAAS;IAIpC,cAAc,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,cAAc,EAAE,GAAG,SAAS;IASzE,mBAAmB,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI;IAOtD,IAAI,IAAI,KAAK,CAAC;QACZ,EAAE,EAAE,MAAM,CAAC;QACX,QAAQ,EAAE,MAAM,CAAC;QACjB,KAAK,EAAE,MAAM,CAAC;QACd,YAAY,EAAE,MAAM,CAAC;QACrB,QAAQ,EAAE,MAAM,CAAC;KAClB,CAAC;IAUF,OAAO,CAAC,YAAY;IAQpB,OAAO,CAAC,OAAO;CAQhB"}
@@ -0,0 +1,67 @@
1
+ const CLEANUP_MAX_AGE_MS = 60 * 60 * 1000; // 1 hour
2
+ const MAX_SESSION_MESSAGES = 50;
3
+ export class SessionStore {
4
+ sessions = new Map();
5
+ create(provider, model, systemPrompt) {
6
+ this.cleanup();
7
+ const id = `s_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`;
8
+ const messages = [];
9
+ if (systemPrompt) {
10
+ messages.push({ role: "system", content: systemPrompt });
11
+ }
12
+ this.sessions.set(id, {
13
+ id,
14
+ provider,
15
+ model,
16
+ messages,
17
+ createdAt: Date.now(),
18
+ lastUsedAt: Date.now(),
19
+ });
20
+ return id;
21
+ }
22
+ get(id) {
23
+ return this.sessions.get(id);
24
+ }
25
+ addUserMessage(id, content) {
26
+ const session = this.sessions.get(id);
27
+ if (!session)
28
+ return undefined;
29
+ session.messages.push({ role: "user", content });
30
+ session.lastUsedAt = Date.now();
31
+ this.trimMessages(session);
32
+ return [...session.messages];
33
+ }
34
+ addAssistantMessage(id, content) {
35
+ const session = this.sessions.get(id);
36
+ if (!session)
37
+ return;
38
+ session.messages.push({ role: "assistant", content });
39
+ session.lastUsedAt = Date.now();
40
+ }
41
+ list() {
42
+ return [...this.sessions.values()].map((s) => ({
43
+ id: s.id,
44
+ provider: s.provider,
45
+ model: s.model,
46
+ messageCount: s.messages.length,
47
+ lastUsed: s.lastUsedAt,
48
+ }));
49
+ }
50
+ trimMessages(session) {
51
+ if (session.messages.length <= MAX_SESSION_MESSAGES)
52
+ return;
53
+ const hasSystem = session.messages[0]?.role === "system";
54
+ const system = hasSystem ? [session.messages[0]] : [];
55
+ const keep = MAX_SESSION_MESSAGES - system.length;
56
+ session.messages = [...system, ...session.messages.slice(-keep)];
57
+ }
58
+ cleanup() {
59
+ const now = Date.now();
60
+ for (const [id, session] of this.sessions) {
61
+ if (now - session.lastUsedAt > CLEANUP_MAX_AGE_MS) {
62
+ this.sessions.delete(id);
63
+ }
64
+ }
65
+ }
66
+ }
67
+ //# sourceMappingURL=session.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session.js","sourceRoot":"","sources":["../src/session.ts"],"names":[],"mappings":"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"}
package/dist/task.d.ts ADDED
@@ -0,0 +1,19 @@
1
+ import type { TaskState, CompletionResult, CompletionProvider } from "./types.js";
2
+ import type { SessionStore } from "./session.js";
3
+ export declare class TaskStore {
4
+ private tasks;
5
+ create(goal: string, provider: string, model: string, sessionId?: string): TaskState;
6
+ get(taskId: string): TaskState | undefined;
7
+ appendChunk(taskId: string, chunk: string): void;
8
+ complete(taskId: string, result: CompletionResult): void;
9
+ fail(taskId: string, error: string): void;
10
+ cancel(taskId: string): boolean;
11
+ private cleanup;
12
+ }
13
+ export declare function launchTask(taskStore: TaskStore, sessionStore: SessionStore, completionProvider: CompletionProvider, task: TaskState, messages: Array<{
14
+ role: "system" | "user" | "assistant";
15
+ content: string;
16
+ }>): void;
17
+ export declare function formatTaskStatus(task: TaskState): string;
18
+ export declare function formatTaskResult(task: TaskState): string;
19
+ //# sourceMappingURL=task.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"task.d.ts","sourceRoot":"","sources":["../src/task.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,SAAS,EACT,gBAAgB,EAChB,kBAAkB,EAEnB,MAAM,YAAY,CAAC;AACpB,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAIjD,qBAAa,SAAS;IACpB,OAAO,CAAC,KAAK,CAAgC;IAE7C,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS;IAmBpF,GAAG,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,GAAG,SAAS;IAI1C,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI;IAOhD,QAAQ,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,gBAAgB,GAAG,IAAI;IAUxD,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI;IASzC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO;IAU/B,OAAO,CAAC,OAAO;CAYhB;AAMD,wBAAgB,UAAU,CACxB,SAAS,EAAE,SAAS,EACpB,YAAY,EAAE,YAAY,EAC1B,kBAAkB,EAAE,kBAAkB,EACtC,IAAI,EAAE,SAAS,EACf,QAAQ,EAAE,KAAK,CAAC;IAAE,IAAI,EAAE,QAAQ,GAAG,MAAM,GAAG,WAAW,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC,GAC1E,IAAI,CA6BN;AAMD,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,SAAS,GAAG,MAAM,CAiBxD;AAED,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,SAAS,GAAG,MAAM,CAcxD"}
package/dist/task.js ADDED
@@ -0,0 +1,138 @@
1
+ const CLEANUP_MAX_AGE_MS = 30 * 60 * 1000; // 30 minutes
2
+ export class TaskStore {
3
+ tasks = new Map();
4
+ create(goal, provider, model, sessionId) {
5
+ this.cleanup();
6
+ const taskId = `task_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`;
7
+ const task = {
8
+ taskId,
9
+ status: "running",
10
+ goal,
11
+ provider,
12
+ model,
13
+ sessionId,
14
+ streamBuffer: "",
15
+ progress: 0,
16
+ startedAt: Date.now(),
17
+ abortController: new AbortController(),
18
+ };
19
+ this.tasks.set(taskId, task);
20
+ return task;
21
+ }
22
+ get(taskId) {
23
+ return this.tasks.get(taskId);
24
+ }
25
+ appendChunk(taskId, chunk) {
26
+ const task = this.tasks.get(taskId);
27
+ if (!task || task.status !== "running")
28
+ return;
29
+ task.streamBuffer += chunk;
30
+ task.progress = Math.min(95, Math.floor(task.streamBuffer.length / 100));
31
+ }
32
+ complete(taskId, result) {
33
+ const task = this.tasks.get(taskId);
34
+ if (!task)
35
+ return;
36
+ task.status = "completed";
37
+ task.result = result;
38
+ task.progress = 100;
39
+ task.completedAt = Date.now();
40
+ task.abortController = undefined;
41
+ }
42
+ fail(taskId, error) {
43
+ const task = this.tasks.get(taskId);
44
+ if (!task)
45
+ return;
46
+ task.status = "failed";
47
+ task.error = error;
48
+ task.completedAt = Date.now();
49
+ task.abortController = undefined;
50
+ }
51
+ cancel(taskId) {
52
+ const task = this.tasks.get(taskId);
53
+ if (!task || task.status !== "running")
54
+ return false;
55
+ task.abortController?.abort();
56
+ task.status = "cancelled";
57
+ task.completedAt = Date.now();
58
+ task.abortController = undefined;
59
+ return true;
60
+ }
61
+ cleanup() {
62
+ const now = Date.now();
63
+ for (const [id, task] of this.tasks) {
64
+ if (task.status !== "running" &&
65
+ task.completedAt &&
66
+ now - task.completedAt > CLEANUP_MAX_AGE_MS) {
67
+ this.tasks.delete(id);
68
+ }
69
+ }
70
+ }
71
+ }
72
+ // ============================================================
73
+ // Task Execution Engine
74
+ // ============================================================
75
+ export function launchTask(taskStore, sessionStore, completionProvider, task, messages) {
76
+ const run = async () => {
77
+ try {
78
+ const request = {
79
+ model: task.model,
80
+ messages: messages,
81
+ signal: task.abortController?.signal,
82
+ };
83
+ const result = await completionProvider.completeStream(request, (chunk) => taskStore.appendChunk(task.taskId, chunk));
84
+ if (task.sessionId) {
85
+ sessionStore.addAssistantMessage(task.sessionId, result.content);
86
+ }
87
+ taskStore.complete(task.taskId, result);
88
+ }
89
+ catch (error) {
90
+ if (task.status === "cancelled")
91
+ return;
92
+ const msg = error instanceof Error ? error.message : String(error);
93
+ taskStore.fail(task.taskId, msg);
94
+ }
95
+ };
96
+ run().catch((err) => {
97
+ console.error(`[mmf] Task ${task.taskId} error:`, err);
98
+ taskStore.fail(task.taskId, String(err));
99
+ });
100
+ }
101
+ // ============================================================
102
+ // Formatting
103
+ // ============================================================
104
+ export function formatTaskStatus(task) {
105
+ const elapsed = Date.now() - task.startedAt;
106
+ const elapsedStr = elapsed < 1000 ? `${elapsed}ms` : `${(elapsed / 1000).toFixed(1)}s`;
107
+ const lines = [
108
+ `Task: ${task.taskId}`,
109
+ `Status: ${task.status.toUpperCase()} | Provider: ${task.provider} | Model: ${task.model}`,
110
+ `Elapsed: ${elapsedStr} | Progress: ~${task.progress}%`,
111
+ ];
112
+ if (task.streamBuffer.length > 0) {
113
+ const preview = task.streamBuffer.length > 500
114
+ ? "..." + task.streamBuffer.slice(-500)
115
+ : task.streamBuffer;
116
+ lines.push("", "--- Partial Output ---", preview);
117
+ }
118
+ if (task.error)
119
+ lines.push("", `Error: ${task.error}`);
120
+ return lines.join("\n");
121
+ }
122
+ export function formatTaskResult(task) {
123
+ if (!task.result)
124
+ return "No result available.";
125
+ const elapsed = (task.completedAt ?? Date.now()) - task.startedAt;
126
+ const elapsedStr = elapsed < 1000 ? `${elapsed}ms` : `${(elapsed / 1000).toFixed(1)}s`;
127
+ const lines = [
128
+ `Task ${task.taskId} completed in ${elapsedStr}`,
129
+ `Provider: ${task.provider} | Model: ${task.result.model}`,
130
+ ];
131
+ if (task.result.usage) {
132
+ const u = task.result.usage;
133
+ lines.push(`Tokens: ${u.promptTokens} in + ${u.completionTokens} out = ${u.totalTokens} total`);
134
+ }
135
+ lines.push("", "--- Result ---", task.result.content);
136
+ return lines.join("\n");
137
+ }
138
+ //# sourceMappingURL=task.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"task.js","sourceRoot":"","sources":["../src/task.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,86 @@
1
+ import type OpenAI from "openai";
2
+ export interface ProviderConfig {
3
+ apiKey: string;
4
+ baseUrl: string;
5
+ defaultModel: string;
6
+ timeout: number;
7
+ maxRetries: number;
8
+ }
9
+ export interface ModelRoute {
10
+ prefix: string;
11
+ provider: string;
12
+ configFile: string;
13
+ apiKeyEnv: string;
14
+ baseUrlEnv: string;
15
+ modelEnv: string;
16
+ defaultBaseUrl?: string;
17
+ defaultModel: string;
18
+ defaultTimeout: number;
19
+ }
20
+ export interface CompletionRequest {
21
+ model: string;
22
+ messages: OpenAI.ChatCompletionMessageParam[];
23
+ timeoutMs?: number;
24
+ signal?: AbortSignal;
25
+ extra?: Record<string, unknown>;
26
+ }
27
+ export interface CompletionResult {
28
+ content: string;
29
+ model: string;
30
+ usage?: {
31
+ promptTokens: number;
32
+ completionTokens: number;
33
+ totalTokens: number;
34
+ };
35
+ }
36
+ export interface CompletionProvider {
37
+ complete(request: CompletionRequest): Promise<CompletionResult>;
38
+ completeStream(request: CompletionRequest, onChunk: (chunk: string) => void): Promise<CompletionResult>;
39
+ }
40
+ export interface SessionMessage {
41
+ role: "system" | "user" | "assistant";
42
+ content: string;
43
+ }
44
+ export interface Session {
45
+ id: string;
46
+ provider: string;
47
+ model: string;
48
+ messages: SessionMessage[];
49
+ createdAt: number;
50
+ lastUsedAt: number;
51
+ }
52
+ export type TaskStatus = "running" | "completed" | "failed" | "cancelled";
53
+ export interface TaskState {
54
+ taskId: string;
55
+ status: TaskStatus;
56
+ goal: string;
57
+ provider: string;
58
+ model: string;
59
+ sessionId?: string;
60
+ streamBuffer: string;
61
+ progress: number;
62
+ startedAt: number;
63
+ completedAt?: number;
64
+ result?: CompletionResult;
65
+ error?: string;
66
+ abortController?: AbortController;
67
+ }
68
+ export type TaskDomain = "frontend" | "backend" | "review" | "general";
69
+ export interface RouteDecision {
70
+ model: string;
71
+ provider: string;
72
+ systemPrompt: string;
73
+ }
74
+ export interface ToolResponse {
75
+ [key: string]: unknown;
76
+ content: Array<{
77
+ type: "text";
78
+ text: string;
79
+ }>;
80
+ isError?: boolean;
81
+ }
82
+ export interface ErrorContext {
83
+ serviceName: string;
84
+ model?: string;
85
+ }
86
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
package/dist/types.js ADDED
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
package/package.json ADDED
@@ -0,0 +1,48 @@
1
+ {
2
+ "name": "@realseek/mmflow",
3
+ "version": "0.1.0",
4
+ "description": "Multi-Model Flow - Lightweight multi-model orchestration MCP server for Claude Code",
5
+ "type": "module",
6
+ "bin": {
7
+ "mmflow": "./dist/cli.js",
8
+ "mmflow-server": "./dist/index.js"
9
+ },
10
+ "files": [
11
+ "dist",
12
+ ".claude",
13
+ "CLAUDE.md",
14
+ "README.md"
15
+ ],
16
+ "scripts": {
17
+ "build": "tsc",
18
+ "dev": "tsc --watch",
19
+ "start": "node dist/index.js",
20
+ "prepublishOnly": "npm run build"
21
+ },
22
+ "keywords": [
23
+ "claude-code",
24
+ "mcp",
25
+ "multi-model",
26
+ "codex",
27
+ "gemini",
28
+ "orchestration",
29
+ "workflow"
30
+ ],
31
+ "license": "MIT",
32
+ "repository": {
33
+ "type": "git",
34
+ "url": "https://github.com/RealSeek/Multi-Model-Flow.git"
35
+ },
36
+ "dependencies": {
37
+ "@modelcontextprotocol/sdk": "^1.12.1",
38
+ "openai": "^4.104.0",
39
+ "zod": "^3.25.67"
40
+ },
41
+ "devDependencies": {
42
+ "@types/node": "^22.15.21",
43
+ "typescript": "^5.8.3"
44
+ },
45
+ "engines": {
46
+ "node": ">=18.0.0"
47
+ }
48
+ }