studiograph 1.1.2 → 1.2.0-beta.1
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 +301 -10
- package/dist/agent/orchestrator.d.ts +17 -9
- package/dist/agent/orchestrator.js +142 -97
- package/dist/agent/orchestrator.js.map +1 -1
- package/dist/agent/prompts/system.md +186 -0
- package/dist/agent/skill-loader.d.ts +48 -0
- package/dist/agent/skill-loader.js +166 -0
- package/dist/agent/skill-loader.js.map +1 -0
- package/dist/agent/skills/enrich-entities.md +136 -0
- package/dist/agent/skills/entity-schema.md +502 -0
- package/dist/agent/skills/gather-context.md +46 -0
- package/dist/agent/skills/obsidian-source-setup.md +246 -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/skills/sync-configuration.md +144 -0
- package/dist/agent/skills/sync-setup.md +68 -0
- package/dist/agent/tools/connector-tools.d.ts +37 -0
- package/dist/agent/tools/connector-tools.js +132 -0
- package/dist/agent/tools/connector-tools.js.map +1 -0
- package/dist/agent/tools/fs-tools.d.ts +39 -0
- package/dist/agent/tools/fs-tools.js +106 -0
- package/dist/agent/tools/fs-tools.js.map +1 -0
- package/dist/agent/tools/graph-tools.d.ts +30 -2
- package/dist/agent/tools/graph-tools.js +154 -37
- 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/sync-tools.d.ts +25 -0
- package/dist/agent/tools/sync-tools.js +691 -0
- package/dist/agent/tools/sync-tools.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/auth/github.d.ts +11 -8
- package/dist/auth/github.js +56 -75
- package/dist/auth/github.js.map +1 -1
- package/dist/cli/colors.d.ts +54 -0
- package/dist/cli/colors.js +133 -0
- package/dist/cli/colors.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/auth.d.ts +1 -1
- package/dist/cli/commands/auth.js +26 -10
- package/dist/cli/commands/auth.js.map +1 -1
- package/dist/cli/commands/clone.d.ts +9 -0
- package/dist/cli/commands/clone.js +167 -0
- package/dist/cli/commands/clone.js.map +1 -0
- package/dist/cli/commands/commit.d.ts +8 -0
- package/dist/cli/commands/commit.js +43 -0
- package/dist/cli/commands/commit.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 +178 -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/enrich.d.ts +11 -0
- package/dist/cli/commands/enrich.js +135 -0
- package/dist/cli/commands/enrich.js.map +1 -0
- package/dist/cli/commands/graphrag.d.ts +12 -0
- package/dist/cli/commands/graphrag.js +122 -0
- package/dist/cli/commands/graphrag.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 -210
- package/dist/cli/commands/init.js.map +1 -1
- package/dist/cli/commands/join.js +89 -24
- 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/orphans.d.ts +8 -0
- package/dist/cli/commands/orphans.js +125 -0
- package/dist/cli/commands/orphans.js.map +1 -0
- package/dist/cli/commands/provision.d.ts +8 -0
- package/dist/cli/commands/provision.js +116 -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 +87 -6
- package/dist/cli/commands/r2.js.map +1 -1
- package/dist/cli/commands/reset.d.ts +12 -0
- package/dist/cli/commands/reset.js +137 -0
- package/dist/cli/commands/reset.js.map +1 -0
- package/dist/cli/commands/review.d.ts +19 -0
- package/dist/cli/commands/review.js +128 -0
- package/dist/cli/commands/review.js.map +1 -0
- package/dist/cli/commands/serve.js +47 -2
- package/dist/cli/commands/serve.js.map +1 -1
- package/dist/cli/commands/source.d.ts +16 -0
- package/dist/cli/commands/source.js +159 -0
- package/dist/cli/commands/source.js.map +1 -0
- package/dist/cli/commands/start.js +472 -103
- package/dist/cli/commands/start.js.map +1 -1
- package/dist/cli/commands/sync-entities.d.ts +13 -0
- package/dist/cli/commands/sync-entities.js +242 -0
- package/dist/cli/commands/sync-entities.js.map +1 -0
- package/dist/cli/commands/sync.js +40 -9
- 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 +114 -3
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/scaffolding.d.ts +10 -0
- package/dist/cli/scaffolding.js +302 -0
- package/dist/cli/scaffolding.js.map +1 -0
- package/dist/cli/setup-wizard.d.ts +30 -0
- package/dist/cli/setup-wizard.js +244 -0
- package/dist/cli/setup-wizard.js.map +1 -0
- package/dist/cli/sync-review-interactive.d.ts +31 -0
- package/dist/cli/sync-review-interactive.js +393 -0
- package/dist/cli/sync-review-interactive.js.map +1 -0
- package/dist/cli/theme.d.ts +31 -0
- package/dist/cli/theme.js +116 -0
- package/dist/cli/theme.js.map +1 -0
- package/dist/core/graph.d.ts +16 -9
- package/dist/core/graph.js +263 -145
- 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/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 -3
- package/dist/core/types.js +21 -2
- package/dist/core/types.js.map +1 -1
- package/dist/core/user-config.d.ts +16 -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 +20 -11
- package/dist/core/workspace.js +123 -34
- package/dist/core/workspace.js.map +1 -1
- package/dist/mcp/connector-manager.d.ts +65 -0
- package/dist/mcp/connector-manager.js +223 -0
- package/dist/mcp/connector-manager.js.map +1 -0
- package/dist/mcp/connectors/asana.d.ts +2 -0
- package/dist/mcp/connectors/asana.js +20 -0
- package/dist/mcp/connectors/asana.js.map +1 -0
- package/dist/mcp/connectors/definitions.d.ts +45 -0
- package/dist/mcp/connectors/definitions.js +32 -0
- package/dist/mcp/connectors/definitions.js.map +1 -0
- package/dist/mcp/connectors/figma.d.ts +5 -0
- package/dist/mcp/connectors/figma.js +21 -0
- package/dist/mcp/connectors/figma.js.map +1 -0
- package/dist/mcp/connectors/gdrive.d.ts +2 -0
- package/dist/mcp/connectors/gdrive.js +20 -0
- package/dist/mcp/connectors/gdrive.js.map +1 -0
- package/dist/mcp/connectors/granola.d.ts +2 -0
- package/dist/mcp/connectors/granola.js +12 -0
- package/dist/mcp/connectors/granola.js.map +1 -0
- package/dist/mcp/connectors/linear.d.ts +2 -0
- package/dist/mcp/connectors/linear.js +19 -0
- package/dist/mcp/connectors/linear.js.map +1 -0
- package/dist/mcp/connectors/obsidian.d.ts +2 -0
- package/dist/mcp/connectors/obsidian.js +19 -0
- package/dist/mcp/connectors/obsidian.js.map +1 -0
- package/dist/mcp/connectors/pipedrive.d.ts +2 -0
- package/dist/mcp/connectors/pipedrive.js +20 -0
- package/dist/mcp/connectors/pipedrive.js.map +1 -0
- package/dist/mcp/connectors/slack.d.ts +2 -0
- package/dist/mcp/connectors/slack.js +21 -0
- package/dist/mcp/connectors/slack.js.map +1 -0
- package/dist/mcp/oauth-provider.d.ts +41 -0
- package/dist/mcp/oauth-provider.js +160 -0
- package/dist/mcp/oauth-provider.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 +15 -0
- package/dist/server/plugin-loader.js +68 -2
- 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 +9 -3
- package/dist/services/github-provisioner.js +46 -8
- package/dist/services/github-provisioner.js.map +1 -1
- package/dist/services/lint-service.d.ts +27 -0
- package/dist/services/lint-service.js +83 -0
- package/dist/services/lint-service.js.map +1 -0
- package/dist/services/markdown.d.ts +9 -0
- package/dist/services/markdown.js +26 -5
- package/dist/services/markdown.js.map +1 -1
- package/dist/services/memory-service.d.ts +1 -2
- package/dist/services/memory-service.js +5 -4
- package/dist/services/memory-service.js.map +1 -1
- package/dist/services/orphan-service.d.ts +31 -0
- package/dist/services/orphan-service.js +100 -0
- package/dist/services/orphan-service.js.map +1 -0
- package/dist/services/sync/commit.d.ts +58 -0
- package/dist/services/sync/commit.js +350 -0
- package/dist/services/sync/commit.js.map +1 -0
- package/dist/services/sync/context-index.d.ts +69 -0
- package/dist/services/sync/context-index.js +280 -0
- package/dist/services/sync/context-index.js.map +1 -0
- package/dist/services/sync/derive.d.ts +34 -0
- package/dist/services/sync/derive.js +164 -0
- package/dist/services/sync/derive.js.map +1 -0
- package/dist/services/sync/enrichment-state.d.ts +31 -0
- package/dist/services/sync/enrichment-state.js +63 -0
- package/dist/services/sync/enrichment-state.js.map +1 -0
- package/dist/services/sync/enrichment.d.ts +25 -0
- package/dist/services/sync/enrichment.js +121 -0
- package/dist/services/sync/enrichment.js.map +1 -0
- package/dist/services/sync/frontmatter-extractor.d.ts +40 -0
- package/dist/services/sync/frontmatter-extractor.js +273 -0
- package/dist/services/sync/frontmatter-extractor.js.map +1 -0
- package/dist/services/sync/graph-match-state.d.ts +33 -0
- package/dist/services/sync/graph-match-state.js +61 -0
- package/dist/services/sync/graph-match-state.js.map +1 -0
- package/dist/services/sync/graph-match.d.ts +53 -0
- package/dist/services/sync/graph-match.js +316 -0
- package/dist/services/sync/graph-match.js.map +1 -0
- package/dist/services/sync/graphrag-client.d.ts +43 -0
- package/dist/services/sync/graphrag-client.js +94 -0
- package/dist/services/sync/graphrag-client.js.map +1 -0
- package/dist/services/sync/graphrag-config.d.ts +16 -0
- package/dist/services/sync/graphrag-config.js +39 -0
- package/dist/services/sync/graphrag-config.js.map +1 -0
- package/dist/services/sync/graphrag-context.d.ts +14 -0
- package/dist/services/sync/graphrag-context.js +109 -0
- package/dist/services/sync/graphrag-context.js.map +1 -0
- package/dist/services/sync/graphrag-indexer.d.ts +30 -0
- package/dist/services/sync/graphrag-indexer.js +358 -0
- package/dist/services/sync/graphrag-indexer.js.map +1 -0
- package/dist/services/sync/llm.d.ts +32 -0
- package/dist/services/sync/llm.js +115 -0
- package/dist/services/sync/llm.js.map +1 -0
- package/dist/services/sync/mcp-client.d.ts +59 -0
- package/dist/services/sync/mcp-client.js +285 -0
- package/dist/services/sync/mcp-client.js.map +1 -0
- package/dist/services/sync/model-factory.d.ts +10 -0
- package/dist/services/sync/model-factory.js +24 -0
- package/dist/services/sync/model-factory.js.map +1 -0
- package/dist/services/sync/name-quality.d.ts +31 -0
- package/dist/services/sync/name-quality.js +60 -0
- package/dist/services/sync/name-quality.js.map +1 -0
- package/dist/services/sync/output-schemas.d.ts +92 -0
- package/dist/services/sync/output-schemas.js +43 -0
- package/dist/services/sync/output-schemas.js.map +1 -0
- package/dist/services/sync/prompts.d.ts +19 -0
- package/dist/services/sync/prompts.js +128 -0
- package/dist/services/sync/prompts.js.map +1 -0
- package/dist/services/sync/reconciler.d.ts +48 -0
- package/dist/services/sync/reconciler.js +295 -0
- package/dist/services/sync/reconciler.js.map +1 -0
- package/dist/services/sync/source-config.d.ts +45 -0
- package/dist/services/sync/source-config.js +208 -0
- package/dist/services/sync/source-config.js.map +1 -0
- package/dist/services/sync/source-definitions/asana.d.ts +15 -0
- package/dist/services/sync/source-definitions/asana.js +48 -0
- package/dist/services/sync/source-definitions/asana.js.map +1 -0
- package/dist/services/sync/source-definitions/definitions.d.ts +21 -0
- package/dist/services/sync/source-definitions/definitions.js +26 -0
- package/dist/services/sync/source-definitions/definitions.js.map +1 -0
- package/dist/services/sync/source-definitions/gdrive.d.ts +16 -0
- package/dist/services/sync/source-definitions/gdrive.js +68 -0
- package/dist/services/sync/source-definitions/gdrive.js.map +1 -0
- package/dist/services/sync/source-definitions/granola.d.ts +2 -0
- package/dist/services/sync/source-definitions/granola.js +28 -0
- package/dist/services/sync/source-definitions/granola.js.map +1 -0
- package/dist/services/sync/source-definitions/linear.d.ts +2 -0
- package/dist/services/sync/source-definitions/linear.js +60 -0
- package/dist/services/sync/source-definitions/linear.js.map +1 -0
- package/dist/services/sync/source-definitions/obsidian.d.ts +2 -0
- package/dist/services/sync/source-definitions/obsidian.js +55 -0
- package/dist/services/sync/source-definitions/obsidian.js.map +1 -0
- package/dist/services/sync/source-definitions/pipedrive.d.ts +2 -0
- package/dist/services/sync/source-definitions/pipedrive.js +52 -0
- package/dist/services/sync/source-definitions/pipedrive.js.map +1 -0
- package/dist/services/sync/staging.d.ts +53 -0
- package/dist/services/sync/staging.js +131 -0
- package/dist/services/sync/staging.js.map +1 -0
- package/dist/services/sync/structured-extractor.d.ts +49 -0
- package/dist/services/sync/structured-extractor.js +344 -0
- package/dist/services/sync/structured-extractor.js.map +1 -0
- package/dist/services/sync/sync-runner.d.ts +32 -0
- package/dist/services/sync/sync-runner.js +195 -0
- package/dist/services/sync/sync-runner.js.map +1 -0
- package/dist/services/sync/sync-state.d.ts +43 -0
- package/dist/services/sync/sync-state.js +154 -0
- package/dist/services/sync/sync-state.js.map +1 -0
- package/dist/services/sync/types.d.ts +203 -0
- package/dist/services/sync/types.js +8 -0
- package/dist/services/sync/types.js.map +1 -0
- package/dist/services/sync/unstructured-extractor.d.ts +29 -0
- package/dist/services/sync/unstructured-extractor.js +197 -0
- package/dist/services/sync/unstructured-extractor.js.map +1 -0
- package/dist/services/vector-service.d.ts +88 -0
- package/dist/services/vector-service.js +322 -0
- package/dist/services/vector-service.js.map +1 -0
- package/dist/utils/git.d.ts +26 -4
- package/dist/utils/git.js +55 -7
- package/dist/utils/git.js.map +1 -1
- package/dist/utils/merge-resolver.d.ts +34 -0
- package/dist/utils/merge-resolver.js +201 -0
- package/dist/utils/merge-resolver.js.map +1 -0
- package/dist/utils/preflight.d.ts +2 -1
- package/dist/utils/preflight.js +8 -1
- package/dist/utils/preflight.js.map +1 -1
- 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/dist/utils/workspace-config.d.ts +8 -0
- package/dist/utils/workspace-config.js +22 -0
- package/dist/utils/workspace-config.js.map +1 -0
- package/package.json +24 -11
|
@@ -4,234 +4,126 @@
|
|
|
4
4
|
* Initializes a new Studiograph workspace in the current directory
|
|
5
5
|
*/
|
|
6
6
|
import { Command } from 'commander';
|
|
7
|
-
import { intro, text,
|
|
7
|
+
import { intro, text, confirm, outro, spinner, log } from '@clack/prompts';
|
|
8
|
+
import { existsSync, mkdirSync, writeFileSync, readFileSync, appendFileSync } from 'fs';
|
|
9
|
+
import { execSync } from 'child_process';
|
|
10
|
+
import { join, resolve } from 'path';
|
|
8
11
|
import { Workspace } from '../../core/workspace.js';
|
|
9
|
-
import {
|
|
10
|
-
import { loadToken, runDeviceFlow, storeToken, getGitHubUser, getAuthenticatedOctokit } from '../../auth/github.js';
|
|
12
|
+
import { loadToken, promptForPAT, storeToken, getGitHubUser, getAuthenticatedOctokit } from '../../auth/github.js';
|
|
11
13
|
import { provisionWorkspace } from '../../services/github-provisioner.js';
|
|
12
14
|
import { runPreflight } from '../../utils/preflight.js';
|
|
13
|
-
// Industry templates configuration
|
|
14
|
-
const INDUSTRY_TEMPLATES = {
|
|
15
|
-
'design-studio': {
|
|
16
|
-
name: 'Design & production studio',
|
|
17
|
-
description: 'Product design teams, UX/UI agencies, design consultancies',
|
|
18
|
-
pattern: 'client-centric',
|
|
19
|
-
functionRepos: [
|
|
20
|
-
{ name: 'new-business', description: 'Proposals, pitches, and business development' },
|
|
21
|
-
{ name: 'accounting', description: 'Financials, billing, and budgets (restricted)' },
|
|
22
|
-
{ name: 'operations', description: 'Team capacity, processes, and policies' },
|
|
23
|
-
],
|
|
24
|
-
sharedRepos: [
|
|
25
|
-
{ name: 'templates', description: 'Proposal templates, processes, and standards' },
|
|
26
|
-
{ name: 'design-systems', description: 'Reusable components, patterns, and tokens' },
|
|
27
|
-
{ name: 'research', description: 'Design references, techniques, and inspiration' },
|
|
28
|
-
],
|
|
29
|
-
},
|
|
30
|
-
'marketing-agency': {
|
|
31
|
-
name: 'Marketing & communications agency',
|
|
32
|
-
description: 'Advertising, digital marketing, social, content, PR',
|
|
33
|
-
pattern: 'project-centric',
|
|
34
|
-
functionRepos: [
|
|
35
|
-
{ name: 'pitches', description: 'New business pitches and campaign proposals' },
|
|
36
|
-
{ name: 'media-planning', description: 'Media budgets, buys, and performance tracking' },
|
|
37
|
-
{ name: 'finance', description: 'Project budgets and billing (restricted)' },
|
|
38
|
-
],
|
|
39
|
-
sharedRepos: [
|
|
40
|
-
{ name: 'brand-guidelines', description: 'Client brand standards and messaging' },
|
|
41
|
-
{ name: 'creative-library', description: 'Stock assets, campaign references, and tools' },
|
|
42
|
-
{ name: 'production-resources', description: 'Vendor database and production resources' },
|
|
43
|
-
],
|
|
44
|
-
},
|
|
45
|
-
'content-shop': {
|
|
46
|
-
name: 'Content & storytelling shop',
|
|
47
|
-
description: 'Film/video production, editorial, podcast studios',
|
|
48
|
-
pattern: 'project-centric',
|
|
49
|
-
functionRepos: [
|
|
50
|
-
{ name: 'pitches', description: 'Content proposals and treatments' },
|
|
51
|
-
{ name: 'production-ops', description: 'Crew database, equipment, and schedules' },
|
|
52
|
-
{ name: 'finance', description: 'Production budgets and freelance rates (restricted)' },
|
|
53
|
-
],
|
|
54
|
-
sharedRepos: [
|
|
55
|
-
{ name: 'editorial-guidelines', description: 'Voice, tone, and editorial standards' },
|
|
56
|
-
{ name: 'content-library', description: 'Stock footage, music, and graphics templates' },
|
|
57
|
-
{ name: 'reference-library', description: 'Film references and storytelling techniques' },
|
|
58
|
-
],
|
|
59
|
-
},
|
|
60
|
-
'experiential-firm': {
|
|
61
|
-
name: 'Experiential & environmental firm',
|
|
62
|
-
description: 'Event/experiential agencies, exhibition design, installations',
|
|
63
|
-
pattern: 'client-centric',
|
|
64
|
-
functionRepos: [
|
|
65
|
-
{ name: 'business-development', description: 'Event proposals and exhibition pitches' },
|
|
66
|
-
{ name: 'production-management', description: 'Vendor coordination and installation planning' },
|
|
67
|
-
{ name: 'finance', description: 'Project budgets and vendor payments (restricted)' },
|
|
68
|
-
],
|
|
69
|
-
sharedRepos: [
|
|
70
|
-
{ name: 'installation-library', description: 'Past installations and technical specs' },
|
|
71
|
-
{ name: 'vendor-database', description: 'Fabricators, AV vendors, and specialists' },
|
|
72
|
-
{ name: 'reference-library', description: 'Experiential examples and spatial design' },
|
|
73
|
-
],
|
|
74
|
-
},
|
|
75
|
-
'digital-studio': {
|
|
76
|
-
name: 'Digital product & technology studio',
|
|
77
|
-
description: 'Web/app studios, product design + engineering firms',
|
|
78
|
-
pattern: 'project-centric',
|
|
79
|
-
functionRepos: [
|
|
80
|
-
{ name: 'proposals', description: 'SOWs, estimates, and technical proposals' },
|
|
81
|
-
{ name: 'operations', description: 'Capacity planning and sprint tracking' },
|
|
82
|
-
{ name: 'finance', description: 'Project budgets and contractor rates (restricted)' },
|
|
83
|
-
],
|
|
84
|
-
sharedRepos: [
|
|
85
|
-
{ name: 'architecture', description: 'System design patterns and tech standards' },
|
|
86
|
-
{ name: 'codebase', description: 'Reusable components and integrations' },
|
|
87
|
-
{ name: 'product-references', description: 'Competitor analysis and UX patterns' },
|
|
88
|
-
],
|
|
89
|
-
},
|
|
90
|
-
'consulting-firm': {
|
|
91
|
-
name: 'Strategy, consulting & innovation firm',
|
|
92
|
-
description: 'Brand/innovation consultancies, service design firms',
|
|
93
|
-
pattern: 'client-centric',
|
|
94
|
-
functionRepos: [
|
|
95
|
-
{ name: 'proposals', description: 'Strategic proposals and workshop proposals' },
|
|
96
|
-
{ name: 'research-ops', description: 'Research methodologies and participant recruiting' },
|
|
97
|
-
{ name: 'finance', description: 'Engagement budgets and billing (restricted)' },
|
|
98
|
-
],
|
|
99
|
-
sharedRepos: [
|
|
100
|
-
{ name: 'frameworks', description: 'Strategy frameworks and innovation toolkits' },
|
|
101
|
-
{ name: 'research-library', description: 'Market research and competitive intelligence' },
|
|
102
|
-
{ name: 'case-studies', description: 'Past engagements and outcomes' },
|
|
103
|
-
],
|
|
104
|
-
},
|
|
105
|
-
'architecture-studio': {
|
|
106
|
-
name: 'Architecture studio',
|
|
107
|
-
description: 'Architectural design practices',
|
|
108
|
-
pattern: 'client-centric',
|
|
109
|
-
functionRepos: [
|
|
110
|
-
{ name: 'proposals', description: 'RFPs, competition entries, and fee proposals' },
|
|
111
|
-
{ name: 'project-management', description: 'Construction admin and permitting' },
|
|
112
|
-
{ name: 'finance', description: 'Project budgets and consultant fees (restricted)' },
|
|
113
|
-
],
|
|
114
|
-
sharedRepos: [
|
|
115
|
-
{ name: 'standards', description: 'Building codes and accessibility standards' },
|
|
116
|
-
{ name: 'details-library', description: 'Construction details and material specs' },
|
|
117
|
-
{ name: 'precedent-studies', description: 'Architectural references and site analyses' },
|
|
118
|
-
],
|
|
119
|
-
},
|
|
120
|
-
'creative-tech': {
|
|
121
|
-
name: 'Creative technology firm',
|
|
122
|
-
description: 'Interactive/immersive studios, creative R&D labs',
|
|
123
|
-
pattern: 'project-centric',
|
|
124
|
-
functionRepos: [
|
|
125
|
-
{ name: 'proposals', description: 'R&D proposals and prototyping scopes' },
|
|
126
|
-
{ name: 'lab-operations', description: 'Equipment inventory and prototyping resources' },
|
|
127
|
-
{ name: 'finance', description: 'Project budgets and hardware costs (restricted)' },
|
|
128
|
-
],
|
|
129
|
-
sharedRepos: [
|
|
130
|
-
{ name: 'technical-library', description: 'Code patterns and hardware specs' },
|
|
131
|
-
{ name: 'prototype-archive', description: 'Past experiments and learnings' },
|
|
132
|
-
{ name: 'tech-references', description: 'Emerging tech and academic papers' },
|
|
133
|
-
],
|
|
134
|
-
},
|
|
135
|
-
};
|
|
136
15
|
export const initCommand = new Command('init')
|
|
137
|
-
.description('Initialize a new Studiograph workspace
|
|
138
|
-
.
|
|
16
|
+
.description('Initialize a new Studiograph workspace')
|
|
17
|
+
.argument('<team-name>', 'Name of your team (e.g., "Acme Studios")')
|
|
18
|
+
.argument('[directory]', 'Directory to create workspace in (default: derived from team name, use "." for current directory)')
|
|
19
|
+
.option('--bare', 'Skip starter repos and example entities')
|
|
139
20
|
.option('--github', 'Automatically create GitHub repos after init')
|
|
140
21
|
.option('--github-org <org>', 'GitHub org to create repos in (implies --github)')
|
|
141
|
-
.action(async (options) => {
|
|
22
|
+
.action(async (teamName, directory, options) => {
|
|
142
23
|
intro('Studiograph Workspace Setup');
|
|
143
24
|
const ready = runPreflight();
|
|
144
25
|
if (!ready) {
|
|
145
26
|
process.exit(1);
|
|
146
27
|
return;
|
|
147
28
|
}
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
if (
|
|
151
|
-
|
|
29
|
+
// Determine target directory
|
|
30
|
+
let targetDir;
|
|
31
|
+
if (directory === '.') {
|
|
32
|
+
// Use current directory (must be empty or non-existent)
|
|
33
|
+
targetDir = process.cwd();
|
|
34
|
+
const workspace = new Workspace(targetDir);
|
|
35
|
+
if (workspace.isWorkspace()) {
|
|
36
|
+
outro('❌ Already a Studiograph workspace');
|
|
37
|
+
process.exit(1);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
else if (directory) {
|
|
41
|
+
// Use specified directory
|
|
42
|
+
targetDir = resolve(directory);
|
|
43
|
+
}
|
|
44
|
+
else {
|
|
45
|
+
// Auto-generate from team name slug
|
|
46
|
+
const slug = teamName.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-+|-+$/g, '');
|
|
47
|
+
targetDir = resolve(slug);
|
|
48
|
+
}
|
|
49
|
+
// Check if target directory exists and has .studiograph
|
|
50
|
+
const studiographDir = join(targetDir, '.studiograph');
|
|
51
|
+
if (existsSync(studiographDir)) {
|
|
52
|
+
outro(`❌ A .studiograph directory already exists at ${targetDir}`);
|
|
152
53
|
process.exit(1);
|
|
153
54
|
}
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
const firmType = await select({
|
|
159
|
-
message: 'What type of creative firm are you?',
|
|
160
|
-
options: [
|
|
161
|
-
{ value: 'design-studio', label: 'Design & production studio', hint: 'Product design, UX/UI, branding' },
|
|
162
|
-
{ value: 'marketing-agency', label: 'Marketing & communications agency', hint: 'Advertising, digital marketing, PR' },
|
|
163
|
-
{ value: 'content-shop', label: 'Content & storytelling shop', hint: 'Film/video production, editorial' },
|
|
164
|
-
{ value: 'experiential-firm', label: 'Experiential & environmental firm', hint: 'Events, exhibitions, installations' },
|
|
165
|
-
{ value: 'digital-studio', label: 'Digital product & technology studio', hint: 'Web/app studios, product teams' },
|
|
166
|
-
{ value: 'consulting-firm', label: 'Strategy, consulting & innovation firm', hint: 'Brand consultancies, service design' },
|
|
167
|
-
{ value: 'architecture-studio', label: 'Architecture studio', hint: 'Architectural design practices' },
|
|
168
|
-
{ value: 'creative-tech', label: 'Creative technology firm', hint: 'Interactive, immersive, R&D labs' },
|
|
169
|
-
{ value: 'bare', label: 'Bare (custom setup)', hint: 'No scaffolding, build your own' },
|
|
170
|
-
],
|
|
171
|
-
});
|
|
172
|
-
if (typeof firmType === 'symbol' || !firmType) {
|
|
173
|
-
outro('Cancelled');
|
|
174
|
-
process.exit(0);
|
|
175
|
-
}
|
|
176
|
-
selectedTemplate = firmType === 'bare' ? null : firmType;
|
|
55
|
+
// Create target directory if needed
|
|
56
|
+
if (!existsSync(targetDir)) {
|
|
57
|
+
mkdirSync(targetDir, { recursive: true });
|
|
58
|
+
log.info(`Created directory: ${targetDir}`);
|
|
177
59
|
}
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
60
|
+
else if (directory !== '.') {
|
|
61
|
+
// Directory exists but is not current dir - check if empty
|
|
62
|
+
const { readdirSync } = await import('fs');
|
|
63
|
+
const files = readdirSync(targetDir);
|
|
64
|
+
if (files.length > 0) {
|
|
65
|
+
const proceed = await confirm({
|
|
66
|
+
message: `Directory ${targetDir} is not empty. Continue anyway?`,
|
|
67
|
+
initialValue: false,
|
|
68
|
+
});
|
|
69
|
+
if (!proceed || typeof proceed === 'symbol') {
|
|
70
|
+
outro('Cancelled');
|
|
71
|
+
process.exit(0);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
190
74
|
}
|
|
191
75
|
// Initialize workspace
|
|
76
|
+
const workspace = new Workspace(targetDir);
|
|
77
|
+
workspace.quietMigrations = true;
|
|
192
78
|
const s = spinner();
|
|
193
79
|
s.start('Creating workspace...');
|
|
194
80
|
try {
|
|
195
81
|
workspace.init(teamName);
|
|
196
82
|
s.stop('Workspace created');
|
|
197
|
-
//
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
// Create shared resource repos
|
|
210
|
-
for (const repo of template.sharedRepos) {
|
|
211
|
-
workspace.registerRepo({
|
|
212
|
-
name: repo.name,
|
|
213
|
-
type: RepoType.SHARED_RESOURCE,
|
|
214
|
-
description: repo.description,
|
|
215
|
-
});
|
|
83
|
+
// Create private/ directory and add to .gitignore
|
|
84
|
+
const workspacePath = workspace.getWorkspacePath();
|
|
85
|
+
const privatePath = join(workspacePath, 'private');
|
|
86
|
+
if (!existsSync(privatePath)) {
|
|
87
|
+
mkdirSync(privatePath, { recursive: true });
|
|
88
|
+
}
|
|
89
|
+
const gitignorePath = join(workspacePath, '.gitignore');
|
|
90
|
+
const entry = 'private/';
|
|
91
|
+
if (existsSync(gitignorePath)) {
|
|
92
|
+
const content = readFileSync(gitignorePath, 'utf-8');
|
|
93
|
+
if (!content.split('\n').some((line) => line.trim() === entry)) {
|
|
94
|
+
appendFileSync(gitignorePath, `\n${entry}\n`);
|
|
216
95
|
}
|
|
217
|
-
|
|
96
|
+
}
|
|
97
|
+
else {
|
|
98
|
+
writeFileSync(gitignorePath, `${entry}\n`);
|
|
99
|
+
}
|
|
100
|
+
// Scaffold starter repos and example entities (unless --bare)
|
|
101
|
+
if (!options.bare) {
|
|
102
|
+
s.start('Creating example entities...');
|
|
103
|
+
const { scaffoldExampleEntities } = await import('../scaffolding.js');
|
|
104
|
+
await scaffoldExampleEntities(workspace, teamName);
|
|
105
|
+
s.stop('Example entities created');
|
|
218
106
|
}
|
|
219
107
|
// --- GitHub provisioning ---
|
|
220
108
|
const wantsGitHub = options.githubOrg || options.github;
|
|
221
109
|
let shouldProvision = wantsGitHub;
|
|
222
110
|
if (!wantsGitHub) {
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
111
|
+
// Only ask about GitHub if auth is already configured
|
|
112
|
+
const hasToken = !!loadToken();
|
|
113
|
+
if (hasToken) {
|
|
114
|
+
const answer = await confirm({
|
|
115
|
+
message: 'Would you like to create these repos on GitHub?',
|
|
116
|
+
initialValue: false,
|
|
117
|
+
});
|
|
118
|
+
shouldProvision = answer === true;
|
|
119
|
+
}
|
|
228
120
|
}
|
|
229
121
|
if (shouldProvision) {
|
|
230
122
|
// Ensure we have a token
|
|
231
123
|
let stored = loadToken();
|
|
232
124
|
if (!stored) {
|
|
233
125
|
log.info('No GitHub token found. Starting authentication...');
|
|
234
|
-
const token = await
|
|
126
|
+
const token = await promptForPAT();
|
|
235
127
|
const user = await getGitHubUser(token);
|
|
236
128
|
storeToken(token, user);
|
|
237
129
|
stored = { token, user };
|
|
@@ -253,11 +145,11 @@ export const initCommand = new Command('init')
|
|
|
253
145
|
githubOrg = orgInput;
|
|
254
146
|
}
|
|
255
147
|
const octokit = getAuthenticatedOctokit(stored.token);
|
|
256
|
-
const currentConfig = workspace.loadConfig();
|
|
148
|
+
const currentConfig = await workspace.loadConfig();
|
|
257
149
|
const provisionSpinner = spinner();
|
|
258
150
|
provisionSpinner.start('Creating GitHub repos...');
|
|
259
151
|
try {
|
|
260
|
-
const
|
|
152
|
+
const result = await provisionWorkspace({
|
|
261
153
|
octokit,
|
|
262
154
|
org: githubOrg,
|
|
263
155
|
workspacePath: workspace.getWorkspacePath(),
|
|
@@ -265,15 +157,27 @@ export const initCommand = new Command('init')
|
|
|
265
157
|
onProgress: (msg) => provisionSpinner.message(msg),
|
|
266
158
|
});
|
|
267
159
|
// Write back updated config with github_urls + org
|
|
268
|
-
|
|
269
|
-
workspace.writeConfig(
|
|
160
|
+
result.config.github = { org: githubOrg };
|
|
161
|
+
workspace.writeConfig(result.config);
|
|
162
|
+
// Push updated workspace.json back to config repo
|
|
163
|
+
provisionSpinner.message('Updating config repo with GitHub URLs...');
|
|
164
|
+
const configPath = workspace.getWorkspacePath() + '/.studiograph';
|
|
165
|
+
try {
|
|
166
|
+
execSync('git add workspace.json', { cwd: configPath, stdio: 'pipe' });
|
|
167
|
+
execSync('git commit -m "Add GitHub URLs to workspace config"', { cwd: configPath, stdio: 'pipe' });
|
|
168
|
+
execSync('git push origin main', { cwd: configPath, stdio: 'pipe' });
|
|
169
|
+
}
|
|
170
|
+
catch (err) {
|
|
171
|
+
// If nothing to commit or push fails, continue anyway
|
|
172
|
+
}
|
|
270
173
|
provisionSpinner.stop('GitHub repos created');
|
|
271
|
-
const
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
174
|
+
const configRepoName = `${currentConfig.team_name.toLowerCase().replace(/[^a-z0-9]+/g, '-')}-config`;
|
|
175
|
+
const configRepoUrl = `https://github.com/${githubOrg}/${configRepoName}.git`;
|
|
176
|
+
const nextStep = directory === '.' ? '' : `\n\nNext: cd ${targetDir} && studiograph start`;
|
|
177
|
+
log.success('All repos pushed to GitHub!');
|
|
178
|
+
log.info(`\nTo join this workspace from another machine:`);
|
|
179
|
+
log.info(` studiograph join ${configRepoUrl}`);
|
|
180
|
+
outro(`✨ Workspace initialized with GitHub repos!${nextStep}`);
|
|
277
181
|
}
|
|
278
182
|
catch (provisionError) {
|
|
279
183
|
provisionSpinner.stop('Failed to provision GitHub repos');
|
|
@@ -282,12 +186,8 @@ export const initCommand = new Command('init')
|
|
|
282
186
|
}
|
|
283
187
|
}
|
|
284
188
|
else {
|
|
285
|
-
const
|
|
286
|
-
|
|
287
|
-
: null;
|
|
288
|
-
outro(label
|
|
289
|
-
? `✨ ${label} workspace initialized!`
|
|
290
|
-
: '✨ Workspace initialized!');
|
|
189
|
+
const nextStep = directory === '.' ? '' : `\n\nNext: cd ${targetDir} && studiograph start`;
|
|
190
|
+
outro(`✨ Workspace initialized!${nextStep}`);
|
|
291
191
|
}
|
|
292
192
|
}
|
|
293
193
|
catch (error) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"init.js","sourceRoot":"","sources":["../../../src/cli/commands/init.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,
|
|
1
|
+
{"version":3,"file":"init.js","sourceRoot":"","sources":["../../../src/cli/commands/init.ts"],"names":[],"mappings":"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"}
|
|
@@ -12,6 +12,8 @@ import { Workspace } from '../../core/workspace.js';
|
|
|
12
12
|
import { gitClone, getGitConfig } from '../../utils/git.js';
|
|
13
13
|
import { loadToken, getGitHubUser } from '../../auth/github.js';
|
|
14
14
|
import { runPreflight } from '../../utils/preflight.js';
|
|
15
|
+
import { reindexWorkspace } from '../../services/vector-service.js';
|
|
16
|
+
import { promptGitHubAuthIfNeeded, promptLLMSetupIfNeeded } from '../setup-wizard.js';
|
|
15
17
|
/**
|
|
16
18
|
* Attempt to identify a workspace member using the stored GitHub token.
|
|
17
19
|
* Returns the matching TeamMember, or undefined if not identified.
|
|
@@ -46,9 +48,9 @@ function canAccess(role, access) {
|
|
|
46
48
|
export const joinCommand = new Command('join')
|
|
47
49
|
.description('Join an existing Studiograph workspace')
|
|
48
50
|
.argument('<workspace-url>', 'GitHub URL to the .studiograph config repo')
|
|
49
|
-
.
|
|
51
|
+
.argument('[directory]', 'Directory to create workspace in (default: derived from workspace name, use "." for current directory)')
|
|
50
52
|
.option('--github-username <username>', 'Your GitHub username (used to detect your role)')
|
|
51
|
-
.action(async (workspaceUrl, options) => {
|
|
53
|
+
.action(async (workspaceUrl, directory, options) => {
|
|
52
54
|
intro('Join Studiograph Workspace');
|
|
53
55
|
const ready = runPreflight();
|
|
54
56
|
if (!ready) {
|
|
@@ -56,36 +58,83 @@ export const joinCommand = new Command('join')
|
|
|
56
58
|
return;
|
|
57
59
|
}
|
|
58
60
|
try {
|
|
59
|
-
// Step
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
process.exit(1);
|
|
65
|
-
return;
|
|
66
|
-
}
|
|
67
|
-
mkdirSync(targetDir, { recursive: true });
|
|
68
|
-
// Step 2: Clone the .studiograph config repo
|
|
61
|
+
// Step 0: Ensure GitHub auth is configured
|
|
62
|
+
await promptGitHubAuthIfNeeded();
|
|
63
|
+
// Step 1: Clone config repo to temp location first (to get workspace name)
|
|
64
|
+
const tempDir = join(process.cwd(), '.studiograph-temp-' + Date.now());
|
|
65
|
+
mkdirSync(tempDir, { recursive: true });
|
|
69
66
|
const cloneSpinner = spinner();
|
|
70
|
-
cloneSpinner.start('
|
|
67
|
+
cloneSpinner.start('Fetching workspace configuration...');
|
|
71
68
|
try {
|
|
72
|
-
gitClone(workspaceUrl,
|
|
73
|
-
cloneSpinner.stop('
|
|
69
|
+
gitClone(workspaceUrl, join(tempDir, '.studiograph'));
|
|
70
|
+
cloneSpinner.stop('Configuration fetched');
|
|
74
71
|
}
|
|
75
72
|
catch {
|
|
76
73
|
cloneSpinner.stop('Failed');
|
|
74
|
+
// Clean up temp dir
|
|
75
|
+
const { rmSync } = await import('fs');
|
|
76
|
+
rmSync(tempDir, { recursive: true, force: true });
|
|
77
77
|
outro(`❌ Could not clone ${workspaceUrl}. Check the URL and your access permissions.`);
|
|
78
78
|
process.exit(1);
|
|
79
79
|
return;
|
|
80
80
|
}
|
|
81
|
-
//
|
|
82
|
-
const
|
|
83
|
-
|
|
84
|
-
|
|
81
|
+
// Load config to get workspace name
|
|
82
|
+
const tempWorkspace = new Workspace(tempDir);
|
|
83
|
+
const tempConfig = await tempWorkspace.loadConfig();
|
|
84
|
+
// Determine target directory
|
|
85
|
+
let targetDir;
|
|
86
|
+
if (directory === '.') {
|
|
87
|
+
// Use current directory
|
|
88
|
+
targetDir = process.cwd();
|
|
89
|
+
}
|
|
90
|
+
else if (directory) {
|
|
91
|
+
// Use specified directory
|
|
92
|
+
targetDir = resolve(directory);
|
|
93
|
+
}
|
|
94
|
+
else {
|
|
95
|
+
// Auto-generate from workspace name slug
|
|
96
|
+
const slug = tempConfig.team_name.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-+|-+$/g, '');
|
|
97
|
+
targetDir = resolve(slug);
|
|
98
|
+
}
|
|
99
|
+
// Check if target directory has .studiograph
|
|
100
|
+
const studiographDir = join(targetDir, '.studiograph');
|
|
101
|
+
if (existsSync(studiographDir)) {
|
|
102
|
+
// Clean up temp dir
|
|
103
|
+
const { rmSync } = await import('fs');
|
|
104
|
+
rmSync(tempDir, { recursive: true, force: true });
|
|
105
|
+
outro(`❌ A .studiograph directory already exists at ${targetDir}`);
|
|
85
106
|
process.exit(1);
|
|
86
107
|
return;
|
|
87
108
|
}
|
|
88
|
-
|
|
109
|
+
// Create target directory if needed
|
|
110
|
+
if (!existsSync(targetDir)) {
|
|
111
|
+
mkdirSync(targetDir, { recursive: true });
|
|
112
|
+
log.info(`Created directory: ${targetDir}`);
|
|
113
|
+
}
|
|
114
|
+
else if (directory !== '.') {
|
|
115
|
+
// Directory exists but is not current dir - check if empty
|
|
116
|
+
const { readdirSync, rmSync } = await import('fs');
|
|
117
|
+
const files = readdirSync(targetDir);
|
|
118
|
+
if (files.length > 0) {
|
|
119
|
+
const proceed = await confirm({
|
|
120
|
+
message: `Directory ${targetDir} is not empty. Continue anyway?`,
|
|
121
|
+
initialValue: false,
|
|
122
|
+
});
|
|
123
|
+
if (!proceed || typeof proceed === 'symbol') {
|
|
124
|
+
rmSync(tempDir, { recursive: true, force: true });
|
|
125
|
+
outro('Cancelled');
|
|
126
|
+
process.exit(0);
|
|
127
|
+
return;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
// Move temp .studiograph to target directory
|
|
132
|
+
const { renameSync, rmSync } = await import('fs');
|
|
133
|
+
renameSync(join(tempDir, '.studiograph'), studiographDir);
|
|
134
|
+
rmSync(tempDir, { recursive: true, force: true });
|
|
135
|
+
// Step 2: Load workspace config and team roster
|
|
136
|
+
const workspace = new Workspace(targetDir);
|
|
137
|
+
const config = await workspace.loadConfig();
|
|
89
138
|
const members = workspace.loadMembers();
|
|
90
139
|
log.info(`Workspace: ${config.team_name}`);
|
|
91
140
|
log.info(`${config.repos.length} repositor${config.repos.length === 1 ? 'y' : 'ies'} in workspace`);
|
|
@@ -205,7 +254,21 @@ export const joinCommand = new Command('join')
|
|
|
205
254
|
failed++;
|
|
206
255
|
}
|
|
207
256
|
}
|
|
208
|
-
// Step 7:
|
|
257
|
+
// Step 7: Index entities for search
|
|
258
|
+
if (cloned > 0) {
|
|
259
|
+
const indexSpinner = spinner();
|
|
260
|
+
indexSpinner.start('Building search index...');
|
|
261
|
+
try {
|
|
262
|
+
const indexedRepos = accessibleRepos
|
|
263
|
+
.filter(r => r.github_url && existsSync(join(targetDir, r.path)));
|
|
264
|
+
const total = await reindexWorkspace(targetDir, indexedRepos);
|
|
265
|
+
indexSpinner.stop(`Search index ready (${total} entities)`);
|
|
266
|
+
}
|
|
267
|
+
catch {
|
|
268
|
+
indexSpinner.stop('Search index skipped (non-fatal)');
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
// Step 8: Summary
|
|
209
272
|
const parts = [];
|
|
210
273
|
if (cloned > 0)
|
|
211
274
|
parts.push(`${cloned} cloned`);
|
|
@@ -214,12 +277,14 @@ export const joinCommand = new Command('join')
|
|
|
214
277
|
if (failed > 0)
|
|
215
278
|
parts.push(`${failed} failed`);
|
|
216
279
|
const summary = parts.join(', ');
|
|
217
|
-
|
|
280
|
+
// Step 8: AI model setup
|
|
281
|
+
await promptLLMSetupIfNeeded();
|
|
282
|
+
const nextStep = directory === '.' ? '' : `\n\nNext: cd ${targetDir} && studiograph start`;
|
|
218
283
|
if (failed > 0) {
|
|
219
|
-
outro(
|
|
284
|
+
outro(`Joined ${config.team_name} with issues (${summary}). Ask a workspace admin to verify your repo access.${nextStep}`);
|
|
220
285
|
}
|
|
221
286
|
else {
|
|
222
|
-
outro(
|
|
287
|
+
outro(`Joined ${config.team_name} workspace (${summary})${nextStep}`);
|
|
223
288
|
}
|
|
224
289
|
}
|
|
225
290
|
catch (error) {
|