studiograph 1.2.0-beta.9 → 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/README.md +13 -18
- package/dist/agent/orchestrator.d.ts +56 -0
- package/dist/agent/orchestrator.js +167 -22
- package/dist/agent/orchestrator.js.map +1 -1
- package/dist/agent/prompts/system.md +51 -63
- package/dist/agent/skill-loader.js +8 -0
- package/dist/agent/skill-loader.js.map +1 -1
- package/dist/agent/skills/entity-schema.md +4 -19
- package/dist/agent/skills/gather-context.md +1 -1
- package/dist/agent/tools/graph-tools.d.ts +41 -1
- package/dist/agent/tools/graph-tools.js +133 -57
- package/dist/agent/tools/graph-tools.js.map +1 -1
- package/dist/agent/tools/ops-tools.js +82 -0
- package/dist/agent/tools/ops-tools.js.map +1 -1
- package/dist/agent/tools/permission-tools.d.ts +90 -0
- package/dist/agent/tools/permission-tools.js +207 -0
- package/dist/agent/tools/permission-tools.js.map +1 -0
- package/dist/agent/tools/sync-tools.js +2 -2
- package/dist/agent/tools/sync-tools.js.map +1 -1
- package/dist/auth/github.d.ts +1 -1
- package/dist/auth/github.js +21 -13
- package/dist/auth/github.js.map +1 -1
- package/dist/cli/commands/access.d.ts +11 -0
- package/dist/cli/commands/access.js +156 -0
- package/dist/cli/commands/access.js.map +1 -0
- package/dist/cli/commands/app.js +25 -2
- package/dist/cli/commands/app.js.map +1 -1
- package/dist/cli/commands/clear.d.ts +5 -0
- package/dist/cli/commands/clear.js +36 -0
- package/dist/cli/commands/clear.js.map +1 -0
- package/dist/cli/commands/clone.js +3 -3
- package/dist/cli/commands/clone.js.map +1 -1
- package/dist/cli/commands/collection.d.ts +10 -0
- package/dist/cli/commands/collection.js +187 -0
- package/dist/cli/commands/collection.js.map +1 -0
- package/dist/cli/commands/commit.js +2 -1
- package/dist/cli/commands/commit.js.map +1 -1
- package/dist/cli/commands/config.d.ts +100 -0
- package/dist/cli/commands/config.js +1 -1
- package/dist/cli/commands/config.js.map +1 -1
- package/dist/cli/commands/deploy.js +10 -1
- package/dist/cli/commands/deploy.js.map +1 -1
- package/dist/cli/commands/index.js +1 -1
- package/dist/cli/commands/index.js.map +1 -1
- package/dist/cli/commands/init.js +32 -40
- package/dist/cli/commands/init.js.map +1 -1
- package/dist/cli/commands/join.d.ts +0 -6
- package/dist/cli/commands/join.js +26 -111
- package/dist/cli/commands/join.js.map +1 -1
- package/dist/cli/commands/lint.js +1 -2
- package/dist/cli/commands/lint.js.map +1 -1
- package/dist/cli/commands/mcp.js +6 -5
- package/dist/cli/commands/mcp.js.map +1 -1
- package/dist/cli/commands/org.d.ts +10 -0
- package/dist/cli/commands/org.js +132 -0
- package/dist/cli/commands/org.js.map +1 -0
- package/dist/cli/commands/orphans.js +1 -2
- package/dist/cli/commands/orphans.js.map +1 -1
- package/dist/cli/commands/provision.js +3 -3
- package/dist/cli/commands/provision.js.map +1 -1
- package/dist/cli/commands/resolve.d.ts +8 -0
- package/dist/cli/commands/resolve.js +85 -0
- package/dist/cli/commands/resolve.js.map +1 -0
- package/dist/cli/commands/serve.js +55 -25
- package/dist/cli/commands/serve.js.map +1 -1
- package/dist/cli/commands/start.js +22 -205
- package/dist/cli/commands/start.js.map +1 -1
- package/dist/cli/commands/sync.js +53 -8
- package/dist/cli/commands/sync.js.map +1 -1
- package/dist/cli/commands/team.d.ts +12 -0
- package/dist/cli/commands/team.js +185 -0
- package/dist/cli/commands/team.js.map +1 -0
- package/dist/cli/index.js +41 -34
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/scaffolding.d.ts +5 -3
- package/dist/cli/scaffolding.js +191 -97
- package/dist/cli/scaffolding.js.map +1 -1
- package/dist/cli/setup-wizard.js +20 -10
- package/dist/cli/setup-wizard.js.map +1 -1
- package/dist/cli/sync-review-interactive.js +1 -1
- package/dist/cli/sync-review-interactive.js.map +1 -1
- package/dist/core/graph.d.ts +5 -10
- package/dist/core/graph.js +84 -85
- package/dist/core/graph.js.map +1 -1
- package/dist/core/migration-runner.d.ts +42 -0
- package/dist/core/migration-runner.js +232 -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/types.d.ts +19 -34
- package/dist/core/types.js +3 -21
- package/dist/core/types.js.map +1 -1
- package/dist/core/user-config.d.ts +27 -0
- package/dist/core/user-config.js +51 -0
- package/dist/core/user-config.js.map +1 -1
- package/dist/core/validation.d.ts +978 -2182
- package/dist/core/validation.js +242 -397
- package/dist/core/validation.js.map +1 -1
- package/dist/core/workspace-manager.d.ts +32 -31
- package/dist/core/workspace-manager.js +171 -186
- package/dist/core/workspace-manager.js.map +1 -1
- package/dist/core/workspace.d.ts +0 -5
- package/dist/core/workspace.js +33 -101
- package/dist/core/workspace.js.map +1 -1
- package/dist/lib/lib/utils.d.ts +2 -0
- package/dist/lib/lib/utils.js +6 -0
- package/dist/lib/lib/utils.js.map +1 -0
- package/dist/mcp/tools.js +13 -13
- package/dist/mcp/tools.js.map +1 -1
- package/dist/server/chrome/chrome.css +562 -0
- package/dist/server/chrome/chrome.js +540 -0
- package/dist/server/index.js +163 -10
- package/dist/server/index.js.map +1 -1
- package/dist/server/plugin-loader.d.ts +7 -0
- package/dist/server/plugin-loader.js +9 -1
- package/dist/server/plugin-loader.js.map +1 -1
- package/dist/server/routes/chat.d.ts +3 -2
- package/dist/server/routes/chat.js +67 -16
- package/dist/server/routes/chat.js.map +1 -1
- package/dist/server/routes/git-api.d.ts +9 -0
- package/dist/server/routes/git-api.js +82 -0
- package/dist/server/routes/git-api.js.map +1 -0
- package/dist/server/routes/graph-api.d.ts +2 -2
- package/dist/server/routes/graph-api.js +267 -3
- package/dist/server/routes/graph-api.js.map +1 -1
- package/dist/server/routes/permissions-api.d.ts +9 -0
- package/dist/server/routes/permissions-api.js +176 -0
- package/dist/server/routes/permissions-api.js.map +1 -0
- package/dist/server/routes/workspace-api.d.ts +9 -0
- package/dist/server/routes/workspace-api.js +283 -0
- package/dist/server/routes/workspace-api.js.map +1 -0
- package/dist/services/assets/base.d.ts +2 -2
- package/dist/services/assets/base.js +4 -4
- package/dist/services/assets/base.js.map +1 -1
- package/dist/services/assets/index.d.ts +6 -6
- package/dist/services/assets/index.js +12 -12
- package/dist/services/assets/index.js.map +1 -1
- package/dist/services/git.d.ts +35 -0
- package/dist/services/git.js +93 -0
- package/dist/services/git.js.map +1 -1
- package/dist/services/github-provisioner.js +1 -2
- package/dist/services/github-provisioner.js.map +1 -1
- package/dist/services/github-service.d.ts +99 -0
- package/dist/services/github-service.js +310 -0
- package/dist/services/github-service.js.map +1 -0
- package/dist/services/markdown.js +4 -9
- package/dist/services/markdown.js.map +1 -1
- package/dist/services/memory-service.d.ts +4 -0
- package/dist/services/memory-service.js +13 -1
- package/dist/services/memory-service.js.map +1 -1
- package/dist/services/sync/commit.d.ts +2 -0
- package/dist/services/sync/commit.js +21 -6
- package/dist/services/sync/commit.js.map +1 -1
- package/dist/services/sync/graphrag-indexer.js +2 -2
- package/dist/services/sync/graphrag-indexer.js.map +1 -1
- package/dist/utils/git.d.ts +5 -0
- package/dist/utils/git.js +10 -0
- package/dist/utils/git.js.map +1 -1
- package/dist/utils/merge-resolver.d.ts +33 -8
- package/dist/utils/merge-resolver.js +157 -55
- package/dist/utils/merge-resolver.js.map +1 -1
- package/dist/utils/preflight.d.ts +1 -1
- package/dist/utils/preflight.js +1 -1
- package/dist/web/_app/env.js +1 -0
- package/dist/web/_app/immutable/assets/0.CDbX4Cwz.css +1 -0
- package/dist/web/_app/immutable/assets/2.DRHi7ABa.css +1 -0
- package/dist/web/_app/immutable/assets/3.BJy7pVXi.css +1 -0
- package/dist/web/_app/immutable/assets/4.Ad16uh9o.css +1 -0
- package/dist/web/_app/immutable/assets/5.BhKgiXd2.css +1 -0
- package/dist/web/_app/immutable/assets/6.CeHKR5ZY.css +1 -0
- package/dist/web/_app/immutable/assets/AppShell.CXdE5aqF.css +1 -0
- package/dist/web/_app/immutable/assets/ChatPanel.RFD5GGYI.css +1 -0
- package/dist/web/_app/immutable/assets/editor.CPAf2SRV.css +1 -0
- package/dist/web/_app/immutable/chunks/3_5VIr68.js +1 -0
- package/dist/web/_app/immutable/chunks/4QY4j-jX.js +1 -0
- package/dist/web/_app/immutable/chunks/B0nldqWF.js +23 -0
- package/dist/web/_app/immutable/chunks/BB_5th5W.js +3383 -0
- package/dist/web/_app/immutable/chunks/BButMJ6M.js +1 -0
- package/dist/web/_app/immutable/chunks/BiubvAUI.js +2 -0
- package/dist/web/_app/immutable/chunks/CAXuTUkp.js +1 -0
- package/dist/web/_app/immutable/chunks/CUzqHQY_.js +1 -0
- package/dist/web/_app/immutable/chunks/CYrVHOHA.js +1 -0
- package/dist/web/_app/immutable/chunks/CqkleIqs.js +1 -0
- package/dist/web/_app/immutable/chunks/DPmdIe6Y.js +1 -0
- package/dist/web/_app/immutable/chunks/Dh_H7Owr.js +18 -0
- package/dist/web/_app/immutable/chunks/DnlgZ_Tk.js +5 -0
- package/dist/web/_app/immutable/chunks/DsERsGWg.js +64 -0
- package/dist/web/_app/immutable/chunks/DtVH--hH.js +6 -0
- package/dist/web/_app/immutable/chunks/F20aIBpJ.js +1 -0
- package/dist/web/_app/immutable/chunks/PPVm8Dsz.js +1 -0
- package/dist/web/_app/immutable/chunks/WSUKABI_.js +1 -0
- package/dist/web/_app/immutable/chunks/YFT1281h.js +2 -0
- package/dist/web/_app/immutable/chunks/aosHekRC.js +1 -0
- package/dist/web/_app/immutable/chunks/fwnBoL5x.js +1 -0
- package/dist/web/_app/immutable/chunks/hHxe9oXh.js +1 -0
- package/dist/web/_app/immutable/chunks/nZKqDQ0w.js +6 -0
- package/dist/web/_app/immutable/entry/app.B6Ngvu5P.js +2 -0
- package/dist/web/_app/immutable/entry/start.NykKAKQv.js +1 -0
- package/dist/web/_app/immutable/nodes/0.DQ5KdeNU.js +1 -0
- package/dist/web/_app/immutable/nodes/1.BR6DZ9ov.js +1 -0
- package/dist/web/_app/immutable/nodes/2.COSjVZ_C.js +1 -0
- package/dist/web/_app/immutable/nodes/3.B9r1XIlO.js +1 -0
- package/dist/web/_app/immutable/nodes/4.p-c6hlFf.js +16 -0
- package/dist/web/_app/immutable/nodes/5.CPc-Bqal.js +4 -0
- package/dist/web/_app/immutable/nodes/6.jJ67YnBc.js +2 -0
- package/dist/web/_app/version.json +1 -0
- package/dist/web/index.html +43 -0
- package/package.json +21 -3
- package/dist/agent/skills/bundled/enrich-entities.md +0 -124
- package/dist/agent/skills/bundled/gather-context.md +0 -46
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* studiograph resolve — retry conflict resolution for repos stuck mid-rebase.
|
|
3
|
+
*
|
|
4
|
+
* Scans all workspace repos, finds those with an in-progress rebase,
|
|
5
|
+
* and runs the conflict resolver on them.
|
|
6
|
+
*/
|
|
7
|
+
import { Command } from 'commander';
|
|
8
|
+
import { log, outro } from '@clack/prompts';
|
|
9
|
+
import { existsSync } from 'fs';
|
|
10
|
+
import { join } from 'path';
|
|
11
|
+
import { Workspace } from '../../core/workspace.js';
|
|
12
|
+
import { isInRebase, gitStashPop } from '../../utils/git.js';
|
|
13
|
+
import { resolveConflicts } from '../../utils/merge-resolver.js';
|
|
14
|
+
export const resolveCommand = new Command('resolve')
|
|
15
|
+
.description('Retry conflict resolution for repos stuck mid-rebase')
|
|
16
|
+
.action(async () => {
|
|
17
|
+
const workspace = new Workspace();
|
|
18
|
+
if (!workspace.isWorkspace()) {
|
|
19
|
+
console.error('❌ Not a Studiograph workspace. Run `studiograph init` first.');
|
|
20
|
+
process.exit(1);
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
const workspaceRoot = workspace.getWorkspacePath();
|
|
24
|
+
// Gather all repo paths
|
|
25
|
+
const repoPaths = [];
|
|
26
|
+
const studioPath = join(workspaceRoot, '.studiograph');
|
|
27
|
+
if (existsSync(studioPath)) {
|
|
28
|
+
repoPaths.push({ name: '.studiograph', path: studioPath });
|
|
29
|
+
}
|
|
30
|
+
const config = await workspace.loadConfig();
|
|
31
|
+
for (const repo of config.repos) {
|
|
32
|
+
const repoPath = join(workspaceRoot, repo.path);
|
|
33
|
+
if (existsSync(repoPath)) {
|
|
34
|
+
repoPaths.push({ name: repo.name, path: repoPath });
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
// Find repos mid-rebase
|
|
38
|
+
const rebasingRepos = repoPaths.filter(r => isInRebase(r.path));
|
|
39
|
+
if (rebasingRepos.length === 0) {
|
|
40
|
+
log.info('No collections are mid-rebase. Nothing to resolve.');
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
log.info(`Found ${rebasingRepos.length} collection${rebasingRepos.length === 1 ? '' : 's'} mid-rebase.`);
|
|
44
|
+
let hasFailure = false;
|
|
45
|
+
for (const repo of rebasingRepos) {
|
|
46
|
+
log.info(`\nResolving conflicts in ${repo.name}...`);
|
|
47
|
+
const resolution = await resolveConflicts(repo.path, (msg) => log.info(msg));
|
|
48
|
+
gitStashPop(repo.path);
|
|
49
|
+
if (resolution.success) {
|
|
50
|
+
const count = resolution.resolutions.filter(r => r.resolved).length;
|
|
51
|
+
log.success(`${repo.name}: resolved (${count} conflict${count === 1 ? '' : 's'})`);
|
|
52
|
+
for (const r of resolution.resolutions) {
|
|
53
|
+
if (r.resolved) {
|
|
54
|
+
log.info(` ${r.file} — ${r.summary}`);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
else {
|
|
59
|
+
const failed = resolution.resolutions.filter(r => !r.resolved);
|
|
60
|
+
if (failed.length > 0) {
|
|
61
|
+
log.warn(`${repo.name}: ${failed.length} conflict${failed.length === 1 ? '' : 's'} could not be resolved`);
|
|
62
|
+
for (const r of failed) {
|
|
63
|
+
log.info(` ${r.file} — ${r.summary ?? 'unresolved'}`);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
else {
|
|
67
|
+
log.warn(`${repo.name}: resolution failed (no conflicts found — rebase may need manual intervention)`);
|
|
68
|
+
}
|
|
69
|
+
log.info('');
|
|
70
|
+
log.info(' To resolve manually:');
|
|
71
|
+
log.info(` cd ${repo.path}`);
|
|
72
|
+
log.info(' git status');
|
|
73
|
+
log.info(' # edit conflicted files, then: git add <file> && git rebase --continue');
|
|
74
|
+
hasFailure = true;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
if (hasFailure) {
|
|
78
|
+
outro('⚠️ Some conflicts remain. Resolve them manually, then run `studiograph push`.');
|
|
79
|
+
process.exit(1);
|
|
80
|
+
}
|
|
81
|
+
else {
|
|
82
|
+
outro('All conflicts resolved.');
|
|
83
|
+
}
|
|
84
|
+
});
|
|
85
|
+
//# sourceMappingURL=resolve.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resolve.js","sourceRoot":"","sources":["../../../src/cli/commands/resolve.ts"],"names":[],"mappings":"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"}
|
|
@@ -16,13 +16,16 @@
|
|
|
16
16
|
import { Command } from 'commander';
|
|
17
17
|
import { join } from 'path';
|
|
18
18
|
import { existsSync } from 'fs';
|
|
19
|
-
import { spawnSync } from 'child_process';
|
|
19
|
+
import { exec, spawnSync } from 'child_process';
|
|
20
20
|
import { Workspace } from '../../core/workspace.js';
|
|
21
21
|
import { WorkspaceManager } from '../../core/workspace-manager.js';
|
|
22
|
-
import { loadUserConfig } from '../../core/user-config.js';
|
|
22
|
+
import { loadUserConfig, resolveApiKey, propagateApiKeyToEnv } from '../../core/user-config.js';
|
|
23
|
+
import { promptLLMSetupIfNeeded } from '../setup-wizard.js';
|
|
23
24
|
import { runPreflight } from '../../utils/preflight.js';
|
|
24
25
|
import { createServer } from '../../server/index.js';
|
|
25
26
|
import { gitClone } from '../../utils/git.js';
|
|
27
|
+
import { box } from 'consola/utils';
|
|
28
|
+
import { header, dimText } from '../colors.js';
|
|
26
29
|
/**
|
|
27
30
|
* Pull latest changes for a git repo. Non-fatal — logs warnings on failure.
|
|
28
31
|
*/
|
|
@@ -112,9 +115,12 @@ async function bootstrapWorkspace(workspacePath) {
|
|
|
112
115
|
}
|
|
113
116
|
export const serveCommand = new Command('serve')
|
|
114
117
|
.description('Start the Studiograph HTTP server')
|
|
115
|
-
.option('-p, --port <port>', 'Port to listen on', '
|
|
118
|
+
.option('-p, --port <port>', 'Port to listen on', '4800')
|
|
116
119
|
.option('-H, --host <host>', 'Host to bind to', '0.0.0.0')
|
|
120
|
+
.option('--verbose', 'Show detailed startup info (tools, etc.)')
|
|
117
121
|
.action(async (opts) => {
|
|
122
|
+
if (opts.verbose)
|
|
123
|
+
process.env.STUDIOGRAPH_VERBOSE = '1';
|
|
118
124
|
// Bootstrap from STUDIOGRAPH_CONFIG_REPO if repos are not present (e.g. Railway first boot)
|
|
119
125
|
await bootstrapWorkspace(process.cwd());
|
|
120
126
|
const workspace = new Workspace();
|
|
@@ -128,29 +134,28 @@ export const serveCommand = new Command('serve')
|
|
|
128
134
|
return;
|
|
129
135
|
}
|
|
130
136
|
const config = await workspace.loadConfig();
|
|
131
|
-
//
|
|
132
|
-
const
|
|
133
|
-
if (
|
|
134
|
-
|
|
137
|
+
// Prompt for model setup if not configured (non-blocking — server works without it, but chat won't)
|
|
138
|
+
const isRemote = !!process.env.STUDIOGRAPH_CONFIG_REPO;
|
|
139
|
+
if (!isRemote) {
|
|
140
|
+
await promptLLMSetupIfNeeded();
|
|
135
141
|
}
|
|
142
|
+
// Propagate API key from user config to env (orchestrator reads provider env vars)
|
|
143
|
+
const userConfig = loadUserConfig();
|
|
144
|
+
propagateApiKeyToEnv(userConfig, config);
|
|
145
|
+
const llmApiKey = resolveApiKey(userConfig, config);
|
|
136
146
|
// Build GitUser from workspace config
|
|
137
147
|
const gitUser = {
|
|
138
148
|
id: 'serve',
|
|
139
149
|
name: config.team_name || 'Studiograph Server',
|
|
140
150
|
email: 'noreply@studiograph.local',
|
|
141
151
|
};
|
|
142
|
-
|
|
143
|
-
const serverUser = { ...gitUser, role: 'admin' };
|
|
144
|
-
const workspaceManager = new WorkspaceManager(process.cwd(), config, gitUser, serverUser);
|
|
152
|
+
const workspaceManager = new WorkspaceManager(process.cwd(), config, gitUser);
|
|
145
153
|
// Read API keys from environment (semicolon-separated)
|
|
146
154
|
const apiKeysEnv = process.env.API_KEYS || '';
|
|
147
155
|
const apiKeys = apiKeysEnv
|
|
148
156
|
.split(';')
|
|
149
157
|
.map(k => k.trim())
|
|
150
158
|
.filter(k => k.length > 0);
|
|
151
|
-
if (apiKeys.length === 0) {
|
|
152
|
-
console.warn('Warning: No API_KEYS configured — server is open (dev mode)');
|
|
153
|
-
}
|
|
154
159
|
const webhookSecret = process.env.WEBHOOK_SECRET;
|
|
155
160
|
const port = parseInt(process.env.PORT || opts.port, 10);
|
|
156
161
|
const host = process.env.HOST || opts.host;
|
|
@@ -166,17 +171,42 @@ export const serveCommand = new Command('serve')
|
|
|
166
171
|
apiKeys,
|
|
167
172
|
webhookSecret,
|
|
168
173
|
});
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
174
|
+
// Try to listen, auto-incrementing port if in use
|
|
175
|
+
let actualPort = port;
|
|
176
|
+
const maxRetries = 10;
|
|
177
|
+
for (let attempt = 0; attempt < maxRetries; attempt++) {
|
|
178
|
+
try {
|
|
179
|
+
await server.listen({ port: actualPort, host });
|
|
180
|
+
break;
|
|
181
|
+
}
|
|
182
|
+
catch (err) {
|
|
183
|
+
if (err.code === 'EADDRINUSE' && attempt < maxRetries - 1) {
|
|
184
|
+
actualPort++;
|
|
185
|
+
continue;
|
|
186
|
+
}
|
|
187
|
+
console.error(`\nFailed to start server: ${err.message}`);
|
|
188
|
+
process.exit(1);
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
const collections = config.repos.length;
|
|
192
|
+
const hasChat = !!llmApiKey;
|
|
193
|
+
const url = `http://localhost:${actualPort}`;
|
|
194
|
+
console.log(box([
|
|
195
|
+
`URL: ${header(url)}`,
|
|
196
|
+
`Collections: ${collections}`,
|
|
197
|
+
`Chat: ${hasChat ? 'enabled' : dimText('disabled (run studiograph config to add an AI model)')}`,
|
|
198
|
+
].join('\n'), {
|
|
199
|
+
title: `Studiograph — ${config.team_name}`,
|
|
200
|
+
style: { borderColor: 'cyan', padding: 1 },
|
|
201
|
+
}));
|
|
202
|
+
if (actualPort !== port) {
|
|
203
|
+
console.log(dimText(` Port ${port} was in use, using ${actualPort} instead.\n`));
|
|
204
|
+
}
|
|
205
|
+
// Open browser on local dev (not on Railway/remote deployments)
|
|
206
|
+
if (!isRemote) {
|
|
207
|
+
const openUrl = process.platform === 'darwin' ? 'open' : process.platform === 'win32' ? 'start' : 'xdg-open';
|
|
208
|
+
exec(`${openUrl} ${url}`);
|
|
209
|
+
}
|
|
210
|
+
console.log(dimText('Press Ctrl+C to stop the server.\n'));
|
|
181
211
|
});
|
|
182
212
|
//# sourceMappingURL=serve.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"serve.js","sourceRoot":"","sources":["../../../src/cli/commands/serve.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAC5B,OAAO,EAAE,UAAU,EAAE,MAAM,IAAI,CAAC;AAChC,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"serve.js","sourceRoot":"","sources":["../../../src/cli/commands/serve.ts"],"names":[],"mappings":"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"}
|
|
@@ -19,9 +19,10 @@ import { createLoadSkillTool } from '../../agent/tools/load-skill.js';
|
|
|
19
19
|
import { loadCustomTools } from '../../agent/tools/tool-loader.js';
|
|
20
20
|
import { ConnectorManager } from '../../mcp/connector-manager.js';
|
|
21
21
|
import { buildConnectorRegistry, createConnectorTools } from '../../agent/tools/connector-tools.js';
|
|
22
|
-
import {
|
|
22
|
+
import { spinner } from '@clack/prompts';
|
|
23
23
|
import { runPreflight } from '../../utils/preflight.js';
|
|
24
|
-
import {
|
|
24
|
+
import { promptLLMSetupIfNeeded } from '../setup-wizard.js';
|
|
25
|
+
import { loadUserConfig, resolveApiKey, resolveProvider, resolveModelId } from '../../core/user-config.js';
|
|
25
26
|
import { notifyUpdateAvailable } from '../../utils/version-checker.js';
|
|
26
27
|
import { PluginLoader } from '../../server/plugin-loader.js';
|
|
27
28
|
import { join, dirname } from 'path';
|
|
@@ -35,71 +36,12 @@ import { info, dimText, header, warn, toolRef, renderUserPrompt } from '../color
|
|
|
35
36
|
import { box } from 'consola/utils';
|
|
36
37
|
import ora from 'ora';
|
|
37
38
|
import { markdownTheme } from '../theme.js';
|
|
38
|
-
// Model provider configurations
|
|
39
|
-
const MODEL_PROVIDERS = {
|
|
40
|
-
anthropic: {
|
|
41
|
-
name: 'Anthropic (Claude)',
|
|
42
|
-
models: [
|
|
43
|
-
{ id: 'claude-opus-4-6', name: 'Claude Opus 4.6 (Most Capable)', hint: 'Best reasoning, can be slower' },
|
|
44
|
-
{ id: 'claude-sonnet-4-5-20250929', name: 'Claude Sonnet 4.5 (Recommended)', hint: 'Great balance of speed and quality' },
|
|
45
|
-
{ id: 'claude-3-7-sonnet-20250219', name: 'Claude 3.7 Sonnet', hint: 'Faster, good for most tasks' },
|
|
46
|
-
{ id: 'claude-3-5-haiku-20241022', name: 'Claude 3.5 Haiku', hint: 'Fastest, lightweight tasks' },
|
|
47
|
-
],
|
|
48
|
-
requiresApiKey: true,
|
|
49
|
-
envVar: 'ANTHROPIC_API_KEY',
|
|
50
|
-
},
|
|
51
|
-
openai: {
|
|
52
|
-
name: 'OpenAI (GPT)',
|
|
53
|
-
models: [
|
|
54
|
-
{ id: 'gpt-4o', name: 'GPT-4o (Recommended)', hint: 'Latest multimodal model' },
|
|
55
|
-
{ id: 'gpt-4o-mini', name: 'GPT-4o Mini', hint: 'Faster and cheaper' },
|
|
56
|
-
{ id: 'gpt-4-turbo', name: 'GPT-4 Turbo', hint: 'Previous generation' },
|
|
57
|
-
],
|
|
58
|
-
requiresApiKey: true,
|
|
59
|
-
envVar: 'OPENAI_API_KEY',
|
|
60
|
-
},
|
|
61
|
-
google: {
|
|
62
|
-
name: 'Google (Gemini)',
|
|
63
|
-
models: [
|
|
64
|
-
{ id: 'gemini-2.0-flash-exp', name: 'Gemini 2.0 Flash (Experimental)', hint: 'Latest experimental model' },
|
|
65
|
-
{ id: 'gemini-1.5-pro', name: 'Gemini 1.5 Pro', hint: 'Most capable' },
|
|
66
|
-
{ id: 'gemini-1.5-flash', name: 'Gemini 1.5 Flash', hint: 'Fast and efficient' },
|
|
67
|
-
],
|
|
68
|
-
requiresApiKey: true,
|
|
69
|
-
envVar: 'GOOGLE_API_KEY',
|
|
70
|
-
},
|
|
71
|
-
xai: {
|
|
72
|
-
name: 'xAI (Grok)',
|
|
73
|
-
models: [
|
|
74
|
-
{ id: 'grok-2-1212', name: 'Grok 2', hint: 'Latest xAI model' },
|
|
75
|
-
{ id: 'grok-2-vision-1212', name: 'Grok 2 Vision', hint: 'With vision capabilities' },
|
|
76
|
-
],
|
|
77
|
-
requiresApiKey: true,
|
|
78
|
-
envVar: 'XAI_API_KEY',
|
|
79
|
-
},
|
|
80
|
-
groq: {
|
|
81
|
-
name: 'Groq (Fast Inference)',
|
|
82
|
-
models: [
|
|
83
|
-
{ id: 'llama-3.3-70b-versatile', name: 'Llama 3.3 70B', hint: 'Very fast inference' },
|
|
84
|
-
{ id: 'mixtral-8x7b-32768', name: 'Mixtral 8x7B', hint: 'Fast and capable' },
|
|
85
|
-
],
|
|
86
|
-
requiresApiKey: true,
|
|
87
|
-
envVar: 'GROQ_API_KEY',
|
|
88
|
-
},
|
|
89
|
-
openrouter: {
|
|
90
|
-
name: 'OpenRouter (Access to many models)',
|
|
91
|
-
models: [
|
|
92
|
-
{ id: 'anthropic/claude-opus-4-6', name: 'Claude Opus 4.6 (via OpenRouter)', hint: 'Access Claude without Anthropic API' },
|
|
93
|
-
{ id: 'openai/gpt-4o', name: 'GPT-4o (via OpenRouter)', hint: 'Access OpenAI without direct API' },
|
|
94
|
-
{ id: 'meta-llama/llama-3.3-70b-instruct', name: 'Llama 3.3 70B', hint: 'Open source model' },
|
|
95
|
-
],
|
|
96
|
-
requiresApiKey: true,
|
|
97
|
-
envVar: 'OPENROUTER_API_KEY',
|
|
98
|
-
},
|
|
99
|
-
};
|
|
100
39
|
export const startCommand = new Command('start')
|
|
101
40
|
.description('Start the Studiograph agent chat interface')
|
|
102
|
-
.
|
|
41
|
+
.option('--verbose', 'Show detailed startup info (tools, etc.)')
|
|
42
|
+
.action(async (opts) => {
|
|
43
|
+
if (opts.verbose)
|
|
44
|
+
process.env.STUDIOGRAPH_VERBOSE = '1';
|
|
103
45
|
const workspace = new Workspace();
|
|
104
46
|
// Check if workspace is initialized
|
|
105
47
|
if (!workspace.isWorkspace()) {
|
|
@@ -111,135 +53,26 @@ export const startCommand = new Command('start')
|
|
|
111
53
|
process.exit(1);
|
|
112
54
|
return;
|
|
113
55
|
}
|
|
114
|
-
// Load workspace config
|
|
56
|
+
// Load workspace config
|
|
115
57
|
const config = await workspace.loadConfig();
|
|
116
58
|
const repos = await workspace.getRepos();
|
|
59
|
+
// Model setup — shared wizard handles first-time prompts and "already configured" message
|
|
60
|
+
await promptLLMSetupIfNeeded();
|
|
61
|
+
// Re-read user config (wizard may have updated it)
|
|
117
62
|
const userConfig = loadUserConfig();
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
if (!modelProvider || !modelId) {
|
|
124
|
-
// First-time setup
|
|
125
|
-
intro('🎨 Studiograph Setup');
|
|
126
|
-
console.log('Let\'s configure your AI model.\n');
|
|
127
|
-
// Select provider
|
|
128
|
-
const providerChoice = await select({
|
|
129
|
-
message: 'Which AI provider would you like to use?',
|
|
130
|
-
options: [
|
|
131
|
-
{ value: 'anthropic', label: 'Anthropic (Claude)', hint: 'Recommended - Best reasoning' },
|
|
132
|
-
{ value: 'openai', label: 'OpenAI (GPT)', hint: 'Popular, widely used' },
|
|
133
|
-
{ value: 'google', label: 'Google (Gemini)', hint: 'Free tier available' },
|
|
134
|
-
{ value: 'xai', label: 'xAI (Grok)', hint: 'Real-time knowledge' },
|
|
135
|
-
{ value: 'groq', label: 'Groq', hint: 'Fastest inference' },
|
|
136
|
-
{ value: 'openrouter', label: 'OpenRouter', hint: 'Access many models with one API key' },
|
|
137
|
-
],
|
|
138
|
-
});
|
|
139
|
-
if (typeof providerChoice === 'symbol') {
|
|
140
|
-
outro('Cancelled');
|
|
141
|
-
process.exit(0);
|
|
142
|
-
}
|
|
143
|
-
modelProvider = providerChoice;
|
|
144
|
-
const provider = MODEL_PROVIDERS[modelProvider];
|
|
145
|
-
// Select model
|
|
146
|
-
const modelChoice = await select({
|
|
147
|
-
message: `Which ${provider.name} model?`,
|
|
148
|
-
options: provider.models.map(m => ({
|
|
149
|
-
value: m.id,
|
|
150
|
-
label: m.name,
|
|
151
|
-
hint: m.hint,
|
|
152
|
-
})),
|
|
153
|
-
});
|
|
154
|
-
if (typeof modelChoice === 'symbol') {
|
|
155
|
-
outro('Cancelled');
|
|
156
|
-
process.exit(0);
|
|
157
|
-
}
|
|
158
|
-
modelId = modelChoice;
|
|
159
|
-
// Get API key if required
|
|
160
|
-
if (provider.requiresApiKey && !apiKey) {
|
|
161
|
-
// Check environment variable first
|
|
162
|
-
const envKey = process.env[provider.envVar];
|
|
163
|
-
if (envKey) {
|
|
164
|
-
console.log(`✓ Using ${provider.envVar} from environment\n`);
|
|
165
|
-
apiKey = envKey;
|
|
166
|
-
}
|
|
167
|
-
else if (modelProvider === 'anthropic') {
|
|
168
|
-
// Anthropic requires API key from console.anthropic.com
|
|
169
|
-
const keyInput = await text({
|
|
170
|
-
message: 'Enter your Anthropic API key:',
|
|
171
|
-
placeholder: 'sk-ant-api03-...',
|
|
172
|
-
validate: (value) => {
|
|
173
|
-
if (!value || value.length < 10)
|
|
174
|
-
return 'API key seems too short';
|
|
175
|
-
},
|
|
176
|
-
});
|
|
177
|
-
if (typeof keyInput !== 'string') {
|
|
178
|
-
outro('Cancelled');
|
|
179
|
-
process.exit(0);
|
|
180
|
-
}
|
|
181
|
-
apiKey = keyInput;
|
|
182
|
-
const s = spinner();
|
|
183
|
-
s.start('Saving configuration...');
|
|
184
|
-
workspace.setModelConfig(modelProvider, modelId, apiKey);
|
|
185
|
-
s.stop('Configuration saved ✓');
|
|
186
|
-
outro(`Model configured: ${provider.name} - ${modelId}\n`);
|
|
187
|
-
}
|
|
188
|
-
else {
|
|
189
|
-
const keyInput = await text({
|
|
190
|
-
message: `Enter your ${provider.name} API key:`,
|
|
191
|
-
placeholder: 'sk-...',
|
|
192
|
-
validate: (value) => {
|
|
193
|
-
if (!value || value.length < 10)
|
|
194
|
-
return 'API key seems too short';
|
|
195
|
-
},
|
|
196
|
-
});
|
|
197
|
-
if (typeof keyInput !== 'string') {
|
|
198
|
-
outro('Cancelled');
|
|
199
|
-
process.exit(0);
|
|
200
|
-
}
|
|
201
|
-
apiKey = keyInput;
|
|
202
|
-
const s = spinner();
|
|
203
|
-
s.start('Saving configuration...');
|
|
204
|
-
workspace.setModelConfig(modelProvider, modelId, apiKey);
|
|
205
|
-
s.stop('Configuration saved ✓');
|
|
206
|
-
outro(`Model configured: ${provider.name} - ${modelId}\n`);
|
|
207
|
-
}
|
|
208
|
-
}
|
|
209
|
-
else {
|
|
210
|
-
// Save configuration (non-Anthropic or key already available)
|
|
211
|
-
const s = spinner();
|
|
212
|
-
s.start('Saving configuration...');
|
|
213
|
-
workspace.setModelConfig(modelProvider, modelId, apiKey);
|
|
214
|
-
s.stop('Configuration saved ✓');
|
|
215
|
-
outro(`Model configured: ${provider.name} - ${modelId}\n`);
|
|
216
|
-
}
|
|
217
|
-
}
|
|
218
|
-
// Validate we have all required config
|
|
219
|
-
if (!modelProvider || !modelId) {
|
|
220
|
-
console.error('❌ Model configuration incomplete');
|
|
63
|
+
const modelProvider = resolveProvider(userConfig, config);
|
|
64
|
+
const modelId = resolveModelId(userConfig, config);
|
|
65
|
+
const apiKey = resolveApiKey(userConfig, config);
|
|
66
|
+
if (!apiKey) {
|
|
67
|
+
console.error('❌ No API key configured. Run `studiograph config` to set one up.');
|
|
221
68
|
process.exit(1);
|
|
222
69
|
}
|
|
223
|
-
// Check if we need API key for this provider
|
|
224
|
-
const provider = MODEL_PROVIDERS[modelProvider];
|
|
225
|
-
if (provider?.requiresApiKey && !apiKey) {
|
|
226
|
-
const envKey = process.env[provider.envVar];
|
|
227
|
-
if (envKey) {
|
|
228
|
-
apiKey = envKey;
|
|
229
|
-
}
|
|
230
|
-
else {
|
|
231
|
-
console.error(`❌ API key required for ${provider.name}`);
|
|
232
|
-
console.error(` Set ${provider.envVar} environment variable or run setup again`);
|
|
233
|
-
process.exit(1);
|
|
234
|
-
}
|
|
235
|
-
}
|
|
236
70
|
// Initialize memory service
|
|
237
71
|
const memoryService = new MemoryService();
|
|
238
72
|
const recentMemory = memoryService.loadRecentMemory();
|
|
239
73
|
// Initialize workspace manager
|
|
240
74
|
const gitUser = { id: 'cli-user', name: config.team_name, email: 'noreply@studiograph.local' };
|
|
241
|
-
const
|
|
242
|
-
const workspaceManager = new WorkspaceManager(process.cwd(), config, gitUser, cliUser);
|
|
75
|
+
const workspaceManager = new WorkspaceManager(process.cwd(), config, gitUser);
|
|
243
76
|
// Discover app-bundled skill and tool directories
|
|
244
77
|
const appsDir = join(process.cwd(), '.studiograph', 'apps');
|
|
245
78
|
const loader = new PluginLoader();
|
|
@@ -309,10 +142,15 @@ export const startCommand = new Command('start')
|
|
|
309
142
|
await initSearchIndex(workspaceManager, config.repos, process.cwd());
|
|
310
143
|
const totalTools = agent.state.tools.length;
|
|
311
144
|
const memoryDays = memoryService.listMemoryFiles().length;
|
|
145
|
+
const hasSemanticSearch = !!loadUserConfig().voyage_api_key;
|
|
146
|
+
const searchStatus = hasSemanticSearch
|
|
147
|
+
? 'semantic'
|
|
148
|
+
: `keyword ${dimText('(run studiograph config to enable semantic search)')}`;
|
|
312
149
|
console.log(box([
|
|
313
150
|
`Model: ${header(modelProvider + '/' + modelId)}`,
|
|
314
151
|
`Tools: ${totalTools} registered${connectorSummary ? ` (${connectorSummary})` : ''}`,
|
|
315
152
|
`Memory: ${memoryDays} day${memoryDays === 1 ? '' : 's'} loaded`,
|
|
153
|
+
`Search: ${searchStatus}`,
|
|
316
154
|
].join('\n'), {
|
|
317
155
|
title: `Studiograph — ${config.team_name}`,
|
|
318
156
|
style: { borderColor: 'cyan', padding: 1 },
|
|
@@ -579,27 +417,6 @@ async function initSearchIndex(workspaceManager, repos, workspacePath) {
|
|
|
579
417
|
// First-run: no repos have been indexed yet
|
|
580
418
|
const isFirstRun = repos.every(r => !vectorService.getLastIndexedTime(r.name));
|
|
581
419
|
if (isFirstRun) {
|
|
582
|
-
// Prompt for Voyage AI key (optional)
|
|
583
|
-
if (!userConfig.voyage_api_key) {
|
|
584
|
-
const choice = await select({
|
|
585
|
-
message: 'Enable semantic search? (optional)',
|
|
586
|
-
options: [
|
|
587
|
-
{ value: 'skip', label: 'Skip — use FTS keyword search', hint: 'No setup required' },
|
|
588
|
-
{ value: 'voyage', label: 'Enable semantic search', hint: 'Voyage AI key required' },
|
|
589
|
-
],
|
|
590
|
-
});
|
|
591
|
-
if (choice === 'voyage' && typeof choice === 'string') {
|
|
592
|
-
const keyInput = await text({
|
|
593
|
-
message: 'Enter your Voyage AI API key:',
|
|
594
|
-
placeholder: 'pa-...',
|
|
595
|
-
validate: (v) => (!v || v.length < 10 ? 'Key seems too short' : undefined),
|
|
596
|
-
});
|
|
597
|
-
if (typeof keyInput === 'string') {
|
|
598
|
-
userConfig.voyage_api_key = keyInput;
|
|
599
|
-
saveUserConfig(userConfig);
|
|
600
|
-
}
|
|
601
|
-
}
|
|
602
|
-
}
|
|
603
420
|
// Full index on first run
|
|
604
421
|
const s = spinner();
|
|
605
422
|
s.start('Indexing workspace for search...');
|