Skip to content

Commit e3d9f5d

Browse files
authored
Merge pull request #3 from multiagentcoordinationprotocol/fix-correctness-bugs
v0.4.0: Fix correctness bugs, add lossless reconnect, outbound track…
2 parents 176b836 + f9bdafa commit e3d9f5d

45 files changed

Lines changed: 1187 additions & 90 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
-- P1.3: Add capabilities, stream cursor, and stream timestamps to runtime_sessions
2+
ALTER TABLE "runtime_sessions" ADD COLUMN "capabilities" JSONB NOT NULL DEFAULT '{}';
3+
ALTER TABLE "runtime_sessions" ADD COLUMN "last_stream_cursor" INTEGER;
4+
ALTER TABLE "runtime_sessions" ADD COLUMN "stream_connected_at" TIMESTAMP WITH TIME ZONE;
5+
ALTER TABLE "runtime_sessions" ADD COLUMN "stream_disconnected_at" TIMESTAMP WITH TIME ZONE;
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
-- P1.4: Add schema_version to canonical events
2+
ALTER TABLE "run_events_canonical" ADD COLUMN "schema_version" INTEGER NOT NULL DEFAULT 3;
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
-- P1.5: Fix webhook active column from integer to boolean
2+
ALTER TABLE "webhooks" ALTER COLUMN "active" TYPE BOOLEAN USING (active = 1);
3+
ALTER TABLE "webhooks" ALTER COLUMN "active" SET DEFAULT true;

drizzle/0009_outbound_messages.sql

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
-- P2.2: Outbound message tracking table
2+
CREATE TABLE "run_outbound_messages" (
3+
"id" UUID PRIMARY KEY,
4+
"run_id" UUID NOT NULL REFERENCES "runs"("id") ON DELETE CASCADE,
5+
"runtime_session_id" VARCHAR(255) NOT NULL,
6+
"message_id" VARCHAR(255) NOT NULL,
7+
"message_type" VARCHAR(128) NOT NULL,
8+
"category" VARCHAR(32) NOT NULL,
9+
"sender" VARCHAR(255) NOT NULL,
10+
"recipients" JSONB NOT NULL DEFAULT '[]',
11+
"status" VARCHAR(32) NOT NULL DEFAULT 'queued',
12+
"payload_descriptor" JSONB NOT NULL DEFAULT '{}',
13+
"ack" JSONB,
14+
"error_message" TEXT,
15+
"created_at" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(),
16+
"accepted_at" TIMESTAMP WITH TIME ZONE,
17+
"updated_at" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now()
18+
);
19+
CREATE UNIQUE INDEX ON "run_outbound_messages" ("message_id");
20+
CREATE INDEX ON "run_outbound_messages" ("run_id");
21+
CREATE INDEX ON "run_outbound_messages" ("status");
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
-- P4.2: Durable webhook delivery tracking
2+
CREATE TABLE "webhook_deliveries" (
3+
"id" UUID PRIMARY KEY,
4+
"webhook_id" UUID NOT NULL REFERENCES "webhooks"("id") ON DELETE CASCADE,
5+
"event" VARCHAR(128) NOT NULL,
6+
"run_id" UUID NOT NULL,
7+
"payload" JSONB NOT NULL,
8+
"status" VARCHAR(32) NOT NULL DEFAULT 'pending',
9+
"attempts" INTEGER NOT NULL DEFAULT 0,
10+
"last_attempt_at" TIMESTAMP WITH TIME ZONE,
11+
"response_status" INTEGER,
12+
"error_message" TEXT,
13+
"created_at" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(),
14+
"delivered_at" TIMESTAMP WITH TIME ZONE
15+
);
16+
CREATE INDEX ON "webhook_deliveries" ("webhook_id");
17+
CREATE INDEX ON "webhook_deliveries" ("status");
18+
CREATE INDEX ON "webhook_deliveries" ("run_id");

