@lssm/example.agent-console 0.0.0-canary-20251225044228 → 0.0.0-canary-20251225052113

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.
@@ -61,6 +61,34 @@ const CreateToolCommand = defineCommand({
61
61
  payload: ToolSummaryModel
62
62
  }],
63
63
  audit: ["tool.created"]
64
+ },
65
+ acceptance: {
66
+ scenarios: [{
67
+ key: "create-tool-happy-path",
68
+ given: ["User is authenticated", "Organization exists"],
69
+ when: ["User submits valid tool configuration"],
70
+ then: ["New tool is created", "ToolCreated event is emitted"]
71
+ }, {
72
+ key: "create-tool-slug-conflict",
73
+ given: ["Tool with same slug exists"],
74
+ when: ["User submits tool with duplicate slug"],
75
+ then: ["SLUG_EXISTS error is returned"]
76
+ }],
77
+ examples: [{
78
+ key: "create-api-tool",
79
+ input: {
80
+ name: "Weather API",
81
+ slug: "weather-api",
82
+ category: "api",
83
+ description: "Fetches weather data"
84
+ },
85
+ output: {
86
+ id: "tool-123",
87
+ name: "Weather API",
88
+ slug: "weather-api",
89
+ status: "draft"
90
+ }
91
+ }]
64
92
  }
65
93
  });
