@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.
- package/.version.json +3 -3
- package/CHANGELOG.md +43 -12
- package/README.md +31 -26
- package/bin/postinstall +0 -0
- package/dist/.version.json +3 -3
- package/dist/adapters/a2a/a2a-protocol.js +4 -2
- package/dist/adapters/a2a/a2a-tool.js +4 -2
- package/dist/adapters/a2a/mcp-integration.d.ts +2 -1
- package/dist/adapters/a2a/mcp-integration.js +6 -3
- package/dist/adapters/browser/browser-exporter.d.ts +26 -0
- package/dist/adapters/browser/browser-exporter.js +73 -0
- package/dist/adapters/browser/browser-runner.d.ts +23 -0
- package/dist/adapters/browser/browser-runner.js +46 -0
- package/dist/adapters/browser/index.d.ts +9 -0
- package/dist/adapters/browser/index.js +9 -0
- package/dist/adapters/docker/index.d.ts +2 -0
- package/dist/adapters/docker/index.js +2 -0
- package/dist/adapters/docker/openclaw-bridge.d.ts +57 -0
- package/dist/adapters/docker/openclaw-bridge.js +173 -0
- package/dist/adapters/drupal/index.d.ts +1 -0
- package/dist/adapters/drupal/index.js +2 -0
- package/dist/adapters/drupal/twig-renderer.d.ts +23 -0
- package/dist/adapters/drupal/twig-renderer.js +99 -0
- package/dist/adapters/gitlab/agent-generator.js +2 -1
- package/dist/api/index.js +2 -1
- package/dist/api/routes/mcp.router.js +3 -1
- package/dist/api/routes/wizard.router.js +3 -1
- package/dist/cli/commands/agent/discover-type.command.js +1 -1
- package/dist/cli/commands/agent-card.command.js +37 -10
- package/dist/cli/commands/agents-sync.command.d.ts +2 -2
- package/dist/cli/commands/agents-sync.command.js +27 -17
- package/dist/cli/commands/catalog/config.js +1 -1
- package/dist/cli/commands/catalog/validate.command.js +2 -2
- package/dist/cli/commands/config.command.js +2 -2
- package/dist/cli/commands/daemon.command.js +32 -8
- package/dist/cli/commands/discover.d.ts +1 -1
- package/dist/cli/commands/discover.js +16 -8
- package/dist/cli/commands/economics.command.d.ts +9 -0
- package/dist/cli/commands/economics.command.js +113 -0
- package/dist/cli/commands/export.command.js +6 -3
- package/dist/cli/commands/mcp.command.js +3 -1
- package/dist/cli/commands/memory.command.d.ts +18 -0
- package/dist/cli/commands/memory.command.js +168 -0
- package/dist/cli/commands/publish.command.js +7 -4
- package/dist/cli/commands/serve-builder-routes.js +1 -1
- package/dist/cli/commands/usie-skills.command.d.ts +24 -0
- package/dist/cli/commands/usie-skills.command.js +297 -0
- package/dist/cli/commands/validate.command.js +8 -1
- package/dist/cli/commands/verify.d.ts +3 -3
- package/dist/cli/commands/verify.js +12 -6
- package/dist/cli/commands/workspace.command.d.ts +1 -0
- package/dist/cli/commands/workspace.command.js +28 -4
- package/dist/cli/index.js +12 -0
- package/dist/cli/workspace-validate.d.ts +23 -0
- package/dist/cli/workspace-validate.js +117 -0
- package/dist/data/platform-matrix.js +1 -4
- package/dist/generated/types.d.ts +97 -97
- package/dist/index.d.ts +2 -0
- package/dist/index.js +2 -0
- package/dist/mcp-server/index.js +658 -982
- package/dist/mesh/discovery-gkg.d.ts +26 -0
- package/dist/mesh/discovery-gkg.js +92 -0
- package/dist/messenger/Handler/AgentBatchHandler.js +3 -2
- package/dist/messenger/Handler/AgentExecutionHandler.js +6 -1
- package/dist/package.json +20 -4
- package/dist/sdks/shared/types.d.ts +1 -1
- package/dist/services/agent-card-generator.js +6 -2
- package/dist/services/daemon/audit-log.service.js +3 -1
- package/dist/services/daemon/execution.service.js +8 -4
- package/dist/services/daemon/fs-watcher.service.js +6 -7
- package/dist/services/daemon/pairing.service.js +2 -1
- package/dist/services/daemon/skill-aggregator.service.js +105 -21
- package/dist/services/daemon/sse-endpoints.js +1 -1
- package/dist/services/daemon/ws-server.js +10 -3
- package/dist/services/governance/cedar-provider.js +12 -8
- package/dist/services/governance/cedar-validator.service.js +1 -1
- package/dist/services/mcp/bridge.service.js +40 -9
- package/dist/services/openapi-extensions-validation.d.ts +20 -0
- package/dist/services/openapi-extensions-validation.js +193 -0
- package/dist/services/release-automation/merge-request.service.d.ts +4 -4
- package/dist/services/release-automation/release-buttons.js +3 -3
- package/dist/services/release-automation/schemas/release.schema.d.ts +3 -3
- package/dist/services/runtime/openai.adapter.d.ts +46 -13
- package/dist/services/runtime/openai.adapter.js +169 -131
- package/dist/services/skill-registry.service.d.ts +1 -1
- package/dist/services/skills-pipeline/skills-research.service.js +47 -7
- package/dist/services/trust/trust.service.js +6 -4
- package/dist/services/validation-zod.service.js +3 -22
- package/dist/services/validators/index.d.ts +1 -0
- package/dist/services/validators/index.js +1 -0
- package/dist/services/validators/registry.d.ts +21 -0
- package/dist/services/validators/registry.js +42 -0
- package/dist/skills/test-skill/package.json +1 -1
- package/dist/spec/extensions/cognition.schema.json +87 -0
- package/dist/spec/layer4-economics/duadp-examples.json +44 -0
- package/dist/spec/v0.4/agent.schema.json +14 -0
- package/dist/spec/v0.5/agent-builder-openapi.yaml +230 -0
- package/dist/spec/v0.5/agent.schema.json +32 -1
- package/dist/spec/v0.5/extensions/cognition/cognition.schema.json +78 -1
- package/dist/spec/v0.5/extensions/economics/context-pack.schema.json +91 -0
- package/dist/spec/v0.5/extensions/economics/execution-profile.schema.json +148 -0
- package/dist/spec/v0.5/extensions/economics/failure-semantics.schema.json +32 -0
- package/dist/spec/v0.5/extensions/economics/replay-packet.schema.json +120 -0
- package/dist/spec/v0.5/extensions/mcp/README.md +1 -1
- package/dist/spec/v0.5/memory-hierarchy.yaml +120 -0
- package/dist/spec/v1/agent-card.schema.json +254 -0
- package/dist/types/cognition.zod.d.ts +312 -0
- package/dist/types/cognition.zod.js +223 -0
- package/dist/types/identity.zod.d.ts +5 -5
- package/dist/types/index.d.ts +53 -7
- package/dist/types/index.js +4 -2
- package/dist/types/personality.zod.d.ts +3 -3
- package/dist/utils/http-client.d.ts +22 -0
- package/dist/utils/http-client.js +51 -0
- package/dist/utils/index.d.ts +3 -0
- package/dist/utils/index.js +3 -0
- package/dist/utils/proxy-resolver.d.ts +36 -0
- package/dist/utils/proxy-resolver.js +59 -0
- package/dist/utils/user-agent.d.ts +11 -0
- package/dist/utils/user-agent.js +17 -0
- package/dist/validation/version-compliance.js +1 -1
- package/examples/agentscope/react-assistant/README.md +1 -1
- package/examples/agentscope/react-assistant/agent.ossa.yaml +1 -1
- package/examples/drupal/drupal-contributor-agent/.eslintrc.json +58 -0
- package/examples/drupal/drupal-contributor-agent/.prettierrc.json +10 -0
- package/examples/drupal/drupal-contributor-agent/package.json +55 -0
- package/examples/drupal/drupal-contributor-agent/src/core/index.ts +10 -0
- package/examples/drupal/drupal-contributor-agent/src/index.ts +17 -0
- package/examples/drupal/drupal-contributor-agent/src/types/index.ts +180 -0
- package/examples/drupal/drupal-contributor-agent/tsconfig.json +36 -0
- package/examples/getting-started/01-minimal-agent.ossa.yaml +1 -1
- package/examples/getting-started/02-agent-with-tools.ossa.yaml +1 -1
- package/examples/getting-started/03-agent-with-safety.ossa.yaml +1 -1
- package/examples/getting-started/04-agent-with-messaging.ossa.yaml +1 -1
- package/examples/getting-started/05-workflow-composition.ossa.yaml +1 -1
- package/examples/getting-started/hello-world-complete.ossa.yaml +1 -1
- package/examples/reference-implementations/python-client/examples/basic_usage.py +0 -0
- package/examples/reference-implementations/python-client/examples/publish_agent.py +0 -0
- package/openapi/agent-cognition-sessions.yaml +580 -0
- package/openapi/agent-crud.yaml +20 -20
- package/openapi/core/ossa-registry-api.openapi.yaml +1 -1
- package/openapi/ossa-cli-enhancements.openapi.yaml +1 -1
- package/openapi/release-automation.openapi.yaml +1 -1
- package/openapi/schemas/common/economics.yaml +98 -0
- package/openapi/uadp-asyncapi.yaml +1 -1
- package/openapi/uadp-openapi.yaml +2 -2
- package/package.json +114 -96
- package/spec/extensions/cognition.schema.json +87 -0
- package/spec/layer4-economics/duadp-examples.json +44 -0
- package/spec/v0.4/agent.schema.json +14 -0
- package/spec/v0.5/agent-builder-openapi.yaml +230 -0
- package/spec/v0.5/agent.schema.json +32 -1
- package/spec/v0.5/extensions/cognition/cognition.schema.json +78 -1
- package/spec/v0.5/extensions/economics/context-pack.schema.json +91 -0
- package/spec/v0.5/extensions/economics/execution-profile.schema.json +148 -0
- package/spec/v0.5/extensions/economics/failure-semantics.schema.json +32 -0
- package/spec/v0.5/extensions/economics/replay-packet.schema.json +120 -0
- package/spec/v0.5/extensions/mcp/README.md +1 -1
- package/spec/v0.5/memory-hierarchy.yaml +120 -0
- package/spec/v1/agent-card.schema.json +254 -0
- package/dist/adapters/a2a/__tests__/mcp-integration.spec.d.ts +0 -5
- package/dist/adapters/a2a/__tests__/mcp-integration.spec.js +0 -268
- package/dist/adapters/a2a/__tests__/mcp-transport.spec.d.ts +0 -5
- package/dist/adapters/a2a/__tests__/mcp-transport.spec.js +0 -203
- package/dist/mcp-server/__tests__/mcp-server.spec.d.ts +0 -8
- package/dist/mcp-server/__tests__/mcp-server.spec.js +0 -566
- package/dist/validation/__tests__/error-codes.test.d.ts +0 -5
- package/dist/validation/__tests__/error-codes.test.js +0 -252
- package/dist/version-management/core/version-manager.test.d.ts +0 -2
- package/dist/version-management/core/version-manager.test.js +0 -210
|
@@ -1,566 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* OSSA MCP Server — Integration Tests
|
|
3
|
-
*
|
|
4
|
-
* Tests all 7 tools end-to-end using the MCP SDK Client.
|
|
5
|
-
* Uses vitest + @modelcontextprotocol/sdk.
|
|
6
|
-
*/
|
|
7
|
-
import { describe, it, expect, beforeAll, afterAll } from 'vitest';
|
|
8
|
-
import { Client } from '@modelcontextprotocol/sdk/client/index.js';
|
|
9
|
-
import { StdioClientTransport } from '@modelcontextprotocol/sdk/client/stdio.js';
|
|
10
|
-
import * as path from 'node:path';
|
|
11
|
-
import * as fs from 'node:fs';
|
|
12
|
-
import * as os from 'node:os';
|
|
13
|
-
const SERVER_PATH = path.resolve(import.meta.dirname, '../../../dist/mcp-server/index.js');
|
|
14
|
-
const FIXTURE_DIR = path.resolve(import.meta.dirname, '../../../spec/reference/reference-agents');
|
|
15
|
-
let client;
|
|
16
|
-
let transport;
|
|
17
|
-
let tmpDir;
|
|
18
|
-
beforeAll(async () => {
|
|
19
|
-
tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'ossa-mcp-test-'));
|
|
20
|
-
transport = new StdioClientTransport({
|
|
21
|
-
command: 'node',
|
|
22
|
-
args: [SERVER_PATH],
|
|
23
|
-
env: { ...process.env, LOG_LEVEL: 'silent' },
|
|
24
|
-
});
|
|
25
|
-
client = new Client({ name: 'ossa-mcp-test', version: '1.0.0' }, { capabilities: {} });
|
|
26
|
-
await client.connect(transport);
|
|
27
|
-
}, 15000);
|
|
28
|
-
afterAll(async () => {
|
|
29
|
-
await client?.close();
|
|
30
|
-
// cleanup tmpDir
|
|
31
|
-
if (tmpDir && fs.existsSync(tmpDir)) {
|
|
32
|
-
fs.rmSync(tmpDir, { recursive: true, force: true });
|
|
33
|
-
}
|
|
34
|
-
});
|
|
35
|
-
function readTextResource(content) {
|
|
36
|
-
if (typeof content.text === 'string') {
|
|
37
|
-
return content.text;
|
|
38
|
-
}
|
|
39
|
-
if (typeof content.blob === 'string') {
|
|
40
|
-
return Buffer.from(content.blob, 'base64').toString('utf8');
|
|
41
|
-
}
|
|
42
|
-
throw new Error('Expected text resource content');
|
|
43
|
-
}
|
|
44
|
-
describe('ossa_validate', () => {
|
|
45
|
-
it('validates a valid manifest', async () => {
|
|
46
|
-
const manifestPath = path.join(FIXTURE_DIR, 'compliance-auditor/manifest.ossa.yaml');
|
|
47
|
-
const result = await client.callTool({
|
|
48
|
-
name: 'ossa_validate',
|
|
49
|
-
arguments: { path: manifestPath },
|
|
50
|
-
});
|
|
51
|
-
expect(result.isError).toBeFalsy();
|
|
52
|
-
const data = JSON.parse(result.content[0].text);
|
|
53
|
-
expect(data.valid).toBe(true);
|
|
54
|
-
expect(data.manifest_path).toBe(manifestPath);
|
|
55
|
-
});
|
|
56
|
-
it('returns error for non-existent file', async () => {
|
|
57
|
-
const result = await client.callTool({
|
|
58
|
-
name: 'ossa_validate',
|
|
59
|
-
arguments: { path: '/tmp/does-not-exist.ossa.yaml' },
|
|
60
|
-
});
|
|
61
|
-
expect(result.isError).toBe(true);
|
|
62
|
-
});
|
|
63
|
-
});
|
|
64
|
-
describe('ossa_scaffold', () => {
|
|
65
|
-
it('scaffolds a new agent with full directory structure', async () => {
|
|
66
|
-
const result = await client.callTool({
|
|
67
|
-
name: 'ossa_scaffold',
|
|
68
|
-
arguments: {
|
|
69
|
-
name: 'test-agent',
|
|
70
|
-
output_dir: tmpDir,
|
|
71
|
-
description: 'A test agent for CI',
|
|
72
|
-
role: 'You are a test agent.',
|
|
73
|
-
type: 'worker',
|
|
74
|
-
},
|
|
75
|
-
});
|
|
76
|
-
expect(result.isError).toBeFalsy();
|
|
77
|
-
const data = JSON.parse(result.content[0].text);
|
|
78
|
-
expect(data.success).toBe(true);
|
|
79
|
-
expect(data.files_created).toContain('manifest.ossa.yaml');
|
|
80
|
-
expect(data.files_created).toContain('AGENTS.md');
|
|
81
|
-
expect(data.files_created).toContain('prompts/');
|
|
82
|
-
expect(data.files_created).toContain('tools/');
|
|
83
|
-
// Verify files on disk
|
|
84
|
-
const agentDir = path.join(tmpDir, 'test-agent');
|
|
85
|
-
expect(fs.existsSync(path.join(agentDir, 'manifest.ossa.yaml'))).toBe(true);
|
|
86
|
-
expect(fs.existsSync(path.join(agentDir, 'AGENTS.md'))).toBe(true);
|
|
87
|
-
expect(fs.existsSync(path.join(agentDir, 'prompts'))).toBe(true);
|
|
88
|
-
expect(fs.existsSync(path.join(agentDir, 'tools'))).toBe(true);
|
|
89
|
-
});
|
|
90
|
-
it('rejects duplicate directory', async () => {
|
|
91
|
-
// test-agent already created above
|
|
92
|
-
const result = await client.callTool({
|
|
93
|
-
name: 'ossa_scaffold',
|
|
94
|
-
arguments: { name: 'test-agent', output_dir: tmpDir },
|
|
95
|
-
});
|
|
96
|
-
expect(result.isError).toBe(true);
|
|
97
|
-
const data = JSON.parse(result.content[0].text);
|
|
98
|
-
expect(data.error).toContain('already exists');
|
|
99
|
-
});
|
|
100
|
-
it('rejects invalid DNS-1123 names', async () => {
|
|
101
|
-
const result = await client.callTool({
|
|
102
|
-
name: 'ossa_scaffold',
|
|
103
|
-
arguments: { name: 'InvalidName!', output_dir: tmpDir },
|
|
104
|
-
});
|
|
105
|
-
expect(result.isError).toBe(true);
|
|
106
|
-
});
|
|
107
|
-
});
|
|
108
|
-
describe('ossa_generate', () => {
|
|
109
|
-
it('generates agent-card.json from scaffolded manifest', async () => {
|
|
110
|
-
// Use the scaffolded manifest (known-good structure)
|
|
111
|
-
const manifestPath = path.join(tmpDir, 'test-agent/manifest.ossa.yaml');
|
|
112
|
-
const result = await client.callTool({
|
|
113
|
-
name: 'ossa_generate',
|
|
114
|
-
arguments: { path: manifestPath },
|
|
115
|
-
});
|
|
116
|
-
// Agent card generation may fail for minimal manifests — that's OK
|
|
117
|
-
const data = JSON.parse(result.content[0].text);
|
|
118
|
-
expect(data).toBeDefined();
|
|
119
|
-
});
|
|
120
|
-
it('returns structured error for manifests missing capabilities', async () => {
|
|
121
|
-
const manifestPath = path.join(FIXTURE_DIR, 'compliance-auditor/manifest.ossa.yaml');
|
|
122
|
-
const result = await client.callTool({
|
|
123
|
-
name: 'ossa_generate',
|
|
124
|
-
arguments: { path: manifestPath },
|
|
125
|
-
});
|
|
126
|
-
// Should return error (not crash) when manifest lacks spec.capabilities
|
|
127
|
-
const data = JSON.parse(result.content[0].text);
|
|
128
|
-
expect(data).toBeDefined();
|
|
129
|
-
});
|
|
130
|
-
});
|
|
131
|
-
describe('ossa_publish', () => {
|
|
132
|
-
it('dry-run returns payload without sending', async () => {
|
|
133
|
-
// Use scaffolded manifest
|
|
134
|
-
const manifestPath = path.join(tmpDir, 'test-agent/manifest.ossa.yaml');
|
|
135
|
-
const result = await client.callTool({
|
|
136
|
-
name: 'ossa_publish',
|
|
137
|
-
arguments: { path: manifestPath, dry_run: true },
|
|
138
|
-
});
|
|
139
|
-
expect(result.isError).toBeFalsy();
|
|
140
|
-
const data = JSON.parse(result.content[0].text);
|
|
141
|
-
expect(data.dry_run).toBe(true);
|
|
142
|
-
expect(data.payload).toBeDefined();
|
|
143
|
-
expect(data.payload.manifest).toBeDefined();
|
|
144
|
-
});
|
|
145
|
-
it('returns instructions when no registry configured', async () => {
|
|
146
|
-
const manifestPath = path.join(tmpDir, 'test-agent/manifest.ossa.yaml');
|
|
147
|
-
const result = await client.callTool({
|
|
148
|
-
name: 'ossa_publish',
|
|
149
|
-
arguments: { path: manifestPath },
|
|
150
|
-
});
|
|
151
|
-
expect(result.isError).toBeFalsy();
|
|
152
|
-
const data = JSON.parse(result.content[0].text);
|
|
153
|
-
expect(data.next_steps).toBeDefined();
|
|
154
|
-
expect(data.next_steps.length).toBeGreaterThan(0);
|
|
155
|
-
});
|
|
156
|
-
});
|
|
157
|
-
describe('ossa_list', () => {
|
|
158
|
-
it('discovers agents in spec/reference', async () => {
|
|
159
|
-
const result = await client.callTool({
|
|
160
|
-
name: 'ossa_list',
|
|
161
|
-
arguments: { directory: FIXTURE_DIR, format: 'json' },
|
|
162
|
-
});
|
|
163
|
-
expect(result.isError).toBeFalsy();
|
|
164
|
-
const data = JSON.parse(result.content[0].text);
|
|
165
|
-
expect(data.count).toBeGreaterThanOrEqual(1);
|
|
166
|
-
expect(data.agents).toBeInstanceOf(Array);
|
|
167
|
-
expect(data.agents[0]).toHaveProperty('name');
|
|
168
|
-
expect(data.agents[0]).toHaveProperty('path');
|
|
169
|
-
});
|
|
170
|
-
it('returns summary format by default', async () => {
|
|
171
|
-
const result = await client.callTool({
|
|
172
|
-
name: 'ossa_list',
|
|
173
|
-
arguments: { directory: FIXTURE_DIR },
|
|
174
|
-
});
|
|
175
|
-
expect(result.isError).toBeFalsy();
|
|
176
|
-
const data = JSON.parse(result.content[0].text);
|
|
177
|
-
expect(data.count).toBeGreaterThanOrEqual(1);
|
|
178
|
-
// Summary format returns strings, not objects
|
|
179
|
-
expect(typeof data.agents[0]).toBe('string');
|
|
180
|
-
});
|
|
181
|
-
});
|
|
182
|
-
describe('ossa_inspect', () => {
|
|
183
|
-
it('deep-inspects a manifest', async () => {
|
|
184
|
-
const manifestPath = path.join(FIXTURE_DIR, 'compliance-auditor/manifest.ossa.yaml');
|
|
185
|
-
const result = await client.callTool({
|
|
186
|
-
name: 'ossa_inspect',
|
|
187
|
-
arguments: { path: manifestPath },
|
|
188
|
-
});
|
|
189
|
-
expect(result.isError).toBeFalsy();
|
|
190
|
-
const data = JSON.parse(result.content[0].text);
|
|
191
|
-
expect(data.name).toBeDefined();
|
|
192
|
-
expect(data.kind).toBeDefined();
|
|
193
|
-
expect(data.apiVersion).toBeDefined();
|
|
194
|
-
expect(data.validation).toBeDefined();
|
|
195
|
-
expect(data.validation.valid).toBeDefined();
|
|
196
|
-
expect(data.file_size_bytes).toBeGreaterThan(0);
|
|
197
|
-
});
|
|
198
|
-
});
|
|
199
|
-
describe('ossa_convert', () => {
|
|
200
|
-
const manifestPath = path.join(FIXTURE_DIR, 'compliance-auditor/manifest.ossa.yaml');
|
|
201
|
-
it('converts to kagent v1alpha2 format with Agent + ModelConfig', async () => {
|
|
202
|
-
const result = await client.callTool({
|
|
203
|
-
name: 'ossa_convert',
|
|
204
|
-
arguments: { path: manifestPath, target: 'kagent' },
|
|
205
|
-
});
|
|
206
|
-
expect(result.isError).toBeFalsy();
|
|
207
|
-
const data = JSON.parse(result.content[0].text);
|
|
208
|
-
expect(data.target).toBe('kagent');
|
|
209
|
-
// v1alpha2 multi-resource output: Agent + ModelConfig
|
|
210
|
-
expect(data.content._ossa_multi_resource).toBe(true);
|
|
211
|
-
expect(data.content.resources).toBeInstanceOf(Array);
|
|
212
|
-
expect(data.content.resources.length).toBe(2);
|
|
213
|
-
// Agent CRD
|
|
214
|
-
const agent = data.content.agent;
|
|
215
|
-
expect(agent.apiVersion).toBe('kagent.dev/v1alpha2');
|
|
216
|
-
expect(agent.kind).toBe('Agent');
|
|
217
|
-
expect(agent.spec.type).toBe('Declarative');
|
|
218
|
-
expect(agent.spec.declarative.modelConfig).toBeDefined();
|
|
219
|
-
expect(agent.spec.declarative.systemMessage).toBeDefined();
|
|
220
|
-
// ModelConfig CRD
|
|
221
|
-
const modelCfg = data.content.modelConfig;
|
|
222
|
-
expect(modelCfg.apiVersion).toBe('kagent.dev/v1alpha2');
|
|
223
|
-
expect(modelCfg.kind).toBe('ModelConfig');
|
|
224
|
-
});
|
|
225
|
-
it('converts to docker-compose format', async () => {
|
|
226
|
-
const result = await client.callTool({
|
|
227
|
-
name: 'ossa_convert',
|
|
228
|
-
arguments: { path: manifestPath, target: 'docker' },
|
|
229
|
-
});
|
|
230
|
-
expect(result.isError).toBeFalsy();
|
|
231
|
-
const data = JSON.parse(result.content[0].text);
|
|
232
|
-
expect(data.target).toBe('docker');
|
|
233
|
-
expect(data.content.version).toBe('3.8');
|
|
234
|
-
expect(data.content.services).toBeDefined();
|
|
235
|
-
});
|
|
236
|
-
it('converts to langchain format', async () => {
|
|
237
|
-
const result = await client.callTool({
|
|
238
|
-
name: 'ossa_convert',
|
|
239
|
-
arguments: { path: manifestPath, target: 'langchain' },
|
|
240
|
-
});
|
|
241
|
-
expect(result.isError).toBeFalsy();
|
|
242
|
-
const data = JSON.parse(result.content[0].text);
|
|
243
|
-
expect(data.target).toBe('langchain');
|
|
244
|
-
expect(data.content._type).toBe('agent');
|
|
245
|
-
});
|
|
246
|
-
it('converts to crewai format', async () => {
|
|
247
|
-
const result = await client.callTool({
|
|
248
|
-
name: 'ossa_convert',
|
|
249
|
-
arguments: { path: manifestPath, target: 'crewai' },
|
|
250
|
-
});
|
|
251
|
-
expect(result.isError).toBeFalsy();
|
|
252
|
-
const data = JSON.parse(result.content[0].text);
|
|
253
|
-
expect(data.target).toBe('crewai');
|
|
254
|
-
expect(data.content.agents).toBeInstanceOf(Array);
|
|
255
|
-
});
|
|
256
|
-
it('converts to anthropic format', async () => {
|
|
257
|
-
const result = await client.callTool({
|
|
258
|
-
name: 'ossa_convert',
|
|
259
|
-
arguments: { path: manifestPath, target: 'anthropic' },
|
|
260
|
-
});
|
|
261
|
-
expect(result.isError).toBeFalsy();
|
|
262
|
-
const data = JSON.parse(result.content[0].text);
|
|
263
|
-
expect(data.target).toBe('anthropic');
|
|
264
|
-
expect(data.content.model).toBeDefined();
|
|
265
|
-
expect(data.content.system).toBeDefined();
|
|
266
|
-
});
|
|
267
|
-
it('converts to a2a agent-card format', async () => {
|
|
268
|
-
const result = await client.callTool({
|
|
269
|
-
name: 'ossa_convert',
|
|
270
|
-
arguments: { path: manifestPath, target: 'agent-card' },
|
|
271
|
-
});
|
|
272
|
-
expect(result.isError).toBeFalsy();
|
|
273
|
-
const data = JSON.parse(result.content[0].text);
|
|
274
|
-
expect(data.target).toBe('agent-card');
|
|
275
|
-
expect(data.content.name).toBeDefined();
|
|
276
|
-
expect(data.content.description).toBeDefined();
|
|
277
|
-
expect(data.content.url).toBeDefined();
|
|
278
|
-
expect(data.content.capabilities).toBeDefined();
|
|
279
|
-
expect(data.content.skills).toBeInstanceOf(Array);
|
|
280
|
-
});
|
|
281
|
-
it('converts to openai format', async () => {
|
|
282
|
-
const result = await client.callTool({
|
|
283
|
-
name: 'ossa_convert',
|
|
284
|
-
arguments: { path: manifestPath, target: 'openai' },
|
|
285
|
-
});
|
|
286
|
-
expect(result.isError).toBeFalsy();
|
|
287
|
-
const data = JSON.parse(result.content[0].text);
|
|
288
|
-
expect(data.target).toBe('openai');
|
|
289
|
-
expect(data.content.model).toBeDefined();
|
|
290
|
-
expect(data.content.instructions).toBeDefined();
|
|
291
|
-
expect(data.content.tools).toBeInstanceOf(Array);
|
|
292
|
-
if (data.content.tools.length > 0) {
|
|
293
|
-
expect(data.content.tools[0].type).toBe('function');
|
|
294
|
-
expect(data.content.tools[0].function.name).toBeDefined();
|
|
295
|
-
}
|
|
296
|
-
});
|
|
297
|
-
it('converts to autogen format', async () => {
|
|
298
|
-
const result = await client.callTool({
|
|
299
|
-
name: 'ossa_convert',
|
|
300
|
-
arguments: { path: manifestPath, target: 'autogen' },
|
|
301
|
-
});
|
|
302
|
-
expect(result.isError).toBeFalsy();
|
|
303
|
-
const data = JSON.parse(result.content[0].text);
|
|
304
|
-
expect(data.target).toBe('autogen');
|
|
305
|
-
expect(data.content.name).toBeDefined();
|
|
306
|
-
expect(data.content.system_message).toBeDefined();
|
|
307
|
-
expect(data.content.llm_config).toBeDefined();
|
|
308
|
-
expect(data.content.llm_config.config_list).toBeInstanceOf(Array);
|
|
309
|
-
});
|
|
310
|
-
it('converts to semantic-kernel format', async () => {
|
|
311
|
-
const result = await client.callTool({
|
|
312
|
-
name: 'ossa_convert',
|
|
313
|
-
arguments: { path: manifestPath, target: 'semantic-kernel' },
|
|
314
|
-
});
|
|
315
|
-
expect(result.isError).toBeFalsy();
|
|
316
|
-
const data = JSON.parse(result.content[0].text);
|
|
317
|
-
expect(data.target).toBe('semantic-kernel');
|
|
318
|
-
expect(data.content.name).toBeDefined();
|
|
319
|
-
expect(data.content.instructions).toBeDefined();
|
|
320
|
-
expect(data.content.execution_settings).toBeDefined();
|
|
321
|
-
expect(data.content.plugins).toBeInstanceOf(Array);
|
|
322
|
-
});
|
|
323
|
-
it('agent-card includes all platform adapters with SDK references', async () => {
|
|
324
|
-
const result = await client.callTool({
|
|
325
|
-
name: 'ossa_convert',
|
|
326
|
-
arguments: { path: manifestPath, target: 'agent-card' },
|
|
327
|
-
});
|
|
328
|
-
expect(result.isError).toBeFalsy();
|
|
329
|
-
const data = JSON.parse(result.content[0].text);
|
|
330
|
-
const adapters = data.content.adapters;
|
|
331
|
-
expect(adapters).toBeDefined();
|
|
332
|
-
// All 12 platforms present
|
|
333
|
-
const expectedPlatforms = [
|
|
334
|
-
'openai',
|
|
335
|
-
'anthropic',
|
|
336
|
-
'google_genai',
|
|
337
|
-
'langchain',
|
|
338
|
-
'langflow',
|
|
339
|
-
'crewai',
|
|
340
|
-
'autogen',
|
|
341
|
-
'semantic_kernel',
|
|
342
|
-
'llamaindex',
|
|
343
|
-
'dspy',
|
|
344
|
-
'kagent',
|
|
345
|
-
'gitlab_duo',
|
|
346
|
-
];
|
|
347
|
-
for (const platform of expectedPlatforms) {
|
|
348
|
-
expect(adapters[platform]).toBeDefined();
|
|
349
|
-
}
|
|
350
|
-
// Each adapter has sdk, config, usage
|
|
351
|
-
expect(adapters.openai.sdk.npm).toBe('openai');
|
|
352
|
-
expect(adapters.openai.sdk.pip).toBe('openai');
|
|
353
|
-
expect(adapters.openai.config).toBeDefined();
|
|
354
|
-
expect(adapters.openai.usage).toBeDefined();
|
|
355
|
-
expect(adapters.anthropic.sdk.npm).toBe('@anthropic-ai/sdk');
|
|
356
|
-
expect(adapters.anthropic.sdk.pip).toBe('anthropic');
|
|
357
|
-
expect(adapters.google_genai.sdk.npm).toBe('@google/generative-ai');
|
|
358
|
-
expect(adapters.langchain.sdk.pip).toBeInstanceOf(Array);
|
|
359
|
-
expect(adapters.llamaindex.sdk.pip).toBe('llama-index');
|
|
360
|
-
expect(adapters.dspy.sdk.pip).toBe('dspy');
|
|
361
|
-
// MCP section
|
|
362
|
-
expect(data.content.mcp).toBeDefined();
|
|
363
|
-
expect(data.content.mcp.tools).toBeInstanceOf(Array);
|
|
364
|
-
// OSSA contract
|
|
365
|
-
expect(data.content.ossa).toBeDefined();
|
|
366
|
-
expect(data.content.ossa.role).toBeDefined();
|
|
367
|
-
});
|
|
368
|
-
it('converts to gitlab-duo format', async () => {
|
|
369
|
-
const result = await client.callTool({
|
|
370
|
-
name: 'ossa_convert',
|
|
371
|
-
arguments: { path: manifestPath, target: 'gitlab-duo' },
|
|
372
|
-
});
|
|
373
|
-
expect(result.isError).toBeFalsy();
|
|
374
|
-
const data = JSON.parse(result.content[0].text);
|
|
375
|
-
expect(data.target).toBe('gitlab-duo');
|
|
376
|
-
expect(data.content.name).toBeDefined();
|
|
377
|
-
});
|
|
378
|
-
it('writes converted output to disk', async () => {
|
|
379
|
-
const outDir = path.join(tmpDir, 'convert-output');
|
|
380
|
-
const result = await client.callTool({
|
|
381
|
-
name: 'ossa_convert',
|
|
382
|
-
arguments: { path: manifestPath, target: 'kagent', output_dir: outDir },
|
|
383
|
-
});
|
|
384
|
-
expect(result.isError).toBeFalsy();
|
|
385
|
-
const data = JSON.parse(result.content[0].text);
|
|
386
|
-
expect(data.written_to).toBeDefined();
|
|
387
|
-
expect(fs.existsSync(data.written_to)).toBe(true);
|
|
388
|
-
});
|
|
389
|
-
});
|
|
390
|
-
describe('ossa_workspace', () => {
|
|
391
|
-
it('initializes a workspace', async () => {
|
|
392
|
-
const wsDir = path.join(tmpDir, 'ws-test');
|
|
393
|
-
fs.mkdirSync(wsDir, { recursive: true });
|
|
394
|
-
const result = await client.callTool({
|
|
395
|
-
name: 'ossa_workspace',
|
|
396
|
-
arguments: { action: 'init', directory: wsDir, name: 'test-workspace' },
|
|
397
|
-
});
|
|
398
|
-
expect(result.isError).toBeFalsy();
|
|
399
|
-
const data = JSON.parse(result.content[0].text);
|
|
400
|
-
expect(data.action).toBe('init');
|
|
401
|
-
expect(data.status).toBe('created');
|
|
402
|
-
expect(fs.existsSync(path.join(wsDir, '.agents-workspace'))).toBe(true);
|
|
403
|
-
});
|
|
404
|
-
it('discovers agents in a directory', async () => {
|
|
405
|
-
const result = await client.callTool({
|
|
406
|
-
name: 'ossa_workspace',
|
|
407
|
-
arguments: { action: 'discover', directory: FIXTURE_DIR },
|
|
408
|
-
});
|
|
409
|
-
expect(result.isError).toBeFalsy();
|
|
410
|
-
const data = JSON.parse(result.content[0].text);
|
|
411
|
-
expect(data.action).toBe('discover');
|
|
412
|
-
expect(data.count).toBeGreaterThanOrEqual(1);
|
|
413
|
-
expect(data.agents).toBeInstanceOf(Array);
|
|
414
|
-
expect(data.agents[0].name).toBeDefined();
|
|
415
|
-
});
|
|
416
|
-
it('shows workspace status', async () => {
|
|
417
|
-
const wsDir = path.join(tmpDir, 'ws-test');
|
|
418
|
-
const result = await client.callTool({
|
|
419
|
-
name: 'ossa_workspace',
|
|
420
|
-
arguments: { action: 'status', directory: wsDir },
|
|
421
|
-
});
|
|
422
|
-
expect(result.isError).toBeFalsy();
|
|
423
|
-
const data = JSON.parse(result.content[0].text);
|
|
424
|
-
expect(data.action).toBe('status');
|
|
425
|
-
expect(data.initialized).toBe(true);
|
|
426
|
-
});
|
|
427
|
-
});
|
|
428
|
-
describe('ossa_diff', () => {
|
|
429
|
-
it('compares two manifests and detects differences', async () => {
|
|
430
|
-
// Create two slightly different manifests for comparison
|
|
431
|
-
const dirA = path.join(tmpDir, 'diff-a');
|
|
432
|
-
const dirB = path.join(tmpDir, 'diff-b');
|
|
433
|
-
fs.mkdirSync(dirA, { recursive: true });
|
|
434
|
-
fs.mkdirSync(dirB, { recursive: true });
|
|
435
|
-
fs.writeFileSync(path.join(dirA, 'manifest.ossa.yaml'), `apiVersion: ossa/v0.4\nkind: Agent\nmetadata:\n name: agent-a\n version: 1.0.0\nspec:\n role: Agent A\n tools:\n - name: tool-one\n`);
|
|
436
|
-
fs.writeFileSync(path.join(dirB, 'manifest.ossa.yaml'), `apiVersion: ossa/v0.4\nkind: Agent\nmetadata:\n name: agent-b\n version: 2.0.0\nspec:\n role: Agent B\n tools:\n - name: tool-two\n`);
|
|
437
|
-
const result = await client.callTool({
|
|
438
|
-
name: 'ossa_diff',
|
|
439
|
-
arguments: {
|
|
440
|
-
path_a: path.join(dirA, 'manifest.ossa.yaml'),
|
|
441
|
-
path_b: path.join(dirB, 'manifest.ossa.yaml'),
|
|
442
|
-
},
|
|
443
|
-
});
|
|
444
|
-
expect(result.isError).toBeFalsy();
|
|
445
|
-
const data = JSON.parse(result.content[0].text);
|
|
446
|
-
expect(data.total_changes).toBeGreaterThanOrEqual(1);
|
|
447
|
-
expect(data.changes).toBeInstanceOf(Array);
|
|
448
|
-
expect(data.breaking_changes).toBeInstanceOf(Array);
|
|
449
|
-
expect(data.breaking_changes.length).toBeGreaterThan(0); // name changed = breaking
|
|
450
|
-
expect(typeof data.compatible).toBe('boolean');
|
|
451
|
-
expect(data.compatible).toBe(false); // name changed
|
|
452
|
-
});
|
|
453
|
-
});
|
|
454
|
-
describe('ossa_migrate', () => {
|
|
455
|
-
it('migrates a manifest to v0.4', async () => {
|
|
456
|
-
const manifestPath = path.join(tmpDir, 'test-agent/manifest.ossa.yaml');
|
|
457
|
-
const result = await client.callTool({
|
|
458
|
-
name: 'ossa_migrate',
|
|
459
|
-
arguments: { path: manifestPath, target_version: 'ossa/v0.4' },
|
|
460
|
-
});
|
|
461
|
-
expect(result.isError).toBeFalsy();
|
|
462
|
-
const data = JSON.parse(result.content[0].text);
|
|
463
|
-
expect(data.migrated).toBeDefined();
|
|
464
|
-
});
|
|
465
|
-
it('writes migrated manifest to output dir', async () => {
|
|
466
|
-
const manifestPath = path.join(tmpDir, 'test-agent/manifest.ossa.yaml');
|
|
467
|
-
const outDir = path.join(tmpDir, 'migrate-output');
|
|
468
|
-
const result = await client.callTool({
|
|
469
|
-
name: 'ossa_migrate',
|
|
470
|
-
arguments: { path: manifestPath, output_dir: outDir },
|
|
471
|
-
});
|
|
472
|
-
expect(result.isError).toBeFalsy();
|
|
473
|
-
const data = JSON.parse(result.content[0].text);
|
|
474
|
-
if (data.written_to) {
|
|
475
|
-
expect(fs.existsSync(data.written_to)).toBe(true);
|
|
476
|
-
}
|
|
477
|
-
});
|
|
478
|
-
});
|
|
479
|
-
describe('MCP resources', () => {
|
|
480
|
-
it('lists all OSSA resources', async () => {
|
|
481
|
-
const resources = await client.listResources();
|
|
482
|
-
expect(resources.resources.length).toBeGreaterThanOrEqual(5);
|
|
483
|
-
const uris = resources.resources.map((r) => r.uri);
|
|
484
|
-
expect(uris).toContain('ossa://schema/v0.4/agent');
|
|
485
|
-
expect(uris).toContain('ossa://template/minimal');
|
|
486
|
-
expect(uris).toContain('ossa://template/full');
|
|
487
|
-
expect(uris).toContain('ossa://guide/mcp-ossa-a2a');
|
|
488
|
-
expect(uris).toContain('ossa://platforms/supported');
|
|
489
|
-
});
|
|
490
|
-
it('reads minimal template', async () => {
|
|
491
|
-
const result = await client.readResource({
|
|
492
|
-
uri: 'ossa://template/minimal',
|
|
493
|
-
});
|
|
494
|
-
expect(result.contents.length).toBe(1);
|
|
495
|
-
expect(readTextResource(result.contents[0])).toContain('apiVersion: ossa/v0.4');
|
|
496
|
-
expect(readTextResource(result.contents[0])).toContain('kind: Agent');
|
|
497
|
-
});
|
|
498
|
-
it('reads full template with all sections', async () => {
|
|
499
|
-
const result = await client.readResource({ uri: 'ossa://template/full' });
|
|
500
|
-
expect(readTextResource(result.contents[0])).toContain('spec:');
|
|
501
|
-
expect(readTextResource(result.contents[0])).toContain('tools:');
|
|
502
|
-
expect(readTextResource(result.contents[0])).toContain('autonomy:');
|
|
503
|
-
expect(readTextResource(result.contents[0])).toContain('extensions:');
|
|
504
|
-
expect(readTextResource(result.contents[0])).toContain('token_efficiency:');
|
|
505
|
-
});
|
|
506
|
-
it('reads MCP→OSSA→A2A guide', async () => {
|
|
507
|
-
const result = await client.readResource({
|
|
508
|
-
uri: 'ossa://guide/mcp-ossa-a2a',
|
|
509
|
-
});
|
|
510
|
-
expect(readTextResource(result.contents[0])).toContain('MCP');
|
|
511
|
-
expect(readTextResource(result.contents[0])).toContain('OSSA');
|
|
512
|
-
expect(readTextResource(result.contents[0])).toContain('A2A');
|
|
513
|
-
});
|
|
514
|
-
it('reads supported platforms with SDK references', async () => {
|
|
515
|
-
const result = await client.readResource({
|
|
516
|
-
uri: 'ossa://platforms/supported',
|
|
517
|
-
});
|
|
518
|
-
const platforms = JSON.parse(readTextResource(result.contents[0]));
|
|
519
|
-
expect(platforms.total).toBeGreaterThanOrEqual(14);
|
|
520
|
-
expect(platforms.platforms).toBeInstanceOf(Array);
|
|
521
|
-
const openai = platforms.platforms.find((p) => p.id === 'openai');
|
|
522
|
-
expect(openai.sdk.npm).toBe('openai');
|
|
523
|
-
expect(openai.sdk.pip).toBe('openai');
|
|
524
|
-
});
|
|
525
|
-
});
|
|
526
|
-
describe('MCP prompts', () => {
|
|
527
|
-
it('lists all prompts', async () => {
|
|
528
|
-
const prompts = await client.listPrompts();
|
|
529
|
-
expect(prompts.prompts.length).toBeGreaterThanOrEqual(4);
|
|
530
|
-
const names = prompts.prompts.map((p) => p.name);
|
|
531
|
-
expect(names).toContain('create-agent');
|
|
532
|
-
expect(names).toContain('convert-for-platform');
|
|
533
|
-
expect(names).toContain('explain-manifest');
|
|
534
|
-
expect(names).toContain('what-is-ossa');
|
|
535
|
-
});
|
|
536
|
-
it('gets create-agent prompt', async () => {
|
|
537
|
-
const result = await client.getPrompt({
|
|
538
|
-
name: 'create-agent',
|
|
539
|
-
arguments: { description: 'a code review bot' },
|
|
540
|
-
});
|
|
541
|
-
expect(result.messages.length).toBeGreaterThanOrEqual(1);
|
|
542
|
-
expect(JSON.stringify(result.messages[0].content)).toContain('code review bot');
|
|
543
|
-
});
|
|
544
|
-
it('gets what-is-ossa prompt', async () => {
|
|
545
|
-
const result = await client.getPrompt({ name: 'what-is-ossa' });
|
|
546
|
-
expect(result.messages.length).toBeGreaterThanOrEqual(1);
|
|
547
|
-
expect(JSON.stringify(result.messages[0].content)).toContain('OSSA');
|
|
548
|
-
});
|
|
549
|
-
});
|
|
550
|
-
describe('error handling', () => {
|
|
551
|
-
it('returns error for unknown tool', async () => {
|
|
552
|
-
const result = await client.callTool({
|
|
553
|
-
name: 'ossa_nonexistent',
|
|
554
|
-
arguments: {},
|
|
555
|
-
});
|
|
556
|
-
expect(result.isError).toBe(true);
|
|
557
|
-
});
|
|
558
|
-
it('returns error for missing required arguments', async () => {
|
|
559
|
-
const result = await client.callTool({
|
|
560
|
-
name: 'ossa_validate',
|
|
561
|
-
arguments: {},
|
|
562
|
-
});
|
|
563
|
-
expect(result.isError).toBe(true);
|
|
564
|
-
});
|
|
565
|
-
});
|
|
566
|
-
//# sourceMappingURL=mcp-server.spec.js.map
|