@girardmedia/bootspring 1.2.0 → 2.0.3
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/README.md +107 -14
- package/bin/bootspring.js +166 -27
- package/cli/agent.js +189 -17
- package/cli/analyze.js +499 -0
- package/cli/audit.js +557 -0
- package/cli/auth.js +495 -38
- package/cli/billing.js +302 -0
- package/cli/build.js +695 -0
- package/cli/business.js +109 -26
- package/cli/checkpoint-utils.js +168 -0
- package/cli/checkpoint.js +639 -0
- package/cli/cloud-sync.js +447 -0
- package/cli/content.js +198 -0
- package/cli/context.js +1 -1
- package/cli/deploy.js +543 -0
- package/cli/fundraise.js +112 -50
- package/cli/github-cmd.js +435 -0
- package/cli/health.js +477 -0
- package/cli/init.js +84 -13
- package/cli/legal.js +107 -95
- package/cli/log.js +2 -2
- package/cli/loop.js +976 -73
- package/cli/manager.js +711 -0
- package/cli/metrics.js +480 -0
- package/cli/monitor.js +812 -0
- package/cli/onboard.js +521 -0
- package/cli/orchestrator.js +12 -24
- package/cli/prd.js +594 -0
- package/cli/preseed-start.js +1483 -0
- package/cli/preseed.js +2302 -0
- package/cli/project.js +436 -0
- package/cli/quality.js +233 -0
- package/cli/security.js +913 -0
- package/cli/seed.js +1441 -5
- package/cli/skill.js +273 -211
- package/cli/suggest.js +989 -0
- package/cli/switch.js +453 -0
- package/cli/visualize.js +527 -0
- package/cli/watch.js +769 -0
- package/cli/workspace.js +607 -0
- package/core/analyze-workflow.js +1134 -0
- package/core/api-client.js +535 -22
- package/core/audit-workflow.js +1350 -0
- package/core/build-orchestrator.js +480 -0
- package/core/build-state.js +577 -0
- package/core/checkpoint-engine.js +408 -0
- package/core/config.js +1109 -26
- package/core/context-loader.js +21 -1
- package/core/deploy-workflow.js +836 -0
- package/core/entitlements.js +93 -22
- package/core/github-sync.js +610 -0
- package/core/index.js +8 -1
- package/core/ingest.js +1111 -0
- package/core/metrics-engine.js +768 -0
- package/core/onboard-workflow.js +1007 -0
- package/core/preseed-workflow.js +934 -0
- package/core/preseed.js +1617 -0
- package/core/project-context.js +325 -0
- package/core/project-state.js +694 -0
- package/core/r2-sync.js +583 -0
- package/core/scaffold.js +525 -7
- package/core/session.js +258 -0
- package/core/task-extractor.js +758 -0
- package/core/telemetry.js +28 -6
- package/core/tier-enforcement.js +737 -0
- package/core/utils.js +38 -14
- package/generators/questionnaire.js +15 -12
- package/generators/sections/ai.js +7 -7
- package/generators/sections/content.js +300 -0
- package/generators/sections/index.js +3 -0
- package/generators/sections/plugins.js +7 -6
- package/generators/templates/build-planning.template.js +596 -0
- package/generators/templates/content.template.js +819 -0
- package/generators/templates/index.js +2 -1
- package/hooks/git-autopilot.js +1250 -0
- package/hooks/index.js +9 -0
- package/intelligence/agent-collab.js +2057 -0
- package/intelligence/auto-suggest.js +634 -0
- package/intelligence/content-gen.js +1589 -0
- package/intelligence/cross-project.js +1647 -0
- package/intelligence/index.js +184 -0
- package/intelligence/learning/insights.json +517 -7
- package/intelligence/learning/pattern-learner.js +1008 -14
- package/intelligence/memory/decision-tracker.js +1431 -31
- package/intelligence/memory/decisions.jsonl +0 -0
- package/intelligence/orchestrator.js +2896 -1
- package/intelligence/prd.js +92 -1
- package/intelligence/recommendation-weights.json +14 -2
- package/intelligence/recommendations.js +463 -9
- package/intelligence/workflow-composer.js +1451 -0
- package/marketplace/index.d.ts +324 -0
- package/marketplace/index.js +1921 -0
- package/mcp/contracts/mcp-contract.v1.json +342 -4
- package/mcp/registry.js +680 -3
- package/mcp/response-formatter.js +23 -0
- package/mcp/tools/assist-tool.js +78 -4
- package/mcp/tools/autopilot-tool.js +408 -0
- package/mcp/tools/content-tool.js +571 -0
- package/mcp/tools/dashboard-tool.js +251 -5
- package/mcp/tools/mvp-tool.js +344 -0
- package/mcp/tools/plugin-tool.js +23 -1
- package/mcp/tools/prd-tool.js +579 -0
- package/mcp/tools/seed-tool.js +447 -0
- package/mcp/tools/skill-tool.js +43 -14
- package/mcp/tools/suggest-tool.js +147 -0
- package/package.json +15 -6
- package/agents/README.md +0 -93
- package/agents/ai-integration-expert/context.md +0 -386
- package/agents/api-expert/context.md +0 -416
- package/agents/architecture-expert/context.md +0 -454
- package/agents/auth-expert/context.md +0 -399
- package/agents/backend-expert/context.md +0 -483
- package/agents/business-strategy-expert/context.md +0 -180
- package/agents/code-review-expert/context.md +0 -365
- package/agents/competitive-analysis-expert/context.md +0 -239
- package/agents/data-modeling-expert/context.md +0 -352
- package/agents/database-expert/context.md +0 -250
- package/agents/devops-expert/context.md +0 -446
- package/agents/email-expert/context.md +0 -379
- package/agents/financial-expert/context.md +0 -213
- package/agents/frontend-expert/context.md +0 -364
- package/agents/fundraising-expert/context.md +0 -257
- package/agents/growth-expert/context.md +0 -249
- package/agents/index.js +0 -140
- package/agents/investor-relations-expert/context.md +0 -266
- package/agents/legal-expert/context.md +0 -284
- package/agents/marketing-expert/context.md +0 -236
- package/agents/monitoring-expert/context.md +0 -362
- package/agents/operations-expert/context.md +0 -279
- package/agents/partnerships-expert/context.md +0 -286
- package/agents/payment-expert/context.md +0 -340
- package/agents/performance-expert/context.md +0 -377
- package/agents/private-equity-expert/context.md +0 -246
- package/agents/railway-expert/context.md +0 -284
- package/agents/research-expert/context.md +0 -245
- package/agents/sales-expert/context.md +0 -241
- package/agents/security-expert/context.md +0 -343
- package/agents/testing-expert/context.md +0 -414
- package/agents/ui-ux-expert/context.md +0 -448
- package/agents/vercel-expert/context.md +0 -426
- package/skills/index.js +0 -787
- package/skills/patterns/README.md +0 -163
- package/skills/patterns/ai/agents.md +0 -281
- package/skills/patterns/ai/claude.md +0 -138
- package/skills/patterns/ai/embeddings.md +0 -150
- package/skills/patterns/ai/rag.md +0 -266
- package/skills/patterns/ai/streaming.md +0 -170
- package/skills/patterns/ai/structured-output.md +0 -162
- package/skills/patterns/ai/tools.md +0 -154
- package/skills/patterns/analytics/tracking.md +0 -220
- package/skills/patterns/api/errors.md +0 -296
- package/skills/patterns/api/graphql.md +0 -440
- package/skills/patterns/api/middleware.md +0 -279
- package/skills/patterns/api/openapi.md +0 -285
- package/skills/patterns/api/rate-limiting.md +0 -231
- package/skills/patterns/api/route-handler.md +0 -217
- package/skills/patterns/api/server-action.md +0 -249
- package/skills/patterns/api/versioning.md +0 -443
- package/skills/patterns/api/webhooks.md +0 -247
- package/skills/patterns/auth/clerk.md +0 -132
- package/skills/patterns/auth/mfa.md +0 -313
- package/skills/patterns/auth/nextauth.md +0 -140
- package/skills/patterns/auth/oauth.md +0 -237
- package/skills/patterns/auth/rbac.md +0 -152
- package/skills/patterns/auth/session-management.md +0 -367
- package/skills/patterns/auth/session.md +0 -120
- package/skills/patterns/database/audit.md +0 -177
- package/skills/patterns/database/migrations.md +0 -177
- package/skills/patterns/database/pagination.md +0 -230
- package/skills/patterns/database/pooling.md +0 -357
- package/skills/patterns/database/prisma.md +0 -180
- package/skills/patterns/database/relations.md +0 -187
- package/skills/patterns/database/seeding.md +0 -246
- package/skills/patterns/database/soft-delete.md +0 -153
- package/skills/patterns/database/transactions.md +0 -162
- package/skills/patterns/deployment/ci-cd.md +0 -231
- package/skills/patterns/deployment/docker.md +0 -188
- package/skills/patterns/deployment/monitoring.md +0 -387
- package/skills/patterns/deployment/vercel.md +0 -160
- package/skills/patterns/email/resend.md +0 -143
- package/skills/patterns/email/templates.md +0 -245
- package/skills/patterns/email/transactional.md +0 -503
- package/skills/patterns/email/verification.md +0 -176
- package/skills/patterns/files/download.md +0 -243
- package/skills/patterns/files/upload.md +0 -239
- package/skills/patterns/i18n/nextintl.md +0 -188
- package/skills/patterns/logging/structured.md +0 -292
- package/skills/patterns/notifications/email-queue.md +0 -248
- package/skills/patterns/notifications/push.md +0 -279
- package/skills/patterns/payments/checkout.md +0 -303
- package/skills/patterns/payments/invoices.md +0 -287
- package/skills/patterns/payments/portal.md +0 -245
- package/skills/patterns/payments/stripe.md +0 -272
- package/skills/patterns/payments/subscriptions.md +0 -300
- package/skills/patterns/payments/usage.md +0 -279
- package/skills/patterns/performance/caching.md +0 -276
- package/skills/patterns/performance/code-splitting.md +0 -233
- package/skills/patterns/performance/edge.md +0 -254
- package/skills/patterns/performance/isr.md +0 -266
- package/skills/patterns/performance/lazy-loading.md +0 -281
- package/skills/patterns/realtime/sse.md +0 -327
- package/skills/patterns/realtime/websockets.md +0 -336
- package/skills/patterns/search/filtering.md +0 -329
- package/skills/patterns/search/fulltext.md +0 -260
- package/skills/patterns/security/audit-logging.md +0 -444
- package/skills/patterns/security/csrf.md +0 -234
- package/skills/patterns/security/headers.md +0 -252
- package/skills/patterns/security/sanitization.md +0 -258
- package/skills/patterns/security/secrets.md +0 -261
- package/skills/patterns/security/validation.md +0 -268
- package/skills/patterns/security/xss.md +0 -229
- package/skills/patterns/seo/metadata.md +0 -252
- package/skills/patterns/state/context.md +0 -349
- package/skills/patterns/state/react-query.md +0 -313
- package/skills/patterns/state/url-state.md +0 -482
- package/skills/patterns/state/zustand.md +0 -262
- package/skills/patterns/testing/api.md +0 -259
- package/skills/patterns/testing/component.md +0 -233
- package/skills/patterns/testing/coverage.md +0 -207
- package/skills/patterns/testing/fixtures.md +0 -225
- package/skills/patterns/testing/integration.md +0 -436
- package/skills/patterns/testing/mocking.md +0 -177
- package/skills/patterns/testing/playwright.md +0 -162
- package/skills/patterns/testing/snapshot.md +0 -175
- package/skills/patterns/testing/vitest.md +0 -307
- package/skills/patterns/ui/accordions.md +0 -395
- package/skills/patterns/ui/cards.md +0 -299
- package/skills/patterns/ui/dropdowns.md +0 -476
- package/skills/patterns/ui/empty-states.md +0 -320
- package/skills/patterns/ui/forms.md +0 -405
- package/skills/patterns/ui/inputs.md +0 -319
- package/skills/patterns/ui/layouts.md +0 -282
- package/skills/patterns/ui/loading.md +0 -291
- package/skills/patterns/ui/modals.md +0 -338
- package/skills/patterns/ui/navigation.md +0 -374
- package/skills/patterns/ui/tables.md +0 -407
- package/skills/patterns/ui/toasts.md +0 -300
- package/skills/patterns/ui/tooltips.md +0 -396
- package/skills/patterns/utils/dates.md +0 -435
- package/skills/patterns/utils/errors.md +0 -451
- package/skills/patterns/utils/formatting.md +0 -345
- package/skills/patterns/utils/validation.md +0 -434
- package/templates/bootspring.config.js +0 -83
- package/templates/business/business-model-canvas.md +0 -246
- package/templates/business/business-plan.md +0 -266
- package/templates/business/competitive-analysis.md +0 -312
- package/templates/fundraising/data-room-checklist.md +0 -300
- package/templates/fundraising/investor-research.md +0 -243
- package/templates/fundraising/pitch-deck-outline.md +0 -253
- package/templates/legal/gdpr-checklist.md +0 -339
- package/templates/legal/privacy-policy.md +0 -285
- package/templates/legal/terms-of-service.md +0 -222
- package/templates/mcp.json +0 -9
package/mcp/registry.js
CHANGED
|
@@ -15,12 +15,54 @@ const intelligence = require('../intelligence');
|
|
|
15
15
|
const gitMemory = require('../intelligence/git-memory');
|
|
16
16
|
const prdModule = require('../intelligence/prd');
|
|
17
17
|
const quality = require('../quality');
|
|
18
|
-
const skills = require('../skills');
|
|
19
18
|
const entitlements = require('../core/entitlements');
|
|
19
|
+
|
|
20
|
+
// Thin client: skills module may not exist locally
|
|
21
|
+
// Skills are now served from the API
|
|
22
|
+
let skills;
|
|
23
|
+
try {
|
|
24
|
+
skills = require('../skills');
|
|
25
|
+
} catch {
|
|
26
|
+
// Stub for thin client - skills fetched from API
|
|
27
|
+
skills = {
|
|
28
|
+
listSkills: () => [],
|
|
29
|
+
getSkillMetadata: () => null,
|
|
30
|
+
loadSkill: () => null,
|
|
31
|
+
searchSkills: () => [],
|
|
32
|
+
getCategories: () => [],
|
|
33
|
+
hasExternalSkillLibrary: () => false
|
|
34
|
+
};
|
|
35
|
+
}
|
|
20
36
|
const telemetry = require('../core/telemetry');
|
|
21
37
|
const capabilities = require('./capabilities');
|
|
22
38
|
const format = require('./response-formatter');
|
|
23
39
|
|
|
40
|
+
// Seed system modules (lazy loaded)
|
|
41
|
+
let seedModule = null;
|
|
42
|
+
let ingestModule = null;
|
|
43
|
+
let scaffoldModule = null;
|
|
44
|
+
let mvpModule = null;
|
|
45
|
+
|
|
46
|
+
function getSeedModule() {
|
|
47
|
+
if (!seedModule) seedModule = require('../cli/seed');
|
|
48
|
+
return seedModule;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function getIngestModule() {
|
|
52
|
+
if (!ingestModule) ingestModule = require('../core/ingest');
|
|
53
|
+
return ingestModule;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function getScaffoldModule() {
|
|
57
|
+
if (!scaffoldModule) scaffoldModule = require('../core/scaffold');
|
|
58
|
+
return scaffoldModule;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function getMvpModule() {
|
|
62
|
+
if (!mvpModule) mvpModule = require('../core/mvp');
|
|
63
|
+
return mvpModule;
|
|
64
|
+
}
|
|
65
|
+
|
|
24
66
|
const agentTool = require('./tools/agent-tool');
|
|
25
67
|
const assistTool = require('./tools/assist-tool');
|
|
26
68
|
const capabilitiesTool = require('./tools/capabilities-tool');
|
|
@@ -35,6 +77,12 @@ const qualityTool = require('./tools/quality-tool');
|
|
|
35
77
|
const skillTool = require('./tools/skill-tool');
|
|
36
78
|
const telemetryTool = require('./tools/telemetry-tool');
|
|
37
79
|
const todoTool = require('./tools/todo-tool');
|
|
80
|
+
const seedTool = require('./tools/seed-tool');
|
|
81
|
+
const mvpTool = require('./tools/mvp-tool');
|
|
82
|
+
const prdTool = require('./tools/prd-tool');
|
|
83
|
+
const autopilotTool = require('./tools/autopilot-tool');
|
|
84
|
+
const contentTool = require('./tools/content-tool');
|
|
85
|
+
const suggestTool = require('./tools/suggest-tool');
|
|
38
86
|
|
|
39
87
|
// Natural language and context detection
|
|
40
88
|
const natural = require('../natural');
|
|
@@ -69,7 +117,13 @@ const TOOLS = [
|
|
|
69
117
|
telemetryTool.getToolDefinition(),
|
|
70
118
|
orchestratorTool.getToolDefinition(),
|
|
71
119
|
loopTool.getToolDefinition(),
|
|
72
|
-
memoryTool.getToolDefinition()
|
|
120
|
+
memoryTool.getToolDefinition(),
|
|
121
|
+
seedTool.getToolDefinition(),
|
|
122
|
+
mvpTool.getToolDefinition(),
|
|
123
|
+
prdTool.getToolDefinition(),
|
|
124
|
+
autopilotTool.getToolDefinition(),
|
|
125
|
+
contentTool.getToolDefinition(),
|
|
126
|
+
suggestTool.getToolDefinition()
|
|
73
127
|
];
|
|
74
128
|
|
|
75
129
|
const RESOURCES = [
|
|
@@ -96,6 +150,36 @@ const RESOURCES = [
|
|
|
96
150
|
name: 'Agent List',
|
|
97
151
|
description: 'Available specialized agents',
|
|
98
152
|
mimeType: 'application/json'
|
|
153
|
+
},
|
|
154
|
+
{
|
|
155
|
+
uri: 'bootspring://workflow/status',
|
|
156
|
+
name: 'Workflow Status',
|
|
157
|
+
description: 'Current active workflow status and progress',
|
|
158
|
+
mimeType: 'application/json'
|
|
159
|
+
},
|
|
160
|
+
{
|
|
161
|
+
uri: 'bootspring://skills/catalog',
|
|
162
|
+
name: 'Skills Catalog',
|
|
163
|
+
description: 'Available skills and patterns catalog',
|
|
164
|
+
mimeType: 'application/json'
|
|
165
|
+
},
|
|
166
|
+
{
|
|
167
|
+
uri: 'bootspring://memory/recent',
|
|
168
|
+
name: 'Recent Memory',
|
|
169
|
+
description: 'Recent decisions and learning insights',
|
|
170
|
+
mimeType: 'application/json'
|
|
171
|
+
},
|
|
172
|
+
{
|
|
173
|
+
uri: 'bootspring://autopilot/status',
|
|
174
|
+
name: 'Git Autopilot Status',
|
|
175
|
+
description: 'Git autopilot status and pending workflow suggestions',
|
|
176
|
+
mimeType: 'application/json'
|
|
177
|
+
},
|
|
178
|
+
{
|
|
179
|
+
uri: 'bootspring://content/templates',
|
|
180
|
+
name: 'Content Templates',
|
|
181
|
+
description: 'Available document templates for content generation',
|
|
182
|
+
mimeType: 'application/json'
|
|
99
183
|
}
|
|
100
184
|
];
|
|
101
185
|
|
|
@@ -152,6 +236,53 @@ const toolHandlers = {
|
|
|
152
236
|
}),
|
|
153
237
|
bootspring_memory: memoryTool.createHandler({ gitMemory }),
|
|
154
238
|
bootspring_telemetry: telemetryTool.createHandler({ telemetry }),
|
|
239
|
+
bootspring_seed: seedTool.createHandler({
|
|
240
|
+
seedModule: { run: (args) => getSeedModule().run(args) },
|
|
241
|
+
ingestModule: {
|
|
242
|
+
ingestAll: (root) => getIngestModule().ingestAll(root),
|
|
243
|
+
generateDocuments: (ingested, seedConfig, root) => getIngestModule().generateDocuments(ingested, seedConfig, root),
|
|
244
|
+
updateContextIndex: (root, ingested) => getIngestModule().updateContextIndex(root, ingested),
|
|
245
|
+
ingestPRD: (root) => getIngestModule().ingestPRD(root)
|
|
246
|
+
},
|
|
247
|
+
scaffoldModule: {
|
|
248
|
+
getPresets: () => getScaffoldModule().getPresets(),
|
|
249
|
+
getPresetConfig: (preset) => getScaffoldModule().getPresetConfig(preset),
|
|
250
|
+
getPresetInfo: (preset) => getScaffoldModule().getPresetInfo(preset),
|
|
251
|
+
planScaffold: (cfg, root) => getScaffoldModule().planScaffold(cfg, root),
|
|
252
|
+
execute: (plan, root) => getScaffoldModule().execute(plan, root)
|
|
253
|
+
},
|
|
254
|
+
config,
|
|
255
|
+
format
|
|
256
|
+
}),
|
|
257
|
+
bootspring_mvp: mvpTool.createHandler({
|
|
258
|
+
mvpModule: {
|
|
259
|
+
MVP_STRUCTURE: { source: '.bootspring/inputs/mvp/source', references: '.bootspring/references' },
|
|
260
|
+
initMvpFolders: () => getMvpModule().initMvpFolders(),
|
|
261
|
+
analyzeMvp: () => getMvpModule().analyzeMvp(),
|
|
262
|
+
importMvp: (opts) => getMvpModule().importMvp(opts),
|
|
263
|
+
CODE_ISSUES: getMvpModule().CODE_ISSUES || {}
|
|
264
|
+
},
|
|
265
|
+
config,
|
|
266
|
+
format
|
|
267
|
+
}),
|
|
268
|
+
bootspring_prd: prdTool.createHandler({
|
|
269
|
+
ingestModule: {
|
|
270
|
+
ingestPRD: (root) => getIngestModule().ingestPRD(root)
|
|
271
|
+
},
|
|
272
|
+
todoModule,
|
|
273
|
+
config,
|
|
274
|
+
format
|
|
275
|
+
}),
|
|
276
|
+
bootspring_autopilot: autopilotTool.createHandler({ format }),
|
|
277
|
+
bootspring_content: contentTool.createHandler({
|
|
278
|
+
contentGen: intelligence.contentGen,
|
|
279
|
+
config,
|
|
280
|
+
format
|
|
281
|
+
}),
|
|
282
|
+
bootspring_suggest: suggestTool.createHandler({
|
|
283
|
+
config,
|
|
284
|
+
format
|
|
285
|
+
}),
|
|
155
286
|
};
|
|
156
287
|
|
|
157
288
|
const resourceHandlers = {
|
|
@@ -214,13 +345,559 @@ const resourceHandlers = {
|
|
|
214
345
|
text: JSON.stringify(agents, null, 2)
|
|
215
346
|
}]
|
|
216
347
|
};
|
|
348
|
+
},
|
|
349
|
+
|
|
350
|
+
'bootspring://workflow/status': async () => {
|
|
351
|
+
const state = intelligence.loadState();
|
|
352
|
+
const currentPhase = intelligence.getCurrentPhase();
|
|
353
|
+
const phaseConfig = intelligence.PHASE_AGENTS[currentPhase];
|
|
354
|
+
|
|
355
|
+
let workflowInfo = null;
|
|
356
|
+
if (state.activeWorkflow) {
|
|
357
|
+
const workflow = intelligence.getWorkflow(state.activeWorkflow);
|
|
358
|
+
const progress = intelligence.getWorkflowSignalProgress(state.activeWorkflow, state);
|
|
359
|
+
workflowInfo = {
|
|
360
|
+
name: state.activeWorkflow,
|
|
361
|
+
step: state.workflowStep + 1,
|
|
362
|
+
totalSteps: workflow?.phases?.length || 0,
|
|
363
|
+
currentPhase: workflow?.phases?.[state.workflowStep]?.name || null,
|
|
364
|
+
progress: progress || null
|
|
365
|
+
};
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
return {
|
|
369
|
+
contents: [{
|
|
370
|
+
uri: 'bootspring://workflow/status',
|
|
371
|
+
mimeType: 'application/json',
|
|
372
|
+
text: JSON.stringify({
|
|
373
|
+
phase: currentPhase,
|
|
374
|
+
phaseName: phaseConfig?.name || 'Unknown',
|
|
375
|
+
activeWorkflow: workflowInfo,
|
|
376
|
+
availableWorkflows: intelligence.listWorkflows().map(w => ({
|
|
377
|
+
key: w.key,
|
|
378
|
+
name: w.name,
|
|
379
|
+
tier: w.tier
|
|
380
|
+
})),
|
|
381
|
+
lastAnalysis: state.lastAnalysis
|
|
382
|
+
}, null, 2)
|
|
383
|
+
}]
|
|
384
|
+
};
|
|
385
|
+
},
|
|
386
|
+
|
|
387
|
+
'bootspring://skills/catalog': async () => {
|
|
388
|
+
const allSkills = skills.listSkills({ includeExternal: true });
|
|
389
|
+
const catalog = allSkills.map(skillId => {
|
|
390
|
+
const metadata = skills.getSkillMetadata(skillId);
|
|
391
|
+
return {
|
|
392
|
+
id: skillId,
|
|
393
|
+
name: metadata?.name || skillId,
|
|
394
|
+
description: metadata?.description || '',
|
|
395
|
+
category: metadata?.category || 'general',
|
|
396
|
+
source: metadata?.source || 'built-in'
|
|
397
|
+
};
|
|
398
|
+
});
|
|
399
|
+
|
|
400
|
+
return {
|
|
401
|
+
contents: [{
|
|
402
|
+
uri: 'bootspring://skills/catalog',
|
|
403
|
+
mimeType: 'application/json',
|
|
404
|
+
text: JSON.stringify({
|
|
405
|
+
total: catalog.length,
|
|
406
|
+
skills: catalog
|
|
407
|
+
}, null, 2)
|
|
408
|
+
}]
|
|
409
|
+
};
|
|
410
|
+
},
|
|
411
|
+
|
|
412
|
+
'bootspring://memory/recent': async () => {
|
|
413
|
+
const memory = intelligence.memory;
|
|
414
|
+
let recentDecisions = [];
|
|
415
|
+
let stats = {};
|
|
416
|
+
let patterns = [];
|
|
417
|
+
|
|
418
|
+
try {
|
|
419
|
+
recentDecisions = memory.getRecentDecisions(10);
|
|
420
|
+
stats = memory.getStats();
|
|
421
|
+
patterns = memory.getPatterns().slice(0, 5);
|
|
422
|
+
} catch {
|
|
423
|
+
// Memory may not be initialized
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
return {
|
|
427
|
+
contents: [{
|
|
428
|
+
uri: 'bootspring://memory/recent',
|
|
429
|
+
mimeType: 'application/json',
|
|
430
|
+
text: JSON.stringify({
|
|
431
|
+
stats,
|
|
432
|
+
recentDecisions: recentDecisions.map(d => ({
|
|
433
|
+
id: d.id,
|
|
434
|
+
type: d.type,
|
|
435
|
+
decision: d.decision,
|
|
436
|
+
outcome: d.outcome?.status || 'pending',
|
|
437
|
+
timestamp: d.timestamp
|
|
438
|
+
})),
|
|
439
|
+
topPatterns: patterns
|
|
440
|
+
}, null, 2)
|
|
441
|
+
}]
|
|
442
|
+
};
|
|
443
|
+
},
|
|
444
|
+
|
|
445
|
+
'bootspring://autopilot/status': async () => {
|
|
446
|
+
let autopilotStatus = { enabled: false, suggestions: [] };
|
|
447
|
+
|
|
448
|
+
try {
|
|
449
|
+
const gitAutopilot = require('../hooks/git-autopilot');
|
|
450
|
+
autopilotStatus = gitAutopilot.getStatus();
|
|
451
|
+
} catch {
|
|
452
|
+
// Autopilot may not be available
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
return {
|
|
456
|
+
contents: [{
|
|
457
|
+
uri: 'bootspring://autopilot/status',
|
|
458
|
+
mimeType: 'application/json',
|
|
459
|
+
text: JSON.stringify({
|
|
460
|
+
enabled: autopilotStatus.enabled,
|
|
461
|
+
watcherActive: autopilotStatus.watcherActive || false,
|
|
462
|
+
pendingSuggestions: autopilotStatus.pendingSuggestions || 0,
|
|
463
|
+
suggestions: (autopilotStatus.suggestions || []).map(s => ({
|
|
464
|
+
workflow: s.workflow,
|
|
465
|
+
trigger: s.trigger,
|
|
466
|
+
triggerType: s.triggerType,
|
|
467
|
+
value: s.value,
|
|
468
|
+
confidence: s.confidence
|
|
469
|
+
})),
|
|
470
|
+
lastCheck: autopilotStatus.lastCheck
|
|
471
|
+
}, null, 2)
|
|
472
|
+
}]
|
|
473
|
+
};
|
|
474
|
+
},
|
|
475
|
+
|
|
476
|
+
'bootspring://content/templates': async () => {
|
|
477
|
+
const contentGen = intelligence.contentGen;
|
|
478
|
+
const templates = contentGen.listTemplates();
|
|
479
|
+
const categories = contentGen.getCategories();
|
|
480
|
+
const stats = contentGen.getStatistics();
|
|
481
|
+
|
|
482
|
+
// Group templates by category
|
|
483
|
+
const grouped = {};
|
|
484
|
+
for (const t of templates) {
|
|
485
|
+
if (!grouped[t.category]) {
|
|
486
|
+
grouped[t.category] = [];
|
|
487
|
+
}
|
|
488
|
+
grouped[t.category].push({
|
|
489
|
+
key: t.key,
|
|
490
|
+
name: t.name,
|
|
491
|
+
description: t.description,
|
|
492
|
+
sections: t.sections,
|
|
493
|
+
hasTemplateFile: t.hasTemplateFile,
|
|
494
|
+
compliance: t.compliance
|
|
495
|
+
});
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
return {
|
|
499
|
+
contents: [{
|
|
500
|
+
uri: 'bootspring://content/templates',
|
|
501
|
+
mimeType: 'application/json',
|
|
502
|
+
text: JSON.stringify({
|
|
503
|
+
total: templates.length,
|
|
504
|
+
categories,
|
|
505
|
+
byCategory: grouped,
|
|
506
|
+
statistics: {
|
|
507
|
+
totalGenerated: stats.totalGenerated,
|
|
508
|
+
lastGeneration: stats.lastGeneration
|
|
509
|
+
}
|
|
510
|
+
}, null, 2)
|
|
511
|
+
}]
|
|
512
|
+
};
|
|
217
513
|
}
|
|
218
514
|
};
|
|
219
515
|
|
|
516
|
+
// ============================================================================
|
|
517
|
+
// Tool Invocation System
|
|
518
|
+
// ============================================================================
|
|
519
|
+
// Provides tool-to-tool invocation with circular dependency prevention
|
|
520
|
+
// and context passing between tools.
|
|
521
|
+
// ============================================================================
|
|
522
|
+
|
|
523
|
+
/**
|
|
524
|
+
* Active call stack for circular dependency detection.
|
|
525
|
+
* Uses AsyncLocalStorage for proper async context tracking.
|
|
526
|
+
*/
|
|
527
|
+
const { AsyncLocalStorage } = require('async_hooks');
|
|
528
|
+
const toolCallContext = new AsyncLocalStorage();
|
|
529
|
+
|
|
530
|
+
/**
|
|
531
|
+
* Maximum allowed tool call depth to prevent runaway recursion
|
|
532
|
+
*/
|
|
533
|
+
const MAX_CALL_DEPTH = 10;
|
|
534
|
+
|
|
535
|
+
/**
|
|
536
|
+
* Create an invocation context for tracking tool calls
|
|
537
|
+
* @param {object} parentContext - Optional parent context
|
|
538
|
+
* @returns {object} New invocation context
|
|
539
|
+
*/
|
|
540
|
+
function createInvocationContext(parentContext = null) {
|
|
541
|
+
return {
|
|
542
|
+
callStack: parentContext?.callStack ? [...parentContext.callStack] : [],
|
|
543
|
+
depth: parentContext?.depth ?? 0,
|
|
544
|
+
startTime: Date.now(),
|
|
545
|
+
parentTool: parentContext?.currentTool || null,
|
|
546
|
+
currentTool: null,
|
|
547
|
+
sharedData: parentContext?.sharedData || {},
|
|
548
|
+
results: parentContext?.results || {}
|
|
549
|
+
};
|
|
550
|
+
}
|
|
551
|
+
|
|
552
|
+
/**
|
|
553
|
+
* Get the current invocation context
|
|
554
|
+
* @returns {object|null} Current context or null if not in a tool invocation
|
|
555
|
+
*/
|
|
556
|
+
function getCurrentContext() {
|
|
557
|
+
return toolCallContext.getStore() || null;
|
|
558
|
+
}
|
|
559
|
+
|
|
560
|
+
/**
|
|
561
|
+
* Check if invoking a tool would create a circular dependency
|
|
562
|
+
* @param {string} toolName - Tool to check
|
|
563
|
+
* @param {object} ctx - Current invocation context
|
|
564
|
+
* @returns {boolean} True if circular dependency detected
|
|
565
|
+
*/
|
|
566
|
+
function wouldCreateCircularDependency(toolName, ctx) {
|
|
567
|
+
if (!ctx || !ctx.callStack) return false;
|
|
568
|
+
return ctx.callStack.includes(toolName);
|
|
569
|
+
}
|
|
570
|
+
|
|
571
|
+
/**
|
|
572
|
+
* Invoke a tool from within another tool (tool chaining)
|
|
573
|
+
*
|
|
574
|
+
* Features:
|
|
575
|
+
* - Circular dependency prevention
|
|
576
|
+
* - Call depth limiting
|
|
577
|
+
* - Context passing between tools
|
|
578
|
+
* - Result caching within invocation chain
|
|
579
|
+
*
|
|
580
|
+
* @param {string} toolName - Name of the tool to invoke (e.g., 'bootspring_context')
|
|
581
|
+
* @param {object} args - Arguments to pass to the tool
|
|
582
|
+
* @param {object} options - Invocation options
|
|
583
|
+
* @param {boolean} options.allowCircular - Allow circular calls (default: false)
|
|
584
|
+
* @param {boolean} options.useCache - Use cached result if available (default: true)
|
|
585
|
+
* @param {object} options.context - Additional context to pass
|
|
586
|
+
* @returns {Promise<object>} Tool result
|
|
587
|
+
*/
|
|
588
|
+
async function invokeTool(toolName, args = {}, options = {}) {
|
|
589
|
+
const { allowCircular = false, useCache = true, context: additionalContext = {} } = options;
|
|
590
|
+
|
|
591
|
+
const handler = toolHandlers[toolName];
|
|
592
|
+
|
|
593
|
+
if (!handler) {
|
|
594
|
+
const available = Object.keys(toolHandlers).join(', ');
|
|
595
|
+
return {
|
|
596
|
+
error: true,
|
|
597
|
+
code: 'TOOL_NOT_FOUND',
|
|
598
|
+
message: `Tool not found: ${toolName}. Available: ${available}`,
|
|
599
|
+
tool: toolName
|
|
600
|
+
};
|
|
601
|
+
}
|
|
602
|
+
|
|
603
|
+
// Get or create invocation context
|
|
604
|
+
const parentCtx = getCurrentContext();
|
|
605
|
+
const ctx = createInvocationContext(parentCtx);
|
|
606
|
+
ctx.currentTool = toolName;
|
|
607
|
+
|
|
608
|
+
// Check for circular dependency
|
|
609
|
+
if (!allowCircular && wouldCreateCircularDependency(toolName, ctx)) {
|
|
610
|
+
return {
|
|
611
|
+
error: true,
|
|
612
|
+
code: 'CIRCULAR_DEPENDENCY',
|
|
613
|
+
message: `Circular dependency detected: ${ctx.callStack.join(' -> ')} -> ${toolName}`,
|
|
614
|
+
tool: toolName,
|
|
615
|
+
callStack: [...ctx.callStack, toolName]
|
|
616
|
+
};
|
|
617
|
+
}
|
|
618
|
+
|
|
619
|
+
// Check call depth
|
|
620
|
+
if (ctx.depth >= MAX_CALL_DEPTH) {
|
|
621
|
+
return {
|
|
622
|
+
error: true,
|
|
623
|
+
code: 'MAX_DEPTH_EXCEEDED',
|
|
624
|
+
message: `Maximum tool call depth (${MAX_CALL_DEPTH}) exceeded`,
|
|
625
|
+
tool: toolName,
|
|
626
|
+
depth: ctx.depth
|
|
627
|
+
};
|
|
628
|
+
}
|
|
629
|
+
|
|
630
|
+
// Check cache for identical calls
|
|
631
|
+
const cacheKey = `${toolName}:${JSON.stringify(args)}`;
|
|
632
|
+
if (useCache && ctx.results[cacheKey]) {
|
|
633
|
+
return {
|
|
634
|
+
...ctx.results[cacheKey],
|
|
635
|
+
_cached: true
|
|
636
|
+
};
|
|
637
|
+
}
|
|
638
|
+
|
|
639
|
+
// Update context for this invocation
|
|
640
|
+
ctx.callStack.push(toolName);
|
|
641
|
+
ctx.depth++;
|
|
642
|
+
|
|
643
|
+
// Merge additional context into shared data
|
|
644
|
+
if (additionalContext) {
|
|
645
|
+
Object.assign(ctx.sharedData, additionalContext);
|
|
646
|
+
}
|
|
647
|
+
|
|
648
|
+
// Execute the tool within the context
|
|
649
|
+
try {
|
|
650
|
+
const result = await toolCallContext.run(ctx, async () => {
|
|
651
|
+
// Add invocation metadata to args if tool supports it
|
|
652
|
+
const enhancedArgs = {
|
|
653
|
+
...args,
|
|
654
|
+
_invocation: {
|
|
655
|
+
caller: ctx.parentTool,
|
|
656
|
+
depth: ctx.depth,
|
|
657
|
+
sharedData: ctx.sharedData
|
|
658
|
+
}
|
|
659
|
+
};
|
|
660
|
+
|
|
661
|
+
return await handler(enhancedArgs);
|
|
662
|
+
});
|
|
663
|
+
|
|
664
|
+
// Cache the result
|
|
665
|
+
ctx.results[cacheKey] = result;
|
|
666
|
+
|
|
667
|
+
// Add metadata to result
|
|
668
|
+
return {
|
|
669
|
+
...result,
|
|
670
|
+
_meta: {
|
|
671
|
+
tool: toolName,
|
|
672
|
+
depth: ctx.depth,
|
|
673
|
+
duration: Date.now() - ctx.startTime,
|
|
674
|
+
caller: ctx.parentTool
|
|
675
|
+
}
|
|
676
|
+
};
|
|
677
|
+
} catch (error) {
|
|
678
|
+
return {
|
|
679
|
+
error: true,
|
|
680
|
+
code: 'TOOL_ERROR',
|
|
681
|
+
message: error.message,
|
|
682
|
+
tool: toolName,
|
|
683
|
+
stack: error.stack,
|
|
684
|
+
caller: ctx.parentTool
|
|
685
|
+
};
|
|
686
|
+
}
|
|
687
|
+
}
|
|
688
|
+
|
|
689
|
+
/**
|
|
690
|
+
* Invoke multiple tools in sequence with context sharing
|
|
691
|
+
*
|
|
692
|
+
* Results from earlier tools are available to later tools via sharedData.
|
|
693
|
+
*
|
|
694
|
+
* @param {Array<{tool: string, args: object|function}>} toolCalls - Array of tool invocations
|
|
695
|
+
* args can be a function (previousResults) => args for dynamic arguments
|
|
696
|
+
* @param {object} options - Options for the sequence
|
|
697
|
+
* @param {boolean} options.stopOnError - Stop sequence on first error (default: true)
|
|
698
|
+
* @param {object} options.initialContext - Initial shared context
|
|
699
|
+
* @returns {Promise<object>} Sequence result with all tool results
|
|
700
|
+
*/
|
|
701
|
+
async function invokeToolSequence(toolCalls, options = {}) {
|
|
702
|
+
const { stopOnError = true, initialContext = {} } = options;
|
|
703
|
+
const results = [];
|
|
704
|
+
const sharedData = { ...initialContext };
|
|
705
|
+
|
|
706
|
+
// Create a root context for the sequence
|
|
707
|
+
const rootCtx = createInvocationContext();
|
|
708
|
+
rootCtx.sharedData = sharedData;
|
|
709
|
+
|
|
710
|
+
for (let i = 0; i < toolCalls.length; i++) {
|
|
711
|
+
const call = toolCalls[i];
|
|
712
|
+
const { tool } = call;
|
|
713
|
+
|
|
714
|
+
// Support dynamic args based on previous results
|
|
715
|
+
let args = call.args || {};
|
|
716
|
+
if (typeof args === 'function') {
|
|
717
|
+
args = args(results, sharedData);
|
|
718
|
+
}
|
|
719
|
+
|
|
720
|
+
const result = await toolCallContext.run(rootCtx, async () => {
|
|
721
|
+
return await invokeTool(tool, args, { context: sharedData });
|
|
722
|
+
});
|
|
723
|
+
|
|
724
|
+
results.push({ tool, result, index: i });
|
|
725
|
+
|
|
726
|
+
// Store result in shared data for next tool
|
|
727
|
+
sharedData[`_result_${tool}`] = result;
|
|
728
|
+
sharedData._lastResult = result;
|
|
729
|
+
|
|
730
|
+
// Stop on error if configured
|
|
731
|
+
if (stopOnError && result.error) {
|
|
732
|
+
return {
|
|
733
|
+
success: false,
|
|
734
|
+
stoppedAt: i,
|
|
735
|
+
stoppedTool: tool,
|
|
736
|
+
error: result,
|
|
737
|
+
results,
|
|
738
|
+
sharedData
|
|
739
|
+
};
|
|
740
|
+
}
|
|
741
|
+
}
|
|
742
|
+
|
|
743
|
+
return {
|
|
744
|
+
success: true,
|
|
745
|
+
results,
|
|
746
|
+
sharedData
|
|
747
|
+
};
|
|
748
|
+
}
|
|
749
|
+
|
|
750
|
+
/**
|
|
751
|
+
* Invoke multiple tools in parallel
|
|
752
|
+
*
|
|
753
|
+
* All tools execute concurrently. Use when tools are independent.
|
|
754
|
+
*
|
|
755
|
+
* @param {Array<{tool: string, args: object}>} toolCalls - Array of tool invocations
|
|
756
|
+
* @param {object} options - Options for parallel execution
|
|
757
|
+
* @param {number} options.concurrency - Max concurrent calls (default: unlimited)
|
|
758
|
+
* @param {boolean} options.settleAll - Wait for all to complete even on errors (default: true)
|
|
759
|
+
* @returns {Promise<object>} Parallel result with all tool results
|
|
760
|
+
*/
|
|
761
|
+
async function invokeToolParallel(toolCalls, options = {}) {
|
|
762
|
+
const { concurrency = Infinity, settleAll = true } = options;
|
|
763
|
+
|
|
764
|
+
// Create root context for parallel execution
|
|
765
|
+
const rootCtx = createInvocationContext();
|
|
766
|
+
|
|
767
|
+
// Execute with concurrency limit
|
|
768
|
+
const executeWithLimit = async (calls, limit) => {
|
|
769
|
+
const results = [];
|
|
770
|
+
const executing = new Set();
|
|
771
|
+
|
|
772
|
+
for (const call of calls) {
|
|
773
|
+
const promise = toolCallContext.run(rootCtx, async () => {
|
|
774
|
+
const result = await invokeTool(call.tool, call.args || {});
|
|
775
|
+
return { tool: call.tool, result };
|
|
776
|
+
});
|
|
777
|
+
|
|
778
|
+
results.push(promise);
|
|
779
|
+
executing.add(promise);
|
|
780
|
+
|
|
781
|
+
// Remove from executing set when done
|
|
782
|
+
promise.finally(() => executing.delete(promise));
|
|
783
|
+
|
|
784
|
+
// Wait if at concurrency limit
|
|
785
|
+
if (executing.size >= limit) {
|
|
786
|
+
await Promise.race(executing);
|
|
787
|
+
}
|
|
788
|
+
}
|
|
789
|
+
|
|
790
|
+
return settleAll
|
|
791
|
+
? Promise.allSettled(results)
|
|
792
|
+
: Promise.all(results);
|
|
793
|
+
};
|
|
794
|
+
|
|
795
|
+
const rawResults = await executeWithLimit(toolCalls, concurrency);
|
|
796
|
+
|
|
797
|
+
// Normalize results
|
|
798
|
+
const normalizedResults = rawResults.map((r, index) => {
|
|
799
|
+
if (r.status === 'fulfilled') {
|
|
800
|
+
return r.value;
|
|
801
|
+
} else {
|
|
802
|
+
return {
|
|
803
|
+
tool: toolCalls[index].tool,
|
|
804
|
+
result: {
|
|
805
|
+
error: true,
|
|
806
|
+
code: 'PARALLEL_ERROR',
|
|
807
|
+
message: r.reason?.message || 'Unknown error'
|
|
808
|
+
}
|
|
809
|
+
};
|
|
810
|
+
}
|
|
811
|
+
});
|
|
812
|
+
|
|
813
|
+
const errors = normalizedResults.filter(r => r.result?.error);
|
|
814
|
+
|
|
815
|
+
return {
|
|
816
|
+
success: errors.length === 0,
|
|
817
|
+
results: normalizedResults,
|
|
818
|
+
errors: errors.length > 0 ? errors : undefined
|
|
819
|
+
};
|
|
820
|
+
}
|
|
821
|
+
|
|
822
|
+
/**
|
|
823
|
+
* Create a tool invoker bound to specific context
|
|
824
|
+
*
|
|
825
|
+
* Useful for passing to tools that need to invoke other tools.
|
|
826
|
+
*
|
|
827
|
+
* @param {object} boundContext - Context to bind to all invocations
|
|
828
|
+
* @returns {object} Bound invoker with invokeTool, invokeSequence, invokeParallel
|
|
829
|
+
*/
|
|
830
|
+
function createBoundInvoker(boundContext = {}) {
|
|
831
|
+
return {
|
|
832
|
+
invoke: (toolName, args, options = {}) =>
|
|
833
|
+
invokeTool(toolName, args, { ...options, context: { ...boundContext, ...options.context } }),
|
|
834
|
+
|
|
835
|
+
sequence: (toolCalls, options = {}) =>
|
|
836
|
+
invokeToolSequence(toolCalls, { ...options, initialContext: { ...boundContext, ...options.initialContext } }),
|
|
837
|
+
|
|
838
|
+
parallel: (toolCalls, options) =>
|
|
839
|
+
invokeToolParallel(toolCalls, options),
|
|
840
|
+
|
|
841
|
+
// Convenience method to get a tool's result
|
|
842
|
+
get: async (toolName, args) => {
|
|
843
|
+
const result = await invokeTool(toolName, args, { context: boundContext });
|
|
844
|
+
return result.error ? null : result;
|
|
845
|
+
}
|
|
846
|
+
};
|
|
847
|
+
}
|
|
848
|
+
|
|
849
|
+
/**
|
|
850
|
+
* Get list of available tool names
|
|
851
|
+
* @returns {Array<string>} Tool names
|
|
852
|
+
*/
|
|
853
|
+
function getAvailableTools() {
|
|
854
|
+
return Object.keys(toolHandlers);
|
|
855
|
+
}
|
|
856
|
+
|
|
857
|
+
/**
|
|
858
|
+
* Check if a tool exists
|
|
859
|
+
* @param {string} toolName - Tool name to check
|
|
860
|
+
* @returns {boolean} True if tool exists
|
|
861
|
+
*/
|
|
862
|
+
function hasTool(toolName) {
|
|
863
|
+
return toolName in toolHandlers;
|
|
864
|
+
}
|
|
865
|
+
|
|
866
|
+
/**
|
|
867
|
+
* Get tool definition by name
|
|
868
|
+
* @param {string} toolName - Tool name
|
|
869
|
+
* @returns {object|null} Tool definition or null
|
|
870
|
+
*/
|
|
871
|
+
function getToolDefinition(toolName) {
|
|
872
|
+
const tool = TOOLS.find(t => t.name === toolName);
|
|
873
|
+
return tool || null;
|
|
874
|
+
}
|
|
875
|
+
|
|
220
876
|
module.exports = {
|
|
877
|
+
// Tool and resource definitions
|
|
221
878
|
TOOLS,
|
|
222
879
|
RESOURCES,
|
|
880
|
+
|
|
881
|
+
// Handlers
|
|
223
882
|
toolHandlers,
|
|
224
883
|
resourceHandlers,
|
|
225
|
-
trackTelemetry
|
|
884
|
+
trackTelemetry,
|
|
885
|
+
|
|
886
|
+
// Tool invocation system
|
|
887
|
+
invokeTool,
|
|
888
|
+
invokeToolSequence,
|
|
889
|
+
invokeToolParallel,
|
|
890
|
+
createBoundInvoker,
|
|
891
|
+
|
|
892
|
+
// Tool introspection
|
|
893
|
+
getAvailableTools,
|
|
894
|
+
hasTool,
|
|
895
|
+
getToolDefinition,
|
|
896
|
+
|
|
897
|
+
// Context utilities (for advanced use)
|
|
898
|
+
getCurrentContext,
|
|
899
|
+
createInvocationContext,
|
|
900
|
+
|
|
901
|
+
// Constants
|
|
902
|
+
MAX_CALL_DEPTH
|
|
226
903
|
};
|