@openscout/scout 0.2.60 → 0.2.61

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.
@@ -5501,116 +5501,6 @@ var init_mesh = () => {};
5501
5501
 
5502
5502
  // packages/protocol/dist/conversations.js
5503
5503
  var init_conversations = () => {};
5504
-
5505
- // packages/protocol/dist/collaboration.js
5506
- function isQuestionTerminalState(state) {
5507
- return state === "closed" || state === "declined";
5508
- }
5509
- function isWorkItemTerminalState(state) {
5510
- return state === "done" || state === "cancelled";
5511
- }
5512
- function collaborationRequiresNextMoveOwner(record) {
5513
- if (record.kind === "question") {
5514
- return !isQuestionTerminalState(record.state);
5515
- }
5516
- return !isWorkItemTerminalState(record.state);
5517
- }
5518
- function collaborationRequiresOwner(record) {
5519
- return record.kind === "work_item" && !isWorkItemTerminalState(record.state);
5520
- }
5521
- function collaborationRequiresWaitingOn(record) {
5522
- return record.kind === "work_item" && record.state === "waiting";
5523
- }
5524
- function collaborationRequiresAcceptance(record) {
5525
- if (record.acceptanceState === "none") {
5526
- return false;
5527
- }
5528
- if (record.kind === "question") {
5529
- return Boolean(record.askedById && record.askedOfId);
5530
- }
5531
- return Boolean(record.requestedById);
5532
- }
5533
- function validateCollaborationRecord(record) {
5534
- const errors = [];
5535
- if (!record.id.trim()) {
5536
- errors.push("collaboration record id is required");
5537
- }
5538
- if (!record.title.trim()) {
5539
- errors.push("collaboration title is required");
5540
- }
5541
- if (!record.createdById.trim()) {
5542
- errors.push("createdById is required");
5543
- }
5544
- if (record.parentId && record.parentId === record.id) {
5545
- errors.push("parentId cannot reference the record itself");
5546
- }
5547
- if (record.createdAt > record.updatedAt) {
5548
- errors.push("updatedAt must be greater than or equal to createdAt");
5549
- }
5550
- if (collaborationRequiresOwner(record) && !record.ownerId) {
5551
- errors.push("non-terminal work items require ownerId");
5552
- }
5553
- if (collaborationRequiresNextMoveOwner(record) && !record.nextMoveOwnerId) {
5554
- errors.push("non-terminal collaboration records require nextMoveOwnerId");
5555
- }
5556
- if (record.kind === "work_item" && collaborationRequiresWaitingOn(record) && !record.waitingOn) {
5557
- errors.push("waiting work items require waitingOn");
5558
- }
5559
- if (record.kind === "question") {
5560
- if (record.spawnedWorkItemId && record.spawnedWorkItemId === record.id) {
5561
- errors.push("question spawnedWorkItemId cannot reference the question itself");
5562
- }
5563
- } else if (record.waitingOn?.targetId && record.waitingOn.targetId === record.id) {
5564
- errors.push("waitingOn.targetId cannot reference the work item itself");
5565
- }
5566
- if (record.acceptanceState !== "none" && !collaborationRequiresAcceptance(record)) {
5567
- errors.push("acceptanceState requires the corresponding requester and reviewer identities");
5568
- }
5569
- return errors;
5570
- }
5571
- function assertValidCollaborationRecord(record) {
5572
- const errors = validateCollaborationRecord(record);
5573
- if (errors.length > 0) {
5574
- throw new Error(errors.join("; "));
5575
- }
5576
- }
5577
- function validateCollaborationEvent(event, record) {
5578
- const errors = [];
5579
- if (!event.id.trim()) {
5580
- errors.push("collaboration event id is required");
5581
- }
5582
- if (!event.recordId.trim()) {
5583
- errors.push("collaboration event recordId is required");
5584
- }
5585
- if (!event.actorId.trim()) {
5586
- errors.push("collaboration event actorId is required");
5587
- }
5588
- if (record) {
5589
- if (record.id !== event.recordId) {
5590
- errors.push("collaboration event recordId does not match the target record");
5591
- }
5592
- if (record.kind !== event.recordKind) {
5593
- errors.push("collaboration event recordKind does not match the target record");
5594
- }
5595
- }
5596
- if (event.kind === "answered" && event.recordKind !== "question") {
5597
- errors.push("answered events only apply to questions");
5598
- }
5599
- if (event.kind === "declined" && event.recordKind !== "question") {
5600
- errors.push("declined events only apply to questions");
5601
- }
5602
- if ((event.kind === "waiting" || event.kind === "progressed" || event.kind === "review_requested" || event.kind === "done" || event.kind === "cancelled") && event.recordKind !== "work_item") {
5603
- errors.push(`${event.kind} events only apply to work items`);
5604
- }
5605
- return errors;
5606
- }
5607
- function assertValidCollaborationEvent(event, record) {
5608
- const errors = validateCollaborationEvent(event, record);
5609
- if (errors.length > 0) {
5610
- throw new Error(errors.join("; "));
5611
- }
5612
- }
5613
-
5614
5504
  // packages/protocol/dist/messages.js
5615
5505
  var init_messages = () => {};
5616
5506
 
