@bluefly/openstandardagents 0.5.0 → 0.5.1

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.
Files changed (170) hide show
  1. package/.version.json +3 -3
  2. package/CHANGELOG.md +43 -12
  3. package/README.md +31 -26
  4. package/bin/postinstall +0 -0
  5. package/dist/.version.json +3 -3
  6. package/dist/adapters/a2a/a2a-protocol.js +4 -2
  7. package/dist/adapters/a2a/a2a-tool.js +4 -2
  8. package/dist/adapters/a2a/mcp-integration.d.ts +2 -1
  9. package/dist/adapters/a2a/mcp-integration.js +6 -3
  10. package/dist/adapters/browser/browser-exporter.d.ts +26 -0
  11. package/dist/adapters/browser/browser-exporter.js +73 -0
  12. package/dist/adapters/browser/browser-runner.d.ts +23 -0
  13. package/dist/adapters/browser/browser-runner.js +46 -0
  14. package/dist/adapters/browser/index.d.ts +9 -0
  15. package/dist/adapters/browser/index.js +9 -0
  16. package/dist/adapters/docker/index.d.ts +2 -0
  17. package/dist/adapters/docker/index.js +2 -0
  18. package/dist/adapters/docker/openclaw-bridge.d.ts +57 -0
  19. package/dist/adapters/docker/openclaw-bridge.js +173 -0
  20. package/dist/adapters/drupal/index.d.ts +1 -0
  21. package/dist/adapters/drupal/index.js +2 -0
  22. package/dist/adapters/drupal/twig-renderer.d.ts +23 -0
  23. package/dist/adapters/drupal/twig-renderer.js +99 -0
  24. package/dist/adapters/gitlab/agent-generator.js +2 -1
  25. package/dist/api/index.js +2 -1
  26. package/dist/api/routes/mcp.router.js +3 -1
  27. package/dist/api/routes/wizard.router.js +3 -1
  28. package/dist/cli/commands/agent/discover-type.command.js +1 -1
  29. package/dist/cli/commands/agent-card.command.js +37 -10
  30. package/dist/cli/commands/agents-sync.command.d.ts +2 -2
  31. package/dist/cli/commands/agents-sync.command.js +27 -17
  32. package/dist/cli/commands/catalog/config.js +1 -1
  33. package/dist/cli/commands/catalog/validate.command.js +2 -2
  34. package/dist/cli/commands/config.command.js +2 -2
  35. package/dist/cli/commands/daemon.command.js +32 -8
  36. package/dist/cli/commands/discover.d.ts +1 -1
  37. package/dist/cli/commands/discover.js +16 -8
  38. package/dist/cli/commands/economics.command.d.ts +9 -0
  39. package/dist/cli/commands/economics.command.js +113 -0
  40. package/dist/cli/commands/export.command.js +6 -3
  41. package/dist/cli/commands/mcp.command.js +3 -1
  42. package/dist/cli/commands/memory.command.d.ts +18 -0
  43. package/dist/cli/commands/memory.command.js +168 -0
  44. package/dist/cli/commands/publish.command.js +7 -4
  45. package/dist/cli/commands/serve-builder-routes.js +1 -1
  46. package/dist/cli/commands/usie-skills.command.d.ts +24 -0
  47. package/dist/cli/commands/usie-skills.command.js +297 -0
  48. package/dist/cli/commands/validate.command.js +8 -1
  49. package/dist/cli/commands/verify.d.ts +3 -3
  50. package/dist/cli/commands/verify.js +12 -6
  51. package/dist/cli/commands/workspace.command.d.ts +1 -0
  52. package/dist/cli/commands/workspace.command.js +28 -4
  53. package/dist/cli/index.js +12 -0
  54. package/dist/cli/workspace-validate.d.ts +23 -0
  55. package/dist/cli/workspace-validate.js +117 -0
  56. package/dist/data/platform-matrix.js +1 -4
  57. package/dist/generated/types.d.ts +97 -97
  58. package/dist/index.d.ts +2 -0
  59. package/dist/index.js +2 -0
  60. package/dist/mcp-server/index.js +658 -982
  61. package/dist/mesh/discovery-gkg.d.ts +26 -0
  62. package/dist/mesh/discovery-gkg.js +92 -0
  63. package/dist/messenger/Handler/AgentBatchHandler.js +3 -2
  64. package/dist/messenger/Handler/AgentExecutionHandler.js +6 -1
  65. package/dist/package.json +20 -4
  66. package/dist/sdks/shared/types.d.ts +1 -1
  67. package/dist/services/agent-card-generator.js +6 -2
  68. package/dist/services/daemon/audit-log.service.js +3 -1
  69. package/dist/services/daemon/execution.service.js +8 -4
  70. package/dist/services/daemon/fs-watcher.service.js +6 -7
  71. package/dist/services/daemon/pairing.service.js +2 -1
  72. package/dist/services/daemon/skill-aggregator.service.js +105 -21
  73. package/dist/services/daemon/sse-endpoints.js +1 -1
  74. package/dist/services/daemon/ws-server.js +10 -3
  75. package/dist/services/governance/cedar-provider.js +12 -8
  76. package/dist/services/governance/cedar-validator.service.js +1 -1
  77. package/dist/services/mcp/bridge.service.js +40 -9
  78. package/dist/services/openapi-extensions-validation.d.ts +20 -0
  79. package/dist/services/openapi-extensions-validation.js +193 -0
  80. package/dist/services/release-automation/merge-request.service.d.ts +4 -4
  81. package/dist/services/release-automation/release-buttons.js +3 -3
  82. package/dist/services/release-automation/schemas/release.schema.d.ts +3 -3
  83. package/dist/services/runtime/openai.adapter.d.ts +46 -13
  84. package/dist/services/runtime/openai.adapter.js +169 -131
  85. package/dist/services/skill-registry.service.d.ts +1 -1
  86. package/dist/services/skills-pipeline/skills-research.service.js +47 -7
  87. package/dist/services/trust/trust.service.js +6 -4
  88. package/dist/services/validation-zod.service.js +3 -22
  89. package/dist/services/validators/index.d.ts +1 -0
  90. package/dist/services/validators/index.js +1 -0
  91. package/dist/services/validators/registry.d.ts +21 -0
  92. package/dist/services/validators/registry.js +42 -0
  93. package/dist/skills/test-skill/package.json +1 -1
  94. package/dist/spec/extensions/cognition.schema.json +87 -0
  95. package/dist/spec/layer4-economics/duadp-examples.json +44 -0
  96. package/dist/spec/v0.4/agent.schema.json +14 -0
  97. package/dist/spec/v0.5/agent-builder-openapi.yaml +230 -0
  98. package/dist/spec/v0.5/agent.schema.json +32 -1
  99. package/dist/spec/v0.5/extensions/cognition/cognition.schema.json +78 -1
  100. package/dist/spec/v0.5/extensions/economics/context-pack.schema.json +91 -0
  101. package/dist/spec/v0.5/extensions/economics/execution-profile.schema.json +148 -0
  102. package/dist/spec/v0.5/extensions/economics/failure-semantics.schema.json +32 -0
  103. package/dist/spec/v0.5/extensions/economics/replay-packet.schema.json +120 -0
  104. package/dist/spec/v0.5/extensions/mcp/README.md +1 -1
  105. package/dist/spec/v0.5/memory-hierarchy.yaml +120 -0
  106. package/dist/spec/v1/agent-card.schema.json +254 -0
  107. package/dist/types/cognition.zod.d.ts +312 -0
  108. package/dist/types/cognition.zod.js +223 -0
  109. package/dist/types/identity.zod.d.ts +5 -5
  110. package/dist/types/index.d.ts +53 -7
  111. package/dist/types/index.js +4 -2
  112. package/dist/types/personality.zod.d.ts +3 -3
  113. package/dist/utils/http-client.d.ts +22 -0
  114. package/dist/utils/http-client.js +51 -0
  115. package/dist/utils/index.d.ts +3 -0
  116. package/dist/utils/index.js +3 -0
  117. package/dist/utils/proxy-resolver.d.ts +36 -0
  118. package/dist/utils/proxy-resolver.js +59 -0
  119. package/dist/utils/user-agent.d.ts +11 -0
  120. package/dist/utils/user-agent.js +17 -0
  121. package/dist/validation/version-compliance.js +1 -1
  122. package/examples/agentscope/react-assistant/README.md +1 -1
  123. package/examples/agentscope/react-assistant/agent.ossa.yaml +1 -1
  124. package/examples/drupal/drupal-contributor-agent/.eslintrc.json +58 -0
  125. package/examples/drupal/drupal-contributor-agent/.prettierrc.json +10 -0
  126. package/examples/drupal/drupal-contributor-agent/package.json +55 -0
  127. package/examples/drupal/drupal-contributor-agent/src/core/index.ts +10 -0
  128. package/examples/drupal/drupal-contributor-agent/src/index.ts +17 -0
  129. package/examples/drupal/drupal-contributor-agent/src/types/index.ts +180 -0
  130. package/examples/drupal/drupal-contributor-agent/tsconfig.json +36 -0
  131. package/examples/getting-started/01-minimal-agent.ossa.yaml +1 -1
  132. package/examples/getting-started/02-agent-with-tools.ossa.yaml +1 -1
  133. package/examples/getting-started/03-agent-with-safety.ossa.yaml +1 -1
  134. package/examples/getting-started/04-agent-with-messaging.ossa.yaml +1 -1
  135. package/examples/getting-started/05-workflow-composition.ossa.yaml +1 -1
  136. package/examples/getting-started/hello-world-complete.ossa.yaml +1 -1
  137. package/examples/reference-implementations/python-client/examples/basic_usage.py +0 -0
  138. package/examples/reference-implementations/python-client/examples/publish_agent.py +0 -0
  139. package/openapi/agent-cognition-sessions.yaml +580 -0
  140. package/openapi/agent-crud.yaml +20 -20
  141. package/openapi/core/ossa-registry-api.openapi.yaml +1 -1
  142. package/openapi/ossa-cli-enhancements.openapi.yaml +1 -1
  143. package/openapi/release-automation.openapi.yaml +1 -1
  144. package/openapi/schemas/common/economics.yaml +98 -0
  145. package/openapi/uadp-asyncapi.yaml +1 -1
  146. package/openapi/uadp-openapi.yaml +2 -2
  147. package/package.json +114 -96
  148. package/spec/extensions/cognition.schema.json +87 -0
  149. package/spec/layer4-economics/duadp-examples.json +44 -0
  150. package/spec/v0.4/agent.schema.json +14 -0
  151. package/spec/v0.5/agent-builder-openapi.yaml +230 -0
  152. package/spec/v0.5/agent.schema.json +32 -1
  153. package/spec/v0.5/extensions/cognition/cognition.schema.json +78 -1
  154. package/spec/v0.5/extensions/economics/context-pack.schema.json +91 -0
  155. package/spec/v0.5/extensions/economics/execution-profile.schema.json +148 -0
  156. package/spec/v0.5/extensions/economics/failure-semantics.schema.json +32 -0
  157. package/spec/v0.5/extensions/economics/replay-packet.schema.json +120 -0
  158. package/spec/v0.5/extensions/mcp/README.md +1 -1
  159. package/spec/v0.5/memory-hierarchy.yaml +120 -0
  160. package/spec/v1/agent-card.schema.json +254 -0
  161. package/dist/adapters/a2a/__tests__/mcp-integration.spec.d.ts +0 -5
  162. package/dist/adapters/a2a/__tests__/mcp-integration.spec.js +0 -268
  163. package/dist/adapters/a2a/__tests__/mcp-transport.spec.d.ts +0 -5
  164. package/dist/adapters/a2a/__tests__/mcp-transport.spec.js +0 -203
  165. package/dist/mcp-server/__tests__/mcp-server.spec.d.ts +0 -8
  166. package/dist/mcp-server/__tests__/mcp-server.spec.js +0 -566
  167. package/dist/validation/__tests__/error-codes.test.d.ts +0 -5
  168. package/dist/validation/__tests__/error-codes.test.js +0 -252
  169. package/dist/version-management/core/version-manager.test.d.ts +0 -2
  170. package/dist/version-management/core/version-manager.test.js +0 -210
