| 1 | import { describe, expect, it } from 'vitest';
|
| 2 | import {
|
| 3 | buildOwnerCompletionReport,
|
| 4 | buildOwnerFeedback,
|
| 5 | buildQuickstartInteraction,
|
| 6 | } from '../apps/api/src/quickstart.js';
|
| 7 | import { buildPublicAgentCard } from '../packages/persistence/src/hosted.js';
|
| 8 | import type { AgentProfile } from '../packages/persistence/src/onboarding.js';
|
| 9 |
|
| 10 | const now = new Date('2026-08-31T10:00:00.000Z');
|
| 11 | const initiatorProfile: AgentProfile = {
|
| 12 | agentId: 'agent-owner',
|
| 13 | projectId: 'project-owner',
|
| 14 | name: 'Owner agent',
|
| 15 | description: 'Researches products',
|
| 16 | framework: 'OpenClasp hosted',
|
| 17 | agentVersion: '1.0.0',
|
| 18 | agentMode: 'temporary_chat',
|
| 19 | transport: 'openclasp_gateway',
|
| 20 | autoPublish: true,
|
| 21 | autoAcceptPolicy: 'off',
|
| 22 | autoAcceptTaskCategories: [],
|
| 23 | capabilities: ['research'],
|
| 24 | limitations: [],
|
| 25 | identityMode: 'owner_managed',
|
| 26 | status: 'active',
|
| 27 | createdAt: now.toISOString(),
|
| 28 | updatedAt: now.toISOString(),
|
| 29 | };
|
| 30 | const responderProfile: AgentProfile = {
|
| 31 | ...initiatorProfile,
|
| 32 | agentId: 'agent-peer',
|
| 33 | projectId: 'project-peer',
|
| 34 | name: 'Peer agent',
|
| 35 | framework: 'Custom runtime',
|
| 36 | agentMode: 'persistent_runtime',
|
| 37 | transport: 'direct_a2a',
|
| 38 | a2aEndpoint: 'https://peer.example/a2a',
|
| 39 | };
|
| 40 |
|
| 41 | describe('guided first interaction', () => {
|
| 42 | it('builds a canonical, accepted agreement from plain-language inputs', () => {
|
| 43 | const interaction = buildQuickstartInteraction(
|
| 44 | buildPublicAgentCard(initiatorProfile, 'https://openclasp.example'),
|
| 45 | buildPublicAgentCard(responderProfile, 'https://openclasp.example'),
|
| 46 | {
|
| 47 | task: 'Compare three support platforms',
|
| 48 | requestedOutcome: 'A ranked shortlist',
|
| 49 | successCriterion: 'Three current options with source links',
|
| 50 | taskCategory: 'research',
|
| 51 | },
|
| 52 | { interactionId: '11111111-1111-4111-8111-111111111111', now },
|
| 53 | );
|
| 54 | expect(interaction).toMatchObject({
|
| 55 | status: 'pending',
|
| 56 | initiatorAgentId: 'agent-owner',
|
| 57 | responderAgentId: 'agent-peer',
|
| 58 | contract: {
|
| 59 | requestedOutcome: 'A ranked shortlist',
|
| 60 | successCriteria: ['Three current options with source links'],
|
| 61 | prohibitedData: ['credentials', 'government identifiers', 'payment card data'],
|
| 62 | },
|
| 63 | acceptances: {
|
| 64 | 'agent-owner': { method: 'oauth_account' },
|
| 65 | },
|
| 66 | });
|
| 67 | });
|
| 68 |
|
| 69 | it('records owner-attested outcomes and normalized private feedback', () => {
|
| 70 | const interaction = buildQuickstartInteraction(
|
| 71 | buildPublicAgentCard(initiatorProfile, 'https://openclasp.example'),
|
| 72 | buildPublicAgentCard(responderProfile, 'https://openclasp.example'),
|
| 73 | {
|
| 74 | task: 'Compare three support platforms',
|
| 75 | requestedOutcome: 'A ranked shortlist',
|
| 76 | successCriterion: 'Three current options with source links',
|
| 77 | },
|
| 78 | { interactionId: '11111111-1111-4111-8111-111111111111', now },
|
| 79 | );
|
| 80 | const report = buildOwnerCompletionReport(
|
| 81 | { ...interaction, status: 'active' },
|
| 82 | initiatorProfile,
|
| 83 | { outcome: 'success', summary: 'Delivered a sourced comparison.' },
|
| 84 | { reportId: '22222222-2222-4222-8222-222222222222', now },
|
| 85 | );
|
| 86 | expect(report).toMatchObject({
|
| 87 | reportingAgentId: 'agent-owner',
|
| 88 | counterpartyAgentId: 'agent-peer',
|
| 89 | submissionMethod: 'oauth_account',
|
| 90 | criteria: [{ status: 'met' }],
|
| 91 | });
|
| 92 | const feedback = buildOwnerFeedback(
|
| 93 | {
|
| 94 | requestId: '33333333-3333-4333-8333-333333333333',
|
| 95 | interactionId: interaction.interactionId,
|
| 96 | reviewerAgentId: 'agent-owner',
|
| 97 | subjectAgentId: 'agent-peer',
|
| 98 | status: 'pending',
|
| 99 | requestedDimensions: ['overall_satisfaction', 'communication'],
|
| 100 | requestedAt: now.toISOString(),
|
| 101 | dueAt: new Date(now.getTime() + 86_400_000).toISOString(),
|
| 102 | },
|
| 103 | initiatorProfile,
|
| 104 | { rating: 4, wouldWorkAgain: 'yes' },
|
| 105 | { feedbackId: '44444444-4444-4444-8444-444444444444', now },
|
| 106 | );
|
| 107 | expect(feedback).toMatchObject({
|
| 108 | submissionMethod: 'oauth_account',
|
| 109 | ratings: { overall_satisfaction: 0.75, communication: 0.75 },
|
| 110 | });
|
| 111 | });
|
| 112 | });
|