trykora 1.0.1 → 1.2.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/dist/bin/kora.js +0 -6
- package/dist/bin/kora.js.map +1 -1
- package/dist/src/cli/index.d.ts.map +1 -1
- package/dist/src/cli/index.js +2 -0
- package/dist/src/cli/index.js.map +1 -1
- package/dist/src/cli/init.d.ts.map +1 -1
- package/dist/src/cli/init.js +162 -91
- package/dist/src/cli/init.js.map +1 -1
- package/dist/src/cli/sync.d.ts +3 -0
- package/dist/src/cli/sync.d.ts.map +1 -0
- package/dist/src/cli/sync.js +40 -0
- package/dist/src/cli/sync.js.map +1 -0
- package/dist/src/mcp/tools.d.ts.map +1 -1
- package/dist/src/mcp/tools.js +184 -61
- package/dist/src/mcp/tools.js.map +1 -1
- package/dist/src/storage/sqlite.d.ts +1 -1
- package/dist/src/storage/sqlite.d.ts.map +1 -1
- package/dist/src/storage/sqlite.js +2 -2
- package/dist/src/storage/sqlite.js.map +1 -1
- package/package.json +2 -2
package/dist/bin/kora.js
CHANGED
|
@@ -5,12 +5,6 @@ program
|
|
|
5
5
|
.name('kora')
|
|
6
6
|
.description('Your build-in-public brain — capture learnings, draft tweets')
|
|
7
7
|
.version('0.1.0');
|
|
8
|
-
program
|
|
9
|
-
.command('serve')
|
|
10
|
-
.description('Start the MCP stdio server (used by Claude Desktop, Cursor, etc.)')
|
|
11
|
-
.action(async () => {
|
|
12
|
-
await startMcpServer();
|
|
13
|
-
});
|
|
14
8
|
async function main() {
|
|
15
9
|
// Dynamically import CLI commands to avoid loading heavy deps in serve mode
|
|
16
10
|
const { registerCommands } = await import('../src/cli/index.js');
|
package/dist/bin/kora.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"kora.js","sourceRoot":"","sources":["../../bin/kora.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAEtD,OAAO;KACJ,IAAI,CAAC,MAAM,CAAC;KACZ,WAAW,CAAC,8DAA8D,CAAC;KAC3E,OAAO,CAAC,OAAO,CAAC,CAAC;AAEpB,
|
|
1
|
+
{"version":3,"file":"kora.js","sourceRoot":"","sources":["../../bin/kora.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAEtD,OAAO;KACJ,IAAI,CAAC,MAAM,CAAC;KACZ,WAAW,CAAC,8DAA8D,CAAC;KAC3E,OAAO,CAAC,OAAO,CAAC,CAAC;AAEpB,KAAK,UAAU,IAAI;IACjB,4EAA4E;IAC5E,MAAM,EAAE,gBAAgB,EAAE,GAAG,MAAM,MAAM,CAAC,qBAAqB,CAAC,CAAC;IACjE,gBAAgB,CAAC,OAAO,CAAC,CAAC;IAC1B,OAAO,CAAC,KAAK,EAAE,CAAC;AAClB,CAAC;AAED,iDAAiD;AACjD,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,OAAO,EAAE,CAAC;IAChC,cAAc,EAAE,CAAC;AACnB,CAAC;KAAM,CAAC;IACN,IAAI,EAAE,CAAC;AACT,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/cli/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/cli/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAWpC,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,OAAO,QAWhD"}
|
package/dist/src/cli/index.js
CHANGED
|
@@ -6,6 +6,7 @@ import { listCommand } from './list.js';
|
|
|
6
6
|
import { backupCommand } from './backup.js';
|
|
7
7
|
import { notionCommand } from './notion.js';
|
|
8
8
|
import { resetKeyCommand } from './reset-key.js';
|
|
9
|
+
import { syncCommand } from './sync.js';
|
|
9
10
|
export function registerCommands(program) {
|
|
10
11
|
showBanner();
|
|
11
12
|
loginCommand(program);
|
|
@@ -15,5 +16,6 @@ export function registerCommands(program) {
|
|
|
15
16
|
backupCommand(program);
|
|
16
17
|
notionCommand(program);
|
|
17
18
|
resetKeyCommand(program);
|
|
19
|
+
syncCommand(program);
|
|
18
20
|
}
|
|
19
21
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/cli/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AACtC,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC1C,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AACxC,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AACxC,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/cli/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AACtC,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC1C,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AACxC,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AACxC,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AACjD,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAExC,MAAM,UAAU,gBAAgB,CAAC,OAAgB;IAC/C,UAAU,EAAE,CAAC;IAEb,YAAY,CAAC,OAAO,CAAC,CAAC;IACtB,WAAW,CAAC,OAAO,CAAC,CAAC;IACrB,aAAa,CAAC,OAAO,CAAC,CAAC;IACvB,WAAW,CAAC,OAAO,CAAC,CAAC;IACrB,aAAa,CAAC,OAAO,CAAC,CAAC;IACvB,aAAa,CAAC,OAAO,CAAC,CAAC;IACvB,eAAe,CAAC,OAAO,CAAC,CAAC;IACzB,WAAW,CAAC,OAAO,CAAC,CAAC;AACvB,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../../src/cli/init.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../../src/cli/init.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAgGpC,wBAAgB,WAAW,CAAC,OAAO,EAAE,OAAO,QAsE3C"}
|
package/dist/src/cli/init.js
CHANGED
|
@@ -2,23 +2,94 @@ import fs from 'fs';
|
|
|
2
2
|
import path from 'path';
|
|
3
3
|
import os from 'os';
|
|
4
4
|
import chalk from 'chalk';
|
|
5
|
-
import
|
|
6
|
-
import { showHeader, successBox, errorBox, step, infoBox } from '../ui.js';
|
|
5
|
+
import { showHeader, successBox, errorBox, step } from '../ui.js';
|
|
7
6
|
import { readConfig } from '../config.js';
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
7
|
+
// OS-specific paths
|
|
8
|
+
const homedir = os.homedir();
|
|
9
|
+
const platform = os.platform();
|
|
10
|
+
const getClaudeDesktopPath = () => {
|
|
11
|
+
if (platform === 'darwin')
|
|
12
|
+
return path.join(homedir, 'Library', 'Application Support', 'Claude', 'claude_desktop_config.json');
|
|
13
|
+
if (platform === 'win32')
|
|
14
|
+
return path.join(homedir, 'AppData', 'Roaming', 'Claude', 'claude_desktop_config.json');
|
|
16
15
|
return null;
|
|
17
|
-
}
|
|
16
|
+
};
|
|
17
|
+
const getRooCodePath = () => {
|
|
18
|
+
if (platform === 'darwin')
|
|
19
|
+
return path.join(homedir, 'Library', 'Application Support', 'Code', 'User', 'globalStorage', 'saoudrizwan.claude-dev', 'settings', 'cline_mcp_settings.json');
|
|
20
|
+
if (platform === 'win32')
|
|
21
|
+
return path.join(homedir, 'AppData', 'Roaming', 'Code', 'User', 'globalStorage', 'saoudrizwan.claude-dev', 'settings', 'cline_mcp_settings.json');
|
|
22
|
+
if (platform === 'linux')
|
|
23
|
+
return path.join(homedir, '.config', 'Code', 'User', 'globalStorage', 'saoudrizwan.claude-dev', 'settings', 'cline_mcp_settings.json');
|
|
24
|
+
return null;
|
|
25
|
+
};
|
|
26
|
+
const getWindsurfPath = () => {
|
|
27
|
+
if (platform === 'win32')
|
|
28
|
+
return path.join(homedir, 'AppData', 'Roaming', 'Codeium', 'Windsurf', 'mcp_config.json');
|
|
29
|
+
return path.join(homedir, '.codeium', 'windsurf', 'mcp_config.json');
|
|
30
|
+
};
|
|
31
|
+
const getCursorPath = () => {
|
|
32
|
+
if (platform === 'win32')
|
|
33
|
+
return path.join(homedir, 'AppData', 'Roaming', 'Cursor', 'User', 'globalStorage', 'mcp.json');
|
|
34
|
+
return path.join(homedir, '.cursor', 'mcp.json'); // Mac and Linux default
|
|
35
|
+
};
|
|
36
|
+
const getOpenCodePath = () => {
|
|
37
|
+
if (platform === 'win32')
|
|
38
|
+
return path.join(homedir, '.config', 'opencode', 'opencode.json');
|
|
39
|
+
return path.join(homedir, '.config', 'opencode', 'opencode.json');
|
|
40
|
+
};
|
|
41
|
+
// Tool Configuration Definitions
|
|
42
|
+
const TOOLS = [
|
|
43
|
+
{
|
|
44
|
+
name: 'Claude Desktop',
|
|
45
|
+
path: getClaudeDesktopPath(),
|
|
46
|
+
type: 'json-mcpServers',
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
name: 'Claude Code',
|
|
50
|
+
path: path.join(homedir, '.claude.json'),
|
|
51
|
+
type: 'json-mcpServers',
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
name: 'Cursor',
|
|
55
|
+
path: getCursorPath(),
|
|
56
|
+
type: 'json-mcpServers',
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
name: 'Windsurf',
|
|
60
|
+
path: getWindsurfPath(),
|
|
61
|
+
type: 'json-mcpServers',
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
name: 'Cline',
|
|
65
|
+
path: path.join(homedir, '.cline', 'data', 'settings', 'cline_mcp_settings.json'),
|
|
66
|
+
type: 'json-mcpServers',
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
name: 'Roo Code',
|
|
70
|
+
path: getRooCodePath(),
|
|
71
|
+
type: 'json-mcpServers',
|
|
72
|
+
},
|
|
73
|
+
{
|
|
74
|
+
name: 'Antigravity',
|
|
75
|
+
path: path.join(homedir, '.gemini', 'antigravity', 'mcp_config.json'),
|
|
76
|
+
type: 'json-mcpServers', // Antigravity format matches standard
|
|
77
|
+
},
|
|
78
|
+
{
|
|
79
|
+
name: 'OpenCode',
|
|
80
|
+
path: getOpenCodePath(),
|
|
81
|
+
type: 'json-mcp', // OpenCode uses "mcp" instead of "mcpServers"
|
|
82
|
+
},
|
|
83
|
+
{
|
|
84
|
+
name: 'Codex',
|
|
85
|
+
path: path.join(homedir, '.codex', 'config.toml'),
|
|
86
|
+
type: 'toml-block',
|
|
87
|
+
}
|
|
88
|
+
];
|
|
18
89
|
export function initCommand(program) {
|
|
19
90
|
program
|
|
20
91
|
.command('init')
|
|
21
|
-
.description('
|
|
92
|
+
.description('Auto-discover and set up Kora in your AI tools')
|
|
22
93
|
.action(async () => {
|
|
23
94
|
showHeader('init');
|
|
24
95
|
const config = readConfig();
|
|
@@ -26,94 +97,94 @@ export function initCommand(program) {
|
|
|
26
97
|
errorBox('No API key found. Run `kora login` first.');
|
|
27
98
|
return;
|
|
28
99
|
}
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
100
|
+
step(1, 2, 'Scanning for AI tools and injecting Kora MCP server...');
|
|
101
|
+
let configuredTools = [];
|
|
102
|
+
let skippedTools = [];
|
|
103
|
+
let failedTools = [];
|
|
104
|
+
for (const tool of TOOLS) {
|
|
105
|
+
if (!tool.path)
|
|
106
|
+
continue;
|
|
107
|
+
// Skip if the directory structure doesn't even exist
|
|
108
|
+
const dir = path.dirname(tool.path);
|
|
109
|
+
if (!fs.existsSync(dir)) {
|
|
110
|
+
skippedTools.push(tool.name);
|
|
111
|
+
continue;
|
|
112
|
+
}
|
|
113
|
+
try {
|
|
114
|
+
const success = setupTool(tool.name, tool.path, tool.type);
|
|
115
|
+
if (success) {
|
|
116
|
+
configuredTools.push(tool.name);
|
|
117
|
+
}
|
|
118
|
+
else {
|
|
119
|
+
failedTools.push(tool.name);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
catch (err) {
|
|
123
|
+
failedTools.push(tool.name);
|
|
124
|
+
}
|
|
41
125
|
}
|
|
42
|
-
|
|
43
|
-
|
|
126
|
+
step(2, 2, 'Done!');
|
|
127
|
+
if (configuredTools.length > 0) {
|
|
128
|
+
successBox('Kora MCP Server successfully installed!', [
|
|
129
|
+
chalk.white('We added Kora to the following tools:'),
|
|
130
|
+
...configuredTools.map(t => chalk.green(` ✓ ${t}`)),
|
|
131
|
+
'',
|
|
132
|
+
chalk.yellow('⚠ Please restart these tools for the changes to take effect.'),
|
|
133
|
+
'',
|
|
134
|
+
'After restarting, try saying:',
|
|
135
|
+
chalk.cyan(' "save this as a learning: [your insight]"'),
|
|
136
|
+
].join('\n'));
|
|
44
137
|
}
|
|
45
138
|
else {
|
|
46
|
-
|
|
139
|
+
errorBox('We couldn\'t find any supported AI tools on your system.\n' +
|
|
140
|
+
chalk.white('Searched for: ') + TOOLS.map(t => t.name).join(', ') + '\n\n' +
|
|
141
|
+
'You can still set up Kora manually. Add this to your MCP config:\n' +
|
|
142
|
+
` Command: ${chalk.cyan('npx')}\n` +
|
|
143
|
+
` Args: ${chalk.cyan('["kora", "serve"]')}`);
|
|
144
|
+
}
|
|
145
|
+
if (failedTools.length > 0) {
|
|
146
|
+
console.log(chalk.red('\nFailed to update: ') + failedTools.join(', '));
|
|
47
147
|
}
|
|
48
148
|
});
|
|
49
149
|
}
|
|
50
|
-
|
|
51
|
-
const
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
150
|
+
function setupTool(name, configPath, type) {
|
|
151
|
+
const koraConfig = {
|
|
152
|
+
command: 'npx',
|
|
153
|
+
args: ['kora', 'serve']
|
|
154
|
+
};
|
|
155
|
+
if (type === 'json-mcpServers' || type === 'json-mcp') {
|
|
156
|
+
let existing = {};
|
|
157
|
+
if (fs.existsSync(configPath)) {
|
|
158
|
+
try {
|
|
159
|
+
existing = JSON.parse(fs.readFileSync(configPath, 'utf-8'));
|
|
160
|
+
}
|
|
161
|
+
catch {
|
|
162
|
+
// Start fresh warning if corrupted, assume empty
|
|
163
|
+
existing = {};
|
|
164
|
+
}
|
|
62
165
|
}
|
|
63
|
-
|
|
64
|
-
|
|
166
|
+
const key = type === 'json-mcp' ? 'mcp' : 'mcpServers';
|
|
167
|
+
existing[key] = existing[key] || {};
|
|
168
|
+
// Don't overwrite if it already exists perfectly
|
|
169
|
+
if (existing[key].kora?.command === 'npx' && existing[key].kora?.args?.includes('kora')) {
|
|
170
|
+
return true;
|
|
65
171
|
}
|
|
172
|
+
existing[key].kora = koraConfig;
|
|
173
|
+
fs.writeFileSync(configPath, JSON.stringify(existing, null, 2));
|
|
174
|
+
return true;
|
|
66
175
|
}
|
|
67
|
-
if (
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
176
|
+
else if (type === 'toml-block') {
|
|
177
|
+
let content = '';
|
|
178
|
+
if (fs.existsSync(configPath)) {
|
|
179
|
+
content = fs.readFileSync(configPath, 'utf-8');
|
|
180
|
+
}
|
|
181
|
+
if (content.includes('[mcpServers.kora]')) {
|
|
182
|
+
return true;
|
|
183
|
+
}
|
|
184
|
+
const addition = `\n\n[mcpServers.kora]\ncommand = "npx"\nargs = ["kora", "serve"]\n`;
|
|
185
|
+
fs.appendFileSync(configPath, addition);
|
|
186
|
+
return true;
|
|
76
187
|
}
|
|
77
|
-
|
|
78
|
-
existing.mcpServers = existing.mcpServers || {};
|
|
79
|
-
existing.mcpServers.kora = {
|
|
80
|
-
command: 'npx',
|
|
81
|
-
args: ['kora', 'serve'],
|
|
82
|
-
};
|
|
83
|
-
fs.mkdirSync(path.dirname(configPath), { recursive: true });
|
|
84
|
-
fs.writeFileSync(configPath, JSON.stringify(existing, null, 2));
|
|
85
|
-
step(3, 3, 'Done!');
|
|
86
|
-
successBox('Claude Desktop configured!', [
|
|
87
|
-
`Config written to: ${chalk.dim(configPath)}`,
|
|
88
|
-
'',
|
|
89
|
-
chalk.yellow('⚠ Restart Claude Desktop to activate Kora.'),
|
|
90
|
-
'',
|
|
91
|
-
'After restarting, try saying:',
|
|
92
|
-
chalk.cyan(' "save this as a learning: [your insight]"'),
|
|
93
|
-
].join('\n'));
|
|
94
|
-
}
|
|
95
|
-
function showCursorInstructions() {
|
|
96
|
-
infoBox('Cursor Setup', [
|
|
97
|
-
'Add this to your Cursor MCP settings:',
|
|
98
|
-
'',
|
|
99
|
-
chalk.cyan(JSON.stringify({
|
|
100
|
-
kora: {
|
|
101
|
-
command: 'npx',
|
|
102
|
-
args: ['kora', 'serve'],
|
|
103
|
-
},
|
|
104
|
-
}, null, 2)),
|
|
105
|
-
'',
|
|
106
|
-
'Or add it to your project\'s .cursor/mcp.json file.',
|
|
107
|
-
].join('\n'));
|
|
108
|
-
}
|
|
109
|
-
function showManualInstructions() {
|
|
110
|
-
infoBox('Manual Setup', [
|
|
111
|
-
'Add this MCP server config to your AI tool:',
|
|
112
|
-
'',
|
|
113
|
-
` Command: ${chalk.cyan('npx')}`,
|
|
114
|
-
` Args: ${chalk.cyan('["kora", "serve"]')}`,
|
|
115
|
-
'',
|
|
116
|
-
'The MCP server communicates over stdio.',
|
|
117
|
-
].join('\n'));
|
|
188
|
+
return false;
|
|
118
189
|
}
|
|
119
190
|
//# sourceMappingURL=init.js.map
|
package/dist/src/cli/init.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"init.js","sourceRoot":"","sources":["../../../src/cli/init.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,
|
|
1
|
+
{"version":3,"file":"init.js","sourceRoot":"","sources":["../../../src/cli/init.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sync.d.ts","sourceRoot":"","sources":["../../../src/cli/sync.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAMpC,wBAAgB,WAAW,CAAC,OAAO,EAAE,OAAO,QAyC3C"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import chalk from 'chalk';
|
|
2
|
+
import { readConfig } from '../config.js';
|
|
3
|
+
import { getDb, retryUnsynced } from '../storage/sqlite.js';
|
|
4
|
+
import { showHeader, spinner, successBox, errorBox } from '../ui.js';
|
|
5
|
+
export function syncCommand(program) {
|
|
6
|
+
program
|
|
7
|
+
.command('sync')
|
|
8
|
+
.description('Manually sync pending learnings to Notion')
|
|
9
|
+
.action(async () => {
|
|
10
|
+
showHeader('sync');
|
|
11
|
+
const config = readConfig();
|
|
12
|
+
if (!config.key) {
|
|
13
|
+
errorBox('Not logged in. Run `kora login` first.');
|
|
14
|
+
return;
|
|
15
|
+
}
|
|
16
|
+
if (!config.hasNotion) {
|
|
17
|
+
errorBox('Notion not connected. Run `kora notion` first.');
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
const db = getDb();
|
|
21
|
+
const count = db.prepare('SELECT COUNT(*) as n FROM learnings WHERE synced = 0').get().n;
|
|
22
|
+
if (count === 0) {
|
|
23
|
+
successBox('All caught up', 'No pending learnings to sync.');
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
const spin = spinner(`Syncing ${count} learning${count === 1 ? '' : 's'} to Notion...`);
|
|
27
|
+
spin.start();
|
|
28
|
+
await retryUnsynced(config.key, 'manual');
|
|
29
|
+
const remaining = db.prepare('SELECT COUNT(*) as n FROM learnings WHERE synced = 0').get().n;
|
|
30
|
+
if (remaining === 0) {
|
|
31
|
+
spin.succeed('Sync complete!');
|
|
32
|
+
console.log(chalk.dim(` Synced ${count} learning${count === 1 ? '' : 's'} successfully.\n`));
|
|
33
|
+
}
|
|
34
|
+
else {
|
|
35
|
+
spin.fail('Partial sync');
|
|
36
|
+
console.log(chalk.red(` Failed to sync ${remaining} learning${remaining === 1 ? '' : 's'}. Try again later.\n`));
|
|
37
|
+
}
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
//# sourceMappingURL=sync.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sync.js","sourceRoot":"","sources":["../../../src/cli/sync.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,EAAE,KAAK,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAC5D,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AAErE,MAAM,UAAU,WAAW,CAAC,OAAgB;IACxC,OAAO;SACF,OAAO,CAAC,MAAM,CAAC;SACf,WAAW,CAAC,2CAA2C,CAAC;SACxD,MAAM,CAAC,KAAK,IAAI,EAAE;QACf,UAAU,CAAC,MAAM,CAAC,CAAC;QAEnB,MAAM,MAAM,GAAG,UAAU,EAAE,CAAC;QAC5B,IAAI,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC;YACd,QAAQ,CAAC,wCAAwC,CAAC,CAAC;YACnD,OAAO;QACX,CAAC;QAED,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC;YACpB,QAAQ,CAAC,gDAAgD,CAAC,CAAC;YAC3D,OAAO;QACX,CAAC;QAED,MAAM,EAAE,GAAG,KAAK,EAAE,CAAC;QACnB,MAAM,KAAK,GAAI,EAAE,CAAC,OAAO,CAAC,sDAAsD,CAAC,CAAC,GAAG,EAAU,CAAC,CAAC,CAAC;QAElG,IAAI,KAAK,KAAK,CAAC,EAAE,CAAC;YACd,UAAU,CAAC,eAAe,EAAE,+BAA+B,CAAC,CAAC;YAC7D,OAAO;QACX,CAAC;QAED,MAAM,IAAI,GAAG,OAAO,CAAC,WAAW,KAAK,YAAY,KAAK,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,eAAe,CAAC,CAAC;QACxF,IAAI,CAAC,KAAK,EAAE,CAAC;QAEb,MAAM,aAAa,CAAC,MAAM,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC;QAE1C,MAAM,SAAS,GAAI,EAAE,CAAC,OAAO,CAAC,sDAAsD,CAAC,CAAC,GAAG,EAAU,CAAC,CAAC,CAAC;QAEtG,IAAI,SAAS,KAAK,CAAC,EAAE,CAAC;YAClB,IAAI,CAAC,OAAO,CAAC,gBAAgB,CAAC,CAAC;YAC/B,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,YAAY,KAAK,YAAY,KAAK,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,kBAAkB,CAAC,CAAC,CAAC;QAClG,CAAC;aAAM,CAAC;YACJ,IAAI,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;YAC1B,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,oBAAoB,SAAS,YAAY,SAAS,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,sBAAsB,CAAC,CAAC,CAAC;QACtH,CAAC;IACL,CAAC,CAAC,CAAC;AACX,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../../../src/mcp/tools.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAUpE,wBAAgB,aAAa,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,OAAO,CAAA;CAAE,
|
|
1
|
+
{"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../../../src/mcp/tools.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAUpE,wBAAgB,aAAa,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,OAAO,CAAA;CAAE,QAwX3F"}
|
package/dist/src/mcp/tools.js
CHANGED
|
@@ -3,18 +3,21 @@ import { ulid } from 'ulid';
|
|
|
3
3
|
import { getDb, retryUnsynced } from '../storage/sqlite.js';
|
|
4
4
|
import { validateKey } from '../auth.js';
|
|
5
5
|
function bgSync(key) {
|
|
6
|
-
retryUnsynced(key).catch(() => { });
|
|
6
|
+
retryUnsynced(key, 'auto').catch(() => { });
|
|
7
7
|
}
|
|
8
8
|
export function registerTools(server, config) {
|
|
9
9
|
// ── save_learning ──────────────────────────────────────────────
|
|
10
|
-
server.
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
10
|
+
server.registerTool('save_learning', {
|
|
11
|
+
description: [
|
|
12
|
+
'Save a learning from the current session.',
|
|
13
|
+
'Use this whenever the user discovers an insight, makes a mistake, ships something, or learns a lesson worth sharing.',
|
|
14
|
+
'Call this proactively when you notice something worth capturing — do not wait to be asked.',
|
|
15
|
+
].join(' '),
|
|
16
|
+
inputSchema: {
|
|
17
|
+
raw: z.string().describe('The raw insight or learning in the user\'s own words'),
|
|
18
|
+
tags: z.array(z.enum(['win', 'mistake', 'lesson', 'shipit'])).optional(),
|
|
19
|
+
project: z.string().optional().describe('Current project name'),
|
|
20
|
+
},
|
|
18
21
|
}, async ({ raw, tags = [], project }) => {
|
|
19
22
|
await validateKey(config.key, 'save_learning');
|
|
20
23
|
bgSync(config.key);
|
|
@@ -34,19 +37,23 @@ export function registerTools(server, config) {
|
|
|
34
37
|
`Tags: ${tags.length ? tags.join(', ') : 'none'}`,
|
|
35
38
|
`Total learnings: ${total}`,
|
|
36
39
|
'',
|
|
37
|
-
'
|
|
38
|
-
'
|
|
39
|
-
'
|
|
40
|
-
'
|
|
40
|
+
'To create content from this:',
|
|
41
|
+
'"draft a post for X from my last learning"',
|
|
42
|
+
'"draft a LinkedIn post from this"',
|
|
43
|
+
'"draft a Reddit post about this mistake"',
|
|
44
|
+
'"write a Show HN post about what I built today"',
|
|
41
45
|
].join('\n'),
|
|
42
46
|
}],
|
|
43
47
|
};
|
|
44
48
|
});
|
|
45
49
|
// ── list_learnings ─────────────────────────────────────────────
|
|
46
|
-
server.
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
+
server.registerTool('list_learnings', {
|
|
51
|
+
description: 'Browse saved learnings. Returns a list of learnings with IDs for use in draft_post and draft_thread.',
|
|
52
|
+
inputSchema: {
|
|
53
|
+
tag: z.enum(['win', 'mistake', 'lesson', 'shipit']).optional(),
|
|
54
|
+
limit: z.number().min(1).max(50).optional().default(10),
|
|
55
|
+
since: z.string().optional().describe("'7d', '30d', or ISO date"),
|
|
56
|
+
},
|
|
50
57
|
}, async ({ tag, limit, since }) => {
|
|
51
58
|
await validateKey(config.key, 'list_learnings');
|
|
52
59
|
bgSync(config.key);
|
|
@@ -80,7 +87,7 @@ export function registerTools(server, config) {
|
|
|
80
87
|
return [
|
|
81
88
|
`${i + 1}. ID: ${r.id}`,
|
|
82
89
|
` "${r.raw}"`,
|
|
83
|
-
` Tags: ${tags.join(', ') || 'none'} | ${new Date(r.created_at).toLocaleDateString()} | ${r.tweet_draft ? '
|
|
90
|
+
` Tags: ${tags.join(', ') || 'none'} | ${new Date(r.created_at).toLocaleDateString()} | ${r.tweet_draft ? 'drafted ✓' : 'no draft yet'}`,
|
|
84
91
|
].join('\n');
|
|
85
92
|
}).join('\n\n');
|
|
86
93
|
return {
|
|
@@ -90,21 +97,36 @@ export function registerTools(server, config) {
|
|
|
90
97
|
`${rows.length} learning${rows.length === 1 ? '' : 's'} found:\n`,
|
|
91
98
|
formatted,
|
|
92
99
|
'',
|
|
93
|
-
'Use these IDs with
|
|
100
|
+
'Use these IDs with draft_post or draft_thread.',
|
|
101
|
+
'- "draft a post for X from this learning" — turn it into a tweet',
|
|
102
|
+
'- "draft a Reddit post from this learning" — format for r/startups',
|
|
103
|
+
'- "draft a LinkedIn post from this learning" — professional format',
|
|
104
|
+
'- "draft a Show HN post from this learning" — Hacker News format',
|
|
94
105
|
].join('\n'),
|
|
95
106
|
}],
|
|
96
107
|
};
|
|
97
108
|
});
|
|
98
|
-
// ──
|
|
99
|
-
server.
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
109
|
+
// ── draft_post ─────────────────────────────────────────────────
|
|
110
|
+
server.registerTool('draft_post', {
|
|
111
|
+
description: [
|
|
112
|
+
'Fetch a saved learning and return it formatted for the AI to draft a social media post.',
|
|
113
|
+
'Works for X/Twitter, Reddit, LinkedIn, Hacker News, newsletter, and Bluesky formats.',
|
|
114
|
+
'After getting this tool result, immediately write the post — do not ask for more input.',
|
|
115
|
+
].join(' '),
|
|
116
|
+
inputSchema: {
|
|
117
|
+
id: z.string().describe('Learning ID from list_learnings. Use "last" to get the most recent.'),
|
|
118
|
+
platform: z.enum([
|
|
119
|
+
'twitter',
|
|
120
|
+
'reddit',
|
|
121
|
+
'linkedin',
|
|
122
|
+
'hackernews',
|
|
123
|
+
'newsletter',
|
|
124
|
+
'bluesky',
|
|
125
|
+
]).optional().default('twitter'),
|
|
126
|
+
style: z.enum(['hook', 'story', 'tip', 'hot-take']).optional().default('hook'),
|
|
127
|
+
},
|
|
128
|
+
}, async ({ id, platform, style }) => {
|
|
129
|
+
await validateKey(config.key, 'draft_post');
|
|
108
130
|
bgSync(config.key);
|
|
109
131
|
const db = getDb();
|
|
110
132
|
const learning = id === 'last'
|
|
@@ -119,45 +141,146 @@ export function registerTools(server, config) {
|
|
|
119
141
|
};
|
|
120
142
|
}
|
|
121
143
|
const tags = JSON.parse(learning.tags || '[]');
|
|
144
|
+
const PLATFORM_GUIDES = {
|
|
145
|
+
twitter: [
|
|
146
|
+
'## Draft a tweet from this learning',
|
|
147
|
+
'',
|
|
148
|
+
`Learning: "${learning.raw}"`,
|
|
149
|
+
`Tags: ${tags.join(', ') || 'none'}`,
|
|
150
|
+
`Style: ${style}`,
|
|
151
|
+
'',
|
|
152
|
+
'## Tweet drafting rules',
|
|
153
|
+
'- Under 280 characters',
|
|
154
|
+
'- First line must be a hook that stops scrolling',
|
|
155
|
+
'- One concrete insight only — no padding or fluff',
|
|
156
|
+
'- Sound like a real builder, not a marketer',
|
|
157
|
+
'- No buzzwords (game-changer, revolutionary, unlock, etc)',
|
|
158
|
+
'- No emojis unless they genuinely add meaning',
|
|
159
|
+
'- No hashtags',
|
|
160
|
+
'- End with something that makes people want to follow',
|
|
161
|
+
'',
|
|
162
|
+
'## Style guide',
|
|
163
|
+
'hook: Bold opening statement that challenges a common assumption',
|
|
164
|
+
'story: "I did X, it went wrong/right, here\'s what I learned"',
|
|
165
|
+
'tip: Direct actionable advice from first-hand experience',
|
|
166
|
+
'hot-take: Controversial but defensible opinion from your experience',
|
|
167
|
+
'',
|
|
168
|
+
'Now write the tweet. Output only the tweet text, nothing else.',
|
|
169
|
+
].join('\n'),
|
|
170
|
+
reddit: [
|
|
171
|
+
'## Draft a Reddit post from this learning',
|
|
172
|
+
'',
|
|
173
|
+
`Learning: "${learning.raw}"`,
|
|
174
|
+
`Tags: ${tags.join(', ') || 'none'}`,
|
|
175
|
+
'',
|
|
176
|
+
'## Rules',
|
|
177
|
+
'- Write a compelling title (max 300 chars)',
|
|
178
|
+
'- Body is 2-4 paragraphs, conversational',
|
|
179
|
+
'- Tell the story — what happened, what you learned',
|
|
180
|
+
'- End with a question to spark discussion',
|
|
181
|
+
'- Suggest a subreddit: r/startups, r/SideProject, r/Entrepreneur, r/indiehackers',
|
|
182
|
+
'',
|
|
183
|
+
'## Format',
|
|
184
|
+
'Title: [your title]',
|
|
185
|
+
'',
|
|
186
|
+
'[body paragraphs]',
|
|
187
|
+
'',
|
|
188
|
+
'Suggested subreddit: r/[name]',
|
|
189
|
+
'',
|
|
190
|
+
'Output only the post. Nothing else.',
|
|
191
|
+
].join('\n'),
|
|
192
|
+
linkedin: [
|
|
193
|
+
'## Draft a LinkedIn post from this learning',
|
|
194
|
+
'',
|
|
195
|
+
`Learning: "${learning.raw}"`,
|
|
196
|
+
`Tags: ${tags.join(', ') || 'none'}`,
|
|
197
|
+
'',
|
|
198
|
+
'## Rules',
|
|
199
|
+
'- Professional but human tone — not corporate speak',
|
|
200
|
+
'- 3-5 short paragraphs',
|
|
201
|
+
'- Start with a bold first line that hooks',
|
|
202
|
+
'- Include the lesson clearly',
|
|
203
|
+
'- End with an insight or question',
|
|
204
|
+
'- No hashtag spam (max 2 if needed)',
|
|
205
|
+
'- 150-300 words ideal',
|
|
206
|
+
'',
|
|
207
|
+
'Output only the post. Nothing else.',
|
|
208
|
+
].join('\n'),
|
|
209
|
+
hackernews: [
|
|
210
|
+
'## Draft a Hacker News post from this learning',
|
|
211
|
+
'',
|
|
212
|
+
`Learning: "${learning.raw}"`,
|
|
213
|
+
`Tags: ${tags.join(', ') || 'none'}`,
|
|
214
|
+
'',
|
|
215
|
+
'## Rules',
|
|
216
|
+
'- Decide: is this a Show HN, Ask HN, or regular submission?',
|
|
217
|
+
'- Title is factual, specific, non-clickbait',
|
|
218
|
+
'- Body (for Ask/Show HN) is 2-3 paragraphs max',
|
|
219
|
+
'- Technical and honest tone',
|
|
220
|
+
'- No marketing language whatsoever',
|
|
221
|
+
'- HN readers value substance over story',
|
|
222
|
+
'',
|
|
223
|
+
'## Format',
|
|
224
|
+
'Type: [Show HN / Ask HN / Submission]',
|
|
225
|
+
'Title: [your title]',
|
|
226
|
+
'',
|
|
227
|
+
'[body if Ask HN or Show HN]',
|
|
228
|
+
'',
|
|
229
|
+
'Output only the post. Nothing else.',
|
|
230
|
+
].join('\n'),
|
|
231
|
+
newsletter: [
|
|
232
|
+
'## Draft a newsletter section from this learning',
|
|
233
|
+
'',
|
|
234
|
+
`Learning: "${learning.raw}"`,
|
|
235
|
+
`Tags: ${tags.join(', ') || 'none'}`,
|
|
236
|
+
'',
|
|
237
|
+
'## Rules',
|
|
238
|
+
'- 1-3 paragraphs, flows as a standalone section',
|
|
239
|
+
'- Conversational, first-person',
|
|
240
|
+
'- Start with what happened',
|
|
241
|
+
'- Middle: the insight or lesson',
|
|
242
|
+
'- End: why it matters to the reader',
|
|
243
|
+
'- 100-250 words',
|
|
244
|
+
'- Could have a heading (##) or stand alone without one',
|
|
245
|
+
'',
|
|
246
|
+
'Output only the newsletter section. Nothing else.',
|
|
247
|
+
].join('\n'),
|
|
248
|
+
bluesky: [
|
|
249
|
+
'## Draft a Bluesky post from this learning',
|
|
250
|
+
'',
|
|
251
|
+
`Learning: "${learning.raw}"`,
|
|
252
|
+
`Tags: ${tags.join(', ') || 'none'}`,
|
|
253
|
+
`Style: ${style}`,
|
|
254
|
+
'',
|
|
255
|
+
'## Rules',
|
|
256
|
+
'- Under 300 characters (Bluesky limit)',
|
|
257
|
+
'- Slightly more casual and community-first than Twitter',
|
|
258
|
+
'- Same hook principles but warmer tone',
|
|
259
|
+
'- No hashtag spam',
|
|
260
|
+
'- Threads work well on Bluesky if one post isn\'t enough',
|
|
261
|
+
'',
|
|
262
|
+
'Output only the post text. Nothing else.',
|
|
263
|
+
].join('\n'),
|
|
264
|
+
};
|
|
265
|
+
const guide = PLATFORM_GUIDES[platform] || PLATFORM_GUIDES.twitter;
|
|
122
266
|
return {
|
|
123
267
|
content: [{
|
|
124
268
|
type: 'text',
|
|
125
|
-
text:
|
|
126
|
-
'## Draft a tweet from this learning',
|
|
127
|
-
'',
|
|
128
|
-
`Learning: "${learning.raw}"`,
|
|
129
|
-
`Tags: ${tags.join(', ') || 'none'}`,
|
|
130
|
-
`Style: ${style}`,
|
|
131
|
-
'',
|
|
132
|
-
'## Tweet drafting rules',
|
|
133
|
-
'- Under 280 characters',
|
|
134
|
-
'- First line must be a hook that stops scrolling',
|
|
135
|
-
'- One concrete insight only — no padding or fluff',
|
|
136
|
-
'- Sound like a real builder, not a marketer',
|
|
137
|
-
'- No buzzwords (game-changer, revolutionary, unlock, etc)',
|
|
138
|
-
'- No emojis unless they genuinely add meaning',
|
|
139
|
-
'- No hashtags',
|
|
140
|
-
'- End with something that makes people want to follow',
|
|
141
|
-
'',
|
|
142
|
-
'## Style guide',
|
|
143
|
-
'hook: Bold opening statement that challenges a common assumption',
|
|
144
|
-
'story: "I did X, it went wrong/right, here\'s what I learned"',
|
|
145
|
-
'tip: Direct actionable advice from first-hand experience',
|
|
146
|
-
'hot-take: Controversial but defensible opinion from your experience',
|
|
147
|
-
'',
|
|
148
|
-
'Now write the tweet. Output only the tweet text, nothing else.',
|
|
149
|
-
].join('\n'),
|
|
269
|
+
text: guide,
|
|
150
270
|
}],
|
|
151
271
|
};
|
|
152
272
|
});
|
|
153
273
|
// ── draft_thread ───────────────────────────────────────────────
|
|
154
|
-
server.
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
274
|
+
server.registerTool('draft_thread', {
|
|
275
|
+
description: [
|
|
276
|
+
'Fetch multiple saved learnings and return them formatted for the AI to turn into an X thread.',
|
|
277
|
+
'The AI should draft a numbered thread with a hook tweet at the top.',
|
|
278
|
+
'After getting this tool result, immediately write the thread — do not ask the user for more input.',
|
|
279
|
+
].join(' '),
|
|
280
|
+
inputSchema: {
|
|
281
|
+
ids: z.array(z.string()).describe('Learning IDs. Pass ["last5"] to auto-select 5 most recent.'),
|
|
282
|
+
topic: z.string().optional().describe('Optional theme or title for the thread'),
|
|
283
|
+
},
|
|
161
284
|
}, async ({ ids, topic }) => {
|
|
162
285
|
await validateKey(config.key, 'draft_thread');
|
|
163
286
|
bgSync(config.key);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tools.js","sourceRoot":"","sources":["../../../src/mcp/tools.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAC5B,OAAO,EAAE,KAAK,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAC5D,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAEzC,SAAS,MAAM,CAAC,GAAW;IACzB,aAAa,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,
|
|
1
|
+
{"version":3,"file":"tools.js","sourceRoot":"","sources":["../../../src/mcp/tools.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import Database from 'better-sqlite3';
|
|
2
2
|
export declare function initDb(): void;
|
|
3
3
|
export declare function getDb(): Database.Database;
|
|
4
|
-
export declare function retryUnsynced(apiKey: string): Promise<void>;
|
|
4
|
+
export declare function retryUnsynced(apiKey: string, source?: 'auto' | 'manual'): Promise<void>;
|
|
5
5
|
//# sourceMappingURL=sqlite.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sqlite.d.ts","sourceRoot":"","sources":["../../../src/storage/sqlite.ts"],"names":[],"mappings":"AAAA,OAAO,QAAQ,MAAM,gBAAgB,CAAC;AAUtC,wBAAgB,MAAM,SAkBrB;AAED,wBAAgB,KAAK,IAAI,QAAQ,CAAC,QAAQ,CAGzC;AAED,wBAAsB,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"sqlite.d.ts","sourceRoot":"","sources":["../../../src/storage/sqlite.ts"],"names":[],"mappings":"AAAA,OAAO,QAAQ,MAAM,gBAAgB,CAAC;AAUtC,wBAAgB,MAAM,SAkBrB;AAED,wBAAgB,KAAK,IAAI,QAAQ,CAAC,QAAQ,CAGzC;AAED,wBAAsB,aAAa,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,GAAE,MAAM,GAAG,QAAiB,GAAG,OAAO,CAAC,IAAI,CAAC,CAuBrG"}
|
|
@@ -29,7 +29,7 @@ export function getDb() {
|
|
|
29
29
|
initDb();
|
|
30
30
|
return db;
|
|
31
31
|
}
|
|
32
|
-
export async function retryUnsynced(apiKey) {
|
|
32
|
+
export async function retryUnsynced(apiKey, source = 'auto') {
|
|
33
33
|
const database = getDb();
|
|
34
34
|
const pending = database.prepare('SELECT * FROM learnings WHERE synced = 0 LIMIT 10').all();
|
|
35
35
|
for (const learning of pending) {
|
|
@@ -37,7 +37,7 @@ export async function retryUnsynced(apiKey) {
|
|
|
37
37
|
const res = await fetch('https://trykora.xyz/api/sync', {
|
|
38
38
|
method: 'POST',
|
|
39
39
|
headers: { 'Content-Type': 'application/json' },
|
|
40
|
-
body: JSON.stringify({ key: apiKey, learning }),
|
|
40
|
+
body: JSON.stringify({ key: apiKey, learning, source }),
|
|
41
41
|
});
|
|
42
42
|
const { success, notionId } = await res.json();
|
|
43
43
|
if (success) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sqlite.js","sourceRoot":"","sources":["../../../src/storage/sqlite.ts"],"names":[],"mappings":"AAAA,OAAO,QAAQ,MAAM,gBAAgB,CAAC;AACtC,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,EAAE,MAAM,IAAI,CAAC;AAEpB,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,OAAO,CAAC,CAAC;AAChD,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;AAElD,IAAI,EAAqB,CAAC;AAE1B,MAAM,UAAU,MAAM;IACpB,EAAE,CAAC,SAAS,CAAC,MAAM,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC1C,EAAE,GAAG,IAAI,QAAQ,CAAC,OAAO,CAAC,CAAC;IAC3B,EAAE,CAAC,IAAI,CAAC;;;;;;;;;;;;;;GAcP,CAAC,CAAC;AACL,CAAC;AAED,MAAM,UAAU,KAAK;IACnB,IAAI,CAAC,EAAE;QAAE,MAAM,EAAE,CAAC;IAClB,OAAO,EAAE,CAAC;AACZ,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,MAAc;
|
|
1
|
+
{"version":3,"file":"sqlite.js","sourceRoot":"","sources":["../../../src/storage/sqlite.ts"],"names":[],"mappings":"AAAA,OAAO,QAAQ,MAAM,gBAAgB,CAAC;AACtC,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,EAAE,MAAM,IAAI,CAAC;AAEpB,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,OAAO,CAAC,CAAC;AAChD,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;AAElD,IAAI,EAAqB,CAAC;AAE1B,MAAM,UAAU,MAAM;IACpB,EAAE,CAAC,SAAS,CAAC,MAAM,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC1C,EAAE,GAAG,IAAI,QAAQ,CAAC,OAAO,CAAC,CAAC;IAC3B,EAAE,CAAC,IAAI,CAAC;;;;;;;;;;;;;;GAcP,CAAC,CAAC;AACL,CAAC;AAED,MAAM,UAAU,KAAK;IACnB,IAAI,CAAC,EAAE;QAAE,MAAM,EAAE,CAAC;IAClB,OAAO,EAAE,CAAC;AACZ,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,MAAc,EAAE,SAA4B,MAAM;IACpF,MAAM,QAAQ,GAAG,KAAK,EAAE,CAAC;IACzB,MAAM,OAAO,GAAG,QAAQ,CAAC,OAAO,CAC9B,mDAAmD,CACpD,CAAC,GAAG,EAAW,CAAC;IAEjB,KAAK,MAAM,QAAQ,IAAI,OAAO,EAAE,CAAC;QAC/B,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,8BAA8B,EAAE;gBACtD,MAAM,EAAE,MAAM;gBACd,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;gBAC/C,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC;aACxD,CAAC,CAAC;YACH,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE,GAAG,MAAM,GAAG,CAAC,IAAI,EAAS,CAAC;YACtD,IAAI,OAAO,EAAE,CAAC;gBACZ,QAAQ,CAAC,OAAO,CACd,6DAA6D,CAC9D,CAAC,GAAG,CAAC,QAAQ,EAAE,QAAQ,CAAC,EAAE,CAAC,CAAC;YAC/B,CAAC;QACH,CAAC;QAAC,MAAM,CAAC;YACP,qCAAqC;QACvC,CAAC;IACH,CAAC;AACH,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "trykora",
|
|
3
|
-
"version": "1.0
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "1.2.0",
|
|
4
|
+
"description": "Grow your audience while you build — capture insights and turn them into X, Reddit, LinkedIn, and HN posts inside any AI tool",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
7
7
|
"trykora": "./dist/bin/kora.js",
|