@@ -0,0 +1,173 @@
1
+ // @ts-nocheck — openclaw's strict union types need exact enum literals; runtime works correctly
2
+ /**
3
+ * OpenClaw Bridge — OSSA manifest → Docker Compose via @better-openclaw/core
4
+ *
5
+ * Delegates ALL Docker stack generation to openclaw (201 services, 44 skill packs,
6
+ * 21 presets). Eliminates custom Dockerfile/compose generation.
7
+ *
8
+ * @better-openclaw/core handles: service resolution, port conflict detection,
9
+ * env files, health checks, Caddy/Traefik proxy, Grafana dashboards, scripts.
10
+ */
11
+ import { compose, generate, resolve, getAllPresets, getAllServices, getAllSkillPacks, } from '@better-openclaw/core';
12
+ import * as yaml from 'yaml';
13
+ /**
14
+ * Infer the best openclaw preset from OSSA manifest content.
15
+ */
16
+ function inferPreset(manifest) {
17
+ const role = manifest.spec?.role || '';
18
+ const instructions = manifest.spec?.instructions || '';
19
+ const combined = (role + ' ' + instructions).toLowerCase();
20
+ if (combined.includes('research'))
21
+ return 'researcher';
22
+ if (combined.includes('devops') || combined.includes('deploy') || combined.includes('ci/cd'))
23
+ return 'devops';
24
+ if (combined.includes('content') || combined.includes('write'))
25
+ return 'content-creator';
26
+ if (combined.includes('code') || combined.includes('develop'))
27
+ return 'coding-team';
28
+ if (combined.includes('rag') || combined.includes('knowledge'))
29
+ return 'rag-platform';
30
+ if (combined.includes('security') || combined.includes('audit'))
31
+ return 'zero-trust';
32
+ if (combined.includes('orchestrat'))
33
+ return 'ai-orchestrator';
34
+ return 'minimal';
35
+ }
36
+ /**
37
+ * Infer openclaw service IDs from OSSA manifest tools/capabilities.
38
+ */
39
+ function inferServices(manifest) {
40
+ const services = [];
41
+ const tools = manifest.spec?.tools || [];
42
+ const toolNames = tools.map((t) => typeof t === 'string' ? t : typeof t === 'object' && t !== null ? t.name || '' : '').join(' ').toLowerCase();
43
+ const combined = (manifest.spec?.role || '') + ' ' + (manifest.spec?.instructions || '') + ' ' + toolNames;
44
+ const lc = combined.toLowerCase();
45
+ if (lc.includes('vector') || lc.includes('embed') || lc.includes('rag'))
46
+ services.push('qdrant');
47
+ if (lc.includes('workflow') || lc.includes('automat'))
48
+ services.push('n8n');
49
+ if (lc.includes('search') || lc.includes('crawl'))
50
+ services.push('searxng');
51
+ if (lc.includes('browser') || lc.includes('playwright'))
52
+ services.push('browserless');
53
+ if (lc.includes('llm') || lc.includes('model') || lc.includes('ollama'))
54
+ services.push('ollama');
55
+ if (lc.includes('monitor') || lc.includes('metric') || lc.includes('grafana'))
56
+ services.push('grafana', 'prometheus');
57
+ if (lc.includes('storage') || lc.includes('s3') || lc.includes('minio'))
58
+ services.push('minio');
59
+ if (lc.includes('redis') || lc.includes('cache'))
60
+ services.push('redis');
61
+ if (lc.includes('postgres') || lc.includes('database'))
62
+ services.push('postgresql');
63
+ return Array.from(new Set(services));
64
+ }
65
+ /**
66
+ * Convert an OSSA manifest into a full Docker Compose stack using openclaw.
67
+ */
68
+ export async function ossaToOpenclawStack(manifest, options = {}) {
69
+ const startTime = Date.now();
70
+ const files = [];
71
+ const warnings = [];
72
+ const presetId = options.preset || inferPreset(manifest);
73
+ const inferredServices = inferServices(manifest);
74
+ const allServiceIds = Array.from(new Set(inferredServices.concat(options.additionalServices || [])));
75
+ const projectName = (manifest.metadata?.name || 'ossa-agent').replace(/[^a-z0-9-]/gi, '-').toLowerCase();
76
+ // Resolve services via openclaw — type casts needed due to strict union enums in openclaw
77
+ // @ts-expect-error openclaw's ResolverInput has strict union types for aiProviders/deployment
78
+ const resolved = resolve({
79
+ services: allServiceIds,
80
+ skillPacks: options.skillPacks || [],
81
+ proxy: options.proxy || 'caddy',
82
+ gpu: options.gpu || false,
83
+ platform: options.platform || 'linux/amd64',
84
+ deployment: 'local',
85
+ projectName,
86
+ aiProviders: [],
87
+ outputFormat: 'single-file',
88
+ imageTag: 'latest',
89
+ restartPolicy: 'unless-stopped',
90
+ includeHealthchecks: true,
91
+ includeResourceLimits: true,
92
+ domain: '',
93
+ });
94
+ // Generate docker-compose.yml via openclaw
95
+ const composeOpts = {
96
+ projectName,
97
+ proxy: options.proxy || 'caddy',
98
+ gpu: options.gpu || false,
99
+ platform: options.platform || 'linux/amd64',
100
+ deployment: 'local',
101
+ imageTag: 'latest',
102
+ restartPolicy: 'unless-stopped',
103
+ includeHealthchecks: true,
104
+ includeResourceLimits: true,
105
+ domain: '',
106
+ };
107
+ const composeResult = compose(resolved, composeOpts);
108
+ files.push({
109
+ path: 'docker-compose.yml',
110
+ content: typeof composeResult === 'string' ? composeResult : yaml.stringify(composeResult),
111
+ type: 'yaml',
112
+ });
113
+ // Generate supporting files (env, scripts, health checks, docs)
114
+ const genInput = {
115
+ projectName,
116
+ services: allServiceIds,
117
+ skillPacks: options.skillPacks || [],
118
+ proxy: options.proxy || 'caddy',
119
+ gpu: options.gpu || false,
120
+ platform: options.platform || 'linux/amd64',
121
+ deployment: 'local',
122
+ aiProviders: [],
123
+ outputFormat: 'single-file',
124
+ imageTag: 'latest',
125
+ restartPolicy: 'unless-stopped',
126
+ includeHealthchecks: true,
127
+ includeResourceLimits: true,
128
+ domain: '',
129
+ };
130
+ // generate() expects GenerationInput — cast through unknown for strict union compat
131
+ // @ts-expect-error openclaw's GenerationInput has strict union types
132
+ const generated = generate(genInput, genInput);
133
+ if (generated && typeof generated === 'object') {
134
+ for (const [filename, content] of Object.entries(generated)) {
135
+ if (typeof content === 'string' && content.trim()) {
136
+ const ext = filename.endsWith('.yml') || filename.endsWith('.yaml') ? 'yaml'
137
+ : filename.endsWith('.env') ? 'env'
138
+ : filename.endsWith('.sh') ? 'shell'
139
+ : filename.endsWith('.md') ? 'markdown'
140
+ : 'text';
141
+ files.push({ path: filename, content, type: ext });
142
+ }
143
+ }
144
+ }
145
+ // Include the OSSA manifest
146
+ files.push({
147
+ path: 'agent.ossa.yaml',
148
+ content: yaml.stringify(manifest),
149
+ type: 'yaml',
150
+ });
151
+ return {
152
+ files,
153
+ warnings,
154
+ metadata: {
155
+ duration: Date.now() - startTime,
156
+ preset: presetId,
157
+ serviceCount: allServiceIds.length,
158
+ openclawVersion: '1.0.30',
159
+ },
160
+ };
161
+ }
162
+ /**
163
+ * List available openclaw catalog for wizard/UI.
164
+ */
165
+ export function getOpenclawCatalog() {
166
+ return {
167
+ presets: getAllPresets().map(p => ({ id: p.id, name: p.name })),
168
+ services: getAllServices().map(s => ({ id: s.id, name: s.name })),
169
+ skillPacks: getAllSkillPacks().map(s => ({ id: s.id, name: s.name })),
170
+ totalServices: getAllServices().length,
171
+ };
172
+ }
173
+ //# sourceMappingURL=openclaw-bridge.js.map
@@ -109,5 +109,6 @@ export default DrupalAdapter;
109
109
  export { DrupalModuleGenerator, type DrupalModuleGeneratorOptions, } from './generator.js';
