@agentrix/shared 1.0.5 → 1.0.7

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.
package/dist/index.cjs CHANGED
@@ -71,10 +71,10 @@ const SignatureAuthRequestSchema = zod.z.object({
71
71
  // Base64-encoded random challenge
72
72
  signature: zod.z.string(),
73
73
  // Base64-encoded Ed25519 signature
74
- salt: zod.z.string(),
75
- // Salt for PIN code encryption (base64)
76
- encryptedSecret: zod.z.string()
77
- // Encrypted secret (base64)
74
+ salt: zod.z.string().optional(),
75
+ // Salt for password encryption (base64) - optional, set after login
76
+ encryptedSecret: zod.z.string().optional()
77
+ // Encrypted secret (base64) - optional, set after login
78
78
  });
79
79
  const SignatureAuthResponseSchema = zod.z.object({
80
80
  token: zod.z.string(),
@@ -82,8 +82,10 @@ const SignatureAuthResponseSchema = zod.z.object({
82
82
  });
83
83
  const UserProfileResponseSchema = zod.z.object({
84
84
  user: UserBasicInfoSchema.extend({
85
- encryptedSecret: zod.z.string(),
86
- secretSalt: zod.z.string(),
85
+ encryptedSecret: zod.z.string().nullable(),
86
+ // Can be null before password is set
87
+ secretSalt: zod.z.string().nullable(),
88
+ // Can be null before password is set
87
89
  createdAt: DateSchema,
88
90
  oauthAccounts: zod.z.array(OAuthAccountInfoSchema).optional()
89
91
  })
@@ -113,10 +115,10 @@ const OAuthLoginQuerySchema = zod.z.object({
113
115
  // Base64-encoded random challenge
114
116
  signatureProof: zod.z.string(),
115
117
  // Base64-encoded Ed25519 signature
116
- salt: zod.z.string(),
117
- // Salt for PIN code encryption (base64)
118
- encryptedSecret: zod.z.string()
119
- // Encrypted secret (base64)
118
+ salt: zod.z.string().optional(),
119
+ // Salt for password encryption (base64) - optional, set after login
120
+ encryptedSecret: zod.z.string().optional()
121
+ // Encrypted secret (base64) - optional, set after login
120
122
  });
121
123
  const OAuthCallbackQuerySchema = zod.z.object({
122
124
  code: zod.z.string(),
@@ -198,6 +200,8 @@ const StartTaskRequestSchema = zod.z.object({
198
200
  repositoryId: zod.z.string().optional(),
199
201
  baseBranch: zod.z.string().optional(),
200
202
  // Base branch for the repository
203
+ repositorySourceType: zod.z.enum(["temporary", "directory", "git-server"]).optional(),
204
+ // Repository source type
201
205
  dataEncryptionKey: zod.z.string().optional()
202
206
  // base64 sealed-box: app public key encrypted by machine public key
203
207
  }).refine((data) => data.machineId || data.cloudId, {
@@ -247,6 +251,8 @@ const TaskItemSchema = zod.z.object({
247
251
  dataEncryptionKey: zod.z.string().nullable(),
248
252
  cwd: zod.z.string().nullable(),
249
253
  // Current working directory from CLI worker
254
+ repositorySourceType: zod.z.enum(["temporary", "directory", "git-server"]).nullable(),
255
+ // Repository source type
250
256
  pullRequestNumber: zod.z.number().nullable(),
251
257
  pullRequestUrl: zod.z.string().nullable(),
252
258
  pullRequestState: zod.z.enum(["open", "closed", "merged"]).nullable(),
@@ -258,6 +264,8 @@ const TaskItemSchema = zod.z.object({
258
264
  totalDeletions: zod.z.number(),
259
265
  files: zod.z.array(FileStatsSchema)
260
266
  }).nullable(),
267
+ totalDuration: zod.z.number().nullable(),
268
+ // Cumulative execution time (milliseconds)
261
269
  createdAt: zod.z.string(),
262
270
  // ISO 8601 string
263
271
  updatedAt: zod.z.string()
@@ -860,6 +868,41 @@ const GitServerSchema = zod.z.object({
860
868
  const ListGitServersResponseSchema = zod.z.array(GitServerSchema);
861
869
  const GetGitServerResponseSchema = GitServerSchema;
862
870
 
871
+ const AskUserOptionSchema = zod.z.object({
872
+ label: zod.z.string(),
873
+ // Option label (1-5 words)
874
+ description: zod.z.string()
875
+ // Option explanation
876
+ });
877
+ const AskUserQuestionSchema = zod.z.object({
878
+ question: zod.z.string(),
879
+ // Complete question text
880
+ header: zod.z.string().max(12),
881
+ // Short label (max 12 chars)
882
+ multiSelect: zod.z.boolean(),
883
+ // Allow multiple selections
884
+ options: zod.z.array(AskUserOptionSchema).min(2).max(5)
885
+ // 2-5 options (CLI may add "Other")
886
+ });
887
+ const AskUserMessageSchema = zod.z.object({
888
+ type: zod.z.literal("ask_user"),
889
+ questions: zod.z.array(AskUserQuestionSchema).min(1).max(4)
890
+ // 1-4 questions
891
+ });
892
+ const AskUserResponseMessageSchema = zod.z.object({
893
+ type: zod.z.literal("ask_user_response"),
894
+ answers: zod.z.array(zod.z.string())
895
+ // Array of answers (labels), one per question
896
+ });
897
+ function isAskUserMessage(message) {
898
+ return typeof message === "object" && message !== null && "type" in message && message.type === "ask_user";
899
+ }
900
+ function isAskUserResponseMessage(message) {
901
+ return typeof message === "object" && message !== null && "type" in message && message.type === "ask_user_response";
902
+ }
903
+ function isSDKMessage(message) {
904
+ return typeof message === "object" && message !== null && "type" in message && message.type !== "ask_user" && message.type !== "ask_user_response";
905
+ }
863
906
  const EventBaseSchema = zod.z.object({
864
907
  eventId: zod.z.string()
865
908
  });
@@ -895,7 +938,9 @@ const WorkerInitializingSchema = EventBaseSchema.extend({
895
938
  const WorkerReadySchema = EventBaseSchema.extend({
896
939
  taskId: zod.z.string(),
897
940
  machineId: zod.z.string(),
898
- timestamp: zod.z.string()
941
+ timestamp: zod.z.string(),
942
+ duration: zod.z.number().optional()
943
+ // Duration of this execution round (milliseconds)
899
944
  });
900
945
  const WorkerAliveEventSchema = EventBaseSchema.extend({
901
946
  taskId: zod.z.string(),
@@ -986,12 +1031,14 @@ const StopTaskSchema = EventBaseSchema.extend({
986
1031
  const TaskMessageSchema = EventBaseSchema.extend({
987
1032
  taskId: zod.z.string(),
988
1033
  from: zod.z.enum(["app", "api-server", "machine", "worker"]),
1034
+ opCode: zod.z.string().optional(),
1035
+ // eventId of the message this is responding to (e.g., ask_user_response → ask_user)
989
1036
  message: zod.z.custom(
990
1037
  (data) => {
991
1038
  return typeof data === "object" && data !== null && "type" in data;
992
1039
  },
993
1040
  {
994
- message: "Invalid SDKMessage format"
1041
+ message: "Invalid TaskMessagePayload format"
995
1042
  }
996
1043
  ).optional(),
997
1044
  encryptedMessage: zod.z.string().optional()
@@ -1004,18 +1051,6 @@ const TaskMessageSchema = EventBaseSchema.extend({
1004
1051
  message: "Exactly one of message or encryptedMessage must be provided"
1005
1052
  }
1006
1053
  );
1007
- const RequirePermissionSchema = EventBaseSchema.extend({
1008
- taskId: zod.z.string(),
1009
- toolName: zod.z.string(),
1010
- toolInput: zod.z.record(zod.z.unknown())
1011
- });
1012
- const RequirePermissionResponseSchema = EventBaseSchema.extend({
1013
- taskId: zod.z.string(),
1014
- opCode: zod.z.string(),
1015
- // Echoed back, equals to eventId in RequirePermissionRequest
1016
- behavior: zod.z.enum(["allow", "deny"]),
1017
- message: zod.z.string().optional()
1018
- });
1019
1054
  const TaskArtifactsUpdatedEventSchema = EventBaseSchema.extend({
1020
1055
  taskId: zod.z.string(),
1021
1056
  commitHash: zod.z.string(),
@@ -1163,10 +1198,6 @@ const EventSchemaMap = {
1163
1198
  "update-task-agent-session-id": UpdateTaskAgentSessionIdEventSchema,
1164
1199
  // Artifacts events
1165
1200
  "task-artifacts-updated": TaskArtifactsUpdatedEventSchema,
1166
- // Permission events
1167
- "require-permission": RequirePermissionSchema,
1168
- "require-permission-response": RequirePermissionResponseSchema,
1169
- // Git operation events
1170
1201
  // Merge request events
1171
1202
  "merge-request": MergeRequestEventSchema,
1172
1203
  // System message events
@@ -1187,7 +1218,6 @@ const workerTaskEvents = [
1187
1218
  "change-task-title",
1188
1219
  "update-task-agent-session-id",
1189
1220
  "task-artifacts-updated",
1190
- "require-permission",
1191
1221
  "merge-request"
1192
1222
  ];
1193
1223
 
@@ -1231,20 +1261,6 @@ const AgentMetadataSchema = zod.z.object({
1231
1261
  version: zod.z.string(),
1232
1262
  description: zod.z.string().optional()
1233
1263
  });
1234
- const MCPServerConfigSchema = zod.z.object({
1235
- name: zod.z.string(),
1236
- command: zod.z.string().optional(),
1237
- args: zod.z.array(zod.z.string()).optional(),
1238
- env: zod.z.record(zod.z.string()).optional(),
1239
- url: zod.z.string().url().optional(),
1240
- transport: zod.z.enum(["stdio", "http"]).optional()
1241
- });
1242
- const SkillConfigSchema = zod.z.object({
1243
- name: zod.z.string(),
1244
- description: zod.z.string().optional(),
1245
- enabled: zod.z.boolean(),
1246
- implementation: zod.z.string().optional()
1247
- });
1248
1264
  const ClaudeConfigSchema = zod.z.object({
1249
1265
  // SDK native model configuration
1250
1266
  model: zod.z.string().optional(),
@@ -1260,13 +1276,9 @@ const ClaudeConfigSchema = zod.z.object({
1260
1276
  permissionMode: zod.z.enum(["default", "acceptEdits", "bypassPermissions", "plan"]).optional(),
1261
1277
  allowedTools: zod.z.array(zod.z.string()).optional()
1262
1278
  }).optional(),
1263
- mcpServers: zod.z.object({
1264
- enabled: zod.z.array(zod.z.string()),
1265
- directory: zod.z.string()
1266
- }).optional(),
1267
- skills: zod.z.object({
1268
- enabled: zod.z.array(zod.z.string()),
1269
- directory: zod.z.string()
1279
+ pullRequestPrompt: zod.z.object({
1280
+ path: zod.z.string(),
1281
+ mode: zod.z.enum(["append", "replace"]).optional().default("append")
1270
1282
  }).optional()
1271
1283
  });
1272
1284
 
@@ -1372,71 +1384,15 @@ function assertAgentExists(agentDir, agentId) {
1372
1384
  }
1373
1385
  }
1374
1386
 
1375
- async function loadMcpServers(mcpServersDir, enabledServers) {
1376
- const loaded = {};
1377
- if (!node_fs.existsSync(mcpServersDir)) {
1378
- return loaded;
1387
+ function discoverPlugins(pluginsDir) {
1388
+ if (!node_fs.existsSync(pluginsDir)) {
1389
+ return [];
1379
1390
  }
1380
- const serverDirs = node_fs.readdirSync(mcpServersDir, { withFileTypes: true }).filter((dirent) => dirent.isDirectory()).map((dirent) => dirent.name);
1381
- for (const serverName of enabledServers) {
1382
- if (!serverDirs.includes(serverName)) {
1383
- throw new AgentLoadError(
1384
- `MCP server "${serverName}" is enabled but directory not found`
1385
- );
1386
- }
1387
- const serverDir = node_path.join(mcpServersDir, serverName);
1388
- try {
1389
- const config = await loadMcpServerConfig(serverDir, serverName);
1390
- const instance = await createMcpServerInstance(config);
1391
- loaded[serverName] = {
1392
- name: serverName,
1393
- config,
1394
- instance
1395
- };
1396
- } catch (error) {
1397
- throw new AgentLoadError(
1398
- `Failed to load MCP server "${serverName}": ${error instanceof Error ? error.message : String(error)}`,
1399
- error instanceof Error ? error : void 0
1400
- );
1401
- }
1402
- }
1403
- return loaded;
1391
+ return node_fs.readdirSync(pluginsDir, { withFileTypes: true }).filter((dirent) => dirent.isDirectory()).map((dirent) => node_path.join(pluginsDir, dirent.name)).filter((pluginPath) => isValidPluginDirectory(pluginPath));
1404
1392
  }
1405
- async function loadMcpServerConfig(serverDir, serverName) {
1406
- const configPath = node_path.join(serverDir, "config.json");
1407
- if (!node_fs.existsSync(configPath)) {
1408
- throw new AgentLoadError(`MCP server "${serverName}" missing config.json`);
1409
- }
1410
- try {
1411
- const content = node_fs.readFileSync(configPath, "utf-8");
1412
- const rawConfig = JSON.parse(content);
1413
- const validatedConfig = MCPServerConfigSchema.parse(rawConfig);
1414
- return validatedConfig;
1415
- } catch (error) {
1416
- if (error instanceof SyntaxError) {
1417
- throw new AgentConfigValidationError(
1418
- `Invalid JSON in MCP server config: ${serverName}`
1419
- );
1420
- }
1421
- throw new AgentConfigValidationError(
1422
- `Invalid MCP server configuration for "${serverName}": ${error instanceof Error ? error.message : String(error)}`
1423
- );
1424
- }
1425
- }
1426
- async function createMcpServerInstance(config) {
1427
- if (config.transport === "stdio" && config.command) {
1428
- throw new AgentLoadError(
1429
- "stdio transport for MCP servers not yet implemented. Use inline MCP servers for now."
1430
- );
1431
- }
1432
- if (config.transport === "http" && config.url) {
1433
- throw new AgentLoadError(
1434
- "HTTP transport for MCP servers not yet implemented"
1435
- );
1436
- }
1437
- throw new AgentLoadError(
1438
- `Cannot create MCP server instance: unsupported configuration for "${config.name}"`
1439
- );
1393
+ function isValidPluginDirectory(pluginDir) {
1394
+ const manifestPath = node_path.join(pluginDir, ".claude-plugin", "plugin.json");
1395
+ return node_fs.existsSync(manifestPath);
1440
1396
  }
1441
1397
 
1442
1398
  async function loadAgentConfig(options) {
@@ -1506,19 +1462,17 @@ async function loadClaudeConfiguration(agentDir, metadata) {
1506
1462
  if (config.systemPrompt) {
1507
1463
  systemPrompt = await loadSystemPrompt(claudeDir, config.systemPrompt.path);
1508
1464
  }
1509
- const mcpServers = config.mcpServers ? await loadMcpServers(
1510
- node_path.join(claudeDir, config.mcpServers.directory),
1511
- config.mcpServers.enabled
1512
- ) : {};
1513
- const skills = config.skills ? await loadSkills(
1514
- node_path.join(claudeDir, config.skills.directory),
1515
- config.skills.enabled
1516
- ) : [];
1465
+ let prPromptTemplate;
1466
+ if (config.pullRequestPrompt) {
1467
+ prPromptTemplate = await loadSystemPrompt(claudeDir, config.pullRequestPrompt.path);
1468
+ }
1469
+ const pluginsDir = node_path.join(claudeDir, "plugins");
1470
+ const plugins = discoverPlugins(pluginsDir);
1517
1471
  return {
1518
1472
  config,
1519
1473
  systemPrompt,
1520
- mcpServers,
1521
- skills
1474
+ prPromptTemplate,
1475
+ plugins
1522
1476
  };
1523
1477
  }
1524
1478
  async function loadClaudeConfig(claudeDir) {
@@ -1553,43 +1507,6 @@ async function loadSystemPrompt(claudeDir, promptFile) {
1553
1507
  );
1554
1508
  }
1555
1509
  }
1556
- async function loadSkills(skillsDir, enabledSkills) {
1557
- const skills = [];
1558
- if (!node_fs.existsSync(skillsDir)) {
1559
- return skills;
1560
- }
1561
- const skillDirs = node_fs.readdirSync(skillsDir, { withFileTypes: true }).filter((dirent) => dirent.isDirectory()).map((dirent) => dirent.name);
1562
- for (const skillName of enabledSkills) {
1563
- if (!skillDirs.includes(skillName)) {
1564
- throw new AgentLoadError(
1565
- `Skill "${skillName}" is enabled but directory not found`
1566
- );
1567
- }
1568
- const skillDir = node_path.join(skillsDir, skillName);
1569
- const skillConfigPath = node_path.join(skillDir, "skill.json");
1570
- if (!node_fs.existsSync(skillConfigPath)) {
1571
- throw new MissingAgentFileError(
1572
- `skills/${skillName}/skill.json`
1573
- );
1574
- }
1575
- try {
1576
- const content = node_fs.readFileSync(skillConfigPath, "utf-8");
1577
- const rawSkill = JSON.parse(content);
1578
- const skill = SkillConfigSchema.parse(rawSkill);
1579
- skills.push(skill);
1580
- } catch (error) {
1581
- if (error instanceof SyntaxError) {
1582
- throw new AgentConfigValidationError(
1583
- `Invalid JSON in skills/${skillName}/skill.json`
1584
- );
1585
- }
1586
- throw new AgentConfigValidationError(
1587
- `Invalid skill configuration for "${skillName}": ${error instanceof Error ? error.message : String(error)}`
1588
- );
1589
- }
1590
- }
1591
- return skills;
1592
- }
1593
1510
 
1594
1511
  const cryptoModule = typeof globalThis.crypto !== "undefined" ? globalThis.crypto : (async () => {
1595
1512
  try {
@@ -1614,7 +1531,11 @@ async function hmac_sha512(key, data) {
1614
1531
  false,
1615
1532
  ["sign"]
1616
1533
  );
1617
- const signature = await crypto.subtle.sign("HMAC", cryptoKey, data);
1534
+ const signature = await crypto.subtle.sign(
1535
+ "HMAC",
1536
+ cryptoKey,
1537
+ data
1538
+ );
1618
1539
  return new Uint8Array(signature);
1619
1540
  }
1620
1541
 
@@ -1836,6 +1757,10 @@ exports.AppAliveEventSchema = AppAliveEventSchema;
1836
1757
  exports.ApprovalStatusResponseSchema = ApprovalStatusResponseSchema;
1837
1758
  exports.ArchiveTaskRequestSchema = ArchiveTaskRequestSchema;
1838
1759
  exports.ArchiveTaskResponseSchema = ArchiveTaskResponseSchema;
1760
+ exports.AskUserMessageSchema = AskUserMessageSchema;
1761
+ exports.AskUserOptionSchema = AskUserOptionSchema;
1762
+ exports.AskUserQuestionSchema = AskUserQuestionSchema;
1763
+ exports.AskUserResponseMessageSchema = AskUserResponseMessageSchema;
1839
1764
  exports.BillingStatsResponseSchema = BillingStatsResponseSchema;
1840
1765
  exports.BranchSchema = BranchSchema;
1841
1766
  exports.CancelTaskRequestSchema = CancelTaskRequestSchema;
@@ -1916,7 +1841,6 @@ exports.ListTransactionsQuerySchema = ListTransactionsQuerySchema;
1916
1841
  exports.ListTransactionsResponseSchema = ListTransactionsResponseSchema;
1917
1842
  exports.LocalMachineSchema = LocalMachineSchema;
1918
1843
  exports.LogoutResponseSchema = LogoutResponseSchema;
1919
- exports.MCPServerConfigSchema = MCPServerConfigSchema;
1920
1844
  exports.MachineAliveEventSchema = MachineAliveEventSchema;
1921
1845
  exports.MachineApprovalRequestSchema = MachineApprovalRequestSchema;
1922
1846
  exports.MachineApprovalStatusQuerySchema = MachineApprovalStatusQuerySchema;
@@ -1944,8 +1868,6 @@ exports.QueryEventsRequestSchema = QueryEventsRequestSchema;
1944
1868
  exports.RechargeResponseSchema = RechargeResponseSchema;
1945
1869
  exports.RemoveChatMemberRequestSchema = RemoveChatMemberRequestSchema;
1946
1870
  exports.RepositorySchema = RepositorySchema;
1947
- exports.RequirePermissionResponseSchema = RequirePermissionResponseSchema;
1948
- exports.RequirePermissionSchema = RequirePermissionSchema;
1949
1871
  exports.ResetSecretRequestSchema = ResetSecretRequestSchema;
1950
1872
  exports.ResetSecretResponseSchema = ResetSecretResponseSchema;
1951
1873
  exports.ResumeTaskRequestSchema = ResumeTaskRequestSchema;
@@ -1954,7 +1876,6 @@ exports.ShutdownMachineSchema = ShutdownMachineSchema;
1954
1876
  exports.SignatureAuthRequestSchema = SignatureAuthRequestSchema;
1955
1877
  exports.SignatureAuthResponseSchema = SignatureAuthResponseSchema;
1956
1878
  exports.SimpleSuccessSchema = SimpleSuccessSchema;
1957
- exports.SkillConfigSchema = SkillConfigSchema;
1958
1879
  exports.StartTaskRequestSchema = StartTaskRequestSchema;
1959
1880
  exports.StartTaskResponseSchema = StartTaskResponseSchema;
1960
1881
  exports.StatsQuerySchema = StatsQuerySchema;
@@ -2008,6 +1929,7 @@ exports.decryptFileContent = decryptFileContent;
2008
1929
  exports.decryptMachineEncryptionKey = decryptMachineEncryptionKey;
2009
1930
  exports.decryptSdkMessage = decryptSdkMessage;
2010
1931
  exports.decryptWithEphemeralKey = decryptWithEphemeralKey;
1932
+ exports.discoverPlugins = discoverPlugins;
2011
1933
  exports.encodeBase64 = encodeBase64;
2012
1934
  exports.encodeBase64Url = encodeBase64Url;
2013
1935
  exports.encryptAES = encryptAES;
@@ -2019,8 +1941,10 @@ exports.generateAESKey = generateAESKey;
2019
1941
  exports.generateAESKeyBase64 = generateAESKeyBase64;
2020
1942
  exports.getAgentContext = getAgentContext;
2021
1943
  exports.getRandomBytes = getRandomBytes;
1944
+ exports.isAskUserMessage = isAskUserMessage;
1945
+ exports.isAskUserResponseMessage = isAskUserResponseMessage;
1946
+ exports.isSDKMessage = isSDKMessage;
2022
1947
  exports.loadAgentConfig = loadAgentConfig;
2023
- exports.loadMcpServers = loadMcpServers;
2024
1948
  exports.machineAuth = machineAuth;
2025
1949
  exports.permissionResponseRequestSchema = permissionResponseRequestSchema;
2026
1950
  exports.resumeTaskRequestSchema = resumeTaskRequestSchema;