{"version":3,"file":"settings-default-tools.test.d.ts","sourceRoot":"","sources":["../../src/core/settings-default-tools.test.ts"],"names":[],"mappings":"","sourcesContent":["import { tmpdir } from \"node:os\";\nimport { join } from \"node:path\";\nimport type { Model } from \"@apholdings/jensen-ai\";\nimport { afterEach, beforeEach, describe, expect, it } from \"vitest\";\nimport { AuthStorage } from \"./auth-storage.js\";\nimport { ModelRegistry } from \"./model-registry.js\";\nimport { DefaultResourceLoader } from \"./resource-loader.js\";\nimport { createAgentSession } from \"./sdk.js\";\nimport { SessionManager } from \"./session-manager.js\";\nimport { SettingsManager } from \"./settings-manager.js\";\n\nfunction createTestModel(): Model<\"openai-chat\"> {\n\treturn {\n\t\tid: \"default-tools-test-model\",\n\t\tname: \"Default Tools Test Model\",\n\t\tprovider: \"default-tools-test-provider\",\n\t\tapi: \"openai-chat\",\n\t\tbaseUrl: \"https://example.test\",\n\t\treasoning: true,\n\t\tinput: [\"text\"],\n\t\tcost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },\n\t\tcontextWindow: 200_000,\n\t\tmaxTokens: 8_000,\n\t};\n}\n\nfunction setupTestEnv() {\n\tconst rootDir = require(\"fs\").mkdtempSync(join(tmpdir(), \"jensen-default-tools-\"));\n\tconst cwd = join(rootDir, \"repo\");\n\tconst agentDir = join(rootDir, \"agent\");\n\tconst sessionDir = join(rootDir, \"sessions\");\n\n\trequire(\"fs\").mkdirSync(cwd, { recursive: true });\n\trequire(\"fs\").mkdirSync(agentDir, { recursive: true });\n\trequire(\"fs\").mkdirSync(sessionDir, { recursive: true });\n\n\tconst authStorage = AuthStorage.create(join(agentDir, \"auth.json\"));\n\tconst modelRegistry = new ModelRegistry(authStorage);\n\tconst testModel = createTestModel();\n\tmodelRegistry.registerProvider(testModel.provider, {\n\t\tapi: testModel.api,\n\t\tapiKey: \"test-api-key\",\n\t\tbaseUrl: testModel.baseUrl,\n\t\tmodels: [\n\t\t\t{\n\t\t\t\tid: testModel.id,\n\t\t\t\tname: testModel.name,\n\t\t\t\tapi: testModel.api,\n\t\t\t\treasoning: testModel.reasoning,\n\t\t\t\tinput: testModel.input,\n\t\t\t\tcost: testModel.cost,\n\t\t\t\tcontextWindow: testModel.contextWindow,\n\t\t\t\tmaxTokens: testModel.maxTokens,\n\t\t\t},\n\t\t],\n\t});\n\n\treturn { rootDir, cwd, agentDir, sessionDir, authStorage, modelRegistry, testModel };\n}\n\ndescribe(\"settings default tools\", () => {\n\tlet rootDir: string;\n\tlet cwd: string;\n\tlet agentDir: string;\n\n\tbeforeEach(() => {\n\t\tconst env = setupTestEnv();\n\t\trootDir = env.rootDir;\n\t\tcwd = env.cwd;\n\t\tagentDir = env.agentDir;\n\t});\n\n\tafterEach(() => {\n\t\trequire(\"fs\").rmSync(rootDir, { recursive: true, force: true });\n\t});\n\n\tdescribe(\"getDefaultActiveToolNames\", () => {\n\t\tit(\"returns undefined when tools config is absent\", () => {\n\t\t\tconst settingsManager = SettingsManager.inMemory({});\n\t\t\texpect(settingsManager.getDefaultActiveToolNames()).toBeUndefined();\n\t\t});\n\n\t\tit(\"returns undefined when tools config is empty object\", () => {\n\t\t\tconst settingsManager = SettingsManager.inMemory({ tools: {} });\n\t\t\texpect(settingsManager.getDefaultActiveToolNames()).toBeUndefined();\n\t\t});\n\n\t\tit(\"returns configured tool names when present\", () => {\n\t\t\tconst settingsManager = SettingsManager.inMemory({\n\t\t\t\ttools: { defaultActiveToolNames: [\"read\", \"bash\"] },\n\t\t\t});\n\t\t\texpect(settingsManager.getDefaultActiveToolNames()).toEqual([\"read\", \"bash\"]);\n\t\t});\n\n\t\tit(\"filters unknown tool names\", () => {\n\t\t\tconst settingsManager = SettingsManager.inMemory({\n\t\t\t\ttools: { defaultActiveToolNames: [\"read\", \"unknown_tool\", \"bash\"] },\n\t\t\t});\n\t\t\texpect(settingsManager.getDefaultActiveToolNames()).toEqual([\"read\", \"bash\"]);\n\t\t});\n\n\t\tit(\"returns undefined when all configured tools are unknown\", () => {\n\t\t\tconst settingsManager = SettingsManager.inMemory({\n\t\t\t\ttools: { defaultActiveToolNames: [\"unknown1\", \"unknown2\"] },\n\t\t\t});\n\t\t\texpect(settingsManager.getDefaultActiveToolNames()).toBeUndefined();\n\t\t});\n\n\t\tit(\"supports web_search in configured tools\", () => {\n\t\t\tconst settingsManager = SettingsManager.inMemory({\n\t\t\t\ttools: { defaultActiveToolNames: [\"web_search\"] },\n\t\t\t});\n\t\t\texpect(settingsManager.getDefaultActiveToolNames()).toEqual([\"web_search\"]);\n\t\t});\n\n\t\tit(\"supports powershell in configured tools\", () => {\n\t\t\tconst settingsManager = SettingsManager.inMemory({\n\t\t\t\ttools: { defaultActiveToolNames: [\"powershell\"] },\n\t\t\t});\n\t\t\texpect(settingsManager.getDefaultActiveToolNames()).toEqual([\"powershell\"]);\n\t\t});\n\n\t\tit(\"returns undefined for empty array\", () => {\n\t\t\tconst settingsManager = SettingsManager.inMemory({\n\t\t\t\ttools: { defaultActiveToolNames: [] },\n\t\t\t});\n\t\t\texpect(settingsManager.getDefaultActiveToolNames()).toBeUndefined();\n\t\t});\n\n\t\tit(\"filters out non-string entries\", () => {\n\t\t\tconst settingsManager = SettingsManager.inMemory({\n\t\t\t\t// @ts-expect-error - testing runtime behavior with invalid data\n\t\t\t\ttools: { defaultActiveToolNames: [\"read\", 123, null, \"bash\", undefined] },\n\t\t\t});\n\t\t\texpect(settingsManager.getDefaultActiveToolNames()).toEqual([\"read\", \"bash\"]);\n\t\t});\n\t});\n\n\tdescribe(\"createAgentSession with settings default tools\", () => {\n\t\tit(\"uses legacy defaults when settings have no tools config\", async () => {\n\t\t\tconst env = setupTestEnv();\n\t\t\trootDir = env.rootDir;\n\t\t\tcwd = env.cwd;\n\t\t\tagentDir = env.agentDir;\n\n\t\t\ttry {\n\t\t\t\tconst settingsManager = SettingsManager.inMemory({});\n\t\t\t\tconst sessionManager = SessionManager.inMemory();\n\t\t\t\tconst resourceLoader = new DefaultResourceLoader({\n\t\t\t\t\tcwd,\n\t\t\t\t\tagentDir,\n\t\t\t\t\tsettingsManager,\n\t\t\t\t});\n\t\t\t\tawait resourceLoader.reload();\n\n\t\t\t\tconst { session } = await createAgentSession({\n\t\t\t\t\tcwd,\n\t\t\t\t\tagentDir,\n\t\t\t\t\tsettingsManager,\n\t\t\t\t\tauthStorage: env.authStorage,\n\t\t\t\t\tmodelRegistry: env.modelRegistry,\n\t\t\t\t\tresourceLoader,\n\t\t\t\t\tsessionManager,\n\t\t\t\t});\n\n\t\t\t\t// Legacy defaults now include todo, memory and web research tools\n\t\t\t\tconst activeTools = session.getActiveToolNames();\n\t\t\t\texpect(activeTools).toContain(\"read\");\n\t\t\t\texpect(activeTools).toContain(\"bash\");\n\t\t\t\texpect(activeTools).toContain(\"edit\");\n\t\t\t\texpect(activeTools).toContain(\"write\");\n\t\t\t\texpect(activeTools).toContain(\"todo_write\");\n\t\t\t\texpect(activeTools).toContain(\"todo_read\");\n\t\t\t\texpect(activeTools).toContain(\"todo_update\");\n\t\t\t\texpect(activeTools).toContain(\"memory_write\");\n\t\t\t\texpect(activeTools).toContain(\"web_search\");\n\t\t\t\texpect(activeTools).toContain(\"web_fetch\");\n\t\t\t\texpect(activeTools).toContain(\"deep_research\");\n\t\t\t\texpect(activeTools).toContain(\"web_research_status\");\n\t\t\t} finally {\n\t\t\t\trequire(\"fs\").rmSync(rootDir, { recursive: true, force: true });\n\t\t\t}\n\t\t});\n\n\t\tit(\"uses configured tools from settings when no explicit tools provided\", async () => {\n\t\t\tconst env = setupTestEnv();\n\t\t\trootDir = env.rootDir;\n\t\t\tcwd = env.cwd;\n\t\t\tagentDir = env.agentDir;\n\n\t\t\ttry {\n\t\t\t\tconst settingsManager = SettingsManager.inMemory({\n\t\t\t\t\ttools: { defaultActiveToolNames: [\"read\", \"bash\"] },\n\t\t\t\t});\n\t\t\t\tconst sessionManager = SessionManager.inMemory();\n\t\t\t\tconst resourceLoader = new DefaultResourceLoader({\n\t\t\t\t\tcwd,\n\t\t\t\t\tagentDir,\n\t\t\t\t\tsettingsManager,\n\t\t\t\t});\n\t\t\t\tawait resourceLoader.reload();\n\n\t\t\t\tconst { session } = await createAgentSession({\n\t\t\t\t\tcwd,\n\t\t\t\t\tagentDir,\n\t\t\t\t\tsettingsManager,\n\t\t\t\t\tauthStorage: env.authStorage,\n\t\t\t\t\tmodelRegistry: env.modelRegistry,\n\t\t\t\t\tresourceLoader,\n\t\t\t\t\tsessionManager,\n\t\t\t\t});\n\n\t\t\t\t// Should use configured settings tools\n\t\t\t\tconst activeTools = session.getActiveToolNames();\n\t\t\t\texpect(activeTools).toContain(\"read\");\n\t\t\t\texpect(activeTools).toContain(\"bash\");\n\t\t\t\texpect(activeTools).not.toContain(\"edit\");\n\t\t\t\texpect(activeTools).not.toContain(\"write\");\n\t\t\t} finally {\n\t\t\t\trequire(\"fs\").rmSync(rootDir, { recursive: true, force: true });\n\t\t\t}\n\t\t});\n\n\t\tit(\"uses explicit tools over settings when provided\", async () => {\n\t\t\tconst env = setupTestEnv();\n\t\t\trootDir = env.rootDir;\n\t\t\tcwd = env.cwd;\n\t\t\tagentDir = env.agentDir;\n\n\t\t\ttry {\n\t\t\t\tconst settingsManager = SettingsManager.inMemory({\n\t\t\t\t\ttools: { defaultActiveToolNames: [\"read\", \"bash\"] },\n\t\t\t\t});\n\t\t\t\tconst sessionManager = SessionManager.inMemory();\n\t\t\t\tconst resourceLoader = new DefaultResourceLoader({\n\t\t\t\t\tcwd,\n\t\t\t\t\tagentDir,\n\t\t\t\t\tsettingsManager,\n\t\t\t\t});\n\t\t\t\tawait resourceLoader.reload();\n\n\t\t\t\t// Provide explicit tools - should override settings\n\t\t\t\tconst { session } = await createAgentSession({\n\t\t\t\t\tcwd,\n\t\t\t\t\tagentDir,\n\t\t\t\t\tsettingsManager,\n\t\t\t\t\tauthStorage: env.authStorage,\n\t\t\t\t\tmodelRegistry: env.modelRegistry,\n\t\t\t\t\tresourceLoader,\n\t\t\t\t\tsessionManager,\n\t\t\t\t\ttools: [{ name: \"grep\" }] as any,\n\t\t\t\t});\n\n\t\t\t\t// Should use explicit tools, not settings\n\t\t\t\tconst activeTools = session.getActiveToolNames();\n\t\t\t\texpect(activeTools).toContain(\"grep\");\n\t\t\t} finally {\n\t\t\t\trequire(\"fs\").rmSync(rootDir, { recursive: true, force: true });\n\t\t\t}\n\t\t});\n\n\t\tit(\"falls back to legacy defaults when all configured tools are invalid\", async () => {\n\t\t\tconst env = setupTestEnv();\n\t\t\trootDir = env.rootDir;\n\t\t\tcwd = env.cwd;\n\t\t\tagentDir = env.agentDir;\n\n\t\t\ttry {\n\t\t\t\tconst settingsManager = SettingsManager.inMemory({\n\t\t\t\t\ttools: { defaultActiveToolNames: [\"invalid1\", \"invalid2\"] },\n\t\t\t\t});\n\t\t\t\tconst sessionManager = SessionManager.inMemory();\n\t\t\t\tconst resourceLoader = new DefaultResourceLoader({\n\t\t\t\t\tcwd,\n\t\t\t\t\tagentDir,\n\t\t\t\t\tsettingsManager,\n\t\t\t\t});\n\t\t\t\tawait resourceLoader.reload();\n\n\t\t\t\tconst { session } = await createAgentSession({\n\t\t\t\t\tcwd,\n\t\t\t\t\tagentDir,\n\t\t\t\t\tsettingsManager,\n\t\t\t\t\tauthStorage: env.authStorage,\n\t\t\t\t\tmodelRegistry: env.modelRegistry,\n\t\t\t\t\tresourceLoader,\n\t\t\t\t\tsessionManager,\n\t\t\t\t});\n\n\t\t\t\t// Should fall back to legacy defaults (now includes todo and memory tools)\n\t\t\t\tconst activeTools = session.getActiveToolNames();\n\t\t\t\texpect(activeTools).toContain(\"read\");\n\t\t\t\texpect(activeTools).toContain(\"bash\");\n\t\t\t\texpect(activeTools).toContain(\"edit\");\n\t\t\t\texpect(activeTools).toContain(\"write\");\n\t\t\t\texpect(activeTools).toContain(\"todo_write\");\n\t\t\t\texpect(activeTools).toContain(\"todo_read\");\n\t\t\t\texpect(activeTools).toContain(\"todo_update\");\n\t\t\t\texpect(activeTools).toContain(\"memory_write\");\n\t\t\t} finally {\n\t\t\t\trequire(\"fs\").rmSync(rootDir, { recursive: true, force: true });\n\t\t\t}\n\t\t});\n\t});\n});\n"]}