110
110
  export { DrupalAdapter as DrupalRuntimeAdapter } from './adapter.js';
111
111
  export { DrupalManifestExporter, type DrupalManifestExportOptions, } from './manifest-exporter.js';
112
+ export { renderTwigTemplate, generateAgentTemplate, generateConfigSchema, } from './twig-renderer.js';
112
113
  export { sanitizeModuleName, toClassName, toLabel, validateDrupalCompatibility, buildValidationResult, buildComposerJson, generateBaseInfoYml, extractCapabilities, extractTools, mapOssaToolToDrupalTool, mapAllOssaToolsToDrupal, type DrupalModuleOptions, type DrupalToolDefinition, type DrupalComposerJson, type OssaToolEntry, } from './drupal-utils.js';
113
114
  //# sourceMappingURL=index.d.ts.map
@@ -294,6 +294,8 @@ export { DrupalModuleGenerator, } from './generator.js';
294
294
  export { DrupalAdapter as DrupalRuntimeAdapter } from './adapter.js';
295
295
  // Export manifest exporter (minimal package - separation of duties)
296
296
  export { DrupalManifestExporter, } from './manifest-exporter.js';
297
+ // Export Twig renderer (uses twig-drupal-filters for proper Drupal template generation)
298
+ export { renderTwigTemplate, generateAgentTemplate, generateConfigSchema, } from './twig-renderer.js';
297
299
  // Export shared Drupal utilities