66
94
  /**
@@ -119,6 +147,27 @@ const UpdateToolCommand = defineCommand({
119
147
  payload: ToolSummaryModel
120
148
  }],
121
149
  audit: ["tool.updated"]
150
+ },
151
+ acceptance: {
152
+ scenarios: [{
153
+ key: "update-tool-happy-path",
154
+ given: ["Tool exists", "User owns the tool"],
155
+ when: ["User submits updated configuration"],
156
+ then: ["Tool is updated", "ToolUpdated event is emitted"]
157
+ }],
158
+ examples: [{
159
+ key: "update-description",
160
+ input: {
161
+ toolId: "tool-123",
162
+ description: "Updated weather API tool"
163
+ },
164
+ output: {
165
+ id: "tool-123",
166
+ name: "Weather API",
167
+ status: "draft",
168
+ updatedAt: "2025-01-01T00:00:00Z"
169
+ }
170
+ }]
122
171
  }
123
172
  });
124
173
  /**
@@ -151,7 +200,25 @@ const GetToolQuery = defineQuery({
151
200
  when: "Tool ID is invalid"
152
201
  } }
153
202
  },
154
- policy: { auth: "user" }
203
+ policy: { auth: "user" },
204
+ acceptance: {
205
+ scenarios: [{
206
+ key: "get-tool-happy-path",
207
+ given: ["Tool exists"],
208
+ when: ["User requests tool by ID"],
209
+ then: ["Tool details are returned"]
210
+ }],
211
+ examples: [{
212
+ key: "get-basic",
213
+ input: { toolId: "tool-123" },
214
+ output: {
215
+ id: "tool-123",
216
+ name: "Weather API",
217
+ status: "active",
218
+ category: "api"
219
+ }
220
+ }]
221
+ }
155
222
  });
156
223
  /**
157
224
  * ListToolsQuery - Lists tools for an organization.
@@ -218,7 +285,28 @@ const ListToolsQuery = defineQuery({
218
285
  }
219
286
  })
220
287
  },
221
- policy: { auth: "user" }
288
+ policy: { auth: "user" },
289
+ acceptance: {
290
+ scenarios: [{
291
+ key: "list-tools-happy-path",
292
+ given: ["Organization has tools"],
293
+ when: ["User lists tools"],
294
+ then: ["Paginated list of tools is returned"]
295
+ }],
296
+ examples: [{
297
+ key: "list-by-category",
298
+ input: {
299
+ organizationId: "org-123",
300
+ category: "api",
301
+ limit: 10
302
+ },
303
+ output: {
304
+ items: [],
305
+ total: 0,
306
+ hasMore: false
307
+ }
308
+ }]
309
+ }
222
310
  });
223
311
  /**
224
312
  * TestToolCommand - Tests a tool with sample input.
@@ -285,7 +373,32 @@ const TestToolCommand = defineCommand({
285
373
  }
286
374
  },
287
375
  policy: { auth: "user" },
288
- sideEffects: { audit: ["tool.tested"] }
376
+ sideEffects: { audit: ["tool.tested"] },
377
+ acceptance: {
378
+ scenarios: [{
379
+ key: "test-tool-success",
380
+ given: ["Tool exists", "Tool is configured correctly"],
381
+ when: ["User runs test with valid input"],
382
+ then: ["Tool executes successfully", "Output is returned"]
383
+ }, {
384
+ key: "test-tool-failure",
385
+ given: ["Tool exists", "Tool has configuration error"],
386
+ when: ["User runs test"],
387
+ then: ["TOOL_EXECUTION_ERROR is returned"]
388
+ }],
389
+ examples: [{
390
+ key: "test-weather-api",
391
+ input: {
392
+ toolId: "tool-123",
393
+ testInput: { city: "Paris" }
394
+ },
395
+ output: {
396
+ success: true,
397
+ output: { temperature: 22 },
398
+ durationMs: 150
399
+ }
400
+ }]
401
+ }
289
402
  });
290
403
 
291
404
  //#endregion
@@ -1 +1 @@
1
- {"version":3,"file":"tool.operation.js","names":[],"sources":["../../src/tool/tool.operation.ts"],"sourcesContent":["import { defineCommand, defineQuery } from '@lssm/lib.contracts/operations';\nimport { defineSchemaModel, ScalarTypeEnum } from '@lssm/lib.schema';\nimport { ToolCategoryEnum, ToolStatusEnum } from './tool.enum';\nimport {\n CreateToolInputModel,\n ToolModel,\n ToolSummaryModel,\n UpdateToolInputModel,\n} from './tool.schema';\n\nconst OWNERS = ['@agent-console-team'] as const;\n\n/**\n * CreateToolCommand - Creates a new tool definition.\n */\nexport const CreateToolCommand = defineCommand({\n meta: {\n key: 'agent.tool.create',\n version: 1,\n stability: 'stable',\n owners: [...OWNERS],\n tags: ['tool', 'create'],\n description: 'Creates a new AI tool definition.',\n goal: 'Allow users to define new tools that agents can use.',\n context: 'Called from the tool builder UI when creating a new tool.',\n },\n io: {\n input: CreateToolInputModel,\n output: defineSchemaModel({\n name: 'CreateToolOutput',\n fields: {\n id: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },\n name: { type: ScalarTypeEnum.NonEmptyString(), isOptional: false },\n slug: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },\n status: { type: ToolStatusEnum, isOptional: false },\n },\n }),\n errors: {\n SLUG_EXISTS: {\n description: 'A tool with this slug already exists in the organization',\n http: 409,\n gqlCode: 'SLUG_EXISTS',\n when: 'Slug is already taken',\n },\n },\n },\n policy: { auth: 'user' },\n sideEffects: {\n emits: [\n {\n key: 'tool.created',\n version: 1,\n stability: 'stable',\n owners: [...OWNERS],\n tags: ['tool', 'created'],\n when: 'Tool is successfully created',\n payload: ToolSummaryModel,\n },\n ],\n audit: ['tool.created'],\n },\n});\n\n/**\n * UpdateToolCommand - Updates an existing tool.\n */\nexport const UpdateToolCommand = defineCommand({\n meta: {\n key: 'agent.tool.update',\n version: 1,\n stability: 'stable',\n owners: [...OWNERS],\n tags: ['tool', 'update'],\n description: 'Updates an existing AI tool definition.',\n goal: 'Allow users to modify tool settings and configuration.',\n context: 'Called from the tool settings UI.',\n },\n io: {\n input: UpdateToolInputModel,\n output: defineSchemaModel({\n name: 'UpdateToolOutput',\n fields: {\n id: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },\n name: { type: ScalarTypeEnum.NonEmptyString(), isOptional: false },\n status: { type: ToolStatusEnum, isOptional: false },\n updatedAt: { type: ScalarTypeEnum.DateTime(), isOptional: false },\n },\n }),\n errors: {\n TOOL_NOT_FOUND: {\n description: 'The specified tool does not exist',\n http: 404,\n gqlCode: 'TOOL_NOT_FOUND',\n when: 'Tool ID is invalid',\n },\n },\n },\n policy: { auth: 'user' },\n sideEffects: {\n emits: [\n {\n key: 'tool.updated',\n version: 1,\n stability: 'stable',\n owners: [...OWNERS],\n tags: ['tool', 'updated'],\n when: 'Tool is updated',\n payload: ToolSummaryModel,\n },\n ],\n audit: ['tool.updated'],\n },\n});\n\n/**\n * GetToolQuery - Retrieves a tool by ID.\n */\nexport const GetToolQuery = defineQuery({\n meta: {\n key: 'agent.tool.get',\n version: 1,\n stability: 'stable',\n owners: [...OWNERS],\n tags: ['tool', 'get'],\n description: 'Retrieves a tool by its ID.',\n goal: 'View detailed tool configuration.',\n context: 'Called when viewing tool details or editing.',\n },\n io: {\n input: defineSchemaModel({\n name: 'GetToolInput',\n fields: {\n toolId: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },\n },\n }),\n output: ToolModel,\n errors: {\n TOOL_NOT_FOUND: {\n description: 'The specified tool does not exist',\n http: 404,\n gqlCode: 'TOOL_NOT_FOUND',\n when: 'Tool ID is invalid',\n },\n },\n },\n policy: { auth: 'user' },\n});\n\n/**\n * ListToolsQuery - Lists tools for an organization.\n */\nexport const ListToolsQuery = defineQuery({\n meta: {\n key: 'agent.tool.list',\n version: 1,\n stability: 'stable',\n owners: [...OWNERS],\n tags: ['tool', 'list'],\n description: 'Lists tools for an organization with optional filtering.',\n goal: 'Browse and search available tools.',\n context: 'Tool list/dashboard view.',\n },\n io: {\n input: defineSchemaModel({\n name: 'ListToolsInput',\n fields: {\n organizationId: {\n type: ScalarTypeEnum.String_unsecure(),\n isOptional: false,\n },\n category: { type: ToolCategoryEnum, isOptional: true },\n status: { type: ToolStatusEnum, isOptional: true },\n search: { type: ScalarTypeEnum.String_unsecure(), isOptional: true },\n limit: {\n type: ScalarTypeEnum.Int_unsecure(),\n isOptional: true,\n defaultValue: 20,\n },\n offset: {\n type: ScalarTypeEnum.Int_unsecure(),\n isOptional: true,\n defaultValue: 0,\n },\n },\n }),\n output: defineSchemaModel({\n name: 'ListToolsOutput',\n fields: {\n items: { type: ToolSummaryModel, isArray: true, isOptional: false },\n total: { type: ScalarTypeEnum.Int_unsecure(), isOptional: false },\n hasMore: { type: ScalarTypeEnum.Boolean(), isOptional: false },\n },\n }),\n },\n policy: { auth: 'user' },\n});\n\n/**\n * TestToolCommand - Tests a tool with sample input.\n */\nexport const TestToolCommand = defineCommand({\n meta: {\n key: 'agent.tool.test',\n version: 1,\n stability: 'stable',\n owners: [...OWNERS],\n tags: ['tool', 'test'],\n description: 'Tests a tool with sample input to verify it works correctly.',\n goal: 'Validate tool configuration before deployment.',\n context: 'Tool builder UI - test panel.',\n },\n io: {\n input: defineSchemaModel({\n name: 'TestToolInput',\n fields: {\n toolId: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },\n testInput: { type: ScalarTypeEnum.JSONObject(), isOptional: false },\n },\n }),\n output: defineSchemaModel({\n name: 'TestToolOutput',\n fields: {\n success: { type: ScalarTypeEnum.Boolean(), isOptional: false },\n output: { type: ScalarTypeEnum.JSONObject(), isOptional: true },\n error: { type: ScalarTypeEnum.String_unsecure(), isOptional: true },\n durationMs: { type: ScalarTypeEnum.Int_unsecure(), isOptional: false },\n },\n }),\n errors: {\n TOOL_NOT_FOUND: {\n description: 'The specified tool does not exist',\n http: 404,\n gqlCode: 'TOOL_NOT_FOUND',\n when: 'Tool ID is invalid',\n },\n TOOL_EXECUTION_ERROR: {\n description: 'Tool execution failed',\n http: 500,\n gqlCode: 'TOOL_EXECUTION_ERROR',\n when: 'Tool returns an error',\n },\n },\n },\n policy: { auth: 'user' },\n sideEffects: { audit: ['tool.tested'] },\n});\n"],"mappings":"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"}
1
+ {"version":3,"file":"tool.operation.js","names":[],"sources":["../../src/tool/tool.operation.ts"],"sourcesContent":["import { defineCommand, defineQuery } from '@lssm/lib.contracts/operations';\nimport { defineSchemaModel, ScalarTypeEnum } from '@lssm/lib.schema';\nimport { ToolCategoryEnum, ToolStatusEnum } from './tool.enum';\nimport {\n CreateToolInputModel,\n ToolModel,\n ToolSummaryModel,\n UpdateToolInputModel,\n} from './tool.schema';\n\nconst OWNERS = ['@agent-console-team'] as const;\n\n/**\n * CreateToolCommand - Creates a new tool definition.\n */\nexport const CreateToolCommand = defineCommand({\n meta: {\n key: 'agent.tool.create',\n version: 1,\n stability: 'stable',\n owners: [...OWNERS],\n tags: ['tool', 'create'],\n description: 'Creates a new AI tool definition.',\n goal: 'Allow users to define new tools that agents can use.',\n context: 'Called from the tool builder UI when creating a new tool.',\n },\n io: {\n input: CreateToolInputModel,\n output: defineSchemaModel({\n name: 'CreateToolOutput',\n fields: {\n id: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },\n name: { type: ScalarTypeEnum.NonEmptyString(), isOptional: false },\n slug: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },\n status: { type: ToolStatusEnum, isOptional: false },\n },\n }),\n errors: {\n SLUG_EXISTS: {\n description: 'A tool with this slug already exists in the organization',\n http: 409,\n gqlCode: 'SLUG_EXISTS',\n when: 'Slug is already taken',\n },\n },\n },\n policy: { auth: 'user' },\n sideEffects: {\n emits: [\n {\n key: 'tool.created',\n version: 1,\n stability: 'stable',\n owners: [...OWNERS],\n tags: ['tool', 'created'],\n when: 'Tool is successfully created',\n payload: ToolSummaryModel,\n },\n ],\n audit: ['tool.created'],\n },\n acceptance: {\n scenarios: [\n {\n key: 'create-tool-happy-path',\n given: ['User is authenticated', 'Organization exists'],\n when: ['User submits valid tool configuration'],\n then: ['New tool is created', 'ToolCreated event is emitted'],\n },\n {\n key: 'create-tool-slug-conflict',\n given: ['Tool with same slug exists'],\n when: ['User submits tool with duplicate slug'],\n then: ['SLUG_EXISTS error is returned'],\n },\n ],\n examples: [\n {\n key: 'create-api-tool',\n input: { name: 'Weather API', slug: 'weather-api', category: 'api', description: 'Fetches weather data' },\n output: { id: 'tool-123', name: 'Weather API', slug: 'weather-api', status: 'draft' },\n },\n ],\n },\n});\n\n/**\n * UpdateToolCommand - Updates an existing tool.\n */\nexport const UpdateToolCommand = defineCommand({\n meta: {\n key: 'agent.tool.update',\n version: 1,\n stability: 'stable',\n owners: [...OWNERS],\n tags: ['tool', 'update'],\n description: 'Updates an existing AI tool definition.',\n goal: 'Allow users to modify tool settings and configuration.',\n context: 'Called from the tool settings UI.',\n },\n io: {\n input: UpdateToolInputModel,\n output: defineSchemaModel({\n name: 'UpdateToolOutput',\n fields: {\n id: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },\n name: { type: ScalarTypeEnum.NonEmptyString(), isOptional: false },\n status: { type: ToolStatusEnum, isOptional: false },\n updatedAt: { type: ScalarTypeEnum.DateTime(), isOptional: false },\n },\n }),\n errors: {\n TOOL_NOT_FOUND: {\n description: 'The specified tool does not exist',\n http: 404,\n gqlCode: 'TOOL_NOT_FOUND',\n when: 'Tool ID is invalid',\n },\n },\n },\n policy: { auth: 'user' },\n sideEffects: {\n emits: [\n {\n key: 'tool.updated',\n version: 1,\n stability: 'stable',\n owners: [...OWNERS],\n tags: ['tool', 'updated'],\n when: 'Tool is updated',\n payload: ToolSummaryModel,\n },\n ],\n audit: ['tool.updated'],\n },\n acceptance: {\n scenarios: [\n {\n key: 'update-tool-happy-path',\n given: ['Tool exists', 'User owns the tool'],\n when: ['User submits updated configuration'],\n then: ['Tool is updated', 'ToolUpdated event is emitted'],\n },\n ],\n examples: [\n {\n key: 'update-description',\n input: { toolId: 'tool-123', description: 'Updated weather API tool' },\n output: { id: 'tool-123', name: 'Weather API', status: 'draft', updatedAt: '2025-01-01T00:00:00Z' },\n },\n ],\n },\n});\n\n/**\n * GetToolQuery - Retrieves a tool by ID.\n */\nexport const GetToolQuery = defineQuery({\n meta: {\n key: 'agent.tool.get',\n version: 1,\n stability: 'stable',\n owners: [...OWNERS],\n tags: ['tool', 'get'],\n description: 'Retrieves a tool by its ID.',\n goal: 'View detailed tool configuration.',\n context: 'Called when viewing tool details or editing.',\n },\n io: {\n input: defineSchemaModel({\n name: 'GetToolInput',\n fields: {\n toolId: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },\n },\n }),\n output: ToolModel,\n errors: {\n TOOL_NOT_FOUND: {\n description: 'The specified tool does not exist',\n http: 404,\n gqlCode: 'TOOL_NOT_FOUND',\n when: 'Tool ID is invalid',\n },\n },\n },\n policy: { auth: 'user' },\n acceptance: {\n scenarios: [\n {\n key: 'get-tool-happy-path',\n given: ['Tool exists'],\n when: ['User requests tool by ID'],\n then: ['Tool details are returned'],\n },\n ],\n examples: [\n {\n key: 'get-basic',\n input: { toolId: 'tool-123' },\n output: { id: 'tool-123', name: 'Weather API', status: 'active', category: 'api' },\n },\n ],\n },\n});\n\n/**\n * ListToolsQuery - Lists tools for an organization.\n */\nexport const ListToolsQuery = defineQuery({\n meta: {\n key: 'agent.tool.list',\n version: 1,\n stability: 'stable',\n owners: [...OWNERS],\n tags: ['tool', 'list'],\n description: 'Lists tools for an organization with optional filtering.',\n goal: 'Browse and search available tools.',\n context: 'Tool list/dashboard view.',\n },\n io: {\n input: defineSchemaModel({\n name: 'ListToolsInput',\n fields: {\n organizationId: {\n type: ScalarTypeEnum.String_unsecure(),\n isOptional: false,\n },\n category: { type: ToolCategoryEnum, isOptional: true },\n status: { type: ToolStatusEnum, isOptional: true },\n search: { type: ScalarTypeEnum.String_unsecure(), isOptional: true },\n limit: {\n type: ScalarTypeEnum.Int_unsecure(),\n isOptional: true,\n defaultValue: 20,\n },\n offset: {\n type: ScalarTypeEnum.Int_unsecure(),\n isOptional: true,\n defaultValue: 0,\n },\n },\n }),\n output: defineSchemaModel({\n name: 'ListToolsOutput',\n fields: {\n items: { type: ToolSummaryModel, isArray: true, isOptional: false },\n total: { type: ScalarTypeEnum.Int_unsecure(), isOptional: false },\n hasMore: { type: ScalarTypeEnum.Boolean(), isOptional: false },\n },\n }),\n },\n policy: { auth: 'user' },\n acceptance: {\n scenarios: [\n {\n key: 'list-tools-happy-path',\n given: ['Organization has tools'],\n when: ['User lists tools'],\n then: ['Paginated list of tools is returned'],\n },\n ],\n examples: [\n {\n key: 'list-by-category',\n input: { organizationId: 'org-123', category: 'api', limit: 10 },\n output: { items: [], total: 0, hasMore: false },\n },\n ],\n },\n});\n\n/**\n * TestToolCommand - Tests a tool with sample input.\n */\nexport const TestToolCommand = defineCommand({\n meta: {\n key: 'agent.tool.test',\n version: 1,\n stability: 'stable',\n owners: [...OWNERS],\n tags: ['tool', 'test'],\n description: 'Tests a tool with sample input to verify it works correctly.',\n goal: 'Validate tool configuration before deployment.',\n context: 'Tool builder UI - test panel.',\n },\n io: {\n input: defineSchemaModel({\n name: 'TestToolInput',\n fields: {\n toolId: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },\n testInput: { type: ScalarTypeEnum.JSONObject(), isOptional: false },\n },\n }),\n output: defineSchemaModel({\n name: 'TestToolOutput',\n fields: {\n success: { type: ScalarTypeEnum.Boolean(), isOptional: false },\n output: { type: ScalarTypeEnum.JSONObject(), isOptional: true },\n error: { type: ScalarTypeEnum.String_unsecure(), isOptional: true },\n durationMs: { type: ScalarTypeEnum.Int_unsecure(), isOptional: false },\n },\n }),\n errors: {\n TOOL_NOT_FOUND: {\n description: 'The specified tool does not exist',\n http: 404,\n gqlCode: 'TOOL_NOT_FOUND',\n when: 'Tool ID is invalid',\n },\n TOOL_EXECUTION_ERROR: {\n description: 'Tool execution failed',\n http: 500,\n gqlCode: 'TOOL_EXECUTION_ERROR',\n when: 'Tool returns an error',\n },\n },\n },\n policy: { auth: 'user' },\n sideEffects: { audit: ['tool.tested'] },\n acceptance: {\n scenarios: [\n {\n key: 'test-tool-success',\n given: ['Tool exists', 'Tool is configured correctly'],\n when: ['User runs test with valid input'],\n then: ['Tool executes successfully', 'Output is returned'],\n },\n {\n key: 'test-tool-failure',\n given: ['Tool exists', 'Tool has configuration error'],\n when: ['User runs test'],\n then: ['TOOL_EXECUTION_ERROR is returned'],\n },\n ],\n examples: [\n {\n key: 'test-weather-api',\n input: { toolId: 'tool-123', testInput: { city: 'Paris' } },\n output: { success: true, output: { temperature: 22 }, durationMs: 150 },\n },\n ],\n },\n});\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"tool.presentation.d.ts","names":[],"sources":["../../src/tool/tool.presentation.ts"],"sourcesContent":[],"mappings":";;;;;;AAOA;AA2Ba,cA3BA,oBAgDZ,EAhDkC,gBAgDlC;;;;cArBY,wBAAwB"}
1
+ {"version":3,"file":"tool.presentation.d.ts","names":[],"sources":["../../src/tool/tool.presentation.ts"],"sourcesContent":[],"mappings":";;;;;;AAOA;AA2Ba,cA3BA,oBA2BwB,EA3BF,gBAgDlC;;;;cArBY,wBAAwB"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lssm/example.agent-console",
3
- "version": "0.0.0-canary-20251225044228",
3
+ "version": "0.0.0-canary-20251225052113",
4
4
  "description": "Agent Console example - AI agent orchestration with tools, runs, and logs",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -57,17 +57,17 @@
57
57
  "test": "bun run"
58
58
  },
59
59
  "dependencies": {
60
- "@lssm/lib.schema": "0.0.0-canary-20251225044228",
61
- "@lssm/lib.contracts": "0.0.0-canary-20251225044228",
62
- "@lssm/lib.identity-rbac": "0.0.0-canary-20251225044228",
63
- "@lssm/module.audit-trail": "0.0.0-canary-20251225044228",
64
- "@lssm/lib.jobs": "0.0.0-canary-20251225044228",
60
+ "@lssm/lib.schema": "0.0.0-canary-20251225052113",
61
+ "@lssm/lib.contracts": "0.0.0-canary-20251225052113",
62
+ "@lssm/lib.identity-rbac": "0.0.0-canary-20251225052113",
63
+ "@lssm/module.audit-trail": "0.0.0-canary-20251225052113",
64
+ "@lssm/lib.jobs": "0.0.0-canary-20251225052113",
65
65
  "zod": "^4.1.13"
66
66
  },
67
67
  "devDependencies": {
68
- "@lssm/tool.tsdown": "0.0.0-canary-20251225044228",
69
- "@lssm/tool.typescript": "0.0.0-canary-20251225044228",
70
- "tsdown": "^0.18.1",
68
+ "@lssm/tool.tsdown": "0.0.0-canary-20251225052113",
69
+ "@lssm/tool.typescript": "0.0.0-canary-20251225052113",
70
+ "tsdown": "^0.18.3",
71
71
  "typescript": "^5.9.3"
72
72
  },
73
73
  "module": "./dist/index.js",
@@ -59,6 +59,29 @@ export const CreateAgentCommand = defineCommand({
59
59
  ],
60
60
  audit: ['agent-console.agent.created'],
61
61
  },
62
+ acceptance: {
63
+ scenarios: [
64
+ {
65
+ key: 'create-agent-happy-path',
66
+ given: ['User is authenticated', 'Organization exists'],
67
+ when: ['User submits valid agent configuration'],
68
+ then: ['New agent is created with DRAFT status', 'AgentCreated event is emitted'],
69
+ },
70
+ {
71
+ key: 'create-agent-slug-conflict',
72
+ given: ['User is authenticated', 'Agent with same slug exists'],
73
+ when: ['User submits agent with duplicate slug'],
74
+ then: ['SLUG_EXISTS error is returned with 409 status'],
75
+ },
76
+ ],
77
+ examples: [
78
+ {
79
+ key: 'basic-create',
80
+ input: { name: 'Support Assistant', slug: 'support-assistant', modelProvider: 'openai', modelId: 'gpt-4' },
81
+ output: { id: 'agent-123', name: 'Support Assistant', slug: 'support-assistant', status: 'draft' },
82
+ },
83
+ ],
84
+ },
62
85
  });
