goto-assistant 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.
- package/LICENSE +21 -0
- package/README.md +113 -0
- package/bin/goto-assistant.js +9 -0
- package/dist/agents/claude.d.ts +7 -0
- package/dist/agents/claude.js +75 -0
- package/dist/agents/claude.js.map +1 -0
- package/dist/agents/openai.d.ts +3 -0
- package/dist/agents/openai.js +109 -0
- package/dist/agents/openai.js.map +1 -0
- package/dist/agents/router.d.ts +15 -0
- package/dist/agents/router.js +17 -0
- package/dist/agents/router.js.map +1 -0
- package/dist/config.d.ts +33 -0
- package/dist/config.js +67 -0
- package/dist/config.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +12 -0
- package/dist/index.js.map +1 -0
- package/dist/server.d.ts +4 -0
- package/dist/server.js +253 -0
- package/dist/server.js.map +1 -0
- package/dist/sessions.d.ts +35 -0
- package/dist/sessions.js +98 -0
- package/dist/sessions.js.map +1 -0
- package/dist/uploads.d.ts +15 -0
- package/dist/uploads.js +41 -0
- package/dist/uploads.js.map +1 -0
- package/package.json +65 -0
- package/public/cron-sync.js +50 -0
- package/public/index.html +320 -0
- package/public/setup.html +296 -0
- package/public/style.css +200 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 John Lau
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
# goto-assistant
|
|
2
|
+
|
|
3
|
+
Lightweight, self-hosted AI assistant with first-class MCP support. Supports both Claude (Anthropic) and OpenAI as providers, with a web-based chat interface.
|
|
4
|
+
|
|
5
|
+
## Quick Start
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npx goto-assistant
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
Open http://localhost:3000 — first run redirects to setup page for API key config.
|
|
12
|
+
|
|
13
|
+
### Requirements
|
|
14
|
+
- Node.js 20.11 or later
|
|
15
|
+
- Anthropic or OpenAI API key
|
|
16
|
+
|
|
17
|
+
### Data Storage
|
|
18
|
+
All data (config, conversations, uploads) stored in `~/.goto-assistant/`.
|
|
19
|
+
Custom location: `GOTO_DATA_DIR=/path/to/data npx goto-assistant`
|
|
20
|
+
|
|
21
|
+
### Custom Port
|
|
22
|
+
```bash
|
|
23
|
+
PORT=3001 npx goto-assistant
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## Architecture
|
|
27
|
+
|
|
28
|
+
```
|
|
29
|
+
┌─────────────────────────────────────────────────────────┐
|
|
30
|
+
│ Browser │
|
|
31
|
+
│ ┌──────────────┐ ┌──────────────┐ │
|
|
32
|
+
│ │ index.html │ │ setup.html │ │
|
|
33
|
+
│ │ (Chat UI) │ │ (Config) │ │
|
|
34
|
+
│ └──────┬───────┘ └──────┬───────┘ │
|
|
35
|
+
│ │ WebSocket │ HTTP POST │
|
|
36
|
+
└─────────┼──────────────────┼────────────────────────────┘
|
|
37
|
+
│ │
|
|
38
|
+
┌─────────┼──────────────────┼────────────────────────────┐
|
|
39
|
+
│ server.ts │ │
|
|
40
|
+
│ ┌──────┴───────┐ ┌──────┴───────┐ │
|
|
41
|
+
│ │ WebSocket │ │ REST API │ │
|
|
42
|
+
│ │ Handler │ │ /api/* │ │
|
|
43
|
+
│ └──────┬───────┘ └──────────────┘ │
|
|
44
|
+
│ │ │
|
|
45
|
+
│ ┌──────┴───────┐ │
|
|
46
|
+
│ │ router.ts │──── routes by provider │
|
|
47
|
+
│ └──┬────────┬──┘ │
|
|
48
|
+
│ │ │ │
|
|
49
|
+
│ ┌──┴──┐ ┌──┴───┐ ┌────────────┐ │
|
|
50
|
+
│ │Claude│ │OpenAI│────▶│ MCP Servers │ │
|
|
51
|
+
│ │Agent │ │Agent │ │ (memory, │ │
|
|
52
|
+
│ │ SDK │ │ SDK │ │ fs, cron) │ │
|
|
53
|
+
│ └──┬──┘ └──┬───┘ └────────────┘ │
|
|
54
|
+
│ │ │ │
|
|
55
|
+
│ ┌──┴────────┴──┐ ┌────────────┐ │
|
|
56
|
+
│ │ sessions.ts │────▶│ SQLite DB │ │
|
|
57
|
+
│ │ (persistence)│ │ data/ │ │
|
|
58
|
+
│ └──────────────┘ └────────────┘ │
|
|
59
|
+
└─────────────────────────────────────────────────────────┘
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
## Development Setup
|
|
63
|
+
|
|
64
|
+
1. Install dependencies:
|
|
65
|
+
```bash
|
|
66
|
+
pnpm install
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
2. Start the development server:
|
|
70
|
+
```bash
|
|
71
|
+
pnpm dev
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
3. Open `http://localhost:3000` — you'll be redirected to the setup page on first run to configure your AI provider and API key.
|
|
75
|
+
|
|
76
|
+
## Configuration
|
|
77
|
+
|
|
78
|
+
App configuration is stored in `data/config.json` (created on first setup). MCP server configuration is stored separately in `data/mcp.json`. Environment variables override file config:
|
|
79
|
+
|
|
80
|
+
- `ANTHROPIC_API_KEY` — API key for Claude
|
|
81
|
+
- `OPENAI_API_KEY` — API key for OpenAI
|
|
82
|
+
|
|
83
|
+
## MCP Servers
|
|
84
|
+
|
|
85
|
+
The assistant comes pre-configured with these MCP servers:
|
|
86
|
+
|
|
87
|
+
| Server | Package | Capabilities |
|
|
88
|
+
|--------|---------|-------------|
|
|
89
|
+
| **memory** | [`@modelcontextprotocol/server-memory`](https://github.com/modelcontextprotocol/servers/tree/main/src/memory) | Persistent knowledge graph across conversations |
|
|
90
|
+
| **filesystem** | [`@modelcontextprotocol/server-filesystem`](https://github.com/modelcontextprotocol/servers/tree/main/src/filesystem) | Read, write, and manage local files |
|
|
91
|
+
| **cron** | [`mcp-cron`](https://github.com/jolks/mcp-cron) | Schedule shell commands and AI prompts with access to MCP servers |
|
|
92
|
+
|
|
93
|
+
Add your own through the setup page or by editing `data/mcp.json` directly. Any MCP server that supports stdio transport will work — browse the [MCP server directory](https://github.com/modelcontextprotocol/servers) for more.
|
|
94
|
+
|
|
95
|
+
### Claude Code MCP servers
|
|
96
|
+
|
|
97
|
+
If you use [Claude Code](https://claude.ai/code), copy the example config to get MCP servers for development:
|
|
98
|
+
|
|
99
|
+
```bash
|
|
100
|
+
cp .mcp.json.example .mcp.json
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
Edit `.mcp.json` to set your preferred AI provider/model for the cron server. This file is gitignored since it contains personal preferences.
|
|
104
|
+
|
|
105
|
+
## Development
|
|
106
|
+
|
|
107
|
+
```bash
|
|
108
|
+
pnpm dev # run with tsx (hot TypeScript execution)
|
|
109
|
+
pnpm build # compile TypeScript to dist/
|
|
110
|
+
pnpm start # run compiled build
|
|
111
|
+
pnpm test # run tests
|
|
112
|
+
pnpm test:watch # run tests in watch mode
|
|
113
|
+
```
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { Config, McpServerConfig } from "../config.js";
|
|
2
|
+
import type { Attachment } from "./router.js";
|
|
3
|
+
export interface AgentResponse {
|
|
4
|
+
sessionId: string | null;
|
|
5
|
+
conversationId: string;
|
|
6
|
+
}
|
|
7
|
+
export declare function runClaude(prompt: string, config: Config, mcpServersConfig: Record<string, McpServerConfig>, onChunk: (text: string) => void, resumeSessionId?: string, attachments?: Attachment[]): Promise<AgentResponse>;
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { query } from "@anthropic-ai/claude-agent-sdk";
|
|
2
|
+
import { MEMORY_FILE_PATH, MEMORY_SERVER_NAME } from "../config.js";
|
|
3
|
+
export async function runClaude(prompt, config, mcpServersConfig, onChunk, resumeSessionId, attachments) {
|
|
4
|
+
const env = {
|
|
5
|
+
...process.env,
|
|
6
|
+
ANTHROPIC_API_KEY: config.claude.apiKey,
|
|
7
|
+
};
|
|
8
|
+
if (config.claude.baseUrl) {
|
|
9
|
+
env.ANTHROPIC_BASE_URL = config.claude.baseUrl;
|
|
10
|
+
}
|
|
11
|
+
// Build MCP servers config with their env vars
|
|
12
|
+
const mcpServers = {};
|
|
13
|
+
for (const [name, server] of Object.entries(mcpServersConfig)) {
|
|
14
|
+
const serverEnv = { ...env, ...server.env };
|
|
15
|
+
if (name === MEMORY_SERVER_NAME) {
|
|
16
|
+
serverEnv.MEMORY_FILE_PATH = MEMORY_FILE_PATH;
|
|
17
|
+
}
|
|
18
|
+
mcpServers[name] = {
|
|
19
|
+
command: server.command,
|
|
20
|
+
args: server.args,
|
|
21
|
+
env: serverEnv,
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
const options = {
|
|
25
|
+
model: config.claude.model,
|
|
26
|
+
mcpServers,
|
|
27
|
+
permissionMode: "bypassPermissions",
|
|
28
|
+
allowDangerouslySkipPermissions: true,
|
|
29
|
+
allowedTools: Object.keys(mcpServersConfig).map((name) => `mcp__${name}__*`),
|
|
30
|
+
systemPrompt: "You are a helpful personal AI assistant. You have access to MCP tools for memory, filesystem, browser automation, and scheduled tasks. Use them when appropriate. IMPORTANT: At the start of each conversation, you MUST call the memory read_graph tool to retrieve all known context about the user before responding to their first message.",
|
|
31
|
+
env,
|
|
32
|
+
maxTurns: 30,
|
|
33
|
+
};
|
|
34
|
+
if (resumeSessionId) {
|
|
35
|
+
options.resume = resumeSessionId;
|
|
36
|
+
}
|
|
37
|
+
// When attachments are present, reference file paths in the prompt so Claude
|
|
38
|
+
// can read them via the filesystem MCP server's read_media_file tool.
|
|
39
|
+
// The query() function only accepts a plain string prompt.
|
|
40
|
+
let queryPrompt = prompt;
|
|
41
|
+
if (attachments && attachments.length > 0) {
|
|
42
|
+
const paths = attachments
|
|
43
|
+
.filter((att) => att.filePath)
|
|
44
|
+
.map((att) => att.filePath);
|
|
45
|
+
if (paths.length > 0) {
|
|
46
|
+
queryPrompt = `${prompt}\n\n[The user attached ${paths.length} image(s). Read them using the filesystem read_media_file tool to see the content:\n${paths.join("\n")}]`;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
let sessionId = null;
|
|
50
|
+
const result = query({ prompt: queryPrompt, options });
|
|
51
|
+
for await (const message of result) {
|
|
52
|
+
if (message.type === "system" && message.subtype === "init") {
|
|
53
|
+
sessionId = message.session_id ?? null;
|
|
54
|
+
}
|
|
55
|
+
if (message.type === "assistant") {
|
|
56
|
+
const content = message.content;
|
|
57
|
+
if (content) {
|
|
58
|
+
for (const block of content) {
|
|
59
|
+
if (block.type === "text" && block.text) {
|
|
60
|
+
onChunk(block.text);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
if (message.type === "result" && message.subtype === "success") {
|
|
66
|
+
const resultMsg = message;
|
|
67
|
+
sessionId = resultMsg.session_id ?? sessionId;
|
|
68
|
+
if (resultMsg.result) {
|
|
69
|
+
onChunk(resultMsg.result);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
return { sessionId, conversationId: "" };
|
|
74
|
+
}
|
|
75
|
+
//# sourceMappingURL=claude.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"claude.js","sourceRoot":"","sources":["../../src/agents/claude.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import type { Config, McpServerConfig } from "../config.js";
|
|
2
|
+
import type { Attachment, HistoryMessage } from "./router.js";
|
|
3
|
+
export declare function runOpenAI(prompt: string, config: Config, mcpServersConfig: Record<string, McpServerConfig>, onChunk: (text: string) => void, attachments?: Attachment[], history?: HistoryMessage[]): Promise<void>;
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import { Agent, run, MCPServerStdio } from "@openai/agents";
|
|
2
|
+
import { MEMORY_FILE_PATH, MEMORY_SERVER_NAME } from "../config.js";
|
|
3
|
+
import { parseMessageContent } from "../sessions.js";
|
|
4
|
+
import { getUpload } from "../uploads.js";
|
|
5
|
+
export async function runOpenAI(prompt, config, mcpServersConfig, onChunk, attachments, history) {
|
|
6
|
+
const env = {
|
|
7
|
+
...process.env,
|
|
8
|
+
OPENAI_API_KEY: config.openai.apiKey,
|
|
9
|
+
};
|
|
10
|
+
if (config.openai.baseUrl) {
|
|
11
|
+
env.OPENAI_BASE_URL = config.openai.baseUrl;
|
|
12
|
+
}
|
|
13
|
+
// Set up MCP stdio servers
|
|
14
|
+
const mcpServers = [];
|
|
15
|
+
for (const [name, server] of Object.entries(mcpServersConfig)) {
|
|
16
|
+
const serverEnv = { ...env, ...server.env };
|
|
17
|
+
if (name === MEMORY_SERVER_NAME) {
|
|
18
|
+
serverEnv.MEMORY_FILE_PATH = MEMORY_FILE_PATH;
|
|
19
|
+
}
|
|
20
|
+
mcpServers.push(new MCPServerStdio({
|
|
21
|
+
name,
|
|
22
|
+
fullCommand: `${server.command} ${server.args.join(" ")}`,
|
|
23
|
+
env: serverEnv,
|
|
24
|
+
}));
|
|
25
|
+
}
|
|
26
|
+
try {
|
|
27
|
+
// Connect all MCP servers
|
|
28
|
+
for (const server of mcpServers) {
|
|
29
|
+
await server.connect();
|
|
30
|
+
}
|
|
31
|
+
const agent = new Agent({
|
|
32
|
+
name: "goto-assistant",
|
|
33
|
+
instructions: "You are a helpful personal AI assistant. You have access to MCP tools for memory, filesystem, browser automation, and scheduled tasks. Use them when appropriate. IMPORTANT: At the start of each conversation, you MUST call the memory read_graph tool to retrieve all known context about the user before responding to their first message.",
|
|
34
|
+
model: config.openai.model,
|
|
35
|
+
mcpServers,
|
|
36
|
+
});
|
|
37
|
+
// Build conversation input with history
|
|
38
|
+
const inputMessages = [];
|
|
39
|
+
// Add previous messages (re-include images from uploads)
|
|
40
|
+
if (history && history.length > 0) {
|
|
41
|
+
for (const msg of history) {
|
|
42
|
+
const parsed = parseMessageContent(msg.content);
|
|
43
|
+
if (msg.role === "assistant") {
|
|
44
|
+
// OpenAI Responses API requires assistant content as an array of output blocks
|
|
45
|
+
inputMessages.push({
|
|
46
|
+
role: "assistant",
|
|
47
|
+
content: [{ type: "output_text", text: parsed.text }],
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
else if (parsed.attachments && parsed.attachments.length > 0) {
|
|
51
|
+
// Re-read image data for user messages that had attachments
|
|
52
|
+
const content = [];
|
|
53
|
+
for (const att of parsed.attachments) {
|
|
54
|
+
const upload = getUpload(att.fileId);
|
|
55
|
+
if (upload) {
|
|
56
|
+
content.push({
|
|
57
|
+
type: "input_image",
|
|
58
|
+
image: `data:${upload.mimeType};base64,${upload.data.toString("base64")}`,
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
content.push({ type: "input_text", text: parsed.text });
|
|
63
|
+
inputMessages.push({ role: "user", content });
|
|
64
|
+
}
|
|
65
|
+
else {
|
|
66
|
+
inputMessages.push({ role: msg.role, content: parsed.text });
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
// Add current message
|
|
71
|
+
if (attachments && attachments.length > 0) {
|
|
72
|
+
const content = [];
|
|
73
|
+
for (const att of attachments) {
|
|
74
|
+
content.push({
|
|
75
|
+
type: "input_image",
|
|
76
|
+
image: `data:${att.mimeType};base64,${att.data.toString("base64")}`,
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
content.push({ type: "input_text", text: prompt });
|
|
80
|
+
inputMessages.push({ role: "user", content });
|
|
81
|
+
}
|
|
82
|
+
else {
|
|
83
|
+
inputMessages.push({ role: "user", content: prompt });
|
|
84
|
+
}
|
|
85
|
+
const input = inputMessages.length === 1 && !history?.length && !attachments?.length ? prompt : inputMessages;
|
|
86
|
+
const result = await run(agent, input, { stream: true });
|
|
87
|
+
for await (const event of result) {
|
|
88
|
+
if (event.type === "raw_model_stream_event" &&
|
|
89
|
+
event.data?.type === "output_text_delta") {
|
|
90
|
+
const delta = event.data.delta;
|
|
91
|
+
if (delta) {
|
|
92
|
+
onChunk(delta);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
finally {
|
|
98
|
+
// Disconnect all MCP servers
|
|
99
|
+
for (const server of mcpServers) {
|
|
100
|
+
try {
|
|
101
|
+
await server.close();
|
|
102
|
+
}
|
|
103
|
+
catch {
|
|
104
|
+
// ignore cleanup errors
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
//# sourceMappingURL=openai.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"openai.js","sourceRoot":"","sources":["../../src/agents/openai.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { Config, McpServerConfig } from "../config.js";
|
|
2
|
+
export interface Attachment {
|
|
3
|
+
filename: string;
|
|
4
|
+
mimeType: string;
|
|
5
|
+
data: Buffer;
|
|
6
|
+
filePath?: string;
|
|
7
|
+
}
|
|
8
|
+
export interface HistoryMessage {
|
|
9
|
+
role: string;
|
|
10
|
+
content: string;
|
|
11
|
+
}
|
|
12
|
+
export interface RouteResult {
|
|
13
|
+
sessionId: string | null;
|
|
14
|
+
}
|
|
15
|
+
export declare function routeMessage(prompt: string, config: Config, mcpServers: Record<string, McpServerConfig>, onChunk: (text: string) => void, resumeSessionId?: string, attachments?: Attachment[], history?: HistoryMessage[]): Promise<RouteResult>;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { runClaude } from "./claude.js";
|
|
2
|
+
import { runOpenAI } from "./openai.js";
|
|
3
|
+
export async function routeMessage(prompt, config, mcpServers, onChunk, resumeSessionId, attachments, history) {
|
|
4
|
+
switch (config.provider) {
|
|
5
|
+
case "claude": {
|
|
6
|
+
const result = await runClaude(prompt, config, mcpServers, onChunk, resumeSessionId, attachments);
|
|
7
|
+
return { sessionId: result.sessionId };
|
|
8
|
+
}
|
|
9
|
+
case "openai": {
|
|
10
|
+
await runOpenAI(prompt, config, mcpServers, onChunk, attachments, history);
|
|
11
|
+
return { sessionId: null };
|
|
12
|
+
}
|
|
13
|
+
default:
|
|
14
|
+
throw new Error(`Unknown provider: ${config.provider}`);
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=router.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"router.js","sourceRoot":"","sources":["../../src/agents/router.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAkBxC,MAAM,CAAC,KAAK,UAAU,YAAY,CAChC,MAAc,EACd,MAAc,EACd,UAA2C,EAC3C,OAA+B,EAC/B,eAAwB,EACxB,WAA0B,EAC1B,OAA0B;IAE1B,QAAQ,MAAM,CAAC,QAAQ,EAAE,CAAC;QACxB,KAAK,QAAQ,CAAC,CAAC,CAAC;YACd,MAAM,MAAM,GAAG,MAAM,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,OAAO,EAAE,eAAe,EAAE,WAAW,CAAC,CAAC;YAClG,OAAO,EAAE,SAAS,EAAE,MAAM,CAAC,SAAS,EAAE,CAAC;QACzC,CAAC;QACD,KAAK,QAAQ,CAAC,CAAC,CAAC;YACd,MAAM,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,OAAO,EAAE,WAAW,EAAE,OAAO,CAAC,CAAC;YAC3E,OAAO,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC;QAC7B,CAAC;QACD;YACE,MAAM,IAAI,KAAK,CAAC,qBAAqB,MAAM,CAAC,QAAQ,EAAE,CAAC,CAAC;IAC5D,CAAC;AACH,CAAC"}
|
package/dist/config.d.ts
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
export interface McpServerConfig {
|
|
2
|
+
command: string;
|
|
3
|
+
args: string[];
|
|
4
|
+
env?: Record<string, string>;
|
|
5
|
+
}
|
|
6
|
+
export interface Config {
|
|
7
|
+
provider: "claude" | "openai";
|
|
8
|
+
claude: {
|
|
9
|
+
apiKey: string;
|
|
10
|
+
model: string;
|
|
11
|
+
baseUrl: string;
|
|
12
|
+
};
|
|
13
|
+
openai: {
|
|
14
|
+
apiKey: string;
|
|
15
|
+
model: string;
|
|
16
|
+
baseUrl: string;
|
|
17
|
+
};
|
|
18
|
+
server: {
|
|
19
|
+
port: number;
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
export declare const DATA_DIR: string;
|
|
23
|
+
export declare const MCP_CONFIG_PATH: string;
|
|
24
|
+
export declare const MEMORY_FILE_PATH: string;
|
|
25
|
+
export declare const MEMORY_SERVER_NAME = "memory";
|
|
26
|
+
export declare function isConfigured(): boolean;
|
|
27
|
+
export declare function loadConfig(): Config;
|
|
28
|
+
export declare function saveConfig(config: Config): void;
|
|
29
|
+
export declare function loadMcpServers(): Record<string, McpServerConfig>;
|
|
30
|
+
export declare function saveMcpServers(servers: Record<string, McpServerConfig>): void;
|
|
31
|
+
export declare function maskApiKey(key: string): string;
|
|
32
|
+
export declare function getMaskedConfig(config: Config): Config;
|
|
33
|
+
export declare function getMaskedMcpServers(servers: Record<string, McpServerConfig>): Record<string, McpServerConfig>;
|
package/dist/config.js
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
export const DATA_DIR = path.join(process.cwd(), process.env.GOTO_DATA_DIR || "data");
|
|
4
|
+
const CONFIG_PATH = path.join(DATA_DIR, "config.json");
|
|
5
|
+
export const MCP_CONFIG_PATH = path.join(DATA_DIR, "mcp.json");
|
|
6
|
+
export const MEMORY_FILE_PATH = path.join(DATA_DIR, "memory.json");
|
|
7
|
+
export const MEMORY_SERVER_NAME = "memory";
|
|
8
|
+
export function isConfigured() {
|
|
9
|
+
return fs.existsSync(CONFIG_PATH);
|
|
10
|
+
}
|
|
11
|
+
export function loadConfig() {
|
|
12
|
+
const raw = fs.readFileSync(CONFIG_PATH, "utf-8");
|
|
13
|
+
const config = JSON.parse(raw);
|
|
14
|
+
// Environment variables override config file values
|
|
15
|
+
if (process.env.ANTHROPIC_API_KEY) {
|
|
16
|
+
config.claude.apiKey = process.env.ANTHROPIC_API_KEY;
|
|
17
|
+
}
|
|
18
|
+
if (process.env.OPENAI_API_KEY) {
|
|
19
|
+
config.openai.apiKey = process.env.OPENAI_API_KEY;
|
|
20
|
+
}
|
|
21
|
+
return config;
|
|
22
|
+
}
|
|
23
|
+
export function saveConfig(config) {
|
|
24
|
+
if (!fs.existsSync(DATA_DIR)) {
|
|
25
|
+
fs.mkdirSync(DATA_DIR, { recursive: true });
|
|
26
|
+
}
|
|
27
|
+
fs.writeFileSync(CONFIG_PATH, JSON.stringify(config, null, 2));
|
|
28
|
+
}
|
|
29
|
+
export function loadMcpServers() {
|
|
30
|
+
if (!fs.existsSync(MCP_CONFIG_PATH))
|
|
31
|
+
return {};
|
|
32
|
+
const raw = fs.readFileSync(MCP_CONFIG_PATH, "utf-8");
|
|
33
|
+
const parsed = JSON.parse(raw);
|
|
34
|
+
return parsed.mcpServers ?? {};
|
|
35
|
+
}
|
|
36
|
+
export function saveMcpServers(servers) {
|
|
37
|
+
if (!fs.existsSync(DATA_DIR)) {
|
|
38
|
+
fs.mkdirSync(DATA_DIR, { recursive: true });
|
|
39
|
+
}
|
|
40
|
+
fs.writeFileSync(MCP_CONFIG_PATH, JSON.stringify({ mcpServers: servers }, null, 2));
|
|
41
|
+
}
|
|
42
|
+
export function maskApiKey(key) {
|
|
43
|
+
if (key.length <= 8)
|
|
44
|
+
return "****";
|
|
45
|
+
return key.slice(0, 4) + "****" + key.slice(-4);
|
|
46
|
+
}
|
|
47
|
+
export function getMaskedConfig(config) {
|
|
48
|
+
return {
|
|
49
|
+
...config,
|
|
50
|
+
claude: { ...config.claude, apiKey: maskApiKey(config.claude.apiKey) },
|
|
51
|
+
openai: { ...config.openai, apiKey: maskApiKey(config.openai.apiKey) },
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
export function getMaskedMcpServers(servers) {
|
|
55
|
+
return Object.fromEntries(Object.entries(servers).map(([name, server]) => [
|
|
56
|
+
name,
|
|
57
|
+
{
|
|
58
|
+
...server,
|
|
59
|
+
env: server.env
|
|
60
|
+
? Object.fromEntries(Object.entries(server.env).map(([k, v]) => k.toLowerCase().includes("key") || k.toLowerCase().includes("secret")
|
|
61
|
+
? [k, maskApiKey(v)]
|
|
62
|
+
: [k, v]))
|
|
63
|
+
: undefined,
|
|
64
|
+
},
|
|
65
|
+
]));
|
|
66
|
+
}
|
|
67
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { createApp, createServer } from "./server.js";
|
|
2
|
+
import { isConfigured, loadConfig } from "./config.js";
|
|
3
|
+
const app = createApp();
|
|
4
|
+
const server = createServer(app);
|
|
5
|
+
const port = Number(process.env.PORT) || (isConfigured() ? loadConfig().server.port : 3000);
|
|
6
|
+
server.listen(port, () => {
|
|
7
|
+
console.log(`goto-assistant running at http://localhost:${port}`);
|
|
8
|
+
if (!isConfigured()) {
|
|
9
|
+
console.log("First run detected — visit the URL above to configure.");
|
|
10
|
+
}
|
|
11
|
+
});
|
|
12
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AACtD,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAEvD,MAAM,GAAG,GAAG,SAAS,EAAE,CAAC;AACxB,MAAM,MAAM,GAAG,YAAY,CAAC,GAAG,CAAC,CAAC;AAEjC,MAAM,IAAI,GAAG,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,CAAC,CAAC,CAAC,UAAU,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;AAE5F,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,GAAG,EAAE;IACvB,OAAO,CAAC,GAAG,CAAC,8CAA8C,IAAI,EAAE,CAAC,CAAC;IAClE,IAAI,CAAC,YAAY,EAAE,EAAE,CAAC;QACpB,OAAO,CAAC,GAAG,CAAC,wDAAwD,CAAC,CAAC;IACxE,CAAC;AACH,CAAC,CAAC,CAAC"}
|
package/dist/server.d.ts
ADDED