studiograph 1.0.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.
Files changed (101) hide show
  1. package/README.md +18 -0
  2. package/dist/agent/orchestrator.d.ts +69 -0
  3. package/dist/agent/orchestrator.js +211 -0
  4. package/dist/agent/orchestrator.js.map +1 -0
  5. package/dist/agent/tools/graph-tools.d.ts +30 -0
  6. package/dist/agent/tools/graph-tools.js +536 -0
  7. package/dist/agent/tools/graph-tools.js.map +1 -0
  8. package/dist/auth/github.d.ts +53 -0
  9. package/dist/auth/github.js +180 -0
  10. package/dist/auth/github.js.map +1 -0
  11. package/dist/cli/commands/auth.d.ts +10 -0
  12. package/dist/cli/commands/auth.js +63 -0
  13. package/dist/cli/commands/auth.js.map +1 -0
  14. package/dist/cli/commands/init.d.ts +7 -0
  15. package/dist/cli/commands/init.js +299 -0
  16. package/dist/cli/commands/init.js.map +1 -0
  17. package/dist/cli/commands/join.d.ts +14 -0
  18. package/dist/cli/commands/join.js +230 -0
  19. package/dist/cli/commands/join.js.map +1 -0
  20. package/dist/cli/commands/members.d.ts +11 -0
  21. package/dist/cli/commands/members.js +230 -0
  22. package/dist/cli/commands/members.js.map +1 -0
  23. package/dist/cli/commands/serve.d.ts +17 -0
  24. package/dist/cli/commands/serve.js +90 -0
  25. package/dist/cli/commands/serve.js.map +1 -0
  26. package/dist/cli/commands/start.d.ts +7 -0
  27. package/dist/cli/commands/start.js +381 -0
  28. package/dist/cli/commands/start.js.map +1 -0
  29. package/dist/cli/commands/sync.d.ts +10 -0
  30. package/dist/cli/commands/sync.js +121 -0
  31. package/dist/cli/commands/sync.js.map +1 -0
  32. package/dist/cli/index.d.ts +7 -0
  33. package/dist/cli/index.js +31 -0
  34. package/dist/cli/index.js.map +1 -0
  35. package/dist/core/graph.d.ts +169 -0
  36. package/dist/core/graph.js +558 -0
  37. package/dist/core/graph.js.map +1 -0
  38. package/dist/core/types.d.ts +216 -0
  39. package/dist/core/types.js +71 -0
  40. package/dist/core/types.js.map +1 -0
  41. package/dist/core/user-config.d.ts +31 -0
  42. package/dist/core/user-config.js +50 -0
  43. package/dist/core/user-config.js.map +1 -0
  44. package/dist/core/validation.d.ts +2371 -0
  45. package/dist/core/validation.js +432 -0
  46. package/dist/core/validation.js.map +1 -0
  47. package/dist/core/workspace-manager.d.ts +104 -0
  48. package/dist/core/workspace-manager.js +432 -0
  49. package/dist/core/workspace-manager.js.map +1 -0
  50. package/dist/core/workspace.d.ts +103 -0
  51. package/dist/core/workspace.js +306 -0
  52. package/dist/core/workspace.js.map +1 -0
  53. package/dist/server/index.d.ts +25 -0
  54. package/dist/server/index.js +84 -0
  55. package/dist/server/index.js.map +1 -0
  56. package/dist/server/plugin-loader.d.ts +31 -0
  57. package/dist/server/plugin-loader.js +81 -0
  58. package/dist/server/plugin-loader.js.map +1 -0
  59. package/dist/server/routes/chat.d.ts +11 -0
  60. package/dist/server/routes/chat.js +66 -0
  61. package/dist/server/routes/chat.js.map +1 -0
  62. package/dist/server/routes/graph-api.d.ts +9 -0
  63. package/dist/server/routes/graph-api.js +72 -0
  64. package/dist/server/routes/graph-api.js.map +1 -0
  65. package/dist/server/routes/webhook.d.ts +14 -0
  66. package/dist/server/routes/webhook.js +69 -0
  67. package/dist/server/routes/webhook.js.map +1 -0
  68. package/dist/services/assets/base.d.ts +69 -0
  69. package/dist/services/assets/base.js +113 -0
  70. package/dist/services/assets/base.js.map +1 -0
  71. package/dist/services/assets/index.d.ts +36 -0
  72. package/dist/services/assets/index.js +89 -0
  73. package/dist/services/assets/index.js.map +1 -0
  74. package/dist/services/assets/local.d.ts +42 -0
  75. package/dist/services/assets/local.js +161 -0
  76. package/dist/services/assets/local.js.map +1 -0
  77. package/dist/services/assets/r2.d.ts +36 -0
  78. package/dist/services/assets/r2.js +182 -0
  79. package/dist/services/assets/r2.js.map +1 -0
  80. package/dist/services/csv-service.d.ts +36 -0
  81. package/dist/services/csv-service.js +143 -0
  82. package/dist/services/csv-service.js.map +1 -0
  83. package/dist/services/git.d.ts +99 -0
  84. package/dist/services/git.js +306 -0
  85. package/dist/services/git.js.map +1 -0
  86. package/dist/services/github-provisioner.d.ts +30 -0
  87. package/dist/services/github-provisioner.js +89 -0
  88. package/dist/services/github-provisioner.js.map +1 -0
  89. package/dist/services/markdown.d.ts +82 -0
  90. package/dist/services/markdown.js +338 -0
  91. package/dist/services/markdown.js.map +1 -0
  92. package/dist/services/memory-service.d.ts +74 -0
  93. package/dist/services/memory-service.js +183 -0
  94. package/dist/services/memory-service.js.map +1 -0
  95. package/dist/utils/git.d.ts +28 -0
  96. package/dist/utils/git.js +55 -0
  97. package/dist/utils/git.js.map +1 -0
  98. package/dist/utils/preflight.d.ts +44 -0
  99. package/dist/utils/preflight.js +95 -0
  100. package/dist/utils/preflight.js.map +1 -0
  101. package/package.json +55 -0
