@equinor/fusion-framework-cli-plugin-ai-index 1.0.5 → 2.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.
- package/CHANGELOG.md +91 -2
- package/README.md +105 -69
- package/dist/esm/bin/embed.js +28 -13
- package/dist/esm/bin/embed.js.map +1 -1
- package/dist/esm/delete-command.js +100 -0
- package/dist/esm/delete-command.js.map +1 -0
- package/dist/esm/delete-command.options.js +43 -0
- package/dist/esm/delete-command.options.js.map +1 -0
- package/dist/esm/{command.js → embeddings-command.js} +42 -28
- package/dist/esm/embeddings-command.js.map +1 -0
- package/dist/esm/{command.options.js → embeddings-command.options.js} +14 -7
- package/dist/esm/embeddings-command.options.js.map +1 -0
- package/dist/esm/index.js +37 -4
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/search-command.js +198 -0
- package/dist/esm/search-command.js.map +1 -0
- package/dist/esm/utils/generate-chunk-id.js +17 -5
- package/dist/esm/utils/generate-chunk-id.js.map +1 -1
- package/dist/esm/utils/git/file-changes.js +26 -11
- package/dist/esm/utils/git/file-changes.js.map +1 -1
- package/dist/esm/utils/git/git-client.js +16 -7
- package/dist/esm/utils/git/git-client.js.map +1 -1
- package/dist/esm/utils/git/metadata.js +7 -3
- package/dist/esm/utils/git/metadata.js.map +1 -1
- package/dist/esm/utils/git/status.js +9 -3
- package/dist/esm/utils/git/status.js.map +1 -1
- package/dist/esm/utils/markdown/parser.js +53 -13
- package/dist/esm/utils/markdown/parser.js.map +1 -1
- package/dist/esm/utils/package-resolver.js +10 -6
- package/dist/esm/utils/package-resolver.js.map +1 -1
- package/dist/esm/utils/ts-doc/constants.js +4 -1
- package/dist/esm/utils/ts-doc/constants.js.map +1 -1
- package/dist/esm/utils/ts-doc/extractors.js +27 -13
- package/dist/esm/utils/ts-doc/extractors.js.map +1 -1
- package/dist/esm/utils/ts-doc/parser.js +19 -10
- package/dist/esm/utils/ts-doc/parser.js.map +1 -1
- package/dist/esm/version.js +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/types/config.d.ts +51 -10
- package/dist/types/delete-command.d.ts +9 -0
- package/dist/types/delete-command.options.d.ts +32 -0
- package/dist/types/embeddings-command.d.ts +11 -0
- package/dist/types/embeddings-command.options.d.ts +40 -0
- package/dist/types/index.d.ts +19 -2
- package/dist/types/search-command.d.ts +8 -0
- package/dist/types/utils/generate-chunk-id.d.ts +17 -5
- package/dist/types/utils/git/file-changes.d.ts +26 -11
- package/dist/types/utils/git/git-client.d.ts +16 -7
- package/dist/types/utils/git/metadata.d.ts +7 -3
- package/dist/types/utils/git/status.d.ts +9 -3
- package/dist/types/utils/git/types.d.ts +15 -9
- package/dist/types/utils/markdown/parser.d.ts +23 -10
- package/dist/types/utils/markdown/types.d.ts +13 -2
- package/dist/types/utils/package-resolver.d.ts +8 -5
- package/dist/types/utils/ts-doc/constants.d.ts +4 -1
- package/dist/types/utils/ts-doc/extractors.d.ts +27 -13
- package/dist/types/utils/ts-doc/parser.d.ts +19 -10
- package/dist/types/utils/ts-doc/types.d.ts +12 -4
- package/dist/types/utils/types.d.ts +10 -6
- package/dist/types/version.d.ts +1 -1
- package/package.json +13 -11
- package/src/bin/delete-removed-files.ts +1 -1
- package/src/bin/embed.ts +47 -18
- package/src/bin/file-stream.ts +1 -1
- package/src/bin/get-diff.ts +1 -1
- package/src/bin/types.ts +1 -1
- package/src/config.ts +52 -10
- package/src/delete-command.options.ts +51 -0
- package/src/delete-command.ts +117 -0
- package/src/{command.options.ts → embeddings-command.options.ts} +16 -9
- package/src/{command.ts → embeddings-command.ts} +46 -28
- package/src/index.ts +38 -4
- package/src/search-command.ts +259 -0
- package/src/utils/generate-chunk-id.ts +17 -5
- package/src/utils/git/file-changes.ts +26 -11
- package/src/utils/git/git-client.ts +16 -7
- package/src/utils/git/metadata.ts +7 -3
- package/src/utils/git/status.ts +9 -3
- package/src/utils/git/types.ts +15 -9
- package/src/utils/markdown/parser.ts +54 -13
- package/src/utils/markdown/types.ts +13 -2
- package/src/utils/package-resolver.ts +10 -6
- package/src/utils/ts-doc/constants.ts +4 -1
- package/src/utils/ts-doc/extractors.ts +27 -13
- package/src/utils/ts-doc/parser.ts +19 -10
- package/src/utils/ts-doc/types.ts +12 -4
- package/src/utils/types.ts +10 -6
- package/src/version.ts +1 -1
- package/dist/esm/command.js.map +0 -1
- package/dist/esm/command.options.js.map +0 -1
- package/dist/types/command.d.ts +0 -2
- package/dist/types/command.options.d.ts +0 -33
|
@@ -2,11 +2,11 @@ import { createCommand, createOption } from 'commander';
|
|
|
2
2
|
import { loadFusionAIConfig, setupFramework } from '@equinor/fusion-framework-cli-plugin-ai-base';
|
|
3
3
|
import { withOptions as withAiOptions } from '@equinor/fusion-framework-cli-plugin-ai-base/command-options';
|
|
4
4
|
import { embed } from './bin/embed.js';
|
|
5
|
-
import { CommandOptionsSchema } from './command.options.js';
|
|
5
|
+
import { CommandOptionsSchema } from './embeddings-command.options.js';
|
|
6
6
|
/**
|
|
7
|
-
* CLI command: `ai
|
|
7
|
+
* CLI command: `ai index add`
|
|
8
8
|
*
|
|
9
|
-
*
|
|
9
|
+
* Add documents to the AI search index via embedding generation.
|
|
10
10
|
*
|
|
11
11
|
* Features:
|
|
12
12
|
* - Markdown/MDX document chunking with frontmatter extraction
|
|
@@ -17,7 +17,7 @@ import { CommandOptionsSchema } from './command.options.js';
|
|
|
17
17
|
* - Configurable file patterns via fusion-ai.config.ts
|
|
18
18
|
*
|
|
19
19
|
* Usage:
|
|
20
|
-
* $ ffc ai
|
|
20
|
+
* $ ffc ai index add [options] [glob-patterns...]
|
|
21
21
|
*
|
|
22
22
|
* Arguments:
|
|
23
23
|
* glob-patterns Glob patterns to match files (optional when using --diff)
|
|
@@ -30,38 +30,44 @@ import { CommandOptionsSchema } from './command.options.js';
|
|
|
30
30
|
* --base-ref <ref> Git reference to compare against (default: HEAD~1)
|
|
31
31
|
* --clean Delete all existing documents from the vector store before processing
|
|
32
32
|
*
|
|
33
|
-
* AI Options (required):
|
|
34
|
-
* --openai-api-key <key> Azure OpenAI API key (or AZURE_OPENAI_API_KEY env var)
|
|
35
|
-
* --openai-api-version <version> Azure OpenAI API version (default: 2024-02-15-preview)
|
|
36
|
-
* --openai-instance <name> Azure OpenAI instance name (or AZURE_OPENAI_INSTANCE_NAME env var)
|
|
37
|
-
* --openai-embedding-deployment <name> Azure OpenAI embedding deployment name (or AZURE_OPENAI_EMBEDDING_DEPLOYMENT_NAME env var)
|
|
38
|
-
* --azure-search-endpoint <url> Azure Search endpoint URL (or AZURE_SEARCH_ENDPOINT env var)
|
|
39
|
-
* --azure-search-api-key <key> Azure Search API key (or AZURE_SEARCH_API_KEY env var)
|
|
40
|
-
* --azure-search-index-name <name> Azure Search index name (or AZURE_SEARCH_INDEX_NAME env var)
|
|
41
|
-
*
|
|
42
33
|
* Examples:
|
|
43
|
-
* $ ffc ai
|
|
44
|
-
* $ ffc ai
|
|
45
|
-
* $ ffc ai
|
|
46
|
-
* $ ffc ai
|
|
47
|
-
* $ ffc ai
|
|
34
|
+
* $ ffc ai index add --dry-run ./src
|
|
35
|
+
* $ ffc ai index add "*.ts" "*.md" "*.mdx"
|
|
36
|
+
* $ ffc ai index add --diff
|
|
37
|
+
* $ ffc ai index add --diff --base-ref origin/main
|
|
38
|
+
* $ ffc ai index add --clean "*.ts"
|
|
48
39
|
*/
|
|
49
|
-
const _command = createCommand('
|
|
50
|
-
.description('
|
|
40
|
+
const _command = createCommand('add')
|
|
41
|
+
.description('Add documents to the AI search index via embedding generation')
|
|
51
42
|
.addOption(createOption('--dry-run', 'Show what would be processed without actually doing it').default(false))
|
|
52
43
|
.addOption(createOption('--config <config>', 'Path to a config file').default('fusion-ai.config'))
|
|
53
44
|
.addOption(createOption('--diff', 'Process only changed files (workflow mode)').default(false))
|
|
54
45
|
.addOption(createOption('--base-ref <ref>', 'Git reference to compare against').default('HEAD~1'))
|
|
55
46
|
.addOption(createOption('--clean', 'Delete all existing documents from the vector store before processing').default(false))
|
|
56
47
|
.argument('[glob-patterns...]', 'Glob patterns to match files (optional when using --diff)')
|
|
57
|
-
.action(async (patterns, commandOptions)
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
const config = await loadFusionAIConfig(
|
|
61
|
-
baseDir: process.cwd(),
|
|
62
|
-
});
|
|
63
|
-
// CLI args take precedence over config patterns
|
|
48
|
+
.action(async function (patterns, commandOptions) {
|
|
49
|
+
// Load configuration before validation so config values can fill gaps
|
|
50
|
+
const preOptions = commandOptions;
|
|
51
|
+
const config = await loadFusionAIConfig(preOptions.config ?? 'fusion-ai.config', { baseDir: process.cwd() });
|
|
64
52
|
const indexConfig = config.index ?? {};
|
|
53
|
+
// Config file values override env-var defaults but not explicit CLI flags.
|
|
54
|
+
// Commander merges env vars before the action runs, so we use
|
|
55
|
+
// getOptionValueSource to distinguish "user passed --flag" from "came from env".
|
|
56
|
+
const parentCommand = this.parent ?? this;
|
|
57
|
+
if (indexConfig.name) {
|
|
58
|
+
const source = parentCommand.getOptionValueSource('azureSearchIndexName');
|
|
59
|
+
if (source !== 'cli') {
|
|
60
|
+
preOptions.azureSearchIndexName = indexConfig.name;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
if (indexConfig.model) {
|
|
64
|
+
const source = parentCommand.getOptionValueSource('openaiEmbeddingDeployment');
|
|
65
|
+
if (source !== 'cli') {
|
|
66
|
+
preOptions.openaiEmbeddingDeployment = indexConfig.model;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
const options = await CommandOptionsSchema.parseAsync(preOptions);
|
|
70
|
+
// CLI args take precedence over config patterns
|
|
65
71
|
const allowedFilePatterns = indexConfig.patterns ?? ['**/*.ts', '**/*.md', '**/*.mdx'];
|
|
66
72
|
const filePatterns = patterns.length ? patterns : allowedFilePatterns;
|
|
67
73
|
// Initialize framework
|
|
@@ -74,9 +80,17 @@ const _command = createCommand('embeddings')
|
|
|
74
80
|
filePatterns,
|
|
75
81
|
});
|
|
76
82
|
});
|
|
83
|
+
/**
|
|
84
|
+
* Configured Commander command for the `ai index add` subcommand.
|
|
85
|
+
*
|
|
86
|
+
* This constant is the fully-configured {@link Command} instance with all
|
|
87
|
+
* AI-specific options (embedding deployment, Azure Search credentials) applied
|
|
88
|
+
* via `withAiOptions`. It is registered with the CLI automatically by
|
|
89
|
+
* {@link registerAiPlugin}.
|
|
90
|
+
*/
|
|
77
91
|
export const command = withAiOptions(_command, {
|
|
78
92
|
includeEmbedding: true,
|
|
79
93
|
includeSearch: true,
|
|
80
94
|
});
|
|
81
95
|
export default command;
|
|
82
|
-
//# sourceMappingURL=command.js.map
|
|
96
|
+
//# sourceMappingURL=embeddings-command.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"embeddings-command.js","sourceRoot":"","sources":["../../src/embeddings-command.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,14 +1,21 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
2
|
import { AiOptionsSchema } from '@equinor/fusion-framework-cli-plugin-ai-base/command-options';
|
|
3
3
|
/**
|
|
4
|
-
* Zod schema for validating command options for the
|
|
4
|
+
* Zod schema for validating command options for the `ai index add` command.
|
|
5
5
|
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
6
|
+
* Extends the base AI options schema ({@link AiOptionsSchema}) with
|
|
7
|
+
* add-specific options such as `--dry-run`, `--diff`, `--config`,
|
|
8
|
+
* `--base-ref`, and `--clean`.
|
|
8
9
|
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
10
|
+
* Azure Search and embedding options that are optional in the base schema
|
|
11
|
+
* become **required** because the add command always writes to a
|
|
12
|
+
* vector store.
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* ```ts
|
|
16
|
+
* const validated = await CommandOptionsSchema.parseAsync(rawOptions);
|
|
17
|
+
* // validated.dryRun, validated.azureSearchEndpoint, etc.
|
|
18
|
+
* ```
|
|
12
19
|
*/
|
|
13
20
|
export const CommandOptionsSchema = AiOptionsSchema.extend({
|
|
14
21
|
// Override optional AI options to make them required for embeddings command
|
|
@@ -45,4 +52,4 @@ export const CommandOptionsSchema = AiOptionsSchema.extend({
|
|
|
45
52
|
.boolean({ message: 'clean must be a boolean value.' })
|
|
46
53
|
.describe('Delete all existing documents from the vector store before processing'),
|
|
47
54
|
}).describe('Command options for the embeddings command');
|
|
48
|
-
//# sourceMappingURL=command.options.js.map
|
|
55
|
+
//# sourceMappingURL=embeddings-command.options.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"embeddings-command.options.js","sourceRoot":"","sources":["../../src/embeddings-command.options.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAE,eAAe,EAAE,MAAM,8DAA8D,CAAC;AAE/F;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG,eAAe,CAAC,MAAM,CAAC;IACzD,4EAA4E;IAC5E,yBAAyB,EAAE,CAAC;SACzB,MAAM,CAAC,EAAE,OAAO,EAAE,+DAA+D,EAAE,CAAC;SACpF,GAAG,CAAC,CAAC,EAAE,uDAAuD,CAAC;SAC/D,QAAQ,CAAC,wCAAwC,CAAC;IACrD,mBAAmB,EAAE,CAAC;SACnB,MAAM,CAAC,EAAE,OAAO,EAAE,2DAA2D,EAAE,CAAC;SAChF,GAAG,CAAC,4CAA4C,CAAC;SACjD,GAAG,CAAC,CAAC,EAAE,mDAAmD,CAAC;SAC3D,QAAQ,CAAC,2BAA2B,CAAC;IACxC,iBAAiB,EAAE,CAAC;SACjB,MAAM,CAAC,EAAE,OAAO,EAAE,0DAA0D,EAAE,CAAC;SAC/E,GAAG,CAAC,CAAC,EAAE,kDAAkD,CAAC;SAC1D,QAAQ,CAAC,sBAAsB,CAAC;IACnC,oBAAoB,EAAE,CAAC;SACpB,MAAM,CAAC,EAAE,OAAO,EAAE,6DAA6D,EAAE,CAAC;SAClF,GAAG,CAAC,CAAC,EAAE,qDAAqD,CAAC;SAC7D,QAAQ,CAAC,yBAAyB,CAAC;IAEtC,8BAA8B;IAC9B,MAAM,EAAE,CAAC;SACN,OAAO,CAAC,EAAE,OAAO,EAAE,iCAAiC,EAAE,CAAC;SACvD,QAAQ,CAAC,wDAAwD,CAAC;IACrE,MAAM,EAAE,CAAC;SACN,MAAM,CAAC,EAAE,OAAO,EAAE,8DAA8D,EAAE,CAAC;SACnF,GAAG,CAAC,CAAC,EAAE,8CAA8C,CAAC;SACtD,QAAQ,CAAC,uBAAuB,CAAC;IACpC,IAAI,EAAE,CAAC;SACJ,OAAO,CAAC,EAAE,OAAO,EAAE,+BAA+B,EAAE,CAAC;SACrD,QAAQ,CAAC,4CAA4C,CAAC;IACzD,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,kCAAkC,CAAC;IAClF,KAAK,EAAE,CAAC;SACL,OAAO,CAAC,EAAE,OAAO,EAAE,gCAAgC,EAAE,CAAC;SACtD,QAAQ,CAAC,uEAAuE,CAAC;CACrF,CAAC,CAAC,QAAQ,CAAC,4CAA4C,CAAC,CAAC"}
|
package/dist/esm/index.js
CHANGED
|
@@ -1,11 +1,44 @@
|
|
|
1
|
+
import { createCommand } from 'commander';
|
|
1
2
|
import { registerAiPlugin as registerAiPluginBase } from '@equinor/fusion-framework-cli-plugin-ai-base';
|
|
2
|
-
import { command as
|
|
3
|
+
import { command as addCommand } from './embeddings-command.js';
|
|
4
|
+
import { deleteCommand as removeCommand } from './delete-command.js';
|
|
5
|
+
import { searchCommand } from './search-command.js';
|
|
3
6
|
/**
|
|
4
|
-
*
|
|
5
|
-
*
|
|
7
|
+
* Parent command for the `ai index` group.
|
|
8
|
+
*
|
|
9
|
+
* Owns three subcommands:
|
|
10
|
+
* - `add` — index documents into the Azure AI Search vector store.
|
|
11
|
+
* - `remove` — remove documents from the vector store.
|
|
12
|
+
* - `search` — query the vector store for indexed documents.
|
|
13
|
+
*/
|
|
14
|
+
const indexCommand = createCommand('index')
|
|
15
|
+
.description('Manage the AI search index (add, search, remove)')
|
|
16
|
+
.addCommand(addCommand)
|
|
17
|
+
.addCommand(removeCommand)
|
|
18
|
+
.addCommand(searchCommand);
|
|
19
|
+
/**
|
|
20
|
+
* Registers the `ai index` command with the Fusion Framework CLI.
|
|
21
|
+
*
|
|
22
|
+
* Adds a single `index` command under `ai` with subcommands for indexing,
|
|
23
|
+
* searching, and removing documents in the Azure AI Search vector store.
|
|
24
|
+
*
|
|
25
|
+
* @param program - The root Commander {@link Command} instance to attach to.
|
|
26
|
+
*
|
|
27
|
+
* @example
|
|
28
|
+
* ```ts
|
|
29
|
+
* import { Command } from 'commander';
|
|
30
|
+
* import { registerAiPlugin } from '@equinor/fusion-framework-cli-plugin-ai-index';
|
|
31
|
+
*
|
|
32
|
+
* const program = new Command();
|
|
33
|
+
* registerAiPlugin(program);
|
|
34
|
+
* program.parse();
|
|
35
|
+
* // ffc ai index add [glob-patterns...]
|
|
36
|
+
* // ffc ai index search <query>
|
|
37
|
+
* // ffc ai index remove [source-paths...]
|
|
38
|
+
* ```
|
|
6
39
|
*/
|
|
7
40
|
export function registerAiPlugin(program) {
|
|
8
|
-
registerAiPluginBase(program,
|
|
41
|
+
registerAiPluginBase(program, indexCommand);
|
|
9
42
|
}
|
|
10
43
|
export default registerAiPlugin;
|
|
11
44
|
// Re-export config utilities for convenience
|
package/dist/esm/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,gBAAgB,IAAI,oBAAoB,EAAE,MAAM,8CAA8C,CAAC;AACxG,OAAO,EAAE,OAAO,IAAI,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,gBAAgB,IAAI,oBAAoB,EAAE,MAAM,8CAA8C,CAAC;AACxG,OAAO,EAAE,OAAO,IAAI,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAChE,OAAO,EAAE,aAAa,IAAI,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACrE,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAIpD;;;;;;;GAOG;AACH,MAAM,YAAY,GAAG,aAAa,CAAC,OAAO,CAAC;KACxC,WAAW,CAAC,kDAAkD,CAAC;KAC/D,UAAU,CAAC,UAAU,CAAC;KACtB,UAAU,CAAC,aAAa,CAAC;KACzB,UAAU,CAAC,aAAa,CAAC,CAAC;AAE7B;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,UAAU,gBAAgB,CAAC,OAAgB;IAC/C,oBAAoB,CAAC,OAAO,EAAE,YAAY,CAAC,CAAC;AAC9C,CAAC;AAED,eAAe,gBAAgB,CAAC;AAEhC,6CAA6C;AAC7C,OAAO,EACL,iBAAiB,GAElB,MAAM,8CAA8C,CAAC"}
|
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
import { createCommand, createOption } from 'commander';
|
|
2
|
+
import { inspect } from 'node:util';
|
|
3
|
+
import { setupFramework } from '@equinor/fusion-framework-cli-plugin-ai-base';
|
|
4
|
+
import { withOptions as withAiOptions, } from '@equinor/fusion-framework-cli-plugin-ai-base/command-options';
|
|
5
|
+
/**
|
|
6
|
+
* Flatten Azure Cognitive Search metadata attributes into a plain object.
|
|
7
|
+
*
|
|
8
|
+
* Azure Search stores custom metadata as an array of `{ key, value }` pairs
|
|
9
|
+
* under an `attributes` property. This helper converts that array into a flat
|
|
10
|
+
* key-value map so consumers can access attributes directly
|
|
11
|
+
* (e.g. `metadata.source` instead of iterating the attributes array).
|
|
12
|
+
*
|
|
13
|
+
* JSON-encoded attribute values are transparently parsed; plain strings are
|
|
14
|
+
* kept as-is.
|
|
15
|
+
*
|
|
16
|
+
* @param metadata - Raw metadata record from an Azure Search document.
|
|
17
|
+
* @returns A shallow copy of `metadata` with the `attributes` array replaced by
|
|
18
|
+
* its flattened key-value entries.
|
|
19
|
+
*/
|
|
20
|
+
const normalizeMetadata = (metadata) => {
|
|
21
|
+
const normalized = { ...metadata };
|
|
22
|
+
if (Array.isArray(normalized.attributes)) {
|
|
23
|
+
const attributesObj = {};
|
|
24
|
+
for (const attr of normalized.attributes) {
|
|
25
|
+
if (typeof attr === 'object' &&
|
|
26
|
+
attr !== null &&
|
|
27
|
+
'key' in attr &&
|
|
28
|
+
'value' in attr &&
|
|
29
|
+
typeof attr.key === 'string') {
|
|
30
|
+
try {
|
|
31
|
+
attributesObj[attr.key] = JSON.parse(attr.value);
|
|
32
|
+
}
|
|
33
|
+
catch {
|
|
34
|
+
attributesObj[attr.key] = attr.value;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
Object.assign(normalized, attributesObj);
|
|
39
|
+
delete normalized.attributes;
|
|
40
|
+
}
|
|
41
|
+
return normalized;
|
|
42
|
+
};
|
|
43
|
+
/**
|
|
44
|
+
* Commander subcommand: **`ai index search`**
|
|
45
|
+
*
|
|
46
|
+
* Performs semantic vector-store search against an Azure Cognitive Search index
|
|
47
|
+
* and displays the matching documents. Use this command to validate that
|
|
48
|
+
* embeddings are indexed correctly, to explore the retrieval corpus, or to
|
|
49
|
+
* test OData filter expressions.
|
|
50
|
+
*
|
|
51
|
+
* Supports two search algorithms:
|
|
52
|
+
* - **`similarity`** (default) — pure cosine-similarity ranking.
|
|
53
|
+
* - **`mmr`** — Maximum Marginal Relevance, which re-ranks results to increase
|
|
54
|
+
* diversity while staying relevant.
|
|
55
|
+
*
|
|
56
|
+
* Results can be output as human-readable text (default) or as JSON objects
|
|
57
|
+
* (`--json`). The `--raw` flag preserves Azure Search's native metadata
|
|
58
|
+
* structure; without it, metadata attributes are flattened by
|
|
59
|
+
* {@link normalizeMetadata}.
|
|
60
|
+
*
|
|
61
|
+
* @example
|
|
62
|
+
* ```sh
|
|
63
|
+
* # Basic similarity search
|
|
64
|
+
* ffc ai index search "how to configure modules"
|
|
65
|
+
*
|
|
66
|
+
* # Limit results and use MMR for diversity
|
|
67
|
+
* ffc ai index search "authentication" --limit 5 --search-type mmr
|
|
68
|
+
*
|
|
69
|
+
* # Filter by package name
|
|
70
|
+
* ffc ai index search "hooks" --filter "metadata/attributes/any(a: a/key eq 'pkg_name' and a/value eq '@equinor/fusion-framework-react')" --json
|
|
71
|
+
*
|
|
72
|
+
* # Verbose output with raw Azure metadata
|
|
73
|
+
* ffc ai index search "API reference" --verbose --raw
|
|
74
|
+
* ```
|
|
75
|
+
*/
|
|
76
|
+
const _command = createCommand('search')
|
|
77
|
+
.description('Search the vector store to validate embeddings and retrieve relevant documents')
|
|
78
|
+
.addOption(createOption('--limit <number>', 'Maximum number of results to return')
|
|
79
|
+
.default(10)
|
|
80
|
+
.argParser(parseInt))
|
|
81
|
+
.addOption(createOption('--search-type <type>', 'Search type: mmr or similarity')
|
|
82
|
+
.choices(['mmr', 'similarity'])
|
|
83
|
+
.default('similarity'))
|
|
84
|
+
.addOption(createOption('--filter <expression>', 'OData filter expression for metadata filtering'))
|
|
85
|
+
.addOption(createOption('--json', 'Output results as JSON').default(false))
|
|
86
|
+
.addOption(createOption('--raw', 'Output raw metadata without normalization').default(false))
|
|
87
|
+
.addOption(createOption('--verbose', 'Enable verbose output').default(false))
|
|
88
|
+
.argument('<query>', 'Search query string')
|
|
89
|
+
.action(async (query, options) => {
|
|
90
|
+
if (options.verbose) {
|
|
91
|
+
console.log('🔍 Initializing framework...');
|
|
92
|
+
}
|
|
93
|
+
const framework = await setupFramework(options);
|
|
94
|
+
if (!options.azureSearchIndexName) {
|
|
95
|
+
throw new Error('Azure Search index name is required');
|
|
96
|
+
}
|
|
97
|
+
if (options.verbose) {
|
|
98
|
+
console.log('✅ Framework initialized successfully');
|
|
99
|
+
console.log(`📇 Index: ${options.azureSearchIndexName}`);
|
|
100
|
+
console.log(`🔎 Searching for: "${query}"`);
|
|
101
|
+
console.log(`📊 Limit: ${options.limit}`);
|
|
102
|
+
console.log(`🔍 Search type: ${options.searchType}`);
|
|
103
|
+
if (options.filter) {
|
|
104
|
+
console.log(`🔧 Filter: ${options.filter}`);
|
|
105
|
+
}
|
|
106
|
+
console.log('');
|
|
107
|
+
}
|
|
108
|
+
const vectorStoreService = framework.ai.getService('search', options.azureSearchIndexName);
|
|
109
|
+
try {
|
|
110
|
+
const filter = options.filter ? { filterExpression: options.filter } : undefined;
|
|
111
|
+
const retrieverOptions = options.searchType === 'mmr'
|
|
112
|
+
? {
|
|
113
|
+
k: options.limit,
|
|
114
|
+
searchType: 'mmr',
|
|
115
|
+
...(filter && { filter: filter }),
|
|
116
|
+
}
|
|
117
|
+
: {
|
|
118
|
+
k: options.limit,
|
|
119
|
+
searchType: 'similarity',
|
|
120
|
+
...(filter && { filter: filter }),
|
|
121
|
+
};
|
|
122
|
+
const retriever = vectorStoreService.asRetriever(retrieverOptions);
|
|
123
|
+
const results = await retriever.invoke(query);
|
|
124
|
+
if (!results || !Array.isArray(results)) {
|
|
125
|
+
throw new Error(`Invalid search results: expected array but got ${results === null ? 'null' : typeof results}`);
|
|
126
|
+
}
|
|
127
|
+
if (options.json) {
|
|
128
|
+
for (const doc of results) {
|
|
129
|
+
if (options.raw) {
|
|
130
|
+
console.log(inspect(doc, { depth: null, colors: true }));
|
|
131
|
+
}
|
|
132
|
+
else {
|
|
133
|
+
const metadata = normalizeMetadata(doc.metadata);
|
|
134
|
+
console.log({
|
|
135
|
+
content: doc.pageContent,
|
|
136
|
+
metadata,
|
|
137
|
+
score: metadata?.score,
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
else {
|
|
143
|
+
if (results.length === 0) {
|
|
144
|
+
console.log('❌ No results found');
|
|
145
|
+
return;
|
|
146
|
+
}
|
|
147
|
+
console.log(`✅ Found ${results.length} result${results.length !== 1 ? 's' : ''}:\n`);
|
|
148
|
+
results.forEach((doc, index) => {
|
|
149
|
+
const processedMetadata = options.raw
|
|
150
|
+
? doc.metadata
|
|
151
|
+
: normalizeMetadata(doc.metadata);
|
|
152
|
+
const metadata = processedMetadata;
|
|
153
|
+
const score = metadata.score;
|
|
154
|
+
const source = metadata.source || 'Unknown source';
|
|
155
|
+
console.log(`${'─'.repeat(80)}`);
|
|
156
|
+
console.log(`Result ${index + 1}${score !== undefined ? ` (Score: ${score.toFixed(4)})` : ''}`);
|
|
157
|
+
console.log(`Source: ${source}`);
|
|
158
|
+
if (options.verbose) {
|
|
159
|
+
const { source: _, score: __, ...otherMetadata } = metadata;
|
|
160
|
+
if (Object.keys(otherMetadata).length > 0) {
|
|
161
|
+
console.log(`Metadata:`, JSON.stringify(otherMetadata, null, 2));
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
console.log('');
|
|
165
|
+
const content = doc.pageContent;
|
|
166
|
+
const maxLength = 500;
|
|
167
|
+
if (content.length > maxLength) {
|
|
168
|
+
console.log(`${content.substring(0, maxLength)}...`);
|
|
169
|
+
console.log(`\n[Content truncated - ${content.length} characters total]`);
|
|
170
|
+
}
|
|
171
|
+
else {
|
|
172
|
+
console.log(content);
|
|
173
|
+
}
|
|
174
|
+
console.log('');
|
|
175
|
+
});
|
|
176
|
+
console.log(`${'─'.repeat(80)}`);
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
catch (error) {
|
|
180
|
+
console.error(`❌ Search failed: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
181
|
+
if (options.verbose && error instanceof Error && error.stack) {
|
|
182
|
+
console.error(error.stack);
|
|
183
|
+
}
|
|
184
|
+
process.exit(1);
|
|
185
|
+
}
|
|
186
|
+
});
|
|
187
|
+
/**
|
|
188
|
+
* Configured Commander command for the `ai index search` subcommand.
|
|
189
|
+
*
|
|
190
|
+
* Fully-configured {@link Command} instance with all AI-specific options
|
|
191
|
+
* (embedding deployment, Azure Search credentials) applied via `withAiOptions`.
|
|
192
|
+
*/
|
|
193
|
+
export const searchCommand = withAiOptions(_command, {
|
|
194
|
+
includeEmbedding: true,
|
|
195
|
+
includeSearch: true,
|
|
196
|
+
});
|
|
197
|
+
export default searchCommand;
|
|
198
|
+
//# sourceMappingURL=search-command.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"search-command.js","sourceRoot":"","sources":["../../src/search-command.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,9 +1,21 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Generates a
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
2
|
+
* Generates a deterministic, URL-safe identifier for a document chunk.
|
|
3
|
+
*
|
|
4
|
+
* The identifier is a Base64-encoded hash of the file path with all
|
|
5
|
+
* non-alphanumeric characters stripped, making it safe for use as an
|
|
6
|
+
* Azure AI Search document key.
|
|
7
|
+
*
|
|
8
|
+
* @param filePath - The relative file path to hash.
|
|
9
|
+
* @param chunkIndex - Optional zero-based chunk index appended to distinguish
|
|
10
|
+
* multiple chunks originating from the same file.
|
|
11
|
+
* @returns A stable, alphanumeric document ID string.
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* ```ts
|
|
15
|
+
* generateChunkId('packages/cli/src/index.ts'); // 'cGFja2FnZXMvY2xpL3NyYy9pbmRleC50cw'
|
|
16
|
+
* generateChunkId('packages/cli/src/index.ts', 0); // 'cGFja2FnZXMvY2xpL3NyYy9pbmRleC50cw-0'
|
|
17
|
+
* generateChunkId('packages/cli/src/index.ts', 3); // 'cGFja2FnZXMvY2xpL3NyYy9pbmRleC50cw-3'
|
|
18
|
+
* ```
|
|
7
19
|
*/
|
|
8
20
|
export const generateChunkId = (filePath, chunkIndex) => {
|
|
9
21
|
// Convert file path to base64 and remove non-alphanumeric characters
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"generate-chunk-id.js","sourceRoot":"","sources":["../../../src/utils/generate-chunk-id.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"generate-chunk-id.js","sourceRoot":"","sources":["../../../src/utils/generate-chunk-id.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,QAAgB,EAAE,UAAmB,EAAU,EAAE;IAC/E,qEAAqE;IACrE,gEAAgE;IAChE,yEAAyE;IACzE,MAAM,QAAQ,GAAG,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC;SACnC,QAAQ,CAAC,QAAQ,CAAC;SAClB,OAAO,CAAC,eAAe,EAAE,EAAE,CAAC,CAAC;IAChC,mFAAmF;IACnF,OAAO,UAAU,CAAC,CAAC,CAAC,GAAG,QAAQ,IAAI,UAAU,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC;AAC7D,CAAC,CAAC"}
|
|
@@ -1,9 +1,15 @@
|
|
|
1
1
|
import { join, relative } from 'node:path';
|
|
2
2
|
import { resolveProjectRoot, getGit } from './git-client.js';
|
|
3
3
|
/**
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
4
|
+
* Returns a list of files changed between `baseRef` and HEAD.
|
|
5
|
+
*
|
|
6
|
+
* Parses the output of `git diff --name-status` to classify each file as
|
|
7
|
+
* `'new'`, `'modified'`, or `'removed'`. Renames are expanded into a
|
|
8
|
+
* `'removed'` entry for the old path and a `'new'` entry for the new path.
|
|
9
|
+
*
|
|
10
|
+
* @param options - Configuration controlling the diff reference and working directory.
|
|
11
|
+
* @returns Array of changed files with their status.
|
|
12
|
+
* @throws {Error} If the working directory is not inside a git repository.
|
|
7
13
|
*/
|
|
8
14
|
export const getChangedFiles = async (options) => {
|
|
9
15
|
const { diff, baseRef = 'HEAD~1', cwd = process.cwd() } = options;
|
|
@@ -70,10 +76,15 @@ export const getChangedFiles = async (options) => {
|
|
|
70
76
|
}
|
|
71
77
|
};
|
|
72
78
|
/**
|
|
73
|
-
*
|
|
74
|
-
*
|
|
75
|
-
*
|
|
76
|
-
*
|
|
79
|
+
* Determines the git change status of a single file.
|
|
80
|
+
*
|
|
81
|
+
* Checks tracked status, porcelain output, and rename/copy detection to
|
|
82
|
+
* produce one or two {@link ChangedFile} entries (two when a rename is
|
|
83
|
+
* detected — one `'removed'` for the old path and one `'new'` for the
|
|
84
|
+
* current path).
|
|
85
|
+
*
|
|
86
|
+
* @param filePath - Absolute path to the file to inspect.
|
|
87
|
+
* @returns Array with one or two changed-file entries.
|
|
77
88
|
*/
|
|
78
89
|
export const getFileStatus = async (filePath) => {
|
|
79
90
|
const { git, gitRepoPath } = getGit(filePath) ?? {};
|
|
@@ -182,10 +193,14 @@ export const getFileStatus = async (filePath) => {
|
|
|
182
193
|
}
|
|
183
194
|
};
|
|
184
195
|
/**
|
|
185
|
-
*
|
|
186
|
-
*
|
|
187
|
-
*
|
|
188
|
-
*
|
|
196
|
+
* Checks whether a file path appears in a list of changed files.
|
|
197
|
+
*
|
|
198
|
+
* When the changed-files list is empty (no diff filtering active), every
|
|
199
|
+
* file is considered changed so that all files are processed.
|
|
200
|
+
*
|
|
201
|
+
* @param filePath - Absolute file path to look up.
|
|
202
|
+
* @param changedFiles - Array of {@link ChangedFile} entries to search.
|
|
203
|
+
* @returns `true` if the file has changed or if diff filtering is disabled.
|
|
189
204
|
*/
|
|
190
205
|
export const isFileChanged = (filePath, changedFiles) => {
|
|
191
206
|
if (changedFiles.length === 0) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"file-changes.js","sourceRoot":"","sources":["../../../../src/utils/git/file-changes.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAE3C,OAAO,EAAE,kBAAkB,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AAE7D
|
|
1
|
+
{"version":3,"file":"file-changes.js","sourceRoot":"","sources":["../../../../src/utils/git/file-changes.ts"],"names":[],"mappings":"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"}
|
|
@@ -4,9 +4,13 @@ import { dirname, join } from 'node:path';
|
|
|
4
4
|
import { existsSync } from 'node:fs';
|
|
5
5
|
const gitCache = new Map();
|
|
6
6
|
/**
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
7
|
+
* Resolves the git repository root for a given file path.
|
|
8
|
+
*
|
|
9
|
+
* Walks up the directory tree looking for a `.git` directory or file
|
|
10
|
+
* (to support worktrees) and returns the enclosing directory.
|
|
11
|
+
*
|
|
12
|
+
* @param filePath - Absolute file or directory path to resolve from.
|
|
13
|
+
* @returns Absolute path to the repository root, or `undefined` if not inside a git repo.
|
|
10
14
|
*/
|
|
11
15
|
export const resolveProjectRoot = (filePath) => {
|
|
12
16
|
// if we are in the root of the git repository, return the root
|
|
@@ -18,10 +22,15 @@ export const resolveProjectRoot = (filePath) => {
|
|
|
18
22
|
return projectRoot;
|
|
19
23
|
};
|
|
20
24
|
/**
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
+
* Returns a cached `SimpleGit` instance scoped to the repository that
|
|
26
|
+
* contains `filePath`.
|
|
27
|
+
*
|
|
28
|
+
* Instances are cached by repository root to avoid repeatedly spawning
|
|
29
|
+
* new git processes for the same repo.
|
|
30
|
+
*
|
|
31
|
+
* @param filePath - Absolute file path to locate the repository for.
|
|
32
|
+
* @returns An object containing the git client and the repository root path,
|
|
33
|
+
* or `undefined` when `filePath` is not inside a git repository.
|
|
25
34
|
*/
|
|
26
35
|
export const getGit = (filePath) => {
|
|
27
36
|
const gitRepoPath = resolveProjectRoot(filePath);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"git-client.js","sourceRoot":"","sources":["../../../../src/utils/git/git-client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAkB,MAAM,YAAY,CAAC;AACvD,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAErC,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAqB,CAAC;AAE9C
|
|
1
|
+
{"version":3,"file":"git-client.js","sourceRoot":"","sources":["../../../../src/utils/git/git-client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAkB,MAAM,YAAY,CAAC;AACvD,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAErC,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAqB,CAAC;AAE9C;;;;;;;;GAQG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,QAAgB,EAAsB,EAAE;IACzE,+DAA+D;IAC/D,IAAI,UAAU,CAAC,IAAI,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC,EAAE,CAAC;QACvC,OAAO,QAAQ,CAAC;IAClB,CAAC;IACD,MAAM,WAAW,GAAG,UAAU,CAAC,MAAM,EAAE,EAAE,GAAG,EAAE,OAAO,CAAC,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC;IACjF,MAAM,WAAW,GAAG,WAAW,EAAE,OAAO,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;IACvD,OAAO,WAAW,CAAC;AACrB,CAAC,CAAC;AAEF;;;;;;;;;;GAUG;AACH,MAAM,CAAC,MAAM,MAAM,GAAG,CACpB,QAAgB,EACiD,EAAE;IACnE,MAAM,WAAW,GAAG,kBAAkB,CAAC,QAAQ,CAAC,CAAC;IACjD,IAAI,WAAW,EAAE,CAAC;QAChB,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,WAAW,CAAC,EAAE,CAAC;YAC/B,QAAQ,CAAC,GAAG,CAAC,WAAW,EAAE,SAAS,CAAC,WAAW,CAAC,CAAC,CAAC;QACpD,CAAC;QACD,OAAO;YACL,GAAG,EAAE,QAAQ,CAAC,GAAG,CAAC,WAAW,CAAC;YAC9B,WAAW;SACZ,CAAC;IACJ,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC,CAAC"}
|
|
@@ -17,9 +17,13 @@ const generateGithubPermalink = (gitRemoteUrl, filePath, slug) => {
|
|
|
17
17
|
return undefined;
|
|
18
18
|
};
|
|
19
19
|
/**
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
20
|
+
* Extracts git metadata for a single source file.
|
|
21
|
+
*
|
|
22
|
+
* Resolves the latest commit hash, commit date, and a GitHub permalink
|
|
23
|
+
* (when the remote is a GitHub URL) by inspecting `git log` output.
|
|
24
|
+
*
|
|
25
|
+
* @param filePath - Absolute path to the file.
|
|
26
|
+
* @returns Git metadata, or `undefined` if the file is not inside a git repository.
|
|
23
27
|
*/
|
|
24
28
|
export const extractGitMetadata = async (filePath) => {
|
|
25
29
|
const { git, gitRepoPath: gitRepoRoot } = getGit(filePath) ?? {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"metadata.js","sourceRoot":"","sources":["../../../../src/utils/git/metadata.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAErC,OAAO,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AAEzC;;;;;;;GAOG;AACH,MAAM,uBAAuB,GAAG,CAC9B,YAAoB,EACpB,QAAgB,EAChB,IAAa,EACO,EAAE;IACtB,MAAM,WAAW,GAAG,YAAY,CAAC,KAAK,CAAC,6CAA6C,CAAC,CAAC;IACtF,IAAI,WAAW,EAAE,CAAC;QAChB,MAAM,CAAC,EAAE,KAAK,EAAE,IAAI,CAAC,GAAG,WAAW,CAAC;QACpC,OAAO,sBAAsB,KAAK,IAAI,IAAI,SAAS,IAAI,IAAI,MAAM,IAAI,QAAQ,EAAE,CAAC;IAClF,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC,CAAC;AAEF
|
|
1
|
+
{"version":3,"file":"metadata.js","sourceRoot":"","sources":["../../../../src/utils/git/metadata.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAErC,OAAO,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AAEzC;;;;;;;GAOG;AACH,MAAM,uBAAuB,GAAG,CAC9B,YAAoB,EACpB,QAAgB,EAChB,IAAa,EACO,EAAE;IACtB,MAAM,WAAW,GAAG,YAAY,CAAC,KAAK,CAAC,6CAA6C,CAAC,CAAC;IACtF,IAAI,WAAW,EAAE,CAAC;QAChB,MAAM,CAAC,EAAE,KAAK,EAAE,IAAI,CAAC,GAAG,WAAW,CAAC;QACpC,OAAO,sBAAsB,KAAK,IAAI,IAAI,SAAS,IAAI,IAAI,MAAM,IAAI,QAAQ,EAAE,CAAC;IAClF,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC,CAAC;AAEF;;;;;;;;GAQG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG,KAAK,EAAE,QAAgB,EAAoC,EAAE;IAC7F,MAAM,EAAE,GAAG,EAAE,WAAW,EAAE,WAAW,EAAE,GAAG,MAAM,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC;IACjE,IAAI,CAAC,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC;QACzB,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,MAAM,WAAW,GAAG,QAAQ,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAC;IACpD,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,GAAG,CAAC,GAAG,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,QAAQ,EAAE,CAAC,EAAE,CAAC,CAAC;IACrE,MAAM,YAAY,GAAG,MAAM,GAAG;SAC3B,SAAS,CAAC,mBAAmB,CAAC;SAC9B,IAAI,CAAC,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,KAAK,IAAI,SAAS,CAAC,CAAC;IAC3C,MAAM,QAAQ,GAAG,YAAY,CAAC,CAAC,CAAC,uBAAuB,CAAC,YAAY,EAAE,WAAW,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IAC/F,OAAO;QACL,QAAQ;QACR,eAAe,EAAE,MAAM,EAAE,IAAI;QAC7B,eAAe,EAAE,MAAM,EAAE,IAAI;KAC9B,CAAC;AACJ,CAAC,CAAC"}
|