@@ -18128,2480 +18018,200 @@ function whoEntryState(endpoints, registrationKind) {
18128
18018
 
18129
18019
  // packages/web/server/core/observe/service.ts
18130
18020
  init_src();
18021
+ await init_local_agents();
18131
18022
  import { existsSync as existsSync12, readdirSync as readdirSync2, readFileSync as readFileSync8, statSync as statSync4 } from "fs";
18132
18023
  import { homedir as homedir12 } from "os";
18133
18024
  import { join as join18, resolve as resolve8 } from "path";
18134
-
18135
- // packages/runtime/src/registry.ts
18136
- function createRuntimeRegistrySnapshot(value = {}) {
18137
- return {
18138
- nodes: value.nodes ?? {},
18139
- actors: value.actors ?? {},
18140
- agents: value.agents ?? {},
18141
- endpoints: value.endpoints ?? {},
18142
- conversations: value.conversations ?? {},
18143
- bindings: value.bindings ?? {},
18144
- messages: value.messages ?? {},
18145
- flights: value.flights ?? {},
18146
- collaborationRecords: value.collaborationRecords ?? {}
18025
+ var HISTORY_SNAPSHOT_CACHE_LIMIT = 128;
18026
+ var historySnapshotCache = new Map;
18027
+ var OBSERVE_SUMMARY_TAIL_SIZE = 8;
18028
+ function activeEndpoint(snapshot, agentId) {
18029
+ const candidates = Object.values(snapshot.endpoints ?? {}).filter((endpoint) => endpoint.agentId === agentId);
18030
+ const rank = (state) => {
18031
+ switch (state) {
18032
+ case "active":
18033
+ return 0;
18034
+ case "idle":
18035
+ return 1;
18036
+ case "waiting":
18037
+ return 2;
18038
+ case "offline":
18039
+ return 5;
18040
+ default:
18041
+ return 4;
18042
+ }
18147
18043
  };
18044
+ return [...candidates].sort((left, right) => rank(left.state) - rank(right.state))[0] ?? null;
18148
18045
  }
18149
-
18150
- // packages/runtime/src/index.ts
18151
- init_harness_catalog();
18152
-
18153
- // packages/runtime/src/planner.ts
18154
- function createDeliveryId(messageId, targetId, reason, transport) {
18155
- return `del-${messageId}-${targetId}-${reason}-${transport}`;
18156
- }
18157
- function unique(values) {
18158
- return [...new Set(values)];
18159
- }
18160
- function resolveVisibilityAudience(message, conversation) {
18161
- if (message.audience?.visibleTo?.length) {
18162
- return unique(message.audience.visibleTo);
18046
+ function expandHome(value) {
18047
+ if (!value) {
18048
+ return null;
18163
18049
  }
18164
- return unique(conversation.participantIds.filter((participantId) => participantId !== message.actorId));
18165
- }
18166
- function resolveNotifyAudience(message) {
18167
- const fromMentions = (message.mentions ?? []).map((mention) => mention.actorId);
18168
- const explicit = message.audience?.notify ?? [];
18169
- return unique([...fromMentions, ...explicit].filter((actorId) => actorId !== message.actorId));
18170
- }
18171
- function resolveInvocationAudience(message) {
18172
- return unique((message.audience?.invoke ?? []).filter((actorId) => actorId !== message.actorId));
18050
+ if (value === "~") {
18051
+ return homedir12();
18052
+ }
18053
+ if (value.startsWith("~/")) {
18054
+ return join18(homedir12(), value.slice(2));
18055
+ }
18056
+ return value;
18173
18057
  }
18174
- function planTargetDelivery(message, route, reason, policy) {
18175
- return {
18176
- id: createDeliveryId(message.id, route.targetId, reason, route.transport),
18177
- messageId: message.id,
18178
- targetId: route.targetId,
18179
- targetNodeId: route.nodeId,
18180
- targetKind: route.targetKind,
18181
- transport: route.transport,
18182
- reason,
18183
- policy,
18184
- status: "pending",
18185
- bindingId: route.bindingId
18186
- };
18058
+ function encodeClaudeProjectsSlug2(absolutePath) {
18059
+ const normalized = resolve8(absolutePath);
18060
+ return `-${normalized.replace(/^\//u, "").replace(/\//gu, "-")}`;
18187
18061
  }
18188
- function planMessageDeliveries(input) {
18189
- const visibilityIds = new Set(resolveVisibilityAudience(input.message, input.conversation));
18190
- const notifyIds = new Set(resolveNotifyAudience(input.message));
18191
- const invokeIds = new Set(resolveInvocationAudience(input.message));
18192
- const deliveries2 = new Map;
18193
- for (const route of input.participantRoutes) {
18194
- if (visibilityIds.has(route.targetId)) {
18195
- const intent = planTargetDelivery(input.message, {
18196
- ...route,
18197
- transport: route.nodeId && input.localNodeId && route.nodeId !== input.localNodeId ? "peer_broker" : route.transport
18198
- }, input.conversation.kind === "direct" || input.conversation.kind === "group_direct" ? "direct_message" : "conversation_visibility", "durable");
18199
- deliveries2.set(intent.id, intent);
18200
- }
18201
- if (notifyIds.has(route.targetId)) {
18202
- const intent = planTargetDelivery(input.message, {
18203
- ...route,
18204
- transport: route.nodeId && input.localNodeId && route.nodeId !== input.localNodeId ? "peer_broker" : route.transport
18205
- }, "mention", "must_ack");
18206
- deliveries2.set(intent.id, intent);
18207
- }
18208
- if (invokeIds.has(route.targetId)) {
18209
- const intent = planTargetDelivery(input.message, {
18210
- ...route,
18211
- transport: route.nodeId && input.localNodeId && route.nodeId !== input.localNodeId ? "peer_broker" : route.transport
18212
- }, "invocation", "must_ack");
18213
- deliveries2.set(intent.id, intent);
18214
- }
18215
- if (input.message.speech?.text && route.speechEnabled) {
18216
- const speechIntent = planTargetDelivery(input.message, {
18217
- ...route,
18218
- transport: route.transport === "local_socket" ? "native_voice" : "tts",
18219
- targetKind: route.targetKind === "device" ? "voice_session" : route.targetKind
18220
- }, "speech", "best_effort");
18221
- deliveries2.set(speechIntent.id, speechIntent);
18222
- }
18223
- }
18224
- for (const route of input.bindingRoutes ?? []) {
18225
- const intent = planTargetDelivery(input.message, route, "bridge_outbound", "durable");
18226
- deliveries2.set(intent.id, intent);
18227
- }
18228
- return [...deliveries2.values()];
18229
- }
18230
- // node_modules/.bun/drizzle-orm@0.45.2+29ab9a45addfc34e/node_modules/drizzle-orm/entity.js
18231
- var entityKind = Symbol.for("drizzle:entityKind");
18232
- var hasOwnEntityKind = Symbol.for("drizzle:hasOwnEntityKind");
18233
- function is(value, type) {
18234
- if (!value || typeof value !== "object") {
18235
- return false;
18236
- }
18237
- if (value instanceof type) {
18238
- return true;
18062
+ function resolveClaudeHistoryPath(cwd, sessionId) {
18063
+ const normalizedCwd = expandHome(cwd)?.trim();
18064
+ if (!normalizedCwd) {
18065
+ return null;
18239
18066
  }
18240
- if (!Object.prototype.hasOwnProperty.call(type, entityKind)) {
18241
- throw new Error(`Class "${type.name ?? "<unknown>"}" doesn't look like a Drizzle entity. If this is incorrect and the class is provided by Drizzle, please report this as a bug.`);
18067
+ const projectDir = join18(homedir12(), ".claude", "projects", encodeClaudeProjectsSlug2(normalizedCwd));
18068
+ const normalizedSessionId = sessionId?.trim().replace(/\.jsonl$/u, "") || "";
18069
+ if (normalizedSessionId) {
18070
+ const exactPath = join18(projectDir, `${normalizedSessionId}.jsonl`);
18071
+ if (existsSync12(exactPath)) {
18072
+ return exactPath;
18073
+ }
18242
18074
  }
18243
- let cls = Object.getPrototypeOf(value).constructor;
18244
- if (cls) {
18245
- while (cls) {
18246
- if (entityKind in cls && cls[entityKind] === type[entityKind]) {
18247
- return true;
18075
+ return findMostRecentJsonl(projectDir);
18076
+ }
18077
+ function findMostRecentJsonl(dir) {
18078
+ if (!existsSync12(dir))
18079
+ return null;
18080
+ try {
18081
+ let best = null;
18082
+ for (const entry of readdirSync2(dir)) {
18083
+ if (!entry.endsWith(".jsonl"))
18084
+ continue;
18085
+ const full = join18(dir, entry);
18086
+ const st = statSync4(full);
18087
+ if (!best || st.mtimeMs > best.mtime) {
18088
+ best = { path: full, mtime: st.mtimeMs };
18248
18089
  }
18249
- cls = Object.getPrototypeOf(cls);
18250
18090
  }
18091
+ return best?.path ?? null;
18092
+ } catch {
18093
+ return null;
18251
18094
  }
18252
- return false;
18253
18095
  }
18254
-
18255
- // node_modules/.bun/drizzle-orm@0.45.2+29ab9a45addfc34e/node_modules/drizzle-orm/column.js
18256
- class Column {
18257
- constructor(table, config) {
18258
- this.table = table;
18259
- this.config = config;
18260
- this.name = config.name;
18261
- this.keyAsName = config.keyAsName;
18262
- this.notNull = config.notNull;
18263
- this.default = config.default;
18264
- this.defaultFn = config.defaultFn;
18265
- this.onUpdateFn = config.onUpdateFn;
18266
- this.hasDefault = config.hasDefault;
18267
- this.primary = config.primaryKey;
18268
- this.isUnique = config.isUnique;
18269
- this.uniqueName = config.uniqueName;
18270
- this.uniqueType = config.uniqueType;
18271
- this.dataType = config.dataType;
18272
- this.columnType = config.columnType;
18273
- this.generated = config.generated;
18274
- this.generatedIdentity = config.generatedIdentity;
18275
- }
18276
- static [entityKind] = "Column";
18277
- name;
18278
- keyAsName;
18279
- primary;
18280
- notNull;
18281
- default;
18282
- defaultFn;
18283
- onUpdateFn;
18284
- hasDefault;
18285
- isUnique;
18286
- uniqueName;
18287
- uniqueType;
18288
- dataType;
18289
- columnType;
18290
- enumValues = undefined;
18291
- generated = undefined;
18292
- generatedIdentity = undefined;
18293
- config;
18294
- mapFromDriverValue(value) {
18295
- return value;
18096
+ function historyAdapterAlias(value) {
18097
+ const normalized = value?.trim().toLowerCase();
18098
+ if (!normalized) {
18099
+ return null;
18296
18100
  }
18297
- mapToDriverValue(value) {
18298
- return value;
18101
+ if (normalized === "claude" || normalized === "claude-code" || normalized === "claude_stream_json") {
18102
+ return "claude-code";
18299
18103
  }
18300
- shouldDisableInsert() {
18301
- return this.config.generated !== undefined && this.config.generated.type !== "byDefault";
18104
+ if (normalized === "codex" || normalized === "codex_app_server") {
18105
+ return "codex";
18302
18106
  }
18107
+ return null;
18303
18108
  }
18304
-
18305
- // node_modules/.bun/drizzle-orm@0.45.2+29ab9a45addfc34e/node_modules/drizzle-orm/column-builder.js
18306
- class ColumnBuilder {
18307
- static [entityKind] = "ColumnBuilder";
18308
- config;
18309
- constructor(name, dataType, columnType) {
18310
- this.config = {
18311
- name,
18312
- keyAsName: name === "",
18313
- notNull: false,
18314
- default: undefined,
18315
- hasDefault: false,
18316
- primaryKey: false,
18317
- isUnique: false,
18318
- uniqueName: undefined,
18319
- uniqueType: undefined,
18320
- dataType,
18321
- columnType,
18322
- generated: undefined
18323
- };
18324
- }
18325
- $type() {
18326
- return this;
18327
- }
18328
- notNull() {
18329
- this.config.notNull = true;
18330
- return this;
18331
- }
18332
- default(value) {
18333
- this.config.default = value;
18334
- this.config.hasDefault = true;
18335
- return this;
18336
- }
18337
- $defaultFn(fn) {
18338
- this.config.defaultFn = fn;
18339
- this.config.hasDefault = true;
18340
- return this;
18341
- }
18342
- $default = this.$defaultFn;
18343
- $onUpdateFn(fn) {
18344
- this.config.onUpdateFn = fn;
18345
- this.config.hasDefault = true;
18346
- return this;
18109
+ function snapshotProviderMeta(snapshot) {
18110
+ const providerMeta = snapshot.session.providerMeta;
18111
+ return providerMeta && typeof providerMeta === "object" ? providerMeta : {};
18112
+ }
18113
+ function firstString(...values) {
18114
+ for (const value of values) {
18115
+ if (typeof value === "string" && value.trim().length > 0) {
18116
+ return value.trim();
18117
+ }
18347
18118
  }
18348
- $onUpdate = this.$onUpdateFn;
18349
- primaryKey() {
18350
- this.config.primaryKey = true;
18351
- this.config.notNull = true;
18352
- return this;
18119
+ return null;
18120
+ }
18121
+ function resolveHistoryCandidate(agent, snapshot) {
18122
+ const snapshotAdapter = historyAdapterAlias(snapshot?.session.adapterType);
18123
+ const agentAdapter = historyAdapterAlias(agent.harness);
18124
+ const providerMeta = snapshot ? snapshotProviderMeta(snapshot) : {};
18125
+ const directPath = firstString(providerMeta.resumeSessionPath, providerMeta.threadPath);
18126
+ if (directPath) {
18127
+ const adapterType = snapshotAdapter ?? agentAdapter;
18128
+ if (adapterType) {
18129
+ return { path: directPath, adapterType };
18130
+ }
18353
18131
  }
18354
- setName(name) {
18355
- if (this.config.name !== "")
18356
- return;
18357
- this.config.name = name;
18132
+ const claudeSessionId = firstString(providerMeta.transportSessionId, agent.harnessSessionId);
18133
+ const claudeCwd = firstString(snapshot?.session.cwd, agent.cwd, agent.projectRoot);
18134
+ if ((snapshotAdapter ?? agentAdapter) === "claude-code") {
18135
+ const path = resolveClaudeHistoryPath(claudeCwd, claudeSessionId);
18136
+ if (path) {
18137
+ return { path, adapterType: "claude-code" };
18138
+ }
18358
18139
  }
18140
+ return null;
18359
18141
  }
18360
-
18361
- // node_modules/.bun/drizzle-orm@0.45.2+29ab9a45addfc34e/node_modules/drizzle-orm/table.utils.js
18362
- var TableName = Symbol.for("drizzle:Name");
18363
-
18364
- // node_modules/.bun/drizzle-orm@0.45.2+29ab9a45addfc34e/node_modules/drizzle-orm/tracing-utils.js
18365
- function iife(fn, ...args) {
18366
- return fn(...args);
18367
- }
18368
-
18369
- // node_modules/.bun/drizzle-orm@0.45.2+29ab9a45addfc34e/node_modules/drizzle-orm/pg-core/unique-constraint.js
18370
- function uniqueKeyName(table, columns) {
18371
- return `${table[TableName]}_${columns.join("_")}_unique`;
18372
- }
18373
-
18374
- // node_modules/.bun/drizzle-orm@0.45.2+29ab9a45addfc34e/node_modules/drizzle-orm/pg-core/columns/common.js
18375
- class PgColumn extends Column {
18376
- constructor(table, config) {
18377
- if (!config.uniqueName) {
18378
- config.uniqueName = uniqueKeyName(table, [config.name]);
18379
- }
18380
- super(table, config);
18381
- this.table = table;
18142
+ function normalizeTimedEvents(events2) {
18143
+ if (!events2) {
18144
+ return [];
18382
18145
  }
18383
- static [entityKind] = "PgColumn";
18146
+ return events2.map((entry) => ({
18147
+ timestamp: entry.capturedAt,
18148
+ event: entry.event
18149
+ }));
18384
18150
  }
18385
-
18386
- class ExtraConfigColumn extends PgColumn {
18387
- static [entityKind] = "ExtraConfigColumn";
18388
- getSQLType() {
18389
- return this.getSQLType();
18390
- }
18391
- indexConfig = {
18392
- order: this.config.order ?? "asc",
18393
- nulls: this.config.nulls ?? "last",
18394
- opClass: this.config.opClass
18395
- };
18396
- defaultConfig = {
18397
- order: "asc",
18398
- nulls: "last",
18399
- opClass: undefined
18400
- };
18401
- asc() {
18402
- this.indexConfig.order = "asc";
18403
- return this;
18151
+ function readHistorySnapshot(candidate) {
18152
+ if (!candidate) {
18153
+ return null;
18404
18154
  }
18405
- desc() {
18406
- this.indexConfig.order = "desc";
18407
- return this;
18155
+ if (!supportsHistorySessionSnapshotForPath(candidate.path, candidate.adapterType)) {
18156
+ return null;
18408
18157
  }
18409
- nullsFirst() {
18410
- this.indexConfig.nulls = "first";
18411
- return this;
18158
+ if (!existsSync12(candidate.path)) {
18159
+ return null;
18412
18160
  }
18413
- nullsLast() {
18414
- this.indexConfig.nulls = "last";
18415
- return this;
18161
+ const stat5 = statSync4(candidate.path);
18162
+ const cached = historySnapshotCache.get(candidate.path);
18163
+ if (cached && cached.adapterType === candidate.adapterType && cached.mtimeMs === stat5.mtimeMs && cached.size === stat5.size) {
18164
+ return {
18165
+ historyPath: cached.historyPath,
18166
+ snapshot: cached.snapshot,
18167
+ timedEvents: cached.timedEvents
18168
+ };
18416
18169
  }
18417
- op(opClass) {
18418
- this.indexConfig.opClass = opClass;
18419
- return this;
18170
+ const replay = createHistorySessionSnapshot({
18171
+ path: candidate.path,
18172
+ content: readFileSync8(candidate.path, "utf8"),
18173
+ adapterType: candidate.adapterType,
18174
+ baseTimestampMs: stat5.mtimeMs
18175
+ });
18176
+ const nextEntry = {
18177
+ historyPath: candidate.path,
18178
+ snapshot: replay.snapshot,
18179
+ timedEvents: normalizeTimedEvents(replay.events),
18180
+ adapterType: candidate.adapterType,
18181
+ mtimeMs: stat5.mtimeMs,
18182
+ size: stat5.size
18183
+ };
18184
+ historySnapshotCache.set(candidate.path, nextEntry);
18185
+ if (historySnapshotCache.size > HISTORY_SNAPSHOT_CACHE_LIMIT) {
18186
+ const oldestKey = historySnapshotCache.keys().next().value;
18187
+ if (typeof oldestKey === "string") {
18188
+ historySnapshotCache.delete(oldestKey);
18189
+ }
18420
18190
  }
18191
+ return {
18192
+ historyPath: nextEntry.historyPath,
18193
+ snapshot: nextEntry.snapshot,
18194
+ timedEvents: nextEntry.timedEvents
18195
+ };
18421
18196
  }
18422
-
18423
- // node_modules/.bun/drizzle-orm@0.45.2+29ab9a45addfc34e/node_modules/drizzle-orm/pg-core/columns/enum.js
18424
- class PgEnumObjectColumn extends PgColumn {
18425
- static [entityKind] = "PgEnumObjectColumn";
18426
- enum;
18427
- enumValues = this.config.enum.enumValues;
18428
- constructor(table, config) {
18429
- super(table, config);
18430
- this.enum = config.enum;
18431
- }
18432
- getSQLType() {
18433
- return this.enum.enumName;
18197
+ async function readLiveSnapshot(endpoint) {
18198
+ if (!endpoint?.sessionId) {
18199
+ return null;
18434
18200
  }
18435
- }
18436
- var isPgEnumSym = Symbol.for("drizzle:isPgEnum");
18437
- function isPgEnum(obj) {
18438
- return !!obj && typeof obj === "function" && isPgEnumSym in obj && obj[isPgEnumSym] === true;
18439
- }
18440
- class PgEnumColumn extends PgColumn {
18441
- static [entityKind] = "PgEnumColumn";
18442
- enum = this.config.enum;
18443
- enumValues = this.config.enum.enumValues;
18444
- constructor(table, config) {
18445
- super(table, config);
18446
- this.enum = config.enum;
18201
+ if (endpoint.transport === "pairing_bridge") {
18202
+ return await getScoutWebPairingSessionSnapshot(endpoint.sessionId);
18447
18203
  }
18448
- getSQLType() {
18449
- return this.enum.enumName;
18204
+ if (endpoint.transport === "codex_app_server" || endpoint.transport === "claude_stream_json") {
18205
+ return await getLocalAgentEndpointSessionSnapshot(endpoint);
18450
18206
  }
18207
+ return null;
18451
18208
  }
18452
-
18453
- // node_modules/.bun/drizzle-orm@0.45.2+29ab9a45addfc34e/node_modules/drizzle-orm/subquery.js
18454
- class Subquery {
18455
- static [entityKind] = "Subquery";
18456
- constructor(sql, fields, alias, isWith = false, usedTables = []) {
18457
- this._ = {
18458
- brand: "Subquery",
18459
- sql,
18460
- selectedFields: fields,
18461
- alias,
18462
- isWith,
18463
- usedTables
18464
- };
18209
+ function summarizeCommandOutput(output) {
18210
+ const lines = output.split(/\r?\n/u).map((line) => line.trimEnd()).filter((line) => line.length > 0);
18211
+ if (lines.length === 0) {
18212
+ return;
18465
18213
  }
18466
- }
18467
-
18468
- // node_modules/.bun/drizzle-orm@0.45.2+29ab9a45addfc34e/node_modules/drizzle-orm/version.js
18469
- var version = "0.45.2";
18470
-
18471
- // node_modules/.bun/drizzle-orm@0.45.2+29ab9a45addfc34e/node_modules/drizzle-orm/tracing.js
18472
- var otel;
18473
- var rawTracer;
18474
- var tracer = {
18475
- startActiveSpan(name, fn) {
18476
- if (!otel) {
18477
- return fn();
18478
- }
18479
- if (!rawTracer) {
18480
- rawTracer = otel.trace.getTracer("drizzle-orm", version);
18481
- }
18482
- return iife((otel2, rawTracer2) => rawTracer2.startActiveSpan(name, (span) => {
18483
- try {
18484
- return fn(span);
18485
- } catch (e) {
18486
- span.setStatus({
18487
- code: otel2.SpanStatusCode.ERROR,
18488
- message: e instanceof Error ? e.message : "Unknown error"
18489
- });
18490
- throw e;
18491
- } finally {
18492
- span.end();
18493
- }
18494
- }), otel, rawTracer);
18495
- }
18496
- };
18497
-
18498
- // node_modules/.bun/drizzle-orm@0.45.2+29ab9a45addfc34e/node_modules/drizzle-orm/view-common.js
18499
- var ViewBaseConfig = Symbol.for("drizzle:ViewBaseConfig");
18500
-
18501
- // node_modules/.bun/drizzle-orm@0.45.2+29ab9a45addfc34e/node_modules/drizzle-orm/table.js
18502
- var Schema = Symbol.for("drizzle:Schema");
18503
- var Columns = Symbol.for("drizzle:Columns");
18504
- var ExtraConfigColumns = Symbol.for("drizzle:ExtraConfigColumns");
18505
- var OriginalName = Symbol.for("drizzle:OriginalName");
18506
- var BaseName = Symbol.for("drizzle:BaseName");
18507
- var IsAlias = Symbol.for("drizzle:IsAlias");
18508
- var ExtraConfigBuilder = Symbol.for("drizzle:ExtraConfigBuilder");
18509
- var IsDrizzleTable = Symbol.for("drizzle:IsDrizzleTable");
18510
-
18511
- class Table {
18512
- static [entityKind] = "Table";
18513
- static Symbol = {
18514
- Name: TableName,
18515
- Schema,
18516
- OriginalName,
18517
- Columns,
18518
- ExtraConfigColumns,
18519
- BaseName,
18520
- IsAlias,
18521
- ExtraConfigBuilder
18522
- };
18523
- [TableName];
18524
- [OriginalName];
18525
- [Schema];
18526
- [Columns];
18527
- [ExtraConfigColumns];
18528
- [BaseName];
18529
- [IsAlias] = false;
18530
- [IsDrizzleTable] = true;
18531
- [ExtraConfigBuilder] = undefined;
18532
- constructor(name, schema, baseName) {
18533
- this[TableName] = this[OriginalName] = name;
18534
- this[Schema] = schema;
18535
- this[BaseName] = baseName;
18536
- }
18537
- }
18538
-
18539
- // node_modules/.bun/drizzle-orm@0.45.2+29ab9a45addfc34e/node_modules/drizzle-orm/sql/sql.js
18540
- function isSQLWrapper(value) {
18541
- return value !== null && value !== undefined && typeof value.getSQL === "function";
18542
- }
18543
- function mergeQueries(queries) {
18544
- const result = { sql: "", params: [] };
18545
- for (const query of queries) {
18546
- result.sql += query.sql;
18547
- result.params.push(...query.params);
18548
- if (query.typings?.length) {
18549
- if (!result.typings) {
18550
- result.typings = [];
18551
- }
18552
- result.typings.push(...query.typings);
18553
- }
18554
- }
18555
- return result;
18556
- }
18557
-
18558
- class StringChunk {
18559
- static [entityKind] = "StringChunk";
18560
- value;
18561
- constructor(value) {
18562
- this.value = Array.isArray(value) ? value : [value];
18563
- }
18564
- getSQL() {
18565
- return new SQL([this]);
18566
- }
18567
- }
18568
-
18569
- class SQL {
18570
- constructor(queryChunks) {
18571
- this.queryChunks = queryChunks;
18572
- for (const chunk of queryChunks) {
18573
- if (is(chunk, Table)) {
18574
- const schemaName = chunk[Table.Symbol.Schema];
18575
- this.usedTables.push(schemaName === undefined ? chunk[Table.Symbol.Name] : schemaName + "." + chunk[Table.Symbol.Name]);
18576
- }
18577
- }
18578
- }
18579
- static [entityKind] = "SQL";
18580
- decoder = noopDecoder;
18581
- shouldInlineParams = false;
18582
- usedTables = [];
18583
- append(query) {
18584
- this.queryChunks.push(...query.queryChunks);
18585
- return this;
18586
- }
18587
- toQuery(config) {
18588
- return tracer.startActiveSpan("drizzle.buildSQL", (span) => {
18589
- const query = this.buildQueryFromSourceParams(this.queryChunks, config);
18590
- span?.setAttributes({
18591
- "drizzle.query.text": query.sql,
18592
- "drizzle.query.params": JSON.stringify(query.params)
18593
- });
18594
- return query;
18595
- });
18596
- }
18597
- buildQueryFromSourceParams(chunks, _config) {
18598
- const config = Object.assign({}, _config, {
18599
- inlineParams: _config.inlineParams || this.shouldInlineParams,
18600
- paramStartIndex: _config.paramStartIndex || { value: 0 }
18601
- });
18602
- const {
18603
- casing,
18604
- escapeName,
18605
- escapeParam,
18606
- prepareTyping,
18607
- inlineParams,
18608
- paramStartIndex
18609
- } = config;
18610
- return mergeQueries(chunks.map((chunk) => {
18611
- if (is(chunk, StringChunk)) {
18612
- return { sql: chunk.value.join(""), params: [] };
18613
- }
18614
- if (is(chunk, Name)) {
18615
- return { sql: escapeName(chunk.value), params: [] };
18616
- }
18617
- if (chunk === undefined) {
18618
- return { sql: "", params: [] };
18619
- }
18620
- if (Array.isArray(chunk)) {
18621
- const result = [new StringChunk("(")];
18622
- for (const [i, p] of chunk.entries()) {
18623
- result.push(p);
18624
- if (i < chunk.length - 1) {
18625
- result.push(new StringChunk(", "));
18626
- }
18627
- }
18628
- result.push(new StringChunk(")"));
18629
- return this.buildQueryFromSourceParams(result, config);
18630
- }
18631
- if (is(chunk, SQL)) {
18632
- return this.buildQueryFromSourceParams(chunk.queryChunks, {
18633
- ...config,
18634
- inlineParams: inlineParams || chunk.shouldInlineParams
18635
- });
18636
- }
18637
- if (is(chunk, Table)) {
18638
- const schemaName = chunk[Table.Symbol.Schema];
18639
- const tableName = chunk[Table.Symbol.Name];
18640
- return {
18641
- sql: schemaName === undefined || chunk[IsAlias] ? escapeName(tableName) : escapeName(schemaName) + "." + escapeName(tableName),
18642
- params: []
18643
- };
18644
- }
18645
- if (is(chunk, Column)) {
18646
- const columnName = casing.getColumnCasing(chunk);
18647
- if (_config.invokeSource === "indexes") {
18648
- return { sql: escapeName(columnName), params: [] };
18649
- }
18650
- const schemaName = chunk.table[Table.Symbol.Schema];
18651
- return {
18652
- sql: chunk.table[IsAlias] || schemaName === undefined ? escapeName(chunk.table[Table.Symbol.Name]) + "." + escapeName(columnName) : escapeName(schemaName) + "." + escapeName(chunk.table[Table.Symbol.Name]) + "." + escapeName(columnName),
18653
- params: []
18654
- };
18655
- }
18656
- if (is(chunk, View)) {
18657
- const schemaName = chunk[ViewBaseConfig].schema;
18658
- const viewName = chunk[ViewBaseConfig].name;
18659
- return {
18660
- sql: schemaName === undefined || chunk[ViewBaseConfig].isAlias ? escapeName(viewName) : escapeName(schemaName) + "." + escapeName(viewName),
18661
- params: []
18662
- };
18663
- }
18664
- if (is(chunk, Param)) {
18665
- if (is(chunk.value, Placeholder)) {
18666
- return { sql: escapeParam(paramStartIndex.value++, chunk), params: [chunk], typings: ["none"] };
18667
- }
18668
- const mappedValue = chunk.value === null ? null : chunk.encoder.mapToDriverValue(chunk.value);
18669
- if (is(mappedValue, SQL)) {
18670
- return this.buildQueryFromSourceParams([mappedValue], config);
18671
- }
18672
- if (inlineParams) {
18673
- return { sql: this.mapInlineParam(mappedValue, config), params: [] };
18674
- }
18675
- let typings = ["none"];
18676
- if (prepareTyping) {
18677
- typings = [prepareTyping(chunk.encoder)];
18678
- }
18679
- return { sql: escapeParam(paramStartIndex.value++, mappedValue), params: [mappedValue], typings };
18680
- }
18681
- if (is(chunk, Placeholder)) {
18682
- return { sql: escapeParam(paramStartIndex.value++, chunk), params: [chunk], typings: ["none"] };
18683
- }
18684
- if (is(chunk, SQL.Aliased) && chunk.fieldAlias !== undefined) {
18685
- return { sql: escapeName(chunk.fieldAlias), params: [] };
18686
- }
18687
- if (is(chunk, Subquery)) {
18688
- if (chunk._.isWith) {
18689
- return { sql: escapeName(chunk._.alias), params: [] };
18690
- }
18691
- return this.buildQueryFromSourceParams([
18692
- new StringChunk("("),
18693
- chunk._.sql,
18694
- new StringChunk(") "),
18695
- new Name(chunk._.alias)
18696
- ], config);
18697
- }
18698
- if (isPgEnum(chunk)) {
18699
- if (chunk.schema) {
18700
- return { sql: escapeName(chunk.schema) + "." + escapeName(chunk.enumName), params: [] };
18701
- }
18702
- return { sql: escapeName(chunk.enumName), params: [] };
18703
- }
18704
- if (isSQLWrapper(chunk)) {
18705
- if (chunk.shouldOmitSQLParens?.()) {
18706
- return this.buildQueryFromSourceParams([chunk.getSQL()], config);
18707
- }
18708
- return this.buildQueryFromSourceParams([
18709
- new StringChunk("("),
18710
- chunk.getSQL(),
18711
- new StringChunk(")")
18712
- ], config);
18713
- }
18714
- if (inlineParams) {
18715
- return { sql: this.mapInlineParam(chunk, config), params: [] };
18716
- }
18717
- return { sql: escapeParam(paramStartIndex.value++, chunk), params: [chunk], typings: ["none"] };
18718
- }));
18719
- }
18720
- mapInlineParam(chunk, { escapeString }) {
18721
- if (chunk === null) {
18722
- return "null";
18723
- }
18724
- if (typeof chunk === "number" || typeof chunk === "boolean") {
18725
- return chunk.toString();
18726
- }
18727
- if (typeof chunk === "string") {
18728
- return escapeString(chunk);
18729
- }
18730
- if (typeof chunk === "object") {
18731
- const mappedValueAsString = chunk.toString();
18732
- if (mappedValueAsString === "[object Object]") {
18733
- return escapeString(JSON.stringify(chunk));
18734
- }
18735
- return escapeString(mappedValueAsString);
18736
- }
18737
- throw new Error("Unexpected param value: " + chunk);
18738
- }
18739
- getSQL() {
18740
- return this;
18741
- }
18742
- as(alias) {
18743
- if (alias === undefined) {
18744
- return this;
18745
- }
18746
- return new SQL.Aliased(this, alias);
18747
- }
18748
- mapWith(decoder) {
18749
- this.decoder = typeof decoder === "function" ? { mapFromDriverValue: decoder } : decoder;
18750
- return this;
18751
- }
18752
- inlineParams() {
18753
- this.shouldInlineParams = true;
18754
- return this;
18755
- }
18756
- if(condition) {
18757
- return condition ? this : undefined;
18758
- }
18759
- }
18760
-
18761
- class Name {
18762
- constructor(value) {
18763
- this.value = value;
18764
- }
18765
- static [entityKind] = "Name";
18766
- brand;
18767
- getSQL() {
18768
- return new SQL([this]);
18769
- }
18770
- }
18771
- var noopDecoder = {
18772
- mapFromDriverValue: (value) => value
18773
- };
18774
- var noopEncoder = {
18775
- mapToDriverValue: (value) => value
18776
- };
18777
- var noopMapper = {
18778
- ...noopDecoder,
18779
- ...noopEncoder
18780
- };
18781
-
18782
- class Param {
18783
- constructor(value, encoder = noopEncoder) {
18784
- this.value = value;
18785
- this.encoder = encoder;
18786
- }
18787
- static [entityKind] = "Param";
18788
- brand;
18789
- getSQL() {
18790
- return new SQL([this]);
18791
- }
18792
- }
18793
- function sql(strings, ...params) {
18794
- const queryChunks = [];
18795
- if (params.length > 0 || strings.length > 0 && strings[0] !== "") {
18796
- queryChunks.push(new StringChunk(strings[0]));
18797
- }
18798
- for (const [paramIndex, param2] of params.entries()) {
18799
- queryChunks.push(param2, new StringChunk(strings[paramIndex + 1]));
18800
- }
18801
- return new SQL(queryChunks);
18802
- }
18803
- ((sql2) => {
18804
- function empty() {
18805
- return new SQL([]);
18806
- }
18807
- sql2.empty = empty;
18808
- function fromList(list) {
18809
- return new SQL(list);
18810
- }
18811
- sql2.fromList = fromList;
18812
- function raw2(str) {
18813
- return new SQL([new StringChunk(str)]);
18814
- }
18815
- sql2.raw = raw2;
18816
- function join18(chunks, separator) {
18817
- const result = [];
18818
- for (const [i, chunk] of chunks.entries()) {
18819
- if (i > 0 && separator !== undefined) {
18820
- result.push(separator);
18821
- }
18822
- result.push(chunk);
18823
- }
18824
- return new SQL(result);
18825
- }
18826
- sql2.join = join18;
18827
- function identifier(value) {
18828
- return new Name(value);
18829
- }
18830
- sql2.identifier = identifier;
18831
- function placeholder2(name2) {
18832
- return new Placeholder(name2);
18833
- }
18834
- sql2.placeholder = placeholder2;
18835
- function param2(value, encoder) {
18836
- return new Param(value, encoder);
18837
- }
18838
- sql2.param = param2;
18839
- })(sql || (sql = {}));
18840
- ((SQL2) => {
18841
-
18842
- class Aliased {
18843
- constructor(sql2, fieldAlias) {
18844
- this.sql = sql2;
18845
- this.fieldAlias = fieldAlias;
18846
- }
18847
- static [entityKind] = "SQL.Aliased";
18848
- isSelectionField = false;
18849
- getSQL() {
18850
- return this.sql;
18851
- }
18852
- clone() {
18853
- return new Aliased(this.sql, this.fieldAlias);
18854
- }
18855
- }
18856
- SQL2.Aliased = Aliased;
18857
- })(SQL || (SQL = {}));
18858
-
18859
- class Placeholder {
18860
- constructor(name2) {
18861
- this.name = name2;
18862
- }
18863
- static [entityKind] = "Placeholder";
18864
- getSQL() {
18865
- return new SQL([this]);
18866
- }
18867
- }
18868
- var IsDrizzleView = Symbol.for("drizzle:IsDrizzleView");
18869
-
18870
- class View {
18871
- static [entityKind] = "View";
18872
- [ViewBaseConfig];
18873
- [IsDrizzleView] = true;
18874
- constructor({ name: name2, schema, selectedFields, query }) {
18875
- this[ViewBaseConfig] = {
18876
- name: name2,
18877
- originalName: name2,
18878
- schema,
18879
- selectedFields,
18880
- query,
18881
- isExisting: !query,
18882
- isAlias: false
18883
- };
18884
- }
18885
- getSQL() {
18886
- return new SQL([this]);
18887
- }
18888
- }
18889
- Column.prototype.getSQL = function() {
18890
- return new SQL([this]);
18891
- };
18892
- Table.prototype.getSQL = function() {
18893
- return new SQL([this]);
18894
- };
18895
- Subquery.prototype.getSQL = function() {
18896
- return new SQL([this]);
18897
- };
18898
-
18899
- // node_modules/.bun/drizzle-orm@0.45.2+29ab9a45addfc34e/node_modules/drizzle-orm/utils.js
18900
- function getColumnNameAndConfig(a, b) {
18901
- return {
18902
- name: typeof a === "string" && a.length > 0 ? a : "",
18903
- config: typeof a === "object" ? a : b
18904
- };
18905
- }
18906
- var textDecoder = typeof TextDecoder === "undefined" ? null : new TextDecoder;
18907
-
18908
- // node_modules/.bun/drizzle-orm@0.45.2+29ab9a45addfc34e/node_modules/drizzle-orm/sqlite-core/foreign-keys.js
18909
- class ForeignKeyBuilder {
18910
- static [entityKind] = "SQLiteForeignKeyBuilder";
18911
- reference;
18912
- _onUpdate;
18913
- _onDelete;
18914
- constructor(config, actions) {
18915
- this.reference = () => {
18916
- const { name, columns, foreignColumns } = config();
18917
- return { name, columns, foreignTable: foreignColumns[0].table, foreignColumns };
18918
- };
18919
- if (actions) {
18920
- this._onUpdate = actions.onUpdate;
18921
- this._onDelete = actions.onDelete;
18922
- }
18923
- }
18924
- onUpdate(action) {
18925
- this._onUpdate = action;
18926
- return this;
18927
- }
18928
- onDelete(action) {
18929
- this._onDelete = action;
18930
- return this;
18931
- }
18932
- build(table) {
18933
- return new ForeignKey(table, this);
18934
- }
18935
- }
18936
-
18937
- class ForeignKey {
18938
- constructor(table, builder) {
18939
- this.table = table;
18940
- this.reference = builder.reference;
18941
- this.onUpdate = builder._onUpdate;
18942
- this.onDelete = builder._onDelete;
18943
- }
18944
- static [entityKind] = "SQLiteForeignKey";
18945
- reference;
18946
- onUpdate;
18947
- onDelete;
18948
- getName() {
18949
- const { name, columns, foreignColumns } = this.reference();
18950
- const columnNames = columns.map((column) => column.name);
18951
- const foreignColumnNames = foreignColumns.map((column) => column.name);
18952
- const chunks = [
18953
- this.table[TableName],
18954
- ...columnNames,
18955
- foreignColumns[0].table[TableName],
18956
- ...foreignColumnNames
18957
- ];
18958
- return name ?? `${chunks.join("_")}_fk`;
18959
- }
18960
- }
18961
-
18962
- // node_modules/.bun/drizzle-orm@0.45.2+29ab9a45addfc34e/node_modules/drizzle-orm/sqlite-core/unique-constraint.js
18963
- function uniqueKeyName2(table, columns) {
18964
- return `${table[TableName]}_${columns.join("_")}_unique`;
18965
- }
18966
-
18967
- // node_modules/.bun/drizzle-orm@0.45.2+29ab9a45addfc34e/node_modules/drizzle-orm/sqlite-core/columns/common.js
18968
- class SQLiteColumnBuilder extends ColumnBuilder {
18969
- static [entityKind] = "SQLiteColumnBuilder";
18970
- foreignKeyConfigs = [];
18971
- references(ref, actions = {}) {
18972
- this.foreignKeyConfigs.push({ ref, actions });
18973
- return this;
18974
- }
18975
- unique(name) {
18976
- this.config.isUnique = true;
18977
- this.config.uniqueName = name;
18978
- return this;
18979
- }
18980
- generatedAlwaysAs(as, config) {
18981
- this.config.generated = {
18982
- as,
18983
- type: "always",
18984
- mode: config?.mode ?? "virtual"
18985
- };
18986
- return this;
18987
- }
18988
- buildForeignKeys(column, table) {
18989
- return this.foreignKeyConfigs.map(({ ref, actions }) => {
18990
- return ((ref2, actions2) => {
18991
- const builder = new ForeignKeyBuilder(() => {
18992
- const foreignColumn = ref2();
18993
- return { columns: [column], foreignColumns: [foreignColumn] };
18994
- });
18995
- if (actions2.onUpdate) {
18996
- builder.onUpdate(actions2.onUpdate);
18997
- }
18998
- if (actions2.onDelete) {
18999
- builder.onDelete(actions2.onDelete);
19000
- }
19001
- return builder.build(table);
19002
- })(ref, actions);
19003
- });
19004
- }
19005
- }
19006
-
19007
- class SQLiteColumn extends Column {
19008
- constructor(table, config) {
19009
- if (!config.uniqueName) {
19010
- config.uniqueName = uniqueKeyName2(table, [config.name]);
19011
- }
19012
- super(table, config);
19013
- this.table = table;
19014
- }
19015
- static [entityKind] = "SQLiteColumn";
19016
- }
19017
-
19018
- // node_modules/.bun/drizzle-orm@0.45.2+29ab9a45addfc34e/node_modules/drizzle-orm/sqlite-core/columns/blob.js
19019
- class SQLiteBigIntBuilder extends SQLiteColumnBuilder {
19020
- static [entityKind] = "SQLiteBigIntBuilder";
19021
- constructor(name) {
19022
- super(name, "bigint", "SQLiteBigInt");
19023
- }
19024
- build(table) {
19025
- return new SQLiteBigInt(table, this.config);
19026
- }
19027
- }
19028
-
19029
- class SQLiteBigInt extends SQLiteColumn {
19030
- static [entityKind] = "SQLiteBigInt";
19031
- getSQLType() {
19032
- return "blob";
19033
- }
19034
- mapFromDriverValue(value) {
19035
- if (typeof Buffer !== "undefined" && Buffer.from) {
19036
- const buf = Buffer.isBuffer(value) ? value : value instanceof ArrayBuffer ? Buffer.from(value) : value.buffer ? Buffer.from(value.buffer, value.byteOffset, value.byteLength) : Buffer.from(value);
19037
- return BigInt(buf.toString("utf8"));
19038
- }
19039
- return BigInt(textDecoder.decode(value));
19040
- }
19041
- mapToDriverValue(value) {
19042
- return Buffer.from(value.toString());
19043
- }
19044
- }
19045
-
19046
- class SQLiteBlobJsonBuilder extends SQLiteColumnBuilder {
19047
- static [entityKind] = "SQLiteBlobJsonBuilder";
19048
- constructor(name) {
19049
- super(name, "json", "SQLiteBlobJson");
19050
- }
19051
- build(table) {
19052
- return new SQLiteBlobJson(table, this.config);
19053
- }
19054
- }
19055
-
19056
- class SQLiteBlobJson extends SQLiteColumn {
19057
- static [entityKind] = "SQLiteBlobJson";
19058
- getSQLType() {
19059
- return "blob";
19060
- }
19061
- mapFromDriverValue(value) {
19062
- if (typeof Buffer !== "undefined" && Buffer.from) {
19063
- const buf = Buffer.isBuffer(value) ? value : value instanceof ArrayBuffer ? Buffer.from(value) : value.buffer ? Buffer.from(value.buffer, value.byteOffset, value.byteLength) : Buffer.from(value);
19064
- return JSON.parse(buf.toString("utf8"));
19065
- }
19066
- return JSON.parse(textDecoder.decode(value));
19067
- }
19068
- mapToDriverValue(value) {
19069
- return Buffer.from(JSON.stringify(value));
19070
- }
19071
- }
19072
-
19073
- class SQLiteBlobBufferBuilder extends SQLiteColumnBuilder {
19074
- static [entityKind] = "SQLiteBlobBufferBuilder";
19075
- constructor(name) {
19076
- super(name, "buffer", "SQLiteBlobBuffer");
19077
- }
19078
- build(table) {
19079
- return new SQLiteBlobBuffer(table, this.config);
19080
- }
19081
- }
19082
-
19083
- class SQLiteBlobBuffer extends SQLiteColumn {
19084
- static [entityKind] = "SQLiteBlobBuffer";
19085
- mapFromDriverValue(value) {
19086
- if (Buffer.isBuffer(value)) {
19087
- return value;
19088
- }
19089
- return Buffer.from(value);
19090
- }
19091
- getSQLType() {
19092
- return "blob";
19093
- }
19094
- }
19095
- function blob(a, b) {
19096
- const { name, config } = getColumnNameAndConfig(a, b);
19097
- if (config?.mode === "json") {
19098
- return new SQLiteBlobJsonBuilder(name);
19099
- }
19100
- if (config?.mode === "bigint") {
19101
- return new SQLiteBigIntBuilder(name);
19102
- }
19103
- return new SQLiteBlobBufferBuilder(name);
19104
- }
19105
-
19106
- // node_modules/.bun/drizzle-orm@0.45.2+29ab9a45addfc34e/node_modules/drizzle-orm/sqlite-core/columns/custom.js
19107
- class SQLiteCustomColumnBuilder extends SQLiteColumnBuilder {
19108
- static [entityKind] = "SQLiteCustomColumnBuilder";
19109
- constructor(name, fieldConfig, customTypeParams) {
19110
- super(name, "custom", "SQLiteCustomColumn");
19111
- this.config.fieldConfig = fieldConfig;
19112
- this.config.customTypeParams = customTypeParams;
19113
- }
19114
- build(table) {
19115
- return new SQLiteCustomColumn(table, this.config);
19116
- }
19117
- }
19118
-
19119
- class SQLiteCustomColumn extends SQLiteColumn {
19120
- static [entityKind] = "SQLiteCustomColumn";
19121
- sqlName;
19122
- mapTo;
19123
- mapFrom;
19124
- constructor(table, config) {
19125
- super(table, config);
19126
- this.sqlName = config.customTypeParams.dataType(config.fieldConfig);
19127
- this.mapTo = config.customTypeParams.toDriver;
19128
- this.mapFrom = config.customTypeParams.fromDriver;
19129
- }
19130
- getSQLType() {
19131
- return this.sqlName;
19132
- }
19133
- mapFromDriverValue(value) {
19134
- return typeof this.mapFrom === "function" ? this.mapFrom(value) : value;
19135
- }
19136
- mapToDriverValue(value) {
19137
- return typeof this.mapTo === "function" ? this.mapTo(value) : value;
19138
- }
19139
- }
19140
- function customType(customTypeParams) {
19141
- return (a, b) => {
19142
- const { name, config } = getColumnNameAndConfig(a, b);
19143
- return new SQLiteCustomColumnBuilder(name, config, customTypeParams);
19144
- };
19145
- }
19146
-
19147
- // node_modules/.bun/drizzle-orm@0.45.2+29ab9a45addfc34e/node_modules/drizzle-orm/sqlite-core/columns/integer.js
19148
- class SQLiteBaseIntegerBuilder extends SQLiteColumnBuilder {
19149
- static [entityKind] = "SQLiteBaseIntegerBuilder";
19150
- constructor(name, dataType, columnType) {
19151
- super(name, dataType, columnType);
19152
- this.config.autoIncrement = false;
19153
- }
19154
- primaryKey(config) {
19155
- if (config?.autoIncrement) {
19156
- this.config.autoIncrement = true;
19157
- }
19158
- this.config.hasDefault = true;
19159
- return super.primaryKey();
19160
- }
19161
- }
19162
-
19163
- class SQLiteBaseInteger extends SQLiteColumn {
19164
- static [entityKind] = "SQLiteBaseInteger";
19165
- autoIncrement = this.config.autoIncrement;
19166
- getSQLType() {
19167
- return "integer";
19168
- }
19169
- }
19170
-
19171
- class SQLiteIntegerBuilder extends SQLiteBaseIntegerBuilder {
19172
- static [entityKind] = "SQLiteIntegerBuilder";
19173
- constructor(name) {
19174
- super(name, "number", "SQLiteInteger");
19175
- }
19176
- build(table) {
19177
- return new SQLiteInteger(table, this.config);
19178
- }
19179
- }
19180
-
19181
- class SQLiteInteger extends SQLiteBaseInteger {
19182
- static [entityKind] = "SQLiteInteger";
19183
- }
19184
-
19185
- class SQLiteTimestampBuilder extends SQLiteBaseIntegerBuilder {
19186
- static [entityKind] = "SQLiteTimestampBuilder";
19187
- constructor(name, mode) {
19188
- super(name, "date", "SQLiteTimestamp");
19189
- this.config.mode = mode;
19190
- }
19191
- defaultNow() {
19192
- return this.default(sql`(cast((julianday('now') - 2440587.5)*86400000 as integer))`);
19193
- }
19194
- build(table) {
19195
- return new SQLiteTimestamp(table, this.config);
19196
- }
19197
- }
19198
-
19199
- class SQLiteTimestamp extends SQLiteBaseInteger {
19200
- static [entityKind] = "SQLiteTimestamp";
19201
- mode = this.config.mode;
19202
- mapFromDriverValue(value) {
19203
- if (this.config.mode === "timestamp") {
19204
- return new Date(value * 1000);
19205
- }
19206
- return new Date(value);
19207
- }
19208
- mapToDriverValue(value) {
19209
- const unix = value.getTime();
19210
- if (this.config.mode === "timestamp") {
19211
- return Math.floor(unix / 1000);
19212
- }
19213
- return unix;
19214
- }
19215
- }
19216
-
19217
- class SQLiteBooleanBuilder extends SQLiteBaseIntegerBuilder {
19218
- static [entityKind] = "SQLiteBooleanBuilder";
19219
- constructor(name, mode) {
19220
- super(name, "boolean", "SQLiteBoolean");
19221
- this.config.mode = mode;
19222
- }
19223
- build(table) {
19224
- return new SQLiteBoolean(table, this.config);
19225
- }
19226
- }
19227
-
19228
- class SQLiteBoolean extends SQLiteBaseInteger {
19229
- static [entityKind] = "SQLiteBoolean";
19230
- mode = this.config.mode;
19231
- mapFromDriverValue(value) {
19232
- return Number(value) === 1;
19233
- }
19234
- mapToDriverValue(value) {
19235
- return value ? 1 : 0;
19236
- }
19237
- }
19238
- function integer(a, b) {
19239
- const { name, config } = getColumnNameAndConfig(a, b);
19240
- if (config?.mode === "timestamp" || config?.mode === "timestamp_ms") {
19241
- return new SQLiteTimestampBuilder(name, config.mode);
19242
- }
19243
- if (config?.mode === "boolean") {
19244
- return new SQLiteBooleanBuilder(name, config.mode);
19245
- }
19246
- return new SQLiteIntegerBuilder(name);
19247
- }
19248
-
19249
- // node_modules/.bun/drizzle-orm@0.45.2+29ab9a45addfc34e/node_modules/drizzle-orm/sqlite-core/columns/numeric.js
19250
- class SQLiteNumericBuilder extends SQLiteColumnBuilder {
19251
- static [entityKind] = "SQLiteNumericBuilder";
19252
- constructor(name) {
19253
- super(name, "string", "SQLiteNumeric");
19254
- }
19255
- build(table) {
19256
- return new SQLiteNumeric(table, this.config);
19257
- }
19258
- }
19259
-
19260
- class SQLiteNumeric extends SQLiteColumn {
19261
- static [entityKind] = "SQLiteNumeric";
19262
- mapFromDriverValue(value) {
19263
- if (typeof value === "string")
19264
- return value;
19265
- return String(value);
19266
- }
19267
- getSQLType() {
19268
- return "numeric";
19269
- }
19270
- }
19271
-
19272
- class SQLiteNumericNumberBuilder extends SQLiteColumnBuilder {
19273
- static [entityKind] = "SQLiteNumericNumberBuilder";
19274
- constructor(name) {
19275
- super(name, "number", "SQLiteNumericNumber");
19276
- }
19277
- build(table) {
19278
- return new SQLiteNumericNumber(table, this.config);
19279
- }
19280
- }
19281
-
19282
- class SQLiteNumericNumber extends SQLiteColumn {
19283
- static [entityKind] = "SQLiteNumericNumber";
19284
- mapFromDriverValue(value) {
19285
- if (typeof value === "number")
19286
- return value;
19287
- return Number(value);
19288
- }
19289
- mapToDriverValue = String;
19290
- getSQLType() {
19291
- return "numeric";
19292
- }
19293
- }
19294
-
19295
- class SQLiteNumericBigIntBuilder extends SQLiteColumnBuilder {
19296
- static [entityKind] = "SQLiteNumericBigIntBuilder";
19297
- constructor(name) {
19298
- super(name, "bigint", "SQLiteNumericBigInt");
19299
- }
19300
- build(table) {
19301
- return new SQLiteNumericBigInt(table, this.config);
19302
- }
19303
- }
19304
-
19305
- class SQLiteNumericBigInt extends SQLiteColumn {
19306
- static [entityKind] = "SQLiteNumericBigInt";
19307
- mapFromDriverValue = BigInt;
19308
- mapToDriverValue = String;
19309
- getSQLType() {
19310
- return "numeric";
19311
- }
19312
- }
19313
- function numeric(a, b) {
19314
- const { name, config } = getColumnNameAndConfig(a, b);
19315
- const mode = config?.mode;
19316
- return mode === "number" ? new SQLiteNumericNumberBuilder(name) : mode === "bigint" ? new SQLiteNumericBigIntBuilder(name) : new SQLiteNumericBuilder(name);
19317
- }
19318
-
19319
- // node_modules/.bun/drizzle-orm@0.45.2+29ab9a45addfc34e/node_modules/drizzle-orm/sqlite-core/columns/real.js
19320
- class SQLiteRealBuilder extends SQLiteColumnBuilder {
19321
- static [entityKind] = "SQLiteRealBuilder";
19322
- constructor(name) {
19323
- super(name, "number", "SQLiteReal");
19324
- }
19325
- build(table) {
19326
- return new SQLiteReal(table, this.config);
19327
- }
19328
- }
19329
-
19330
- class SQLiteReal extends SQLiteColumn {
19331
- static [entityKind] = "SQLiteReal";
19332
- getSQLType() {
19333
- return "real";
19334
- }
19335
- }
19336
- function real(name) {
19337
- return new SQLiteRealBuilder(name ?? "");
19338
- }
19339
-
19340
- // node_modules/.bun/drizzle-orm@0.45.2+29ab9a45addfc34e/node_modules/drizzle-orm/sqlite-core/columns/text.js
19341
- class SQLiteTextBuilder extends SQLiteColumnBuilder {
19342
- static [entityKind] = "SQLiteTextBuilder";
19343
- constructor(name, config) {
19344
- super(name, "string", "SQLiteText");
19345
- this.config.enumValues = config.enum;
19346
- this.config.length = config.length;
19347
- }
19348
- build(table) {
19349
- return new SQLiteText(table, this.config);
19350
- }
19351
- }
19352
-
19353
- class SQLiteText extends SQLiteColumn {
19354
- static [entityKind] = "SQLiteText";
19355
- enumValues = this.config.enumValues;
19356
- length = this.config.length;
19357
- constructor(table, config) {
19358
- super(table, config);
19359
- }
19360
- getSQLType() {
19361
- return `text${this.config.length ? `(${this.config.length})` : ""}`;
19362
- }
19363
- }
19364
-
19365
- class SQLiteTextJsonBuilder extends SQLiteColumnBuilder {
19366
- static [entityKind] = "SQLiteTextJsonBuilder";
19367
- constructor(name) {
19368
- super(name, "json", "SQLiteTextJson");
19369
- }
19370
- build(table) {
19371
- return new SQLiteTextJson(table, this.config);
19372
- }
19373
- }
19374
-
19375
- class SQLiteTextJson extends SQLiteColumn {
19376
- static [entityKind] = "SQLiteTextJson";
19377
- getSQLType() {
19378
- return "text";
19379
- }
19380
- mapFromDriverValue(value) {
19381
- return JSON.parse(value);
19382
- }
19383
- mapToDriverValue(value) {
19384
- return JSON.stringify(value);
19385
- }
19386
- }
19387
- function text(a, b = {}) {
19388
- const { name, config } = getColumnNameAndConfig(a, b);
19389
- if (config.mode === "json") {
19390
- return new SQLiteTextJsonBuilder(name);
19391
- }
19392
- return new SQLiteTextBuilder(name, config);
19393
- }
19394
-
19395
- // node_modules/.bun/drizzle-orm@0.45.2+29ab9a45addfc34e/node_modules/drizzle-orm/sqlite-core/columns/all.js
19396
- function getSQLiteColumnBuilders() {
19397
- return {
19398
- blob,
19399
- customType,
19400
- integer,
19401
- numeric,
19402
- real,
19403
- text
19404
- };
19405
- }
19406
-
19407
- // node_modules/.bun/drizzle-orm@0.45.2+29ab9a45addfc34e/node_modules/drizzle-orm/sqlite-core/table.js
19408
- var InlineForeignKeys = Symbol.for("drizzle:SQLiteInlineForeignKeys");
19409
-
19410
- class SQLiteTable extends Table {
19411
- static [entityKind] = "SQLiteTable";
19412
- static Symbol = Object.assign({}, Table.Symbol, {
19413
- InlineForeignKeys
19414
- });
19415
- [Table.Symbol.Columns];
19416
- [InlineForeignKeys] = [];
19417
- [Table.Symbol.ExtraConfigBuilder] = undefined;
19418
- }
19419
- function sqliteTableBase(name, columns, extraConfig, schema, baseName = name) {
19420
- const rawTable = new SQLiteTable(name, schema, baseName);
19421
- const parsedColumns = typeof columns === "function" ? columns(getSQLiteColumnBuilders()) : columns;
19422
- const builtColumns = Object.fromEntries(Object.entries(parsedColumns).map(([name2, colBuilderBase]) => {
19423
- const colBuilder = colBuilderBase;
19424
- colBuilder.setName(name2);
19425
- const column = colBuilder.build(rawTable);
19426
- rawTable[InlineForeignKeys].push(...colBuilder.buildForeignKeys(column, rawTable));
19427
- return [name2, column];
19428
- }));
19429
- const table = Object.assign(rawTable, builtColumns);
19430
- table[Table.Symbol.Columns] = builtColumns;
19431
- table[Table.Symbol.ExtraConfigColumns] = builtColumns;
19432
- if (extraConfig) {
19433
- table[SQLiteTable.Symbol.ExtraConfigBuilder] = extraConfig;
19434
- }
19435
- return table;
19436
- }
19437
- var sqliteTable = (name, columns, extraConfig) => {
19438
- return sqliteTableBase(name, columns, extraConfig);
19439
- };
19440
-
19441
- // node_modules/.bun/drizzle-orm@0.45.2+29ab9a45addfc34e/node_modules/drizzle-orm/sqlite-core/indexes.js
19442
- class IndexBuilderOn {
19443
- constructor(name, unique2) {
19444
- this.name = name;
19445
- this.unique = unique2;
19446
- }
19447
- static [entityKind] = "SQLiteIndexBuilderOn";
19448
- on(...columns) {
19449
- return new IndexBuilder(this.name, columns, this.unique);
19450
- }
19451
- }
19452
-
19453
- class IndexBuilder {
19454
- static [entityKind] = "SQLiteIndexBuilder";
19455
- config;
19456
- constructor(name, columns, unique2) {
19457
- this.config = {
19458
- name,
19459
- columns,
19460
- unique: unique2,
19461
- where: undefined
19462
- };
19463
- }
19464
- where(condition) {
19465
- this.config.where = condition;
19466
- return this;
19467
- }
19468
- build(table) {
19469
- return new Index(this.config, table);
19470
- }
19471
- }
19472
-
19473
- class Index {
19474
- static [entityKind] = "SQLiteIndex";
19475
- config;
19476
- constructor(config, table) {
19477
- this.config = { ...config, table };
19478
- }
19479
- }
19480
- function index(name) {
19481
- return new IndexBuilderOn(name, false);
19482
- }
19483
-
19484
- // packages/runtime/src/drizzle-schema.ts
19485
- var deliveriesTable = sqliteTable("deliveries", {
19486
- id: text("id").primaryKey(),
19487
- messageId: text("message_id"),
19488
- invocationId: text("invocation_id"),
19489
- targetId: text("target_id").notNull(),
19490
- targetNodeId: text("target_node_id"),
19491
- targetKind: text("target_kind").$type().notNull(),
19492
- transport: text("transport").$type().notNull(),
19493
- reason: text("reason").$type().notNull(),
19494
- policy: text("policy").$type().notNull(),
19495
- status: text("status").$type().notNull(),
19496
- bindingId: text("binding_id"),
19497
- leaseOwner: text("lease_owner"),
19498
- leaseExpiresAt: integer("lease_expires_at"),
19499
- metadataJson: text("metadata_json"),
19500
- createdAt: integer("created_at").notNull().default(sql`(unixepoch())`)
19501
- }, (table) => [
19502
- index("idx_deliveries_status_transport").on(table.status, table.transport)
19503
- ]);
19504
- var deliveryAttemptsTable = sqliteTable("delivery_attempts", {
19505
- id: text("id").primaryKey(),
19506
- deliveryId: text("delivery_id").notNull(),
19507
- attempt: integer("attempt").notNull(),
19508
- status: text("status").$type().notNull(),
19509
- error: text("error"),
19510
- externalRef: text("external_ref"),
19511
- metadataJson: text("metadata_json"),
19512
- createdAt: integer("created_at").notNull()
19513
- });
19514
- // packages/runtime/src/broker.ts
19515
- init_dist2();
19516
- function createRuntimeId(prefix) {
19517
- return `${prefix}-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}`;
19518
- }
19519
- function toTargetKind(actor) {
19520
- if (!actor)
19521
- return "participant";
19522
- if (actor.kind === "agent")
19523
- return "agent";
19524
- if (actor.kind === "device")
19525
- return "device";
19526
- if (actor.kind === "bridge")
19527
- return "bridge";
19528
- return "participant";
19529
- }
19530
- function defaultTransportForActor(actor) {
19531
- if (!actor)
19532
- return "local_socket";
19533
- switch (actor.kind) {
19534
- case "bridge":
19535
- return "webhook";
19536
- case "device":
19537
- return "local_socket";
19538
- case "agent":
19539
- return "local_socket";
19540
- default:
19541
- return "local_socket";
19542
- }
19543
- }
19544
- function endpointTransportRank(transport) {
19545
- switch (transport) {
19546
- case "codex_app_server":
19547
- return 0;
19548
- case "claude_stream_json":
19549
- return 1;
19550
- case "tmux":
19551
- return 2;
19552
- case "local_socket":
19553
- return 3;
19554
- default:
19555
- return 4;
19556
- }
19557
- }
19558
- function shouldBridgeMessageToBinding(binding, message) {
19559
- if (binding.platform !== "telegram") {
19560
- return true;
19561
- }
19562
- const source = typeof message.metadata?.source === "string" ? String(message.metadata.source) : "";
19563
- if (source === "telegram") {
19564
- return false;
19565
- }
19566
- const outboundMode = typeof binding.metadata?.outboundMode === "string" ? String(binding.metadata.outboundMode) : "operator_only";
19567
- const operatorId = typeof binding.metadata?.operatorId === "string" ? String(binding.metadata.operatorId) : "operator";
19568
- const allowedActorIds = Array.isArray(binding.metadata?.allowedActorIds) ? binding.metadata.allowedActorIds.map((entry) => String(entry).trim()).filter(Boolean) : [];
19569
- if (outboundMode === "all") {
19570
- return true;
19571
- }
19572
- if (outboundMode === "allowlist") {
19573
- return allowedActorIds.includes(message.actorId);
19574
- }
19575
- return message.actorId === operatorId;
19576
- }
19577
- function resolveBindingRoutes(bindings, message) {
19578
- return bindings.filter((binding) => shouldBridgeMessageToBinding(binding, message)).map((binding) => ({
19579
- targetId: binding.id,
19580
- targetKind: "bridge",
19581
- transport: binding.platform === "telegram" ? "telegram" : binding.platform === "discord" ? "discord" : "webhook",
19582
- bindingId: binding.id
19583
- }));
19584
- }
19585
- function preferredEndpoint(endpoints) {
19586
- let preferred;
19587
- let preferredRank = Number.POSITIVE_INFINITY;
19588
- for (const endpoint of endpoints) {
19589
- const rank = endpointTransportRank(endpoint.transport);
19590
- if (!preferred || rank < preferredRank) {
19591
- preferred = endpoint;
19592
- preferredRank = rank;
19593
- }
19594
- }
19595
- return preferred;
19596
- }
19597
-
19598
- class InMemoryControlRuntime {
19599
- registry;
19600
- listeners = new Set;
19601
- eventBuffer = [];
19602
- localNodeId;
19603
- endpointIdsByAgentId = new Map;
19604
- bindingIdsByConversationId = new Map;
19605
- flightIdByInvocationId = new Map;
19606
- constructor(initial = {}, options = {}) {
19607
- this.registry = createRuntimeRegistrySnapshot(initial);
19608
- this.localNodeId = options.localNodeId;
19609
- this.rebuildIndexes();
19610
- }
19611
- snapshot() {
19612
- return createRuntimeRegistrySnapshot({
19613
- nodes: { ...this.registry.nodes },
19614
- actors: { ...this.registry.actors },
19615
- agents: { ...this.registry.agents },
19616
- endpoints: { ...this.registry.endpoints },
19617
- conversations: { ...this.registry.conversations },
19618
- bindings: { ...this.registry.bindings },
19619
- messages: { ...this.registry.messages },
19620
- flights: { ...this.registry.flights },
19621
- collaborationRecords: { ...this.registry.collaborationRecords }
19622
- });
19623
- }
19624
- peek() {
19625
- return this.registry;
19626
- }
19627
- node(nodeId) {
19628
- return this.registry.nodes[nodeId];
19629
- }
19630
- agent(agentId) {
19631
- return this.registry.agents[agentId];
19632
- }
19633
- conversation(conversationId) {
19634
- return this.registry.conversations[conversationId];
19635
- }
19636
- message(messageId) {
19637
- return this.registry.messages[messageId];
19638
- }
19639
- collaborationRecord(recordId) {
19640
- return this.registry.collaborationRecords[recordId];
19641
- }
19642
- flightForInvocation(invocationId) {
19643
- const flightId = this.flightIdByInvocationId.get(invocationId);
19644
- return flightId ? this.registry.flights[flightId] : undefined;
19645
- }
19646
- bindingsForConversation(conversationId) {
19647
- const bindingIds = this.bindingIdsByConversationId.get(conversationId);
19648
- if (!bindingIds) {
19649
- return [];
19650
- }
19651
- const bindings = [];
19652
- for (const bindingId of bindingIds) {
19653
- const binding = this.registry.bindings[bindingId];
19654
- if (binding) {
19655
- bindings.push(binding);
19656
- }
19657
- }
19658
- return bindings;
19659
- }
19660
- endpointsForAgent(agentId, options = {}) {
19661
- const endpointIds = this.endpointIdsByAgentId.get(agentId);
19662
- if (!endpointIds) {
19663
- return [];
19664
- }
19665
- const endpoints = [];
19666
- for (const endpointId of endpointIds) {
19667
- const endpoint = this.registry.endpoints[endpointId];
19668
- if (!endpoint)
19669
- continue;
19670
- if (!options.includeOffline && endpoint.state === "offline")
19671
- continue;
19672
- if (options.nodeId && endpoint.nodeId !== options.nodeId)
19673
- continue;
19674
- if (options.harness && endpoint.harness !== options.harness)
19675
- continue;
19676
- endpoints.push(endpoint);
19677
- }
19678
- return endpoints;
19679
- }
19680
- recentEvents(limit = 100) {
19681
- return this.eventBuffer.slice(-limit);
19682
- }
19683
- subscribe(listener) {
19684
- this.listeners.add(listener);
19685
- return () => {
19686
- this.listeners.delete(listener);
19687
- };
19688
- }
19689
- async dispatch(command) {
19690
- switch (command.kind) {
19691
- case "node.upsert":
19692
- await this.upsertNode(command.node);
19693
- return;
19694
- case "actor.upsert":
19695
- await this.upsertActor(command.actor);
19696
- return;
19697
- case "agent.upsert":
19698
- await this.upsertAgent(command.agent);
19699
- return;
19700
- case "agent.endpoint.upsert":
19701
- await this.upsertEndpoint(command.endpoint);
19702
- return;
19703
- case "conversation.upsert":
19704
- await this.upsertConversation(command.conversation);
19705
- return;
19706
- case "binding.upsert":
19707
- await this.upsertBinding(command.binding);
19708
- return;
19709
- case "collaboration.upsert":
19710
- await this.upsertCollaboration(command.record);
19711
- return;
19712
- case "collaboration.event.append":
19713
- await this.appendCollaborationEvent(command.event);
19714
- return;
19715
- case "conversation.post":
19716
- await this.postMessage(command.message);
19717
- return;
19718
- case "agent.invoke":
19719
- await this.invokeAgent(command.invocation);
19720
- return;
19721
- case "agent.ensure_awake":
19722
- this.emit({
19723
- id: createRuntimeId("evt"),
19724
- kind: "flight.updated",
19725
- ts: Date.now(),
19726
- actorId: command.requesterId,
19727
- nodeId: this.localNodeId,
19728
- payload: {
19729
- flight: {
19730
- id: createRuntimeId("flt"),
19731
- invocationId: command.agentId,
19732
- requesterId: command.requesterId,
19733
- targetAgentId: command.agentId,
19734
- state: "waking",
19735
- summary: command.reason
19736
- }
19737
- }
19738
- });
19739
- return;
19740
- case "stream.subscribe":
19741
- return;
19742
- default: {
19743
- const exhaustive = command;
19744
- return exhaustive;
19745
- }
19746
- }
19747
- }
19748
- async upsertNode(node) {
19749
- this.registry.nodes[node.id] = node;
19750
- this.emit({
19751
- id: createRuntimeId("evt"),
19752
- kind: "node.upserted",
19753
- ts: Date.now(),
19754
- actorId: node.id,
19755
- nodeId: node.id,
19756
- payload: { node }
19757
- });
19758
- }
19759
- async upsertActor(actor) {
19760
- this.registry.actors[actor.id] = {
19761
- id: actor.id,
19762
- kind: actor.kind,
19763
- displayName: actor.displayName,
19764
- handle: actor.handle,
19765
- labels: actor.labels,
19766
- metadata: actor.metadata
19767
- };
19768
- this.emit({
19769
- id: createRuntimeId("evt"),
19770
- kind: "actor.registered",
19771
- ts: Date.now(),
19772
- actorId: actor.id,
19773
- nodeId: this.localNodeId,
19774
- payload: { actor }
19775
- });
19776
- }
19777
- async upsertAgent(agent) {
19778
- if (!this.registry.actors[agent.id]) {
19779
- this.registry.actors[agent.id] = {
19780
- id: agent.id,
19781
- kind: agent.kind,
19782
- displayName: agent.displayName,
19783
- handle: agent.handle,
19784
- labels: agent.labels,
19785
- metadata: agent.metadata
19786
- };
19787
- }
19788
- this.registry.agents[agent.id] = agent;
19789
- this.emit({
19790
- id: createRuntimeId("evt"),
19791
- kind: "agent.registered",
19792
- ts: Date.now(),
19793
- actorId: agent.id,
19794
- nodeId: agent.authorityNodeId,
19795
- payload: { agent }
19796
- });
19797
- }
19798
- async upsertEndpoint(endpoint) {
19799
- const previous = this.registry.endpoints[endpoint.id];
19800
- if (previous) {
19801
- this.unindexEndpoint(previous);
19802
- }
19803
- this.registry.endpoints[endpoint.id] = endpoint;
19804
- this.indexEndpoint(endpoint);
19805
- this.emit({
19806
- id: createRuntimeId("evt"),
19807
- kind: "agent.endpoint.upserted",
19808
- ts: Date.now(),
19809
- actorId: endpoint.agentId,
19810
- nodeId: endpoint.nodeId,
19811
- payload: { endpoint }
19812
- });
19813
- }
19814
- async upsertConversation(conversation) {
19815
- this.registry.conversations[conversation.id] = conversation;
19816
- this.emit({
19817
- id: createRuntimeId("evt"),
19818
- kind: "conversation.upserted",
19819
- ts: Date.now(),
19820
- actorId: "system",
19821
- nodeId: conversation.authorityNodeId,
19822
- payload: { conversation }
19823
- });
19824
- }
19825
- async upsertBinding(binding) {
19826
- const previous = this.registry.bindings[binding.id];
19827
- if (previous) {
19828
- this.unindexBinding(previous);
19829
- }
19830
- this.registry.bindings[binding.id] = binding;
19831
- this.indexBinding(binding);
19832
- this.emit({
19833
- id: createRuntimeId("evt"),
19834
- kind: "binding.upserted",
19835
- ts: Date.now(),
19836
- actorId: "system",
19837
- nodeId: this.localNodeId,
19838
- payload: { binding }
19839
- });
19840
- }
19841
- async upsertCollaboration(record) {
19842
- assertValidCollaborationRecord(record);
19843
- this.registry.collaborationRecords[record.id] = record;
19844
- this.emit({
19845
- id: createRuntimeId("evt"),
19846
- kind: "collaboration.upserted",
19847
- ts: Date.now(),
19848
- actorId: record.createdById,
19849
- nodeId: this.localNodeId,
19850
- payload: { record }
19851
- });
19852
- }
19853
- async appendCollaborationEvent(event) {
19854
- const record = this.registry.collaborationRecords[event.recordId];
19855
- if (!record) {
19856
- throw new Error(`unknown collaboration record: ${event.recordId}`);
19857
- }
19858
- assertValidCollaborationEvent(event, record);
19859
- this.emit({
19860
- id: createRuntimeId("evt"),
19861
- kind: "collaboration.event.appended",
19862
- ts: Date.now(),
19863
- actorId: event.actorId,
19864
- nodeId: this.localNodeId,
19865
- payload: { event }
19866
- });
19867
- }
19868
- async upsertFlight(flight) {
19869
- const previous = this.registry.flights[flight.id];
19870
- if (previous && this.flightIdByInvocationId.get(previous.invocationId) === previous.id) {
19871
- this.flightIdByInvocationId.delete(previous.invocationId);
19872
- }
19873
- this.registry.flights[flight.id] = flight;
19874
- this.flightIdByInvocationId.set(flight.invocationId, flight.id);
19875
- this.emit({
19876
- id: createRuntimeId("evt"),
19877
- kind: "flight.updated",
19878
- ts: Date.now(),
19879
- actorId: flight.requesterId,
19880
- nodeId: this.localNodeId,
19881
- payload: { flight }
19882
- });
19883
- }
19884
- async postMessage(message, options = {}) {
19885
- const deliveries2 = this.planMessage(message, options);
19886
- await this.commitMessage(message, deliveries2);
19887
- return deliveries2;
19888
- }
19889
- planMessage(message, options = {}) {
19890
- const conversation = this.registry.conversations[message.conversationId];
19891
- if (!conversation) {
19892
- throw new Error(`unknown conversation: ${message.conversationId}`);
19893
- }
19894
- const bindingRoutes = resolveBindingRoutes(this.bindingsForConversation(conversation.id), message);
19895
- const plannedParticipantRoutes = this.resolveParticipantRoutes(conversation.participantIds);
19896
- const participantRoutes = options.localOnly ? plannedParticipantRoutes.filter((route) => !route.nodeId || route.nodeId === this.localNodeId) : plannedParticipantRoutes;
19897
- const deliveries2 = planMessageDeliveries({
19898
- localNodeId: this.localNodeId,
19899
- message,
19900
- conversation,
19901
- participantRoutes,
19902
- bindingRoutes: options.localOnly ? [] : bindingRoutes
19903
- });
19904
- return deliveries2;
19905
- }
19906
- async commitMessage(message, deliveries2) {
19907
- this.registry.messages[message.id] = message;
19908
- this.emit({
19909
- id: createRuntimeId("evt"),
19910
- kind: "message.posted",
19911
- ts: Date.now(),
19912
- actorId: message.actorId,
19913
- nodeId: message.originNodeId,
19914
- payload: { message }
19915
- });
19916
- for (const delivery of deliveries2) {
19917
- this.emit({
19918
- id: createRuntimeId("evt"),
19919
- kind: "delivery.planned",
19920
- ts: Date.now(),
19921
- actorId: message.actorId,
19922
- nodeId: message.originNodeId,
19923
- payload: { delivery }
19924
- });
19925
- }
19926
- }
19927
- async invokeAgent(invocation) {
19928
- const flight = this.planInvocation(invocation);
19929
- await this.commitInvocation(invocation, flight);
19930
- return flight;
19931
- }
19932
- planInvocation(invocation) {
19933
- const targetAgent = this.registry.agents[invocation.targetAgentId];
19934
- if (!targetAgent) {
19935
- throw new Error(`unknown agent: ${invocation.targetAgentId}`);
19936
- }
19937
- const targetEndpoints = this.endpointsForAgent(invocation.targetAgentId, {
19938
- nodeId: targetAgent.authorityNodeId,
19939
- harness: invocation.execution?.harness
19940
- });
19941
- const isLocalAuthority = !this.localNodeId || targetAgent.authorityNodeId === this.localNodeId;
19942
- const startedAt = Date.now();
19943
- let state = invocation.ensureAwake ? "waking" : "queued";
19944
- let summary;
19945
- let error;
19946
- let completedAt;
19947
- if (isLocalAuthority) {
19948
- if (targetEndpoints.length == 0) {
19949
- state = invocation.ensureAwake ? "waking" : "queued";
19950
- summary = invocation.ensureAwake ? invocation.execution?.harness ? `${targetAgent.displayName} waking on ${invocation.execution.harness}.` : `${targetAgent.displayName} waking.` : `Message stored for ${targetAgent.displayName}. Will deliver when online.`;
19951
- } else {
19952
- state = "queued";
19953
- summary = `${targetAgent.displayName} queued for local execution.`;
19954
- }
19955
- }
19956
- const flight = {
19957
- id: createRuntimeId("flt"),
19958
- invocationId: invocation.id,
19959
- requesterId: invocation.requesterId,
19960
- targetAgentId: invocation.targetAgentId,
19961
- state,
19962
- summary,
19963
- error,
19964
- startedAt,
19965
- completedAt,
19966
- metadata: invocation.metadata
19967
- };
19968
- return flight;
19969
- }
19970
- async commitInvocation(invocation, flight) {
19971
- const previous = this.registry.flights[flight.id];
19972
- if (previous && this.flightIdByInvocationId.get(previous.invocationId) === previous.id) {
19973
- this.flightIdByInvocationId.delete(previous.invocationId);
19974
- }
19975
- this.registry.flights[flight.id] = flight;
19976
- this.flightIdByInvocationId.set(flight.invocationId, flight.id);
19977
- const targetAgent = this.registry.agents[invocation.targetAgentId];
19978
- this.emit({
19979
- id: createRuntimeId("evt"),
19980
- kind: "invocation.requested",
19981
- ts: Date.now(),
19982
- actorId: invocation.requesterId,
19983
- nodeId: invocation.requesterNodeId,
19984
- payload: { invocation }
19985
- });
19986
- this.emit({
19987
- id: createRuntimeId("evt"),
19988
- kind: "flight.updated",
19989
- ts: Date.now(),
19990
- actorId: invocation.requesterId,
19991
- nodeId: targetAgent?.authorityNodeId,
19992
- payload: { flight }
19993
- });
19994
- }
19995
- rebuildIndexes() {
19996
- for (const endpoint of Object.values(this.registry.endpoints)) {
19997
- this.indexEndpoint(endpoint);
19998
- }
19999
- for (const binding of Object.values(this.registry.bindings)) {
20000
- this.indexBinding(binding);
20001
- }
20002
- for (const flight of Object.values(this.registry.flights)) {
20003
- this.flightIdByInvocationId.set(flight.invocationId, flight.id);
20004
- }
20005
- }
20006
- indexEndpoint(endpoint) {
20007
- this.addIndexedId(this.endpointIdsByAgentId, endpoint.agentId, endpoint.id);
20008
- }
20009
- unindexEndpoint(endpoint) {
20010
- this.removeIndexedId(this.endpointIdsByAgentId, endpoint.agentId, endpoint.id);
20011
- }
20012
- indexBinding(binding) {
20013
- this.addIndexedId(this.bindingIdsByConversationId, binding.conversationId, binding.id);
20014
- }
20015
- unindexBinding(binding) {
20016
- this.removeIndexedId(this.bindingIdsByConversationId, binding.conversationId, binding.id);
20017
- }
20018
- addIndexedId(index2, key, value) {
20019
- const ids = index2.get(key) ?? new Set;
20020
- ids.add(value);
20021
- index2.set(key, ids);
20022
- }
20023
- removeIndexedId(index2, key, value) {
20024
- const ids = index2.get(key);
20025
- if (!ids) {
20026
- return;
20027
- }
20028
- ids.delete(value);
20029
- if (ids.size === 0) {
20030
- index2.delete(key);
20031
- }
20032
- }
20033
- resolveParticipantRoutes(participantIds) {
20034
- const routes = [];
20035
- for (const participantId of participantIds) {
20036
- const actor = this.registry.actors[participantId];
20037
- const agent = this.registry.agents[participantId];
20038
- const targetIdentity = actor ?? agent;
20039
- const endpoints = this.endpointsForAgent(participantId);
20040
- const endpoint = preferredEndpoint(endpoints);
20041
- if (!endpoint) {
20042
- if (agent?.authorityNodeId && agent.authorityNodeId !== this.localNodeId) {
20043
- routes.push({
20044
- targetId: participantId,
20045
- nodeId: agent.authorityNodeId,
20046
- targetKind: toTargetKind(targetIdentity),
20047
- transport: defaultTransportForActor(targetIdentity),
20048
- speechEnabled: false
20049
- });
20050
- } else if (agent) {
20051
- routes.push({
20052
- targetId: participantId,
20053
- nodeId: agent.authorityNodeId ?? this.localNodeId,
20054
- targetKind: toTargetKind(targetIdentity),
20055
- transport: defaultTransportForActor(targetIdentity),
20056
- speechEnabled: false
20057
- });
20058
- }
20059
- continue;
20060
- }
20061
- routes.push({
20062
- targetId: participantId,
20063
- nodeId: endpoint.nodeId ?? agent?.authorityNodeId,
20064
- targetKind: toTargetKind(targetIdentity),
20065
- transport: endpoint.transport ?? defaultTransportForActor(targetIdentity),
20066
- speechEnabled: Boolean(actor?.kind === "device" || endpoints.some((candidate) => candidate.transport === "local_socket" || candidate.transport === "websocket"))
20067
- });
20068
- }
20069
- return routes;
20070
- }
20071
- emit(event) {
20072
- this.eventBuffer.push(event);
20073
- if (this.eventBuffer.length > 500) {
20074
- this.eventBuffer.shift();
20075
- }
20076
- for (const listener of this.listeners) {
20077
- listener(event);
20078
- }
20079
- }
20080
- }
20081
- // packages/runtime/src/tailscale.ts
20082
- import { readFile as readFile7 } from "fs/promises";
20083
- import { execFile } from "child_process";
20084
- import { promisify } from "util";
20085
- var execFileAsync = promisify(execFile);
20086
- function parseStatusJson(raw2) {
20087
- return JSON.parse(raw2);
20088
- }
20089
- function parsePeers(status) {
20090
- const peers = Object.entries(status.Peer ?? {});
20091
- return peers.map(([fallbackId, peer]) => ({
20092
- id: peer.ID ?? fallbackId,
20093
- name: peer.HostName ?? peer.DNSName ?? fallbackId,
20094
- dnsName: peer.DNSName,
20095
- addresses: peer.TailscaleIPs ?? [],
20096
- online: peer.Online ?? false,
20097
- hostName: peer.HostName,
20098
- os: peer.OS,
20099
- tags: peer.Tags ?? []
20100
- }));
20101
- }
20102
- function parseSelf(status) {
20103
- const self = status.Self;
20104
- if (!self) {
20105
- return null;
20106
- }
20107
- return {
20108
- id: self.ID ?? self.DNSName ?? self.HostName ?? "self",
20109
- name: self.HostName ?? self.DNSName ?? "self",
20110
- dnsName: self.DNSName,
20111
- addresses: self.TailscaleIPs ?? [],
20112
- online: self.Online ?? true,
20113
- hostName: self.HostName,
20114
- os: self.OS,
20115
- tailnetName: status.CurrentTailnet?.Name,
20116
- magicDnsSuffix: status.CurrentTailnet?.MagicDNSSuffix
20117
- };
20118
- }
20119
- function isBackendRunning(status) {
20120
- return (status.BackendState ?? "").trim().toLowerCase() === "running";
20121
- }
20122
- async function readStatusJsonFromFile(filePath) {
20123
- const raw2 = await readFile7(filePath, "utf8");
20124
- return parseStatusJson(raw2);
20125
- }
20126
- async function readStatusJson() {
20127
- const fixturePath = process.env.OPENSCOUT_TAILSCALE_STATUS_JSON;
20128
- if (fixturePath) {
20129
- return readStatusJsonFromFile(fixturePath);
20130
- }
20131
- try {
20132
- const tailscaleBin = process.env.OPENSCOUT_TAILSCALE_BIN ?? "tailscale";
20133
- const { stdout } = await execFileAsync(tailscaleBin, ["status", "--json"]);
20134
- return parseStatusJson(stdout);
20135
- } catch {
20136
- return null;
20137
- }
20138
- }
20139
- async function readTailscaleSelf() {
20140
- const summary = await readTailscaleStatusSummary();
20141
- if (!summary) {
20142
- return null;
20143
- }
20144
- return summary.self;
20145
- }
20146
- async function readTailscaleStatusSummary() {
20147
- const status = await readStatusJson();
20148
- if (!status) {
20149
- return null;
20150
- }
20151
- return {
20152
- backendState: status.BackendState ?? null,
20153
- running: isBackendRunning(status),
20154
- health: status.Health ?? [],
20155
- peers: parsePeers(status),
20156
- self: parseSelf(status)
20157
- };
20158
- }
20159
-
20160
- // packages/runtime/src/index.ts
20161
- init_broker_service();
20162
- init_local_agents();
20163
-
20164
- // packages/runtime/src/scout-broker.ts
20165
- init_dist2();
20166
- init_setup();
20167
- init_support_paths();
20168
- await __promiseAll([
20169
- init_local_agents(),
20170
- init_broker_service()
20171
- ]);
20172
-
20173
- // packages/runtime/src/index.ts
20174
- init_codex_app_server();
20175
- init_setup();
20176
- init_support_paths();
20177
-
20178
- // packages/runtime/src/scout-agent-cards.ts
20179
- init_dist2();
20180
- // packages/runtime/src/thread-events.ts
20181
- class ThreadWatchProtocolError extends Error {
20182
- status;
20183
- body;
20184
- constructor(status, body) {
20185
- super(body.message);
20186
- this.status = status;
20187
- this.body = body;
20188
- }
20189
- }
20190
- function watchKey(conversationId, watcherNodeId, watcherId) {
20191
- return `${conversationId}:${watcherNodeId}:${watcherId}`;
20192
- }
20193
- function writeSse(response, eventName, payload) {
20194
- response.write(`event: ${eventName}
20195
- data: ${JSON.stringify(payload)}
20196
-
20197
- `);
20198
- }
20199
-
20200
- class ThreadEventPlane {
20201
- options;
20202
- watches = new Map;
20203
- watchIdsByKey = new Map;
20204
- watchIdsByConversation = new Map;
20205
- constructor(options) {
20206
- this.options = options;
20207
- }
20208
- async openWatch(request) {
20209
- const conversation = this.requireConversationAuthority(request.conversationId);
20210
- this.requireRemoteWatchAllowed(conversation);
20211
- const afterSeq = Math.max(0, request.afterSeq ?? 0);
20212
- const oldestSeq = await this.options.projection.oldestThreadSeq(conversation.id);
20213
- const latestSeq = await this.options.projection.latestThreadSeq(conversation.id);
20214
- if (latestSeq > 0 && oldestSeq > 0 && afterSeq < oldestSeq - 1) {
20215
- throw new ThreadWatchProtocolError(409, {
20216
- code: "cursor_out_of_range",
20217
- message: `thread cursor ${afterSeq} is older than retained seq ${oldestSeq}`
20218
- });
20219
- }
20220
- const key = watchKey(conversation.id, request.watcherNodeId, request.watcherId);
20221
- const existingWatchId = this.watchIdsByKey.get(key);
20222
- if (existingWatchId) {
20223
- this.closeWatchInternal(existingWatchId);
20224
- }
20225
- const watchId = `thread-watch:${conversation.id}:${request.watcherNodeId}:${request.watcherId}`;
20226
- const leaseExpiresAt = Date.now() + this.normalizeLeaseMs(request.leaseMs);
20227
- const watch = {
20228
- watchId,
20229
- conversationId: conversation.id,
20230
- watcherNodeId: request.watcherNodeId,
20231
- watcherId: request.watcherId,
20232
- acceptedAfterSeq: afterSeq,
20233
- leaseExpiresAt,
20234
- mode: conversation.shareMode === "summary" ? "summary" : "shared",
20235
- clients: new Set
20236
- };
20237
- this.watches.set(watchId, watch);
20238
- this.watchIdsByKey.set(key, watchId);
20239
- this.indexWatch(watch);
20240
- return {
20241
- watchId,
20242
- conversationId: conversation.id,
20243
- authorityNodeId: conversation.authorityNodeId,
20244
- acceptedAfterSeq: afterSeq,
20245
- latestSeq,
20246
- leaseExpiresAt,
20247
- mode: watch.mode
20248
- };
20249
- }
20250
- async renewWatch(request) {
20251
- const watch = this.requireLiveWatch(request.watchId);
20252
- watch.leaseExpiresAt = Date.now() + this.normalizeLeaseMs(request.leaseMs);
20253
- return {
20254
- watchId: watch.watchId,
20255
- leaseExpiresAt: watch.leaseExpiresAt
20256
- };
20257
- }
20258
- async closeWatch(request) {
20259
- this.closeWatchInternal(request.watchId);
20260
- }
20261
- async replay(options) {
20262
- const conversation = this.requireConversationAuthority(options.conversationId);
20263
- this.requireRemoteWatchAllowed(conversation);
20264
- const oldestSeq = await this.options.projection.oldestThreadSeq(conversation.id);
20265
- const latestSeq = await this.options.projection.latestThreadSeq(conversation.id);
20266
- if (latestSeq > 0 && oldestSeq > 0 && options.afterSeq < oldestSeq - 1) {
20267
- throw new ThreadWatchProtocolError(409, {
20268
- code: "cursor_out_of_range",
20269
- message: `thread cursor ${options.afterSeq} is older than retained seq ${oldestSeq}`
20270
- });
20271
- }
20272
- return this.options.projection.listThreadEvents({
20273
- conversationId: conversation.id,
20274
- afterSeq: options.afterSeq,
20275
- limit: Math.min(options.limit ?? 500, this.options.maxReplayLimit ?? 2000)
20276
- });
20277
- }
20278
- async snapshot(conversationId) {
20279
- const conversation = this.requireConversationAuthority(conversationId);
20280
- this.requireRemoteWatchAllowed(conversation);
20281
- const snapshot = await this.options.projection.getThreadSnapshot(conversation.id);
20282
- if (!snapshot) {
20283
- throw new ThreadWatchProtocolError(404, {
20284
- code: "unknown_conversation",
20285
- message: `unknown conversation ${conversation.id}`
20286
- });
20287
- }
20288
- return snapshot;
20289
- }
20290
- async streamWatch(watchId, request, response) {
20291
- const watch = this.requireLiveWatch(watchId);
20292
- const backlog = await this.options.projection.listThreadEvents({
20293
- conversationId: watch.conversationId,
20294
- afterSeq: watch.acceptedAfterSeq,
20295
- limit: this.options.maxReplayLimit ?? 2000
20296
- });
20297
- response.writeHead(200, {
20298
- "content-type": "text/event-stream",
20299
- "cache-control": "no-cache, no-transform",
20300
- connection: "keep-alive"
20301
- });
20302
- writeSse(response, "hello", {
20303
- watchId: watch.watchId,
20304
- conversationId: watch.conversationId,
20305
- leaseExpiresAt: watch.leaseExpiresAt
20306
- });
20307
- for (const event of backlog) {
20308
- writeSse(response, "thread.event", event);
20309
- }
20310
- watch.clients.add(response);
20311
- request.on("close", () => {
20312
- watch.clients.delete(response);
20313
- response.end();
20314
- });
20315
- }
20316
- publish(events2) {
20317
- for (const event of events2) {
20318
- const watchIds = this.watchIdsByConversation.get(event.conversationId);
20319
- if (!watchIds || watchIds.size === 0) {
20320
- continue;
20321
- }
20322
- for (const watchId of [...watchIds]) {
20323
- const watch = this.watches.get(watchId);
20324
- if (!watch) {
20325
- watchIds.delete(watchId);
20326
- continue;
20327
- }
20328
- if (watch.leaseExpiresAt <= Date.now()) {
20329
- this.closeWatchInternal(watchId);
20330
- continue;
20331
- }
20332
- for (const client of watch.clients) {
20333
- writeSse(client, "thread.event", event);
20334
- }
20335
- }
20336
- }
20337
- }
20338
- normalizeLeaseMs(requestedLeaseMs) {
20339
- const defaultLeaseMs = this.options.defaultLeaseMs ?? 30000;
20340
- const maxLeaseMs = this.options.maxLeaseMs ?? 300000;
20341
- if (!requestedLeaseMs || !Number.isFinite(requestedLeaseMs) || requestedLeaseMs <= 0) {
20342
- return defaultLeaseMs;
20343
- }
20344
- return Math.min(Math.max(requestedLeaseMs, 5000), maxLeaseMs);
20345
- }
20346
- requireConversationAuthority(conversationId) {
20347
- const conversation = this.options.runtime.conversation(conversationId);
20348
- if (!conversation) {
20349
- throw new ThreadWatchProtocolError(404, {
20350
- code: "unknown_conversation",
20351
- message: `unknown conversation ${conversationId}`
20352
- });
20353
- }
20354
- if (conversation.authorityNodeId !== this.options.nodeId) {
20355
- throw new ThreadWatchProtocolError(409, {
20356
- code: "no_responder",
20357
- message: `conversation ${conversationId} is owned by ${conversation.authorityNodeId}`
20358
- });
20359
- }
20360
- return conversation;
20361
- }
20362
- requireRemoteWatchAllowed(conversation) {
20363
- if (conversation.shareMode === "local") {
20364
- throw new ThreadWatchProtocolError(403, {
20365
- code: "forbidden",
20366
- message: `conversation ${conversation.id} does not allow remote watches`
20367
- });
20368
- }
20369
- }
20370
- requireLiveWatch(watchId) {
20371
- const watch = this.watches.get(watchId);
20372
- if (!watch) {
20373
- throw new ThreadWatchProtocolError(404, {
20374
- code: "invalid_request",
20375
- message: `unknown watch ${watchId}`
20376
- });
20377
- }
20378
- if (watch.leaseExpiresAt <= Date.now()) {
20379
- this.closeWatchInternal(watchId);
20380
- throw new ThreadWatchProtocolError(410, {
20381
- code: "lease_expired",
20382
- message: `watch ${watchId} lease expired`
20383
- });
20384
- }
20385
- return watch;
20386
- }
20387
- indexWatch(watch) {
20388
- const ids = this.watchIdsByConversation.get(watch.conversationId) ?? new Set;
20389
- ids.add(watch.watchId);
20390
- this.watchIdsByConversation.set(watch.conversationId, ids);
20391
- }
20392
- closeWatchInternal(watchId) {
20393
- const watch = this.watches.get(watchId);
20394
- if (!watch) {
20395
- return;
20396
- }
20397
- this.watches.delete(watchId);
20398
- this.watchIdsByKey.delete(watchKey(watch.conversationId, watch.watcherNodeId, watch.watcherId));
20399
- const ids = this.watchIdsByConversation.get(watch.conversationId);
20400
- if (ids) {
20401
- ids.delete(watchId);
20402
- if (ids.size === 0) {
20403
- this.watchIdsByConversation.delete(watch.conversationId);
20404
- }
20405
- }
20406
- for (const client of watch.clients) {
20407
- client.end();
20408
- }
20409
- watch.clients.clear();
20410
- }
20411
- }
20412
- // packages/runtime/src/mobile-push.ts
20413
- init_support_paths();
20414
- // packages/web/server/core/observe/service.ts
20415
- var HISTORY_SNAPSHOT_CACHE_LIMIT = 128;
20416
- var historySnapshotCache = new Map;
20417
- var OBSERVE_SUMMARY_TAIL_SIZE = 8;
20418
- function activeEndpoint(snapshot, agentId) {
20419
- const candidates = Object.values(snapshot.endpoints ?? {}).filter((endpoint) => endpoint.agentId === agentId);
20420
- const rank = (state) => {
20421
- switch (state) {
20422
- case "active":
20423
- return 0;
20424
- case "idle":
20425
- return 1;
20426
- case "waiting":
20427
- return 2;
20428
- case "offline":
20429
- return 5;
20430
- default:
20431
- return 4;
20432
- }
20433
- };
20434
- return [...candidates].sort((left, right) => rank(left.state) - rank(right.state))[0] ?? null;
20435
- }
20436
- function expandHome(value) {
20437
- if (!value) {
20438
- return null;
20439
- }
20440
- if (value === "~") {
20441
- return homedir12();
20442
- }
20443
- if (value.startsWith("~/")) {
20444
- return join18(homedir12(), value.slice(2));
20445
- }
20446
- return value;
20447
- }
20448
- function encodeClaudeProjectsSlug2(absolutePath) {
20449
- const normalized = resolve8(absolutePath);
20450
- return `-${normalized.replace(/^\//u, "").replace(/\//gu, "-")}`;
20451
- }
20452
- function resolveClaudeHistoryPath(cwd, sessionId) {
20453
- const normalizedCwd = expandHome(cwd)?.trim();
20454
- if (!normalizedCwd) {
20455
- return null;
20456
- }
20457
- const projectDir = join18(homedir12(), ".claude", "projects", encodeClaudeProjectsSlug2(normalizedCwd));
20458
- const normalizedSessionId = sessionId?.trim().replace(/\.jsonl$/u, "") || "";
20459
- if (normalizedSessionId) {
20460
- const exactPath = join18(projectDir, `${normalizedSessionId}.jsonl`);
20461
- if (existsSync12(exactPath)) {
20462
- return exactPath;
20463
- }
20464
- }
20465
- return findMostRecentJsonl(projectDir);
20466
- }
20467
- function findMostRecentJsonl(dir) {
20468
- if (!existsSync12(dir))
20469
- return null;
20470
- try {
20471
- let best = null;
20472
- for (const entry of readdirSync2(dir)) {
20473
- if (!entry.endsWith(".jsonl"))
20474
- continue;
20475
- const full = join18(dir, entry);
20476
- const st = statSync4(full);
20477
- if (!best || st.mtimeMs > best.mtime) {
20478
- best = { path: full, mtime: st.mtimeMs };
20479
- }
20480
- }
20481
- return best?.path ?? null;
20482
- } catch {
20483
- return null;
20484
- }
20485
- }
20486
- function historyAdapterAlias(value) {
20487
- const normalized = value?.trim().toLowerCase();
20488
- if (!normalized) {
20489
- return null;
20490
- }
20491
- if (normalized === "claude" || normalized === "claude-code" || normalized === "claude_stream_json") {
20492
- return "claude-code";
20493
- }
20494
- if (normalized === "codex" || normalized === "codex_app_server") {
20495
- return "codex";
20496
- }
20497
- return null;
20498
- }
20499
- function snapshotProviderMeta(snapshot) {
20500
- const providerMeta = snapshot.session.providerMeta;
20501
- return providerMeta && typeof providerMeta === "object" ? providerMeta : {};
20502
- }
20503
- function firstString(...values) {
20504
- for (const value of values) {
20505
- if (typeof value === "string" && value.trim().length > 0) {
20506
- return value.trim();
20507
- }
20508
- }
20509
- return null;
20510
- }
20511
- function resolveHistoryCandidate(agent, snapshot) {
20512
- const snapshotAdapter = historyAdapterAlias(snapshot?.session.adapterType);
20513
- const agentAdapter = historyAdapterAlias(agent.harness);
20514
- const providerMeta = snapshot ? snapshotProviderMeta(snapshot) : {};
20515
- const directPath = firstString(providerMeta.resumeSessionPath, providerMeta.threadPath);
20516
- if (directPath) {
20517
- const adapterType = snapshotAdapter ?? agentAdapter;
20518
- if (adapterType) {
20519
- return { path: directPath, adapterType };
20520
- }
20521
- }
20522
- const claudeSessionId = firstString(providerMeta.transportSessionId, agent.harnessSessionId);
20523
- const claudeCwd = firstString(snapshot?.session.cwd, agent.cwd, agent.projectRoot);
20524
- if ((snapshotAdapter ?? agentAdapter) === "claude-code") {
20525
- const path = resolveClaudeHistoryPath(claudeCwd, claudeSessionId);
20526
- if (path) {
20527
- return { path, adapterType: "claude-code" };
20528
- }
20529
- }
20530
- return null;
20531
- }
20532
- function normalizeTimedEvents(events2) {
20533
- if (!events2) {
20534
- return [];
20535
- }
20536
- return events2.map((entry) => ({
20537
- timestamp: entry.capturedAt,
20538
- event: entry.event
20539
- }));
20540
- }
20541
- function readHistorySnapshot(candidate) {
20542
- if (!candidate) {
20543
- return null;
20544
- }
20545
- if (!supportsHistorySessionSnapshotForPath(candidate.path, candidate.adapterType)) {
20546
- return null;
20547
- }
20548
- if (!existsSync12(candidate.path)) {
20549
- return null;
20550
- }
20551
- const stat5 = statSync4(candidate.path);
20552
- const cached = historySnapshotCache.get(candidate.path);
20553
- if (cached && cached.adapterType === candidate.adapterType && cached.mtimeMs === stat5.mtimeMs && cached.size === stat5.size) {
20554
- return {
20555
- historyPath: cached.historyPath,
20556
- snapshot: cached.snapshot,
20557
- timedEvents: cached.timedEvents
20558
- };
20559
- }
20560
- const replay = createHistorySessionSnapshot({
20561
- path: candidate.path,
20562
- content: readFileSync8(candidate.path, "utf8"),
20563
- adapterType: candidate.adapterType,
20564
- baseTimestampMs: stat5.mtimeMs
20565
- });
20566
- const nextEntry = {
20567
- historyPath: candidate.path,
20568
- snapshot: replay.snapshot,
20569
- timedEvents: normalizeTimedEvents(replay.events),
20570
- adapterType: candidate.adapterType,
20571
- mtimeMs: stat5.mtimeMs,
20572
- size: stat5.size
20573
- };
20574
- historySnapshotCache.set(candidate.path, nextEntry);
20575
- if (historySnapshotCache.size > HISTORY_SNAPSHOT_CACHE_LIMIT) {
20576
- const oldestKey = historySnapshotCache.keys().next().value;
20577
- if (typeof oldestKey === "string") {
20578
- historySnapshotCache.delete(oldestKey);
20579
- }
20580
- }
20581
- return {
20582
- historyPath: nextEntry.historyPath,
20583
- snapshot: nextEntry.snapshot,
20584
- timedEvents: nextEntry.timedEvents
20585
- };
20586
- }
20587
- async function readLiveSnapshot(endpoint) {
20588
- if (!endpoint?.sessionId) {
20589
- return null;
20590
- }
20591
- if (endpoint.transport === "pairing_bridge") {
20592
- return await getScoutWebPairingSessionSnapshot(endpoint.sessionId);
20593
- }
20594
- if (endpoint.transport === "codex_app_server" || endpoint.transport === "claude_stream_json") {
20595
- return await getLocalAgentEndpointSessionSnapshot(endpoint);
20596
- }
20597
- return null;
20598
- }
20599
- function summarizeCommandOutput(output) {
20600
- const lines = output.split(/\r?\n/u).map((line) => line.trimEnd()).filter((line) => line.length > 0);
20601
- if (lines.length === 0) {
20602
- return;
20603
- }
20604
- return lines.slice(-12);
18214
+ return lines.slice(-12);
20605
18215
  }
20606
18216
  function truncatePreview(value, maxLines = 6, maxChars = 400) {
20607
18217
  const lines = value.split(/\r?\n/u).map((line) => line.trimEnd()).filter((line) => line.length > 0).slice(0, maxLines);
@@ -20798,8 +18408,8 @@ function syntheticContextUsage(eventCount) {
20798
18408
  return [];
20799
18409
  }
20800
18410
  const length = Math.max(2, Math.min(eventCount, 24));
20801
- return Array.from({ length }, (_, index2) => {
20802
- const progress = length <= 1 ? 1 : index2 / (length - 1);
18411
+ return Array.from({ length }, (_, index) => {
18412
+ const progress = length <= 1 ? 1 : index / (length - 1);
20803
18413
  return Math.min(0.92, 0.08 + progress * 0.66);
20804
18414
  });
20805
18415
  }
@@ -20930,9 +18540,9 @@ function buildObserveDataFromSnapshot(snapshot, timedEvents = [], live = false)
20930
18540
  }
20931
18541
  }
20932
18542
  const seconds = timelineSeconds(eventDrafts.map((draft) => draft.timestampMs), timing.baseTimestampMs);
20933
- const builtEntries = eventDrafts.map((draft, index2) => ({
18543
+ const builtEntries = eventDrafts.map((draft, index) => ({
20934
18544
  draft,
20935
- event: draft.build(seconds[index2] ?? 0)
18545
+ event: draft.build(seconds[index] ?? 0)
20936
18546
  })).filter(({ event }) => event.text.length > 0 || event.kind === "tool" || event.kind === "boot");
20937
18547
  const events2 = builtEntries.map((entry) => entry.event);
20938
18548
  for (const { draft, event } of builtEntries) {
@@ -20963,8 +18573,8 @@ function unavailableObserveData(agent) {
20963
18573
  live: false
20964
18574
  };
20965
18575
  }
20966
- async function resolveSnapshotSource(agent, broker2) {
20967
- const endpoint = broker2 ? activeEndpoint(broker2.snapshot, agent.id) : null;
18576
+ async function resolveSnapshotSource(agent, broker) {
18577
+ const endpoint = broker ? activeEndpoint(broker.snapshot, agent.id) : null;
20968
18578
  const liveSnapshot = await readLiveSnapshot(endpoint);
20969
18579
  const live = Boolean(liveSnapshot && (liveSnapshot.currentTurnId || liveSnapshot.session.status === "active"));
20970
18580
  const historyCandidate = resolveHistoryCandidate(agent, liveSnapshot);
@@ -21007,8 +18617,8 @@ async function resolveSnapshotSource(agent, broker2) {
21007
18617
  sessionId: null
21008
18618
  };
21009
18619
  }
21010
- async function buildAgentObservePayload(agent, broker2) {
21011
- const source = await resolveSnapshotSource(agent, broker2);
18620
+ async function buildAgentObservePayload(agent, broker) {
18621
+ const source = await resolveSnapshotSource(agent, broker);
21012
18622
  if (source.source === "unavailable") {
21013
18623
  return {
21014
18624
  agentId: agent.id,
@@ -21037,8 +18647,8 @@ async function loadAgentObservePayloadsInternal(agentIds) {
21037
18647
  if (filteredAgents.length === 0) {
21038
18648
  return [];
21039
18649
  }
21040
- const broker2 = await loadScoutBrokerContext();
21041
- return await Promise.all(filteredAgents.map((agent) => buildAgentObservePayload(agent, broker2)));
18650
+ const broker = await loadScoutBrokerContext();
18651
+ return await Promise.all(filteredAgents.map((agent) => buildAgentObservePayload(agent, broker)));
21042
18652
  }
21043
18653
  function summarizeAgentObservePayload(payload) {
21044
18654
  return {
@@ -21063,6 +18673,87 @@ async function loadAgentObservePayload(agentId) {
21063
18673
  await init_broker_service();
21064
18674
  import { execFile as execFile2 } from "child_process";
21065
18675
  import { promisify as promisify2 } from "util";
18676
+
18677
+ // packages/runtime/src/tailscale.ts
18678
+ import { readFile as readFile7 } from "fs/promises";
18679
+ import { execFile } from "child_process";
18680
+ import { promisify } from "util";
18681
+ var execFileAsync = promisify(execFile);
18682
+ function parseStatusJson(raw2) {
18683
+ return JSON.parse(raw2);
18684
+ }
18685
+ function parsePeers(status) {
18686
+ const peers = Object.entries(status.Peer ?? {});
18687
+ return peers.map(([fallbackId, peer]) => ({
18688
+ id: peer.ID ?? fallbackId,
18689
+ name: peer.HostName ?? peer.DNSName ?? fallbackId,
18690
+ dnsName: peer.DNSName,
18691
+ addresses: peer.TailscaleIPs ?? [],
18692
+ online: peer.Online ?? false,
18693
+ hostName: peer.HostName,
18694
+ os: peer.OS,
18695
+ tags: peer.Tags ?? []
18696
+ }));
18697
+ }
18698
+ function parseSelf(status) {
18699
+ const self = status.Self;
18700
+ if (!self) {
18701
+ return null;
18702
+ }
18703
+ return {
18704
+ id: self.ID ?? self.DNSName ?? self.HostName ?? "self",
18705
+ name: self.HostName ?? self.DNSName ?? "self",
18706
+ dnsName: self.DNSName,
18707
+ addresses: self.TailscaleIPs ?? [],
18708
+ online: self.Online ?? true,
18709
+ hostName: self.HostName,
18710
+ os: self.OS,
18711
+ tailnetName: status.CurrentTailnet?.Name,
18712
+ magicDnsSuffix: status.CurrentTailnet?.MagicDNSSuffix
18713
+ };
18714
+ }
18715
+ function isBackendRunning(status) {
18716
+ return (status.BackendState ?? "").trim().toLowerCase() === "running";
18717
+ }
18718
+ async function readStatusJsonFromFile(filePath) {
18719
+ const raw2 = await readFile7(filePath, "utf8");
18720
+ return parseStatusJson(raw2);
18721
+ }
18722
+ async function readStatusJson() {
18723
+ const fixturePath = process.env.OPENSCOUT_TAILSCALE_STATUS_JSON;
18724
+ if (fixturePath) {
18725
+ return readStatusJsonFromFile(fixturePath);
18726
+ }
18727
+ try {
18728
+ const tailscaleBin = process.env.OPENSCOUT_TAILSCALE_BIN ?? "tailscale";
18729
+ const { stdout } = await execFileAsync(tailscaleBin, ["status", "--json"]);
18730
+ return parseStatusJson(stdout);
18731
+ } catch {
18732
+ return null;
18733
+ }
18734
+ }
18735
+ async function readTailscaleSelf() {
18736
+ const summary = await readTailscaleStatusSummary();
18737
+ if (!summary) {
18738
+ return null;
18739
+ }
18740
+ return summary.self;
18741
+ }
18742
+ async function readTailscaleStatusSummary() {
18743
+ const status = await readStatusJson();
18744
+ if (!status) {
18745
+ return null;
18746
+ }
18747
+ return {
18748
+ backendState: status.BackendState ?? null,
18749
+ running: isBackendRunning(status),
18750
+ health: status.Health ?? [],
18751
+ peers: parsePeers(status),
18752
+ self: parseSelf(status)
18753
+ };
18754
+ }
18755
+
18756
+ // packages/web/server/core/mesh/service.ts
21066
18757
  var execFileAsync2 = promisify2(execFile2);
21067
18758
  function normalizeHost(host) {
21068
18759
  return host.trim().replace(/^\[/, "").replace(/\]$/, "").toLowerCase();
@@ -21108,7 +18799,7 @@ async function readTailscaleStatus() {
21108
18799
  function formatIssueWarning(issue) {
21109
18800
  return issue.action ? `${issue.title} \u2014 ${issue.summary} ${issue.action}` : `${issue.title} \u2014 ${issue.summary}`;
21110
18801
  }
21111
- function computeIssues(health, localNode, nodes, tailscale2) {
18802
+ function computeIssues(health, localNode, nodes, tailscale) {
21112
18803
  const issues = [];
21113
18804
  if (!health.reachable) {
21114
18805
  issues.push({
@@ -21121,7 +18812,7 @@ function computeIssues(health, localNode, nodes, tailscale2) {
21121
18812
  });
21122
18813
  return issues;
21123
18814
  }
21124
- if (tailscale2.available && !tailscale2.running) {
18815
+ if (tailscale.available && !tailscale.running) {
21125
18816
  issues.push({
21126
18817
  code: "tailscale_stopped",
21127
18818
  severity: "warning",
@@ -21151,7 +18842,7 @@ function computeIssues(health, localNode, nodes, tailscale2) {
21151
18842
  });
21152
18843
  }
21153
18844
  const remoteNodes = Object.values(nodes).filter((n) => n.id !== localNode?.id);
21154
- if (!tailscale2.available && remoteNodes.length === 0) {
18845
+ if (!tailscale.available && remoteNodes.length === 0) {
21155
18846
  issues.push({
21156
18847
  code: "discovery_unconfigured",
21157
18848
  severity: "warning",
@@ -21240,7 +18931,7 @@ function filterCurrentMeshNodes(allNodes, meshId, localNodeId, now) {
21240
18931
  }
21241
18932
  async function loadMeshStatus() {
21242
18933
  const brokerUrl = resolveScoutBrokerUrl();
21243
- const [health, context, tailscale2] = await Promise.all([
18934
+ const [health, context, tailscale] = await Promise.all([
21244
18935
  readScoutBrokerHealth(brokerUrl),
21245
18936
  loadScoutBrokerContext(brokerUrl),
21246
18937
  readTailscaleStatus()
@@ -21250,9 +18941,9 @@ async function loadMeshStatus() {
21250
18941
  const meshId = health.meshId ?? localNode?.meshId ?? null;
21251
18942
  const identity = computeIdentitySummary(health, localNode, meshId);
21252
18943
  const nodes = filterCurrentMeshNodes(allNodes, meshId, localNode?.id, Date.now());
21253
- const issues = computeIssues(health, localNode, nodes, tailscale2);
18944
+ const issues = computeIssues(health, localNode, nodes, tailscale);
21254
18945
  const warnings = issues.map(formatIssueWarning);
21255
- return { brokerUrl, health, localNode, meshId, identity, nodes, tailscale: tailscale2, issues, warnings };
18946
+ return { brokerUrl, health, localNode, meshId, identity, nodes, tailscale, issues, warnings };
21256
18947
  }
21257
18948
  function preferredAnnounceHost(self, currentBrokerUrl) {
21258
18949
  const dnsName = stripTrailingDot(self?.dnsName);