@skilder-ai/runtime 0.7.2 → 0.7.4

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.js CHANGED
@@ -137966,7 +137966,7 @@ var RuntimeCallToolResponse = class extends NatsResponse {
137966
137966
  this.type = type7;
137967
137967
  }
137968
137968
  validate(data) {
137969
- return data.result !== void 0 && data.executedByIdOrAgent !== void 0;
137969
+ return data.result !== void 0 && data.executedBy !== void 0;
137970
137970
  }
137971
137971
  };
137972
137972
  NatsMessage.register(RuntimeCallToolResponse);
@@ -138347,7 +138347,6 @@ __export(dgraph_resolvers_types_exports, {
138347
138347
  OAuthProviderType: () => OAuthProviderType,
138348
138348
  OnboardingStepStatus: () => OnboardingStepStatus,
138349
138349
  OnboardingStepType: () => OnboardingStepType,
138350
- RuntimeType: () => RuntimeType,
138351
138350
  ScriptType: () => ScriptType,
138352
138351
  ToolCallStatus: () => ToolCallStatus,
138353
138352
  WorkspaceRole: () => WorkspaceRole
@@ -138443,11 +138442,6 @@ var OnboardingStepType = /* @__PURE__ */ ((OnboardingStepType2) => {
138443
138442
  OnboardingStepType2["Onboarding"] = "ONBOARDING";
138444
138443
  return OnboardingStepType2;
138445
138444
  })(OnboardingStepType || {});
138446
- var RuntimeType = /* @__PURE__ */ ((RuntimeType2) => {
138447
- RuntimeType2["Edge"] = "EDGE";
138448
- RuntimeType2["Mcp"] = "MCP";
138449
- return RuntimeType2;
138450
- })(RuntimeType || {});
138451
138445
  var ScriptType = /* @__PURE__ */ ((ScriptType3) => {
138452
138446
  ScriptType3["Bash"] = "BASH";
138453
138447
  ScriptType3["Javascript"] = "JAVASCRIPT";
@@ -138467,6 +138461,34 @@ var WorkspaceRole = /* @__PURE__ */ ((WorkspaceRole2) => {
138467
138461
  return WorkspaceRole2;
138468
138462
  })(WorkspaceRole || {});
138469
138463
 
138464
+ // ../common/src/utils/parse-script-args.ts
138465
+ function parseScriptArgs(argsString) {
138466
+ const args = [];
138467
+ let current = "";
138468
+ let inQuotes = false;
138469
+ let quoteChar = "";
138470
+ for (const char of argsString) {
138471
+ if ((char === '"' || char === "'") && !inQuotes) {
138472
+ inQuotes = true;
138473
+ quoteChar = char;
138474
+ } else if (char === quoteChar && inQuotes) {
138475
+ inQuotes = false;
138476
+ quoteChar = "";
138477
+ } else if (char === " " && !inQuotes) {
138478
+ if (current) {
138479
+ args.push(current);
138480
+ current = "";
138481
+ }
138482
+ } else {
138483
+ current += char;
138484
+ }
138485
+ }
138486
+ if (current) {
138487
+ args.push(current);
138488
+ }
138489
+ return args;
138490
+ }
138491
+
138470
138492
  // ../common/src/related-content-detector.ts
138471
138493
  function escapeRegex2(str) {
138472
138494
  return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
@@ -144826,39 +144848,9 @@ For other resources, use the \`learn\` tool instead.`
144826
144848
  };
144827
144849
  }
144828
144850
  const script = scriptEntry;
144829
- const args = lookupArgs ? this.parseScriptArgs(lookupArgs) : [];
144851
+ const args = lookupArgs ? parseScriptArgs(lookupArgs) : [];
144830
144852
  return await this.routeScriptToRuntime(script, skill, args);
144831
144853
  }
144832
- /**
144833
- * Parse script arguments from the path string.
144834
- * Arguments can be space-separated, with quoted strings supported.
144835
- */
144836
- parseScriptArgs(argsString) {
144837
- const args = [];
144838
- let current = "";
144839
- let inQuotes = false;
144840
- let quoteChar = "";
144841
- for (const char of argsString) {
144842
- if ((char === '"' || char === "'") && !inQuotes) {
144843
- inQuotes = true;
144844
- quoteChar = char;
144845
- } else if (char === quoteChar && inQuotes) {
144846
- inQuotes = false;
144847
- quoteChar = "";
144848
- } else if (char === " " && !inQuotes) {
144849
- if (current) {
144850
- args.push(current);
144851
- current = "";
144852
- }
144853
- } else {
144854
- current += char;
144855
- }
144856
- }
144857
- if (current) {
144858
- args.push(current);
144859
- }
144860
- return args;
144861
- }
144862
144854
  /**
144863
144855
  * Route script execution to a runtime via NATS.
144864
144856
  * Scripts always execute on the runtime linked to the script.
@@ -145184,34 +145176,68 @@ This file can be used with other file I/O tools that accept \`@skilder-file:/\`
145184
145176
  const lines = [];
145185
145177
  lines.push(`# Skill: ${skill.name}`);
145186
145178
  lines.push("");
145179
+ lines.push(...this.formatSkillDetails(skill));
145180
+ return {
145181
+ response: { content: [{ type: "text", text: lines.join("\n") }] },
145182
+ skillIds: [skill.id]
145183
+ };
145184
+ }
145185
+ /**
145186
+ * Format full details for a single skill including description, instructions, tool schemas,
145187
+ * and referenced resources. Used by both handleLearnSkill and handleGetHat to ensure DRY
145188
+ * consistency when rendering skill content.
145189
+ *
145190
+ * @param skill - The skill catalog entry to format
145191
+ * @param options.headingLevel - Heading level for tools section (2 for standalone, 4 for within-hat)
145192
+ * @param options.renderedToolNames - Set of tool names already rendered (for deduplication across skills in a hat)
145193
+ */
145194
+ formatSkillDetails(skill, options) {
145195
+ const headingLevel = options?.headingLevel ?? 2;
145196
+ const heading = "#".repeat(headingLevel);
145197
+ const renderedToolNames = options?.renderedToolNames;
145198
+ const firstSkillForTool = options?.firstSkillForTool;
145199
+ const lines = [];
145187
145200
  if (skill.description) {
145188
145201
  lines.push(skill.description);
145189
145202
  lines.push("");
145190
145203
  }
145191
145204
  if (skill.instructions) {
145192
- lines.push("## Instructions");
145205
+ lines.push(`${heading} Instructions`);
145193
145206
  lines.push(skill.instructions);
145194
145207
  lines.push("");
145195
145208
  }
145196
145209
  if (skill.toolNames.length > 0) {
145197
- lines.push("## Available Tools");
145210
+ lines.push(`${heading} Available Tools`);
145198
145211
  lines.push("Use `call_tool` with the tool name and input to execute these tools:");
145199
145212
  lines.push("");
145200
145213
  for (const toolName of skill.toolNames) {
145201
- const tool2 = this.tools.getValue()?.find((t4) => t4.name === toolName);
145202
- if (tool2) {
145203
- lines.push(`### ${tool2.name}`);
145204
- lines.push(tool2.description || "No description");
145205
- lines.push("");
145206
- lines.push("**Input Schema:**");
145207
- lines.push("```json");
145208
- lines.push(JSON.stringify(tool2.inputSchema, null, 2));
145209
- lines.push("```");
145214
+ const subHeading = "#".repeat(headingLevel + 1);
145215
+ if (renderedToolNames?.has(toolName)) {
145216
+ const firstSkill = firstSkillForTool?.get(toolName);
145217
+ lines.push(`${subHeading} ${toolName}`);
145218
+ lines.push(firstSkill ? `(schema shown above under ${firstSkill})` : "(schema shown above)");
145210
145219
  lines.push("");
145211
145220
  } else {
145212
- lines.push(`### ${toolName}`);
145213
- lines.push("Tool definition not available");
145214
- lines.push("");
145221
+ if (renderedToolNames) {
145222
+ renderedToolNames.add(toolName);
145223
+ firstSkillForTool?.set(toolName, skill.name);
145224
+ }
145225
+ const tool2 = this.tools.getValue()?.find((t4) => t4.name === toolName);
145226
+ if (tool2) {
145227
+ lines.push(`${subHeading} ${tool2.name}`);
145228
+ lines.push(tool2.description || "No description");
145229
+ lines.push("");
145230
+ lines.push("**Input Schema:**");
145231
+ lines.push("```json");
145232
+ lines.push(JSON.stringify(tool2.inputSchema, null, 2));
145233
+ lines.push("```");
145234
+ lines.push("");
145235
+ } else {
145236
+ this.logger.warn({ toolName, skillId: skill.id, toolsInitialized: this.tools.getValue() != null }, `Tool "${toolName}" referenced by skill "${skill.name}" not found in tools list`);
145237
+ lines.push(`${subHeading} ${toolName}`);
145238
+ lines.push("Tool definition not available");
145239
+ lines.push("");
145240
+ }
145215
145241
  }
145216
145242
  }
145217
145243
  lines.push('Call these tools using: `call_tool(tool_name="<name>", tool_input={...})`');
@@ -145227,10 +145253,7 @@ This file can be used with other file I/O tools that accept \`@skilder-file:/\`
145227
145253
  } catch (error48) {
145228
145254
  this.logger.warn({ error: error48, skillId: skill.id }, "Failed to detect related mentions in skill instructions");
145229
145255
  }
145230
- return {
145231
- response: { content: [{ type: "text", text: lines.join("\n") }] },
145232
- skillIds: [skill.id]
145233
- };
145256
+ return lines;
145234
145257
  }
145235
145258
  /**
145236
145259
  * Handle feedback_skill tool call.
@@ -145502,27 +145525,19 @@ ${JSON.stringify(toolConfig.inputSchema, null, 2)}`
145502
145525
  }
145503
145526
  this.session.learnedHatIds.add(hat.id);
145504
145527
  const skills = [];
145505
- const allToolNames = /* @__PURE__ */ new Set();
145506
145528
  const missingSkillIds = [];
145507
145529
  for (const skillId of hat.skillIds) {
145508
145530
  const skill = this.catalog.skills.find((s) => s.id === skillId);
145509
145531
  if (skill) {
145510
145532
  this.session.learnedSkillIds.add(skill.id);
145511
- skills.push({
145512
- name: skill.name,
145513
- description: skill.description,
145514
- instructions: skill.instructions,
145515
- toolNames: skill.toolNames
145516
- });
145517
- for (const toolName of skill.toolNames) {
145518
- allToolNames.add(toolName);
145519
- }
145533
+ skills.push(skill);
145520
145534
  } else {
145521
- this.logger.warn(`Skill ID "${skillId}" referenced in hat "${hat.name}" not found in catalog`);
145535
+ this.logger.warn({ skillId, hatId: hat.id, hatName: hat.name }, "Skill referenced in hat not found in catalog");
145522
145536
  missingSkillIds.push(skillId);
145523
145537
  }
145524
145538
  }
145525
- this.logger.info(`User ${this.identity.id} retrieved hat "${hat.name}" with ${skills.length} skills and ${allToolNames.size} tools`);
145539
+ const totalToolCount = new Set(skills.flatMap((s) => s.toolNames)).size;
145540
+ this.logger.info(`User ${this.identity.id} retrieved hat "${hat.name}" with ${skills.length} skills and ${totalToolCount} tools`);
145526
145541
  const lines = [];
145527
145542
  lines.push(`# Hat: ${hat.name}`);
145528
145543
  lines.push("");
@@ -145538,43 +145553,18 @@ ${JSON.stringify(toolConfig.inputSchema, null, 2)}`
145538
145553
  if (skills.length > 0) {
145539
145554
  lines.push("## Skills Learned");
145540
145555
  lines.push("");
145556
+ const renderedToolNames = /* @__PURE__ */ new Set();
145557
+ const firstSkillForTool = /* @__PURE__ */ new Map();
145541
145558
  for (const skill of skills) {
145542
145559
  lines.push(`### ${skill.name}`);
145543
- if (skill.description) {
145544
- lines.push(skill.description);
145545
- }
145546
- if (skill.instructions) {
145547
- lines.push("");
145548
- lines.push("**Instructions:**");
145549
- lines.push(skill.instructions);
145550
- }
145551
- if (skill.toolNames.length > 0) {
145552
- lines.push("");
145553
- lines.push(`**Tools:** ${skill.toolNames.join(", ")}`);
145554
- }
145560
+ lines.push(...this.formatSkillDetails(skill, { headingLevel: 4, renderedToolNames, firstSkillForTool }));
145555
145561
  lines.push("");
145556
145562
  }
145557
145563
  } else {
145558
145564
  lines.push("This hat contains no skills.");
145559
145565
  lines.push("");
145560
145566
  }
145561
- if (allToolNames.size > 0) {
145562
- lines.push("## All Available Tools");
145563
- lines.push("");
145564
- lines.push("The following tools are now available:");
145565
- for (const toolName of allToolNames) {
145566
- const tool2 = this.tools.getValue()?.find((t4) => t4.name === toolName);
145567
- if (tool2) {
145568
- lines.push(`- **${tool2.name}**: ${tool2.description || "No description"}`);
145569
- } else {
145570
- lines.push(`- **${toolName}**`);
145571
- }
145572
- }
145573
- lines.push("");
145574
- lines.push("You can now use these tools to help the user.");
145575
- }
145576
145567
  if (missingSkillIds.length > 0) {
145577
- lines.push("");
145578
145568
  lines.push("## Warning");
145579
145569
  lines.push("");
145580
145570
  lines.push(`Some skills referenced by this hat could not be loaded: ${missingSkillIds.join(", ")}`);
@@ -145842,10 +145832,6 @@ var McpStdioService = class McpStdioService2 extends Service {
145842
145832
  if (!identity || !identity.name) {
145843
145833
  throw new Error("Cannot start MCP server: identity not found or incomplete");
145844
145834
  }
145845
- this.clientInfo = {
145846
- name: request.params.clientInfo.name,
145847
- version: request.params.clientInfo.version
145848
- };
145849
145835
  this.logger.info(`Setting MCP client name to ${request.params.clientInfo.name}`);
145850
145836
  if (request.params.capabilities.roots) {
145851
145837
  this.clientCapabilities.roots = { listChanged: request.params.capabilities.roots.listChanged ?? false };
@@ -145922,7 +145908,6 @@ var McpStdioService = class McpStdioService2 extends Service {
145922
145908
  }
145923
145909
  this.server = void 0;
145924
145910
  this.transport = void 0;
145925
- this.clientInfo = void 0;
145926
145911
  }
145927
145912
  getClientRoots() {
145928
145913
  return this.clientRoots.getValue();
@@ -152626,7 +152611,6 @@ var ToolService = class ToolService2 extends Service {
152626
152611
  this.oauthTokenService = oauthTokenService;
152627
152612
  this.oauthClientInfoService = oauthClientInfoService;
152628
152613
  this.mcpStdioService = mcpStdioService;
152629
- this.runtimeExecutionId = runtimeExecutionId;
152630
152614
  this.scriptExecutorService = scriptExecutorService;
152631
152615
  this.delegateService = delegateService;
152632
152616
  this.name = "tool";
@@ -152731,27 +152715,29 @@ var ToolService = class ToolService2 extends Service {
152731
152715
  const identity = this.authService.getIdentity();
152732
152716
  if (!identity?.workspaceId || !identity?.id) {
152733
152717
  this.logger.warn(`Cannot stop observing configured MCPServers for tool runtime: workspaceId or id not found`);
152734
- return;
152735
- }
152736
- this.logger.debug(`Stopping to observe configured MCPServers for tool runtime ${identity.workspaceId} - ${identity.id}`);
152737
- const drainPromises = this.natsSubscriptions.map(async (subscription) => {
152738
- try {
152739
- if (!subscription.isClosed?.()) {
152740
- await subscription.drain();
152718
+ } else {
152719
+ this.logger.debug(`Stopping to observe configured MCPServers for tool runtime ${identity.workspaceId} - ${identity.id}`);
152720
+ const drainPromises = this.natsSubscriptions.map(async (subscription) => {
152721
+ try {
152722
+ if (!subscription.isClosed?.()) {
152723
+ await subscription.drain();
152724
+ }
152725
+ } catch (error48) {
152726
+ this.logger.warn(`Failed to drain subscription: ${error48}`);
152741
152727
  }
152742
- } catch (error48) {
152743
- this.logger.warn(`Failed to drain subscription: ${error48}`);
152728
+ });
152729
+ await Promise.allSettled(drainPromises);
152730
+ this.natsSubscriptions = [];
152731
+ for (const subscription of this.cacheSubscriptions) {
152732
+ subscription.unsubscribe();
152744
152733
  }
152745
- });
152746
- await Promise.allSettled(drainPromises);
152747
- this.natsSubscriptions = [];
152748
- for (const subscription of this.cacheSubscriptions) {
152749
- subscription.unsubscribe();
152734
+ this.cacheSubscriptions = [];
152750
152735
  }
152751
- this.cacheSubscriptions = [];
152752
152736
  const serverIds = Array.from(this.mcpServers.keys());
152753
152737
  for (const mcpServerId of serverIds) {
152754
152738
  const service = this.mcpServers.get(mcpServerId);
152739
+ if (!service)
152740
+ continue;
152755
152741
  await this.stopMCPServer({ id: mcpServerId, name: service.getName() });
152756
152742
  }
152757
152743
  }
@@ -152874,7 +152860,7 @@ var ToolService = class ToolService2 extends Service {
152874
152860
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
152875
152861
  async handleToolCall(subscription) {
152876
152862
  const identity = this.authService.getIdentity();
152877
- const executedByIdOrAgent = identity?.nature === "runtime" ? identity.id : "AGENT";
152863
+ const executedBy = identity?.nature === "runtime" ? identity.id : "AGENT";
152878
152864
  for await (const msg of subscription) {
152879
152865
  if (msg instanceof SkillCallToolRequest) {
152880
152866
  const logData = { ...msg.data, userKey: msg.data.userKey ? "[REDACTED]" : void 0 };
@@ -152888,7 +152874,7 @@ var ToolService = class ToolService2 extends Service {
152888
152874
  }
152889
152875
  if (msg.isScript()) {
152890
152876
  try {
152891
- await this.handleScriptExecution(msg, executedByIdOrAgent);
152877
+ await this.handleScriptExecution(msg, executedBy);
152892
152878
  } catch (error48) {
152893
152879
  this.logger.error({ error: error48, scriptId: msg.data.scriptId }, "Unhandled error in script execution");
152894
152880
  msg.respond(new ErrorResponse({ error: "Script execution failed unexpectedly" }));
@@ -152941,7 +152927,7 @@ var ToolService = class ToolService2 extends Service {
152941
152927
  ],
152942
152928
  isError: true
152943
152929
  },
152944
- executedByIdOrAgent
152930
+ executedBy
152945
152931
  }));
152946
152932
  toolCalled = true;
152947
152933
  continue;
@@ -152958,7 +152944,7 @@ var ToolService = class ToolService2 extends Service {
152958
152944
  ],
152959
152945
  isError: true
152960
152946
  },
152961
- executedByIdOrAgent
152947
+ executedBy
152962
152948
  }));
152963
152949
  toolCalled = true;
152964
152950
  continue;
@@ -152989,7 +152975,7 @@ var ToolService = class ToolService2 extends Service {
152989
152975
  ],
152990
152976
  isError: true
152991
152977
  },
152992
- executedByIdOrAgent
152978
+ executedBy
152993
152979
  }));
152994
152980
  toolCalled = true;
152995
152981
  continue;
@@ -153034,7 +153020,7 @@ var ToolService = class ToolService2 extends Service {
153034
153020
  }
153035
153021
  msg.respond(new RuntimeCallToolResponse({
153036
153022
  result,
153037
- executedByIdOrAgent
153023
+ executedBy
153038
153024
  }));
153039
153025
  } catch (callError) {
153040
153026
  this.logger.error(`Tool call ${tool2.name} failed: ${callError}`);
@@ -153057,9 +153043,10 @@ var ToolService = class ToolService2 extends Service {
153057
153043
  * Handle script execution requests on EDGE runtime.
153058
153044
  * Fetches script code via NATS and executes using ScriptExecutorService.
153059
153045
  */
153060
- async handleScriptExecution(msg, executedByIdOrAgent) {
153046
+ async handleScriptExecution(msg, executedBy) {
153061
153047
  const { scriptId, scriptName, workspaceId, arguments: toolArgs } = msg.data;
153062
- const args = toolArgs?.args || [];
153048
+ const rawArgs = toolArgs?.args;
153049
+ const args = Array.isArray(rawArgs) ? rawArgs : typeof rawArgs === "string" && rawArgs.trim() ? parseScriptArgs(rawArgs) : [];
153063
153050
  this.logger.info({ scriptId, scriptName, argsCount: args.length }, "Handling script execution request");
153064
153051
  const fetchRequest = SkillFetchScriptRequest.create({
153065
153052
  scriptId,
@@ -153080,7 +153067,7 @@ var ToolService = class ToolService2 extends Service {
153080
153067
  ],
153081
153068
  isError: true
153082
153069
  },
153083
- executedByIdOrAgent
153070
+ executedBy
153084
153071
  }));
153085
153072
  return;
153086
153073
  }
@@ -153090,7 +153077,7 @@ var ToolService = class ToolService2 extends Service {
153090
153077
  content: [{ type: "text", text: `Error: ${fetchResponse.data.error}` }],
153091
153078
  isError: true
153092
153079
  },
153093
- executedByIdOrAgent
153080
+ executedBy
153094
153081
  }));
