@undefineds.co/linx 0.3.18 → 0.3.19

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.
@@ -358,7 +358,7 @@ async function createDefaultRuntime() {
358
358
  runResource: models.runResource,
359
359
  runStepResource: models.runStepResource,
360
360
  agentResource: models.agentResource,
361
- contactResource: models.contactTable,
361
+ contactResource: models.contactResource,
362
362
  auditResource: models.auditResource,
363
363
  inboxNotificationResource: models.inboxNotificationResource,
364
364
  writePodFile: writePodFileToSession,
@@ -836,10 +836,13 @@ function buildSymphonyChatRow(plan, webId, stage, lastPreview) {
836
836
  const createdAt = safeDate(plan.issue.createdAt);
837
837
  const updatedAt = safeDate(plan.session.updatedAt);
838
838
  const secretaryAgent = agentResource.buildIri(webId, { id: SYMPHONY_SECRETARY_AGENT_ID });
839
- const workerAgents = plan.workers.map((worker) => agentResource.buildIri(webId, {
840
- id: buildWorkerAgentId(worker.session.backend, worker.session.target.agent),
839
+ const secretaryContact = buildSecretaryContactIri(webId);
840
+ const workerMembers = plan.workers.map((worker) => ({
841
+ contact: buildWorkerContactIri(webId, worker),
842
+ agent: buildWorkerAgentIri(webId, worker),
843
+ label: worker.session.target.label ?? worker.session.target.contact ?? worker.session.target.agent ?? backendDisplayName(worker.session.backend),
841
844
  }));
842
- const participants = Array.from(new Set([webId, secretaryAgent, ...workerAgents]));
845
+ const participants = Array.from(new Set([webId, secretaryContact, ...workerMembers.map((member) => member.contact)]));
843
846
  const targetChat = selectTargetChatIri(plan.session.target?.chat, webId, plan);
844
847
  return {
845
848
  id: buildTargetChatId(plan, webId),
@@ -849,23 +852,23 @@ function buildSymphonyChatRow(plan, webId, stage, lastPreview) {
849
852
  kind: targetChat === buildSymphonyChatUri(webId) ? 'symphony-control-room' : 'symphony-target-room',
850
853
  surface: 'symphony',
851
854
  secretaryAgent,
855
+ secretaryContact,
852
856
  currentBackend: plan.session.backend,
853
857
  target: plan.session.target,
854
858
  currentStage: stage,
855
859
  memberRoles: Object.fromEntries([
856
860
  [webId, 'owner'],
857
- [secretaryAgent, 'admin'],
858
- ...workerAgents.map((agent) => [agent, 'member']),
861
+ [secretaryContact, 'admin'],
862
+ ...workerMembers.map((member) => [member.contact, 'member']),
859
863
  ]),
860
864
  members: [
861
865
  { uri: webId, role: 'user', label: 'User' },
862
- { uri: secretaryAgent, role: 'secretary', label: 'AI Secretary' },
863
- ...plan.workers.map((worker) => ({
864
- uri: agentResource.buildIri(webId, {
865
- id: buildWorkerAgentId(worker.session.backend, worker.session.target.agent),
866
- }),
866
+ { uri: secretaryContact, agent: secretaryAgent, role: 'secretary', label: 'AI Secretary' },
867
+ ...workerMembers.map((member) => ({
868
+ uri: member.contact,
869
+ agent: member.agent,
867
870
  role: 'worker',
868
- label: worker.session.target.label ?? worker.session.target.agent ?? backendDisplayName(worker.session.backend),
871
+ label: member.label,
869
872
  })),
870
873
  ],
871
874
  },
@@ -902,6 +905,9 @@ function buildSymphonyWorkerSummary(plan, webId, worker) {
902
905
  sessionResource: buildSymphonyWorkerSessionUri(webId, worker),
903
906
  backend: worker.session.backend,
904
907
  agent: worker.session.target.agent,
908
+ contact: worker.session.target.contact ?? buildWorkerContactId(worker),
909
+ contactResource: buildWorkerContactIri(webId, worker),
910
+ agentResource: buildWorkerAgentIri(webId, worker),
905
911
  status: worker.session.status,
906
912
  autoModeSessionId: worker.session.autoModeSessionId,
907
913
  target: worker.session.target,
@@ -1056,6 +1062,7 @@ function buildSymphonySessionRow(plan, webId, worker = plan.workers[0] ?? {
1056
1062
  function buildSymphonyIssueRow(plan, webId) {
1057
1063
  const createdAt = safeDate(plan.issue.createdAt);
1058
1064
  const updatedAt = safeDate(plan.issue.updatedAt);
1065
+ const secretaryContact = buildSecretaryContactIri(webId);
1059
1066
  return {
1060
1067
  id: buildSymphonyIssueId(plan.issue),
1061
1068
  // File-primary: title remains a compact index label for existing Issue schemas.
@@ -1071,7 +1078,7 @@ function buildSymphonyIssueRow(plan, webId) {
1071
1078
  tasks: Array.from(new Set((plan.issue.tasks?.length ? plan.issue.tasks : plan.workers.map((worker) => worker.task))
1072
1079
  .map((task) => normalizeSymphonyTaskIri(webId, task)))),
1073
1080
  createdBy: plan.issue.issuer.webId ?? webId,
1074
- assignedTo: agentResource.buildIri(webId, { id: SYMPHONY_SECRETARY_AGENT_ID }),
1081
+ assignedTo: secretaryContact,
1075
1082
  createdAt,
1076
1083
  updatedAt,
1077
1084
  ...(plan.issue.closedAt ? { closedAt: safeDate(plan.issue.closedAt) } : {}),
@@ -1130,9 +1137,8 @@ function mapSymphonyRunStatus(status) {
1130
1137
  function buildSymphonyTaskRow(plan, webId, worker) {
1131
1138
  const createdAt = safeDate(worker.taskRecord.createdAt);
1132
1139
  const updatedAt = safeDate(worker.taskRecord.updatedAt);
1133
- const workerAgent = agentResource.buildIri(webId, {
1134
- id: buildWorkerAgentId(worker.session.backend, worker.session.target.agent),
1135
- });
1140
+ const workerContact = buildWorkerContactIri(webId, worker);
1141
+ const workerAgent = buildWorkerAgentIri(webId, worker);
1136
1142
  return {
1137
1143
  id: taskResource.buildId({ id: buildSymphonyTaskKey(worker.task) }),
1138
1144
  title: worker.taskRecord.title,
@@ -1144,7 +1150,7 @@ function buildSymphonyTaskRow(plan, webId, worker) {
1144
1150
  workspace: pathToWorkspaceUri(worker.session.cwd) ?? pathToWorkspaceUri(plan.session.cwd) ?? 'file:///',
1145
1151
  status: mapSymphonyTaskStatus(worker.taskRecord.status),
1146
1152
  priority: plan.issue.priority,
1147
- assignedTo: workerAgent,
1153
+ assignedTo: workerContact,
1148
1154
  source: buildSymphonyIssueIri(webId, plan.issue),
1149
1155
  metadata: {
1150
1156
  surface: 'symphony',
@@ -1152,6 +1158,8 @@ function buildSymphonyTaskRow(plan, webId, worker) {
1152
1158
  acceptanceCriteria: worker.taskRecord.acceptanceCriteria,
1153
1159
  backend: worker.session.backend,
1154
1160
  target: worker.session.target,
1161
+ assignedContact: workerContact,
1162
+ assignedAgent: workerAgent,
1155
1163
  workspace: buildSymphonyWorkspaceMetadata(plan, worker),
1156
1164
  spaceContract: buildSymphonySpaceContract(plan, webId, worker),
1157
1165
  podAccessPolicy: buildSymphonyWorkerPodAccessPolicy(plan, webId, worker),
@@ -1165,9 +1173,9 @@ function buildSymphonyDeliveryRow(plan, webId, worker) {
1165
1173
  const createdAt = safeDate(worker.delivery.createdAt);
1166
1174
  const updatedAt = safeDate(worker.delivery.updatedAt);
1167
1175
  const secretaryAgent = agentResource.buildIri(webId, { id: SYMPHONY_SECRETARY_AGENT_ID });
1168
- const workerAgent = agentResource.buildIri(webId, {
1169
- id: buildWorkerAgentId(worker.session.backend, worker.session.target.agent),
1170
- });
1176
+ const secretaryContact = buildSecretaryContactIri(webId);
1177
+ const workerAgent = buildWorkerAgentIri(webId, worker);
1178
+ const workerContact = buildWorkerContactIri(webId, worker);
1171
1179
  return {
1172
1180
  id: deliveryResource.buildId({
1173
1181
  id: getSymphonyArchiveKey(worker.delivery.uri),
@@ -1177,8 +1185,8 @@ function buildSymphonyDeliveryRow(plan, webId, worker) {
1177
1185
  kind: worker.delivery.type,
1178
1186
  status: worker.delivery.status,
1179
1187
  task: buildSymphonyTaskIri(webId, worker.task),
1180
- source: secretaryAgent,
1181
- target: workerAgent,
1188
+ source: secretaryContact,
1189
+ target: workerContact,
1182
1190
  chat: selectWorkerChatIri(plan, webId, worker),
1183
1191
  thread: selectWorkerThreadIri(plan, webId, worker),
1184
1192
  targetThread: selectWorkerThreadIri(plan, webId, worker),
@@ -1192,6 +1200,8 @@ function buildSymphonyDeliveryRow(plan, webId, worker) {
1192
1200
  backend: worker.session.backend,
1193
1201
  mode: worker.session.mode,
1194
1202
  target: worker.session.target,
1203
+ targetContact: workerContact,
1204
+ targetAgent: workerAgent,
1195
1205
  workspace: buildSymphonyWorkspaceMetadata(plan, worker),
1196
1206
  spaceContract: buildSymphonySpaceContract(plan, webId, worker),
1197
1207
  podAccessPolicy: buildSymphonyWorkerPodAccessPolicy(plan, webId, worker),
@@ -1208,6 +1218,9 @@ function buildSymphonyDeliveryRow(plan, webId, worker) {
1208
1218
  session: worker.session.uri,
1209
1219
  }),
1210
1220
  autoModeSessionId: worker.delivery.autoModeSessionId,
1221
+ sourceAgent: secretaryAgent,
1222
+ targetContact: workerContact,
1223
+ targetAgent: workerAgent,
1211
1224
  workspace: buildSymphonyWorkspaceMetadata(plan, worker),
1212
1225
  spaceContract: buildSymphonySpaceContract(plan, webId, worker),
1213
1226
  podAccessPolicy: buildSymphonyWorkerPodAccessPolicy(plan, webId, worker),
@@ -1224,9 +1237,7 @@ function buildSymphonyDeliveryRow(plan, webId, worker) {
1224
1237
  }
1225
1238
  function buildSymphonyReportRow(plan, webId, worker, stage) {
1226
1239
  const completedAt = safeDate(worker.session.completedAt ?? worker.session.updatedAt);
1227
- const workerAgent = agentResource.buildIri(webId, {
1228
- id: buildWorkerAgentId(worker.session.backend, worker.session.target.agent),
1229
- });
1240
+ const workerAgent = buildWorkerAgentIri(webId, worker);
1230
1241
  const run = buildSymphonyRunIri(webId, worker);
1231
1242
  const task = buildSymphonyTaskIri(webId, worker.task);
1232
1243
  const status = worker.session.status === 'failed' || stage === 'failed' ? 'failed' : 'completed';
@@ -1286,9 +1297,7 @@ function buildSymphonyEvidenceRow(plan, webId, worker, stage) {
1286
1297
  const task = buildSymphonyTaskIri(webId, worker.task);
1287
1298
  const delivery = buildSymphonyDeliveryIri(webId, worker);
1288
1299
  const runStep = buildSymphonyRunStepIri(webId, worker, stage);
1289
- const workerAgent = agentResource.buildIri(webId, {
1290
- id: buildWorkerAgentId(worker.session.backend, worker.session.target.agent),
1291
- });
1300
+ const workerAgent = buildWorkerAgentIri(webId, worker);
1292
1301
  return {
1293
1302
  id: evidenceResource.buildId({
1294
1303
  id: `${getSymphonyArchiveKey(worker.session.uri)}-${stage}`,
@@ -1336,7 +1345,7 @@ function buildPostRunReconciliationMetadata(plan, webId, worker, stage) {
1336
1345
  return {
1337
1346
  required: true,
1338
1347
  status: 'pending_secretary_review',
1339
- owner: agentResource.buildIri(webId, { id: SYMPHONY_SECRETARY_AGENT_ID }),
1348
+ owner: buildSecretaryContactIri(webId),
1340
1349
  sourceIssue: buildSymphonyIssueIri(webId, plan.issue),
1341
1350
  sourceTask: buildSymphonyTaskIri(webId, worker.task),
1342
1351
  sourceDelivery: buildSymphonyDeliveryIri(webId, worker),
@@ -1356,10 +1365,10 @@ function buildPostRunReconciliationMetadata(plan, webId, worker, stage) {
1356
1365
  }
1357
1366
  function buildSymphonyReportDeliveryRow(plan, webId, worker, stage) {
1358
1367
  const completedAt = safeDate(worker.session.completedAt ?? worker.session.updatedAt);
1359
- const workerAgent = agentResource.buildIri(webId, {
1360
- id: buildWorkerAgentId(worker.session.backend, worker.session.target.agent),
1361
- });
1368
+ const workerAgent = buildWorkerAgentIri(webId, worker);
1369
+ const workerContact = buildWorkerContactIri(webId, worker);
1362
1370
  const secretaryAgent = agentResource.buildIri(webId, { id: SYMPHONY_SECRETARY_AGENT_ID });
1371
+ const secretaryContact = buildSecretaryContactIri(webId);
1363
1372
  const run = buildSymphonyRunIri(webId, worker);
1364
1373
  const report = buildSymphonyReportIri(webId, worker);
1365
1374
  const task = buildSymphonyTaskIri(webId, worker.task);
@@ -1379,8 +1388,8 @@ function buildSymphonyReportDeliveryRow(plan, webId, worker, stage) {
1379
1388
  kind: 'report',
1380
1389
  status: 'completed',
1381
1390
  task,
1382
- source: workerAgent,
1383
- target: secretaryAgent,
1391
+ source: workerContact,
1392
+ target: secretaryContact,
1384
1393
  chat: selectWorkerChatIri(plan, webId, worker),
1385
1394
  thread: selectWorkerThreadIri(plan, webId, worker),
1386
1395
  targetThread: selectTargetThreadIri(plan.issue.thread ?? worker.session.target?.thread, webId, plan),
@@ -1401,6 +1410,9 @@ function buildSymphonyReportDeliveryRow(plan, webId, worker, stage) {
1401
1410
  run,
1402
1411
  backend: worker.session.backend,
1403
1412
  agent: worker.session.target.agent,
1413
+ contact: worker.session.target.contact ?? buildWorkerContactId(worker),
1414
+ sourceAgent: workerAgent,
1415
+ sourceContact: workerContact,
1404
1416
  autoModeSessionId: worker.session.autoModeSessionId,
1405
1417
  exitCode: worker.session.exitCode,
1406
1418
  error: worker.session.error ?? worker.delivery.error ?? worker.taskRecord.error,
@@ -1512,13 +1524,30 @@ function buildSymphonyRunStepRow(plan, webId, worker, stage) {
1512
1524
  createdAt,
1513
1525
  };
1514
1526
  }
1515
- function buildWorkerAgentId(backend, agent) {
1516
- const suffix = (agent ?? `${backend}-worker`)
1527
+ function normalizeSymphonyActorKey(value, fallback) {
1528
+ return (value ?? fallback)
1517
1529
  .trim()
1518
1530
  .replace(/[^a-zA-Z0-9._-]/gu, '-')
1519
1531
  .replace(/-+/gu, '-')
1520
- .replace(/^-|-$/gu, '');
1521
- return `symphony-${suffix || `${backend}-worker`}`;
1532
+ .replace(/^-|-$/gu, '')
1533
+ || fallback;
1534
+ }
1535
+ function buildWorkerContactId(worker) {
1536
+ return normalizeSymphonyActorKey(worker.session.target.contact ?? worker.session.target.agent ?? worker.delivery.targetAgent, worker.session.backend);
1537
+ }
1538
+ function buildWorkerAgentId(backend, agent, contact) {
1539
+ return normalizeSymphonyActorKey(agent ?? contact, backend);
1540
+ }
1541
+ function buildSecretaryContactIri(webId) {
1542
+ return contactResource.buildIri(webId, { id: SYMPHONY_CONTACT_ID });
1543
+ }
1544
+ function buildWorkerAgentIri(webId, worker) {
1545
+ return agentResource.buildIri(webId, {
1546
+ id: buildWorkerAgentId(worker.session.backend, worker.session.target.agent, worker.session.target.contact),
1547
+ });
1548
+ }
1549
+ function buildWorkerContactIri(webId, worker) {
1550
+ return contactResource.buildIri(webId, { id: buildWorkerContactId(worker) });
1522
1551
  }
1523
1552
  function buildSymphonyAgents(plan) {
1524
1553
  const now = safeDate(plan.session.updatedAt);
@@ -1535,7 +1564,7 @@ function buildSymphonyAgents(plan) {
1535
1564
  ];
1536
1565
  const seen = new Set(agents.map((agent) => agent.id));
1537
1566
  for (const worker of plan.workers) {
1538
- const id = buildWorkerAgentId(worker.session.backend, worker.session.target.agent);
1567
+ const id = buildWorkerAgentId(worker.session.backend, worker.session.target.agent, worker.session.target.contact);
1539
1568
  if (seen.has(id)) {
1540
1569
  continue;
1541
1570
  }
@@ -1554,15 +1583,35 @@ function buildSymphonyAgents(plan) {
1554
1583
  }
1555
1584
  function buildSymphonyContacts(plan, webId) {
1556
1585
  const now = safeDate(plan.session.updatedAt);
1557
- return buildSymphonyAgents(plan).map((agent) => ({
1558
- id: agent.id === SYMPHONY_SECRETARY_AGENT_ID ? SYMPHONY_CONTACT_ID : `${agent.id}-contact`,
1559
- name: agent.name,
1560
- entity: agentResource.buildIri(webId, { id: agent.id }),
1561
- rdfType: ContactClass.AGENT,
1562
- contactType: ContactType.AGENT,
1563
- createdAt: now,
1564
- updatedAt: now,
1565
- }));
1586
+ const contacts = [
1587
+ {
1588
+ id: SYMPHONY_CONTACT_ID,
1589
+ name: 'AI Secretary',
1590
+ entity: agentResource.buildIri(webId, { id: SYMPHONY_SECRETARY_AGENT_ID }),
1591
+ rdfType: ContactClass.AGENT,
1592
+ contactType: ContactType.AGENT,
1593
+ createdAt: now,
1594
+ updatedAt: now,
1595
+ },
1596
+ ];
1597
+ const seen = new Set(contacts.map((contact) => contact.id));
1598
+ for (const worker of plan.workers) {
1599
+ const id = buildWorkerContactId(worker);
1600
+ if (seen.has(id)) {
1601
+ continue;
1602
+ }
1603
+ seen.add(id);
1604
+ contacts.push({
1605
+ id,
1606
+ name: worker.session.target.label ?? worker.session.target.contact ?? worker.session.target.agent ?? backendDisplayName(worker.session.backend),
1607
+ entity: buildWorkerAgentIri(webId, worker),
1608
+ rdfType: ContactClass.AGENT,
1609
+ contactType: ContactType.AGENT,
1610
+ createdAt: now,
1611
+ updatedAt: now,
1612
+ });
1613
+ }
1614
+ return contacts;
1566
1615
  }
1567
1616
  function buildProgressBlock(plan, stage) {
1568
1617
  const statusByStage = {
@@ -1628,7 +1677,7 @@ function buildStatusMessageRow(plan, webId, stage) {
1628
1677
  const content = buildStatusContent(plan, stage);
1629
1678
  const secretaryAgent = agentResource.buildIri(webId, { id: SYMPHONY_SECRETARY_AGENT_ID });
1630
1679
  const routeTargetAgent = agentResource.buildIri(webId, {
1631
- id: buildWorkerAgentId(plan.session.backend, plan.session.target?.agent),
1680
+ id: buildWorkerAgentId(plan.session.backend, plan.session.target?.agent, plan.session.target?.contact),
1632
1681
  });
1633
1682
  return {
1634
1683
  id: `${buildSymphonyThreadId(plan)}-${stage}`,
@@ -1656,6 +1705,7 @@ function buildStatusMessageRow(plan, webId, stage) {
1656
1705
  session: worker.session.uri,
1657
1706
  backend: worker.session.backend,
1658
1707
  agent: worker.session.target.agent,
1708
+ contact: worker.session.target.contact ?? buildWorkerContactId(worker),
1659
1709
  status: worker.session.status,
1660
1710
  autoModeSessionId: worker.session.autoModeSessionId,
1661
1711
  })),
@@ -1693,9 +1743,7 @@ function buildSymphonyReportInboxNotificationRow(webId, worker) {
1693
1743
  const createdAt = safeDate(worker.session.completedAt ?? worker.session.updatedAt);
1694
1744
  return {
1695
1745
  id: stableReportInboxNotificationId(worker),
1696
- actor: agentResource.buildIri(webId, {
1697
- id: buildWorkerAgentId(worker.session.backend, worker.session.target.agent),
1698
- }),
1746
+ actor: buildWorkerContactIri(webId, worker),
1699
1747
  object: buildSymphonyReportDeliveryIri(webId, worker),
1700
1748
  createdAt,
1701
1749
  };