package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/app.module.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ import { EventRepository } from './storage/event.repository';
3232
import { ArtifactRepository } from './storage/artifact.repository';
3333
import { MetricsRepository } from './storage/metrics.repository';
3434
import { ProjectionRepository } from './storage/projection.repository';
35+
import { OutboundMessageRepository } from './storage/outbound-message.repository';
3536
import { RunRepository } from './storage/run.repository';
3637
import { RuntimeSessionRepository } from './storage/runtime-session.repository';
3738
import { InstrumentationService } from './telemetry/instrumentation.service';
@@ -42,6 +43,7 @@ import { RunManagerService } from './runs/run-manager.service';
4243
import { RunRecoveryService } from './runs/run-recovery.service';
4344
import { StreamConsumerService } from './runs/stream-consumer.service';
4445
import { WebhookController } from './controllers/webhook.controller';
46+
import { WebhookDeliveryRepository } from './webhooks/webhook-delivery.repository';
4547
import { WebhookRepository } from './webhooks/webhook.repository';
4648
import { WebhookService } from './webhooks/webhook.service';
4749

@@ -68,6 +70,7 @@ import { WebhookService } from './webhooks/webhook.service';
6870
ProjectionRepository,
6971
ArtifactRepository,
7072
MetricsRepository,
73+
OutboundMessageRepository,
7174
StreamHubService,
7275
EventNormalizerService,
7376
ProjectionService,
@@ -82,6 +85,7 @@ import { WebhookService } from './webhooks/webhook.service';
8285
RunRecoveryService,
8386
RunInsightsService,
8487
WebhookRepository,
88+
WebhookDeliveryRepository,
8589
WebhookService
8690
]
8791
})

src/config/app-config.service.spec.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,13 @@ describe('AppConfigService', () => {
202202
});
203203
});
204204

205+
describe('clientVersion', () => {
206+
it('should read version from package.json', () => {
207+
const config = new AppConfigService();
208+
expect(config.clientVersion).toBe('0.3.0');
209+
});
210+
});
211+
205212
describe('readNumber edge cases', () => {
206213
it('should handle a valid number string for STREAM_BACKOFF_BASE_MS', () => {
207214
process.env.STREAM_BACKOFF_BASE_MS = '500';

src/config/app-config.service.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,16 @@ export class AppConfigService implements OnModuleInit {
2626
readonly nodeEnv = process.env.NODE_ENV ?? 'development';
2727
readonly isDevelopment = this.nodeEnv === 'development';
2828

29+
/** Read from package.json at startup */
30+
readonly clientVersion: string = (() => {
31+
try {
32+
// eslint-disable-next-line @typescript-eslint/no-require-imports
33+
return require('../../package.json').version as string;
34+
} catch {
35+
return '0.0.0';
36+
}
37+
})();
38+
2939
readonly port = readNumber('PORT', 3001);
3040
readonly host = process.env.HOST ?? '0.0.0.0';
3141
readonly corsOrigin = process.env.CORS_ORIGIN ?? 'http://localhost:3000';
@@ -68,6 +78,9 @@ export class AppConfigService implements OnModuleInit {
6878
readonly dbPoolIdleTimeout = readNumber('DB_POOL_IDLE_TIMEOUT', 30000);
6979
readonly dbPoolConnectionTimeout = readNumber('DB_POOL_CONNECTION_TIMEOUT', 5000);
7080

81+
readonly streamHubStrategy = process.env.STREAM_HUB_STRATEGY ?? 'memory';
82+
readonly redisUrl = process.env.REDIS_URL ?? '';
83+
7184
readonly logLevel = process.env.LOG_LEVEL ?? 'info';
7285
readonly otelEnabled = readBoolean('OTEL_ENABLED', false);
7386
readonly otelServiceName = process.env.OTEL_SERVICE_NAME ?? 'macp-control-plane';

src/contracts/control-plane.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,13 @@ export interface ProgressProjection {
236236
}>;
237237
}
238238

239+
export interface OutboundMessageSummary {
240+
total: number;
241+
queued: number;
242+
accepted: number;
243+
rejected: number;
244+
}
245+
239246
export interface RunStateProjection {
240247
run: RunSummaryProjection;
241248
participants: ParticipantProjection[];
@@ -245,6 +252,7 @@ export interface RunStateProjection {
245252
progress: ProgressProjection;
246253
timeline: TimelineProjection;
247254
trace: TraceSummary;
255+
outboundMessages: OutboundMessageSummary;
248256
}
249257

250258
export interface ReplayRequest {

0 commit comments

Comments
 (0)