153095
153082
  return;
153096
153083
  }
@@ -153100,7 +153087,7 @@ var ToolService = class ToolService2 extends Service {
153100
153087
  content: [{ type: "text", text: "Error: Invalid response from backend" }],
153101
153088
  isError: true
153102
153089
  },
153103
- executedByIdOrAgent
153090
+ executedBy
153104
153091
  }));
153105
153092
  return;
153106
153093
  }
@@ -153110,7 +153097,7 @@ var ToolService = class ToolService2 extends Service {
153110
153097
  content: [{ type: "text", text: `Error: ${fetchResponse.data.error}` }],
153111
153098
  isError: true
153112
153099
  },
153113
- executedByIdOrAgent
153100
+ executedBy
153114
153101
  }));
153115
153102
  return;
153116
153103
  }
@@ -153122,7 +153109,7 @@ var ToolService = class ToolService2 extends Service {
153122
153109
  content: [{ type: "text", text: "Error: Script has no type defined (expected Python, Bash, Javascript, or Typescript)" }],
153123
153110
  isError: true
153124
153111
  },
153125
- executedByIdOrAgent
153112
+ executedBy
153126
153113
  }));
153127
153114
  return;
153128
153115
  }
@@ -153158,7 +153145,7 @@ ${result.stderr}`;
153158
153145
  result: {
153159
153146
  content: [{ type: "text", text: output || "(Script executed successfully with no output)" }]
153160
153147
  },
153161
- executedByIdOrAgent
153148
+ executedBy
153162
153149
  }));
153163
153150
  } else {
153164
153151
  const errorOutput = result.stderr || result.error || "Unknown error";
@@ -153173,7 +153160,7 @@ ${errorOutput}`;
153173
153160
  content: [{ type: "text", text: fullOutput }],
153174
153161
  isError: true
153175
153162
  },
153176
- executedByIdOrAgent
153163
+ executedBy
153177
153164
  }));
153178
153165
  }
153179
153166
  }
@@ -153691,10 +153678,15 @@ var MainService = class MainService2 extends Service {
153691
153678
  process.kill(process.pid, "SIGKILL");
153692
153679
  }, 1e4);
153693
153680
  this.logger.info(`Graceful shutdown: ${signal}`);
153694
- await this.stop("index");
153695
- clearInterval(keepAlive);
153696
- clearInterval(forceKill);
153697
- process.exit(0);
153681
+ try {
153682
+ await this.stop("index");
153683
+ } catch (error48) {
153684
+ this.logger.error({ event: "shutdown_error", err: error48 }, "Error during shutdown");
153685
+ } finally {
153686
+ clearInterval(keepAlive);
153687
+ clearInterval(forceKill);
153688
+ process.exit(0);
153689
+ }
153698
153690
  }
153699
153691
  logActiveServices(numberOfExpectedAlive = 0) {
153700
153692
  const activeServices = Service.getActiveServices();