@inkeep/agents-core 0.1.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/LICENSE.md +51 -0
- package/README.md +464 -0
- package/dist/__tests__/integration/helpers.d.ts +5 -0
- package/dist/__tests__/integration/helpers.d.ts.map +1 -0
- package/dist/__tests__/integration/helpers.js +37 -0
- package/dist/__tests__/integration/helpers.js.map +1 -0
- package/dist/__tests__/setup.d.ts +3 -0
- package/dist/__tests__/setup.d.ts.map +1 -0
- package/dist/__tests__/setup.js +29 -0
- package/dist/__tests__/setup.js.map +1 -0
- package/dist/client-exports.d.ts +301 -0
- package/dist/client-exports.d.ts.map +1 -0
- package/dist/client-exports.js +251 -0
- package/dist/client-exports.js.map +1 -0
- package/dist/context/ContextConfig.d.ts +55 -0
- package/dist/context/ContextConfig.d.ts.map +1 -0
- package/dist/context/ContextConfig.js +302 -0
- package/dist/context/ContextConfig.js.map +1 -0
- package/dist/context/ContextFetcher.d.ts +64 -0
- package/dist/context/ContextFetcher.d.ts.map +1 -0
- package/dist/context/ContextFetcher.js +325 -0
- package/dist/context/ContextFetcher.js.map +1 -0
- package/dist/context/ContextResolver.d.ts +52 -0
- package/dist/context/ContextResolver.d.ts.map +1 -0
- package/dist/context/ContextResolver.js +298 -0
- package/dist/context/ContextResolver.js.map +1 -0
- package/dist/context/TemplateEngine.d.ts +46 -0
- package/dist/context/TemplateEngine.d.ts.map +1 -0
- package/dist/context/TemplateEngine.js +175 -0
- package/dist/context/TemplateEngine.js.map +1 -0
- package/dist/context/context.d.ts +7 -0
- package/dist/context/context.d.ts.map +1 -0
- package/dist/context/context.js +157 -0
- package/dist/context/context.js.map +1 -0
- package/dist/context/contextCache.d.ts +50 -0
- package/dist/context/contextCache.d.ts.map +1 -0
- package/dist/context/contextCache.js +175 -0
- package/dist/context/contextCache.js.map +1 -0
- package/dist/context/index.d.ts +11 -0
- package/dist/context/index.d.ts.map +1 -0
- package/dist/context/index.js +8 -0
- package/dist/context/index.js.map +1 -0
- package/dist/credential-stores/index.d.ts +4 -0
- package/dist/credential-stores/index.d.ts.map +1 -0
- package/dist/credential-stores/index.js +4 -0
- package/dist/credential-stores/index.js.map +1 -0
- package/dist/credential-stores/keychain-store.d.ts +100 -0
- package/dist/credential-stores/keychain-store.d.ts.map +1 -0
- package/dist/credential-stores/keychain-store.js +225 -0
- package/dist/credential-stores/keychain-store.js.map +1 -0
- package/dist/credential-stores/memory-store.d.ts +39 -0
- package/dist/credential-stores/memory-store.d.ts.map +1 -0
- package/dist/credential-stores/memory-store.js +58 -0
- package/dist/credential-stores/memory-store.js.map +1 -0
- package/dist/credential-stores/nango-store.d.ts +59 -0
- package/dist/credential-stores/nango-store.d.ts.map +1 -0
- package/dist/credential-stores/nango-store.js +264 -0
- package/dist/credential-stores/nango-store.js.map +1 -0
- package/dist/credential-stuffer/CredentialStuffer.d.ts +80 -0
- package/dist/credential-stuffer/CredentialStuffer.d.ts.map +1 -0
- package/dist/credential-stuffer/CredentialStuffer.js +186 -0
- package/dist/credential-stuffer/CredentialStuffer.js.map +1 -0
- package/dist/credential-stuffer/index.d.ts +2 -0
- package/dist/credential-stuffer/index.d.ts.map +1 -0
- package/dist/credential-stuffer/index.js +2 -0
- package/dist/credential-stuffer/index.js.map +1 -0
- package/dist/data-access/agentDataComponents.d.ts +1 -0
- package/dist/data-access/agentDataComponents.d.ts.map +1 -0
- package/dist/data-access/agentDataComponents.js +2 -0
- package/dist/data-access/agentDataComponents.js.map +1 -0
- package/dist/data-access/agentGraphs.d.ts +406 -0
- package/dist/data-access/agentGraphs.d.ts.map +1 -0
- package/dist/data-access/agentGraphs.js +551 -0
- package/dist/data-access/agentGraphs.js.map +1 -0
- package/dist/data-access/agentRelations.d.ts +456 -0
- package/dist/data-access/agentRelations.d.ts.map +1 -0
- package/dist/data-access/agentRelations.js +471 -0
- package/dist/data-access/agentRelations.js.map +1 -0
- package/dist/data-access/agents.d.ts +218 -0
- package/dist/data-access/agents.d.ts.map +1 -0
- package/dist/data-access/agents.js +130 -0
- package/dist/data-access/agents.js.map +1 -0
- package/dist/data-access/apiKeys.d.ts +114 -0
- package/dist/data-access/apiKeys.d.ts.map +1 -0
- package/dist/data-access/apiKeys.js +185 -0
- package/dist/data-access/apiKeys.js.map +1 -0
- package/dist/data-access/artifactComponents.d.ts +152 -0
- package/dist/data-access/artifactComponents.d.ts.map +1 -0
- package/dist/data-access/artifactComponents.js +214 -0
- package/dist/data-access/artifactComponents.js.map +1 -0
- package/dist/data-access/contextCache.d.ts +68 -0
- package/dist/data-access/contextCache.d.ts.map +1 -0
- package/dist/data-access/contextCache.js +160 -0
- package/dist/data-access/contextCache.js.map +1 -0
- package/dist/data-access/contextConfigs.d.ts +110 -0
- package/dist/data-access/contextConfigs.d.ts.map +1 -0
- package/dist/data-access/contextConfigs.js +156 -0
- package/dist/data-access/contextConfigs.js.map +1 -0
- package/dist/data-access/conversations.d.ts +125 -0
- package/dist/data-access/conversations.d.ts.map +1 -0
- package/dist/data-access/conversations.js +244 -0
- package/dist/data-access/conversations.js.map +1 -0
- package/dist/data-access/credentialReferences.d.ts +86 -0
- package/dist/data-access/credentialReferences.d.ts.map +1 -0
- package/dist/data-access/credentialReferences.js +175 -0
- package/dist/data-access/credentialReferences.js.map +1 -0
- package/dist/data-access/dataComponents.d.ts +129 -0
- package/dist/data-access/dataComponents.d.ts.map +1 -0
- package/dist/data-access/dataComponents.js +213 -0
- package/dist/data-access/dataComponents.js.map +1 -0
- package/dist/data-access/externalAgents.d.ts +83 -0
- package/dist/data-access/externalAgents.d.ts.map +1 -0
- package/dist/data-access/externalAgents.js +163 -0
- package/dist/data-access/externalAgents.js.map +1 -0
- package/dist/data-access/graphFull.d.ts +32 -0
- package/dist/data-access/graphFull.d.ts.map +1 -0
- package/dist/data-access/graphFull.js +995 -0
- package/dist/data-access/graphFull.js.map +1 -0
- package/dist/data-access/index.d.ts +21 -0
- package/dist/data-access/index.d.ts.map +1 -0
- package/dist/data-access/index.js +22 -0
- package/dist/data-access/index.js.map +1 -0
- package/dist/data-access/ledgerArtifacts.d.ts +50 -0
- package/dist/data-access/ledgerArtifacts.d.ts.map +1 -0
- package/dist/data-access/ledgerArtifacts.js +112 -0
- package/dist/data-access/ledgerArtifacts.js.map +1 -0
- package/dist/data-access/messages.d.ts +209 -0
- package/dist/data-access/messages.d.ts.map +1 -0
- package/dist/data-access/messages.js +100 -0
- package/dist/data-access/messages.js.map +1 -0
- package/dist/data-access/projects.d.ts +67 -0
- package/dist/data-access/projects.d.ts.map +1 -0
- package/dist/data-access/projects.js +336 -0
- package/dist/data-access/projects.js.map +1 -0
- package/dist/data-access/tasks.d.ts +37 -0
- package/dist/data-access/tasks.d.ts.map +1 -0
- package/dist/data-access/tasks.js +40 -0
- package/dist/data-access/tasks.js.map +1 -0
- package/dist/data-access/tools.d.ts +277 -0
- package/dist/data-access/tools.d.ts.map +1 -0
- package/dist/data-access/tools.js +183 -0
- package/dist/data-access/tools.js.map +1 -0
- package/dist/data-access/validation.d.ts +17 -0
- package/dist/data-access/validation.d.ts.map +1 -0
- package/dist/data-access/validation.js +52 -0
- package/dist/data-access/validation.js.map +1 -0
- package/dist/db/clean.d.ts +6 -0
- package/dist/db/clean.d.ts.map +1 -0
- package/dist/db/clean.js +81 -0
- package/dist/db/clean.js.map +1 -0
- package/dist/db/client.d.ts +19 -0
- package/dist/db/client.d.ts.map +1 -0
- package/dist/db/client.js +24 -0
- package/dist/db/client.js.map +1 -0
- package/dist/db/schema.d.ts +4337 -0
- package/dist/db/schema.d.ts.map +1 -0
- package/dist/db/schema.js +696 -0
- package/dist/db/schema.js.map +1 -0
- package/dist/db/test-client.d.ts +25 -0
- package/dist/db/test-client.d.ts.map +1 -0
- package/dist/db/test-client.js +136 -0
- package/dist/db/test-client.js.map +1 -0
- package/dist/env.d.ts +17 -0
- package/dist/env.d.ts.map +1 -0
- package/dist/env.js +48 -0
- package/dist/env.js.map +1 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +14 -0
- package/dist/index.js.map +1 -0
- package/dist/middleware/contextValidation.d.ts +48 -0
- package/dist/middleware/contextValidation.d.ts.map +1 -0
- package/dist/middleware/contextValidation.js +469 -0
- package/dist/middleware/contextValidation.js.map +1 -0
- package/dist/middleware/index.d.ts +2 -0
- package/dist/middleware/index.d.ts.map +1 -0
- package/dist/middleware/index.js +2 -0
- package/dist/middleware/index.js.map +1 -0
- package/dist/server/BaseServer.d.ts +83 -0
- package/dist/server/BaseServer.d.ts.map +1 -0
- package/dist/server/BaseServer.js +218 -0
- package/dist/server/BaseServer.js.map +1 -0
- package/dist/types/a2a.d.ts +373 -0
- package/dist/types/a2a.d.ts.map +1 -0
- package/dist/types/a2a.js +14 -0
- package/dist/types/a2a.js.map +1 -0
- package/dist/types/entities.d.ts +147 -0
- package/dist/types/entities.d.ts.map +1 -0
- package/dist/types/entities.js +2 -0
- package/dist/types/entities.js.map +1 -0
- package/dist/types/index.d.ts +5 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +6 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types/server.d.ts +116 -0
- package/dist/types/server.d.ts.map +1 -0
- package/dist/types/server.js +2 -0
- package/dist/types/server.js.map +1 -0
- package/dist/types/utility.d.ts +214 -0
- package/dist/types/utility.d.ts.map +1 -0
- package/dist/types/utility.js +9 -0
- package/dist/types/utility.js.map +1 -0
- package/dist/utils/apiKeys.d.ts +32 -0
- package/dist/utils/apiKeys.d.ts.map +1 -0
- package/dist/utils/apiKeys.js +117 -0
- package/dist/utils/apiKeys.js.map +1 -0
- package/dist/utils/auth-detection.d.ts +23 -0
- package/dist/utils/auth-detection.d.ts.map +1 -0
- package/dist/utils/auth-detection.js +148 -0
- package/dist/utils/auth-detection.js.map +1 -0
- package/dist/utils/credential-store-utils.d.ts +11 -0
- package/dist/utils/credential-store-utils.d.ts.map +1 -0
- package/dist/utils/credential-store-utils.js +19 -0
- package/dist/utils/credential-store-utils.js.map +1 -0
- package/dist/utils/error.d.ts +526 -0
- package/dist/utils/error.d.ts.map +1 -0
- package/dist/utils/error.js +282 -0
- package/dist/utils/error.js.map +1 -0
- package/dist/utils/execution.d.ts +18 -0
- package/dist/utils/execution.d.ts.map +1 -0
- package/dist/utils/execution.js +25 -0
- package/dist/utils/execution.js.map +1 -0
- package/dist/utils/index.d.ts +9 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/index.js +9 -0
- package/dist/utils/index.js.map +1 -0
- package/dist/utils/logger.d.ts +79 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +102 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/utils/logging.d.ts +11 -0
- package/dist/utils/logging.d.ts.map +1 -0
- package/dist/utils/logging.js +6 -0
- package/dist/utils/logging.js.map +1 -0
- package/dist/utils/mcp-client.d.ts +48 -0
- package/dist/utils/mcp-client.d.ts.map +1 -0
- package/dist/utils/mcp-client.js +171 -0
- package/dist/utils/mcp-client.js.map +1 -0
- package/dist/utils/tracer.d.ts +24 -0
- package/dist/utils/tracer.d.ts.map +1 -0
- package/dist/utils/tracer.js +98 -0
- package/dist/utils/tracer.js.map +1 -0
- package/dist/validation/graphFull.d.ts +36 -0
- package/dist/validation/graphFull.d.ts.map +1 -0
- package/dist/validation/graphFull.js +128 -0
- package/dist/validation/graphFull.js.map +1 -0
- package/dist/validation/id-validation.d.ts +38 -0
- package/dist/validation/id-validation.d.ts.map +1 -0
- package/dist/validation/id-validation.js +60 -0
- package/dist/validation/id-validation.js.map +1 -0
- package/dist/validation/index.d.ts +4 -0
- package/dist/validation/index.d.ts.map +1 -0
- package/dist/validation/index.js +5 -0
- package/dist/validation/index.js.map +1 -0
- package/dist/validation/schemas.d.ts +7233 -0
- package/dist/validation/schemas.d.ts.map +1 -0
- package/dist/validation/schemas.js +525 -0
- package/dist/validation/schemas.js.map +1 -0
- package/package.json +89 -0
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
import { SpanStatusCode } from '@opentelemetry/api';
|
|
2
|
+
import { ContextResolver } from './ContextResolver.js';
|
|
3
|
+
import { getLogger } from '../utils/logger.js';
|
|
4
|
+
import { createSpanName, getGlobalTracer, forceFlushTracer } from '../utils/tracer.js';
|
|
5
|
+
import { getAgentGraphWithDefaultAgent, getConversation, updateConversation, getContextConfigById, } from '@inkeep/agents-core';
|
|
6
|
+
const logger = getLogger('context');
|
|
7
|
+
// Get tracer using centralized utility
|
|
8
|
+
const tracer = getGlobalTracer();
|
|
9
|
+
// Helper function to determine context resolution trigger
|
|
10
|
+
async function determineContextTrigger(tenantId, projectId, conversationId, dbClient) {
|
|
11
|
+
const conversation = await getConversation(dbClient)({
|
|
12
|
+
scopes: { tenantId, projectId },
|
|
13
|
+
conversationId,
|
|
14
|
+
});
|
|
15
|
+
// New conversation or no previous context resolution = initialization
|
|
16
|
+
if (!conversation || !conversation.lastContextResolution) {
|
|
17
|
+
return 'initialization';
|
|
18
|
+
}
|
|
19
|
+
// Existing conversation with previous context = invocation
|
|
20
|
+
return 'invocation';
|
|
21
|
+
}
|
|
22
|
+
// Helper function to handle context config changes
|
|
23
|
+
async function handleContextConfigChange(tenantId, projectId, conversationId, graphId, newContextConfigId, dbClient) {
|
|
24
|
+
const conversation = await getConversation(dbClient)({
|
|
25
|
+
scopes: { tenantId, projectId },
|
|
26
|
+
conversationId,
|
|
27
|
+
});
|
|
28
|
+
if (!conversation)
|
|
29
|
+
return;
|
|
30
|
+
// For existing conversations, we conservatively clear cache when there's
|
|
31
|
+
// a possibility of config change since we don't store contextConfigId in conversations
|
|
32
|
+
if (conversation.lastContextResolution) {
|
|
33
|
+
// Context config might have changed - clear cache for this conversation
|
|
34
|
+
const contextResolver = new ContextResolver(tenantId, projectId, dbClient);
|
|
35
|
+
await contextResolver.clearCache(tenantId, projectId, conversationId);
|
|
36
|
+
logger.info({
|
|
37
|
+
conversationId,
|
|
38
|
+
graphId,
|
|
39
|
+
contextConfigId: newContextConfigId,
|
|
40
|
+
}, 'Potential context config change for existing conversation, cache cleared');
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
// Enhanced context resolution function
|
|
44
|
+
async function handleContextResolution(tenantId, projectId, conversationId, graphId, requestContext, dbClient) {
|
|
45
|
+
// Create parent span for the entire context resolution process
|
|
46
|
+
return tracer.startActiveSpan(createSpanName('context.handle_context_resolution'), {
|
|
47
|
+
attributes: {
|
|
48
|
+
'context.request_context_keys': Object.keys(requestContext),
|
|
49
|
+
},
|
|
50
|
+
}, async (parentSpan) => {
|
|
51
|
+
let agentGraph;
|
|
52
|
+
let trigger;
|
|
53
|
+
try {
|
|
54
|
+
// 1. Get graph's context config
|
|
55
|
+
agentGraph = await getAgentGraphWithDefaultAgent(dbClient)({
|
|
56
|
+
scopes: { tenantId, projectId },
|
|
57
|
+
graphId,
|
|
58
|
+
});
|
|
59
|
+
if (!agentGraph?.contextConfigId) {
|
|
60
|
+
logger.debug({ graphId }, 'No context config found for graph');
|
|
61
|
+
return null;
|
|
62
|
+
}
|
|
63
|
+
// 2. Handle context config changes (upsert scenario)
|
|
64
|
+
await handleContextConfigChange(tenantId, projectId, conversationId, graphId, agentGraph.contextConfigId, dbClient);
|
|
65
|
+
// 3. Determine trigger based on conversation state
|
|
66
|
+
trigger = await determineContextTrigger(tenantId, projectId, conversationId, dbClient);
|
|
67
|
+
// 4. Get context configuration directly from database
|
|
68
|
+
const contextConfig = await getContextConfigById(dbClient)({
|
|
69
|
+
scopes: { tenantId, projectId },
|
|
70
|
+
id: agentGraph.contextConfigId,
|
|
71
|
+
});
|
|
72
|
+
if (!contextConfig) {
|
|
73
|
+
logger.warn({ contextConfigId: agentGraph.contextConfigId }, 'Context config not found, proceeding without context resolution');
|
|
74
|
+
parentSpan.setStatus({ code: SpanStatusCode.ERROR });
|
|
75
|
+
parentSpan.addEvent('context.config_not_found', {
|
|
76
|
+
contextConfigId: agentGraph.contextConfigId,
|
|
77
|
+
});
|
|
78
|
+
return null;
|
|
79
|
+
}
|
|
80
|
+
// 5. Resolve context based on trigger
|
|
81
|
+
const contextResolver = new ContextResolver(tenantId, projectId, dbClient);
|
|
82
|
+
// Resolve unified context with appropriate trigger for cache invalidation
|
|
83
|
+
const contextResult = await contextResolver.resolve(contextConfig, {
|
|
84
|
+
triggerEvent: trigger,
|
|
85
|
+
conversationId,
|
|
86
|
+
requestContext,
|
|
87
|
+
tenantId,
|
|
88
|
+
});
|
|
89
|
+
// Add built-in variables to resolved context
|
|
90
|
+
const resolvedContext = {
|
|
91
|
+
...contextResult.resolvedContext,
|
|
92
|
+
$now: new Date().toISOString(),
|
|
93
|
+
$env: process.env,
|
|
94
|
+
};
|
|
95
|
+
// Update conversation's last context resolution timestamp
|
|
96
|
+
await updateConversation(dbClient)({
|
|
97
|
+
scopes: { tenantId, projectId },
|
|
98
|
+
conversationId,
|
|
99
|
+
data: {
|
|
100
|
+
lastContextResolution: new Date().toISOString(),
|
|
101
|
+
},
|
|
102
|
+
});
|
|
103
|
+
// Check if there were any errors during context resolution
|
|
104
|
+
if (contextResult.errors.length > 0) {
|
|
105
|
+
// Mark span as failed if there are errors
|
|
106
|
+
parentSpan.setStatus({
|
|
107
|
+
code: SpanStatusCode.ERROR,
|
|
108
|
+
message: `Context resolution completed with errors`,
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
else {
|
|
112
|
+
// Mark span as successful if no errors
|
|
113
|
+
parentSpan.setStatus({ code: SpanStatusCode.OK });
|
|
114
|
+
}
|
|
115
|
+
// Force flush after critical context resolution span
|
|
116
|
+
await forceFlushTracer();
|
|
117
|
+
logger.info({
|
|
118
|
+
conversationId,
|
|
119
|
+
graphId,
|
|
120
|
+
contextConfigId: contextConfig.id,
|
|
121
|
+
trigger,
|
|
122
|
+
resolvedKeys: Object.keys(resolvedContext),
|
|
123
|
+
cacheHits: contextResult.cacheHits.length,
|
|
124
|
+
cacheMisses: contextResult.cacheMisses.length,
|
|
125
|
+
fetchedDefinitions: contextResult.fetchedDefinitions.length,
|
|
126
|
+
errors: contextResult.errors.length,
|
|
127
|
+
}, 'Context resolution completed (contextConfigId derived from graph)');
|
|
128
|
+
return resolvedContext;
|
|
129
|
+
}
|
|
130
|
+
catch (error) {
|
|
131
|
+
const errorMessage = error instanceof Error ? error.message : 'Unknown error';
|
|
132
|
+
// Record error in parent span
|
|
133
|
+
parentSpan.recordException(error);
|
|
134
|
+
parentSpan.setAttributes({
|
|
135
|
+
'context.final_status': 'failed',
|
|
136
|
+
'context.error_message': errorMessage,
|
|
137
|
+
});
|
|
138
|
+
parentSpan.setStatus({
|
|
139
|
+
code: SpanStatusCode.ERROR,
|
|
140
|
+
message: errorMessage,
|
|
141
|
+
});
|
|
142
|
+
logger.error({
|
|
143
|
+
error: errorMessage,
|
|
144
|
+
contextConfigId: agentGraph?.contextConfigId,
|
|
145
|
+
trigger: await determineContextTrigger(tenantId, projectId, conversationId, dbClient).catch(() => 'unknown'),
|
|
146
|
+
}, 'Failed to resolve context, proceeding without context resolution');
|
|
147
|
+
// Force flush after error to ensure error telemetry is sent
|
|
148
|
+
await forceFlushTracer();
|
|
149
|
+
return null;
|
|
150
|
+
}
|
|
151
|
+
finally {
|
|
152
|
+
parentSpan.end();
|
|
153
|
+
}
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
export { handleContextResolution, determineContextTrigger, handleContextConfigChange };
|
|
157
|
+
//# sourceMappingURL=context.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context.js","sourceRoot":"","sources":["../../src/context/context.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { DatabaseClient } from '../db/client.js';
|
|
2
|
+
export interface CacheEntry {
|
|
3
|
+
contextConfigId: string;
|
|
4
|
+
contextVariableKey: string;
|
|
5
|
+
conversationId: string;
|
|
6
|
+
value: unknown;
|
|
7
|
+
requestHash?: string;
|
|
8
|
+
tenantId: string;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Context cache with request hash-based invalidation and graceful error handling.
|
|
12
|
+
*
|
|
13
|
+
* Implements conversation-scoped caching with smart cache invalidation based on
|
|
14
|
+
* request hash changes. All cache errors are treated as cache misses to ensure
|
|
15
|
+
* system reliability.
|
|
16
|
+
*/
|
|
17
|
+
export declare class ContextCache {
|
|
18
|
+
private tenantId;
|
|
19
|
+
private projectId;
|
|
20
|
+
private dbClient;
|
|
21
|
+
constructor(tenantId: string, projectId: string, dbClient: DatabaseClient);
|
|
22
|
+
/**
|
|
23
|
+
* Get cached context data for a conversation
|
|
24
|
+
*/
|
|
25
|
+
get({ conversationId, contextConfigId, contextVariableKey, requestHash, }: {
|
|
26
|
+
conversationId: string;
|
|
27
|
+
contextConfigId: string;
|
|
28
|
+
contextVariableKey: string;
|
|
29
|
+
requestHash?: string;
|
|
30
|
+
}): Promise<CacheEntry | null>;
|
|
31
|
+
/**
|
|
32
|
+
* Set cached context data for a conversation
|
|
33
|
+
*/
|
|
34
|
+
set(entry: CacheEntry): Promise<void>;
|
|
35
|
+
/**
|
|
36
|
+
* Clear cache entries for a specific conversation
|
|
37
|
+
*/
|
|
38
|
+
clearConversation(tenantId: string, projectId: string, conversationId: string): Promise<void>;
|
|
39
|
+
/**
|
|
40
|
+
* Clear all cache entries for a specific context configuration
|
|
41
|
+
*/
|
|
42
|
+
clearContextConfig(tenantId: string, projectId: string, contextConfigId: string): Promise<void>;
|
|
43
|
+
/**
|
|
44
|
+
* Clean up expired or orphaned cache entries
|
|
45
|
+
*/
|
|
46
|
+
cleanup(): Promise<void>;
|
|
47
|
+
invalidateInvocationDefinitions(tenantId: string, projectId: string, conversationId: string, contextConfigId: string, definitionIds: string[]): Promise<void>;
|
|
48
|
+
invalidateRequestContext(tenantId: string, projectId: string, conversationId: string, contextConfigId: string): Promise<void>;
|
|
49
|
+
}
|
|
50
|
+
//# sourceMappingURL=contextCache.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"contextCache.d.ts","sourceRoot":"","sources":["../../src/context/contextCache.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAajD,MAAM,WAAW,UAAU;IACzB,eAAe,EAAE,MAAM,CAAC;IACxB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,cAAc,EAAE,MAAM,CAAC;IACvB,KAAK,EAAE,OAAO,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED;;;;;;GAMG;AACH,qBAAa,YAAY;IACvB,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,QAAQ,CAAiB;gBAErB,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,cAAc;IAazE;;OAEG;IACG,GAAG,CAAC,EACR,cAAc,EACd,eAAe,EACf,kBAAkB,EAClB,WAAW,GACZ,EAAE;QACD,cAAc,EAAE,MAAM,CAAC;QACvB,eAAe,EAAE,MAAM,CAAC;QACxB,kBAAkB,EAAE,MAAM,CAAC;QAC3B,WAAW,CAAC,EAAE,MAAM,CAAC;KACtB,GAAG,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC;IAmC9B;;OAEG;IACG,GAAG,CAAC,KAAK,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;IA0C3C;;OAEG;IACG,iBAAiB,CACrB,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,MAAM,EACjB,cAAc,EAAE,MAAM,GACrB,OAAO,CAAC,IAAI,CAAC;IA0BhB;;OAEG;IACG,kBAAkB,CACtB,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,MAAM,EACjB,eAAe,EAAE,MAAM,GACtB,OAAO,CAAC,IAAI,CAAC;IA0BhB;;OAEG;IACG,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAsBxB,+BAA+B,CACnC,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,MAAM,EACjB,cAAc,EAAE,MAAM,EACtB,eAAe,EAAE,MAAM,EACvB,aAAa,EAAE,MAAM,EAAE,GACtB,OAAO,CAAC,IAAI,CAAC;IASV,wBAAwB,CAC5B,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,MAAM,EACjB,cAAc,EAAE,MAAM,EACtB,eAAe,EAAE,MAAM,GACtB,OAAO,CAAC,IAAI,CAAC;CAOjB"}
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
import { nanoid } from 'nanoid';
|
|
2
|
+
import { getLogger } from '../utils/logger.js';
|
|
3
|
+
import { clearContextConfigCache, clearConversationCache, getCacheEntry, setCacheEntry, cleanupTenantCache, invalidateInvocationDefinitionsCache, invalidateRequestContextCache, } from '../data-access/index.js';
|
|
4
|
+
const logger = getLogger('context-cache');
|
|
5
|
+
/**
|
|
6
|
+
* Context cache with request hash-based invalidation and graceful error handling.
|
|
7
|
+
*
|
|
8
|
+
* Implements conversation-scoped caching with smart cache invalidation based on
|
|
9
|
+
* request hash changes. All cache errors are treated as cache misses to ensure
|
|
10
|
+
* system reliability.
|
|
11
|
+
*/
|
|
12
|
+
export class ContextCache {
|
|
13
|
+
tenantId;
|
|
14
|
+
projectId;
|
|
15
|
+
dbClient;
|
|
16
|
+
constructor(tenantId, projectId, dbClient) {
|
|
17
|
+
this.tenantId = tenantId;
|
|
18
|
+
this.projectId = projectId;
|
|
19
|
+
this.dbClient = dbClient;
|
|
20
|
+
logger.info({
|
|
21
|
+
tenantId: this.tenantId,
|
|
22
|
+
}, 'ContextCache initialized');
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Get cached context data for a conversation
|
|
26
|
+
*/
|
|
27
|
+
async get({ conversationId, contextConfigId, contextVariableKey, requestHash, }) {
|
|
28
|
+
try {
|
|
29
|
+
const cacheEntry = await getCacheEntry(this.dbClient)({
|
|
30
|
+
conversationId,
|
|
31
|
+
contextConfigId,
|
|
32
|
+
contextVariableKey,
|
|
33
|
+
requestHash,
|
|
34
|
+
});
|
|
35
|
+
if (!cacheEntry) {
|
|
36
|
+
return null;
|
|
37
|
+
}
|
|
38
|
+
return {
|
|
39
|
+
contextConfigId: cacheEntry.contextConfigId,
|
|
40
|
+
contextVariableKey: cacheEntry.contextVariableKey,
|
|
41
|
+
conversationId: cacheEntry.conversationId,
|
|
42
|
+
value: cacheEntry.value,
|
|
43
|
+
requestHash: cacheEntry.requestHash || undefined,
|
|
44
|
+
tenantId: this.tenantId,
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
catch (error) {
|
|
48
|
+
logger.error({
|
|
49
|
+
conversationId,
|
|
50
|
+
contextConfigId,
|
|
51
|
+
contextVariableKey,
|
|
52
|
+
error: error instanceof Error ? error.message : 'Unknown error',
|
|
53
|
+
}, 'Failed to get cache entry');
|
|
54
|
+
// Graceful degradation: treat cache errors as cache misses
|
|
55
|
+
// This ensures the system continues to function even if caching fails
|
|
56
|
+
return null;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Set cached context data for a conversation
|
|
61
|
+
*/
|
|
62
|
+
async set(entry) {
|
|
63
|
+
try {
|
|
64
|
+
const cacheData = {
|
|
65
|
+
id: nanoid(),
|
|
66
|
+
tenantId: this.tenantId,
|
|
67
|
+
projectId: this.projectId,
|
|
68
|
+
conversationId: entry.conversationId,
|
|
69
|
+
contextConfigId: entry.contextConfigId,
|
|
70
|
+
contextVariableKey: entry.contextVariableKey,
|
|
71
|
+
value: entry.value,
|
|
72
|
+
requestHash: entry.requestHash,
|
|
73
|
+
fetchedAt: new Date().toISOString(),
|
|
74
|
+
fetchSource: `${entry.contextConfigId}:${entry.contextVariableKey}`,
|
|
75
|
+
fetchDurationMs: 0, // Will be updated by the resolver
|
|
76
|
+
createdAt: new Date().toISOString(),
|
|
77
|
+
updatedAt: new Date().toISOString(),
|
|
78
|
+
};
|
|
79
|
+
await setCacheEntry(this.dbClient)(cacheData);
|
|
80
|
+
logger.debug({
|
|
81
|
+
conversationId: entry.conversationId,
|
|
82
|
+
contextConfigId: entry.contextConfigId,
|
|
83
|
+
contextVariableKey: entry.contextVariableKey,
|
|
84
|
+
}, 'Cache entry set successfully');
|
|
85
|
+
}
|
|
86
|
+
catch (error) {
|
|
87
|
+
logger.error({
|
|
88
|
+
conversationId: entry.conversationId,
|
|
89
|
+
contextConfigId: entry.contextConfigId,
|
|
90
|
+
contextVariableKey: entry.contextVariableKey,
|
|
91
|
+
error: error instanceof Error ? error.message : 'Unknown error',
|
|
92
|
+
}, 'Failed to set cache entry');
|
|
93
|
+
// Don't throw - caching failures shouldn't break context resolution
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Clear cache entries for a specific conversation
|
|
98
|
+
*/
|
|
99
|
+
async clearConversation(tenantId, projectId, conversationId) {
|
|
100
|
+
try {
|
|
101
|
+
const result = await clearConversationCache(this.dbClient)({
|
|
102
|
+
scopes: { tenantId, projectId },
|
|
103
|
+
conversationId,
|
|
104
|
+
});
|
|
105
|
+
logger.info({
|
|
106
|
+
conversationId,
|
|
107
|
+
rowsCleared: result,
|
|
108
|
+
}, 'Conversation cache cleared successfully');
|
|
109
|
+
}
|
|
110
|
+
catch (error) {
|
|
111
|
+
logger.error({
|
|
112
|
+
conversationId,
|
|
113
|
+
error: error instanceof Error ? error.message : 'Unknown error',
|
|
114
|
+
}, 'Failed to clear conversation cache');
|
|
115
|
+
throw error;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Clear all cache entries for a specific context configuration
|
|
120
|
+
*/
|
|
121
|
+
async clearContextConfig(tenantId, projectId, contextConfigId) {
|
|
122
|
+
try {
|
|
123
|
+
const result = await clearContextConfigCache(this.dbClient)({
|
|
124
|
+
scopes: { tenantId, projectId },
|
|
125
|
+
contextConfigId,
|
|
126
|
+
});
|
|
127
|
+
logger.info({
|
|
128
|
+
contextConfigId,
|
|
129
|
+
rowsCleared: result,
|
|
130
|
+
}, 'Context config cache cleared successfully');
|
|
131
|
+
}
|
|
132
|
+
catch (error) {
|
|
133
|
+
logger.error({
|
|
134
|
+
contextConfigId,
|
|
135
|
+
error: error instanceof Error ? error.message : 'Unknown error',
|
|
136
|
+
}, 'Failed to clear context config cache');
|
|
137
|
+
throw error;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* Clean up expired or orphaned cache entries
|
|
142
|
+
*/
|
|
143
|
+
async cleanup() {
|
|
144
|
+
try {
|
|
145
|
+
const result = await cleanupTenantCache(this.dbClient)({
|
|
146
|
+
scopes: { tenantId: this.tenantId, projectId: this.projectId },
|
|
147
|
+
});
|
|
148
|
+
logger.info({
|
|
149
|
+
rowsCleared: result,
|
|
150
|
+
}, 'Cache cleanup completed');
|
|
151
|
+
}
|
|
152
|
+
catch (error) {
|
|
153
|
+
logger.error({
|
|
154
|
+
error: error instanceof Error ? error.message : 'Unknown error',
|
|
155
|
+
}, 'Failed to cleanup cache');
|
|
156
|
+
throw error;
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
async invalidateInvocationDefinitions(tenantId, projectId, conversationId, contextConfigId, definitionIds) {
|
|
160
|
+
await invalidateInvocationDefinitionsCache(this.dbClient)({
|
|
161
|
+
scopes: { tenantId, projectId },
|
|
162
|
+
conversationId,
|
|
163
|
+
contextConfigId,
|
|
164
|
+
invocationDefinitionIds: definitionIds,
|
|
165
|
+
});
|
|
166
|
+
}
|
|
167
|
+
async invalidateRequestContext(tenantId, projectId, conversationId, contextConfigId) {
|
|
168
|
+
await invalidateRequestContextCache(this.dbClient)({
|
|
169
|
+
scopes: { tenantId, projectId },
|
|
170
|
+
conversationId,
|
|
171
|
+
contextConfigId,
|
|
172
|
+
});
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
//# sourceMappingURL=contextCache.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"contextCache.js","sourceRoot":"","sources":["../../src/context/contextCache.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export type { ContextConfigBuilderOptions } from './ContextConfig.js';
|
|
2
|
+
export { ContextConfigBuilder, contextConfig, fetchDefinition, createRequestSchema } from './ContextConfig.js';
|
|
3
|
+
export type { FetchResult } from './ContextFetcher.js';
|
|
4
|
+
export { ContextFetcher } from './ContextFetcher.js';
|
|
5
|
+
export type { ContextResolutionOptions, ContextResolutionResult, ResolvedContext, } from './ContextResolver.js';
|
|
6
|
+
export { ContextResolver } from './ContextResolver.js';
|
|
7
|
+
export type { TemplateContext, TemplateRenderOptions, } from './TemplateEngine.js';
|
|
8
|
+
export { TemplateEngine } from './TemplateEngine.js';
|
|
9
|
+
export { ContextCache } from './contextCache.js';
|
|
10
|
+
export { handleContextResolution, handleContextConfigChange, determineContextTrigger, } from './context.js';
|
|
11
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/context/index.ts"],"names":[],"mappings":"AAEA,YAAY,EAAE,2BAA2B,EAAE,MAAM,oBAAoB,CAAC;AACtE,OAAO,EAAE,oBAAoB,EAAE,aAAa,EAAE,eAAe,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAC/G,YAAY,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AACvD,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACrD,YAAY,EACV,wBAAwB,EACxB,uBAAuB,EACvB,eAAe,GAChB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AACvD,YAAY,EACV,eAAe,EACf,qBAAqB,GACtB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACrD,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjD,OAAO,EACL,uBAAuB,EACvB,yBAAyB,EACzB,uBAAuB,GACxB,MAAM,cAAc,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
// Context system exports
|
|
2
|
+
export { ContextConfigBuilder, contextConfig, fetchDefinition, createRequestSchema } from './ContextConfig.js';
|
|
3
|
+
export { ContextFetcher } from './ContextFetcher.js';
|
|
4
|
+
export { ContextResolver } from './ContextResolver.js';
|
|
5
|
+
export { TemplateEngine } from './TemplateEngine.js';
|
|
6
|
+
export { ContextCache } from './contextCache.js';
|
|
7
|
+
export { handleContextResolution, handleContextConfigChange, determineContextTrigger, } from './context.js';
|
|
8
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/context/index.ts"],"names":[],"mappings":"AAAA,yBAAyB;AAGzB,OAAO,EAAE,oBAAoB,EAAE,aAAa,EAAE,eAAe,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAE/G,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAMrD,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAKvD,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACrD,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjD,OAAO,EACL,uBAAuB,EACvB,yBAAyB,EACzB,uBAAuB,GACxB,MAAM,cAAc,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/credential-stores/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACzE,OAAO,EAAE,uBAAuB,EAAE,MAAM,mBAAmB,CAAC;AAC5D,OAAO,EAAE,0BAA0B,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/credential-stores/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACzE,OAAO,EAAE,uBAAuB,EAAE,MAAM,mBAAmB,CAAC;AAC5D,OAAO,EAAE,0BAA0B,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC"}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import type { CredentialStore } from '../types/server.js';
|
|
2
|
+
/**
|
|
3
|
+
* KeyChainStore - Cross-platform system keychain credential storage
|
|
4
|
+
*
|
|
5
|
+
* Uses the native OS credential storage:
|
|
6
|
+
* - macOS: Keychain
|
|
7
|
+
* - Windows: Credential Vault
|
|
8
|
+
* - Linux: Secret Service API/libsecret
|
|
9
|
+
*
|
|
10
|
+
* Requires the 'keytar' npm package to be installed.
|
|
11
|
+
* Falls back gracefully if keytar is not available.
|
|
12
|
+
*
|
|
13
|
+
* ## macOS Permission Handling
|
|
14
|
+
*
|
|
15
|
+
* On macOS, when your Node.js app first calls keytar operations:
|
|
16
|
+
* - `setPassword()` creates a new Keychain item (no prompt required)
|
|
17
|
+
* - `getPassword()` may prompt the user for permission on first access
|
|
18
|
+
* - Users can click "Allow", "Always Allow", or "Deny"
|
|
19
|
+
* - If denied, keytar returns `null` which this implementation handles gracefully
|
|
20
|
+
* - The calling binary (usually `node`) will be shown in the permission prompt
|
|
21
|
+
* - For better UX in packaged apps, consider code signing and app bundling
|
|
22
|
+
*
|
|
23
|
+
* This implementation handles all permission scenarios gracefully:
|
|
24
|
+
* - Returns `null` when access is denied or credentials don't exist
|
|
25
|
+
* - Logs errors for debugging permission issues
|
|
26
|
+
* - Never throws on permission denial, only on system-level errors
|
|
27
|
+
*/
|
|
28
|
+
export declare class KeyChainStore implements CredentialStore {
|
|
29
|
+
readonly id: string;
|
|
30
|
+
readonly type = "keychain";
|
|
31
|
+
private readonly service;
|
|
32
|
+
private readonly logger;
|
|
33
|
+
private keytarAvailable;
|
|
34
|
+
private keytar;
|
|
35
|
+
private initializationPromise;
|
|
36
|
+
constructor(id: string, servicePrefix?: string);
|
|
37
|
+
/**
|
|
38
|
+
* Initialize keytar dynamically to handle optional availability
|
|
39
|
+
*/
|
|
40
|
+
private initializeKeytar;
|
|
41
|
+
/**
|
|
42
|
+
* Get a credential from the keychain
|
|
43
|
+
*/
|
|
44
|
+
get(key: string): Promise<string | null>;
|
|
45
|
+
/**
|
|
46
|
+
* Set a credential in the keychain
|
|
47
|
+
*/
|
|
48
|
+
set(key: string, value: string): Promise<void>;
|
|
49
|
+
/**
|
|
50
|
+
* Check if a credential exists in the keychain
|
|
51
|
+
*/
|
|
52
|
+
has(key: string): Promise<boolean>;
|
|
53
|
+
/**
|
|
54
|
+
* Delete a credential from the keychain
|
|
55
|
+
*/
|
|
56
|
+
delete(key: string): Promise<boolean>;
|
|
57
|
+
/**
|
|
58
|
+
* Find all credentials for this service
|
|
59
|
+
* Useful for debugging and listing stored credentials
|
|
60
|
+
*/
|
|
61
|
+
findAllCredentials(): Promise<Array<{
|
|
62
|
+
account: string;
|
|
63
|
+
password: string;
|
|
64
|
+
}>>;
|
|
65
|
+
/**
|
|
66
|
+
* Clear all credentials for this service
|
|
67
|
+
* WARNING: This will delete all credentials stored under this service
|
|
68
|
+
*/
|
|
69
|
+
clearAll(): Promise<number>;
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Factory function to create KeyChainStore
|
|
73
|
+
* Provides consistent initialization and optional configuration
|
|
74
|
+
*
|
|
75
|
+
* ## Usage Recommendations for macOS Permission Handling
|
|
76
|
+
*
|
|
77
|
+
* 1. **First-time setup**: Inform users that they may see permission prompts
|
|
78
|
+
* 2. **Error handling**: Check for `null` returns from `get()` operations
|
|
79
|
+
* 3. **User guidance**: If credentials can't be retrieved, guide users to:
|
|
80
|
+
* - Check Keychain Access app for denied permissions
|
|
81
|
+
* - Re-run the application if they accidentally clicked "Deny"
|
|
82
|
+
* 4. **Development**: Use a consistent `servicePrefix` to avoid permission prompt spam
|
|
83
|
+
* 5. **Production**: Consider code-signing your distributed app for better permission prompts
|
|
84
|
+
*
|
|
85
|
+
* Example usage with permission handling:
|
|
86
|
+
* ```typescript
|
|
87
|
+
* const store = createKeyChainStore('my-app');
|
|
88
|
+
*
|
|
89
|
+
* // Always check for null when retrieving
|
|
90
|
+
* const apiKey = await store.get('api-key');
|
|
91
|
+
* if (!apiKey) {
|
|
92
|
+
* console.log('API key not found or access denied');
|
|
93
|
+
* // Guide user to check permissions or re-enter credentials
|
|
94
|
+
* }
|
|
95
|
+
* ```
|
|
96
|
+
*/
|
|
97
|
+
export declare function createKeyChainStore(id: string, options?: {
|
|
98
|
+
servicePrefix?: string;
|
|
99
|
+
}): KeyChainStore;
|
|
100
|
+
//# sourceMappingURL=keychain-store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"keychain-store.d.ts","sourceRoot":"","sources":["../../src/credential-stores/keychain-store.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAG1D;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,qBAAa,aAAc,YAAW,eAAe;IACnD,SAAgB,EAAE,EAAE,MAAM,CAAC;IAC3B,SAAgB,IAAI,cAAc;IAClC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA8B;IACrD,OAAO,CAAC,eAAe,CAAS;IAChC,OAAO,CAAC,MAAM,CAAoB;IAClC,OAAO,CAAC,qBAAqB,CAAgB;gBAEjC,EAAE,EAAE,MAAM,EAAE,aAAa,SAA2B;IAOhE;;OAEG;YACW,gBAAgB;IA4B9B;;OAEG;IACG,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAiC9C;;OAEG;IACG,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IA+BpD;;OAEG;IACG,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAKxC;;OAEG;IACG,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAsC3C;;;OAGG;IACG,kBAAkB,IAAI,OAAO,CAAC,KAAK,CAAC;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAuBjF;;;OAGG;IACG,QAAQ,IAAI,OAAO,CAAC,MAAM,CAAC;CAwBlC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAgB,mBAAmB,CACjC,EAAE,EAAE,MAAM,EACV,OAAO,CAAC,EAAE;IACR,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB,GACA,aAAa,CAEf"}
|