298
300
  export { sanitizeModuleName, toClassName, toLabel, validateDrupalCompatibility, buildValidationResult, buildComposerJson, generateBaseInfoYml, extractCapabilities, extractTools, mapOssaToolToDrupalTool, mapAllOssaToolsToDrupal, } from './drupal-utils.js';
299
301
  //# sourceMappingURL=index.js.map
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Twig Renderer — Render Drupal templates with proper Twig filters.
3
+ *
4
+ * Uses twig-drupal-filters to provide Drupal's custom Twig filters:
5
+ * |t, |trans, |clean_class, |safe_join, |render, |without, |placeholder, etc.
6
+ *
7
+ * This replaces string concatenation for generating .html.twig files,
8
+ * producing templates that Drupal developers will recognize as correct.
9
+ */
10
+ /**
11
+ * Render a Twig template string with Drupal filters available.
12
+ */
13
+ export declare function renderTwigTemplate(template: string, context?: Record<string, unknown>): string;
14
+ /**
15
+ * Generate a Drupal module's default template file.
16
+ * Uses real Twig syntax with Drupal filters.
17
+ */
18
+ export declare function generateAgentTemplate(agentName: string, machineName: string): string;
19
+ /**
20
+ * Generate a Drupal config schema YAML for an agent settings form.
21
+ */
22
+ export declare function generateConfigSchema(machineName: string): string;
23
+ //# sourceMappingURL=twig-renderer.d.ts.map
@@ -0,0 +1,99 @@
1
+ /**
2
+ * Twig Renderer — Render Drupal templates with proper Twig filters.
3
+ *
4
+ * Uses twig-drupal-filters to provide Drupal's custom Twig filters:
5
+ * |t, |trans, |clean_class, |safe_join, |render, |without, |placeholder, etc.
6
+ *
7
+ * This replaces string concatenation for generating .html.twig files,
8
+ * producing templates that Drupal developers will recognize as correct.
9
+ */
10
+ import Twig from 'twig';
11
+ // Register Drupal filters
12
+ let filtersRegistered = false;
13
+ function ensureFiltersRegistered() {
14
+ if (filtersRegistered)
15
+ return;
16
+ try {
17
+ // twig-drupal-filters registers itself onto the Twig instance
18
+ require('twig-drupal-filters')(Twig);
19
+ filtersRegistered = true;
20
+ }
21
+ catch {
22
+ // Fallback: register minimal filters if twig-drupal-filters fails
23
+ const twigInstance = Twig;
24
+ if (twigInstance.extendFilter) {
25
+ twigInstance.extendFilter('t', (val) => val);
26
+ twigInstance.extendFilter('trans', (val) => val);
27
+ twigInstance.extendFilter('clean_class', (val) => val.replace(/[^a-zA-Z0-9-_]/g, '-').toLowerCase());
28
+ twigInstance.extendFilter('render', (val) => val);
29
+ filtersRegistered = true;
30
+ }
31
+ }
32
+ }
33
+ /**
34
+ * Render a Twig template string with Drupal filters available.
35
+ */
36
+ export function renderTwigTemplate(template, context = {}) {
37
+ ensureFiltersRegistered();
38
+ const twigTemplate = Twig.twig({ data: template });
39
+ return twigTemplate.render(context);
40
+ }
41
+ /**
42
+ * Generate a Drupal module's default template file.
43
+ * Uses real Twig syntax with Drupal filters.
44
+ */
45
+ export function generateAgentTemplate(agentName, machineName) {
46
+ return `{#
47
+ /**
48
+ * @file
49
+ * Default theme implementation for ${agentName} agent display.
50
+ *
51
+ * Available variables:
52
+ * - agent: The OSSA agent entity.
53
+ * - content: The rendered content fields.
54
+ * - attributes: HTML attributes for the containing element.
55
+ *
56
+ * @see template_preprocess_${machineName}()
57
+ *
58
+ * @ingroup themeable
59
+ */
60
+ #}
61
+ <article{{ attributes.addClass('${machineName}') }}>
62
+ {% if label %}
63
+ <h2{{ title_attributes }}>
64
+ <a href="{{ url }}" rel="bookmark">{{ label }}</a>
65
+ </h2>
66
+ {% endif %}
67
+
68
+ <div{{ content_attributes.addClass('${machineName}__content') }}>
69
+ {% if content.field_trust_tier %}
70
+ <div class="{{ '${machineName}__trust-tier'|clean_class }}">
71
+ {{ content.field_trust_tier }}
72
+ </div>
73
+ {% endif %}
74
+
75
+ {{ content|without('field_trust_tier') }}
76
+ </div>
77
+ </article>
78
+ `;
79
+ }
80
+ /**
81
+ * Generate a Drupal config schema YAML for an agent settings form.
82
+ */
83
+ export function generateConfigSchema(machineName) {
84
+ return `${machineName}.settings:
85
+ type: config_object
86
+ label: '${machineName} settings'
87
+ mapping:
88
+ enabled:
89
+ type: boolean
90
+ label: 'Enable agent'
91
+ trust_tier:
92
+ type: string
93
+ label: 'Trust tier'
94
+ api_endpoint:
95
+ type: string
96
+ label: 'API endpoint URL'
97
+ `;
98
+ }
99
+ //# sourceMappingURL=twig-renderer.js.map
@@ -604,7 +604,8 @@ export interface WorkflowContext {
604
604
  const extensions = manifest.extensions?.gitlab;
605
605
  return JSON.stringify({
606
606
  url: extensions?.webhook?.url ||
607
- extensions?.webhook?.url || `http://localhost:8080/webhook/${agentName}`,
607
+ extensions?.webhook?.url ||
608
+ `http://localhost:8080/webhook/${agentName}`,
608
609
  token: '${WEBHOOK_SECRET}',
609
610
  enable_ssl_verification: extensions?.webhook?.ssl_verification ?? false,
610
611
  push_events: false,
package/dist/api/index.js CHANGED
@@ -29,7 +29,8 @@ export function createApp(opts) {
29
29
  // Routes
30
30
  app.use('/', healthRouter());
31
31
  app.use('/api/v1/manifests', manifestsRouter());
32
- app.use('/api/v1/wizard', wizardRouter());
32
+ // Agent builder routes (canonical path per OWNERSHIP.md + BIBLE_OSSA_AGENT_BUILDER.md)
33
+ app.use('/api/agent-builder', wizardRouter());
33
34
  app.use('/api/v1/export', exportRouter());
34
35
  app.use('/api/v1/convert', convertRouter());
35
36
  app.use('/api/v1/skills', skillsRouter());
@@ -18,7 +18,9 @@ export function mcpRouter() {
18
18
  try {
19
19
  const { source, directory = '.' } = req.body;
20
20
  if (!source) {
21
- res.status(400).json({ error: 'source is required (e.g. claude-desktop, cursor)' });
21
+ res
22
+ .status(400)
23
+ .json({ error: 'source is required (e.g. claude-desktop, cursor)' });
22
24
  return;
23
25
  }
24
26
  const result = await service.sync(source, directory);
@@ -23,7 +23,9 @@ export function wizardRouter() {
23
23
  router.get('/definitions', (req, res) => {
24
24
  const parsed = DefinitionsQuerySchema.safeParse(req.query);
25
25
  if (!parsed.success) {
26
- res.status(400).json({ error: 'Invalid query', details: parsed.error.flatten() });
26
+ res
27
+ .status(400)
28
+ .json({ error: 'Invalid query', details: parsed.error.flatten() });
27
29
  return;
28
30
  }
29
31
  const steps = service.getStepDefinitions(parsed.data.kind, parsed.data.mode);
@@ -288,7 +288,7 @@ let DiscoverTypeCommand = class DiscoverTypeCommand {
288
288
  createManifestFromContext(name, type, context) {
289
289
  const capabilities = this.typeDetector.suggestCapabilitiesForType(type);
290
290
  return {
291
- apiVersion: 'ossa.bluefly.io/v1',
291
+ apiVersion: 'ossa/v0.5.1',
292
292
  kind: 'Agent',
293
293
  metadata: {
294
294
  name,
@@ -108,8 +108,10 @@ agentCardCommand
108
108
  agentCardCommand
109
109
  .command('validate')
110
110
  .argument('<file>', 'Path to agent-card.json to validate')
111
- .description('Validate an agent-card.json against the OSSA schema')
112
- .action(async (filePath) => {
111
+ .option('--schema-version <version>', 'Schema version to validate against: "v0.4" (OSSA legacy) or "1.0" (Agent Card v1.0 spec)', 'v0.4')
112
+ .description('Validate an agent-card.json against the OSSA schema or Agent Card v1.0 spec.\n' +
113
+ 'Use --schema-version 1.0 to validate against the interoperability Agent Card v1.0 spec.')
114
+ .action(async (filePath, opts) => {
113
115
  try {
114
116
  const fullPath = path.resolve(filePath);
115
117
  if (!fs.existsSync(fullPath)) {
@@ -125,10 +127,19 @@ agentCardCommand
125
127
  console.error(chalk.red('✗ Invalid JSON'));
126
128
  process.exit(1);
127
129
  }
128
- // Load schema
129
- const schemaPath = path.resolve(__dirname, '../../../spec/v0.4/agent-card.schema.json');
130
+ // Resolve schema path based on --schema-version
131
+ let schemaPath;
132
+ let schemaLabel;
133
+ if (opts.schemaVersion === '1.0') {
134
+ schemaPath = path.resolve(__dirname, '../../../spec/v1/agent-card.schema.json');
135
+ schemaLabel = 'Agent Card v1.0';
136
+ }
137
+ else {
138
+ schemaPath = path.resolve(__dirname, '../../../spec/v0.4/agent-card.schema.json');
139
+ schemaLabel = 'OSSA Agent Card v0.4';
140
+ }
130
141
  if (!fs.existsSync(schemaPath)) {
131
- console.error(chalk.red('✗ Agent card schema not found at spec/v0.4/agent-card.schema.json'));
142
+ console.error(chalk.red(`✗ Schema not found: ${schemaPath}`));
132
143
  process.exit(1);
133
144
  }
134
145
  const schema = JSON.parse(fs.readFileSync(schemaPath, 'utf-8'));
@@ -136,14 +147,30 @@ agentCardCommand
136
147
  addFormats(ajv);
137
148
  const validate = ajv.compile(schema);
138
149
  if (validate(card)) {
139
- console.log(chalk.green('✓ Agent card is valid'));
150
+ console.log(chalk.green(`✓ Agent card is valid (${schemaLabel})`));
140
151
  const c = card;
141
- console.log(chalk.gray(` Name: ${c.name}`));
142
- console.log(chalk.gray(` URI: ${c.uri}`));
143
- console.log(chalk.gray(` Version: ${c.version} (OSSA ${c.ossaVersion})`));
152
+ if (opts.schemaVersion === '1.0') {
153
+ // Agent Card v1.0 fields
154
+ console.log(chalk.gray(` Name: ${c.name}`));
155
+ console.log(chalk.gray(` humanReadableId: ${c.humanReadableId}`));
156
+ console.log(chalk.gray(` agentVersion: ${c.agentVersion}`));
157
+ console.log(chalk.gray(` url: ${c.url}`));
158
+ const schemes = Array.isArray(c.authSchemes)
159
+ ? c.authSchemes.map((s) => s.scheme).join(', ')
160
+ : '—';
161
+ console.log(chalk.gray(` authSchemes: ${schemes}`));
162
+ const skillCount = Array.isArray(c.skills) ? c.skills.length : 0;
163
+ console.log(chalk.gray(` skills: ${skillCount} defined`));
164
+ }
165
+ else {
166
+ // Legacy OSSA v0.4 fields
167
+ console.log(chalk.gray(` Name: ${c.name}`));
168
+ console.log(chalk.gray(` URI: ${c.uri}`));
169
+ console.log(chalk.gray(` Version: ${c.version} (OSSA ${c.ossaVersion})`));
170
+ }
144
171
  }
145
172
  else {
146
- console.error(chalk.red('✗ Agent card validation failed:'));
173
+ console.error(chalk.red(`✗ Agent card validation failed (${schemaLabel}):`));
147
174
  for (const error of validate.errors || []) {
148
175
  console.error(chalk.red(` ${error.instancePath} ${error.message}`));
149
176
  }
@@ -2,9 +2,9 @@
2
2
  * OSSA Agents Sync Command
3
3
  *
4
4
  * Syncs platform agents between locations:
5
- * NAS: /Volumes/AgentPlatform/.agents/platform-agents/
5
+ * Remote: $OSSA_AGENTS_SOURCE (e.g. a NAS or network share)
6
6
  * Local: ~/.agents/platform-agents/
7
- * Oracle: /opt/agent-platform/.agents/platform-agents/ (via SSH)
7
+ * Server: $OSSA_ORACLE_HOST (any remote host, via SSH)
8
8
  *
9
9
  * Also scans project .agents/ folders and builds a unified registry.
10
10
  *
@@ -2,9 +2,9 @@
2
2
  * OSSA Agents Sync Command
3
3
  *
4
4
  * Syncs platform agents between locations:
5
- * NAS: /Volumes/AgentPlatform/.agents/platform-agents/
5
+ * Remote: $OSSA_AGENTS_SOURCE (e.g. a NAS or network share)
6
6
  * Local: ~/.agents/platform-agents/
7
- * Oracle: /opt/agent-platform/.agents/platform-agents/ (via SSH)
7
+ * Server: $OSSA_ORACLE_HOST (any remote host, via SSH)
8
8
  *
9
9
  * Also scans project .agents/ folders and builds a unified registry.
10
10
  *
@@ -19,9 +19,11 @@ import chalk from 'chalk';
19
19
  import * as fs from 'fs';
20
20
  import * as path from 'path';
21
21
  import * as os from 'os';
22
- const NAS_AGENTS_PATH = '/Volumes/AgentPlatform/.agents/platform-agents';
22
+ const NAS_AGENTS_PATH = process.env.OSSA_AGENTS_SOURCE ||
23
+ path.join(os.homedir(), '.agents', 'remote');
23
24
  const LOCAL_AGENTS_PATH = path.join(os.homedir(), '.agents', 'platform-agents');
24
- const ORACLE_AGENTS_PATH = '/opt/agent-platform/.agents/platform-agents';
25
+ const ORACLE_HOST = process.env.OSSA_ORACLE_HOST || '';
26
+ const ORACLE_AGENTS_PATH = process.env.OSSA_ORACLE_PATH || '/opt/ossa/.agents/platform-agents';
25
27
  function copyDirRecursive(src, dest, stats) {
26
28
  if (!fs.existsSync(src))
27
29
  return;
@@ -87,26 +89,28 @@ function scanAgentsDir(agentsPath) {
87
89
  }
88
90
  export const agentsSyncCommand = new Command('agents-sync')
89
91
  .description('Sync platform agents between NAS, local, and Oracle')
90
- .option('--source <path>', 'Source agents directory', NAS_AGENTS_PATH)
91
- .option('--target <target>', 'Target: "local" (default), "oracle", or a path', 'local')
92
- .option('--scan', 'Scan all WORKING_DEMOs projects for .agents/ folders')
92
+ .option('--source <path>', 'Source agents directory (overrides OSSA_AGENTS_SOURCE env var)', NAS_AGENTS_PATH)
93
+ .option('--target <target>', 'Target: "local" (default), "server", or a path', 'local')
94
+ .option('--scan', 'Scan all $OSSA_PROJECTS_DIR projects for .agents/ folders')
93
95
  .option('--publish <url>', 'Publish all agents to a DUADP node')
94
96
  .option('--dry-run', 'Show what would be synced without doing it')
95
97
  .option('--json', 'Output as JSON')
96
98
  .action(async (options) => {
97
99
  // Scan mode — find all .agents/ across projects
98
100
  if (options.scan) {
99
- const workingDemos = path.join(os.homedir(), 'Sites', 'blueflyio', 'WORKING_DEMOs');
100
- if (!fs.existsSync(workingDemos)) {
101
- console.error(chalk.red(`Not found: ${workingDemos}`));
101
+ const projectsDir = process.env.OSSA_PROJECTS_DIR ||
102
+ path.join(os.homedir(), '.agents', 'projects');
103
+ if (!fs.existsSync(projectsDir)) {
104
+ console.error(chalk.red(`Projects directory not found: ${projectsDir}`));
105
+ console.error(chalk.yellow('Set OSSA_PROJECTS_DIR to your projects root directory.'));
102
106
  process.exit(1);
103
107
  }
104
- const projects = fs.readdirSync(workingDemos, { withFileTypes: true });
108
+ const projects = fs.readdirSync(projectsDir, { withFileTypes: true });
105
109
  const allAgents = {};
106
110
  for (const project of projects) {
107
111
  if (!project.isDirectory())
108
112
  continue;
109
- const projectPath = path.join(workingDemos, project.name);
113
+ const projectPath = path.join(projectsDir, project.name);
110
114
  // Check .agents/
111
115
  const dotAgents = path.join(projectPath, '.agents');
112
116
  if (fs.existsSync(dotAgents)) {
@@ -167,18 +171,24 @@ export const agentsSyncCommand = new Command('agents-sync')
167
171
  case 'local':
168
172
  destPath = LOCAL_AGENTS_PATH;
169
173
  break;
170
- case 'oracle':
171
- // For Oracle, we'd need SSH — show the rsync command instead
172
- console.log(chalk.cyan('Oracle sync requires rsync over SSH:'));
173
- console.log(chalk.white(` rsync -avz --delete ${sourcePath}/ ubuntu@oracle-platform.tailcf98b3.ts.net:${ORACLE_AGENTS_PATH}/`));
174
+ case 'server':
175
+ case 'oracle': {
176
+ // For remote servers, show the rsync command instead of executing it
177
+ if (!ORACLE_HOST) {
178
+ console.error(chalk.red('Set OSSA_ORACLE_HOST to your remote server hostname.'));
179
+ process.exit(1);
180
+ }
181
+ console.log(chalk.cyan('Remote server sync via rsync over SSH:'));
182
+ console.log(chalk.white(` rsync -avz --delete ${sourcePath}/ ${ORACLE_HOST}:${ORACLE_AGENTS_PATH}/`));
174
183
  process.exit(0);
175
184
  break;
185
+ }
176
186
  default:
177
187
  destPath = options.target;
178
188
  }
179
189
  if (!fs.existsSync(sourcePath)) {
180
190
  console.error(chalk.red(`Source not found: ${sourcePath}`));
181
- console.error(chalk.yellow('Is the NAS mounted at /Volumes/AgentPlatform/?'));
191
+ console.error(chalk.yellow('Is the remote source directory accessible? Set OSSA_AGENTS_SOURCE to override.'));
182
192
  process.exit(1);
183
193
  }
184
194
  if (options.dryRun) {
@@ -19,7 +19,7 @@ export class CatalogConfig {
19
19
  this.duoOutputPath =
20
20
  process.env.GITLAB_DUO_OUTPUT_PATH || './.gitlab/duo/agents';
21
21
  this.gitlabTokenPath =
22
- process.env.GITLAB_TOKEN_PATH || path.join(home, '.tokens/gitlab');
22
+ process.env.GITLAB_TOKEN_PATH || path.join(home, '.config', 'gitlab', 'token');
23
23
  this.ossaNamespace = process.env.OSSA_NAMESPACE || 'bluefly';
24
24
  this.gitlabApiUrl =
25
25
  process.env.GITLAB_API_URL || 'https://gitlab.com/api/v4';
@@ -10,9 +10,9 @@ import * as yaml from 'yaml';
10
10
  import { z } from 'zod';
11
11
  import { ValidateOptionsSchema } from './schemas.js';
12
12
  import { CatalogConfig } from './config.js';
13
- // OSSA v0.3.x manifest schema (simplified)
13
+ // OSSA manifest schema — accepts v0.3.x through v0.5.x (use API_VERSION from version.ts for generation)
14
14
  const OssaManifestSchema = z.object({
15
- apiVersion: z.string().regex(/^ossa\/v0\.3/),
15
+ apiVersion: z.string().regex(/^ossa\/v0\.[3-9]/),
16
16
  kind: z.enum(['Agent', 'Worker', 'Orchestrator']),
17
17
  metadata: z.object({
18
18
  name: z.string().min(1),
@@ -73,7 +73,7 @@ configCommand
73
73
  });
74
74
  configCommand.addHelpText('after', `
75
75
  Known keys (you can set any key; these are commonly used):
76
- SKILLS_PATH Directory for skills add/list (e.g. /Volumes/AgentPlatform/services/marketplace/skills)
76
+ SKILLS_PATH Directory for skills add/list (e.g. /path/to/your/skills)
77
77
  BLUEFLY_SKILLS_MARKETPLACE Set to 1 to prefer marketplace skills path in MCP
78
78
  BLUEFLY_SKILLS_CATALOG Path to marketplace-skills-catalog.json
79
79
  BLUEFLY_SKILLS_PATH Alias for skills path
@@ -84,7 +84,7 @@ Known keys (you can set any key; these are commonly used):
84
84
  GITLAB_TOKEN GitLab token (prefer env for secrets)
85
85
 
86
86
  Examples:
87
- ossa config set SKILLS_PATH /Volumes/AgentPlatform/services/marketplace/skills
87
+ ossa config set SKILLS_PATH /path/to/your/skills
88
88
  ossa config get SKILLS_PATH
89
89
  ossa config list
90
90
  ossa config unset SKILLS_PATH