studiograph 1.1.1 → 1.1.3
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 +191 -0
- package/README.md +307 -10
- package/dist/agent/orchestrator.d.ts +17 -9
- package/dist/agent/orchestrator.js +95 -95
- package/dist/agent/orchestrator.js.map +1 -1
- package/dist/agent/prompts/system.md +168 -0
- package/dist/agent/skills/bundled/enrich-entities.md +124 -0
- package/dist/agent/skills/bundled/gather-context.md +46 -0
- package/dist/agent/skills/skill-loader.d.ts +48 -0
- package/dist/agent/skills/skill-loader.js +166 -0
- package/dist/agent/skills/skill-loader.js.map +1 -0
- package/dist/agent/tools/graph-tools.d.ts +20 -2
- package/dist/agent/tools/graph-tools.js +64 -8
- package/dist/agent/tools/graph-tools.js.map +1 -1
- package/dist/agent/tools/load-skill.d.ts +42 -0
- package/dist/agent/tools/load-skill.js +45 -0
- package/dist/agent/tools/load-skill.js.map +1 -0
- package/dist/agent/tools/tool-loader.d.ts +25 -0
- package/dist/agent/tools/tool-loader.js +73 -0
- package/dist/agent/tools/tool-loader.js.map +1 -0
- package/dist/cli/commands/app.d.ts +7 -0
- package/dist/cli/commands/app.js +167 -0
- package/dist/cli/commands/app.js.map +1 -0
- package/dist/cli/commands/config.d.ts +13 -0
- package/dist/cli/commands/config.js +276 -0
- package/dist/cli/commands/config.js.map +1 -0
- package/dist/cli/commands/connector.d.ts +33 -0
- package/dist/cli/commands/connector.js +170 -0
- package/dist/cli/commands/connector.js.map +1 -0
- package/dist/cli/commands/deploy.d.ts +11 -0
- package/dist/cli/commands/deploy.js +153 -0
- package/dist/cli/commands/deploy.js.map +1 -0
- package/dist/cli/commands/index.d.ts +15 -0
- package/dist/cli/commands/index.js +117 -0
- package/dist/cli/commands/index.js.map +1 -0
- package/dist/cli/commands/init.js +110 -28
- package/dist/cli/commands/init.js.map +1 -1
- package/dist/cli/commands/join.js +67 -22
- package/dist/cli/commands/join.js.map +1 -1
- package/dist/cli/commands/lint.d.ts +8 -0
- package/dist/cli/commands/lint.js +70 -0
- package/dist/cli/commands/lint.js.map +1 -0
- package/dist/cli/commands/mcp.d.ts +27 -0
- package/dist/cli/commands/mcp.js +56 -0
- package/dist/cli/commands/mcp.js.map +1 -0
- package/dist/cli/commands/provision.d.ts +8 -0
- package/dist/cli/commands/provision.js +112 -0
- package/dist/cli/commands/provision.js.map +1 -0
- package/dist/cli/commands/r2.d.ts +2 -0
- package/dist/cli/commands/r2.js +186 -4
- package/dist/cli/commands/r2.js.map +1 -1
- package/dist/cli/commands/serve.js +47 -2
- package/dist/cli/commands/serve.js.map +1 -1
- package/dist/cli/commands/start.js +210 -71
- package/dist/cli/commands/start.js.map +1 -1
- package/dist/cli/commands/sync.js +4 -4
- package/dist/cli/commands/sync.js.map +1 -1
- package/dist/cli/commands/update.d.ts +8 -0
- package/dist/cli/commands/update.js +155 -0
- package/dist/cli/commands/update.js.map +1 -0
- package/dist/cli/index.js +83 -3
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/scaffolding.d.ts +9 -0
- package/dist/cli/scaffolding.js +288 -0
- package/dist/cli/scaffolding.js.map +1 -0
- package/dist/core/graph.d.ts +12 -1
- package/dist/core/graph.js +147 -78
- package/dist/core/graph.js.map +1 -1
- package/dist/core/migration-runner.d.ts +39 -0
- package/dist/core/migration-runner.js +221 -0
- package/dist/core/migration-runner.js.map +1 -0
- package/dist/core/migration-types.d.ts +101 -0
- package/dist/core/migration-types.js +21 -0
- package/dist/core/migration-types.js.map +1 -0
- package/dist/core/migrations/20260219-formalize-memory-location.d.ts +2 -0
- package/dist/core/migrations/20260219-formalize-memory-location.js +35 -0
- package/dist/core/migrations/20260219-formalize-memory-location.js.map +1 -0
- package/dist/core/migrations/20260220-add-workspace-metadata.d.ts +12 -0
- package/dist/core/migrations/20260220-add-workspace-metadata.js +65 -0
- package/dist/core/migrations/20260220-add-workspace-metadata.js.map +1 -0
- package/dist/core/migrations/20260220-add-workspace-readme.d.ts +11 -0
- package/dist/core/migrations/20260220-add-workspace-readme.js +82 -0
- package/dist/core/migrations/20260220-add-workspace-readme.js.map +1 -0
- package/dist/core/migrations/20260220-migrate-yaml-to-json.d.ts +9 -0
- package/dist/core/migrations/20260220-migrate-yaml-to-json.js +64 -0
- package/dist/core/migrations/20260220-migrate-yaml-to-json.js.map +1 -0
- package/dist/core/migrations/index.d.ts +11 -0
- package/dist/core/migrations/index.js +23 -0
- package/dist/core/migrations/index.js.map +1 -0
- package/dist/core/schema-registry.d.ts +36 -0
- package/dist/core/schema-registry.js +161 -0
- package/dist/core/schema-registry.js.map +1 -0
- package/dist/core/types.d.ts +242 -0
- package/dist/core/types.js +21 -0
- package/dist/core/types.js.map +1 -1
- package/dist/core/user-config.d.ts +10 -0
- package/dist/core/user-config.js +8 -0
- package/dist/core/user-config.js.map +1 -1
- package/dist/core/validation.d.ts +973 -32
- package/dist/core/validation.js +163 -4
- package/dist/core/validation.js.map +1 -1
- package/dist/core/workspace-manager.d.ts +26 -2
- package/dist/core/workspace-manager.js +113 -15
- package/dist/core/workspace-manager.js.map +1 -1
- package/dist/core/workspace.d.ts +8 -7
- package/dist/core/workspace.js +25 -13
- package/dist/core/workspace.js.map +1 -1
- package/dist/mcp/connector-manager.d.ts +61 -0
- package/dist/mcp/connector-manager.js +178 -0
- package/dist/mcp/connector-manager.js.map +1 -0
- package/dist/mcp/connectors/definitions.d.ts +43 -0
- package/dist/mcp/connectors/definitions.js +140 -0
- package/dist/mcp/connectors/definitions.js.map +1 -0
- package/dist/mcp/server.d.ts +11 -0
- package/dist/mcp/server.js +28 -0
- package/dist/mcp/server.js.map +1 -0
- package/dist/mcp/tools.d.ts +14 -0
- package/dist/mcp/tools.js +172 -0
- package/dist/mcp/tools.js.map +1 -0
- package/dist/server/index.js +17 -4
- package/dist/server/index.js.map +1 -1
- package/dist/server/plugin-loader.d.ts +8 -0
- package/dist/server/plugin-loader.js +14 -0
- package/dist/server/plugin-loader.js.map +1 -1
- package/dist/server/routes/graph-api.js +1 -1
- package/dist/server/routes/graph-api.js.map +1 -1
- package/dist/server/routes/webhook.js +33 -0
- package/dist/server/routes/webhook.js.map +1 -1
- package/dist/services/github-provisioner.d.ts +1 -0
- package/dist/services/github-provisioner.js +11 -0
- package/dist/services/github-provisioner.js.map +1 -1
- package/dist/services/lint-service.d.ts +27 -0
- package/dist/services/lint-service.js +76 -0
- package/dist/services/lint-service.js.map +1 -0
- package/dist/services/markdown.d.ts +9 -0
- package/dist/services/markdown.js +23 -2
- package/dist/services/markdown.js.map +1 -1
- package/dist/services/memory-service.d.ts +1 -2
- package/dist/services/memory-service.js +6 -4
- package/dist/services/memory-service.js.map +1 -1
- package/dist/services/vector-service.d.ts +77 -0
- package/dist/services/vector-service.js +280 -0
- package/dist/services/vector-service.js.map +1 -0
- package/dist/utils/version-checker.d.ts +23 -0
- package/dist/utils/version-checker.js +116 -0
- package/dist/utils/version-checker.js.map +1 -0
- package/package.json +10 -6
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* studiograph connector
|
|
3
|
+
*
|
|
4
|
+
* Manage MCP connectors — integrations with third-party MCP servers
|
|
5
|
+
* (Linear, Granola, Slack, etc.) that the Studiograph agent can query on demand.
|
|
6
|
+
*
|
|
7
|
+
* Connector configs are stored at ~/.studiograph/connectors/<name>.json
|
|
8
|
+
* (mode 0600 — tokens never leave your machine).
|
|
9
|
+
*
|
|
10
|
+
* Interactive setup (known connectors):
|
|
11
|
+
* studiograph connector add slack
|
|
12
|
+
* studiograph connector add linear
|
|
13
|
+
*
|
|
14
|
+
* Manual setup (any connector):
|
|
15
|
+
* studiograph connector add linear \
|
|
16
|
+
* --url https://mcp.linear.app/mcp \
|
|
17
|
+
* --token lin_api_xxxx \
|
|
18
|
+
* --description "Linear project management"
|
|
19
|
+
*
|
|
20
|
+
* studiograph connector add granola \
|
|
21
|
+
* --command node \
|
|
22
|
+
* --args "/Users/you/mcp-servers/granola-mcp/dist/index.js" \
|
|
23
|
+
* --description "Granola meeting notes"
|
|
24
|
+
*
|
|
25
|
+
* studiograph connector list
|
|
26
|
+
* studiograph connector remove linear
|
|
27
|
+
*
|
|
28
|
+
* Once added, the connector's tools are available to the agent as
|
|
29
|
+
* <name>__<tool> (e.g. "linear__search_issues", "granola__search_granola_notes").
|
|
30
|
+
* The agent discovers them automatically on the next `studiograph start`.
|
|
31
|
+
*/
|
|
32
|
+
import { Command } from 'commander';
|
|
33
|
+
import { intro, outro, text, password, note, isCancel, cancel } from '@clack/prompts';
|
|
34
|
+
import { ConnectorManager, CONNECTORS_DIR } from '../../mcp/connector-manager.js';
|
|
35
|
+
import { CONNECTOR_DEFINITIONS } from '../../mcp/connectors/definitions.js';
|
|
36
|
+
export const connectorCommand = new Command('connector')
|
|
37
|
+
.description('Manage MCP connectors for third-party service integrations');
|
|
38
|
+
// ── connector add ─────────────────────────────────────────────────────────────
|
|
39
|
+
connectorCommand
|
|
40
|
+
.command('add <name>')
|
|
41
|
+
.description('Add or update a connector')
|
|
42
|
+
.option('--url <url>', 'Remote MCP server URL (http type)')
|
|
43
|
+
.option('--token <token>', 'Bearer token or $ENV_VAR reference (http type)')
|
|
44
|
+
.option('--command <command>', 'Executable to spawn (stdio type, e.g. "node")')
|
|
45
|
+
.option('--args <args...>', 'Arguments for the command (stdio type)')
|
|
46
|
+
.option('--description <desc>', 'Human-readable description')
|
|
47
|
+
.action(async (name, opts) => {
|
|
48
|
+
if (!/^[a-z0-9_-]+$/.test(name)) {
|
|
49
|
+
console.error(`Connector name must be lowercase alphanumeric/dash/underscore. Got: "${name}"`);
|
|
50
|
+
process.exit(1);
|
|
51
|
+
}
|
|
52
|
+
const isHttp = !!(opts.url && opts.token);
|
|
53
|
+
const isStdio = !!opts.command;
|
|
54
|
+
// If no transport flags provided, check for a known connector definition
|
|
55
|
+
if (!isHttp && !isStdio) {
|
|
56
|
+
const def = CONNECTOR_DEFINITIONS[name];
|
|
57
|
+
if (def) {
|
|
58
|
+
await runInteractiveSetup(def);
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
console.error(`Connector "${name}" is not a known connector.`);
|
|
62
|
+
console.error('Provide either --url + --token (http) or --command (stdio).');
|
|
63
|
+
console.error(`Known connectors: ${Object.keys(CONNECTOR_DEFINITIONS).join(', ')}`);
|
|
64
|
+
process.exit(1);
|
|
65
|
+
}
|
|
66
|
+
const config = {
|
|
67
|
+
name,
|
|
68
|
+
description: opts.description,
|
|
69
|
+
...(isStdio
|
|
70
|
+
? { type: 'stdio', command: opts.command, args: opts.args }
|
|
71
|
+
: { type: 'http', url: opts.url, token: opts.token }),
|
|
72
|
+
};
|
|
73
|
+
ConnectorManager.saveConfig(config);
|
|
74
|
+
console.log(`Connector "${name}" saved to ${CONNECTORS_DIR}/${name}.json`);
|
|
75
|
+
console.log(`Tools will be available as ${name}__<tool_name> on the next agent start.`);
|
|
76
|
+
});
|
|
77
|
+
// ── Interactive setup ─────────────────────────────────────────────────────────
|
|
78
|
+
async function runInteractiveSetup(def) {
|
|
79
|
+
intro(`Setting up ${def.label} connector`);
|
|
80
|
+
if (def.docsUrl) {
|
|
81
|
+
note(def.docsUrl, 'Docs');
|
|
82
|
+
}
|
|
83
|
+
// Start with the transport defaults from the definition
|
|
84
|
+
const config = {
|
|
85
|
+
name: def.name,
|
|
86
|
+
description: def.description,
|
|
87
|
+
type: def.type,
|
|
88
|
+
...(def.type === 'stdio'
|
|
89
|
+
? { command: def.command, args: def.args }
|
|
90
|
+
: { url: def.url }),
|
|
91
|
+
};
|
|
92
|
+
// Prompt for each credential field
|
|
93
|
+
for (const field of def.credentialFields) {
|
|
94
|
+
const value = await promptCredentialField(field);
|
|
95
|
+
if (isCancel(value)) {
|
|
96
|
+
cancel('Setup cancelled.');
|
|
97
|
+
process.exit(0);
|
|
98
|
+
}
|
|
99
|
+
applyCredential(config, field.key, value);
|
|
100
|
+
}
|
|
101
|
+
ConnectorManager.saveConfig(config);
|
|
102
|
+
outro(`${def.label} connector saved. Tools available as ${def.name}__<tool_name> on next agent start.`);
|
|
103
|
+
}
|
|
104
|
+
/** Prompt for a single credential field using @clack/prompts. */
|
|
105
|
+
async function promptCredentialField(field) {
|
|
106
|
+
const promptOpts = {
|
|
107
|
+
message: field.label,
|
|
108
|
+
placeholder: field.placeholder,
|
|
109
|
+
hint: field.description,
|
|
110
|
+
validate: field.required
|
|
111
|
+
? (v) => (!v?.trim() ? `${field.label} is required` : undefined)
|
|
112
|
+
: undefined,
|
|
113
|
+
};
|
|
114
|
+
return field.secret ? password(promptOpts) : text(promptOpts);
|
|
115
|
+
}
|
|
116
|
+
/** Write a credential value into the connector config at the given dot-path. */
|
|
117
|
+
function applyCredential(config, key, value) {
|
|
118
|
+
if (key.startsWith('env.')) {
|
|
119
|
+
const envKey = key.slice(4);
|
|
120
|
+
config.env = { ...(config.env ?? {}), [envKey]: value };
|
|
121
|
+
}
|
|
122
|
+
else {
|
|
123
|
+
config[key] = value;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
// ── connector list ────────────────────────────────────────────────────────────
|
|
127
|
+
connectorCommand
|
|
128
|
+
.command('list')
|
|
129
|
+
.description('List configured connectors')
|
|
130
|
+
.action(() => {
|
|
131
|
+
const configs = ConnectorManager.loadConfigs();
|
|
132
|
+
if (configs.length === 0) {
|
|
133
|
+
console.log('No connectors configured.');
|
|
134
|
+
console.log(`Known connectors: ${Object.keys(CONNECTOR_DEFINITIONS).join(', ')}`);
|
|
135
|
+
console.log('Run: studiograph connector add <name>');
|
|
136
|
+
return;
|
|
137
|
+
}
|
|
138
|
+
console.log(`Configured connectors (${configs.length}):\n`);
|
|
139
|
+
for (const c of configs) {
|
|
140
|
+
const type = c.type ?? (c.command ? 'stdio' : 'http');
|
|
141
|
+
console.log(` ${c.name.padEnd(16)} [${type}]`);
|
|
142
|
+
if (type === 'stdio') {
|
|
143
|
+
const cmd = [c.command, ...(c.args ?? [])].join(' ');
|
|
144
|
+
console.log(` ${''.padEnd(16)} ${cmd}`);
|
|
145
|
+
}
|
|
146
|
+
else {
|
|
147
|
+
const tokenDisplay = c.token?.startsWith('$') ? c.token : (c.token?.slice(0, 8) + '…');
|
|
148
|
+
console.log(` ${''.padEnd(16)} ${c.url}`);
|
|
149
|
+
console.log(` ${''.padEnd(16)} token: ${tokenDisplay}`);
|
|
150
|
+
}
|
|
151
|
+
if (c.description)
|
|
152
|
+
console.log(` ${''.padEnd(16)} ${c.description}`);
|
|
153
|
+
console.log();
|
|
154
|
+
}
|
|
155
|
+
});
|
|
156
|
+
// ── connector remove ──────────────────────────────────────────────────────────
|
|
157
|
+
connectorCommand
|
|
158
|
+
.command('remove <name>')
|
|
159
|
+
.description('Remove a connector')
|
|
160
|
+
.action((name) => {
|
|
161
|
+
const removed = ConnectorManager.removeConfig(name);
|
|
162
|
+
if (removed) {
|
|
163
|
+
console.log(`Connector "${name}" removed.`);
|
|
164
|
+
}
|
|
165
|
+
else {
|
|
166
|
+
console.error(`No connector named "${name}" found.`);
|
|
167
|
+
process.exit(1);
|
|
168
|
+
}
|
|
169
|
+
});
|
|
170
|
+
//# sourceMappingURL=connector.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"connector.js","sourceRoot":"","sources":["../../../src/cli/commands/connector.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* studiograph deploy — guided deployment wizard
|
|
3
|
+
*
|
|
4
|
+
* Currently supports Railway. Additional targets (Render, Fly) can be added
|
|
5
|
+
* as subcommands following the same pattern.
|
|
6
|
+
*
|
|
7
|
+
* Usage:
|
|
8
|
+
* studiograph deploy railway
|
|
9
|
+
*/
|
|
10
|
+
import { Command } from 'commander';
|
|
11
|
+
export declare const deployCommand: Command;
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* studiograph deploy — guided deployment wizard
|
|
3
|
+
*
|
|
4
|
+
* Currently supports Railway. Additional targets (Render, Fly) can be added
|
|
5
|
+
* as subcommands following the same pattern.
|
|
6
|
+
*
|
|
7
|
+
* Usage:
|
|
8
|
+
* studiograph deploy railway
|
|
9
|
+
*/
|
|
10
|
+
import { Command } from 'commander';
|
|
11
|
+
import { intro, outro, text, confirm, log, spinner } from '@clack/prompts';
|
|
12
|
+
import { randomBytes } from 'crypto';
|
|
13
|
+
import { spawnSync } from 'child_process';
|
|
14
|
+
import { existsSync, readFileSync } from 'fs';
|
|
15
|
+
import { join } from 'path';
|
|
16
|
+
import { gitClone } from '../../utils/git.js';
|
|
17
|
+
// ── helpers ──────────────────────────────────────────────────────────────────
|
|
18
|
+
function openBrowser(url) {
|
|
19
|
+
const cmd = process.platform === 'darwin' ? 'open' : 'xdg-open';
|
|
20
|
+
spawnSync(cmd, [url], { stdio: 'ignore' });
|
|
21
|
+
}
|
|
22
|
+
function generateSecret() {
|
|
23
|
+
return randomBytes(20).toString('hex');
|
|
24
|
+
}
|
|
25
|
+
/** Inject a GitHub token into an https:// URL for authenticated clone. */
|
|
26
|
+
function authedUrl(url, token) {
|
|
27
|
+
return url.startsWith('https://')
|
|
28
|
+
? url.replace('https://', `https://${token}@`)
|
|
29
|
+
: url;
|
|
30
|
+
}
|
|
31
|
+
function readWorkspaceRepos(configRepoUrl, githubToken) {
|
|
32
|
+
// Clone to a temp path so we can read workspace.json
|
|
33
|
+
const tmpDir = `/tmp/studiograph-deploy-${Date.now()}`;
|
|
34
|
+
try {
|
|
35
|
+
gitClone(authedUrl(configRepoUrl, githubToken), tmpDir);
|
|
36
|
+
const jsonPath = join(tmpDir, 'workspace.json');
|
|
37
|
+
if (!existsSync(jsonPath))
|
|
38
|
+
return [];
|
|
39
|
+
const config = JSON.parse(readFileSync(jsonPath, 'utf-8'));
|
|
40
|
+
return (config.repos ?? []);
|
|
41
|
+
}
|
|
42
|
+
catch {
|
|
43
|
+
return [];
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
// ── deploy command group ──────────────────────────────────────────────────────
|
|
47
|
+
export const deployCommand = new Command('deploy')
|
|
48
|
+
.description('Deploy Studiograph to a hosting platform');
|
|
49
|
+
// ── studiograph deploy railway ────────────────────────────────────────────────
|
|
50
|
+
deployCommand
|
|
51
|
+
.command('railway')
|
|
52
|
+
.description('Guided setup wizard for deploying Studiograph to Railway')
|
|
53
|
+
.action(async () => {
|
|
54
|
+
intro('Deploy Studiograph to Railway');
|
|
55
|
+
log.message('This wizard walks you through deploying Studiograph to Railway in four steps.\n' +
|
|
56
|
+
'You\'ll need a Railway account (railway.app) and your GitHub repos set up.\n');
|
|
57
|
+
// ── Step 1: GitHub token ──────────────────────────────────────────────
|
|
58
|
+
log.step('Step 1 of 4 — GitHub token');
|
|
59
|
+
log.message('Studiograph needs a GitHub fine-grained PAT to clone your private repos at startup.\n' +
|
|
60
|
+
'Opening GitHub → Settings → Developer Settings → Fine-grained personal access tokens...\n\n' +
|
|
61
|
+
' Create a token with these permissions:\n' +
|
|
62
|
+
' Repository access: All repositories (or select specific ones)\n' +
|
|
63
|
+
' Permissions: Contents → Read-only\n');
|
|
64
|
+
openBrowser('https://github.com/settings/personal-access-tokens/new');
|
|
65
|
+
const githubToken = await text({
|
|
66
|
+
message: 'Paste your GitHub token',
|
|
67
|
+
placeholder: 'github_pat_...',
|
|
68
|
+
validate: (v) => v.trim() ? undefined : 'Required',
|
|
69
|
+
});
|
|
70
|
+
if (typeof githubToken === 'symbol') {
|
|
71
|
+
outro('Cancelled');
|
|
72
|
+
process.exit(0);
|
|
73
|
+
}
|
|
74
|
+
// ── Step 2: Configuration ─────────────────────────────────────────────
|
|
75
|
+
log.step('Step 2 of 4 — Workspace configuration');
|
|
76
|
+
const configRepoUrl = await text({
|
|
77
|
+
message: 'Config repo URL (your .studiograph GitHub repo)',
|
|
78
|
+
placeholder: 'https://github.com/your-org/.studiograph.git',
|
|
79
|
+
validate: (v) => v.trim() ? undefined : 'Required',
|
|
80
|
+
});
|
|
81
|
+
if (typeof configRepoUrl === 'symbol') {
|
|
82
|
+
outro('Cancelled');
|
|
83
|
+
process.exit(0);
|
|
84
|
+
}
|
|
85
|
+
const apiKeysInput = await text({
|
|
86
|
+
message: 'API keys for client access (comma-separated, leave blank to skip)',
|
|
87
|
+
placeholder: 'key1,key2',
|
|
88
|
+
});
|
|
89
|
+
if (typeof apiKeysInput === 'symbol') {
|
|
90
|
+
outro('Cancelled');
|
|
91
|
+
process.exit(0);
|
|
92
|
+
}
|
|
93
|
+
const apiKeys = (apiKeysInput || '')
|
|
94
|
+
.split(',')
|
|
95
|
+
.map(k => k.trim())
|
|
96
|
+
.filter(k => k.length > 0)
|
|
97
|
+
.join(';');
|
|
98
|
+
const webhookSecret = generateSecret();
|
|
99
|
+
// ── Step 3: Railway setup ─────────────────────────────────────────────
|
|
100
|
+
log.step('Step 3 of 4 — Railway project setup');
|
|
101
|
+
log.message('Opening Railway — create a new project from this GitHub repo.\n');
|
|
102
|
+
openBrowser('https://railway.app/new');
|
|
103
|
+
log.message('In your Railway project:\n\n' +
|
|
104
|
+
' 1. Add a persistent volume and mount it at /workspace\n\n' +
|
|
105
|
+
' 2. Set the start command:\n' +
|
|
106
|
+
' studiograph serve\n\n' +
|
|
107
|
+
' 3. Set these environment variables:\n\n' +
|
|
108
|
+
` STUDIOGRAPH_CONFIG_REPO = ${configRepoUrl}\n` +
|
|
109
|
+
` GITHUB_TOKEN = ${githubToken}\n` +
|
|
110
|
+
(apiKeys ? ` API_KEYS = ${apiKeys}\n` : '') +
|
|
111
|
+
` WEBHOOK_SECRET = ${webhookSecret}\n` +
|
|
112
|
+
' PORT = 3001\n');
|
|
113
|
+
await confirm({ message: 'Done setting up Railway? Press Enter to continue.' });
|
|
114
|
+
// ── Step 4: GitHub webhooks ───────────────────────────────────────────
|
|
115
|
+
log.step('Step 4 of 4 — GitHub webhooks');
|
|
116
|
+
log.message('Reading your workspace repos to generate webhook URLs...');
|
|
117
|
+
const s = spinner();
|
|
118
|
+
s.start('Cloning config repo to read workspace.json...');
|
|
119
|
+
const repos = readWorkspaceRepos(configRepoUrl, githubToken.trim());
|
|
120
|
+
s.stop(repos.length > 0 ? `Found ${repos.length} repos` : 'Could not read repos — enter your Railway URL manually');
|
|
121
|
+
const railwayUrl = await text({
|
|
122
|
+
message: 'Your Railway app URL',
|
|
123
|
+
placeholder: 'https://your-app.up.railway.app',
|
|
124
|
+
validate: (v) => v.trim() ? undefined : 'Required',
|
|
125
|
+
});
|
|
126
|
+
if (typeof railwayUrl === 'symbol') {
|
|
127
|
+
outro('Cancelled');
|
|
128
|
+
process.exit(0);
|
|
129
|
+
}
|
|
130
|
+
const webhookUrl = `${railwayUrl.replace(/\/$/, '')}/webhooks/github`;
|
|
131
|
+
log.message('Add a webhook to each GitHub repo in your workspace:\n\n' +
|
|
132
|
+
` Payload URL: ${webhookUrl}\n` +
|
|
133
|
+
` Content type: application/json\n` +
|
|
134
|
+
` Secret: ${webhookSecret}\n` +
|
|
135
|
+
' Events: Just the push event\n\n' +
|
|
136
|
+
'Repos to configure:\n' +
|
|
137
|
+
(repos.length > 0
|
|
138
|
+
? repos
|
|
139
|
+
.filter(r => r.github_url)
|
|
140
|
+
.map(r => ` • ${r.github_url}`)
|
|
141
|
+
.join('\n')
|
|
142
|
+
: ' (add webhooks to all repos in your workspace)'));
|
|
143
|
+
log.message('\nFor each repo, go to:\n' +
|
|
144
|
+
' GitHub repo → Settings → Webhooks → Add webhook');
|
|
145
|
+
openBrowser('https://github.com');
|
|
146
|
+
await confirm({ message: 'Webhooks configured? Press Enter to finish.' });
|
|
147
|
+
outro(`✨ All done!\n\n` +
|
|
148
|
+
` Server: ${railwayUrl}\n` +
|
|
149
|
+
` Graph API: ${railwayUrl}/api/repos\n\n` +
|
|
150
|
+
'On Railway\'s next deploy, Studiograph will bootstrap automatically:\n' +
|
|
151
|
+
'clone your config repo, clone your workspace repos, and start serving.');
|
|
152
|
+
});
|
|
153
|
+
//# sourceMappingURL=deploy.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"deploy.js","sourceRoot":"","sources":["../../../src/cli/commands/deploy.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* studiograph index command
|
|
3
|
+
*
|
|
4
|
+
* Bulk-indexes all entities across the workspace into LanceDB.
|
|
5
|
+
* On first run, optionally prompts for a Voyage AI API key to enable
|
|
6
|
+
* semantic search (Tier 2). Without a key, FTS-only indexing still runs.
|
|
7
|
+
*
|
|
8
|
+
* Safe to re-run — uses upsert, not insert.
|
|
9
|
+
*
|
|
10
|
+
* Usage:
|
|
11
|
+
* studiograph index # index all repos
|
|
12
|
+
* studiograph index --repo raa # single repo only
|
|
13
|
+
*/
|
|
14
|
+
import { Command } from 'commander';
|
|
15
|
+
export declare const indexCommand: Command;
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* studiograph index command
|
|
3
|
+
*
|
|
4
|
+
* Bulk-indexes all entities across the workspace into LanceDB.
|
|
5
|
+
* On first run, optionally prompts for a Voyage AI API key to enable
|
|
6
|
+
* semantic search (Tier 2). Without a key, FTS-only indexing still runs.
|
|
7
|
+
*
|
|
8
|
+
* Safe to re-run — uses upsert, not insert.
|
|
9
|
+
*
|
|
10
|
+
* Usage:
|
|
11
|
+
* studiograph index # index all repos
|
|
12
|
+
* studiograph index --repo raa # single repo only
|
|
13
|
+
*/
|
|
14
|
+
import { Command } from 'commander';
|
|
15
|
+
import { join } from 'path';
|
|
16
|
+
import { homedir } from 'os';
|
|
17
|
+
import { select, text, spinner, log, outro } from '@clack/prompts';
|
|
18
|
+
import { Workspace } from '../../core/workspace.js';
|
|
19
|
+
import { loadUserConfig, saveUserConfig } from '../../core/user-config.js';
|
|
20
|
+
import { VectorService } from '../../services/vector-service.js';
|
|
21
|
+
import { BaseGraphManager } from '../../core/graph.js';
|
|
22
|
+
export const indexCommand = new Command('index')
|
|
23
|
+
.description('Index workspace entities for search (FTS + optional semantic search)')
|
|
24
|
+
.option('--repo <name>', 'Index a single repo only')
|
|
25
|
+
.action(async (opts) => {
|
|
26
|
+
const workspace = new Workspace();
|
|
27
|
+
if (!workspace.isWorkspace()) {
|
|
28
|
+
console.error('❌ Not a Studiograph workspace. Run `studiograph init` first.');
|
|
29
|
+
process.exit(1);
|
|
30
|
+
}
|
|
31
|
+
const config = await workspace.loadConfig();
|
|
32
|
+
const userConfig = loadUserConfig();
|
|
33
|
+
// First-run: prompt for Voyage AI key if not configured
|
|
34
|
+
if (!userConfig.voyage_api_key) {
|
|
35
|
+
const choice = await select({
|
|
36
|
+
message: 'Enable semantic search? (optional — requires a Voyage AI API key)',
|
|
37
|
+
options: [
|
|
38
|
+
{
|
|
39
|
+
value: 'skip',
|
|
40
|
+
label: 'Skip — use keyword/FTS search only',
|
|
41
|
+
hint: 'Free, no setup required',
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
value: 'voyage',
|
|
45
|
+
label: 'Enable semantic search',
|
|
46
|
+
hint: 'Voyage AI key required — get one at voyageai.com',
|
|
47
|
+
},
|
|
48
|
+
],
|
|
49
|
+
});
|
|
50
|
+
if (typeof choice === 'symbol') {
|
|
51
|
+
outro('Cancelled');
|
|
52
|
+
process.exit(0);
|
|
53
|
+
}
|
|
54
|
+
if (choice === 'voyage') {
|
|
55
|
+
const keyInput = await text({
|
|
56
|
+
message: 'Enter your Voyage AI API key:',
|
|
57
|
+
placeholder: 'pa-...',
|
|
58
|
+
validate: (value) => {
|
|
59
|
+
if (!value || value.length < 10)
|
|
60
|
+
return 'Key seems too short';
|
|
61
|
+
},
|
|
62
|
+
});
|
|
63
|
+
if (typeof keyInput !== 'string') {
|
|
64
|
+
outro('Cancelled');
|
|
65
|
+
process.exit(0);
|
|
66
|
+
}
|
|
67
|
+
userConfig.voyage_api_key = keyInput;
|
|
68
|
+
saveUserConfig(userConfig);
|
|
69
|
+
log.success('Voyage AI key saved');
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
const dbPath = userConfig.vector_db_path || join(homedir(), '.studiograph', 'vector');
|
|
73
|
+
const vectorService = new VectorService(dbPath, userConfig.voyage_api_key);
|
|
74
|
+
await vectorService.init();
|
|
75
|
+
const repos = opts.repo
|
|
76
|
+
? config.repos.filter(r => r.name === opts.repo)
|
|
77
|
+
: config.repos;
|
|
78
|
+
if (opts.repo && repos.length === 0) {
|
|
79
|
+
console.error(`❌ Repo "${opts.repo}" not found in workspace`);
|
|
80
|
+
process.exit(1);
|
|
81
|
+
}
|
|
82
|
+
const s = spinner();
|
|
83
|
+
let totalIndexed = 0;
|
|
84
|
+
let totalWithVectors = 0;
|
|
85
|
+
for (const repo of repos) {
|
|
86
|
+
const repoPath = join(workspace.getWorkspacePath(), repo.path);
|
|
87
|
+
s.start(`Indexing ${repo.name}...`);
|
|
88
|
+
try {
|
|
89
|
+
const graph = new BaseGraphManager({
|
|
90
|
+
repoPath,
|
|
91
|
+
repoName: repo.name,
|
|
92
|
+
gitUser: { id: 'index', name: 'index', email: 'index@studiograph.local' },
|
|
93
|
+
});
|
|
94
|
+
const entities = graph.list();
|
|
95
|
+
if (entities.length === 0) {
|
|
96
|
+
s.stop(`${repo.name}: no entities`);
|
|
97
|
+
vectorService.setLastIndexedTime(repo.name);
|
|
98
|
+
continue;
|
|
99
|
+
}
|
|
100
|
+
s.message(`Indexing ${repo.name}: ${entities.length} entities...`);
|
|
101
|
+
await vectorService.upsertMany(repo.name, entities);
|
|
102
|
+
vectorService.setLastIndexedTime(repo.name);
|
|
103
|
+
const withVectors = userConfig.voyage_api_key ? entities.length : 0;
|
|
104
|
+
totalIndexed += entities.length;
|
|
105
|
+
totalWithVectors += withVectors;
|
|
106
|
+
s.stop(`${repo.name}: indexed ${entities.length} entities`);
|
|
107
|
+
}
|
|
108
|
+
catch (err) {
|
|
109
|
+
s.stop(`${repo.name}: failed — ${err instanceof Error ? err.message : 'unknown error'}`);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
const vectorNote = userConfig.voyage_api_key
|
|
113
|
+
? ` (${totalWithVectors} with semantic vectors)`
|
|
114
|
+
: ' (FTS only — add voyage_api_key to enable semantic search)';
|
|
115
|
+
outro(`✓ Indexed ${totalIndexed} entities across ${repos.length} repo${repos.length === 1 ? '' : 's'}${vectorNote}`);
|
|
116
|
+
});
|
|
117
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/cli/commands/index.ts"],"names":[],"mappings":"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"}
|