diff --git a/.docs/vscode-configuration-release-20261014.md b/.docs/vscode-configuration-release-20261014.md new file mode 100644 index 000000000..b1980cd3d --- /dev/null +++ b/.docs/vscode-configuration-release-20261014.md @@ -0,0 +1,26 @@ +# VS Code configuration fixes and Continue 0.1.1 + +Refs terraphim/terraphim-ai#3488 (Gitea). + +The released VS Code 0.1.2 package ignored the configured Atomic agent on first autocomplete activation, retained a Store after endpoint changes, and did not consult `enableLocalServer` when sending requests. Its README also attributed a two-character trigger to the Atomic provider, which only responds after a space. + +## Changes + +- `src/helpers/getStore.ts` reads current settings and keys the actual `@tomic/lib` Store by endpoint and agent. Empty credentials use anonymous access; invalid credentials do not replace a valid cache entry or claim successful activation. +- `src/extension.ts` resolves the current Store for commands and completion requests. A response from an old Store is discarded. Configuration failures produce actionable notifications. +- `src/helpers/serverConnection.ts` uses the configured HTTP(S) URL for every request. With local mode disabled it refuses literal localhost/loopback URLs; it never invents a public fallback. This is URL selection, not a DNS/network security boundary. Requests have a five-second timeout and endpoint/role changes advance a revision. +- `src/helpers/completionCache.ts` tracks both request generation and configuration revision. An old response cannot populate a newer query's cache, and an old query cannot fall back to a newly configured endpoint. +- Packaged README/settings/changelog describe this behavior and the actual Atomic space trigger. Version 0.1.3 includes the previously merged runnable examples for the separately installed `terraphim-grep` and `terraphim-agent` CLIs. +- Continue 0.1.1 packages those CLI examples and the tested graph-restart instructions. Its actual MCP initialization version is checked against the integration manifest. This release does not add a Continue Hub listing or change model configuration. + +## Verification + +Before bumping versions: TypeScript compile and ESLint pass; 63 package/integrity tests, 29 existing actual-WASM/protocol/export/link tests, four request-cache state regressions, and six real Continue SDK/install/package/source tests pass. Continue transport uses released `terraphim-grep` 1.21.20 locally; CI retains its pinned Linux 1.21.19 binary. + +`tests/nativeConfiguration.cjs` runs through the existing packaged native-host suite. It updates only that suite's disposable profile, exercises the actual VS Code API and packaged Atomic Store, restores settings, and saves a separate `configuration.json`. It proves configured credentials on first activation, Store replacement after endpoint/credential changes, anonymous reset, malformed-agent refusal, canonical loopback refusal, explicit remote URL selection, real unavailable-server handling, and role revision changes. It does not claim authenticated remote service access. + +Local VS Code 1.141.2 passed those configuration checks and actual saved-file/KG outputs. One earlier candidate also passed native history/reopen; the later candidate refused the history assertion because its window was unfocused. That failed attempt is retained and does not qualify the final package. The immutable release workflow must pass the complete lifecycle on the exact packaged bytes on Linux, macOS and Windows before publication. No all-41 or visual-UI qualification is added by these tests. + +The first PR matrix passed Linux/macOS but failed Windows' local-mode assertion. Its log initialized two Stores at the same endpoint: dynamically requiring a Windows URI-derived path can instantiate another copy of a singleton. The native test now selects exactly one already loaded production module by actual file identity, records requested/loaded paths, and retains all refusal assertions. A fresh complete matrix must confirm the correction; the test never refreshes the singleton itself or substitutes its API. + +No release asset replacement, tag reuse, Open VSX readiness change or branch-protection change is part of this amendment. diff --git a/integrations/continue/README.md b/integrations/continue/README.md index 7e76e989b..9230a8bf9 100644 --- a/integrations/continue/README.md +++ b/integrations/continue/README.md @@ -78,8 +78,16 @@ TERRAPHIM_CONTINUE_RECEIPT=/absolute/new-receipt.json \ The actual SDK client initializes the actual stdio server and calls the released CLI. It verifies literal Concern baseline has no chunks, the exported graph retrieves Risk, retrieval has no answer, synthesis is unavailable by default, invalid parameters and changed graph are refused. Installer tests execute the real installer and verify preservation and symlink refusal. No provider synthesis or native Continue UI acceptance is inferred from these tests. -`risk-concern.exported.json` is the exact public graph exported by the existing VS Code editor in the 2026-10-12 native proof; it is a reusable example input, not evidence of a new operation. The integration CI downloads the immutable 1.21.19 Linux archive, verifies its pinned digest, runs these tests, and produces a separately downloadable zip and SHA256SUMS. A dedicated `terraphim_continue-v0.1.0` tag runs the checks before publishing its own two-asset integration release; it never attaches to VS Code releases. The bundle records its source commit, clean-tree state and payload hashes. Immediately before each release mutation, the workflow verifies the live remote peeled tag still equals the qualified source and belongs to main history. Existing release assets must match exactly; partial uploads fail closed for inspection. The release job uses immutable action versions, a `continue-releases` environment, per-tag concurrency, and mandatory anonymous exact-byte download verification after publication. +`risk-concern.exported.json` is the exact public graph exported by the existing VS Code editor in the 2026-10-12 native proof; it is a reusable example input, not evidence of a new operation. The integration CI downloads the immutable 1.21.19 Linux archive, verifies its pinned digest, runs these tests, and produces a separately downloadable zip and SHA256SUMS. A dedicated `terraphim_continue-v0.1.1` tag runs the checks before publishing its own two-asset integration release; it never attaches to VS Code releases. The bundle records its source commit, clean-tree state and payload hashes. Immediately before each release mutation, the workflow verifies the live remote peeled tag still equals the qualified source and belongs to main history. Existing release assets must match exactly; partial uploads fail closed for inspection. The release job uses immutable action versions, a `continue-releases` environment, per-tag concurrency, and mandatory anonymous exact-byte download verification after publication. We inspected the existing clients `terraphim_mcp_server`: it is a broader role-configured `TerraphimService` server, not installed in this environment, and its search path does not delegate the exact released grep exported-graph/`--answer` behavior. This thin transport reuses the released CLI instead of changing that service or reimplementing KG semantics. The maintained MCP v1 SDK 1.30.0 is pinned to match the existing stdio API; v2 is available but requires a separate compatibility qualification. References: [Continue MCP configuration](https://docs.continue.dev/customize/deep-dives/mcp), [Continue rules](https://docs.continue.dev/customize/deep-dives/rules), [official MCP Python SDK](https://github.com/modelcontextprotocol/python-sdk). + +## Release notes + +### 0.1.1 + +- Include runnable examples for the separately installed `terraphim-grep` and `terraphim-agent` CLIs, including Logseq-compatible `synonyms::` concept Markdown. +- Clarify graph updates: a running connection refuses changed graph bytes; reviewing the replacement and restarting captures the new graph digest. +- Verify that behavior with the actual MCP transport and released `terraphim-grep` output. diff --git a/integrations/continue/integration.json b/integrations/continue/integration.json index a9ed666f1..99ad7f2a9 100644 --- a/integrations/continue/integration.json +++ b/integrations/continue/integration.json @@ -1 +1 @@ -{"name":"terraphim-continue-integration","version":"0.1.0","tagPrefix":"terraphim_continue-v","mode":"Agent","nativeContinueQualified":false} +{"name":"terraphim-continue-integration","version":"0.1.1","tagPrefix":"terraphim_continue-v","mode":"Agent","nativeContinueQualified":false} diff --git a/integrations/continue/server.py b/integrations/continue/server.py index 895078d34..5efbe3d98 100644 --- a/integrations/continue/server.py +++ b/integrations/continue/server.py @@ -94,7 +94,7 @@ async def call(name, arguments): return await execute(name, arguments) async with stdio_server() as (read, write): - await server.run(read, write, InitializationOptions(server_name='terraphim-continue', server_version='0.1.0', capabilities=server.get_capabilities(notification_options=NotificationOptions(), experimental_capabilities={}))) + await server.run(read, write, InitializationOptions(server_name='terraphim-continue', server_version='0.1.1', capabilities=server.get_capabilities(notification_options=NotificationOptions(), experimental_capabilities={}))) if __name__ == '__main__': diff --git a/integrations/continue/test_package.py b/integrations/continue/test_package.py index cabd1bf31..734a69430 100644 --- a/integrations/continue/test_package.py +++ b/integrations/continue/test_package.py @@ -12,7 +12,7 @@ def test_complete_allowlisted_bundle_and_refuse_overwrite(self): with tempfile.TemporaryDirectory() as directory: root = Path(directory) package(root) - archive = root / 'terraphim-continue-integration-0.1.0.zip' + archive = root / 'terraphim-continue-integration-0.1.1.zip' with zipfile.ZipFile(archive) as bundle: self.assertEqual(bundle.namelist(), ['terraphim-continue/' + name for name in FILES] + ['terraphim-continue/source.json']) self.assertEqual((root / 'terraphim-continue-SHA256SUMS').read_text(), hashlib.sha256(archive.read_bytes()).hexdigest() + ' ' + archive.name + '\n') diff --git a/integrations/continue/test_source.py b/integrations/continue/test_source.py index 128a15669..ef936b576 100644 --- a/integrations/continue/test_source.py +++ b/integrations/continue/test_source.py @@ -12,6 +12,7 @@ def test_lightweight_and_annotated_tag_identity(self): def test_actual_git_tag_gate_and_moved_tag_refusal(self): from pathlib import Path + import json import shutil import subprocess import sys @@ -29,13 +30,15 @@ def git(*args, cwd=repo): git('add', '.') git('commit', '-m', 'Public integration fixture') head = git('rev-parse', 'HEAD') - tag = 'terraphim_continue-v0.1.0' + manifest = json.loads((here / 'integration.json').read_text()) + tag = manifest['tagPrefix'] + manifest['version'] + archive_name = f"terraphim-continue-integration-{manifest['version']}.zip" git('tag', tag) git('clone', '--bare', str(repo), str(origin)) git('remote', 'add', 'origin', str(origin)) build = root / 'build' subprocess.check_call([sys.executable, str(repo / 'integrations/continue/package.py'), str(build)], stdout=subprocess.DEVNULL) - command = [sys.executable, str(repo / 'integrations/continue/verify_source.py'), '--tag', tag, '--qualified', head, '--archive', str(build / 'terraphim-continue-integration-0.1.0.zip')] + command = [sys.executable, str(repo / 'integrations/continue/verify_source.py'), '--tag', tag, '--qualified', head, '--archive', str(build / archive_name)] self.assertEqual(subprocess.run(command, capture_output=True).returncode, 0) (repo / 'new.md').write_text('New public source revision\n') git('add', 'new.md') @@ -46,7 +49,7 @@ def git(*args, cwd=repo): git('update-ref', 'refs/tags/' + tag, changed, cwd=origin) unreviewed_build = root / 'unreviewed-build' subprocess.check_call([sys.executable, str(repo / 'integrations/continue/package.py'), str(unreviewed_build)], stdout=subprocess.DEVNULL) - unreviewed = [sys.executable, str(repo / 'integrations/continue/verify_source.py'), '--tag', tag, '--qualified', changed, '--archive', str(unreviewed_build / 'terraphim-continue-integration-0.1.0.zip')] + unreviewed = [sys.executable, str(repo / 'integrations/continue/verify_source.py'), '--tag', tag, '--qualified', changed, '--archive', str(unreviewed_build / archive_name)] self.assertNotEqual(subprocess.run(unreviewed, capture_output=True).returncode, 0) git('checkout', '--detach', head) refused = subprocess.run(command, capture_output=True) diff --git a/integrations/continue/test_transport.py b/integrations/continue/test_transport.py index a7d9a08f8..990b3a9ad 100644 --- a/integrations/continue/test_transport.py +++ b/integrations/continue/test_transport.py @@ -27,7 +27,7 @@ async def exercise(): (corpus / 'brief.md').write_text('Risk: supplier delays require a backup plan.\n') local_graph = Path(directory) / 'graph.json' local_graph.write_bytes(graph.read_bytes()) - baseline = json.loads(subprocess.check_output([str(binary), '--search-only', '--json', '--paths', str(corpus), '--', 'Concern'], cwd=corpus)) + baseline = json.loads(subprocess.check_output([str(binary), '--search-only', '--json', '--paths', str(corpus), '--', 'Concern'], cwd=corpus, timeout=30)) self.assertEqual(baseline['chunks'], []) receipt['baseline'] = baseline params = StdioServerParameters(command=sys.executable, args=[str(HERE / 'server.py'), @@ -35,7 +35,9 @@ async def exercise(): '--graph', str(local_graph), '--corpus', str(corpus)]) async with stdio_client(params) as streams: async with ClientSession(*streams) as session: - await session.initialize() + initialized = await session.initialize() + self.assertEqual(initialized.serverInfo.version, json.loads((HERE / 'integration.json').read_text())['version']) + receipt['serverVersion'] = initialized.serverInfo.version tools = await session.list_tools() self.assertEqual([t.name for t in tools.tools], ['terraphim_retrieve']) result = await session.call_tool('terraphim_retrieve', {'query': 'Concern'}) diff --git a/vs-code-terraphim-it/CHANGELOG.md b/vs-code-terraphim-it/CHANGELOG.md index f3223d926..8e8e5b563 100644 --- a/vs-code-terraphim-it/CHANGELOG.md +++ b/vs-code-terraphim-it/CHANGELOG.md @@ -1,5 +1,13 @@ # Changelog +## 0.1.3 (preview) + +- Read the configured Atomic agent on first autocomplete activation and rebuild the store when its agent or endpoint changes. Clearing the agent selects anonymous access; invalid credentials refuse activation. +- Apply `enableLocalServer` to every server request: disabling it refuses localhost and loopback URLs with an actionable warning. An explicit remote `serverUrl` is required; no remote fallback is selected automatically. +- Discard stale autocomplete responses when the role, endpoint, agent or query changes while loading. +- Correct the Atomic autocomplete instructions: it triggers after a space, not merely after two characters. +- Include runnable `terraphim-grep` synonym-search and `terraphim-agent` memory examples, with separate CLI installation and links to the public walkthroughs. + ## 0.1.2 (preview) - Verify the federated service principal and its Azure DevOps profile before Marketplace publication; retain non-secret identity evidence and refuse an unconfirmed profile. diff --git a/vs-code-terraphim-it/README.md b/vs-code-terraphim-it/README.md index 7210f0fdb..d7f0d4429 100644 --- a/vs-code-terraphim-it/README.md +++ b/vs-code-terraphim-it/README.md @@ -92,12 +92,14 @@ Configure the extension through VS Code settings: ### Server Configuration - `terraphimIt.serverUrl`: Main Terraphim server URL (default: `http://localhost:8000`) - `terraphimIt.atomicServerUrl`: Atomic server URL for knowledge base (default: `https://common.terraphim.io/drive/h6grD0ID`) -- `terraphimIt.enableLocalServer`: Use local server instead of remote (default: `true`) +- `terraphimIt.enableLocalServer`: Allow localhost and loopback URLs (default: `true`). When `false`, set `serverUrl` to your remote Terraphim server. Local URLs are refused with a configuration warning; the extension never selects a remote service automatically. This checks the configured URL, not DNS resolution. ### Role and Agent Configuration - `terraphimIt.selectedRole`: Default role for searches and autocomplete (default: `Terraphim Engineer`) - `terraphimIt.agent`: Agent string for authentication (optional) +Endpoint and agent changes take effect on the next Atomic request, including an already enabled autocomplete provider. Clearing `agent` selects anonymous access. Server endpoint and role changes invalidate cached completion results. + ## Getting Started 1. **Install Terraphim It** from the [Visual Studio Marketplace](https://marketplace.visualstudio.com/items?itemName=applied-knowledge-systems.terraphim-it) or [Open VSX](https://open-vsx.org/extension/applied-knowledge-systems/terraphim-it). Compatible Cursor installations use the Open VSX package. @@ -136,8 +138,8 @@ Uses atomic store integration: ### Autocomplete Usage 1. Enable your preferred autocomplete provider 2. Start typing in any file -3. Autocomplete suggestions will appear as you type -4. Suggestions are triggered after 2+ characters and on space +3. For **Terraphim AI Autocomplete**, type a space after your text. It offers terms from the Atomic knowledge base; typing two characters alone does not trigger Atomic results. Manual completion also requires a trailing space. +4. For **Terraphim Server Autocomplete**, type at least two characters and invoke completion, or type a space after that word. The configured server supplies the suggestions. ### Server Health Check Use the health check command to verify: @@ -188,7 +190,7 @@ The editor importer verifies published hashes. The existing link wrapper reuses **Autocomplete not working:** - Ensure you've activated an autocomplete provider -- Check that you're typing at least 2 characters +- For Atomic autocomplete, place the cursor after a space. For server autocomplete, use a word with at least two characters. - Verify server connectivity if using server-based providers **Authentication errors:** diff --git a/vs-code-terraphim-it/out/extension.js b/vs-code-terraphim-it/out/extension.js index 88e8a02de..8bc687736 100644 --- a/vs-code-terraphim-it/out/extension.js +++ b/vs-code-terraphim-it/out/extension.js @@ -7,11 +7,10 @@ const lib_1 = require("@tomic/lib"); const getStore_1 = require("./helpers/getStore"); const serverConnection_1 = require("./helpers/serverConnection"); const linkReplacement_1 = require("./helpers/linkReplacement"); +const completionCache_1 = require("./helpers/completionCache"); const airportOntology_1 = require("./ontologies/airportOntology"); function activate(context) { (0, alternativeControl_1.registerAlternativeControl)(context); - let agent; - let store; let activeProvider; const disposable = vscode.commands.registerCommand('extension.terraphimCommand', async function () { const editor = vscode.window.activeTextEditor; @@ -24,22 +23,20 @@ function activate(context) { const text = document.getText(); // Get the configuration const config = vscode.workspace.getConfiguration('terraphimIt'); - // Only ask for agent if it's not set and hasn't been asked before + let agent = config.get('agent'); + // Read current settings on every command, including changes since activation. if (!agent) { - agent = config.get('agent'); - if (!agent) { - agent = await vscode.window.showInputBox({ - prompt: 'Enter the agent to use for Terraphim IT (optional)', - placeHolder: 'Agent String' - }); - // Save the agent to configuration if provided - if (agent) { - await config.update('agent', agent, vscode.ConfigurationTarget.Global); - } + agent = await vscode.window.showInputBox({ + prompt: 'Enter the agent to use for Terraphim IT (optional)', + placeHolder: 'Agent String' + }); + // Save the agent to configuration if provided + if (agent) { + await config.update('agent', agent, vscode.ConfigurationTarget.Global); } } try { - store = (0, getStore_1.getStore)(agent); + const store = (0, getStore_1.getStore)(agent); const results = await get_all_resources(store); const replacedText = await (0, linkReplacement_1.replaceLinks)(text, JSON.stringify(results)); if (document.isClosed || document.version !== version || document.getText() !== text) { @@ -62,8 +59,12 @@ function activate(context) { context.subscriptions.push(disposable); // Register the Terraphim AI Autocomplete command const autocompleteDisposable = vscode.commands.registerCommand('extension.terraphimAIAutocomplete', async function () { - if (!store) { - store = (0, getStore_1.getStore)(agent); + try { + (0, getStore_1.getStore)(); // Validate current credentials before claiming activation. + } + catch (error) { + vscode.window.showErrorMessage(`Cannot enable Atomic autocomplete: ${error instanceof Error ? error.message : 'invalid configuration'}`); + return false; } // Deactivate the existing provider if any if (activeProvider) { @@ -71,11 +72,12 @@ function activate(context) { activeProvider = undefined; } // Register the completion provider - const provider = vscode.languages.registerCompletionItemProvider({ scheme: 'file', language: '*' }, new TerraphimCompletionProvider(store), ' ' // Trigger on space + const provider = vscode.languages.registerCompletionItemProvider({ scheme: 'file', language: '*' }, new TerraphimCompletionProvider(), ' ' // Trigger on space ); activeProvider = provider; context.subscriptions.push(provider); vscode.window.showInformationMessage('Terraphim AI Autocomplete activated'); + return true; }); context.subscriptions.push(autocompleteDisposable); // Preserve the legacy command ID while using the packaged server client. @@ -114,35 +116,51 @@ function activate(context) { const configChangeDisposable = vscode.workspace.onDidChangeConfiguration(event => { if (event.affectsConfiguration('terraphimIt')) { serverConnection_1.serverConnection.updateConfiguration(); + if (event.affectsConfiguration('terraphimIt.serverUrl') || event.affectsConfiguration('terraphimIt.enableLocalServer')) { + try { + serverConnection_1.serverConnection.getServerUrl(); + } + catch (error) { + vscode.window.showWarningMessage(`Terraphim server configuration: ${error instanceof Error ? error.message : 'invalid server URL'}`); + return; + } + } vscode.window.showInformationMessage('Terraphim IT configuration updated'); } }); context.subscriptions.push(configChangeDisposable); } class TerraphimCompletionProvider { - constructor(store) { - this.store = store; - } async provideCompletionItems(document, position, token, context) { const linePrefix = document.lineAt(position).text.substr(0, position.character); if (!linePrefix.endsWith(' ')) { return []; } - const results = await get_all_resources(this.store); - return Object.entries(results.data).map(([key, value]) => { - const item = new vscode.CompletionItem(key, vscode.CompletionItemKind.Text); - item.detail = value.description; - item.documentation = new vscode.MarkdownString(`[${value.nterm}](${value.url})`); - return item; - }); + try { + // Check identity after loading too: settings may change during the request. + const store = (0, getStore_1.getStore)(); + const results = await get_all_resources(store); + if ((0, getStore_1.getStore)() !== store) + return []; + return Object.entries(results.data).map(([key, value]) => { + const item = new vscode.CompletionItem(key, vscode.CompletionItemKind.Text); + item.detail = value.description; + item.documentation = new vscode.MarkdownString(`[${value.nterm}](${value.url})`); + return item; + }); + } + catch (error) { + vscode.window.showWarningMessage(`Atomic autocomplete could not load suggestions: ${error instanceof Error ? error.message : 'check endpoint and agent settings'}`); + return []; + } } } class TerraphimServerCompletionProvider { constructor() { - this.lastQuery = ''; - this.lastResults = []; + this.cache = new completionCache_1.CompletionCache(); } async provideCompletionItems(document, position, token, context) { + const revision = serverConnection_1.serverConnection.getConfigurationRevision(); const wordRange = document.getWordRangeAtPosition(position) || (position.character > 0 ? document.getWordRangeAtPosition(position.translate(0, -1)) : undefined); if (!wordRange) { return []; @@ -151,43 +169,47 @@ class TerraphimServerCompletionProvider { if (word.length < 2) { return []; } - if (word !== this.lastQuery) { - this.lastQuery = word; - try { - // Try autocomplete endpoint first - const autocompleteResponse = await serverConnection_1.serverConnection.getAutocompleteSuggestions(word, 10); - if (autocompleteResponse.status === 'success' && autocompleteResponse.suggestions.length > 0) { - this.lastResults = autocompleteResponse.suggestions.map(suggestion => { - const item = new vscode.CompletionItem(suggestion.term, vscode.CompletionItemKind.Text); - item.sortText = suggestion.score.toString().padStart(8, '0'); + const { request, cached } = this.cache.begin(word, revision); + if (cached) + return cached; + let results = []; + try { + // Try autocomplete endpoint first + const autocompleteResponse = await serverConnection_1.serverConnection.getAutocompleteSuggestions(word, 10); + // Do not send the old query to a newly selected endpoint in the fallback. + if (!this.cache.isCurrent(request, serverConnection_1.serverConnection.getConfigurationRevision())) + return []; + if (autocompleteResponse.status === 'success' && autocompleteResponse.suggestions.length > 0) { + results = autocompleteResponse.suggestions.map(suggestion => { + const item = new vscode.CompletionItem(suggestion.term, vscode.CompletionItemKind.Text); + item.sortText = suggestion.score.toString().padStart(8, '0'); + return item; + }); + } + else { + // Fallback to search endpoint + const searchResponse = await serverConnection_1.serverConnection.searchDocuments(word, 10); + if (searchResponse.status === 'success' && searchResponse.results.length > 0) { + results = searchResponse.results.map(result => { + const item = new vscode.CompletionItem(result.title, vscode.CompletionItemKind.Text); + item.detail = result.description || result.body || ''; + item.documentation = new vscode.MarkdownString(`[${result.title}](${result.url})`); + if (result.rank) { + item.sortText = result.rank.toString().padStart(3, '0'); + } return item; }); } else { - // Fallback to search endpoint - const searchResponse = await serverConnection_1.serverConnection.searchDocuments(word, 10); - if (searchResponse.status === 'success' && searchResponse.results.length > 0) { - this.lastResults = searchResponse.results.map(result => { - const item = new vscode.CompletionItem(result.title, vscode.CompletionItemKind.Text); - item.detail = result.description || result.body || ''; - item.documentation = new vscode.MarkdownString(`[${result.title}](${result.url})`); - if (result.rank) { - item.sortText = result.rank.toString().padStart(3, '0'); - } - return item; - }); - } - else { - this.lastResults = []; - } + results = []; } } - catch (error) { - console.error('Server completion failed:', error); - this.lastResults = []; - } } - return this.lastResults; + catch (error) { + console.error('Server completion failed:', error); + results = []; + } + return this.cache.commit(request, serverConnection_1.serverConnection.getConfigurationRevision(), results); } } async function get_all_resources(store) { diff --git a/vs-code-terraphim-it/out/extension.js.map b/vs-code-terraphim-it/out/extension.js.map index 5188b9762..220dbede5 100644 --- a/vs-code-terraphim-it/out/extension.js.map +++ b/vs-code-terraphim-it/out/extension.js.map @@ -1 +1 @@ -{"version":3,"file":"extension.js","sourceRoot":"","sources":["../src/extension.ts"],"names":[],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"extension.js","sourceRoot":"","sources":["../src/extension.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/vs-code-terraphim-it/out/helpers/completionCache.js b/vs-code-terraphim-it/out/helpers/completionCache.js new file mode 100644 index 000000000..019aac95e --- /dev/null +++ b/vs-code-terraphim-it/out/helpers/completionCache.js @@ -0,0 +1,35 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.CompletionCache = void 0; +/** Cache results only for the latest query and configuration, even across awaits. */ +class CompletionCache { + constructor() { + this.generation = 0; + this.revision = -1; + this.query = ''; + this.results = []; + } + /** Start a distinct request, or reuse results for the same query/revision. */ + begin(query, revision) { + if (query === this.query && revision === this.revision) { + return { request: { generation: this.generation, revision }, cached: this.results }; + } + this.query = query; + this.revision = revision; + this.results = []; + return { request: { generation: ++this.generation, revision } }; + } + /** Check before a fallback request so old text is not sent to a new endpoint. */ + isCurrent(request, revision) { + return request.generation === this.generation && request.revision === revision && revision === this.revision; + } + /** Publish only the latest request's response; stale responses stay invisible. */ + commit(request, revision, results) { + if (!this.isCurrent(request, revision)) + return []; + this.results = results; + return results; + } +} +exports.CompletionCache = CompletionCache; +//# sourceMappingURL=completionCache.js.map \ No newline at end of file diff --git a/vs-code-terraphim-it/out/helpers/completionCache.js.map b/vs-code-terraphim-it/out/helpers/completionCache.js.map new file mode 100644 index 000000000..ff7e6cdfd --- /dev/null +++ b/vs-code-terraphim-it/out/helpers/completionCache.js.map @@ -0,0 +1 @@ +{"version":3,"file":"completionCache.js","sourceRoot":"","sources":["../../src/helpers/completionCache.ts"],"names":[],"mappings":";;;AAMA,qFAAqF;AACrF,MAAa,eAAe;IAA5B;QACU,eAAU,GAAG,CAAC,CAAC;QACf,aAAQ,GAAG,CAAC,CAAC,CAAC;QACd,UAAK,GAAG,EAAE,CAAC;QACX,YAAO,GAAQ,EAAE,CAAC;IAwB5B,CAAC;IAtBC,8EAA8E;IAC9E,KAAK,CAAC,KAAa,EAAE,QAAgB;QACnC,IAAI,KAAK,KAAK,IAAI,CAAC,KAAK,IAAI,QAAQ,KAAK,IAAI,CAAC,QAAQ,EAAE,CAAC;YACvD,OAAO,EAAE,OAAO,EAAE,EAAC,UAAU,EAAE,IAAI,CAAC,UAAU,EAAE,QAAQ,EAAC,EAAE,MAAM,EAAE,IAAI,CAAC,OAAO,EAAE,CAAC;QACpF,CAAC;QACD,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;QACnB,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;QACzB,IAAI,CAAC,OAAO,GAAG,EAAE,CAAC;QAClB,OAAO,EAAE,OAAO,EAAE,EAAC,UAAU,EAAE,EAAE,IAAI,CAAC,UAAU,EAAE,QAAQ,EAAC,EAAE,CAAC;IAChE,CAAC;IAED,iFAAiF;IACjF,SAAS,CAAC,OAA0B,EAAE,QAAgB;QACpD,OAAO,OAAO,CAAC,UAAU,KAAK,IAAI,CAAC,UAAU,IAAI,OAAO,CAAC,QAAQ,KAAK,QAAQ,IAAI,QAAQ,KAAK,IAAI,CAAC,QAAQ,CAAC;IAC/G,CAAC;IAED,kFAAkF;IAClF,MAAM,CAAC,OAA0B,EAAE,QAAgB,EAAE,OAAY;QAC/D,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,QAAQ,CAAC;YAAE,OAAO,EAAE,CAAC;QAClD,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;QACvB,OAAO,OAAO,CAAC;IACjB,CAAC;CACF;AA5BD,0CA4BC"} \ No newline at end of file diff --git a/vs-code-terraphim-it/out/helpers/getStore.js b/vs-code-terraphim-it/out/helpers/getStore.js index 890bb3c79..4a9c3dc61 100644 --- a/vs-code-terraphim-it/out/helpers/getStore.js +++ b/vs-code-terraphim-it/out/helpers/getStore.js @@ -5,24 +5,25 @@ exports.resetStore = resetStore; exports.getUpdatedStore = getUpdatedStore; // src/helpers/getStore.ts const lib_1 = require("@tomic/lib"); +const vscode = require("vscode"); const ontologies_1 = require("../ontologies"); -const serverConnection_1 = require("./serverConnection"); let store; +let storeServerUrl; +let storeAgent; function getStore(agent) { - if (!store) { - // Get the atomic server URL from configuration - const atomicServerUrl = serverConnection_1.serverConnection.getAtomicServerUrl(); - if (!agent) { - store = new lib_1.Store({ - serverUrl: atomicServerUrl, - }); - } - else { - store = new lib_1.Store({ - serverUrl: atomicServerUrl, - agent: lib_1.Agent.fromSecret(agent), - }); - } + const config = vscode.workspace.getConfiguration('terraphimIt'); + const atomicServerUrl = config.get('atomicServerUrl') || 'https://common.terraphim.io/drive/h6grD0ID'; + const selectedAgent = agent ?? config.get('agent') ?? ''; + if (!store || storeServerUrl !== atomicServerUrl || storeAgent !== selectedAgent) { + // Construct before replacing the cache: malformed credentials must not + // silently select an anonymous agent or retain a partially updated store. + const nextStore = new lib_1.Store({ + serverUrl: atomicServerUrl, + ...(selectedAgent ? { agent: lib_1.Agent.fromSecret(selectedAgent) } : {}), + }); + store = nextStore; + storeServerUrl = atomicServerUrl; + storeAgent = selectedAgent; (0, ontologies_1.initOntologies)(); console.log(`Initialized Atomic Store with server: ${atomicServerUrl}`); } @@ -33,15 +34,15 @@ function getStore(agent) { */ function resetStore() { store = undefined; + storeServerUrl = undefined; + storeAgent = undefined; console.log('Store instance reset'); } /** * Get store with updated configuration */ function getUpdatedStore(agent) { - // Update server connection configuration - serverConnection_1.serverConnection.updateConfiguration(); - // Reset and recreate store with new config + // Configuration is read when constructing the store. resetStore(); return getStore(agent); } diff --git a/vs-code-terraphim-it/out/helpers/getStore.js.map b/vs-code-terraphim-it/out/helpers/getStore.js.map index 5d45417dd..22f8ebc82 100644 --- a/vs-code-terraphim-it/out/helpers/getStore.js.map +++ b/vs-code-terraphim-it/out/helpers/getStore.js.map @@ -1 +1 @@ -{"version":3,"file":"getStore.js","sourceRoot":"","sources":["../../src/helpers/getStore.ts"],"names":[],"mappings":";;AAQA,4BAqBC;AAKD,gCAGC;AAKD,0CAMC;AAhDD,0BAA0B;AAC1B,oCAA0C;AAE1C,8CAA+C;AAC/C,yDAAsD;AAEtD,IAAI,KAAY,CAAC;AAEjB,SAAgB,QAAQ,CAAC,KAAc;IACrC,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,+CAA+C;QAC/C,MAAM,eAAe,GAAG,mCAAgB,CAAC,kBAAkB,EAAE,CAAC;QAE9D,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,KAAK,GAAG,IAAI,WAAK,CAAC;gBAChB,SAAS,EAAE,eAAe;aAC3B,CAAC,CAAC;QACL,CAAC;aAAM,CAAC;YACN,KAAK,GAAG,IAAI,WAAK,CAAC;gBAChB,SAAS,EAAE,eAAe;gBAC1B,KAAK,EAAE,WAAK,CAAC,UAAU,CAAC,KAAK,CAAC;aAC/B,CAAC,CAAC;QACL,CAAC;QAED,IAAA,2BAAc,GAAE,CAAC;QACjB,OAAO,CAAC,GAAG,CAAC,yCAAyC,eAAe,EAAE,CAAC,CAAC;IAC1E,CAAC;IAED,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;GAEG;AACH,SAAgB,UAAU;IACxB,KAAK,GAAG,SAAgB,CAAC;IACzB,OAAO,CAAC,GAAG,CAAC,sBAAsB,CAAC,CAAC;AACtC,CAAC;AAED;;GAEG;AACH,SAAgB,eAAe,CAAC,KAAc;IAC5C,yCAAyC;IACzC,mCAAgB,CAAC,mBAAmB,EAAE,CAAC;IACvC,2CAA2C;IAC3C,UAAU,EAAE,CAAC;IACb,OAAO,QAAQ,CAAC,KAAK,CAAC,CAAC;AACzB,CAAC"} \ No newline at end of file +{"version":3,"file":"getStore.js","sourceRoot":"","sources":["../../src/helpers/getStore.ts"],"names":[],"mappings":";;AAQA,4BAoBC;AAKD,gCAKC;AAKD,0CAIC;AA/CD,0BAA0B;AAC1B,oCAA0C;AAC1C,iCAAiC;AACjC,8CAA+C;AAC/C,IAAI,KAAwB,CAAC;AAC7B,IAAI,cAAkC,CAAC;AACvC,IAAI,UAA8B,CAAC;AAEnC,SAAgB,QAAQ,CAAC,KAAc;IACrC,MAAM,MAAM,GAAG,MAAM,CAAC,SAAS,CAAC,gBAAgB,CAAC,aAAa,CAAC,CAAC;IAChE,MAAM,eAAe,GAAG,MAAM,CAAC,GAAG,CAAS,iBAAiB,CAAC,IAAI,4CAA4C,CAAC;IAC9G,MAAM,aAAa,GAAG,KAAK,IAAI,MAAM,CAAC,GAAG,CAAS,OAAO,CAAC,IAAI,EAAE,CAAC;IACjE,IAAI,CAAC,KAAK,IAAI,cAAc,KAAK,eAAe,IAAI,UAAU,KAAK,aAAa,EAAE,CAAC;QACjF,uEAAuE;QACvE,0EAA0E;QAC1E,MAAM,SAAS,GAAG,IAAI,WAAK,CAAC;YAC1B,SAAS,EAAE,eAAe;YAC1B,GAAG,CAAC,aAAa,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,WAAK,CAAC,UAAU,CAAC,aAAa,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SACrE,CAAC,CAAC;QACH,KAAK,GAAG,SAAS,CAAC;QAClB,cAAc,GAAG,eAAe,CAAC;QACjC,UAAU,GAAG,aAAa,CAAC;QAE3B,IAAA,2BAAc,GAAE,CAAC;QACjB,OAAO,CAAC,GAAG,CAAC,yCAAyC,eAAe,EAAE,CAAC,CAAC;IAC1E,CAAC;IAED,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;GAEG;AACH,SAAgB,UAAU;IACxB,KAAK,GAAG,SAAS,CAAC;IAClB,cAAc,GAAG,SAAS,CAAC;IAC3B,UAAU,GAAG,SAAS,CAAC;IACvB,OAAO,CAAC,GAAG,CAAC,sBAAsB,CAAC,CAAC;AACtC,CAAC;AAED;;GAEG;AACH,SAAgB,eAAe,CAAC,KAAc;IAC5C,qDAAqD;IACrD,UAAU,EAAE,CAAC;IACb,OAAO,QAAQ,CAAC,KAAK,CAAC,CAAC;AACzB,CAAC"} \ No newline at end of file diff --git a/vs-code-terraphim-it/out/helpers/serverConnection.js b/vs-code-terraphim-it/out/helpers/serverConnection.js index cd08aa4e2..628598e60 100644 --- a/vs-code-terraphim-it/out/helpers/serverConnection.js +++ b/vs-code-terraphim-it/out/helpers/serverConnection.js @@ -5,6 +5,7 @@ exports.serverConnection = exports.TerraphimServerConnection = void 0; const vscode = require("vscode"); class TerraphimServerConnection { constructor() { + this.configurationRevision = 0; this.config = this.loadConfiguration(); } loadConfiguration() { @@ -17,10 +18,28 @@ class TerraphimServerConnection { }; } updateConfiguration() { - this.config = this.loadConfiguration(); + const next = this.loadConfiguration(); + if (JSON.stringify(next) !== JSON.stringify(this.config)) { + this.config = next; + this.configurationRevision += 1; + } + } + getConfigurationRevision() { + return this.configurationRevision; } getServerUrl() { - return this.config.serverUrl; + const url = new URL(this.config.serverUrl); + if (!['http:', 'https:'].includes(url.protocol)) { + throw new Error('Set terraphimIt.serverUrl to an HTTP or HTTPS Terraphim server.'); + } + const hostname = url.hostname.toLowerCase(); + const loopback = hostname === 'localhost' || hostname.endsWith('.localhost') || + hostname.startsWith('127.') || ['0.0.0.0', '[::]', '[::1]'].includes(hostname) || + /^\[::ffff:(?:7f[0-9a-f]{2}:|0:0\])/.test(hostname); + if (!this.config.enableLocalServer && loopback) { + throw new Error('Local Terraphim server is disabled. Set terraphimIt.serverUrl to your remote server or enable terraphimIt.enableLocalServer.'); + } + return url.href.replace(/\/$/, ''); } getAtomicServerUrl() { return this.config.atomicServerUrl; @@ -35,11 +54,12 @@ class TerraphimServerConnection { * Check if the Terraphim server is healthy */ async healthCheck() { + let timeoutId; try { - const healthUrl = `${this.config.serverUrl}/health`; + const healthUrl = `${this.getServerUrl()}/health`; console.log(`Checking server health at: ${healthUrl}`); const controller = new AbortController(); - const timeoutId = setTimeout(() => controller.abort(), 5000); // 5 second timeout + timeoutId = setTimeout(() => controller.abort(), 5000); // 5 second timeout const response = await fetch(healthUrl, { method: 'GET', signal: controller.signal, @@ -48,7 +68,6 @@ class TerraphimServerConnection { 'Content-Type': 'application/json' } }); - clearTimeout(timeoutId); if (response.ok) { const healthData = await response.text(); return { @@ -83,13 +102,16 @@ class TerraphimServerConnection { message: message }; } + finally { + clearTimeout(timeoutId); + } } /** * Search documents using the Terraphim server */ async searchDocuments(query, limit = 10) { try { - const searchUrl = `${this.config.serverUrl}/documents/search`; + const searchUrl = `${this.getServerUrl()}/documents/search`; const searchRequest = { search_term: query, skip: 0, @@ -99,6 +121,7 @@ class TerraphimServerConnection { console.log(`Searching documents at: ${searchUrl}`, searchRequest); const response = await fetch(searchUrl, { method: 'POST', + signal: AbortSignal.timeout(5000), headers: { 'Accept': 'application/json', 'Content-Type': 'application/json' @@ -125,10 +148,11 @@ class TerraphimServerConnection { */ async getAutocompleteSuggestions(query, limit = 10) { try { - const autocompleteUrl = `${this.config.serverUrl}/autocomplete/${encodeURIComponent(this.config.selectedRole)}/${encodeURIComponent(query)}`; + const autocompleteUrl = `${this.getServerUrl()}/autocomplete/${encodeURIComponent(this.config.selectedRole)}/${encodeURIComponent(query)}`; console.log(`Getting autocomplete suggestions at: ${autocompleteUrl}`); const response = await fetch(autocompleteUrl, { method: 'GET', + signal: AbortSignal.timeout(5000), headers: { 'Accept': 'application/json', 'Content-Type': 'application/json' diff --git a/vs-code-terraphim-it/out/helpers/serverConnection.js.map b/vs-code-terraphim-it/out/helpers/serverConnection.js.map index 15ff0016b..1e0a1e11d 100644 --- a/vs-code-terraphim-it/out/helpers/serverConnection.js.map +++ b/vs-code-terraphim-it/out/helpers/serverConnection.js.map @@ -1 +1 @@ -{"version":3,"file":"serverConnection.js","sourceRoot":"","sources":["../../src/helpers/serverConnection.ts"],"names":[],"mappings":";;;AAAA,kCAAkC;AAClC,iCAAiC;AAqCjC,MAAa,yBAAyB;IAGpC;QACE,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,iBAAiB,EAAE,CAAC;IACzC,CAAC;IAEO,iBAAiB;QACvB,MAAM,MAAM,GAAG,MAAM,CAAC,SAAS,CAAC,gBAAgB,CAAC,aAAa,CAAC,CAAC;QAEhE,OAAO;YACL,SAAS,EAAE,MAAM,CAAC,GAAG,CAAS,WAAW,CAAC,IAAI,uBAAuB;YACrE,eAAe,EAAE,MAAM,CAAC,GAAG,CAAS,iBAAiB,CAAC,IAAI,4CAA4C;YACtG,iBAAiB,EAAE,MAAM,CAAC,GAAG,CAAU,mBAAmB,CAAC,KAAK,KAAK,EAAE,eAAe;YACtF,YAAY,EAAE,MAAM,CAAC,GAAG,CAAS,cAAc,CAAC,IAAI,oBAAoB;SACzE,CAAC;IACJ,CAAC;IAEM,mBAAmB;QACxB,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,iBAAiB,EAAE,CAAC;IACzC,CAAC;IAEM,YAAY;QACjB,OAAO,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC;IAC/B,CAAC;IAEM,kBAAkB;QACvB,OAAO,IAAI,CAAC,MAAM,CAAC,eAAe,CAAC;IACrC,CAAC;IAEM,eAAe;QACpB,OAAO,IAAI,CAAC,MAAM,CAAC,YAAY,CAAC;IAClC,CAAC;IAEM,oBAAoB;QACzB,OAAO,IAAI,CAAC,MAAM,CAAC,iBAAiB,CAAC;IACvC,CAAC;IAED;;OAEG;IACI,KAAK,CAAC,WAAW;QACtB,IAAI,CAAC;YACH,MAAM,SAAS,GAAG,GAAG,IAAI,CAAC,MAAM,CAAC,SAAS,SAAS,CAAC;YACpD,OAAO,CAAC,GAAG,CAAC,8BAA8B,SAAS,EAAE,CAAC,CAAC;YAEvD,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAC;YACzC,MAAM,SAAS,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,KAAK,EAAE,EAAE,IAAI,CAAC,CAAC,CAAC,mBAAmB;YAEjF,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,SAAS,EAAE;gBACtC,MAAM,EAAE,KAAK;gBACb,MAAM,EAAE,UAAU,CAAC,MAAM;gBACzB,OAAO,EAAE;oBACP,QAAQ,EAAE,kBAAkB;oBAC5B,cAAc,EAAE,kBAAkB;iBACnC;aACF,CAAC,CAAC;YAEH,YAAY,CAAC,SAAS,CAAC,CAAC;YAExB,IAAI,QAAQ,CAAC,EAAE,EAAE,CAAC;gBAChB,MAAM,UAAU,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;gBACzC,OAAO;oBACL,OAAO,EAAE,IAAI;oBACb,OAAO,EAAE,sBAAsB,UAAU,EAAE;oBAC3C,OAAO,EAAE,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,qBAAqB,CAAC,IAAI,SAAS;iBAClE,CAAC;YACJ,CAAC;iBAAM,CAAC;gBACN,OAAO;oBACL,OAAO,EAAE,KAAK;oBACd,OAAO,EAAE,iCAAiC,QAAQ,CAAC,MAAM,IAAI,QAAQ,CAAC,UAAU,EAAE;iBACnF,CAAC;YACJ,CAAC;QACH,CAAC;QAAC,OAAO,KAAU,EAAE,CAAC;YACpB,IAAI,OAAO,GAAG,wBAAwB,CAAC;YAEvC,IAAI,KAAK,CAAC,IAAI,KAAK,YAAY,EAAE,CAAC;gBAChC,OAAO,GAAG,wCAAwC,CAAC;YACrD,CAAC;iBAAM,IAAI,KAAK,CAAC,IAAI,KAAK,cAAc,EAAE,CAAC;gBACzC,OAAO,GAAG,gDAAgD,CAAC;YAC7D,CAAC;iBAAM,IAAI,KAAK,YAAY,SAAS,IAAI,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;gBACzE,OAAO,GAAG,qCAAqC,CAAC;YAClD,CAAC;iBAAM,CAAC;gBACN,OAAO,GAAG,wBAAwB,KAAK,CAAC,OAAO,EAAE,CAAC;YACpD,CAAC;YAED,OAAO;gBACL,OAAO,EAAE,KAAK;gBACd,OAAO,EAAE,OAAO;aACjB,CAAC;QACJ,CAAC;IACH,CAAC;IAED;;OAEG;IACI,KAAK,CAAC,eAAe,CAAC,KAAa,EAAE,QAAgB,EAAE;QAC5D,IAAI,CAAC;YACH,MAAM,SAAS,GAAG,GAAG,IAAI,CAAC,MAAM,CAAC,SAAS,mBAAmB,CAAC;YAC9D,MAAM,aAAa,GAAkB;gBACnC,WAAW,EAAE,KAAK;gBAClB,IAAI,EAAE,CAAC;gBACP,KAAK,EAAE,KAAK;gBACZ,IAAI,EAAE,IAAI,CAAC,MAAM,CAAC,YAAY;aAC/B,CAAC;YAEF,OAAO,CAAC,GAAG,CAAC,2BAA2B,SAAS,EAAE,EAAE,aAAa,CAAC,CAAC;YAEnE,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,SAAS,EAAE;gBACtC,MAAM,EAAE,MAAM;gBACd,OAAO,EAAE;oBACP,QAAQ,EAAE,kBAAkB;oBAC5B,cAAc,EAAE,kBAAkB;iBACnC;gBACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,aAAa,CAAC;aACpC,CAAC,CAAC;YAEH,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;gBACjB,MAAM,IAAI,KAAK,CAAC,0BAA0B,QAAQ,CAAC,MAAM,IAAI,QAAQ,CAAC,UAAU,EAAE,CAAC,CAAC;YACtF,CAAC;YAED,MAAM,cAAc,GAAmB,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;YAC7D,OAAO,cAAc,CAAC;QACxB,CAAC;QAAC,OAAO,KAAU,EAAE,CAAC;YACpB,OAAO,CAAC,KAAK,CAAC,yBAAyB,EAAE,KAAK,CAAC,CAAC;YAChD,gCAAgC;YAChC,OAAO;gBACL,MAAM,EAAE,OAAO;gBACf,OAAO,EAAE,EAAE;aACZ,CAAC;QACJ,CAAC;IACH,CAAC;IAED;;OAEG;IACI,KAAK,CAAC,0BAA0B,CAAC,KAAa,EAAE,QAAgB,EAAE;QACvE,IAAI,CAAC;YACH,MAAM,eAAe,GAAG,GAAG,IAAI,CAAC,MAAM,CAAC,SAAS,iBAAiB,kBAAkB,CAAC,IAAI,CAAC,MAAM,CAAC,YAAY,CAAC,IAAI,kBAAkB,CAAC,KAAK,CAAC,EAAE,CAAC;YAE7I,OAAO,CAAC,GAAG,CAAC,wCAAwC,eAAe,EAAE,CAAC,CAAC;YAEvE,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,eAAe,EAAE;gBAC5C,MAAM,EAAE,KAAK;gBACb,OAAO,EAAE;oBACP,QAAQ,EAAE,kBAAkB;oBAC5B,cAAc,EAAE,kBAAkB;iBACnC;aACF,CAAC,CAAC;YAEH,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;gBACjB,MAAM,IAAI,KAAK,CAAC,gCAAgC,QAAQ,CAAC,MAAM,IAAI,QAAQ,CAAC,UAAU,EAAE,CAAC,CAAC;YAC5F,CAAC;YAED,MAAM,oBAAoB,GAAyB,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;YACzE,OAAO,oBAAoB,CAAC;QAC9B,CAAC;QAAC,OAAO,KAAU,EAAE,CAAC;YACpB,OAAO,CAAC,KAAK,CAAC,qBAAqB,EAAE,KAAK,CAAC,CAAC;YAC5C,oCAAoC;YACpC,OAAO;gBACL,MAAM,EAAE,OAAO;gBACf,WAAW,EAAE,EAAE;aAChB,CAAC;QACJ,CAAC;IACH,CAAC;IAED;;OAEG;IACI,KAAK,CAAC,cAAc;QAIzB,MAAM,eAAe,GAAG,MAAM,IAAI,CAAC,WAAW,EAAE,CAAC;QAEjD,mCAAmC;QACnC,IAAI,YAAY,GAAG,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,sBAAsB,EAAE,CAAC;QACvE,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,eAAe,EAAE;gBACxD,MAAM,EAAE,MAAM;gBACd,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,IAAI,CAAC;aAClC,CAAC,CAAC;YACH,YAAY,GAAG;gBACb,OAAO,EAAE,QAAQ,CAAC,EAAE;gBACpB,OAAO,EAAE,QAAQ,CAAC,EAAE,CAAC,CAAC,CAAC,6BAA6B,CAAC,CAAC,CAAC,2BAA2B,QAAQ,CAAC,MAAM,EAAE;aACpG,CAAC;QACJ,CAAC;QAAC,OAAO,KAAU,EAAE,CAAC;YACpB,YAAY,GAAG;gBACb,OAAO,EAAE,KAAK;gBACd,OAAO,EAAE,+BAA+B,KAAK,CAAC,OAAO,EAAE;aACxD,CAAC;QACJ,CAAC;QAED,OAAO;YACL,SAAS,EAAE,eAAe;YAC1B,MAAM,EAAE,YAAY;SACrB,CAAC;IACJ,CAAC;CACF;AAtMD,8DAsMC;AAED,8BAA8B;AACjB,QAAA,gBAAgB,GAAG,IAAI,yBAAyB,EAAE,CAAC"} \ No newline at end of file +{"version":3,"file":"serverConnection.js","sourceRoot":"","sources":["../../src/helpers/serverConnection.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/vs-code-terraphim-it/package-lock.json b/vs-code-terraphim-it/package-lock.json index 0dca61e7d..7f71d88f6 100644 --- a/vs-code-terraphim-it/package-lock.json +++ b/vs-code-terraphim-it/package-lock.json @@ -1,12 +1,12 @@ { "name": "terraphim-it", - "version": "0.1.2", + "version": "0.1.3", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "terraphim-it", - "version": "0.1.2", + "version": "0.1.3", "license": "Apache-2.0", "dependencies": { "@tomic/cli": "0.40.0", diff --git a/vs-code-terraphim-it/package.json b/vs-code-terraphim-it/package.json index c6faa7ec0..c5d032286 100644 --- a/vs-code-terraphim-it/package.json +++ b/vs-code-terraphim-it/package.json @@ -2,7 +2,7 @@ "name": "terraphim-it", "displayName": "Terraphim It", "description": "Intelligent Markdown editor with alternatives, knowledge-graph synonyms and role-based suggestions", - "version": "0.1.2", + "version": "0.1.3", "publisher": "applied-knowledge-systems", "private": true, "license": "Apache-2.0", @@ -79,7 +79,7 @@ "terraphimIt.enableLocalServer": { "type": "boolean", "default": true, - "description": "Use local Terraphim server instead of remote servers" + "description": "Allow localhost and loopback server URLs. When disabled, set serverUrl to your remote Terraphim server; there is no automatic remote fallback." }, "terraphimIt.selectedRole": { "type": "string", @@ -108,7 +108,7 @@ "watch": "npx tsc -watch -p ./", "update-ontologies": "npx ad-generate ontologies", "build-rust": "python3 scripts/legacy_assets.py --build", - "test:host": "node --test tests/hostProtocol.test.cjs", + "test:host": "node --test tests/hostProtocol.test.cjs tests/completionCache.test.cjs", "test:assets": "python3 -m unittest discover -s tests -p \"*_test.py\"", "test:export": "node --test tests/knowledgeGraphExport.test.cjs tests/exportIntent.test.cjs tests/exportTarget.test.cjs", "editor:fetch": "python3 scripts/released_editor.py", diff --git a/vs-code-terraphim-it/src/extension.ts b/vs-code-terraphim-it/src/extension.ts index 24459d738..2d6b166b6 100644 --- a/vs-code-terraphim-it/src/extension.ts +++ b/vs-code-terraphim-it/src/extension.ts @@ -4,6 +4,7 @@ import { CollectionBuilder, core, Store } from '@tomic/lib'; import { getStore } from './helpers/getStore'; import { serverConnection } from './helpers/serverConnection'; import { replaceLinks } from './helpers/linkReplacement'; +import { CompletionCache } from './helpers/completionCache'; import { airportOntology, type SystemOperatorAnalyticalLens, @@ -23,8 +24,6 @@ interface EngineeringData { export function activate(context: vscode.ExtensionContext) { registerAlternativeControl(context); - let agent: string | undefined; - let store: Store | undefined; let activeProvider: vscode.Disposable | undefined; const disposable = vscode.commands.registerCommand( @@ -41,23 +40,21 @@ export function activate(context: vscode.ExtensionContext) { // Get the configuration const config = vscode.workspace.getConfiguration('terraphimIt'); - // Only ask for agent if it's not set and hasn't been asked before + let agent = config.get('agent'); + // Read current settings on every command, including changes since activation. if (!agent) { - agent = config.get('agent'); - if (!agent) { - agent = await vscode.window.showInputBox({ - prompt: 'Enter the agent to use for Terraphim IT (optional)', - placeHolder: 'Agent String' - }); + agent = await vscode.window.showInputBox({ + prompt: 'Enter the agent to use for Terraphim IT (optional)', + placeHolder: 'Agent String' + }); - // Save the agent to configuration if provided - if (agent) { - await config.update('agent', agent, vscode.ConfigurationTarget.Global); - } + // Save the agent to configuration if provided + if (agent) { + await config.update('agent', agent, vscode.ConfigurationTarget.Global); } } try { - store = getStore(agent); + const store = getStore(agent); const results = await get_all_resources(store); const replacedText = await replaceLinks(text, JSON.stringify(results)); if (document.isClosed || document.version !== version || document.getText() !== text) { @@ -83,8 +80,11 @@ export function activate(context: vscode.ExtensionContext) { const autocompleteDisposable = vscode.commands.registerCommand( 'extension.terraphimAIAutocomplete', async function () { - if (!store) { - store = getStore(agent); + try { + getStore(); // Validate current credentials before claiming activation. + } catch (error) { + vscode.window.showErrorMessage(`Cannot enable Atomic autocomplete: ${error instanceof Error ? error.message : 'invalid configuration'}`); + return false; } // Deactivate the existing provider if any if (activeProvider) { @@ -94,12 +94,13 @@ export function activate(context: vscode.ExtensionContext) { // Register the completion provider const provider = vscode.languages.registerCompletionItemProvider( { scheme: 'file', language: '*' }, - new TerraphimCompletionProvider(store), + new TerraphimCompletionProvider(), ' ' // Trigger on space ); activeProvider = provider; context.subscriptions.push(provider); vscode.window.showInformationMessage('Terraphim AI Autocomplete activated'); + return true; } ); @@ -158,6 +159,14 @@ export function activate(context: vscode.ExtensionContext) { const configChangeDisposable = vscode.workspace.onDidChangeConfiguration(event => { if (event.affectsConfiguration('terraphimIt')) { serverConnection.updateConfiguration(); + if (event.affectsConfiguration('terraphimIt.serverUrl') || event.affectsConfiguration('terraphimIt.enableLocalServer')) { + try { + serverConnection.getServerUrl(); + } catch (error) { + vscode.window.showWarningMessage(`Terraphim server configuration: ${error instanceof Error ? error.message : 'invalid server URL'}`); + return; + } + } vscode.window.showInformationMessage('Terraphim IT configuration updated'); } }); @@ -167,11 +176,6 @@ export function activate(context: vscode.ExtensionContext) { } class TerraphimCompletionProvider implements vscode.CompletionItemProvider { - private store: Store; - - constructor(store: Store) { - this.store = store; - } async provideCompletionItems( document: vscode.TextDocument, @@ -184,19 +188,26 @@ class TerraphimCompletionProvider implements vscode.CompletionItemProvider { return []; } - const results = await get_all_resources(this.store); - return Object.entries(results.data).map(([key, value]) => { - const item = new vscode.CompletionItem(key, vscode.CompletionItemKind.Text); - item.detail = value.description; - item.documentation = new vscode.MarkdownString(`[${value.nterm}](${value.url})`); - return item; - }); + try { + // Check identity after loading too: settings may change during the request. + const store = getStore(); + const results = await get_all_resources(store); + if (getStore() !== store) return []; + return Object.entries(results.data).map(([key, value]) => { + const item = new vscode.CompletionItem(key, vscode.CompletionItemKind.Text); + item.detail = value.description; + item.documentation = new vscode.MarkdownString(`[${value.nterm}](${value.url})`); + return item; + }); + } catch (error) { + vscode.window.showWarningMessage(`Atomic autocomplete could not load suggestions: ${error instanceof Error ? error.message : 'check endpoint and agent settings'}`); + return []; + } } } class TerraphimServerCompletionProvider implements vscode.CompletionItemProvider { - private lastQuery: string = ''; - private lastResults: vscode.CompletionItem[] = []; + private cache = new CompletionCache(); async provideCompletionItems( document: vscode.TextDocument, @@ -204,6 +215,7 @@ class TerraphimServerCompletionProvider implements vscode.CompletionItemProvider token: vscode.CancellationToken, context: vscode.CompletionContext ): Promise { + const revision = serverConnection.getConfigurationRevision(); const wordRange = document.getWordRangeAtPosition(position) || (position.character > 0 ? document.getWordRangeAtPosition(position.translate(0, -1)) : undefined); if (!wordRange) { return []; @@ -214,42 +226,43 @@ class TerraphimServerCompletionProvider implements vscode.CompletionItemProvider return []; } - if (word !== this.lastQuery) { - this.lastQuery = word; - - try { - // Try autocomplete endpoint first - const autocompleteResponse = await serverConnection.getAutocompleteSuggestions(word, 10); - if (autocompleteResponse.status === 'success' && autocompleteResponse.suggestions.length > 0) { - this.lastResults = autocompleteResponse.suggestions.map(suggestion => { - const item = new vscode.CompletionItem(suggestion.term, vscode.CompletionItemKind.Text); - item.sortText = suggestion.score.toString().padStart(8, '0'); + const {request, cached} = this.cache.begin(word, revision); + if (cached) return cached; + let results: vscode.CompletionItem[] = []; + + try { + // Try autocomplete endpoint first + const autocompleteResponse = await serverConnection.getAutocompleteSuggestions(word, 10); + // Do not send the old query to a newly selected endpoint in the fallback. + if (!this.cache.isCurrent(request, serverConnection.getConfigurationRevision())) return []; + if (autocompleteResponse.status === 'success' && autocompleteResponse.suggestions.length > 0) { + results = autocompleteResponse.suggestions.map(suggestion => { + const item = new vscode.CompletionItem(suggestion.term, vscode.CompletionItemKind.Text); + item.sortText = suggestion.score.toString().padStart(8, '0'); + return item; + }); + } else { + // Fallback to search endpoint + const searchResponse = await serverConnection.searchDocuments(word, 10); + if (searchResponse.status === 'success' && searchResponse.results.length > 0) { + results = searchResponse.results.map(result => { + const item = new vscode.CompletionItem(result.title, vscode.CompletionItemKind.Text); + item.detail = result.description || result.body || ''; + item.documentation = new vscode.MarkdownString(`[${result.title}](${result.url})`); + if (result.rank) { + item.sortText = result.rank.toString().padStart(3, '0'); + } return item; }); } else { - // Fallback to search endpoint - const searchResponse = await serverConnection.searchDocuments(word, 10); - if (searchResponse.status === 'success' && searchResponse.results.length > 0) { - this.lastResults = searchResponse.results.map(result => { - const item = new vscode.CompletionItem(result.title, vscode.CompletionItemKind.Text); - item.detail = result.description || result.body || ''; - item.documentation = new vscode.MarkdownString(`[${result.title}](${result.url})`); - if (result.rank) { - item.sortText = result.rank.toString().padStart(3, '0'); - } - return item; - }); - } else { - this.lastResults = []; - } + results = []; } - } catch (error) { - console.error('Server completion failed:', error); - this.lastResults = []; } + } catch (error) { + console.error('Server completion failed:', error); + results = []; } - - return this.lastResults; + return this.cache.commit(request, serverConnection.getConfigurationRevision(), results); } } diff --git a/vs-code-terraphim-it/src/helpers/completionCache.ts b/vs-code-terraphim-it/src/helpers/completionCache.ts new file mode 100644 index 000000000..e3639e831 --- /dev/null +++ b/vs-code-terraphim-it/src/helpers/completionCache.ts @@ -0,0 +1,36 @@ +/** Identity of a request whose response may populate the completion cache. */ +export interface CompletionRequest { + generation: number; + revision: number; +} + +/** Cache results only for the latest query and configuration, even across awaits. */ +export class CompletionCache { + private generation = 0; + private revision = -1; + private query = ''; + private results: T[] = []; + + /** Start a distinct request, or reuse results for the same query/revision. */ + begin(query: string, revision: number): { request: CompletionRequest; cached?: T[] } { + if (query === this.query && revision === this.revision) { + return { request: {generation: this.generation, revision}, cached: this.results }; + } + this.query = query; + this.revision = revision; + this.results = []; + return { request: {generation: ++this.generation, revision} }; + } + + /** Check before a fallback request so old text is not sent to a new endpoint. */ + isCurrent(request: CompletionRequest, revision: number): boolean { + return request.generation === this.generation && request.revision === revision && revision === this.revision; + } + + /** Publish only the latest request's response; stale responses stay invisible. */ + commit(request: CompletionRequest, revision: number, results: T[]): T[] { + if (!this.isCurrent(request, revision)) return []; + this.results = results; + return results; + } +} diff --git a/vs-code-terraphim-it/src/helpers/getStore.ts b/vs-code-terraphim-it/src/helpers/getStore.ts index cbefd4eff..cb8219357 100644 --- a/vs-code-terraphim-it/src/helpers/getStore.ts +++ b/vs-code-terraphim-it/src/helpers/getStore.ts @@ -2,25 +2,24 @@ import { Store, Agent } from '@tomic/lib'; import * as vscode from 'vscode'; import { initOntologies } from '../ontologies'; -import { serverConnection } from './serverConnection'; - -let store: Store; +let store: Store | undefined; +let storeServerUrl: string | undefined; +let storeAgent: string | undefined; export function getStore(agent?: string): Store { - if (!store) { - // Get the atomic server URL from configuration - const atomicServerUrl = serverConnection.getAtomicServerUrl(); - - if (!agent) { - store = new Store({ - serverUrl: atomicServerUrl, - }); - } else { - store = new Store({ - serverUrl: atomicServerUrl, - agent: Agent.fromSecret(agent), - }); - } + const config = vscode.workspace.getConfiguration('terraphimIt'); + const atomicServerUrl = config.get('atomicServerUrl') || 'https://common.terraphim.io/drive/h6grD0ID'; + const selectedAgent = agent ?? config.get('agent') ?? ''; + if (!store || storeServerUrl !== atomicServerUrl || storeAgent !== selectedAgent) { + // Construct before replacing the cache: malformed credentials must not + // silently select an anonymous agent or retain a partially updated store. + const nextStore = new Store({ + serverUrl: atomicServerUrl, + ...(selectedAgent ? { agent: Agent.fromSecret(selectedAgent) } : {}), + }); + store = nextStore; + storeServerUrl = atomicServerUrl; + storeAgent = selectedAgent; initOntologies(); console.log(`Initialized Atomic Store with server: ${atomicServerUrl}`); @@ -33,7 +32,9 @@ export function getStore(agent?: string): Store { * Reset the store instance - useful when configuration changes */ export function resetStore(): void { - store = undefined as any; + store = undefined; + storeServerUrl = undefined; + storeAgent = undefined; console.log('Store instance reset'); } @@ -41,9 +42,7 @@ export function resetStore(): void { * Get store with updated configuration */ export function getUpdatedStore(agent?: string): Store { - // Update server connection configuration - serverConnection.updateConfiguration(); - // Reset and recreate store with new config + // Configuration is read when constructing the store. resetStore(); return getStore(agent); } diff --git a/vs-code-terraphim-it/src/helpers/serverConnection.ts b/vs-code-terraphim-it/src/helpers/serverConnection.ts index c6533e094..eeb71cd97 100644 --- a/vs-code-terraphim-it/src/helpers/serverConnection.ts +++ b/vs-code-terraphim-it/src/helpers/serverConnection.ts @@ -38,6 +38,7 @@ export interface AutocompleteResponse { export class TerraphimServerConnection { private config: TerraphimServerConfig; + private configurationRevision = 0; constructor() { this.config = this.loadConfiguration(); @@ -55,11 +56,30 @@ export class TerraphimServerConnection { } public updateConfiguration(): void { - this.config = this.loadConfiguration(); + const next = this.loadConfiguration(); + if (JSON.stringify(next) !== JSON.stringify(this.config)) { + this.config = next; + this.configurationRevision += 1; + } + } + + public getConfigurationRevision(): number { + return this.configurationRevision; } public getServerUrl(): string { - return this.config.serverUrl; + const url = new URL(this.config.serverUrl); + if (!['http:', 'https:'].includes(url.protocol)) { + throw new Error('Set terraphimIt.serverUrl to an HTTP or HTTPS Terraphim server.'); + } + const hostname = url.hostname.toLowerCase(); + const loopback = hostname === 'localhost' || hostname.endsWith('.localhost') || + hostname.startsWith('127.') || ['0.0.0.0', '[::]', '[::1]'].includes(hostname) || + /^\[::ffff:(?:7f[0-9a-f]{2}:|0:0\])/.test(hostname); + if (!this.config.enableLocalServer && loopback) { + throw new Error('Local Terraphim server is disabled. Set terraphimIt.serverUrl to your remote server or enable terraphimIt.enableLocalServer.'); + } + return url.href.replace(/\/$/, ''); } public getAtomicServerUrl(): string { @@ -78,12 +98,13 @@ export class TerraphimServerConnection { * Check if the Terraphim server is healthy */ public async healthCheck(): Promise<{ healthy: boolean; message: string; version?: string }> { + let timeoutId: ReturnType | undefined; try { - const healthUrl = `${this.config.serverUrl}/health`; + const healthUrl = `${this.getServerUrl()}/health`; console.log(`Checking server health at: ${healthUrl}`); const controller = new AbortController(); - const timeoutId = setTimeout(() => controller.abort(), 5000); // 5 second timeout + timeoutId = setTimeout(() => controller.abort(), 5000); // 5 second timeout const response = await fetch(healthUrl, { method: 'GET', @@ -94,8 +115,6 @@ export class TerraphimServerConnection { } }); - clearTimeout(timeoutId); - if (response.ok) { const healthData = await response.text(); return { @@ -126,6 +145,8 @@ export class TerraphimServerConnection { healthy: false, message: message }; + } finally { + clearTimeout(timeoutId); } } @@ -134,7 +155,7 @@ export class TerraphimServerConnection { */ public async searchDocuments(query: string, limit: number = 10): Promise { try { - const searchUrl = `${this.config.serverUrl}/documents/search`; + const searchUrl = `${this.getServerUrl()}/documents/search`; const searchRequest: SearchRequest = { search_term: query, skip: 0, @@ -146,6 +167,7 @@ export class TerraphimServerConnection { const response = await fetch(searchUrl, { method: 'POST', + signal: AbortSignal.timeout(5000), headers: { 'Accept': 'application/json', 'Content-Type': 'application/json' @@ -174,12 +196,13 @@ export class TerraphimServerConnection { */ public async getAutocompleteSuggestions(query: string, limit: number = 10): Promise { try { - const autocompleteUrl = `${this.config.serverUrl}/autocomplete/${encodeURIComponent(this.config.selectedRole)}/${encodeURIComponent(query)}`; + const autocompleteUrl = `${this.getServerUrl()}/autocomplete/${encodeURIComponent(this.config.selectedRole)}/${encodeURIComponent(query)}`; console.log(`Getting autocomplete suggestions at: ${autocompleteUrl}`); const response = await fetch(autocompleteUrl, { method: 'GET', + signal: AbortSignal.timeout(5000), headers: { 'Accept': 'application/json', 'Content-Type': 'application/json' diff --git a/vs-code-terraphim-it/tests/completionCache.test.cjs b/vs-code-terraphim-it/tests/completionCache.test.cjs new file mode 100644 index 000000000..29333c145 --- /dev/null +++ b/vs-code-terraphim-it/tests/completionCache.test.cjs @@ -0,0 +1,41 @@ +const {test} = require('node:test'); +const assert = require('node:assert/strict'); +const {CompletionCache} = require('../out/helpers/completionCache.js'); + +test('late old-role response cannot replace results from the new role', () => { + const cache = new CompletionCache(); + const old = cache.begin('Risk', 1).request; + const current = cache.begin('Risk', 2).request; + assert.deepEqual(cache.commit(current, 2, ['new role']), ['new role']); + assert.equal(cache.isCurrent(old, 2), false); + assert.deepEqual(cache.commit(old, 2, ['old role']), []); + assert.deepEqual(cache.begin('Risk', 2).cached, ['new role']); +}); + +test('query A then B then A rejects the original A response', () => { + const cache = new CompletionCache(); + const firstA = cache.begin('Risk', 1).request; + const b = cache.begin('Decision', 1).request; + const latestA = cache.begin('Risk', 1).request; + assert.deepEqual(cache.commit(latestA, 1, ['latest risk']), ['latest risk']); + assert.deepEqual(cache.commit(b, 1, ['decision']), []); + assert.deepEqual(cache.commit(firstA, 1, ['stale risk']), []); + assert.deepEqual(cache.begin('Risk', 1).cached, ['latest risk']); +}); + +test('configuration changes invalidate an in-flight request before another query starts', () => { + const cache = new CompletionCache(); + const request = cache.begin('Risk', 1).request; + assert.equal(cache.isCurrent(request, 2), false); + assert.deepEqual(cache.commit(request, 2, ['old endpoint']), []); + assert.equal(cache.begin('Risk', 2).cached, undefined); +}); + +test('changing query clears previous results while the new request is pending', () => { + const cache = new CompletionCache(); + cache.commit(cache.begin('Risk', 1).request, 1, ['risk']); + const next = cache.begin('Decision', 1); + assert.equal(next.cached, undefined); + assert.deepEqual(cache.begin('Decision', 1).cached, []); + assert.deepEqual(cache.commit(next.request, 1, ['decision']), ['decision']); +}); diff --git a/vs-code-terraphim-it/tests/nativeConfiguration.cjs b/vs-code-terraphim-it/tests/nativeConfiguration.cjs new file mode 100644 index 000000000..b6ca00c03 --- /dev/null +++ b/vs-code-terraphim-it/tests/nativeConfiguration.cjs @@ -0,0 +1,124 @@ +/* Real VS Code settings and the packaged @tomic Store. No HTTP/API substitutes. */ +const vscode = require('vscode'); +const assert = require('node:assert/strict'); +const fs = require('node:fs/promises'); +const path = require('node:path'); +const { createRequire } = require('node:module'); + +exports.checkConfiguration = async (extension, output) => { + const config = () => vscode.workspace.getConfiguration('terraphimIt'); + const keys = ['agent', 'atomicServerUrl', 'serverUrl', 'selectedRole', 'enableLocalServer']; + const previous = Object.fromEntries(keys.map(key => [key, config().inspect(key).globalValue])); + const { Agent } = createRequire(path.join(extension.extensionPath, 'out/extension.js'))('@tomic/lib'); + const canonical = async filename => { + const actual = await fs.realpath(filename); + return process.platform === 'win32' ? actual.toLowerCase() : actual; + }; + const loadedModule = async relative => { + // VS Code's Windows URI path can differ in drive case/short-name spelling + // from Node's loaded filename. A second require would create another + // singleton whose configuration listener was never registered by activate. + const expected = await canonical(path.join(extension.extensionPath, relative)); + const candidates = Object.values(require.cache).filter(module => path.basename(module.filename) === path.basename(relative)); + const matches = []; + for (const module of candidates) { + if (await canonical(module.filename) === expected) matches.push(module); + } + assert.equal(matches.length, 1, `exactly one activated package module: ${relative}`); + return matches[0]; + }; + const storeModule = await loadedModule('out/helpers/getStore.js'); + const connectionModule = await loadedModule('out/helpers/serverConnection.js'); + const stores = storeModule.exports; + const { serverConnection } = connectionModule.exports; + const report = { hostVersion: vscode.version, extensionVersion: extension.packageJSON.version, + requestedModuleFiles: {store:path.join(extension.extensionPath, 'out/helpers/getStore.js'), connection:path.join(extension.extensionPath, 'out/helpers/serverConnection.js')}, + activatedModuleFiles: {store:storeModule.filename, connection:connectionModule.filename}, + scope: 'Actual native settings, packaged Store identity and routing refusal; no authenticated service or successful remote retrieval claimed', checks: [] }; + const update = async (key, value) => { + if (config().inspect(key).globalValue === value) return; + const observed = new Promise((resolve, reject) => { + const timer = setTimeout(() => { + listener.dispose(); + reject(new Error(`Native configuration event timed out: ${key}`)); + }, 5000); + const listener = vscode.workspace.onDidChangeConfiguration(event => { + if (event.affectsConfiguration(`terraphimIt.${key}`)) { + clearTimeout(timer); + listener.dispose(); + resolve(); + } + }); + }); + await config().update(key, value, vscode.ConfigurationTarget.Global); + await observed; + }; + try { + // Deliberately inert, synthetic credentials. Never sent to a service. + const agent = new Agent(Buffer.alloc(32).toString('base64'), 'https://example.invalid/configuration-agent'); + await update('agent', agent.buildSecret()); + await update('atomicServerUrl', 'https://example.invalid/atomic-before'); + assert.equal(await vscode.commands.executeCommand('extension.terraphimAIAutocomplete'), true); + const initial = stores.getStore(); + assert.equal(initial.getAgent().subject, agent.subject); + assert.equal(initial.getServerUrl(), 'https://example.invalid/atomic-before'); + assert.equal(stores.getStore(), initial); + report.checks.push('first autocomplete activation reads the configured agent; unchanged settings reuse the actual Store'); + + await update('atomicServerUrl', 'https://example.invalid/atomic-after'); + const changed = stores.getStore(); + assert.notEqual(changed, initial); + assert.equal(changed.getServerUrl(), 'https://example.invalid/atomic-after'); + assert.equal(changed.getAgent().subject, agent.subject); + await update('agent', ''); + const anonymous = stores.getStore(); + assert.notEqual(anonymous, changed); + assert.equal(anonymous.getAgent(), undefined); + await update('agent', 'invalid-agent'); + assert.equal(await vscode.commands.executeCommand('extension.terraphimAIAutocomplete'), false); + assert.throws(() => stores.getStore()); + await update('agent', ''); + report.checks.push('endpoint and credential changes replace the actual Store; clearing credentials is anonymous; malformed credentials reject activation'); + + await update('serverUrl', 'http://127.0.0.1:0'); + await update('enableLocalServer', false); + assert.throws(() => serverConnection.getServerUrl(), /Local Terraphim server is disabled/); + const disabled = await serverConnection.healthCheck(); + assert.equal(disabled.healthy, false); + assert.match(disabled.message, /Local Terraphim server is disabled/); + assert.deepEqual(await serverConnection.searchDocuments('Risk'), {status:'error', results:[]}); + assert.deepEqual(await serverConnection.getAutocompleteSuggestions('Risk'), {status:'error', suggestions:[]}); + assert.equal(await vscode.commands.executeCommand('extension.terraphimServerAutocomplete'), false); + for (const url of ['http://localhost:8000', 'http://127.1:8000', 'http://[::1]:8000', 'http://[::ffff:127.0.0.1]:8000', 'http://0.0.0.0:8000']) { + await update('serverUrl', url); + assert.throws(() => serverConnection.getServerUrl(), /Local Terraphim server is disabled/); + } + await update('serverUrl', 'https://example.invalid/terraphim/'); + assert.equal(serverConnection.getServerUrl(), 'https://example.invalid/terraphim'); + report.checks.push('disabled local mode refuses loopback in every request path and selects the explicit remote URL without a public fallback'); + + const revision = serverConnection.getConfigurationRevision(); + await update('selectedRole', 'Configuration acceptance role'); + assert.equal(serverConnection.getSelectedRole(), 'Configuration acceptance role'); + assert.ok(serverConnection.getConfigurationRevision() > revision); + await update('serverUrl', 'http://127.0.0.1:0'); + await update('enableLocalServer', true); + assert.equal(serverConnection.getServerUrl(), 'http://127.0.0.1:0'); + const unavailable = await serverConnection.healthCheck(); + assert.equal(unavailable.healthy, false); + assert.doesNotMatch(unavailable.message, /Local Terraphim server is disabled/); + report.checks.push('enabled local mode attempts the real unavailable endpoint; role changes advance the completion-cache revision'); + report.health = {disabled, unavailable}; + report.result = 'PASS'; + } catch (error) { + report.result = 'FAIL'; report.error = String(error.stack || error); throw error; + } finally { + for (const key of keys) { + if (config().inspect(key).globalValue !== previous[key]) await update(key, previous[key]); + } + stores.resetStore(); + report.settingsRestored = keys.every(key => config().inspect(key).globalValue === previous[key]); + await fs.writeFile(path.join(output, 'configuration.json'), JSON.stringify(report, null, 2) + '\n'); + assert.equal(report.settingsRestored, true); + } +}; diff --git a/vs-code-terraphim-it/tests/nativeHostLifecycle.cjs b/vs-code-terraphim-it/tests/nativeHostLifecycle.cjs index 1de5c032b..03abcdcdf 100644 --- a/vs-code-terraphim-it/tests/nativeHostLifecycle.cjs +++ b/vs-code-terraphim-it/tests/nativeHostLifecycle.cjs @@ -24,6 +24,9 @@ exports.run = async () => { try { const extension = vscode.extensions.getExtension('applied-knowledge-systems.terraphim-it'); assert.ok(extension); await extension.activate(); + await require('./nativeConfiguration.cjs').checkConfiguration(extension, output); + await vscode.commands.executeCommand('notifications.clearAll'); + report.checks.push('packaged extension passes real native agent, endpoint, role and local-server configuration regressions; isolated settings restored'); report.extensionPath = extension.extensionPath; report.assetLockSha256 = digest(await fs.readFile(path.join(extension.extensionPath,'media/editor-build.json'))); const {replaceLinks} = require(path.join(extension.extensionPath,'out/helpers/linkReplacement.js'));