@vauban-org/agent-sdk 0.17.4 → 1.2.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/CONTRACT.md +6401 -813
- package/dist/adapters/llm/anthropic-direct.d.ts +1 -0
- package/dist/adapters/llm/anthropic-direct.d.ts.map +1 -1
- package/dist/adapters/llm/anthropic-direct.js +43 -0
- package/dist/adapters/llm/anthropic-direct.js.map +1 -1
- package/dist/adapters/llm/cascade.d.ts.map +1 -1
- package/dist/adapters/llm/cascade.js +57 -14
- package/dist/adapters/llm/cascade.js.map +1 -1
- package/dist/adapters/llm/litellm.d.ts +2 -0
- package/dist/adapters/llm/litellm.d.ts.map +1 -1
- package/dist/adapters/llm/litellm.js +44 -0
- package/dist/adapters/llm/litellm.js.map +1 -1
- package/dist/compute/difficulty-estimator.d.ts +53 -0
- package/dist/compute/difficulty-estimator.d.ts.map +1 -0
- package/dist/compute/difficulty-estimator.js +82 -0
- package/dist/compute/difficulty-estimator.js.map +1 -0
- package/dist/compute/strategies/mixture-of-agents.d.ts +40 -0
- package/dist/compute/strategies/mixture-of-agents.d.ts.map +1 -0
- package/dist/compute/strategies/mixture-of-agents.js +110 -0
- package/dist/compute/strategies/mixture-of-agents.js.map +1 -0
- package/dist/compute/strategies/tree-of-thoughts.d.ts +48 -0
- package/dist/compute/strategies/tree-of-thoughts.d.ts.map +1 -0
- package/dist/compute/strategies/tree-of-thoughts.js +242 -0
- package/dist/compute/strategies/tree-of-thoughts.js.map +1 -0
- package/dist/compute/strategies/two-phase-orient.d.ts +72 -0
- package/dist/compute/strategies/two-phase-orient.d.ts.map +1 -0
- package/dist/compute/strategies/two-phase-orient.js +85 -0
- package/dist/compute/strategies/two-phase-orient.js.map +1 -0
- package/dist/constitution/types.d.ts +10 -10
- package/dist/container/protocol.d.ts +134 -0
- package/dist/container/protocol.d.ts.map +1 -0
- package/dist/container/protocol.js +157 -0
- package/dist/container/protocol.js.map +1 -0
- package/dist/container/runtime.d.ts +140 -0
- package/dist/container/runtime.d.ts.map +1 -0
- package/dist/container/runtime.js +256 -0
- package/dist/container/runtime.js.map +1 -0
- package/dist/events/catalogue.d.ts +327 -30
- package/dist/events/catalogue.d.ts.map +1 -1
- package/dist/events/catalogue.js +18 -0
- package/dist/events/catalogue.js.map +1 -1
- package/dist/events/index.d.ts +9 -0
- package/dist/events/index.d.ts.map +1 -1
- package/dist/events/index.js +9 -0
- package/dist/events/index.js.map +1 -1
- package/dist/events/schemas/agent.completed.v1.d.ts +4 -4
- package/dist/events/schemas/agent.failed.v1.d.ts +2 -2
- package/dist/events/schemas/agent.hitl_resolved.v1.d.ts +2 -2
- package/dist/events/schemas/agent.started.v1.d.ts +2 -2
- package/dist/events/schemas/brain.skill.extracted.v1.d.ts +4 -4
- package/dist/events/schemas/cc.cost.anomaly_detected.v1.d.ts +2 -2
- package/dist/events/schemas/cc.cost.recorded.v1.d.ts +4 -4
- package/dist/events/schemas/citadel.sprint.analyzed.v1.d.ts +55 -0
- package/dist/events/schemas/citadel.sprint.analyzed.v1.d.ts.map +1 -0
- package/dist/events/schemas/citadel.sprint.analyzed.v1.js +22 -0
- package/dist/events/schemas/citadel.sprint.analyzed.v1.js.map +1 -0
- package/dist/events/schemas/citadel.sprint.closed.v1.d.ts +2 -2
- package/dist/events/schemas/forge.inbox.reply_classified.v1.d.ts +33 -0
- package/dist/events/schemas/forge.inbox.reply_classified.v1.d.ts.map +1 -0
- package/dist/events/schemas/forge.inbox.reply_classified.v1.js +15 -0
- package/dist/events/schemas/forge.inbox.reply_classified.v1.js.map +1 -0
- package/dist/events/schemas/forge.lead.qualified.v1.d.ts +2 -2
- package/dist/events/schemas/forge.outreach.sent.v1.d.ts +4 -4
- package/dist/events/schemas/incident.detected.v1.d.ts +2 -2
- package/dist/events/schemas/vauban-finance.forecast.generated.v1.d.ts +21 -0
- package/dist/events/schemas/vauban-finance.forecast.generated.v1.d.ts.map +1 -0
- package/dist/events/schemas/vauban-finance.forecast.generated.v1.js +11 -0
- package/dist/events/schemas/vauban-finance.forecast.generated.v1.js.map +1 -0
- package/dist/events/schemas/vauban-finance.trade.executed.v1.d.ts +24 -0
- package/dist/events/schemas/vauban-finance.trade.executed.v1.d.ts.map +1 -0
- package/dist/events/schemas/vauban-finance.trade.executed.v1.js +12 -0
- package/dist/events/schemas/vauban-finance.trade.executed.v1.js.map +1 -0
- package/dist/events/schemas/vauban.goal.checked.v1.d.ts +21 -0
- package/dist/events/schemas/vauban.goal.checked.v1.d.ts.map +1 -0
- package/dist/events/schemas/vauban.goal.checked.v1.js +11 -0
- package/dist/events/schemas/vauban.goal.checked.v1.js.map +1 -0
- package/dist/events/schemas/vauban.rebalancing.checked.v1.d.ts +21 -0
- package/dist/events/schemas/vauban.rebalancing.checked.v1.d.ts.map +1 -0
- package/dist/events/schemas/vauban.rebalancing.checked.v1.js +11 -0
- package/dist/events/schemas/vauban.rebalancing.checked.v1.js.map +1 -0
- package/dist/events/schemas/vauban.tax.checked.v1.d.ts +21 -0
- package/dist/events/schemas/vauban.tax.checked.v1.d.ts.map +1 -0
- package/dist/events/schemas/vauban.tax.checked.v1.js +11 -0
- package/dist/events/schemas/vauban.tax.checked.v1.js.map +1 -0
- package/dist/events/schemas/vauban.vault.analyzed.v1.d.ts +59 -0
- package/dist/events/schemas/vauban.vault.analyzed.v1.d.ts.map +1 -0
- package/dist/events/schemas/vauban.vault.analyzed.v1.js +19 -0
- package/dist/events/schemas/vauban.vault.analyzed.v1.js.map +1 -0
- package/dist/events/schemas/vauban.vault.compounded.v1.d.ts +24 -0
- package/dist/events/schemas/vauban.vault.compounded.v1.d.ts.map +1 -0
- package/dist/events/schemas/vauban.vault.compounded.v1.js +12 -0
- package/dist/events/schemas/vauban.vault.compounded.v1.js.map +1 -0
- package/dist/identity/agent-persona.d.ts +73 -0
- package/dist/identity/agent-persona.d.ts.map +1 -0
- package/dist/identity/agent-persona.js +165 -0
- package/dist/identity/agent-persona.js.map +1 -0
- package/dist/identity/persona-prompt.d.ts +25 -0
- package/dist/identity/persona-prompt.d.ts.map +1 -0
- package/dist/identity/persona-prompt.js +71 -0
- package/dist/identity/persona-prompt.js.map +1 -0
- package/dist/identity/persona-schema.d.ts +120 -0
- package/dist/identity/persona-schema.d.ts.map +1 -0
- package/dist/identity/persona-schema.js +103 -0
- package/dist/identity/persona-schema.js.map +1 -0
- package/dist/index.d.ts +37 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +29 -1
- package/dist/index.js.map +1 -1
- package/dist/loop/index.d.ts +1 -1
- package/dist/loop/index.d.ts.map +1 -1
- package/dist/loop/index.js.map +1 -1
- package/dist/loop/minimal-loop.js +293 -287
- package/dist/loop/sdk-loop.d.ts +1 -3
- package/dist/loop/sdk-loop.d.ts.map +1 -1
- package/dist/loop/sdk-loop.js +1 -1
- package/dist/loop/sdk-loop.js.map +1 -1
- package/dist/memory/episodic-rrf.d.ts +114 -0
- package/dist/memory/episodic-rrf.d.ts.map +1 -0
- package/dist/memory/episodic-rrf.js +148 -0
- package/dist/memory/episodic-rrf.js.map +1 -0
- package/dist/mesh/attenuation.d.ts +78 -0
- package/dist/mesh/attenuation.d.ts.map +1 -0
- package/dist/mesh/attenuation.js +141 -0
- package/dist/mesh/attenuation.js.map +1 -0
- package/dist/mesh/delegate.d.ts +96 -0
- package/dist/mesh/delegate.d.ts.map +1 -0
- package/dist/mesh/delegate.js +172 -0
- package/dist/mesh/delegate.js.map +1 -0
- package/dist/mesh/dispatcher.d.ts +119 -0
- package/dist/mesh/dispatcher.d.ts.map +1 -0
- package/dist/mesh/dispatcher.js +207 -0
- package/dist/mesh/dispatcher.js.map +1 -0
- package/dist/mesh/index.d.ts +12 -0
- package/dist/mesh/index.d.ts.map +1 -0
- package/dist/mesh/index.js +11 -0
- package/dist/mesh/index.js.map +1 -0
- package/dist/mesh/types.d.ts +30 -0
- package/dist/mesh/types.d.ts.map +1 -0
- package/dist/mesh/types.js +11 -0
- package/dist/mesh/types.js.map +1 -0
- package/dist/orchestration/ooda/skills.d.ts +104 -0
- package/dist/orchestration/ooda/skills.d.ts.map +1 -1
- package/dist/orchestration/ooda/skills.js +106 -0
- package/dist/orchestration/ooda/skills.js.map +1 -1
- package/dist/orchestration/ooda/types.d.ts +3 -8
- package/dist/orchestration/ooda/types.d.ts.map +1 -1
- package/dist/ports/bastion-action.contract.test.d.ts +11 -0
- package/dist/ports/bastion-action.contract.test.d.ts.map +1 -0
- package/dist/ports/bastion-action.contract.test.js +238 -0
- package/dist/ports/bastion-action.contract.test.js.map +1 -0
- package/dist/ports/bastion-action.d.ts +133 -0
- package/dist/ports/bastion-action.d.ts.map +1 -0
- package/dist/ports/bastion-action.js +73 -0
- package/dist/ports/bastion-action.js.map +1 -0
- package/dist/ports/brain.d.ts +31 -0
- package/dist/ports/brain.d.ts.map +1 -1
- package/dist/ports/brain.js +115 -1
- package/dist/ports/brain.js.map +1 -1
- package/dist/ports/citadel-action.contract.test.d.ts +11 -0
- package/dist/ports/citadel-action.contract.test.d.ts.map +1 -0
- package/dist/ports/citadel-action.contract.test.js +317 -0
- package/dist/ports/citadel-action.contract.test.js.map +1 -0
- package/dist/ports/citadel-action.d.ts +111 -0
- package/dist/ports/citadel-action.d.ts.map +1 -0
- package/dist/ports/citadel-action.js +62 -0
- package/dist/ports/citadel-action.js.map +1 -0
- package/dist/ports/compliance-contract.d.ts +123 -0
- package/dist/ports/compliance-contract.d.ts.map +1 -0
- package/dist/ports/compliance-contract.js +35 -0
- package/dist/ports/compliance-contract.js.map +1 -0
- package/dist/ports/db.d.ts +38 -0
- package/dist/ports/db.d.ts.map +1 -1
- package/dist/ports/db.js +88 -1
- package/dist/ports/db.js.map +1 -1
- package/dist/ports/delegation.contract.test.d.ts +9 -0
- package/dist/ports/delegation.contract.test.d.ts.map +1 -0
- package/dist/ports/delegation.contract.test.js +337 -0
- package/dist/ports/delegation.contract.test.js.map +1 -0
- package/dist/ports/delegation.d.ts +134 -0
- package/dist/ports/delegation.d.ts.map +1 -0
- package/dist/ports/delegation.js +105 -0
- package/dist/ports/delegation.js.map +1 -0
- package/dist/ports/event-bus.d.ts +29 -13
- package/dist/ports/event-bus.d.ts.map +1 -1
- package/dist/ports/event-bus.js +106 -1
- package/dist/ports/event-bus.js.map +1 -1
- package/dist/ports/federation.contract.test.d.ts +9 -0
- package/dist/ports/federation.contract.test.d.ts.map +1 -0
- package/dist/ports/federation.contract.test.js +279 -0
- package/dist/ports/federation.contract.test.js.map +1 -0
- package/dist/ports/federation.d.ts +140 -0
- package/dist/ports/federation.d.ts.map +1 -0
- package/dist/ports/federation.js +57 -0
- package/dist/ports/federation.js.map +1 -0
- package/dist/ports/index.d.ts +28 -2
- package/dist/ports/index.d.ts.map +1 -1
- package/dist/ports/index.js +17 -2
- package/dist/ports/index.js.map +1 -1
- package/dist/ports/llm-provider.d.ts +37 -0
- package/dist/ports/llm-provider.d.ts.map +1 -1
- package/dist/ports/llm-provider.js +99 -1
- package/dist/ports/llm-provider.js.map +1 -1
- package/dist/ports/logger.d.ts +27 -0
- package/dist/ports/logger.d.ts.map +1 -1
- package/dist/ports/logger.js +87 -0
- package/dist/ports/logger.js.map +1 -1
- package/dist/ports/manifest-registry.contract.test.d.ts +9 -0
- package/dist/ports/manifest-registry.contract.test.d.ts.map +1 -0
- package/dist/ports/manifest-registry.contract.test.js +246 -0
- package/dist/ports/manifest-registry.contract.test.js.map +1 -0
- package/dist/ports/manifest-registry.d.ts +116 -0
- package/dist/ports/manifest-registry.d.ts.map +1 -0
- package/dist/ports/manifest-registry.js +79 -0
- package/dist/ports/manifest-registry.js.map +1 -0
- package/dist/ports/observability.contract.test.d.ts +12 -0
- package/dist/ports/observability.contract.test.d.ts.map +1 -0
- package/dist/ports/observability.contract.test.js +260 -0
- package/dist/ports/observability.contract.test.js.map +1 -0
- package/dist/ports/observability.d.ts +98 -0
- package/dist/ports/observability.d.ts.map +1 -0
- package/dist/ports/observability.js +59 -0
- package/dist/ports/observability.js.map +1 -0
- package/dist/ports/outcome.d.ts +26 -0
- package/dist/ports/outcome.d.ts.map +1 -1
- package/dist/ports/outcome.js +62 -1
- package/dist/ports/outcome.js.map +1 -1
- package/dist/ports/privacy.contract.test.d.ts +12 -0
- package/dist/ports/privacy.contract.test.d.ts.map +1 -0
- package/dist/ports/privacy.contract.test.js +325 -0
- package/dist/ports/privacy.contract.test.js.map +1 -0
- package/dist/ports/privacy.d.ts +132 -0
- package/dist/ports/privacy.d.ts.map +1 -0
- package/dist/ports/privacy.js +83 -0
- package/dist/ports/privacy.js.map +1 -0
- package/dist/ports/tenant-context.contract.test.d.ts +14 -0
- package/dist/ports/tenant-context.contract.test.d.ts.map +1 -0
- package/dist/ports/tenant-context.contract.test.js +352 -0
- package/dist/ports/tenant-context.contract.test.js.map +1 -0
- package/dist/ports/tenant-context.d.ts +103 -0
- package/dist/ports/tenant-context.d.ts.map +1 -0
- package/dist/ports/tenant-context.js +48 -0
- package/dist/ports/tenant-context.js.map +1 -0
- package/dist/ports/vauban-finance-action.contract.test.d.ts +11 -0
- package/dist/ports/vauban-finance-action.contract.test.d.ts.map +1 -0
- package/dist/ports/vauban-finance-action.contract.test.js +260 -0
- package/dist/ports/vauban-finance-action.contract.test.js.map +1 -0
- package/dist/ports/vauban-finance-action.d.ts +106 -0
- package/dist/ports/vauban-finance-action.d.ts.map +1 -0
- package/dist/ports/vauban-finance-action.js +60 -0
- package/dist/ports/vauban-finance-action.js.map +1 -0
- package/dist/ports/workflow-runtime.d.ts +204 -0
- package/dist/ports/workflow-runtime.d.ts.map +1 -0
- package/dist/ports/workflow-runtime.js +72 -0
- package/dist/ports/workflow-runtime.js.map +1 -0
- package/dist/proof/cert-verify.d.ts +80 -0
- package/dist/proof/cert-verify.d.ts.map +1 -0
- package/dist/proof/cert-verify.js +178 -0
- package/dist/proof/cert-verify.js.map +1 -0
- package/dist/replay/replay.d.ts.map +1 -1
- package/dist/replay/replay.js +5 -1
- package/dist/replay/replay.js.map +1 -1
- package/dist/retry/index.d.ts +129 -0
- package/dist/retry/index.d.ts.map +1 -0
- package/dist/retry/index.js +156 -0
- package/dist/retry/index.js.map +1 -0
- package/dist/retry/presets.d.ts +39 -0
- package/dist/retry/presets.d.ts.map +1 -0
- package/dist/retry/presets.js +69 -0
- package/dist/retry/presets.js.map +1 -0
- package/dist/skill-loop/ab-runner.d.ts +67 -0
- package/dist/skill-loop/ab-runner.d.ts.map +1 -0
- package/dist/skill-loop/ab-runner.js +160 -0
- package/dist/skill-loop/ab-runner.js.map +1 -0
- package/dist/skill-loop/adoption.d.ts +67 -0
- package/dist/skill-loop/adoption.d.ts.map +1 -0
- package/dist/skill-loop/adoption.js +126 -0
- package/dist/skill-loop/adoption.js.map +1 -0
- package/dist/skill-loop/candidate.d.ts +45 -0
- package/dist/skill-loop/candidate.d.ts.map +1 -0
- package/dist/skill-loop/candidate.js +43 -0
- package/dist/skill-loop/candidate.js.map +1 -0
- package/dist/skill-loop/evaluator.d.ts +42 -0
- package/dist/skill-loop/evaluator.d.ts.map +1 -0
- package/dist/skill-loop/evaluator.js +184 -0
- package/dist/skill-loop/evaluator.js.map +1 -0
- package/dist/skill-loop/index.d.ts +27 -0
- package/dist/skill-loop/index.d.ts.map +1 -0
- package/dist/skill-loop/index.js +27 -0
- package/dist/skill-loop/index.js.map +1 -0
- package/dist/skill-loop/reflexion-replay.d.ts +87 -0
- package/dist/skill-loop/reflexion-replay.d.ts.map +1 -0
- package/dist/skill-loop/reflexion-replay.js +110 -0
- package/dist/skill-loop/reflexion-replay.js.map +1 -0
- package/dist/skill-loop/sign-off.d.ts +88 -0
- package/dist/skill-loop/sign-off.d.ts.map +1 -0
- package/dist/skill-loop/sign-off.js +146 -0
- package/dist/skill-loop/sign-off.js.map +1 -0
- package/dist/skill-loop/value-metric.d.ts +55 -0
- package/dist/skill-loop/value-metric.d.ts.map +1 -0
- package/dist/skill-loop/value-metric.js +69 -0
- package/dist/skill-loop/value-metric.js.map +1 -0
- package/dist/skill-loop/versioning.d.ts +36 -0
- package/dist/skill-loop/versioning.d.ts.map +1 -0
- package/dist/skill-loop/versioning.js +47 -0
- package/dist/skill-loop/versioning.js.map +1 -0
- package/dist/skill-manifest/anchor.d.ts +91 -0
- package/dist/skill-manifest/anchor.d.ts.map +1 -0
- package/dist/skill-manifest/anchor.js +331 -0
- package/dist/skill-manifest/anchor.js.map +1 -0
- package/dist/skill-manifest/builder.d.ts +47 -0
- package/dist/skill-manifest/builder.d.ts.map +1 -0
- package/dist/skill-manifest/builder.js +93 -0
- package/dist/skill-manifest/builder.js.map +1 -0
- package/dist/skill-manifest/index.d.ts +13 -0
- package/dist/skill-manifest/index.d.ts.map +1 -0
- package/dist/skill-manifest/index.js +9 -0
- package/dist/skill-manifest/index.js.map +1 -0
- package/dist/skill-manifest/types.d.ts +67 -0
- package/dist/skill-manifest/types.d.ts.map +1 -0
- package/dist/skill-manifest/types.js +16 -0
- package/dist/skill-manifest/types.js.map +1 -0
- package/dist/skill-manifest/verifier.d.ts +42 -0
- package/dist/skill-manifest/verifier.d.ts.map +1 -0
- package/dist/skill-manifest/verifier.js +136 -0
- package/dist/skill-manifest/verifier.js.map +1 -0
- package/dist/skills/brain-query.d.ts +4 -4
- package/dist/skills/brain-store.d.ts +6 -6
- package/dist/skills/errors.d.ts +15 -0
- package/dist/skills/errors.d.ts.map +1 -1
- package/dist/skills/errors.js +21 -0
- package/dist/skills/errors.js.map +1 -1
- package/dist/skills/hitl-request.d.ts +2 -2
- package/dist/skills/index.d.ts +3 -1
- package/dist/skills/index.d.ts.map +1 -1
- package/dist/skills/index.js +4 -1
- package/dist/skills/index.js.map +1 -1
- package/dist/skills/markdown/loader.d.ts +52 -0
- package/dist/skills/markdown/loader.d.ts.map +1 -0
- package/dist/skills/markdown/loader.js +93 -0
- package/dist/skills/markdown/loader.js.map +1 -0
- package/dist/skills/markdown/schema.d.ts +432 -0
- package/dist/skills/markdown/schema.d.ts.map +1 -0
- package/dist/skills/markdown/schema.js +121 -0
- package/dist/skills/markdown/schema.js.map +1 -0
- package/dist/skills/poc-md-loader/markdown-loader.d.ts +77 -0
- package/dist/skills/poc-md-loader/markdown-loader.d.ts.map +1 -0
- package/dist/skills/poc-md-loader/markdown-loader.js +125 -0
- package/dist/skills/poc-md-loader/markdown-loader.js.map +1 -0
- package/dist/skills/poc-md-loader/runner.d.ts +24 -0
- package/dist/skills/poc-md-loader/runner.d.ts.map +1 -0
- package/dist/skills/poc-md-loader/runner.js +57 -0
- package/dist/skills/poc-md-loader/runner.js.map +1 -0
- package/dist/skills/poc-md-loader/vitest.poc.config.d.ts +3 -0
- package/dist/skills/poc-md-loader/vitest.poc.config.d.ts.map +1 -0
- package/dist/skills/poc-md-loader/vitest.poc.config.js +13 -0
- package/dist/skills/poc-md-loader/vitest.poc.config.js.map +1 -0
- package/dist/skills/poc-md-loader/web-search/script.d.ts +33 -0
- package/dist/skills/poc-md-loader/web-search/script.d.ts.map +1 -0
- package/dist/skills/poc-md-loader/web-search/script.js +75 -0
- package/dist/skills/poc-md-loader/web-search/script.js.map +1 -0
- package/dist/skills/record-outcome.d.ts +4 -4
- package/dist/skills/send-email.d.ts.map +1 -1
- package/dist/skills/send-email.js +15 -3
- package/dist/skills/send-email.js.map +1 -1
- package/dist/skills/slack-notify.d.ts +4 -4
- package/dist/skills/starknet-balance.d.ts +1 -1
- package/dist/skills/telegram-notify.d.ts +4 -4
- package/dist/skills/web-search.d.ts +1 -1
- package/dist/testing/contracts/event-bus.contract.d.ts.map +1 -1
- package/dist/testing/contracts/event-bus.contract.js +14 -12
- package/dist/testing/contracts/event-bus.contract.js.map +1 -1
- package/dist/testing/index.d.ts +3 -0
- package/dist/testing/test-brain-port.d.ts +4 -0
- package/dist/testing/test-brain-port.d.ts.map +1 -1
- package/dist/testing/test-brain-port.js +75 -20
- package/dist/testing/test-brain-port.js.map +1 -1
- package/dist/testing/test-event-bus.d.ts.map +1 -1
- package/dist/testing/test-event-bus.js +89 -36
- package/dist/testing/test-event-bus.js.map +1 -1
- package/dist/trace/schema.d.ts +1 -1
- package/dist/trace/schema.d.ts.map +1 -1
- package/dist/trace/schema.js +1 -1
- package/dist/trace/schema.js.map +1 -1
- package/dist/verify/formal/index.d.ts +44 -0
- package/dist/verify/formal/index.d.ts.map +1 -0
- package/dist/verify/formal/index.js +98 -0
- package/dist/verify/formal/index.js.map +1 -0
- package/dist/verify/formal/policy.d.ts +105 -0
- package/dist/verify/formal/policy.d.ts.map +1 -0
- package/dist/verify/formal/policy.js +159 -0
- package/dist/verify/formal/policy.js.map +1 -0
- package/dist/verify/formal/result.d.ts +50 -0
- package/dist/verify/formal/result.d.ts.map +1 -0
- package/dist/verify/formal/result.js +21 -0
- package/dist/verify/formal/result.js.map +1 -0
- package/dist/verify/formal/solver.d.ts +67 -0
- package/dist/verify/formal/solver.d.ts.map +1 -0
- package/dist/verify/formal/solver.js +184 -0
- package/dist/verify/formal/solver.js.map +1 -0
- package/dist/verify/formal/spec-language.d.ts +80 -0
- package/dist/verify/formal/spec-language.d.ts.map +1 -0
- package/dist/verify/formal/spec-language.js +219 -0
- package/dist/verify/formal/spec-language.js.map +1 -0
- package/docs/attestation.md +199 -0
- package/docs/identity.md +193 -0
- package/package.json +22 -1
- package/src/adapters/llm/anthropic-direct.ts +51 -0
- package/src/adapters/llm/cascade.ts +64 -19
- package/src/adapters/llm/litellm.ts +49 -0
- package/src/compute/difficulty-estimator.ts +111 -0
- package/src/compute/strategies/mixture-of-agents.ts +150 -0
- package/src/compute/strategies/tree-of-thoughts.ts +293 -0
- package/src/compute/strategies/two-phase-orient.ts +147 -0
- package/src/container/protocol.ts +243 -0
- package/src/container/runtime.ts +424 -0
- package/src/db/migrations/026_formal_verify_results.sql +30 -0
- package/src/events/catalogue.ts +54 -0
- package/src/events/index.ts +9 -0
- package/src/events/schemas/citadel.sprint.analyzed.v1.ts +23 -0
- package/src/events/schemas/forge.inbox.reply_classified.v1.ts +15 -0
- package/src/events/schemas/vauban-finance.forecast.generated.v1.ts +11 -0
- package/src/events/schemas/vauban-finance.trade.executed.v1.ts +12 -0
- package/src/events/schemas/vauban.goal.checked.v1.ts +11 -0
- package/src/events/schemas/vauban.rebalancing.checked.v1.ts +11 -0
- package/src/events/schemas/vauban.tax.checked.v1.ts +11 -0
- package/src/events/schemas/vauban.vault.analyzed.v1.ts +21 -0
- package/src/events/schemas/vauban.vault.compounded.v1.ts +12 -0
- package/src/identity/agent-persona.ts +203 -0
- package/src/identity/persona-prompt.ts +84 -0
- package/src/identity/persona-schema.ts +127 -0
- package/src/index.ts +338 -1
- package/src/loop/index.ts +0 -1
- package/src/loop/sdk-loop.ts +5 -8
- package/src/memory/episodic-rrf.ts +224 -0
- package/src/mesh/attenuation.ts +190 -0
- package/src/mesh/delegate.ts +254 -0
- package/src/mesh/dispatcher.ts +301 -0
- package/src/mesh/index.ts +39 -0
- package/src/mesh/types.ts +31 -0
- package/src/orchestration/ooda/skills.ts +177 -0
- package/src/orchestration/ooda/types.ts +3 -9
- package/src/ports/bastion-action.contract.test.ts +355 -0
- package/src/ports/bastion-action.ts +198 -0
- package/src/ports/brain.ts +177 -15
- package/src/ports/citadel-action.contract.test.ts +430 -0
- package/src/ports/citadel-action.ts +174 -0
- package/src/ports/compliance-contract.ts +191 -0
- package/src/ports/db.ts +98 -0
- package/src/ports/delegation.contract.test.ts +428 -0
- package/src/ports/delegation.ts +211 -0
- package/src/ports/event-bus.ts +133 -18
- package/src/ports/federation.contract.test.ts +355 -0
- package/src/ports/federation.ts +190 -0
- package/src/ports/index.ts +186 -1
- package/src/ports/llm-provider.ts +123 -0
- package/src/ports/logger.ts +104 -0
- package/src/ports/manifest-registry.contract.test.ts +324 -0
- package/src/ports/manifest-registry.ts +188 -0
- package/src/ports/observability.contract.test.ts +315 -0
- package/src/ports/observability.ts +150 -0
- package/src/ports/outcome.ts +69 -0
- package/src/ports/privacy.contract.test.ts +413 -0
- package/src/ports/privacy.ts +207 -0
- package/src/ports/tenant-context.contract.test.ts +454 -0
- package/src/ports/tenant-context.ts +150 -0
- package/src/ports/vauban-finance-action.contract.test.ts +335 -0
- package/src/ports/vauban-finance-action.ts +166 -0
- package/src/ports/workflow-runtime.ts +327 -0
- package/src/proof/cert-verify.ts +249 -0
- package/src/replay/replay.ts +11 -8
- package/src/retry/index.ts +227 -0
- package/src/retry/presets.ts +75 -0
- package/src/skill-loop/ab-runner.ts +196 -0
- package/src/skill-loop/adoption.ts +188 -0
- package/src/skill-loop/candidate.ts +75 -0
- package/src/skill-loop/evaluator.ts +238 -0
- package/src/skill-loop/index.ts +51 -0
- package/src/skill-loop/reflexion-replay.ts +173 -0
- package/src/skill-loop/sign-off.ts +247 -0
- package/src/skill-loop/value-metric.ts +120 -0
- package/src/skill-loop/versioning.ts +75 -0
- package/src/skill-manifest/anchor.ts +401 -0
- package/src/skill-manifest/builder.ts +129 -0
- package/src/skill-manifest/index.ts +18 -0
- package/src/skill-manifest/types.ts +72 -0
- package/src/skill-manifest/verifier.ts +198 -0
- package/src/skills/errors.ts +30 -2
- package/src/skills/index.ts +19 -0
- package/src/skills/markdown/loader.ts +129 -0
- package/src/skills/markdown/schema.ts +144 -0
- package/src/skills/poc-md-loader/e2e-parity.test.ts +237 -0
- package/src/skills/poc-md-loader/markdown-loader.ts +161 -0
- package/src/skills/poc-md-loader/runner.ts +82 -0
- package/src/skills/poc-md-loader/vitest.poc.config.ts +13 -0
- package/src/skills/poc-md-loader/web-search/SKILL.md +42 -0
- package/src/skills/poc-md-loader/web-search/script.ts +109 -0
- package/src/skills/send-email.ts +15 -3
- package/src/testing/contracts/event-bus.contract.ts +16 -14
- package/src/testing/test-brain-port.ts +98 -24
- package/src/testing/test-event-bus.ts +104 -43
- package/src/trace/schema.ts +1 -1
- package/src/verify/formal/index.ts +154 -0
- package/src/verify/formal/policy.ts +253 -0
- package/src/verify/formal/result.ts +52 -0
- package/src/verify/formal/solver.ts +235 -0
- package/src/verify/formal/spec-language.ts +274 -0
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* E2E parity test — POC-B SKILL.md vs original web-search.ts
|
|
3
|
+
*
|
|
4
|
+
* Runs BOTH the original TS skill and the MD-loaded variant against
|
|
5
|
+
* the same mocked fetch, then compares output shape + content.
|
|
6
|
+
* Measures cold start of the MD loader path.
|
|
7
|
+
*
|
|
8
|
+
* No network calls — fetch is mocked via globalThis.fetch override.
|
|
9
|
+
*
|
|
10
|
+
* @poc-jetable
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import { describe, it, expect, beforeEach, afterEach, vi } from "vitest";
|
|
14
|
+
import { join, dirname } from "node:path";
|
|
15
|
+
import { fileURLToPath } from "node:url";
|
|
16
|
+
|
|
17
|
+
// ── Original skill (TS) ───────────────────────────────────────────────────────
|
|
18
|
+
import { webSearch } from "../web-search.js";
|
|
19
|
+
import type { WebSearchOutput } from "../web-search.js";
|
|
20
|
+
|
|
21
|
+
// ── POC loader ────────────────────────────────────────────────────────────────
|
|
22
|
+
import { loadSkillMd } from "./markdown-loader.js";
|
|
23
|
+
import { runSkillMd } from "./runner.js";
|
|
24
|
+
|
|
25
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
26
|
+
const SKILL_DIR = join(__dirname, "web-search");
|
|
27
|
+
|
|
28
|
+
// ── Mock fetch helpers ────────────────────────────────────────────────────────
|
|
29
|
+
|
|
30
|
+
const BRAVE_MOCK_RESPONSE = {
|
|
31
|
+
web: {
|
|
32
|
+
results: [
|
|
33
|
+
{
|
|
34
|
+
title: "Mock Result 1",
|
|
35
|
+
url: "https://example.com/1",
|
|
36
|
+
description: "Snippet one",
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
title: "Mock Result 2",
|
|
40
|
+
url: "https://example.com/2",
|
|
41
|
+
description: "Snippet two",
|
|
42
|
+
},
|
|
43
|
+
],
|
|
44
|
+
},
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
function mockFetch(response: unknown, status = 200) {
|
|
48
|
+
return vi.fn().mockResolvedValue({
|
|
49
|
+
ok: status >= 200 && status < 300,
|
|
50
|
+
status,
|
|
51
|
+
json: async () => response,
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// ── Replay context for original skill ────────────────────────────────────────
|
|
56
|
+
|
|
57
|
+
const REPLAY_CTX = {
|
|
58
|
+
isReplay: true,
|
|
59
|
+
dryRunMocks: {
|
|
60
|
+
web_search: (_input: unknown) => ({
|
|
61
|
+
results: [
|
|
62
|
+
{
|
|
63
|
+
title: "Mock Result 1",
|
|
64
|
+
url: "https://example.com/1",
|
|
65
|
+
snippet: "Snippet one",
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
title: "Mock Result 2",
|
|
69
|
+
url: "https://example.com/2",
|
|
70
|
+
snippet: "Snippet two",
|
|
71
|
+
},
|
|
72
|
+
],
|
|
73
|
+
provider: "replay" as const,
|
|
74
|
+
}),
|
|
75
|
+
},
|
|
76
|
+
agentId: "poc-test",
|
|
77
|
+
runId: "poc-run-1",
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
// ── Tests ─────────────────────────────────────────────────────────────────────
|
|
81
|
+
|
|
82
|
+
describe("POC-B: SKILL.md parity + cold start", () => {
|
|
83
|
+
let originalFetch: typeof globalThis.fetch;
|
|
84
|
+
|
|
85
|
+
beforeEach(() => {
|
|
86
|
+
originalFetch = globalThis.fetch;
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
afterEach(() => {
|
|
90
|
+
globalThis.fetch = originalFetch;
|
|
91
|
+
delete process.env.BRAVE_SEARCH_KEY;
|
|
92
|
+
delete process.env.TAVILY_API_KEY;
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
// ── 1. Manifest loading ──────────────────────────────────────────────────
|
|
96
|
+
|
|
97
|
+
it("loads SKILL.md and returns valid manifest", async () => {
|
|
98
|
+
const { manifest } = await loadSkillMd(join(SKILL_DIR, "SKILL.md"));
|
|
99
|
+
|
|
100
|
+
expect(manifest.name).toBe("web-search");
|
|
101
|
+
expect(manifest.description).toBeTruthy();
|
|
102
|
+
expect(manifest.description.length).toBeLessThanOrEqual(1024);
|
|
103
|
+
expect(manifest["allowed-tools"]).toBe("Bash(curl:*)");
|
|
104
|
+
expect(manifest.metadata?.version).toBe("1.0.0");
|
|
105
|
+
expect(manifest.metadata?.category).toBe("search");
|
|
106
|
+
expect(manifest.metadata?.["env-mode"]).toBe("at-least-one");
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
// ── 2. Output shape parity (replay vs MD) ───────────────────────────────
|
|
110
|
+
|
|
111
|
+
it("MD output shape matches original skill output shape (replay)", async () => {
|
|
112
|
+
// Original skill in replay mode
|
|
113
|
+
const originalOutput = await webSearch.execute(
|
|
114
|
+
{ query: "test", limit: 2 },
|
|
115
|
+
REPLAY_CTX as never
|
|
116
|
+
);
|
|
117
|
+
|
|
118
|
+
// MD script in replay mode (mock fetch, BRAVE_SEARCH_KEY set → path taken but mocked)
|
|
119
|
+
process.env.BRAVE_SEARCH_KEY = "test-key";
|
|
120
|
+
globalThis.fetch = mockFetch(BRAVE_MOCK_RESPONSE) as never;
|
|
121
|
+
|
|
122
|
+
const { output: mdOutput } = await runSkillMd<WebSearchOutput>(SKILL_DIR, {
|
|
123
|
+
query: "test",
|
|
124
|
+
limit: 2,
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
// Shape parity: both have results[] and provider
|
|
128
|
+
expect(Object.keys(mdOutput)).toEqual(
|
|
129
|
+
expect.arrayContaining(["results", "provider"])
|
|
130
|
+
);
|
|
131
|
+
expect(Array.isArray(mdOutput.results)).toBe(true);
|
|
132
|
+
|
|
133
|
+
// Original replay returns empty results (no mock for live), MD returns from brave mock
|
|
134
|
+
// Key parity: result items have title/url/snippet
|
|
135
|
+
if (mdOutput.results.length > 0) {
|
|
136
|
+
const r = mdOutput.results[0];
|
|
137
|
+
expect(r).toHaveProperty("title");
|
|
138
|
+
expect(r).toHaveProperty("url");
|
|
139
|
+
expect(r).toHaveProperty("snippet");
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
// Provider field exists and is valid
|
|
143
|
+
expect(["brave", "tavily", "replay"]).toContain(mdOutput.provider);
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
// ── 3. Live path parity (both use mocked fetch, same brave response) ────
|
|
147
|
+
|
|
148
|
+
it("MD script returns same data as original skill on Brave success path", async () => {
|
|
149
|
+
process.env.BRAVE_SEARCH_KEY = "test-brave-key";
|
|
150
|
+
globalThis.fetch = mockFetch(BRAVE_MOCK_RESPONSE) as never;
|
|
151
|
+
|
|
152
|
+
// Original skill — live path with mocked fetch
|
|
153
|
+
const originalOutput = await webSearch.execute(
|
|
154
|
+
{ query: "starknet", limit: 2 },
|
|
155
|
+
{ isReplay: false, dryRunMocks: {}, agentId: "poc", runId: "r1" } as never
|
|
156
|
+
);
|
|
157
|
+
|
|
158
|
+
// Reset mock (fresh call counter)
|
|
159
|
+
globalThis.fetch = mockFetch(BRAVE_MOCK_RESPONSE) as never;
|
|
160
|
+
|
|
161
|
+
const { output: mdOutput } = await runSkillMd<WebSearchOutput>(SKILL_DIR, {
|
|
162
|
+
query: "starknet",
|
|
163
|
+
limit: 2,
|
|
164
|
+
});
|
|
165
|
+
|
|
166
|
+
// Full output equality
|
|
167
|
+
expect(mdOutput.provider).toBe(originalOutput.provider);
|
|
168
|
+
expect(mdOutput.results).toEqual(originalOutput.results);
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
// ── 4. Tavily fallback parity ────────────────────────────────────────────
|
|
172
|
+
|
|
173
|
+
it("MD script Tavily fallback matches original skill", async () => {
|
|
174
|
+
process.env.TAVILY_API_KEY = "test-tavily-key";
|
|
175
|
+
// No BRAVE key → goes straight to Tavily
|
|
176
|
+
|
|
177
|
+
const tavilyMock = {
|
|
178
|
+
results: [
|
|
179
|
+
{
|
|
180
|
+
title: "Tavily R1",
|
|
181
|
+
url: "https://tavily.com/1",
|
|
182
|
+
content: "Tavily snippet 1",
|
|
183
|
+
},
|
|
184
|
+
],
|
|
185
|
+
};
|
|
186
|
+
|
|
187
|
+
globalThis.fetch = mockFetch(tavilyMock) as never;
|
|
188
|
+
const originalOutput = await webSearch.execute(
|
|
189
|
+
{ query: "cairo", limit: 1 },
|
|
190
|
+
{ isReplay: false, dryRunMocks: {}, agentId: "poc", runId: "r2" } as never
|
|
191
|
+
);
|
|
192
|
+
|
|
193
|
+
globalThis.fetch = mockFetch(tavilyMock) as never;
|
|
194
|
+
const { output: mdOutput } = await runSkillMd<WebSearchOutput>(SKILL_DIR, {
|
|
195
|
+
query: "cairo",
|
|
196
|
+
limit: 1,
|
|
197
|
+
});
|
|
198
|
+
|
|
199
|
+
expect(mdOutput.provider).toBe("tavily");
|
|
200
|
+
expect(mdOutput.provider).toBe(originalOutput.provider);
|
|
201
|
+
expect(mdOutput.results).toEqual(originalOutput.results);
|
|
202
|
+
});
|
|
203
|
+
|
|
204
|
+
// ── 5. Error parity: missing env ────────────────────────────────────────
|
|
205
|
+
|
|
206
|
+
it("MD runner throws when no API key configured (env-mode: at-least-one)", async () => {
|
|
207
|
+
// No BRAVE_SEARCH_KEY, no TAVILY_API_KEY
|
|
208
|
+
await expect(runSkillMd(SKILL_DIR, { query: "test" })).rejects.toThrow(
|
|
209
|
+
/at least one of/i
|
|
210
|
+
);
|
|
211
|
+
});
|
|
212
|
+
|
|
213
|
+
// ── 6. Cold start measurement ────────────────────────────────────────────
|
|
214
|
+
|
|
215
|
+
it("cold start (load+parse+execute) is under 500ms", async () => {
|
|
216
|
+
process.env.BRAVE_SEARCH_KEY = "perf-test-key";
|
|
217
|
+
globalThis.fetch = mockFetch(BRAVE_MOCK_RESPONSE) as never;
|
|
218
|
+
|
|
219
|
+
const t0 = performance.now();
|
|
220
|
+
const { coldStartMs } = await runSkillMd(SKILL_DIR, {
|
|
221
|
+
query: "perf",
|
|
222
|
+
limit: 1,
|
|
223
|
+
});
|
|
224
|
+
const wallMs = performance.now() - t0;
|
|
225
|
+
|
|
226
|
+
console.log(
|
|
227
|
+
`[POC-B] cold start: ${coldStartMs.toFixed(2)}ms (wall: ${wallMs.toFixed(
|
|
228
|
+
2
|
|
229
|
+
)}ms)`
|
|
230
|
+
);
|
|
231
|
+
|
|
232
|
+
// Primary assertion
|
|
233
|
+
expect(coldStartMs).toBeLessThan(500);
|
|
234
|
+
// Sanity: internal timer matches wall clock within 50ms
|
|
235
|
+
expect(Math.abs(coldStartMs - wallMs)).toBeLessThan(50);
|
|
236
|
+
});
|
|
237
|
+
});
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* markdown-loader — prototype SKILL.md parser.
|
|
3
|
+
*
|
|
4
|
+
* Parses frontmatter (YAML-subset, no external dep) + markdown body.
|
|
5
|
+
* Returns a typed SkillManifest validated against a Zod schema.
|
|
6
|
+
*
|
|
7
|
+
* Constraint: no new npm deps — uses only node:fs/promises + zod (already in pkg).
|
|
8
|
+
*
|
|
9
|
+
* @poc-jetable
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import { readFile } from "node:fs/promises";
|
|
13
|
+
import { z } from "zod";
|
|
14
|
+
|
|
15
|
+
// ── Zod schema for SKILL.md frontmatter ──────────────────────────────────────
|
|
16
|
+
|
|
17
|
+
const MetadataSchema = z
|
|
18
|
+
.object({
|
|
19
|
+
version: z.string().default("1.0.0"),
|
|
20
|
+
category: z.string().optional(),
|
|
21
|
+
tags: z.string().optional(),
|
|
22
|
+
"model-hint": z.string().optional(),
|
|
23
|
+
"env-required": z.string().optional(),
|
|
24
|
+
"env-mode": z.enum(["all", "at-least-one"]).default("all"),
|
|
25
|
+
})
|
|
26
|
+
.strict();
|
|
27
|
+
|
|
28
|
+
export const SkillManifestSchema = z
|
|
29
|
+
.object({
|
|
30
|
+
/** kebab-case, 1-64 chars */
|
|
31
|
+
name: z
|
|
32
|
+
.string()
|
|
33
|
+
.min(1)
|
|
34
|
+
.max(64)
|
|
35
|
+
.regex(/^[a-z0-9-]+$/, "name must be kebab-case"),
|
|
36
|
+
/** 1-1024 chars */
|
|
37
|
+
description: z.string().min(1).max(1024),
|
|
38
|
+
/** Space-separated tool grant list, e.g. "Bash(curl:*) Read" */
|
|
39
|
+
"allowed-tools": z.string().optional(),
|
|
40
|
+
metadata: MetadataSchema.optional(),
|
|
41
|
+
})
|
|
42
|
+
.strict();
|
|
43
|
+
|
|
44
|
+
export type SkillManifest = z.infer<typeof SkillManifestSchema>;
|
|
45
|
+
|
|
46
|
+
// ── Minimal YAML-subset parser (no external dep) ─────────────────────────────
|
|
47
|
+
// Supports: string scalars, nested objects (2-space indent), multi-line > strings.
|
|
48
|
+
|
|
49
|
+
function parseYamlSubset(raw: string): Record<string, unknown> {
|
|
50
|
+
const lines = raw.split("\n");
|
|
51
|
+
const result: Record<string, unknown> = {};
|
|
52
|
+
let i = 0;
|
|
53
|
+
|
|
54
|
+
while (i < lines.length) {
|
|
55
|
+
const line = lines[i];
|
|
56
|
+
if (!line.trim() || line.trim().startsWith("#")) {
|
|
57
|
+
i++;
|
|
58
|
+
continue;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const colonIdx = line.indexOf(":");
|
|
62
|
+
if (colonIdx === -1) {
|
|
63
|
+
i++;
|
|
64
|
+
continue;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
const indent = line.match(/^(\s*)/)?.[1].length ?? 0;
|
|
68
|
+
if (indent > 0) {
|
|
69
|
+
// nested key — handled by parent
|
|
70
|
+
i++;
|
|
71
|
+
continue;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
const key = line.slice(0, colonIdx).trim();
|
|
75
|
+
const rest = line.slice(colonIdx + 1).trim();
|
|
76
|
+
|
|
77
|
+
// Multi-line folded scalar (>) — collect continuation lines
|
|
78
|
+
if (rest === ">") {
|
|
79
|
+
const parts: string[] = [];
|
|
80
|
+
i++;
|
|
81
|
+
while (
|
|
82
|
+
i < lines.length &&
|
|
83
|
+
(lines[i].startsWith(" ") || lines[i].trim() === "")
|
|
84
|
+
) {
|
|
85
|
+
parts.push(lines[i].trim());
|
|
86
|
+
i++;
|
|
87
|
+
}
|
|
88
|
+
result[key] = parts.filter(Boolean).join(" ");
|
|
89
|
+
continue;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// Nested object — collect child lines with 2-space indent
|
|
93
|
+
if (rest === "") {
|
|
94
|
+
const childLines: string[] = [];
|
|
95
|
+
i++;
|
|
96
|
+
while (i < lines.length && lines[i].startsWith(" ")) {
|
|
97
|
+
childLines.push(lines[i].slice(2)); // strip 2-space indent
|
|
98
|
+
i++;
|
|
99
|
+
}
|
|
100
|
+
if (childLines.length > 0) {
|
|
101
|
+
result[key] = parseYamlSubset(childLines.join("\n"));
|
|
102
|
+
}
|
|
103
|
+
continue;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// Quoted string
|
|
107
|
+
if (
|
|
108
|
+
(rest.startsWith('"') && rest.endsWith('"')) ||
|
|
109
|
+
(rest.startsWith("'") && rest.endsWith("'"))
|
|
110
|
+
) {
|
|
111
|
+
result[key] = rest.slice(1, -1);
|
|
112
|
+
i++;
|
|
113
|
+
continue;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// Plain scalar
|
|
117
|
+
result[key] = rest;
|
|
118
|
+
i++;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
return result;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// ── SKILL.md parser ───────────────────────────────────────────────────────────
|
|
125
|
+
|
|
126
|
+
export interface ParsedSkillFile {
|
|
127
|
+
manifest: SkillManifest;
|
|
128
|
+
body: string;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* Parse a SKILL.md file at `filePath`.
|
|
133
|
+
* Extracts frontmatter (between --- delimiters) and validates with Zod.
|
|
134
|
+
* Returns typed manifest + raw markdown body.
|
|
135
|
+
*/
|
|
136
|
+
export async function loadSkillMd(filePath: string): Promise<ParsedSkillFile> {
|
|
137
|
+
const raw = await readFile(filePath, "utf-8");
|
|
138
|
+
|
|
139
|
+
// Extract frontmatter block
|
|
140
|
+
const fmMatch = raw.match(/^---\r?\n([\s\S]*?)\r?\n---\r?\n([\s\S]*)$/);
|
|
141
|
+
if (!fmMatch) {
|
|
142
|
+
throw new Error(
|
|
143
|
+
`SKILL.md at ${filePath}: missing or malformed frontmatter (expected --- delimiters)`
|
|
144
|
+
);
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
const [, frontmatter, body] = fmMatch;
|
|
148
|
+
const rawParsed = parseYamlSubset(frontmatter);
|
|
149
|
+
|
|
150
|
+
// Validate with Zod
|
|
151
|
+
const result = SkillManifestSchema.safeParse(rawParsed);
|
|
152
|
+
if (!result.success) {
|
|
153
|
+
throw new Error(
|
|
154
|
+
`SKILL.md at ${filePath}: invalid frontmatter — ${result.error.issues
|
|
155
|
+
.map((i) => `${i.path.join(".")}: ${i.message}`)
|
|
156
|
+
.join("; ")}`
|
|
157
|
+
);
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
return { manifest: result.data, body: body.trim() };
|
|
161
|
+
}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* runner — prototype SKILL.md execution harness.
|
|
3
|
+
*
|
|
4
|
+
* Loads a SKILL.md manifest, validates env requirements,
|
|
5
|
+
* dynamically imports the companion script.ts, and executes it.
|
|
6
|
+
*
|
|
7
|
+
* No integration with SkillRegistry — standalone POC harness only.
|
|
8
|
+
*
|
|
9
|
+
* @poc-jetable
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import { join } from "node:path";
|
|
13
|
+
import { loadSkillMd, type SkillManifest } from "./markdown-loader.js";
|
|
14
|
+
|
|
15
|
+
export interface RunnerResult<T = unknown> {
|
|
16
|
+
output: T;
|
|
17
|
+
manifest: SkillManifest;
|
|
18
|
+
coldStartMs: number;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Run a SKILL.md skill by directory path.
|
|
23
|
+
*
|
|
24
|
+
* @param skillDir Absolute path to directory containing SKILL.md + script.ts
|
|
25
|
+
* @param input Raw input object passed to script.execute()
|
|
26
|
+
*/
|
|
27
|
+
export async function runSkillMd<T = unknown>(
|
|
28
|
+
skillDir: string,
|
|
29
|
+
input: unknown
|
|
30
|
+
): Promise<RunnerResult<T>> {
|
|
31
|
+
const t0 = performance.now();
|
|
32
|
+
|
|
33
|
+
// Step 1: Load + validate SKILL.md
|
|
34
|
+
const skillMdPath = join(skillDir, "SKILL.md");
|
|
35
|
+
const { manifest } = await loadSkillMd(skillMdPath);
|
|
36
|
+
|
|
37
|
+
// Step 2: Check env requirements
|
|
38
|
+
const envRequired = manifest.metadata?.["env-required"];
|
|
39
|
+
const envMode = manifest.metadata?.["env-mode"] ?? "all";
|
|
40
|
+
if (envRequired) {
|
|
41
|
+
const keys = envRequired.split(" ").filter(Boolean);
|
|
42
|
+
const missing = keys.filter((k) => !process.env[k]);
|
|
43
|
+
if (envMode === "all" && missing.length > 0) {
|
|
44
|
+
throw new Error(
|
|
45
|
+
`Skill '${manifest.name}': missing required env vars: ${missing.join(
|
|
46
|
+
", "
|
|
47
|
+
)}`
|
|
48
|
+
);
|
|
49
|
+
}
|
|
50
|
+
if (envMode === "at-least-one" && missing.length === keys.length) {
|
|
51
|
+
throw new Error(
|
|
52
|
+
`Skill '${manifest.name}': at least one of ${keys.join(
|
|
53
|
+
", "
|
|
54
|
+
)} must be set`
|
|
55
|
+
);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// Step 3: Dynamic import of companion script
|
|
60
|
+
const scriptPath = join(skillDir, "script.js");
|
|
61
|
+
// In test context (tsx/ts-node), import .ts directly; in compiled, import .js
|
|
62
|
+
let scriptModule: { execute: (input: unknown) => Promise<T> };
|
|
63
|
+
try {
|
|
64
|
+
scriptModule = (await import(scriptPath)) as typeof scriptModule;
|
|
65
|
+
} catch {
|
|
66
|
+
// Fallback: try .ts extension (tsx / ts-node context)
|
|
67
|
+
const scriptTsPath = join(skillDir, "script.ts");
|
|
68
|
+
scriptModule = (await import(scriptTsPath)) as typeof scriptModule;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
if (typeof scriptModule.execute !== "function") {
|
|
72
|
+
throw new Error(
|
|
73
|
+
`Skill '${manifest.name}': script must export an execute() function`
|
|
74
|
+
);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// Step 4: Execute
|
|
78
|
+
const output = await scriptModule.execute(input);
|
|
79
|
+
const coldStartMs = performance.now() - t0;
|
|
80
|
+
|
|
81
|
+
return { output, manifest, coldStartMs };
|
|
82
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Vitest config for POC-B tests only — not part of production test suite.
|
|
3
|
+
* @poc-jetable
|
|
4
|
+
*/
|
|
5
|
+
import { defineConfig } from "vitest/config";
|
|
6
|
+
|
|
7
|
+
export default defineConfig({
|
|
8
|
+
test: {
|
|
9
|
+
environment: "node",
|
|
10
|
+
include: ["src/skills/poc-md-loader/**/*.test.ts"],
|
|
11
|
+
globals: false,
|
|
12
|
+
},
|
|
13
|
+
});
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: web-search
|
|
3
|
+
description: >
|
|
4
|
+
Search the web using Brave Search API (primary) or Tavily (fallback).
|
|
5
|
+
Returns ranked results with title, URL, and snippet. Requires at least
|
|
6
|
+
one of BRAVE_SEARCH_KEY or TAVILY_API_KEY environment variables.
|
|
7
|
+
allowed-tools: "Bash(curl:*)"
|
|
8
|
+
metadata:
|
|
9
|
+
version: "1.0.0"
|
|
10
|
+
category: "search"
|
|
11
|
+
tags: "brave tavily web-search"
|
|
12
|
+
model-hint: "sonnet"
|
|
13
|
+
env-required: "BRAVE_SEARCH_KEY TAVILY_API_KEY"
|
|
14
|
+
env-mode: "at-least-one"
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
# web-search
|
|
18
|
+
|
|
19
|
+
Searches the web and returns structured results.
|
|
20
|
+
|
|
21
|
+
## Input
|
|
22
|
+
|
|
23
|
+
| Field | Type | Required | Default | Description |
|
|
24
|
+
|---------|---------|----------|---------|--------------------------|
|
|
25
|
+
| `query` | string | yes | — | Search query (1-512 chars) |
|
|
26
|
+
| `limit` | integer | no | 5 | Max results (1-20) |
|
|
27
|
+
|
|
28
|
+
## Output
|
|
29
|
+
|
|
30
|
+
```json
|
|
31
|
+
{
|
|
32
|
+
"results": [
|
|
33
|
+
{ "title": "...", "url": "...", "snippet": "..." }
|
|
34
|
+
],
|
|
35
|
+
"provider": "brave | tavily | replay"
|
|
36
|
+
}
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## Execution
|
|
40
|
+
|
|
41
|
+
See `script.ts` for the execution logic. The script implements the same
|
|
42
|
+
Brave → Tavily fallback chain as the original `web-search.ts` TS skill.
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* web-search execution script — POC MD loader variant.
|
|
3
|
+
*
|
|
4
|
+
* Identical logic to web-search.ts but as a standalone function
|
|
5
|
+
* with no SDK imports (no Skill<> interface, no withSkillSpan, no errors.ts).
|
|
6
|
+
* This measures the "pure script" execution path of the SKILL.md pattern.
|
|
7
|
+
*
|
|
8
|
+
* @poc-jetable
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
export interface WebSearchInput {
|
|
12
|
+
query: string;
|
|
13
|
+
limit?: number;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export interface WebSearchResult {
|
|
17
|
+
title: string;
|
|
18
|
+
url: string;
|
|
19
|
+
snippet: string;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export interface WebSearchOutput {
|
|
23
|
+
results: WebSearchResult[];
|
|
24
|
+
provider: "brave" | "tavily" | "replay";
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export class SkillNotConfiguredError extends Error {
|
|
28
|
+
constructor(missing: string[]) {
|
|
29
|
+
super(`web-search not configured: missing env ${missing.join(", ")}`);
|
|
30
|
+
this.name = "SkillNotConfiguredError";
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export class SkillExecutionError extends Error {
|
|
35
|
+
constructor(message: string) {
|
|
36
|
+
super(`web-search failed: ${message}`);
|
|
37
|
+
this.name = "SkillExecutionError";
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Execute web search. Same logic as web-search.ts#webSearch.execute().
|
|
43
|
+
*/
|
|
44
|
+
export async function execute(input: WebSearchInput): Promise<WebSearchOutput> {
|
|
45
|
+
const query = input.query;
|
|
46
|
+
const limit = input.limit ?? 5;
|
|
47
|
+
|
|
48
|
+
const braveKey = process.env.BRAVE_SEARCH_KEY;
|
|
49
|
+
const tavilyKey = process.env.TAVILY_API_KEY;
|
|
50
|
+
|
|
51
|
+
if (!braveKey && !tavilyKey) {
|
|
52
|
+
throw new SkillNotConfiguredError(["BRAVE_SEARCH_KEY", "TAVILY_API_KEY"]);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
if (braveKey) {
|
|
56
|
+
const url = `https://api.search.brave.com/res/v1/web/search?q=${encodeURIComponent(
|
|
57
|
+
query
|
|
58
|
+
)}&count=${limit}`;
|
|
59
|
+
const res = await fetch(url, {
|
|
60
|
+
headers: {
|
|
61
|
+
Accept: "application/json",
|
|
62
|
+
"X-Subscription-Token": braveKey,
|
|
63
|
+
},
|
|
64
|
+
});
|
|
65
|
+
if (res.ok) {
|
|
66
|
+
const data = (await res.json()) as {
|
|
67
|
+
web?: {
|
|
68
|
+
results?: Array<{
|
|
69
|
+
title?: string;
|
|
70
|
+
url?: string;
|
|
71
|
+
description?: string;
|
|
72
|
+
}>;
|
|
73
|
+
};
|
|
74
|
+
};
|
|
75
|
+
const results: WebSearchResult[] = (data.web?.results ?? []).map((r) => ({
|
|
76
|
+
title: r.title ?? "",
|
|
77
|
+
url: r.url ?? "",
|
|
78
|
+
snippet: r.description ?? "",
|
|
79
|
+
}));
|
|
80
|
+
return { results, provider: "brave" };
|
|
81
|
+
}
|
|
82
|
+
if (!tavilyKey) {
|
|
83
|
+
throw new SkillExecutionError(`brave ${res.status}`);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// Tavily fallback
|
|
88
|
+
const res = await fetch("https://api.tavily.com/search", {
|
|
89
|
+
method: "POST",
|
|
90
|
+
headers: { "Content-Type": "application/json" },
|
|
91
|
+
body: JSON.stringify({
|
|
92
|
+
api_key: tavilyKey,
|
|
93
|
+
query,
|
|
94
|
+
max_results: limit,
|
|
95
|
+
}),
|
|
96
|
+
});
|
|
97
|
+
if (!res.ok) {
|
|
98
|
+
throw new SkillExecutionError(`tavily ${res.status}`);
|
|
99
|
+
}
|
|
100
|
+
const data = (await res.json()) as {
|
|
101
|
+
results?: Array<{ title?: string; url?: string; content?: string }>;
|
|
102
|
+
};
|
|
103
|
+
const results: WebSearchResult[] = (data.results ?? []).map((r) => ({
|
|
104
|
+
title: r.title ?? "",
|
|
105
|
+
url: r.url ?? "",
|
|
106
|
+
snippet: r.content ?? "",
|
|
107
|
+
}));
|
|
108
|
+
return { results, provider: "tavily" };
|
|
109
|
+
}
|
package/src/skills/send-email.ts
CHANGED
|
@@ -29,6 +29,18 @@ export interface SendEmailOutput {
|
|
|
29
29
|
message_id: string | null;
|
|
30
30
|
}
|
|
31
31
|
|
|
32
|
+
/**
|
|
33
|
+
* Prefer ctx.secrets (audit-trail-bearing) over process.env. When no secrets
|
|
34
|
+
* accessor is configured, falls back to env so legacy callers see no behavior
|
|
35
|
+
* change. When the secret is absent in both, returns undefined.
|
|
36
|
+
*/
|
|
37
|
+
function readSecret(ctx: SkillContext, name: string): string | undefined {
|
|
38
|
+
if (ctx.secrets) {
|
|
39
|
+
if (ctx.secrets.has(name)) return ctx.secrets.get(name);
|
|
40
|
+
}
|
|
41
|
+
return process.env[name];
|
|
42
|
+
}
|
|
43
|
+
|
|
32
44
|
export const sendEmail: Skill<SendEmailInput, SendEmailOutput> = {
|
|
33
45
|
name: "send_email",
|
|
34
46
|
inputSchema,
|
|
@@ -39,9 +51,9 @@ export const sendEmail: Skill<SendEmailInput, SendEmailOutput> = {
|
|
|
39
51
|
return { delivered: false, provider: "replay", message_id: null };
|
|
40
52
|
}
|
|
41
53
|
return withSkillSpan("send_email", async () => {
|
|
42
|
-
const resendKey =
|
|
43
|
-
const smtpUrl =
|
|
44
|
-
const defaultFrom =
|
|
54
|
+
const resendKey = readSecret(ctx, "RESEND_API_KEY");
|
|
55
|
+
const smtpUrl = readSecret(ctx, "SMTP_URL");
|
|
56
|
+
const defaultFrom = readSecret(ctx, "EMAIL_FROM") ?? input.from;
|
|
45
57
|
if (!resendKey && !smtpUrl) {
|
|
46
58
|
throw new SkillNotConfiguredError("send_email", [
|
|
47
59
|
"RESEND_API_KEY",
|