63
86
 
64
87
  /**
@@ -110,6 +133,29 @@ export const UpdateAgentCommand = defineCommand({
110
133
  ],
111
134
  audit: ['agent.updated'],
112
135
  },
136
+ acceptance: {
137
+ scenarios: [
138
+ {
139
+ key: 'update-agent-happy-path',
140
+ given: ['Agent exists', 'User owns the agent'],
141
+ when: ['User submits updated configuration'],
142
+ then: ['Agent is updated', 'AgentUpdated event is emitted'],
143
+ },
144
+ {
145
+ key: 'update-agent-not-found',
146
+ given: ['Agent does not exist'],
147
+ when: ['User attempts to update'],
148
+ then: ['AGENT_NOT_FOUND error is returned'],
149
+ },
150
+ ],
151
+ examples: [
152
+ {
153
+ key: 'update-name',
154
+ input: { agentId: 'agent-123', name: 'Updated Assistant', systemPrompt: 'You are a helpful assistant.' },
155
+ output: { id: 'agent-123', name: 'Updated Assistant', status: 'draft', updatedAt: '2025-01-01T00:00:00Z' },
156
+ },
157
+ ],
158
+ },
113
159
  });
114
160
 
115
161
  /**
@@ -145,6 +191,29 @@ export const GetAgentQuery = defineQuery({
145
191
  },
146
192
  },
147
193
  policy: { auth: 'user' },
194
+ acceptance: {
195
+ scenarios: [
196
+ {
197
+ key: 'get-agent-happy-path',
198
+ given: ['Agent exists'],
199
+ when: ['User requests agent by ID'],
200
+ then: ['Agent details are returned'],
201
+ },
202
+ {
203
+ key: 'get-agent-with-tools',
204
+ given: ['Agent exists with assigned tools'],
205
+ when: ['User requests agent with includeTools=true'],
206
+ then: ['Agent details with tools list are returned'],
207
+ },
208
+ ],
209
+ examples: [
210
+ {
211
+ key: 'get-basic',
212
+ input: { agentId: 'agent-123', includeTools: false },
213
+ output: { id: 'agent-123', name: 'Support Assistant', status: 'active', tools: [] },
214
+ },
215
+ ],
216
+ },
148
217
  });
149
218
 
150
219
  /**
@@ -194,6 +263,29 @@ export const ListAgentsQuery = defineQuery({
194
263
  }),
195
264
  },
196
265
  policy: { auth: 'user' },
266
+ acceptance: {
267
+ scenarios: [
268
+ {
269
+ key: 'list-agents-happy-path',
270
+ given: ['Organization has agents'],
271
+ when: ['User lists agents'],
272
+ then: ['Paginated list of agents is returned'],
273
+ },
274
+ {
275
+ key: 'list-agents-filter-by-status',
276
+ given: ['Organization has agents with mixed statuses'],
277
+ when: ['User filters by status=active'],
278
+ then: ['Only active agents are returned'],
279
+ },
280
+ ],
281
+ examples: [
282
+ {
283
+ key: 'list-basic',
284
+ input: { organizationId: 'org-123', limit: 10, offset: 0 },
285
+ output: { items: [], total: 0, hasMore: false },
286
+ },
287
+ ],
288
+ },
197
289
  });
198
290
 
199
291
  /**
@@ -242,6 +334,29 @@ export const AssignToolToAgentCommand = defineCommand({
242
334
  },
243
335
  policy: { auth: 'user' },
244
336
  sideEffects: { audit: ['agent.tool.assigned'] },
337
+ acceptance: {
338
+ scenarios: [
339
+ {
340
+ key: 'assign-tool-happy-path',
341
+ given: ['Agent exists', 'Tool exists and is not assigned'],
342
+ when: ['User assigns tool to agent'],
343
+ then: ['Tool is assigned', 'Assignment ID is returned'],
344
+ },
345
+ {
346
+ key: 'assign-tool-already-assigned',
347
+ given: ['Tool is already assigned to agent'],
348
+ when: ['User attempts to assign again'],
349
+ then: ['TOOL_ALREADY_ASSIGNED error is returned'],
350
+ },
351
+ ],
352
+ examples: [
353
+ {
354
+ key: 'assign-basic',
355
+ input: { agentId: 'agent-123', toolId: 'tool-456' },
356
+ output: { agentToolId: 'at-789', agentId: 'agent-123', toolId: 'tool-456' },
357
+ },
358
+ ],
359
+ },
245
360
  });
246
361
 
247
362
  /**
@@ -275,4 +390,21 @@ export const RemoveToolFromAgentCommand = defineCommand({
275
390
  },
276
391
  policy: { auth: 'user' },
277
392
  sideEffects: { audit: ['agent.tool.removed'] },
393
+ acceptance: {
394
+ scenarios: [
395
+ {
396
+ key: 'remove-tool-happy-path',
397
+ given: ['Agent exists', 'Tool is assigned to agent'],
398
+ when: ['User removes tool from agent'],
399
+ then: ['Tool is unassigned', 'Success is returned'],
400
+ },
401
+ ],
402
+ examples: [
403
+ {
404
+ key: 'remove-basic',
405
+ input: { agentId: 'agent-123', toolId: 'tool-456' },
406
+ output: { success: true },
407
+ },
408
+ ],
409
+ },
278
410
  });
@@ -83,6 +83,29 @@ export const ExecuteAgentCommand = defineCommand({
83
83
  ],
84
84
  audit: ['run.started'],
85
85
  },
86
+ acceptance: {
87
+ scenarios: [
88
+ {
89
+ key: 'execute-agent-happy-path',
90
+ given: ['Agent exists', 'Agent is active'],
91
+ when: ['User submits execution request'],
92
+ then: ['Run is created', 'RunStarted event is emitted'],
93
+ },
94
+ {
95
+ key: 'execute-agent-not-active',
96
+ given: ['Agent exists but is not active'],
97
+ when: ['User attempts to execute'],
98
+ then: ['AGENT_NOT_ACTIVE error is returned'],
99
+ },
100
+ ],
101
+ examples: [
102
+ {
103
+ key: 'basic-execute',
104
+ input: { agentId: 'agent-123', input: { message: 'Hello' } },
105
+ output: { runId: 'run-456', status: 'pending', estimatedWaitMs: 5000 },
106
+ },
107
+ ],
108
+ },
86
109
  });
87
110
 
88
111
  /**
@@ -144,6 +167,29 @@ export const CancelRunCommand = defineCommand({
144
167
  ],
145
168
  audit: ['run.cancelled'],
146
169
  },
170
+ acceptance: {
171
+ scenarios: [
172
+ {
173
+ key: 'cancel-run-happy-path',
174
+ given: ['Run exists', 'Run is in progress'],
175
+ when: ['User cancels run'],
176
+ then: ['Run is cancelled', 'RunCancelled event is emitted'],
177
+ },
178
+ {
179
+ key: 'cancel-run-already-completed',
180
+ given: ['Run exists but is already completed'],
181
+ when: ['User attempts to cancel'],
182
+ then: ['RUN_NOT_CANCELLABLE error is returned'],
183
+ },
184
+ ],
185
+ examples: [
186
+ {
187
+ key: 'cancel-basic',
188
+ input: { runId: 'run-456', reason: 'User requested' },
189
+ output: { success: true, status: 'cancelled' },
190
+ },
191
+ ],
192
+ },
147
193
  });
148
194
 
149
195
  /**
@@ -180,6 +226,23 @@ export const GetRunQuery = defineQuery({
180
226
  },
181
227
  },
182
228
  policy: { auth: 'user' },
229
+ acceptance: {
230
+ scenarios: [
231
+ {
232
+ key: 'get-run-happy-path',
233
+ given: ['Run exists'],
234
+ when: ['User requests run by ID'],
235
+ then: ['Run details are returned'],
236
+ },
237
+ ],
238
+ examples: [
239
+ {
240
+ key: 'get-with-steps',
241
+ input: { runId: 'run-456', includeSteps: true, includeLogs: false },
242
+ output: { id: 'run-456', status: 'completed', steps: [] },
243
+ },
244
+ ],
245
+ },
183
246
  });
184
247
 
185
248
  /**
@@ -232,6 +295,23 @@ export const ListRunsQuery = defineQuery({
232
295
  }),
233
296
  },
234
297
  policy: { auth: 'user' },
298
+ acceptance: {
299
+ scenarios: [
300
+ {
301
+ key: 'list-runs-happy-path',
302
+ given: ['Organization has runs'],
303
+ when: ['User lists runs'],
304
+ then: ['Paginated list of runs is returned'],
305
+ },
306
+ ],
307
+ examples: [
308
+ {
309
+ key: 'list-by-agent',
310
+ input: { agentId: 'agent-123', limit: 20, offset: 0 },
311
+ output: { items: [], total: 0, hasMore: false },
312
+ },
313
+ ],
314
+ },
235
315
  });
236
316
 
237
317
  /**
@@ -263,6 +343,23 @@ export const GetRunStepsQuery = defineQuery({
263
343
  }),
264
344
  },
265
345
  policy: { auth: 'user' },
346
+ acceptance: {
347
+ scenarios: [
348
+ {
349
+ key: 'get-run-steps-happy-path',
350
+ given: ['Run exists with steps'],
351
+ when: ['User requests steps'],
352
+ then: ['Steps list is returned'],
353
+ },
354
+ ],
355
+ examples: [
356
+ {
357
+ key: 'get-steps-basic',
358
+ input: { runId: 'run-456' },
359
+ output: { steps: [] },
360
+ },
361
+ ],
362
+ },
266
363
  });
267
364
 
268
365
  /**
@@ -308,6 +405,23 @@ export const GetRunLogsQuery = defineQuery({
308
405
  }),
309
406
  },
310
407
  policy: { auth: 'user' },
408
+ acceptance: {
409
+ scenarios: [
410
+ {
411
+ key: 'get-run-logs-happy-path',
412
+ given: ['Run exists with logs'],
413
+ when: ['User requests logs'],
414
+ then: ['Paginated logs list is returned'],
415
+ },
416
+ ],
417
+ examples: [
418
+ {
419
+ key: 'get-logs-filtered',
420
+ input: { runId: 'run-456', level: 'error', limit: 50 },
421
+ output: { items: [], total: 0, hasMore: false },
422
+ },
423
+ ],
424
+ },
311
425
  });
312
426
 
313
427
  /**
@@ -373,4 +487,21 @@ export const GetRunMetricsQuery = defineQuery({
373
487
  }),
374
488
  },
375
489
  policy: { auth: 'user' },
490
+ acceptance: {
491
+ scenarios: [
492
+ {
493
+ key: 'get-run-metrics-happy-path',
494
+ given: ['Organization has run history'],
495
+ when: ['User requests metrics for date range'],
496
+ then: ['Aggregated metrics are returned'],
497
+ },
498
+ ],
499
+ examples: [
500
+ {
501
+ key: 'get-daily-metrics',
502
+ input: { organizationId: 'org-123', startDate: '2025-01-01', endDate: '2025-01-31', granularity: 'day' },
503
+ output: { totalRuns: 100, completedRuns: 90, failedRuns: 10, totalTokens: 50000, totalCostUsd: 5.0, averageDurationMs: 2500, successRate: 0.9, timeline: [] },
504
+ },
505
+ ],
506
+ },
376
507
  });