@@ -0,0 +1,306 @@
1
+ /**
2
+ * Git service for Studiograph
3
+ *
4
+ * Handles Git operations with transaction-based commits,
5
+ * proper user attribution, and security.
6
+ */
7
+ import { execSync } from 'child_process';
8
+ import { existsSync, statSync } from 'fs';
9
+ import { join } from 'path';
10
+ export class GitService {
11
+ repoPath;
12
+ constructor(repoPath) {
13
+ this.repoPath = repoPath;
14
+ this.ensureValidPath();
15
+ this.initializeIfNeeded();
16
+ }
17
+ /**
18
+ * Ensure the repo path exists and is a directory
19
+ */
20
+ ensureValidPath() {
21
+ if (!existsSync(this.repoPath)) {
22
+ throw new Error(`Repository path does not exist: ${this.repoPath}`);
23
+ }
24
+ const stats = statSync(this.repoPath);
25
+ if (!stats.isDirectory()) {
26
+ throw new Error(`Repository path is not a directory: ${this.repoPath}`);
27
+ }
28
+ }
29
+ /**
30
+ * Initialize Git repository if not already initialized
31
+ */
32
+ initializeIfNeeded() {
33
+ const gitDir = join(this.repoPath, '.git');
34
+ if (!existsSync(gitDir)) {
35
+ try {
36
+ execSync('git init', { cwd: this.repoPath, stdio: 'pipe' });
37
+ // Set default branch to main
38
+ execSync('git branch -M main', { cwd: this.repoPath, stdio: 'pipe' });
39
+ // Create initial .gitignore if it doesn't exist
40
+ const gitignorePath = join(this.repoPath, '.gitignore');
41
+ if (!existsSync(gitignorePath)) {
42
+ execSync('echo ".DS_Store\n*.tmp\n*.log" > .gitignore', {
43
+ cwd: this.repoPath,
44
+ stdio: 'pipe'
45
+ });
46
+ }
47
+ }
48
+ catch (error) {
49
+ throw new Error(`Failed to initialize Git repository: ${error instanceof Error ? error.message : 'Unknown error'}`);
50
+ }
51
+ }
52
+ }
53
+ /**
54
+ * Check if repository has any commits
55
+ */
56
+ hasCommits() {
57
+ try {
58
+ execSync('git rev-parse HEAD', { cwd: this.repoPath, stdio: 'pipe' });
59
+ return true;
60
+ }
61
+ catch {
62
+ return false;
63
+ }
64
+ }
65
+ /**
66
+ * Get current branch name
67
+ */
68
+ getCurrentBranch() {
69
+ try {
70
+ return execSync('git rev-parse --abbrev-ref HEAD', {
71
+ cwd: this.repoPath,
72
+ encoding: 'utf-8',
73
+ }).trim();
74
+ }
75
+ catch (error) {
76
+ throw new Error(`Failed to get current branch: ${error instanceof Error ? error.message : 'Unknown error'}`);
77
+ }
78
+ }
79
+ /**
80
+ * Create a transaction for batched commits
81
+ */
82
+ createTransaction() {
83
+ return new GitTransaction(this.repoPath);
84
+ }
85
+ /**
86
+ * Get commit history
87
+ */
88
+ getHistory(limit = 10) {
89
+ if (!this.hasCommits()) {
90
+ return [];
91
+ }
92
+ try {
93
+ const output = execSync(`git log --pretty=format:"%H|%an|%ae|%at|%s" -n ${limit}`, { cwd: this.repoPath, encoding: 'utf-8' });
94
+ if (!output) {
95
+ return [];
96
+ }
97
+ return output.split('\n').map(line => {
98
+ const [hash, name, email, timestamp, message] = line.split('|');
99
+ return {
100
+ hash,
101
+ author: { name, email },
102
+ timestamp: parseInt(timestamp) * 1000, // Convert to milliseconds
103
+ message
104
+ };
105
+ });
106
+ }
107
+ catch (error) {
108
+ throw new Error(`Failed to get commit history: ${error instanceof Error ? error.message : 'Unknown error'}`);
109
+ }
110
+ }
111
+ /**
112
+ * Get file history for a specific file
113
+ */
114
+ getFileHistory(filePath, limit = 10) {
115
+ if (!this.hasCommits()) {
116
+ return [];
117
+ }
118
+ try {
119
+ const output = execSync(`git log --pretty=format:"%H|%an|%ae|%at|%s" -n ${limit} -- ${escapeShellArg(filePath)}`, { cwd: this.repoPath, encoding: 'utf-8' });
120
+ if (!output) {
121
+ return [];
122
+ }
123
+ return output.split('\n').map(line => {
124
+ const [hash, name, email, timestamp, message] = line.split('|');
125
+ return {
126
+ hash,
127
+ author: { name, email },
128
+ timestamp: parseInt(timestamp) * 1000,
129
+ message
130
+ };
131
+ });
132
+ }
133
+ catch (error) {
134
+ throw new Error(`Failed to get file history: ${error instanceof Error ? error.message : 'Unknown error'}`);
135
+ }
136
+ }
137
+ /**
138
+ * Get current status (modified, added, deleted files)
139
+ */
140
+ getStatus() {
141
+ try {
142
+ const output = execSync('git status --porcelain', {
143
+ cwd: this.repoPath,
144
+ encoding: 'utf-8',
145
+ });
146
+ const modified = [];
147
+ const added = [];
148
+ const deleted = [];
149
+ const untracked = [];
150
+ output.split('\n').forEach(line => {
151
+ if (!line)
152
+ return;
153
+ const status = line.substring(0, 2);
154
+ const file = line.substring(3);
155
+ if (status === ' M' || status === 'M ') {
156
+ modified.push(file);
157
+ }
158
+ else if (status === 'A ') {
159
+ added.push(file);
160
+ }
161
+ else if (status === ' D' || status === 'D ') {
162
+ deleted.push(file);
163
+ }
164
+ else if (status === '??') {
165
+ untracked.push(file);
166
+ }
167
+ });
168
+ return { modified, added, deleted, untracked };
169
+ }
170
+ catch (error) {
171
+ throw new Error(`Failed to get status: ${error instanceof Error ? error.message : 'Unknown error'}`);
172
+ }
173
+ }
174
+ /**
175
+ * Check if there are uncommitted changes
176
+ */
177
+ hasUncommittedChanges() {
178
+ const status = this.getStatus();
179
+ return (status.modified.length > 0 ||
180
+ status.added.length > 0 ||
181
+ status.deleted.length > 0 ||
182
+ status.untracked.length > 0);
183
+ }
184
+ }
185
+ /**
186
+ * Transaction class for batched Git commits
187
+ */
188
+ export class GitTransaction {
189
+ repoPath;
190
+ changes = [];
191
+ constructor(repoPath) {
192
+ this.repoPath = repoPath;
193
+ }
194
+ /**
195
+ * Add a change to this transaction
196
+ */
197
+ add(change) {
198
+ this.changes.push(change);
199
+ }
200
+ /**
201
+ * Get all changes in this transaction
202
+ */
203
+ getChanges() {
204
+ return [...this.changes];
205
+ }
206
+ /**
207
+ * Commit all changes in this transaction
208
+ */
209
+ async commit(user, message) {
210
+ if (this.changes.length === 0) {
211
+ throw new Error('No changes to commit');
212
+ }
213
+ // Generate message if not provided
214
+ const commitMessage = message || this.generateMessage();
215
+ // Stage all changes
216
+ try {
217
+ execSync('git add -A', { cwd: this.repoPath, stdio: 'pipe' });
218
+ }
219
+ catch (error) {
220
+ throw new Error(`Failed to stage changes: ${error instanceof Error ? error.message : 'Unknown error'}`);
221
+ }
222
+ // Check if there are actual changes staged
223
+ try {
224
+ execSync('git diff --staged --quiet', { cwd: this.repoPath, stdio: 'pipe' });
225
+ // No changes staged
226
+ console.warn('No actual changes to commit (files may be unchanged)');
227
+ this.changes = [];
228
+ return;
229
+ }
230
+ catch {
231
+ // Changes exist, proceed with commit
232
+ }
233
+ // Commit with proper attribution and escaping
234
+ const escapedMessage = escapeShellArg(commitMessage);
235
+ const authorString = `${user.name} <${user.email}>`;
236
+ const escapedAuthor = escapeShellArg(authorString);
237
+ try {
238
+ execSync(`git commit -m ${escapedMessage} --author=${escapedAuthor}`, { cwd: this.repoPath, stdio: 'pipe' });
239
+ }
240
+ catch (error) {
241
+ throw new Error(`Failed to commit changes: ${error instanceof Error ? error.message : 'Unknown error'}`);
242
+ }
243
+ // Clear changes after successful commit
244
+ this.changes = [];
245
+ }
246
+ /**
247
+ * Generate commit message from changes
248
+ */
249
+ generateMessage() {
250
+ const creates = this.changes.filter(c => c.operation === 'create');
251
+ const updates = this.changes.filter(c => c.operation === 'update');
252
+ const deletes = this.changes.filter(c => c.operation === 'delete');
253
+ const parts = [];
254
+ if (creates.length > 0) {
255
+ const entityTypes = [...new Set(creates.map(c => c.entityType))];
256
+ if (entityTypes.length === 1 && creates.length === 1) {
257
+ parts.push(`Create ${creates[0].entityType}: ${creates[0].entityId}`);
258
+ }
259
+ else {
260
+ parts.push(`Create ${creates.length} ${creates.length === 1 ? 'entity' : 'entities'}`);
261
+ }
262
+ }
263
+ if (updates.length > 0) {
264
+ const entityTypes = [...new Set(updates.map(c => c.entityType))];
265
+ if (entityTypes.length === 1 && updates.length === 1) {
266
+ parts.push(`Update ${updates[0].entityType}: ${updates[0].entityId}`);
267
+ }
268
+ else {
269
+ parts.push(`Update ${updates.length} ${updates.length === 1 ? 'entity' : 'entities'}`);
270
+ }
271
+ }
272
+ if (deletes.length > 0) {
273
+ const entityTypes = [...new Set(deletes.map(c => c.entityType))];
274
+ if (entityTypes.length === 1 && deletes.length === 1) {
275
+ parts.push(`Delete ${deletes[0].entityType}: ${deletes[0].entityId}`);
276
+ }
277
+ else {
278
+ parts.push(`Delete ${deletes.length} ${deletes.length === 1 ? 'entity' : 'entities'}`);
279
+ }
280
+ }
281
+ return parts.join(', ');
282
+ }
283
+ /**
284
+ * Rollback all changes (git reset)
285
+ */
286
+ async rollback() {
287
+ try {
288
+ execSync('git reset --hard HEAD', { cwd: this.repoPath, stdio: 'pipe' });
289
+ execSync('git clean -fd', { cwd: this.repoPath, stdio: 'pipe' });
290
+ this.changes = [];
291
+ }
292
+ catch (error) {
293
+ throw new Error(`Failed to rollback changes: ${error instanceof Error ? error.message : 'Unknown error'}`);
294
+ }
295
+ }
296
+ }
297
+ /**
298
+ * Escape shell arguments to prevent command injection
299
+ */
300
+ function escapeShellArg(arg) {
301
+ // Replace double quotes with escaped double quotes
302
+ const escaped = arg.replace(/"/g, '\\"');
303
+ // Wrap in double quotes
304
+ return `"${escaped}"`;
305
+ }
306
+ //# sourceMappingURL=git.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"git.js","sourceRoot":"","sources":["../../src/services/git.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,30 @@
1
+ /**
2
+ * GitHub repository provisioner
3
+ *
4
+ * Creates GitHub repos for each repo in a workspace config and pushes
5
+ * local content to them. Called from the `init` command when the user
6
+ * opts into GitHub provisioning.
7
+ */
8
+ import { Octokit } from '@octokit/rest';
9
+ import { WorkspaceConfig } from '../core/types.js';
10
+ /**
11
+ * Provision all repos in a workspace on GitHub, then push local content.
12
+ * Updates github_url in workspace.json for each repo created.
13
+ */
14
+ export declare function provisionWorkspace(options: {
15
+ octokit: Octokit;
16
+ org: string;
17
+ workspacePath: string;
18
+ config: WorkspaceConfig;
19
+ onProgress?: (message: string) => void;
20
+ }): Promise<WorkspaceConfig>;
21
+ /**
22
+ * Create a GitHub repository in the given org.
23
+ * Returns the clone URL (HTTPS).
24
+ */
25
+ export declare function createGitHubRepo(octokit: Octokit, org: string, name: string, isPrivate: boolean, description?: string): Promise<string>;
26
+ /**
27
+ * Initialize a local directory as a git repo, add a remote, and push.
28
+ * If already a git repo, just adds the remote and pushes.
29
+ */
30
+ export declare function initAndPush(localPath: string, remoteUrl: string): void;
@@ -0,0 +1,89 @@
1
+ /**
2
+ * GitHub repository provisioner
3
+ *
4
+ * Creates GitHub repos for each repo in a workspace config and pushes
5
+ * local content to them. Called from the `init` command when the user
6
+ * opts into GitHub provisioning.
7
+ */
8
+ import { execSync } from 'child_process';
9
+ import { join } from 'path';
10
+ /**
11
+ * Provision all repos in a workspace on GitHub, then push local content.
12
+ * Updates github_url in workspace.json for each repo created.
13
+ */
14
+ export async function provisionWorkspace(options) {
15
+ const { octokit, org, workspacePath, config, onProgress } = options;
16
+ const updatedConfig = {
17
+ ...config,
18
+ repos: [...config.repos],
19
+ };
20
+ for (let i = 0; i < updatedConfig.repos.length; i++) {
21
+ const repo = updatedConfig.repos[i];
22
+ const isPublic = repo.access === 'public';
23
+ const repoFullName = `${org}/${repo.name}`;
24
+ onProgress?.(`Creating ${repoFullName}...`);
25
+ const cloneUrl = await createGitHubRepo(octokit, org, repo.name, !isPublic, repo.description);
26
+ const localPath = join(workspacePath, repo.path);
27
+ onProgress?.(`Pushing ${repo.name}...`);
28
+ initAndPush(localPath, cloneUrl);
29
+ updatedConfig.repos[i] = { ...repo, github_url: cloneUrl };
30
+ }
31
+ return updatedConfig;
32
+ }
33
+ /**
34
+ * Create a GitHub repository in the given org.
35
+ * Returns the clone URL (HTTPS).
36
+ */
37
+ export async function createGitHubRepo(octokit, org, name, isPrivate, description) {
38
+ try {
39
+ const { data } = await octokit.rest.repos.createInOrg({
40
+ org,
41
+ name,
42
+ private: isPrivate,
43
+ description: description ?? '',
44
+ auto_init: false,
45
+ });
46
+ return data.clone_url;
47
+ }
48
+ catch (err) {
49
+ // 422 = repo already exists — fetch and use the existing one
50
+ if (err?.status === 422) {
51
+ const { data } = await octokit.rest.repos.get({ owner: org, repo: name });
52
+ return data.clone_url;
53
+ }
54
+ throw err;
55
+ }
56
+ }
57
+ /**
58
+ * Initialize a local directory as a git repo, add a remote, and push.
59
+ * If already a git repo, just adds the remote and pushes.
60
+ */
61
+ export function initAndPush(localPath, remoteUrl) {
62
+ const run = (cmd) => execSync(cmd, { cwd: localPath, stdio: 'pipe' });
63
+ try {
64
+ run('git rev-parse --git-dir');
65
+ }
66
+ catch {
67
+ run('git init');
68
+ run('git checkout -b main');
69
+ }
70
+ // Remove existing origin if present, then add fresh
71
+ try {
72
+ run('git remote remove origin');
73
+ }
74
+ catch {
75
+ // No existing remote — that's fine
76
+ }
77
+ run(`git remote add origin ${remoteUrl}`);
78
+ run('git add .');
79
+ // Only commit if there is something to commit
80
+ try {
81
+ run('git diff --cached --quiet');
82
+ // Nothing staged — nothing to commit, just push any existing commits
83
+ }
84
+ catch {
85
+ run('git commit -m "Initial commit"');
86
+ }
87
+ run('git push -u origin main --force');
88
+ }
89
+ //# sourceMappingURL=github-provisioner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"github-provisioner.js","sourceRoot":"","sources":["../../src/services/github-provisioner.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,82 @@
1
+ /**
2
+ * Markdown service for Studiograph
3
+ *
4
+ * Handles parsing and writing markdown files with YAML frontmatter,
5
+ * extracting wikilinks, and validating relationships.
6
+ */
7
+ export interface MarkdownDocument {
8
+ frontmatter: Record<string, any>;
9
+ content: string;
10
+ wikilinks: string[];
11
+ }
12
+ export interface WikilinkValidation {
13
+ valid: string[];
14
+ broken: string[];
15
+ }
16
+ export declare class MarkdownService {
17
+ /**
18
+ * Parse markdown file from path
19
+ */
20
+ parseFile(filePath: string): MarkdownDocument;
21
+ /**
22
+ * Parse markdown content string
23
+ */
24
+ parseContent(content: string): MarkdownDocument;
25
+ /**
26
+ * Extract wikilinks from markdown content and frontmatter
27
+ */
28
+ extractWikilinks(content: string, frontmatter: Record<string, any>): string[];
29
+ /**
30
+ * Recursively extract wikilinks from object (frontmatter)
31
+ */
32
+ private extractWikilinksFromObject;
33
+ /**
34
+ * Write markdown file with frontmatter
35
+ */
36
+ writeFile(filePath: string, doc: MarkdownDocument): void;
37
+ /**
38
+ * Write markdown content from separate frontmatter and content
39
+ */
40
+ write(filePath: string, frontmatter: Record<string, any>, content: string): void;
41
+ /**
42
+ * Validate wikilinks against a repo or set of repos
43
+ */
44
+ validateWikilinks(wikilinks: string[], searchPaths: string[]): WikilinkValidation;
45
+ /**
46
+ * Find entity file by entity ID across multiple search paths
47
+ */
48
+ findEntity(entityId: string, searchPaths: string[]): string | null;
49
+ /**
50
+ * Find all entities of a given type in a directory
51
+ */
52
+ findEntitiesByType(searchPath: string, entityType: string): string[];
53
+ /**
54
+ * Find all markdown files in a directory (recursive)
55
+ */
56
+ findAllEntities(searchPath: string): string[];
57
+ /**
58
+ * Search entities by content or frontmatter
59
+ */
60
+ search(searchPaths: string[], query: string, options?: {
61
+ entityType?: string;
62
+ caseSensitive?: boolean;
63
+ searchContent?: boolean;
64
+ searchFrontmatter?: boolean;
65
+ limit?: number;
66
+ }): MarkdownDocument[];
67
+ /**
68
+ * Get entity relationships (entities that link to this entity)
69
+ */
70
+ findBacklinks(entityId: string, searchPaths: string[]): Array<{
71
+ file: string;
72
+ doc: MarkdownDocument;
73
+ }>;
74
+ /**
75
+ * Update wikilinks in a file (useful for refactoring entity IDs)
76
+ */
77
+ updateWikilinks(filePath: string, oldEntityId: string, newEntityId: string): void;
78
+ /**
79
+ * Recursively update wikilinks in an object (frontmatter)
80
+ */
81
+ private updateWikilinksInObject;
82
+ }