@majkapp/plugin-kit 3.7.3 → 3.7.5

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/docs/AUTH.md ADDED
@@ -0,0 +1,248 @@
1
+ # Auth API
2
+
3
+ Authentication API for accessing MAJK Core Cognito credentials and making authenticated requests to AWS/MAJK services.
4
+
5
+ ## Interface
6
+
7
+ ```typescript
8
+ export interface AuthAPI {
9
+ getAccount(): Promise<SystemAccount | null>;
10
+ getAccountsOfType(type: AccountType | '*'): Promise<SystemAccount[]>;
11
+ getCredentials(options?: CredentialOptions): Promise<Credentials>;
12
+ isAuthenticated(): Promise<boolean>;
13
+ }
14
+ ```
15
+
16
+ ## Usage
17
+
18
+ Access the auth API through the function handler context:
19
+
20
+ ```typescript
21
+ .function('myFunction', {
22
+ description: 'Example function using auth',
23
+ input: { type: 'object', properties: {}, additionalProperties: false },
24
+ output: { type: 'object', properties: { result: { type: 'string' } } },
25
+ handler: async (input, ctx) => {
26
+ // Check authentication status
27
+ const isAuth = await ctx.majk.auth.isAuthenticated();
28
+
29
+ if (!isAuth) {
30
+ throw new Error('Not authenticated');
31
+ }
32
+
33
+ // Get current account
34
+ const account = await ctx.majk.auth.getAccount();
35
+
36
+ // Get credentials for AWS service calls
37
+ const credentials = await ctx.majk.auth.getCredentials();
38
+
39
+ return { result: 'success' };
40
+ }
41
+ })
42
+ ```
43
+
44
+ ## Methods
45
+
46
+ ### isAuthenticated()
47
+
48
+ Check if the user is currently authenticated with MAJK Core.
49
+
50
+ ```typescript
51
+ const isAuthenticated = await ctx.majk.auth.isAuthenticated();
52
+ if (isAuthenticated) {
53
+ // User is authenticated with Cognito
54
+ }
55
+ ```
56
+
57
+ **Returns:** `Promise<boolean>` - true if authenticated
58
+
59
+ ### getAccount()
60
+
61
+ Get the current system account (typically the Cognito account).
62
+
63
+ ```typescript
64
+ const account = await ctx.majk.auth.getAccount();
65
+ if (account) {
66
+ console.log('Account type:', account.type);
67
+ console.log('Account name:', account.name);
68
+ console.log('Expires at:', account.expiresAt);
69
+ }
70
+ ```
71
+
72
+ **Returns:** `Promise<SystemAccount | null>` - Current account or null if not authenticated
73
+
74
+ ### getAccountsOfType(type)
75
+
76
+ Get all accounts of a specific type.
77
+
78
+ ```typescript
79
+ // Get AWS Cognito accounts
80
+ const cognitoAccounts = await ctx.majk.auth.getAccountsOfType('aws-cognito');
81
+
82
+ // Get all accounts
83
+ const allAccounts = await ctx.majk.auth.getAccountsOfType('*');
84
+ ```
85
+
86
+ **Parameters:**
87
+ - `type: AccountType | '*'` - Account type filter or '*' for all
88
+
89
+ **Account Types:**
90
+ - `'aws-cognito'` - AWS Cognito accounts
91
+ - `'azure-entra'` - Azure Entra ID accounts
92
+ - `'api-key'` - API key accounts
93
+ - `'system-default'` - System default accounts
94
+
95
+ **Returns:** `Promise<SystemAccount[]>` - Array of matching accounts
96
+
97
+ ### getCredentials(options?)
98
+
99
+ Get credentials for making authenticated requests to AWS/MAJK services.
100
+
101
+ ```typescript
102
+ // Get current credentials
103
+ const creds = await ctx.majk.auth.getCredentials();
104
+
105
+ // Force refresh credentials
106
+ const freshCreds = await ctx.majk.auth.getCredentials({
107
+ forceRefresh: true
108
+ });
109
+
110
+ // Get credentials for specific purpose
111
+ const serviceCreds = await ctx.majk.auth.getCredentials({
112
+ purpose: 'bedrock-api-call'
113
+ });
114
+ ```
115
+
116
+ **Parameters:**
117
+ - `options?: CredentialOptions`
118
+ - `forceRefresh?: boolean` - Force credential refresh
119
+ - `purpose?: string` - Purpose description for logging
120
+ - `timeout?: number` - Request timeout in milliseconds
121
+
122
+ **Returns:** `Promise<Credentials>` - Credential object with tokens
123
+
124
+ ## Credential Types
125
+
126
+ ### AWS Cognito Credentials
127
+
128
+ ```typescript
129
+ interface AwsCognitoCredentials {
130
+ accountType: 'aws-cognito';
131
+ bearerToken: string; // For Authorization header
132
+ aws: {
133
+ accessKeyId: string; // For AWS SDK
134
+ secretAccessKey: string;
135
+ sessionToken: string;
136
+ region: string;
137
+ };
138
+ cognito: {
139
+ idToken: string; // Cognito identity token
140
+ accessToken: string; // Cognito access token
141
+ refreshToken: string;
142
+ };
143
+ }
144
+ ```
145
+
146
+ ## Common Patterns
147
+
148
+ ### Making AWS Service Calls
149
+
150
+ ```typescript
151
+ handler: async (input, ctx) => {
152
+ const credentials = await ctx.majk.auth.getCredentials();
153
+
154
+ if (credentials.accountType === 'aws-cognito') {
155
+ const awsCreds = credentials.aws;
156
+
157
+ // Use with AWS SDK
158
+ const client = new SomeAWSClient({
159
+ region: awsCreds.region,
160
+ credentials: {
161
+ accessKeyId: awsCreds.accessKeyId,
162
+ secretAccessKey: awsCreds.secretAccessKey,
163
+ sessionToken: awsCreds.sessionToken
164
+ }
165
+ });
166
+
167
+ return await client.someOperation();
168
+ }
169
+ }
170
+ ```
171
+
172
+ ### Making HTTP Requests to MAJK Services
173
+
174
+ ```typescript
175
+ handler: async (input, ctx) => {
176
+ const credentials = await ctx.majk.auth.getCredentials();
177
+
178
+ const response = await fetch('https://api.majkapp.com/some-endpoint', {
179
+ headers: {
180
+ 'Authorization': `Bearer ${credentials.bearerToken}`,
181
+ 'Content-Type': 'application/json'
182
+ },
183
+ method: 'POST',
184
+ body: JSON.stringify(data)
185
+ });
186
+
187
+ return await response.json();
188
+ }
189
+ ```
190
+
191
+ ### Authentication Guard
192
+
193
+ ```typescript
194
+ handler: async (input, ctx) => {
195
+ // Check auth before proceeding
196
+ if (!await ctx.majk.auth.isAuthenticated()) {
197
+ throw new Error('Authentication required');
198
+ }
199
+
200
+ const account = await ctx.majk.auth.getAccount();
201
+ if (!account || account.isExpired()) {
202
+ throw new Error('Account expired or invalid');
203
+ }
204
+
205
+ // Proceed with authenticated operation
206
+ return { success: true };
207
+ }
208
+ ```
209
+
210
+ ### Error Handling
211
+
212
+ ```typescript
213
+ handler: async (input, ctx) => {
214
+ try {
215
+ const credentials = await ctx.majk.auth.getCredentials();
216
+ // Use credentials...
217
+ } catch (error) {
218
+ ctx.logger.error('Authentication failed', {
219
+ error: error.message,
220
+ function: 'myFunction'
221
+ });
222
+
223
+ // Handle unauthenticated state
224
+ if (error.message.includes('not authenticated')) {
225
+ throw new Error('Please authenticate with MAJK Core');
226
+ }
227
+
228
+ throw error;
229
+ }
230
+ }
231
+ ```
232
+
233
+ ## Best Practices
234
+
235
+ 1. **Always check authentication** before accessing protected resources
236
+ 2. **Cache credentials** within a single function call to avoid multiple requests
237
+ 3. **Handle token expiration** gracefully with appropriate error messages
238
+ 4. **Use forceRefresh** only when necessary to avoid rate limiting
239
+ 5. **Log authentication errors** with context for debugging
240
+ 6. **Validate credential types** before using type-specific properties
241
+
242
+ ## Error Scenarios
243
+
244
+ - **Not authenticated**: `isAuthenticated()` returns false
245
+ - **No account**: `getAccount()` returns null
246
+ - **Expired credentials**: Account `isExpired()` returns true
247
+ - **Network issues**: Credential refresh may fail
248
+ - **Rate limiting**: Too many refresh requests
package/docs/BATCH.md ADDED
@@ -0,0 +1,256 @@
1
+ # Batch API
2
+
3
+ Batch processing for large sets of items with parallelism, retry logic, and progress tracking.
4
+
5
+ ## Quick Start
6
+
7
+ ```typescript
8
+ handler: async (input, ctx) => {
9
+ // Create a batch job to process files
10
+ const { job } = await ctx.majk.batch.create_batch_job({
11
+ name: 'Review TypeScript files',
12
+ input: {
13
+ source: { type: 'glob', pattern: 'src/**/*.ts' }
14
+ },
15
+ processor: {
16
+ type: 'teammate',
17
+ teammateId: 'code-reviewer',
18
+ taskTemplate: 'Review {{item}} for best practices'
19
+ },
20
+ execution: { maxParallelism: 3 },
21
+ autoStart: true
22
+ });
23
+
24
+ // Wait for completion
25
+ const result = await ctx.majk.batch.await_batch_job({ jobId: job.id });
26
+ return { processed: result.finalProgress.completedItems };
27
+ }
28
+ ```
29
+
30
+ ## API Reference
31
+
32
+ ### create_batch_job(input)
33
+
34
+ Create a new batch processing job.
35
+
36
+ ```typescript
37
+ const { job } = await ctx.majk.batch.create_batch_job({
38
+ name: string,
39
+ description?: string,
40
+ input: {
41
+ source: BatchInputSource,
42
+ transformTemplate?: string, // Transform items before processing
43
+ skipIfTemplate?: string, // Skip items matching condition
44
+ limit?: number
45
+ },
46
+ processor: BatchProcessorConfig,
47
+ execution?: BatchExecutionConfig,
48
+ tags?: string[],
49
+ metadata?: Record<string, any>,
50
+ autoStart?: boolean
51
+ });
52
+ ```
53
+
54
+ ### Input Sources
55
+
56
+ ```typescript
57
+ // List of items
58
+ { type: 'list', items: ['item1', 'item2', 'item3'] }
59
+
60
+ // Directory scan
61
+ { type: 'directory', path: 'src/', recursive: true, extensions: ['.ts', '.js'] }
62
+
63
+ // Glob pattern
64
+ { type: 'glob', pattern: 'src/**/*.ts', basePath: '.', ignore: ['node_modules'] }
65
+ ```
66
+
67
+ ### Processor Types
68
+
69
+ ```typescript
70
+ // Delegate to teammate
71
+ { type: 'teammate', teammateId: 'code-reviewer', taskTemplate: 'Review {{item}}', witness: {...} }
72
+
73
+ // Call RPC function
74
+ { type: 'rpc', pluginId: 'my-plugin', serviceName: 'analyzer', functionName: 'analyze', input: { file: '{{item}}' } }
75
+
76
+ // Run witness check
77
+ { type: 'witness', witness: { bash: 'eslint {{item}}' } }
78
+
79
+ // Execute script
80
+ { type: 'script', code: 'return processItem(item)', timeoutMs: 5000 }
81
+ ```
82
+
83
+ ### Execution Config
84
+
85
+ ```typescript
86
+ execution: {
87
+ maxParallelism: 5, // Concurrent items
88
+ itemTimeoutMs: 60000, // Per-item timeout
89
+ jobTimeoutMs: 3600000, // Total job timeout
90
+ retry: {
91
+ maxAttempts: 3,
92
+ backoff: 'exponential', // 'none' | 'fixed' | 'linear' | 'exponential'
93
+ initialDelayMs: 1000,
94
+ maxDelayMs: 30000,
95
+ jitter: true
96
+ }
97
+ }
98
+ ```
99
+
100
+ ### start_batch_job(input)
101
+
102
+ Start a pending batch job.
103
+
104
+ ```typescript
105
+ const { job } = await ctx.majk.batch.start_batch_job({ jobId: string });
106
+ ```
107
+
108
+ ### pause_batch_job(input)
109
+
110
+ Pause a running job.
111
+
112
+ ```typescript
113
+ const { job } = await ctx.majk.batch.pause_batch_job({ jobId: string, reason?: string });
114
+ ```
115
+
116
+ ### resume_batch_job(input)
117
+
118
+ Resume a paused job.
119
+
120
+ ```typescript
121
+ const { job } = await ctx.majk.batch.resume_batch_job({ jobId: string });
122
+ ```
123
+
124
+ ### cancel_batch_job(input)
125
+
126
+ Cancel a job.
127
+
128
+ ```typescript
129
+ const { job } = await ctx.majk.batch.cancel_batch_job({ jobId: string });
130
+ ```
131
+
132
+ ### check_batch_job(input)
133
+
134
+ Get current status and progress.
135
+
136
+ ```typescript
137
+ const result = await ctx.majk.batch.check_batch_job({
138
+ jobId: string,
139
+ includeFailedItems?: boolean,
140
+ failedItemsLimit?: number
141
+ });
142
+ // Returns: { job, progress: { totalItems, completedItems, failedItems, ... }, failedItems? }
143
+ ```
144
+
145
+ ### await_batch_job(input)
146
+
147
+ Wait for job completion.
148
+
149
+ ```typescript
150
+ const result = await ctx.majk.batch.await_batch_job({
151
+ jobId: string,
152
+ timeoutMs?: number,
153
+ ignoreBlockers?: boolean
154
+ });
155
+ // Returns: { job, finalProgress, resultSummary?, hasBlockers?, blockedCount? }
156
+ ```
157
+
158
+ ### list_batch_jobs(input?)
159
+
160
+ List jobs with filters.
161
+
162
+ ```typescript
163
+ const { jobs, total, hasMore } = await ctx.majk.batch.list_batch_jobs({
164
+ status?: BatchJobStatus | BatchJobStatus[],
165
+ tags?: string[],
166
+ limit?: number,
167
+ offset?: number
168
+ });
169
+ ```
170
+
171
+ ### get_batch_job_items(input)
172
+
173
+ Get items from a job.
174
+
175
+ ```typescript
176
+ const { items, total, hasMore } = await ctx.majk.batch.get_batch_job_items({
177
+ jobId: string,
178
+ status?: BatchItemStatus | BatchItemStatus[],
179
+ limit?: number,
180
+ offset?: number
181
+ });
182
+ ```
183
+
184
+ ### replay_failed_batch_items(input)
185
+
186
+ Create new job to retry failed items.
187
+
188
+ ```typescript
189
+ const { job } = await ctx.majk.batch.replay_failed_batch_items({ jobId: string });
190
+ ```
191
+
192
+ ### clone_batch_job(input)
193
+
194
+ Clone a job configuration.
195
+
196
+ ```typescript
197
+ const { job } = await ctx.majk.batch.clone_batch_job({
198
+ jobId: string,
199
+ name?: string,
200
+ tags?: string[]
201
+ });
202
+ ```
203
+
204
+ ## Common Patterns
205
+
206
+ ### Process Files with Progress
207
+
208
+ ```typescript
209
+ const { job } = await ctx.majk.batch.create_batch_job({
210
+ name: 'Analyze codebase',
211
+ input: { source: { type: 'glob', pattern: '**/*.ts' } },
212
+ processor: { type: 'rpc', pluginId: 'analyzer', functionName: 'analyze' },
213
+ autoStart: true
214
+ });
215
+
216
+ // Poll for progress
217
+ let status;
218
+ do {
219
+ await new Promise(r => setTimeout(r, 5000));
220
+ status = await ctx.majk.batch.check_batch_job({ jobId: job.id });
221
+ ctx.logger.info(`Progress: ${status.progress.completedItems}/${status.progress.totalItems}`);
222
+ } while (status.job.status === 'running');
223
+ ```
224
+
225
+ ### Handle Failures
226
+
227
+ ```typescript
228
+ const result = await ctx.majk.batch.await_batch_job({ jobId: job.id });
229
+
230
+ if (result.finalProgress.failedItems > 0) {
231
+ const { items } = await ctx.majk.batch.get_batch_job_items({
232
+ jobId: job.id,
233
+ status: 'failed'
234
+ });
235
+
236
+ for (const item of items) {
237
+ ctx.logger.error(`Failed: ${item.data}`, { error: item.error });
238
+ }
239
+
240
+ // Retry failed items
241
+ await ctx.majk.batch.replay_failed_batch_items({ jobId: job.id });
242
+ }
243
+ ```
244
+
245
+ ## Best Practices
246
+
247
+ 1. **Set appropriate parallelism** - Balance throughput vs resource usage
248
+ 2. **Use retry with backoff** - Handle transient failures gracefully
249
+ 3. **Monitor progress** - Check status periodically for long jobs
250
+ 4. **Handle partial failures** - Use replay for failed items
251
+ 5. **Tag jobs** - Organize and filter jobs by purpose
252
+
253
+ ## Next Steps
254
+
255
+ Run `npx @majkapp/plugin-kit --delegation` - Task delegation API
256
+ Run `npx @majkapp/plugin-kit --scripting` - Script execution API
@@ -0,0 +1,206 @@
1
+ # Config API
2
+
3
+ Access MAJK configuration using path-based dot notation.
4
+
5
+ ## Quick Start
6
+
7
+ ```typescript
8
+ handler: async (input, ctx) => {
9
+ // Get config value
10
+ const region = ctx.majk.config.get('aws.region', 'us-east-1');
11
+
12
+ // Check if config exists
13
+ if (ctx.majk.config.has('bedrock.models.claude')) {
14
+ const model = ctx.majk.config.get('bedrock.models.claude');
15
+ }
16
+
17
+ // Discover available keys
18
+ const awsKeys = ctx.majk.config.keys('aws');
19
+
20
+ return { region, awsKeys };
21
+ }
22
+ ```
23
+
24
+ ## API Reference
25
+
26
+ ### get<T>(path, defaultValue?)
27
+
28
+ Get a configuration value by path.
29
+
30
+ ```typescript
31
+ // Simple get
32
+ const region = ctx.majk.config.get('aws.region');
33
+
34
+ // With default value
35
+ const timeout = ctx.majk.config.get('plugins.timeout', 30000);
36
+
37
+ // Type-safe get
38
+ interface BedrockConfig {
39
+ models: string[];
40
+ region: string;
41
+ }
42
+ const bedrock = ctx.majk.config.get<BedrockConfig>('bedrock');
43
+
44
+ // Get entire section
45
+ const awsConfig = ctx.majk.config.get('aws');
46
+ ```
47
+
48
+ ### has(path)
49
+
50
+ Check if a configuration path exists.
51
+
52
+ ```typescript
53
+ if (ctx.majk.config.has('aws.pluginMarket.apiEndpoint')) {
54
+ // Plugin market is configured
55
+ }
56
+
57
+ // Feature detection
58
+ if (ctx.majk.config.has('experimental.newFeature')) {
59
+ // Enable experimental feature
60
+ }
61
+ ```
62
+
63
+ ### keys(path?)
64
+
65
+ Get all keys under a path.
66
+
67
+ ```typescript
68
+ // Top-level namespaces
69
+ const namespaces = ctx.majk.config.keys();
70
+ // ['aws', 'auth', 'bedrock', 'litellm', 'plugins']
71
+
72
+ // Keys under aws
73
+ const awsKeys = ctx.majk.config.keys('aws');
74
+ // ['pluginMarket', 'telemetry', 'region', ...]
75
+
76
+ // Nested keys
77
+ const marketKeys = ctx.majk.config.keys('aws.pluginMarket');
78
+ // ['apiEndpoint', 'region', 'enabled']
79
+ ```
80
+
81
+ ### getAll()
82
+
83
+ Get the entire configuration object.
84
+
85
+ ```typescript
86
+ // For debugging only - prefer specific get() calls
87
+ const allConfig = ctx.majk.config.getAll();
88
+ console.log('Full config:', JSON.stringify(allConfig, null, 2));
89
+ ```
90
+
91
+ ## Configuration Namespaces
92
+
93
+ ### aws.*
94
+
95
+ AWS resources and services.
96
+
97
+ ```typescript
98
+ ctx.majk.config.get('aws.region');
99
+ ctx.majk.config.get('aws.pluginMarket.apiEndpoint');
100
+ ctx.majk.config.get('aws.telemetry.enabled');
101
+ ctx.majk.config.get('aws.tokenUsage.tableName');
102
+ ```
103
+
104
+ ### auth.*
105
+
106
+ Authentication configuration.
107
+
108
+ ```typescript
109
+ ctx.majk.config.get('auth.cognito.userPoolId');
110
+ ctx.majk.config.get('auth.cognito.clientId');
111
+ ctx.majk.config.get('auth.cognito.region');
112
+ ```
113
+
114
+ ### bedrock.*
115
+
116
+ Bedrock AI model settings.
117
+
118
+ ```typescript
119
+ ctx.majk.config.get('bedrock.region');
120
+ ctx.majk.config.get('bedrock.models');
121
+ ctx.majk.config.get('bedrock.defaultModel');
122
+ ```
123
+
124
+ ### litellm.*
125
+
126
+ LiteLLM proxy configuration.
127
+
128
+ ```typescript
129
+ ctx.majk.config.get('litellm.apiBase');
130
+ ctx.majk.config.get('litellm.apiKey');
131
+ ctx.majk.config.get('litellm.models');
132
+ ```
133
+
134
+ ### plugins.*
135
+
136
+ Plugin system configuration.
137
+
138
+ ```typescript
139
+ ctx.majk.config.get('plugins.directory');
140
+ ctx.majk.config.get('plugins.autoStart');
141
+ ctx.majk.config.get('plugins.hotReload');
142
+ ```
143
+
144
+ ## Common Patterns
145
+
146
+ ### Safe Config Access
147
+
148
+ ```typescript
149
+ function getAwsConfig() {
150
+ const region = ctx.majk.config.get('aws.region');
151
+ if (!region) {
152
+ throw new Error('AWS region not configured');
153
+ }
154
+
155
+ return {
156
+ region,
157
+ endpoint: ctx.majk.config.get('aws.pluginMarket.apiEndpoint'),
158
+ enabled: ctx.majk.config.get('aws.pluginMarket.enabled', false)
159
+ };
160
+ }
161
+ ```
162
+
163
+ ### Feature Flags
164
+
165
+ ```typescript
166
+ function isFeatureEnabled(feature: string): boolean {
167
+ return ctx.majk.config.get(`features.${feature}`, false);
168
+ }
169
+
170
+ if (isFeatureEnabled('newUI')) {
171
+ // Use new UI
172
+ }
173
+ ```
174
+
175
+ ### Dynamic Configuration
176
+
177
+ ```typescript
178
+ // Build config object from keys
179
+ const awsKeys = ctx.majk.config.keys('aws');
180
+ const awsConfig = {};
181
+
182
+ for (const key of awsKeys) {
183
+ awsConfig[key] = ctx.majk.config.get(`aws.${key}`);
184
+ }
185
+ ```
186
+
187
+ ### Environment-Specific Config
188
+
189
+ ```typescript
190
+ const env = ctx.majk.config.get('environment', 'development');
191
+ const apiUrl = ctx.majk.config.get(`api.${env}.url`);
192
+ const timeout = ctx.majk.config.get(`api.${env}.timeout`, 5000);
193
+ ```
194
+
195
+ ## Best Practices
196
+
197
+ 1. **Use defaults** - Always provide sensible defaults
198
+ 2. **Check existence** - Use `has()` before optional configs
199
+ 3. **Type assertions** - Use generics for type safety
200
+ 4. **Avoid getAll()** - Use specific paths for better performance
201
+ 5. **Consistent paths** - Follow dot notation conventions
202
+
203
+ ## Next Steps
204
+
205
+ Run `npx @majkapp/plugin-kit --secrets` - Secrets management
206
+ Run `npx @majkapp/plugin-kit --auth` - Authentication API