skedyul 1.2.48 → 1.2.51

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.
@@ -0,0 +1 @@
1
+ export declare function eventCommand(args: string[]): Promise<void>;
package/dist/cli/index.js CHANGED
@@ -1735,6 +1735,23 @@ var file = {
1735
1735
  return data;
1736
1736
  }
1737
1737
  };
1738
+ var event = {
1739
+ async create(name, payload, options) {
1740
+ const { trigger, correlationId, app, context: extraContext } = options ?? {};
1741
+ const context = {
1742
+ ...extraContext ?? {},
1743
+ ...trigger ? { trigger } : {},
1744
+ ...correlationId ? { correlationId } : {}
1745
+ };
1746
+ const { data } = await callCore("event.create", {
1747
+ name,
1748
+ payload,
1749
+ ...Object.keys(context).length > 0 ? { context } : {},
1750
+ ...app ? { app } : {}
1751
+ });
1752
+ return data;
1753
+ }
1754
+ };
1738
1755
 
1739
1756
  // src/cli/commands/invoke.ts
1740
1757
  function getMimeType(filePath) {
@@ -3196,22 +3213,22 @@ function printStartupLog(config, tools, port) {
3196
3213
  }
3197
3214
 
3198
3215
  // src/server/route-handlers/adapters.ts
3199
- function fromLambdaEvent(event) {
3200
- const path23 = event.path || event.rawPath || "/";
3201
- const method = event.httpMethod || event.requestContext?.http?.method || "POST";
3202
- const forwardedProto = event.headers?.["x-forwarded-proto"] ?? event.headers?.["X-Forwarded-Proto"];
3216
+ function fromLambdaEvent(event2) {
3217
+ const path23 = event2.path || event2.rawPath || "/";
3218
+ const method = event2.httpMethod || event2.requestContext?.http?.method || "POST";
3219
+ const forwardedProto = event2.headers?.["x-forwarded-proto"] ?? event2.headers?.["X-Forwarded-Proto"];
3203
3220
  const protocol = forwardedProto ?? "https";
3204
- const host = event.headers?.host ?? event.headers?.Host ?? "localhost";
3205
- const queryString = event.queryStringParameters ? "?" + new URLSearchParams(
3206
- event.queryStringParameters
3221
+ const host = event2.headers?.host ?? event2.headers?.Host ?? "localhost";
3222
+ const queryString = event2.queryStringParameters ? "?" + new URLSearchParams(
3223
+ event2.queryStringParameters
3207
3224
  ).toString() : "";
3208
3225
  const url = `${protocol}://${host}${path23}${queryString}`;
3209
3226
  return {
3210
3227
  path: path23,
3211
3228
  method,
3212
- headers: event.headers,
3213
- query: event.queryStringParameters ?? {},
3214
- body: event.body,
3229
+ headers: event2.headers,
3230
+ query: event2.queryStringParameters ?? {},
3231
+ body: event2.body,
3215
3232
  url
3216
3233
  };
3217
3234
  }
@@ -4574,12 +4591,12 @@ function createServerlessInstance(config, tools, callTool, state, mcpServer) {
4574
4591
  defaultHeaders
4575
4592
  };
4576
4593
  return {
4577
- async handler(event) {
4594
+ async handler(event2) {
4578
4595
  if (!hasLoggedStartup) {
4579
4596
  printStartupLog(config, tools);
4580
4597
  hasLoggedStartup = true;
4581
4598
  }
4582
- const req = fromLambdaEvent(event);
4599
+ const req = fromLambdaEvent(event2);
4583
4600
  const response = await routeRequest(req, ctx);
4584
4601
  return toLambdaResponse(response, defaultHeaders);
4585
4602
  },
@@ -9762,6 +9779,8 @@ var SkillRefSchema = import_v45.z.union([
9762
9779
  skill: import_v45.z.string(),
9763
9780
  description: import_v45.z.string().optional(),
9764
9781
  // For AI SDK Agent Skills discovery
9782
+ /** Auto-inject this skill's instructions and tools on every agent turn */
9783
+ alwaysLoad: import_v45.z.boolean().optional(),
9765
9784
  // Version selection (pick one):
9766
9785
  version: import_v45.z.number().optional(),
9767
9786
  // Pin to specific version number
@@ -9971,8 +9990,10 @@ var PoliciesConfigV3Schema = import_v47.z.object({
9971
9990
  }).optional()
9972
9991
  });
9973
9992
  var RuntimeConfigV3Schema = import_v47.z.object({
9974
- /** LLM model identifier (e.g., "google/gemini-3.1-flash-lite") */
9975
- model: import_v47.z.string().optional()
9993
+ /** LLM model identifier for reasoning (e.g., "google/gemini-3.1-flash-lite") */
9994
+ model: import_v47.z.string().optional(),
9995
+ /** LLM model for persona transformation (e.g., "openai/gpt-5-nano") */
9996
+ personaModel: import_v47.z.string().optional()
9976
9997
  });
9977
9998
  var TimeWindowTimeStampSchema = import_v47.z.union([
9978
9999
  import_v47.z.number().describe("Hour of day (0-23)"),
@@ -10021,10 +10042,21 @@ var TimeWindowDefaultSchema = TimeWindowBehaviorSchema.describe(
10021
10042
  "Fallback behavior when no time window matches"
10022
10043
  );
10023
10044
  var ResponsesBehaviorConfigSchema = import_v47.z.object({
10045
+ /**
10046
+ * Maximum immediate messages per agent run (acks, progress updates).
10047
+ * @default 1
10048
+ */
10049
+ maxImmediate: import_v47.z.number().optional(),
10050
+ /**
10051
+ * Maximum scheduled messages per agent run (follow-ups via sendAt).
10052
+ * @default 2
10053
+ */
10054
+ maxScheduled: import_v47.z.number().optional(),
10024
10055
  /**
10025
10056
  * Maximum intermediate messages per agent run.
10026
10057
  * Intermediate = progress updates, acknowledgments before task completion.
10027
10058
  * The final message slot is always reserved separately.
10059
+ * @deprecated Use maxImmediate instead
10028
10060
  * @default 2
10029
10061
  */
10030
10062
  maxIntermediate: import_v47.z.number().optional(),
@@ -10147,7 +10179,7 @@ var AgentYAMLV3Schema = import_v47.z.object({
10147
10179
  memory: MemoryConfigV3Schema.optional(),
10148
10180
  // Policies - Business rules for the agent
10149
10181
  policies: PoliciesConfigV3Schema.optional(),
10150
- // Runtime - Execution configuration (only model is used)
10182
+ // Runtime - Execution configuration (model + personaModel)
10151
10183
  runtime: RuntimeConfigV3Schema.optional(),
10152
10184
  // Prompts - Agent-specific prompt injections
10153
10185
  prompts: PromptsConfigV3Schema.optional(),
@@ -11730,89 +11762,89 @@ Error: ${input.name} is required`);
11730
11762
  const turnToolCalls = [];
11731
11763
  const turnSkillLoads = [];
11732
11764
  const turnThoughts = [];
11733
- for await (const event of eventStream) {
11765
+ for await (const event2 of eventStream) {
11734
11766
  const now = Date.now();
11735
11767
  const sinceLastEvent = now - lastEventTime;
11736
11768
  lastEventTime = now;
11737
- if (event.agentName) {
11738
- currentAgentName = event.agentName;
11769
+ if (event2.agentName) {
11770
+ currentAgentName = event2.agentName;
11739
11771
  }
11740
- if (event.isChildAgent !== void 0) {
11741
- currentIsChildAgent = event.isChildAgent;
11772
+ if (event2.isChildAgent !== void 0) {
11773
+ currentIsChildAgent = event2.isChildAgent;
11742
11774
  }
11743
- if (event.agentName && event.isChildAgent && event.agentName !== lastDisplayedAgentName && !messageStarted) {
11775
+ if (event2.agentName && event2.isChildAgent && event2.agentName !== lastDisplayedAgentName && !messageStarted) {
11744
11776
  if (currentThought) {
11745
11777
  clearLine();
11746
11778
  currentThought = "";
11747
11779
  }
11748
- console.log(`\x1B[2m [${event.agentName}]\x1B[0m`);
11749
- lastDisplayedAgentName = event.agentName;
11780
+ console.log(`\x1B[2m [${event2.agentName}]\x1B[0m`);
11781
+ lastDisplayedAgentName = event2.agentName;
11750
11782
  }
11751
- if (event.initial && event.threadId) {
11752
- threadId = event.threadId;
11783
+ if (event2.initial && event2.threadId) {
11784
+ threadId = event2.threadId;
11753
11785
  }
11754
- if (event.context && event.context.length > 0 && !messageStarted) {
11755
- for (const ctx of event.context) {
11786
+ if (event2.context && event2.context.length > 0 && !messageStarted) {
11787
+ for (const ctx of event2.context) {
11756
11788
  if (currentThought) {
11757
11789
  clearLine();
11758
11790
  currentThought = "";
11759
11791
  }
11760
11792
  const contextType = ctx.hint || ctx.model || "";
11761
- const durationStr = event.durationMs ? ` (${event.durationMs}ms)` : "";
11762
- const indent = event.isChildAgent ? " " : " ";
11793
+ const durationStr = event2.durationMs ? ` (${event2.durationMs}ms)` : "";
11794
+ const indent = event2.isChildAgent ? " " : " ";
11763
11795
  console.log(
11764
11796
  `\x1B[2m${indent}[Context] ${contextType ? contextType.toLowerCase() + ": " : ""}${ctx.label}${durationStr}\x1B[0m`
11765
11797
  );
11766
11798
  }
11767
11799
  }
11768
- if (event.thought !== void 0 && !messageStarted) {
11769
- if (event.durationMs !== void 0) {
11800
+ if (event2.thought !== void 0 && !messageStarted) {
11801
+ if (event2.durationMs !== void 0) {
11770
11802
  clearLine();
11771
- console.log(formatThought(event.thought, event.isChildAgent) + `\x1B[2m (${event.durationMs}ms)\x1B[0m`);
11772
- turnThoughts.push({ content: event.thought, durationMs: event.durationMs });
11803
+ console.log(formatThought(event2.thought, event2.isChildAgent) + `\x1B[2m (${event2.durationMs}ms)\x1B[0m`);
11804
+ turnThoughts.push({ content: event2.thought, durationMs: event2.durationMs });
11773
11805
  currentThought = "";
11774
11806
  thoughtStartTime = null;
11775
- } else if (!event.thoughtComplete) {
11776
- if (currentThought !== event.thought) {
11807
+ } else if (!event2.thoughtComplete) {
11808
+ if (currentThought !== event2.thought) {
11777
11809
  if (thoughtStartTime === null) {
11778
11810
  thoughtStartTime = now;
11779
11811
  }
11780
11812
  clearLine();
11781
- process.stdout.write(formatThought(event.thought, event.isChildAgent));
11782
- currentThought = event.thought;
11813
+ process.stdout.write(formatThought(event2.thought, event2.isChildAgent));
11814
+ currentThought = event2.thought;
11783
11815
  }
11784
11816
  } else {
11785
11817
  clearLine();
11786
11818
  const thoughtDuration = thoughtStartTime ? now - thoughtStartTime : 0;
11787
- console.log(formatThought(event.thought, event.isChildAgent) + `\x1B[2m (${thoughtDuration}ms)\x1B[0m`);
11788
- turnThoughts.push({ content: event.thought, durationMs: thoughtDuration || void 0 });
11819
+ console.log(formatThought(event2.thought, event2.isChildAgent) + `\x1B[2m (${thoughtDuration}ms)\x1B[0m`);
11820
+ turnThoughts.push({ content: event2.thought, durationMs: thoughtDuration || void 0 });
11789
11821
  currentThought = "";
11790
11822
  thoughtStartTime = null;
11791
11823
  }
11792
11824
  }
11793
- if (event.agentOutput !== void 0 && !messageStarted) {
11825
+ if (event2.agentOutput !== void 0 && !messageStarted) {
11794
11826
  if (currentThought) {
11795
11827
  clearLine();
11796
11828
  currentThought = "";
11797
11829
  thoughtStartTime = null;
11798
11830
  }
11799
- const indent = event.isChildAgent ? " " : " ";
11800
- const durationStr = event.durationMs ? ` (${event.durationMs}ms)` : "";
11831
+ const indent = event2.isChildAgent ? " " : " ";
11832
+ const durationStr = event2.durationMs ? ` (${event2.durationMs}ms)` : "";
11801
11833
  console.log(`\x1B[33m${indent}[Output]${durationStr}\x1B[0m`);
11802
- const lines = event.agentOutput.split("\n");
11834
+ const lines = event2.agentOutput.split("\n");
11803
11835
  for (const line of lines) {
11804
11836
  console.log(`\x1B[33m${indent} ${line}\x1B[0m`);
11805
11837
  }
11806
11838
  }
11807
- if (event.toolCall) {
11808
- debug("Tool call event received:", event.toolCall.name, event.toolCall.status, "messageStarted:", messageStarted);
11839
+ if (event2.toolCall) {
11840
+ debug("Tool call event received:", event2.toolCall.name, event2.toolCall.status, "messageStarted:", messageStarted);
11809
11841
  if (!messageStarted) {
11810
11842
  if (currentThought) {
11811
11843
  clearLine();
11812
11844
  currentThought = "";
11813
11845
  thoughtStartTime = null;
11814
11846
  }
11815
- const tc = event.toolCall;
11847
+ const tc = event2.toolCall;
11816
11848
  const isSkillLoad = tc.name === "system:skill:load" || tc.name === "load_skill";
11817
11849
  const getToolKey = (name, args3) => {
11818
11850
  if ((name === "system:skill:load" || name === "load_skill") && args3?.name) {
@@ -11891,14 +11923,14 @@ Error: ${input.name} is required`);
11891
11923
  debug("Skipping tool call display because messageStarted is true");
11892
11924
  }
11893
11925
  }
11894
- if (event.pendingApproval && !messageStarted) {
11926
+ if (event2.pendingApproval && !messageStarted) {
11895
11927
  if (currentThought) {
11896
11928
  clearLine();
11897
11929
  currentThought = "";
11898
11930
  thoughtStartTime = null;
11899
11931
  }
11900
- const approval = event.pendingApproval;
11901
- const indent = event.isChildAgent ? " " : " ";
11932
+ const approval = event2.pendingApproval;
11933
+ const indent = event2.isChildAgent ? " " : " ";
11902
11934
  console.log(`
11903
11935
  \x1B[33m${indent}[Approval Required] ${approval.displayName}\x1B[0m`);
11904
11936
  if (approval.args && Object.keys(approval.args).length > 0) {
@@ -11912,12 +11944,12 @@ Error: ${input.name} is required`);
11912
11944
  }
11913
11945
  console.log(`\x1B[33m${indent} (Approval flow not yet implemented for non-sandbox mode)\x1B[0m`);
11914
11946
  }
11915
- if (event.data && event.data.length > 0 && !messageStarted) {
11947
+ if (event2.data && event2.data.length > 0 && !messageStarted) {
11916
11948
  if (currentThought) {
11917
11949
  clearLine();
11918
11950
  currentThought = "";
11919
11951
  }
11920
- for (const block of event.data) {
11952
+ for (const block of event2.data) {
11921
11953
  if (block.type === "tool_result") {
11922
11954
  const toolName = block.toolName || "tool";
11923
11955
  const summary = block.summary;
@@ -11925,14 +11957,14 @@ Error: ${input.name} is required`);
11925
11957
  }
11926
11958
  }
11927
11959
  }
11928
- if (event.sentMessage) {
11960
+ if (event2.sentMessage) {
11929
11961
  if (currentThought) {
11930
11962
  clearLine();
11931
11963
  currentThought = "";
11932
11964
  thoughtStartTime = null;
11933
11965
  }
11934
- const msg = event.sentMessage;
11935
- const indent = event.isChildAgent ? " " : " ";
11966
+ const msg = event2.sentMessage;
11967
+ const indent = event2.isChildAgent ? " " : " ";
11936
11968
  const displayName = currentAgentName || "Agent";
11937
11969
  if (msg.type === "intermediate") {
11938
11970
  console.log(`
@@ -11954,26 +11986,26 @@ Error: ${input.name} is required`);
11954
11986
  messageStarted = true;
11955
11987
  }
11956
11988
  }
11957
- if (event.message !== void 0 && event.message !== lastMessage) {
11958
- const isUserEcho = event.message.toLowerCase() === userInput.toLowerCase();
11989
+ if (event2.message !== void 0 && event2.message !== lastMessage) {
11990
+ const isUserEcho = event2.message.toLowerCase() === userInput.toLowerCase();
11959
11991
  if (isUserEcho) {
11960
- debug("Skipping user input echo:", JSON.stringify(event.message));
11961
- lastMessage = event.message;
11992
+ debug("Skipping user input echo:", JSON.stringify(event2.message));
11993
+ lastMessage = event2.message;
11962
11994
  continue;
11963
11995
  }
11964
- debug("Message event - last:", JSON.stringify(lastMessage), "new:", JSON.stringify(event.message));
11965
- lastMessage = event.message;
11996
+ debug("Message event - last:", JSON.stringify(lastMessage), "new:", JSON.stringify(event2.message));
11997
+ lastMessage = event2.message;
11966
11998
  }
11967
- if (event.done) {
11999
+ if (event2.done) {
11968
12000
  const totalTime = Date.now() - requestStartTime;
11969
- debug("Final event received:", JSON.stringify(event).slice(0, 500));
12001
+ debug("Final event received:", JSON.stringify(event2).slice(0, 500));
11970
12002
  if (currentThought) {
11971
12003
  clearLine();
11972
12004
  currentThought = "";
11973
12005
  }
11974
12006
  const displayName = currentAgentName || "Agent";
11975
- const sentMessages = event.sentMessages;
11976
- const eventSchedulingDefaults = event.schedulingDefaults;
12007
+ const sentMessages = event2.sentMessages;
12008
+ const eventSchedulingDefaults = event2.schedulingDefaults;
11977
12009
  if (sandbox && eventSchedulingDefaults) {
11978
12010
  schedulingDefaults = {
11979
12011
  cancelOnActivity: eventSchedulingDefaults.cancelOnActivity ?? true,
@@ -12026,8 +12058,8 @@ Error: ${input.name} is required`);
12026
12058
  console.log(`
12027
12059
  \x1B[1m${displayName}:\x1B[0m ${lastMessage}`);
12028
12060
  }
12029
- if (event.thoughts && Array.isArray(event.thoughts)) {
12030
- for (const t of event.thoughts) {
12061
+ if (event2.thoughts && Array.isArray(event2.thoughts)) {
12062
+ for (const t of event2.thoughts) {
12031
12063
  if (!turnThoughts.some((existing) => existing.content === t.content)) {
12032
12064
  turnThoughts.push({ content: t.content, durationMs: t.durationMs });
12033
12065
  }
@@ -12038,21 +12070,21 @@ Error: ${input.name} is required`);
12038
12070
  printNestedTrace(allToolCalls, turnThoughts);
12039
12071
  }
12040
12072
  console.log(`\x1B[2m Total: ${totalTime}ms\x1B[0m`);
12041
- if (sandbox && event.updatedMockContext) {
12073
+ if (sandbox && event2.updatedMockContext) {
12042
12074
  const oldGoals = getProspectData(mockContext)?.goals;
12043
- mockContext = event.updatedMockContext;
12075
+ mockContext = event2.updatedMockContext;
12044
12076
  const newGoals = getProspectData(mockContext)?.goals;
12045
12077
  debug("Mock context updated from server. Old goals:", JSON.stringify(oldGoals), "New goals:", JSON.stringify(newGoals));
12046
12078
  } else if (sandbox) {
12047
- debug("No updatedMockContext in event. Event keys:", Object.keys(event));
12079
+ debug("No updatedMockContext in event. Event keys:", Object.keys(event2));
12048
12080
  }
12049
12081
  if (sandbox && lastMessage) {
12050
12082
  chatHistory.push({ role: "user", content: trimmed });
12051
12083
  chatHistory.push({ role: "assistant", content: lastMessage });
12052
12084
  debug("Chat history updated, now", chatHistory.length, "messages");
12053
12085
  }
12054
- if (sandbox && event.toolCalls && event.toolCalls.length > 0) {
12055
- const newToolCalls = event.toolCalls.map((tc) => ({
12086
+ if (sandbox && event2.toolCalls && event2.toolCalls.length > 0) {
12087
+ const newToolCalls = event2.toolCalls.map((tc) => ({
12056
12088
  toolCallId: tc.toolCallId,
12057
12089
  toolName: tc.toolName,
12058
12090
  args: tc.args,
@@ -12067,9 +12099,9 @@ Error: ${input.name} is required`);
12067
12099
  }
12068
12100
  break;
12069
12101
  }
12070
- if (event.error) {
12102
+ if (event2.error) {
12071
12103
  console.error(`
12072
- \x1B[31mError: ${event.error}\x1B[0m`);
12104
+ \x1B[31mError: ${event2.error}\x1B[0m`);
12073
12105
  break;
12074
12106
  }
12075
12107
  }
@@ -13498,6 +13530,184 @@ async function workflowsCommand(args2) {
13498
13530
  }
13499
13531
  }
13500
13532
 
13533
+ // src/cli/commands/event.ts
13534
+ init_utils();
13535
+ function printHelp23() {
13536
+ console.log(`
13537
+ skedyul event - Emit test app events to the event bus
13538
+
13539
+ Usage:
13540
+ skedyul event create <name> [data] [options]
13541
+
13542
+ Required:
13543
+ <name> Event name (e.g. customer.sync)
13544
+ --workplace, -w Workplace subdomain
13545
+
13546
+ Options:
13547
+ --data, -d JSON payload (default: {})
13548
+ --app, -a App handle namespace (default: cli)
13549
+ Event type becomes app.{app}.{name}
13550
+ --context, -c JSON context metadata (optional)
13551
+ --json Output full JSON response
13552
+ --help, -h Show this help message
13553
+
13554
+ Examples:
13555
+ # Emit with inline JSON payload
13556
+ skedyul event create customer.sync '{"customers":[{"id":1}]}' -w demo-clinic
13557
+
13558
+ # Emit with --data flag
13559
+ skedyul event create order.created -w demo-clinic \\
13560
+ --data '{"order":{"id":123,"email":"test@example.com"}}'
13561
+
13562
+ # Use a specific app namespace (matches production event types)
13563
+ skedyul event create customer.sync '{"customers":[]}' -w demo-clinic --app shopify
13564
+
13565
+ # Empty payload
13566
+ skedyul event create ping -w demo-clinic
13567
+
13568
+ Notes:
13569
+ - Uses your CLI login + workplace membership (no app install required)
13570
+ - Event type: app.{app}.{name} (app defaults to "cli")
13571
+ - Passthrough when no EventSubscription exists: emitted=false, eventId=null
13572
+ - Create EventSubscription rows in the UI to test workflow dispatch
13573
+ `);
13574
+ }
13575
+ async function getWorkplaceToken8(workplaceSubdomain, serverUrl, cliToken) {
13576
+ return callCliApi(
13577
+ { serverUrl, token: cliToken },
13578
+ "/workplace-token",
13579
+ { workplaceSubdomain }
13580
+ );
13581
+ }
13582
+ function parseJsonObject(value, label) {
13583
+ if (!value || value.trim() === "") {
13584
+ return {};
13585
+ }
13586
+ try {
13587
+ const parsed = JSON.parse(value);
13588
+ if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
13589
+ throw new Error(`${label} must be a JSON object`);
13590
+ }
13591
+ return parsed;
13592
+ } catch (error) {
13593
+ const message = error instanceof Error ? error.message : String(error);
13594
+ throw new Error(`Invalid ${label} JSON: ${message}`);
13595
+ }
13596
+ }
13597
+ async function eventCommand(args2) {
13598
+ const { positional, flags } = parseArgs(args2);
13599
+ if (flags.help || flags.h || positional.length === 0) {
13600
+ printHelp23();
13601
+ return;
13602
+ }
13603
+ const subcommand = positional[0];
13604
+ if (subcommand !== "create") {
13605
+ console.error(`Error: Unknown subcommand: ${subcommand}`);
13606
+ printHelp23();
13607
+ process.exit(1);
13608
+ }
13609
+ const eventName = positional[1];
13610
+ const inlineData = positional[2];
13611
+ if (!eventName) {
13612
+ console.error("Error: Event name is required");
13613
+ console.error(
13614
+ "Usage: skedyul event create <name> [data] --workplace <subdomain>"
13615
+ );
13616
+ process.exit(1);
13617
+ }
13618
+ const workplaceSubdomain = flags.workplace || flags.w;
13619
+ if (!workplaceSubdomain) {
13620
+ console.error("Error: --workplace (-w) is required");
13621
+ console.error(
13622
+ "Example: skedyul event create customer.sync '{}' --workplace demo-clinic"
13623
+ );
13624
+ process.exit(1);
13625
+ }
13626
+ const credentials = getCredentials();
13627
+ if (!credentials) {
13628
+ console.error("Error: Not logged in.");
13629
+ console.error("Run 'skedyul auth login' to authenticate first.");
13630
+ process.exit(1);
13631
+ }
13632
+ const serverUrl = getServerUrl();
13633
+ let workplaceToken;
13634
+ try {
13635
+ workplaceToken = await getWorkplaceToken8(
13636
+ workplaceSubdomain,
13637
+ serverUrl,
13638
+ credentials.token
13639
+ );
13640
+ } catch (error) {
13641
+ console.error(
13642
+ `Error: Failed to get workplace token: ${error instanceof Error ? error.message : String(error)}`
13643
+ );
13644
+ process.exit(1);
13645
+ }
13646
+ const dataSource = flags.data ?? flags.d ?? inlineData;
13647
+ let payload;
13648
+ try {
13649
+ payload = parseJsonObject(dataSource, "payload");
13650
+ } catch (error) {
13651
+ console.error(
13652
+ `Error: ${error instanceof Error ? error.message : String(error)}`
13653
+ );
13654
+ process.exit(1);
13655
+ }
13656
+ const appHandle = flags.app || flags.a;
13657
+ let extraContext;
13658
+ const contextSource = flags.context || flags.c;
13659
+ if (contextSource) {
13660
+ try {
13661
+ extraContext = parseJsonObject(contextSource, "context");
13662
+ } catch (error) {
13663
+ console.error(
13664
+ `Error: ${error instanceof Error ? error.message : String(error)}`
13665
+ );
13666
+ process.exit(1);
13667
+ }
13668
+ }
13669
+ const clientConfig = {
13670
+ baseUrl: serverUrl,
13671
+ apiToken: workplaceToken.token
13672
+ };
13673
+ configure(clientConfig);
13674
+ try {
13675
+ const result = await runWithConfig(
13676
+ clientConfig,
13677
+ () => event.create(eventName, payload, {
13678
+ trigger: "cli",
13679
+ app: appHandle,
13680
+ context: extraContext
13681
+ })
13682
+ );
13683
+ const eventType = result.eventType ?? `app.${appHandle ?? "cli"}.${eventName}`;
13684
+ if (flags.json) {
13685
+ console.log(
13686
+ formatJson({
13687
+ ...result,
13688
+ eventType,
13689
+ workplace: workplaceToken.workplaceSubdomain
13690
+ })
13691
+ );
13692
+ return;
13693
+ }
13694
+ if (result.emitted) {
13695
+ console.log(`Event emitted: ${eventType}`);
13696
+ console.log(`Event ID: ${result.eventId}`);
13697
+ } else {
13698
+ console.log(`Passthrough (no subscription): ${eventType}`);
13699
+ console.log(
13700
+ `No Event row created. Add an EventSubscription for "${eventType}" to test dispatch.`
13701
+ );
13702
+ }
13703
+ } catch (error) {
13704
+ console.error(
13705
+ `Error: ${error instanceof Error ? error.message : String(error)}`
13706
+ );
13707
+ process.exit(1);
13708
+ }
13709
+ }
13710
+
13501
13711
  // src/cli/index.ts
13502
13712
  var args = process.argv.slice(2);
13503
13713
  function printUsage2() {
@@ -13529,6 +13739,7 @@ COMMANDS
13529
13739
  agents Manage agents (list, get, push)
13530
13740
  skills Manage skills (list, get, deploy, publish, versions, delete)
13531
13741
  workflows Manage workflows (list, get, deploy, run, publish, pull)
13742
+ event Emit test app events to the event bus (CLI testing)
13532
13743
  dev Development tools for building and testing apps locally
13533
13744
 
13534
13745
  GETTING STARTED
@@ -13561,6 +13772,12 @@ CRM INSTANCES
13561
13772
  $ skedyul instances update <model> <id> --data '{}' --workplace <subdomain>
13562
13773
  $ skedyul instances delete <model> <id> --workplace <subdomain>
13563
13774
 
13775
+ SIGNALS (CLI testing)
13776
+ Emit app events without an app installation:
13777
+
13778
+ $ skedyul event create customer.sync '{"customers":[]}' --workplace <subdomain>
13779
+ $ skedyul event create ping --workplace <subdomain> --app shopify
13780
+
13564
13781
  CONFIGURATION
13565
13782
  Global credentials: ~/.skedyul/credentials.json
13566
13783
  Global config: ~/.skedyul/config.json
@@ -13736,6 +13953,10 @@ async function main() {
13736
13953
  await workflowsCommand(args.slice(1));
13737
13954
  return;
13738
13955
  }
13956
+ if (command === "event") {
13957
+ await eventCommand(args.slice(1));
13958
+ return;
13959
+ }
13739
13960
  if (command === "build") {
13740
13961
  await buildCommand(args.slice(1));
13741
13962
  return;
@@ -6,7 +6,7 @@
6
6
  import type { ToolRegistry, WebhookRegistry, ToolMetadata, WebhookMetadata } from '../types';
7
7
  import type { ServerHooks } from '../types/handlers';
8
8
  import type { CoreApiConfig } from '../core/types';
9
- import type { EnvSchema, ComputeLayer, ModelDefinition, RelationshipDefinition, ChannelDefinition, WorkflowDefinition, PageDefinition, NavigationConfig, AgentDefinition } from './types';
9
+ import type { EnvSchema, ComputeLayer, ModelDefinition, RelationshipDefinition, ChannelDefinition, WorkflowDefinition, PageDefinition, NavigationConfig, AgentDefinition, SignalDefinition } from './types';
10
10
  /**
11
11
  * Install configuration - defines per-install env vars and SHARED models.
12
12
  * This is configured by users during app installation.
@@ -38,6 +38,8 @@ export interface ProvisionConfig {
38
38
  navigation?: NavigationConfig;
39
39
  /** Page definitions for app UI */
40
40
  pages?: PageDefinition[];
41
+ /** App signal definitions (event bus subscriptions created on install) */
42
+ signals?: SignalDefinition[];
41
43
  }
42
44
  /**
43
45
  * Build configuration - controls how the integration is bundled.
@@ -11,6 +11,7 @@ export * from './channel';
11
11
  export * from './workflow';
12
12
  export * from './agent';
13
13
  export * from './webhook';
14
+ export * from './signal';
14
15
  export * from './navigation';
15
16
  export * from './context';
16
17
  export * from './form';
@@ -0,0 +1,20 @@
1
+ /**
2
+ * App signal definition for provision config.
3
+ *
4
+ * Signals are UI-facing names for event types: signal.{appHandle}.{name}
5
+ * Install-time provisioning creates EventSubscription + EVENT trigger rows.
6
+ */
7
+ export interface SignalDefinition {
8
+ /** Short signal name, e.g. "customer.sync" → signal.shopify.customer.sync */
9
+ name: string;
10
+ /** UI display name */
11
+ label?: string;
12
+ /** Human-readable description */
13
+ description?: string;
14
+ /** Bundled workflow handle, e.g. "sync-customers" or "@shopify/sync-customers" */
15
+ workflowHandle: string;
16
+ /** Default Liquid input mappings for the subscribed workflow */
17
+ inputMappings?: Record<string, string>;
18
+ /** Optional EventSubscription condition filter */
19
+ condition?: string;
20
+ }
@@ -765,6 +765,28 @@ export declare const cron: {
765
765
  subscriptions: CronSubscriptionItem[];
766
766
  }>;
767
767
  };
768
+ export interface EventCreateResult {
769
+ /** false when no EventSubscription matches (passthrough) */
770
+ emitted: boolean;
771
+ eventId: string | null;
772
+ /** Present when server returns resolved event type */
773
+ eventType?: string;
774
+ }
775
+ export interface EventCreateOptions {
776
+ /** Context trigger source, e.g. tool_call, webhook, cli */
777
+ trigger?: string;
778
+ correlationId?: string;
779
+ /** App handle namespace for event type (CLI default: cli) */
780
+ app?: string;
781
+ /** Additional context fields merged into event payload context */
782
+ context?: Record<string, unknown>;
783
+ }
784
+ /**
785
+ * event.create - Emit an app event to the platform event bus.
786
+ */
787
+ export declare const event: {
788
+ create(name: string, payload: Record<string, unknown>, options?: EventCreateOptions): Promise<EventCreateResult>;
789
+ };
768
790
  /**
769
791
  * Parameters for resource.link
770
792
  */
@@ -13,4 +13,4 @@
13
13
  * - BUILD_EXTERNAL: comma-separated list of external dependencies (e.g., 'twilio,stripe')
14
14
  * - MCP_ENV_JSON: JSON string of environment variables to bake into the image
15
15
  */
16
- export declare const DEFAULT_DOCKERFILE = "# =============================================================================\n# BUILDER STAGE - Common build for all targets\n# =============================================================================\nFROM public.ecr.aws/docker/library/node:22-alpine AS builder\n\nARG COMPUTE_LAYER=serverless\nARG BUILD_EXTERNAL=\"\"\nWORKDIR /app\n\n# Install pnpm\nRUN corepack enable && corepack prepare pnpm@latest --activate\n\n# Copy all project files (excluding node_modules via .dockerignore)\n# This includes: package.json, tsconfig.json, skedyul.config.ts, provision.ts, env.ts\n# And directories: src/, crm/, channels/, pages/, workflows/, agents/, etc.\nCOPY . .\n\n# Install dependencies (including dev deps for build), compile, export config, smoke test, then prune\n# Note: Using --no-frozen-lockfile since lockfile may not exist\n# skedyul build reads computeLayer from skedyul.config.ts\n# skedyul config:export resolves all dynamic imports and writes .skedyul/config.json\n# We use tsx to run config:export since it needs to import TypeScript files\n# Smoke test runs before pruning since skedyul CLI is a dev dependency\nRUN pnpm install --no-frozen-lockfile && \\\n pnpm run build && \\\n pnpm exec tsx node_modules/skedyul/dist/cli/index.js config:export && \\\n pnpm exec skedyul smoke-test && \\\n pnpm prune --prod && \\\n pnpm store prune && \\\n rm -rf /tmp/* /var/cache/apk/* ~/.npm\n\n# =============================================================================\n# DEDICATED STAGE - For local Docker and ECS deployments (HTTP server)\n# =============================================================================\nFROM public.ecr.aws/docker/library/node:22-alpine AS dedicated\n\nWORKDIR /app\n\n# Copy built artifacts\nCOPY --from=builder /app/node_modules ./node_modules\nCOPY --from=builder /app/dist ./dist\nCOPY --from=builder /app/package.json ./package.json\nCOPY --from=builder /app/.skedyul ./.skedyul\n\n# Allow overriding the baked-in MCP env at runtime\nARG MCP_ENV_JSON=\"{}\"\nENV MCP_ENV_JSON=${MCP_ENV_JSON}\n\n# Expose the HTTP port\nEXPOSE 3000\n\n# Run as HTTP server (dedicated mode auto-detected by absence of AWS_LAMBDA_FUNCTION_NAME)\n# Support both .js (dedicated builds) and .mjs (serverless builds) extensions\nCMD [\"sh\", \"-c\", \"node dist/server/mcp_server.mjs 2>/dev/null || node dist/server/mcp_server.js\"]\n\n# =============================================================================\n# SERVERLESS STAGE - For AWS Lambda deployments\n# =============================================================================\nFROM public.ecr.aws/lambda/nodejs:22 AS serverless\n\nWORKDIR ${LAMBDA_TASK_ROOT}\n\nCOPY --from=builder /app/node_modules ./node_modules\nCOPY --from=builder /app/dist ./dist\nCOPY --from=builder /app/package.json ./package.json\nCOPY --from=builder /app/.skedyul ./.skedyul\n\n# Allow overriding the baked-in MCP env at runtime\nARG MCP_ENV_JSON=\"{}\"\nENV MCP_ENV_JSON=${MCP_ENV_JSON}\n\n# Lambda handler format\nCMD [\"dist/server/mcp_server.handler\"]\n\n# =============================================================================\n# DEFAULT - Use dedicated for local development, override with --target for production\n# =============================================================================\nFROM dedicated\n";
16
+ export declare const DEFAULT_DOCKERFILE = "# =============================================================================\n# BUILDER STAGE - Common build for all targets\n# =============================================================================\nFROM public.ecr.aws/docker/library/node:22-alpine AS builder\n\nARG COMPUTE_LAYER=serverless\nARG BUILD_EXTERNAL=\"\"\nWORKDIR /app\n\n# Install pnpm (pinned \u2014 avoid pnpm@latest drift breaking esbuild postinstall approval)\nRUN corepack enable && corepack prepare pnpm@10.13.1 --activate\n\n# Copy all project files (excluding node_modules via .dockerignore)\n# This includes: package.json, tsconfig.json, skedyul.config.ts, provision.ts, env.ts\n# And directories: src/, crm/, channels/, pages/, workflows/, agents/, etc.\nCOPY . .\n\nENV CI=true\n\n# esbuild postinstall is required for tsup; pnpm 10+ blocks unapproved lifecycle scripts\nRUN printf '%s\\n' \\\n 'packages:' \\\n ' - \".\"' \\\n 'onlyBuiltDependencies:' \\\n ' - esbuild' \\\n 'allowBuilds:' \\\n ' esbuild: true' \\\n > pnpm-workspace.yaml\n\n# Install dependencies (including dev deps for build), compile, export config, smoke test, then prune\n# Note: Using --no-frozen-lockfile since lockfile may not exist\n# skedyul build reads computeLayer from skedyul.config.ts\n# skedyul config:export resolves all dynamic imports and writes .skedyul/config.json\n# We use tsx to run config:export since it needs to import TypeScript files\n# Smoke test runs before pruning since skedyul CLI is a dev dependency\nRUN pnpm install --no-frozen-lockfile && \\\n pnpm run build && \\\n pnpm exec tsx node_modules/skedyul/dist/cli/index.js config:export && \\\n pnpm exec skedyul smoke-test && \\\n pnpm prune --prod && \\\n pnpm store prune && \\\n rm -rf /tmp/* /var/cache/apk/* ~/.npm\n\n# =============================================================================\n# DEDICATED STAGE - For local Docker and ECS deployments (HTTP server)\n# =============================================================================\nFROM public.ecr.aws/docker/library/node:22-alpine AS dedicated\n\nWORKDIR /app\n\n# Copy built artifacts\nCOPY --from=builder /app/node_modules ./node_modules\nCOPY --from=builder /app/dist ./dist\nCOPY --from=builder /app/package.json ./package.json\nCOPY --from=builder /app/.skedyul ./.skedyul\n\n# Allow overriding the baked-in MCP env at runtime\nARG MCP_ENV_JSON=\"{}\"\nENV MCP_ENV_JSON=${MCP_ENV_JSON}\n\n# Expose the HTTP port\nEXPOSE 3000\n\n# Run as HTTP server (dedicated mode auto-detected by absence of AWS_LAMBDA_FUNCTION_NAME)\n# Support both .js (dedicated builds) and .mjs (serverless builds) extensions\nCMD [\"sh\", \"-c\", \"node dist/server/mcp_server.mjs 2>/dev/null || node dist/server/mcp_server.js\"]\n\n# =============================================================================\n# SERVERLESS STAGE - For AWS Lambda deployments\n# =============================================================================\nFROM public.ecr.aws/lambda/nodejs:22 AS serverless\n\nWORKDIR ${LAMBDA_TASK_ROOT}\n\nCOPY --from=builder /app/node_modules ./node_modules\nCOPY --from=builder /app/dist ./dist\nCOPY --from=builder /app/package.json ./package.json\nCOPY --from=builder /app/.skedyul ./.skedyul\n\n# Allow overriding the baked-in MCP env at runtime\nARG MCP_ENV_JSON=\"{}\"\nENV MCP_ENV_JSON=${MCP_ENV_JSON}\n\n# Lambda handler format\nCMD [\"dist/server/mcp_server.handler\"]\n\n# =============================================================================\n# DEFAULT - Use dedicated for local development, override with --target for production\n# =============================================================================\nFROM dedicated\n";
@@ -585,6 +585,8 @@ var SkillRefSchema = z4.union([
585
585
  skill: z4.string(),
586
586
  description: z4.string().optional(),
587
587
  // For AI SDK Agent Skills discovery
588
+ /** Auto-inject this skill's instructions and tools on every agent turn */
589
+ alwaysLoad: z4.boolean().optional(),
588
590
  // Version selection (pick one):
589
591
  version: z4.number().optional(),
590
592
  // Pin to specific version number
@@ -842,8 +844,10 @@ var PoliciesConfigV3Schema = z6.object({
842
844
  }).optional()
843
845
  });
844
846
  var RuntimeConfigV3Schema = z6.object({
845
- /** LLM model identifier (e.g., "google/gemini-3.1-flash-lite") */
846
- model: z6.string().optional()
847
+ /** LLM model identifier for reasoning (e.g., "google/gemini-3.1-flash-lite") */
848
+ model: z6.string().optional(),
849
+ /** LLM model for persona transformation (e.g., "openai/gpt-5-nano") */
850
+ personaModel: z6.string().optional()
847
851
  });
848
852
  var TimeWindowTimeStampSchema = z6.union([
849
853
  z6.number().describe("Hour of day (0-23)"),
@@ -892,10 +896,21 @@ var TimeWindowDefaultSchema = TimeWindowBehaviorSchema.describe(
892
896
  "Fallback behavior when no time window matches"
893
897
  );
894
898
  var ResponsesBehaviorConfigSchema = z6.object({
899
+ /**
900
+ * Maximum immediate messages per agent run (acks, progress updates).
901
+ * @default 1
902
+ */
903
+ maxImmediate: z6.number().optional(),
904
+ /**
905
+ * Maximum scheduled messages per agent run (follow-ups via sendAt).
906
+ * @default 2
907
+ */
908
+ maxScheduled: z6.number().optional(),
895
909
  /**
896
910
  * Maximum intermediate messages per agent run.
897
911
  * Intermediate = progress updates, acknowledgments before task completion.
898
912
  * The final message slot is always reserved separately.
913
+ * @deprecated Use maxImmediate instead
899
914
  * @default 2
900
915
  */
901
916
  maxIntermediate: z6.number().optional(),
@@ -1018,7 +1033,7 @@ var AgentYAMLV3Schema = z6.object({
1018
1033
  memory: MemoryConfigV3Schema.optional(),
1019
1034
  // Policies - Business rules for the agent
1020
1035
  policies: PoliciesConfigV3Schema.optional(),
1021
- // Runtime - Execution configuration (only model is used)
1036
+ // Runtime - Execution configuration (model + personaModel)
1022
1037
  runtime: RuntimeConfigV3Schema.optional(),
1023
1038
  // Prompts - Agent-specific prompt injections
1024
1039
  prompts: PromptsConfigV3Schema.optional(),
@@ -2938,6 +2953,23 @@ var cron = {
2938
2953
  return { subscriptions: data };
2939
2954
  }
2940
2955
  };
2956
+ var event = {
2957
+ async create(name, payload, options) {
2958
+ const { trigger, correlationId, app, context: extraContext } = options ?? {};
2959
+ const context = {
2960
+ ...extraContext ?? {},
2961
+ ...trigger ? { trigger } : {},
2962
+ ...correlationId ? { correlationId } : {}
2963
+ };
2964
+ const { data } = await callCore("event.create", {
2965
+ name,
2966
+ payload,
2967
+ ...Object.keys(context).length > 0 ? { context } : {},
2968
+ ...app ? { app } : {}
2969
+ });
2970
+ return data;
2971
+ }
2972
+ };
2941
2973
  var resource = {
2942
2974
  /**
2943
2975
  * Link a SHARED app resource (model) to a user's resource.
@@ -3547,22 +3579,22 @@ function printStartupLog(config, tools, port) {
3547
3579
  }
3548
3580
 
3549
3581
  // src/server/route-handlers/adapters.ts
3550
- function fromLambdaEvent(event) {
3551
- const path5 = event.path || event.rawPath || "/";
3552
- const method = event.httpMethod || event.requestContext?.http?.method || "POST";
3553
- const forwardedProto = event.headers?.["x-forwarded-proto"] ?? event.headers?.["X-Forwarded-Proto"];
3582
+ function fromLambdaEvent(event2) {
3583
+ const path5 = event2.path || event2.rawPath || "/";
3584
+ const method = event2.httpMethod || event2.requestContext?.http?.method || "POST";
3585
+ const forwardedProto = event2.headers?.["x-forwarded-proto"] ?? event2.headers?.["X-Forwarded-Proto"];
3554
3586
  const protocol = forwardedProto ?? "https";
3555
- const host = event.headers?.host ?? event.headers?.Host ?? "localhost";
3556
- const queryString = event.queryStringParameters ? "?" + new URLSearchParams(
3557
- event.queryStringParameters
3587
+ const host = event2.headers?.host ?? event2.headers?.Host ?? "localhost";
3588
+ const queryString = event2.queryStringParameters ? "?" + new URLSearchParams(
3589
+ event2.queryStringParameters
3558
3590
  ).toString() : "";
3559
3591
  const url = `${protocol}://${host}${path5}${queryString}`;
3560
3592
  return {
3561
3593
  path: path5,
3562
3594
  method,
3563
- headers: event.headers,
3564
- query: event.queryStringParameters ?? {},
3565
- body: event.body,
3595
+ headers: event2.headers,
3596
+ query: event2.queryStringParameters ?? {},
3597
+ body: event2.body,
3566
3598
  url
3567
3599
  };
3568
3600
  }
@@ -4925,12 +4957,12 @@ function createServerlessInstance(config, tools, callTool, state, mcpServer) {
4925
4957
  defaultHeaders
4926
4958
  };
4927
4959
  return {
4928
- async handler(event) {
4960
+ async handler(event2) {
4929
4961
  if (!hasLoggedStartup) {
4930
4962
  printStartupLog(config, tools);
4931
4963
  hasLoggedStartup = true;
4932
4964
  }
4933
- const req = fromLambdaEvent(event);
4965
+ const req = fromLambdaEvent(event2);
4934
4966
  const response = await routeRequest(req, ctx);
4935
4967
  return toLambdaResponse(response, defaultHeaders);
4936
4968
  },
@@ -5098,14 +5130,26 @@ ARG COMPUTE_LAYER=serverless
5098
5130
  ARG BUILD_EXTERNAL=""
5099
5131
  WORKDIR /app
5100
5132
 
5101
- # Install pnpm
5102
- RUN corepack enable && corepack prepare pnpm@latest --activate
5133
+ # Install pnpm (pinned \u2014 avoid pnpm@latest drift breaking esbuild postinstall approval)
5134
+ RUN corepack enable && corepack prepare pnpm@10.13.1 --activate
5103
5135
 
5104
5136
  # Copy all project files (excluding node_modules via .dockerignore)
5105
5137
  # This includes: package.json, tsconfig.json, skedyul.config.ts, provision.ts, env.ts
5106
5138
  # And directories: src/, crm/, channels/, pages/, workflows/, agents/, etc.
5107
5139
  COPY . .
5108
5140
 
5141
+ ENV CI=true
5142
+
5143
+ # esbuild postinstall is required for tsup; pnpm 10+ blocks unapproved lifecycle scripts
5144
+ RUN printf '%s\\n' \\
5145
+ 'packages:' \\
5146
+ ' - "."' \\
5147
+ 'onlyBuiltDependencies:' \\
5148
+ ' - esbuild' \\
5149
+ 'allowBuilds:' \\
5150
+ ' esbuild: true' \\
5151
+ > pnpm-workspace.yaml
5152
+
5109
5153
  # Install dependencies (including dev deps for build), compile, export config, smoke test, then prune
5110
5154
  # Note: Using --no-frozen-lockfile since lockfile may not exist
5111
5155
  # skedyul build reads computeLayer from skedyul.config.ts
@@ -6914,6 +6958,7 @@ export {
6914
6958
  defineWorkflowYAML,
6915
6959
  evaluateCondition,
6916
6960
  evaluateTemplate,
6961
+ event,
6917
6962
  file,
6918
6963
  formatContextForPrompt,
6919
6964
  formatSkillInstructions,
package/dist/index.d.ts CHANGED
@@ -6,8 +6,8 @@ export { DEFAULT_DOCKERFILE } from './dockerfile';
6
6
  export { InstallError, MissingRequiredFieldError, AuthenticationError, InvalidConfigurationError, ConnectionError, AppAuthInvalidError, } from './errors';
7
7
  export type { InstallErrorCode } from './errors';
8
8
  export { z };
9
- export { workplace, communicationChannel, instance, token, file, webhook, cron, resource, ai, report, configure, getConfig, runWithConfig, createInstanceClient, } from './core/client';
10
- export type { InstanceClient, InstanceContext, InstanceData, InstanceMeta, InstancePagination, InstanceListResult, InstanceListArgs, FileInfo, FileUrlResponse, FileUploadParams, FileUploadResult, WebhookCreateResult, WebhookListItem, WebhookDeleteByNameOptions, WebhookListOptions, CronSubscribeParams, CronSubscribeResult, CronSubscriptionItem, CronListOptions, ResourceLinkParams, ResourceLinkResult, AITextContent, AIFileContent, AIImageContent, AIMessageContent, AIMessage, GenerateObjectOptions, GenerateObjectResult, ReportGenerateParams, ReportGenerateResult, ReportDefineParams, ReportDefineResult, ReportListParams, ReportListItem, ReportListResult, ReportDefinition, } from './core/client';
9
+ export { workplace, communicationChannel, instance, token, file, webhook, cron, event, resource, ai, report, configure, getConfig, runWithConfig, createInstanceClient, } from './core/client';
10
+ export type { InstanceClient, InstanceContext, InstanceData, InstanceMeta, InstancePagination, InstanceListResult, InstanceListArgs, FileInfo, FileUrlResponse, FileUploadParams, FileUploadResult, WebhookCreateResult, WebhookListItem, WebhookDeleteByNameOptions, WebhookListOptions, CronSubscribeParams, CronSubscribeResult, CronSubscriptionItem, CronListOptions, EventCreateResult, EventCreateOptions, ResourceLinkParams, ResourceLinkResult, AITextContent, AIFileContent, AIImageContent, AIMessageContent, AIMessage, GenerateObjectOptions, GenerateObjectResult, ReportGenerateParams, ReportGenerateResult, ReportDefineParams, ReportDefineResult, ReportListParams, ReportListItem, ReportListResult, ReportDefinition, } from './core/client';
11
11
  export { createContextLogger } from './server/logger';
12
12
  export type { ContextLogger } from './server/logger';
13
13
  declare const _default: {
package/dist/index.js CHANGED
@@ -273,6 +273,7 @@ __export(index_exports, {
273
273
  defineWorkflowYAML: () => defineWorkflowYAML,
274
274
  evaluateCondition: () => evaluateCondition,
275
275
  evaluateTemplate: () => evaluateTemplate,
276
+ event: () => event,
276
277
  file: () => file,
277
278
  formatContextForPrompt: () => formatContextForPrompt,
278
279
  formatSkillInstructions: () => formatSkillInstructions,
@@ -895,6 +896,8 @@ var SkillRefSchema = import_v44.z.union([
895
896
  skill: import_v44.z.string(),
896
897
  description: import_v44.z.string().optional(),
897
898
  // For AI SDK Agent Skills discovery
899
+ /** Auto-inject this skill's instructions and tools on every agent turn */
900
+ alwaysLoad: import_v44.z.boolean().optional(),
898
901
  // Version selection (pick one):
899
902
  version: import_v44.z.number().optional(),
900
903
  // Pin to specific version number
@@ -1152,8 +1155,10 @@ var PoliciesConfigV3Schema = import_v46.z.object({
1152
1155
  }).optional()
1153
1156
  });
1154
1157
  var RuntimeConfigV3Schema = import_v46.z.object({
1155
- /** LLM model identifier (e.g., "google/gemini-3.1-flash-lite") */
1156
- model: import_v46.z.string().optional()
1158
+ /** LLM model identifier for reasoning (e.g., "google/gemini-3.1-flash-lite") */
1159
+ model: import_v46.z.string().optional(),
1160
+ /** LLM model for persona transformation (e.g., "openai/gpt-5-nano") */
1161
+ personaModel: import_v46.z.string().optional()
1157
1162
  });
1158
1163
  var TimeWindowTimeStampSchema = import_v46.z.union([
1159
1164
  import_v46.z.number().describe("Hour of day (0-23)"),
@@ -1202,10 +1207,21 @@ var TimeWindowDefaultSchema = TimeWindowBehaviorSchema.describe(
1202
1207
  "Fallback behavior when no time window matches"
1203
1208
  );
1204
1209
  var ResponsesBehaviorConfigSchema = import_v46.z.object({
1210
+ /**
1211
+ * Maximum immediate messages per agent run (acks, progress updates).
1212
+ * @default 1
1213
+ */
1214
+ maxImmediate: import_v46.z.number().optional(),
1215
+ /**
1216
+ * Maximum scheduled messages per agent run (follow-ups via sendAt).
1217
+ * @default 2
1218
+ */
1219
+ maxScheduled: import_v46.z.number().optional(),
1205
1220
  /**
1206
1221
  * Maximum intermediate messages per agent run.
1207
1222
  * Intermediate = progress updates, acknowledgments before task completion.
1208
1223
  * The final message slot is always reserved separately.
1224
+ * @deprecated Use maxImmediate instead
1209
1225
  * @default 2
1210
1226
  */
1211
1227
  maxIntermediate: import_v46.z.number().optional(),
@@ -1328,7 +1344,7 @@ var AgentYAMLV3Schema = import_v46.z.object({
1328
1344
  memory: MemoryConfigV3Schema.optional(),
1329
1345
  // Policies - Business rules for the agent
1330
1346
  policies: PoliciesConfigV3Schema.optional(),
1331
- // Runtime - Execution configuration (only model is used)
1347
+ // Runtime - Execution configuration (model + personaModel)
1332
1348
  runtime: RuntimeConfigV3Schema.optional(),
1333
1349
  // Prompts - Agent-specific prompt injections
1334
1350
  prompts: PromptsConfigV3Schema.optional(),
@@ -3248,6 +3264,23 @@ var cron = {
3248
3264
  return { subscriptions: data };
3249
3265
  }
3250
3266
  };
3267
+ var event = {
3268
+ async create(name, payload, options) {
3269
+ const { trigger, correlationId, app, context: extraContext } = options ?? {};
3270
+ const context = {
3271
+ ...extraContext ?? {},
3272
+ ...trigger ? { trigger } : {},
3273
+ ...correlationId ? { correlationId } : {}
3274
+ };
3275
+ const { data } = await callCore("event.create", {
3276
+ name,
3277
+ payload,
3278
+ ...Object.keys(context).length > 0 ? { context } : {},
3279
+ ...app ? { app } : {}
3280
+ });
3281
+ return data;
3282
+ }
3283
+ };
3251
3284
  var resource = {
3252
3285
  /**
3253
3286
  * Link a SHARED app resource (model) to a user's resource.
@@ -3857,22 +3890,22 @@ function printStartupLog(config, tools, port) {
3857
3890
  }
3858
3891
 
3859
3892
  // src/server/route-handlers/adapters.ts
3860
- function fromLambdaEvent(event) {
3861
- const path5 = event.path || event.rawPath || "/";
3862
- const method = event.httpMethod || event.requestContext?.http?.method || "POST";
3863
- const forwardedProto = event.headers?.["x-forwarded-proto"] ?? event.headers?.["X-Forwarded-Proto"];
3893
+ function fromLambdaEvent(event2) {
3894
+ const path5 = event2.path || event2.rawPath || "/";
3895
+ const method = event2.httpMethod || event2.requestContext?.http?.method || "POST";
3896
+ const forwardedProto = event2.headers?.["x-forwarded-proto"] ?? event2.headers?.["X-Forwarded-Proto"];
3864
3897
  const protocol = forwardedProto ?? "https";
3865
- const host = event.headers?.host ?? event.headers?.Host ?? "localhost";
3866
- const queryString = event.queryStringParameters ? "?" + new URLSearchParams(
3867
- event.queryStringParameters
3898
+ const host = event2.headers?.host ?? event2.headers?.Host ?? "localhost";
3899
+ const queryString = event2.queryStringParameters ? "?" + new URLSearchParams(
3900
+ event2.queryStringParameters
3868
3901
  ).toString() : "";
3869
3902
  const url = `${protocol}://${host}${path5}${queryString}`;
3870
3903
  return {
3871
3904
  path: path5,
3872
3905
  method,
3873
- headers: event.headers,
3874
- query: event.queryStringParameters ?? {},
3875
- body: event.body,
3906
+ headers: event2.headers,
3907
+ query: event2.queryStringParameters ?? {},
3908
+ body: event2.body,
3876
3909
  url
3877
3910
  };
3878
3911
  }
@@ -5235,12 +5268,12 @@ function createServerlessInstance(config, tools, callTool, state, mcpServer) {
5235
5268
  defaultHeaders
5236
5269
  };
5237
5270
  return {
5238
- async handler(event) {
5271
+ async handler(event2) {
5239
5272
  if (!hasLoggedStartup) {
5240
5273
  printStartupLog(config, tools);
5241
5274
  hasLoggedStartup = true;
5242
5275
  }
5243
- const req = fromLambdaEvent(event);
5276
+ const req = fromLambdaEvent(event2);
5244
5277
  const response = await routeRequest(req, ctx);
5245
5278
  return toLambdaResponse(response, defaultHeaders);
5246
5279
  },
@@ -5408,14 +5441,26 @@ ARG COMPUTE_LAYER=serverless
5408
5441
  ARG BUILD_EXTERNAL=""
5409
5442
  WORKDIR /app
5410
5443
 
5411
- # Install pnpm
5412
- RUN corepack enable && corepack prepare pnpm@latest --activate
5444
+ # Install pnpm (pinned \u2014 avoid pnpm@latest drift breaking esbuild postinstall approval)
5445
+ RUN corepack enable && corepack prepare pnpm@10.13.1 --activate
5413
5446
 
5414
5447
  # Copy all project files (excluding node_modules via .dockerignore)
5415
5448
  # This includes: package.json, tsconfig.json, skedyul.config.ts, provision.ts, env.ts
5416
5449
  # And directories: src/, crm/, channels/, pages/, workflows/, agents/, etc.
5417
5450
  COPY . .
5418
5451
 
5452
+ ENV CI=true
5453
+
5454
+ # esbuild postinstall is required for tsup; pnpm 10+ blocks unapproved lifecycle scripts
5455
+ RUN printf '%s\\n' \\
5456
+ 'packages:' \\
5457
+ ' - "."' \\
5458
+ 'onlyBuiltDependencies:' \\
5459
+ ' - esbuild' \\
5460
+ 'allowBuilds:' \\
5461
+ ' esbuild: true' \\
5462
+ > pnpm-workspace.yaml
5463
+
5419
5464
  # Install dependencies (including dev deps for build), compile, export config, smoke test, then prune
5420
5465
  # Note: Using --no-frozen-lockfile since lockfile may not exist
5421
5466
  # skedyul build reads computeLayer from skedyul.config.ts
@@ -7224,6 +7269,7 @@ var index_default = { z: import_v413.z };
7224
7269
  defineWorkflowYAML,
7225
7270
  evaluateCondition,
7226
7271
  evaluateTemplate,
7272
+ event,
7227
7273
  file,
7228
7274
  formatContextForPrompt,
7229
7275
  formatSkillInstructions,
@@ -196,10 +196,12 @@ export declare const PoliciesConfigV3Schema: z.ZodObject<{
196
196
  export type PoliciesConfigV3 = z.infer<typeof PoliciesConfigV3Schema>;
197
197
  /**
198
198
  * Runtime configuration
199
- * Only `model` is actively used for LLM model selection.
199
+ * `model` selects the main reasoning LLM; `personaModel` selects the model
200
+ * used to apply persona voice/style to outbound messages.
200
201
  */
201
202
  export declare const RuntimeConfigV3Schema: z.ZodObject<{
202
203
  model: z.ZodOptional<z.ZodString>;
204
+ personaModel: z.ZodOptional<z.ZodString>;
203
205
  }, z.core.$strip>;
204
206
  export type RuntimeConfigV3 = z.infer<typeof RuntimeConfigV3Schema>;
205
207
  /**
@@ -368,6 +370,8 @@ export type TimeWindowDefault = z.infer<typeof TimeWindowDefaultSchema>;
368
370
  * - Scheduled messages: Future follow-ups
369
371
  */
370
372
  export declare const ResponsesBehaviorConfigSchema: z.ZodObject<{
373
+ maxImmediate: z.ZodOptional<z.ZodNumber>;
374
+ maxScheduled: z.ZodOptional<z.ZodNumber>;
371
375
  maxIntermediate: z.ZodOptional<z.ZodNumber>;
372
376
  requireFinal: z.ZodOptional<z.ZodBoolean>;
373
377
  allowSchedule: z.ZodOptional<z.ZodBoolean>;
@@ -430,6 +434,8 @@ export type SchedulingBehaviorConfig = z.infer<typeof SchedulingBehaviorConfigSc
430
434
  */
431
435
  export declare const BehaviorConfigV3Schema: z.ZodObject<{
432
436
  responses: z.ZodOptional<z.ZodObject<{
437
+ maxImmediate: z.ZodOptional<z.ZodNumber>;
438
+ maxScheduled: z.ZodOptional<z.ZodNumber>;
433
439
  maxIntermediate: z.ZodOptional<z.ZodNumber>;
434
440
  requireFinal: z.ZodOptional<z.ZodBoolean>;
435
441
  allowSchedule: z.ZodOptional<z.ZodBoolean>;
@@ -505,6 +511,7 @@ export declare const AgentYAMLV3Schema: z.ZodObject<{
505
511
  skills: z.ZodOptional<z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodObject<{
506
512
  skill: z.ZodString;
507
513
  description: z.ZodOptional<z.ZodString>;
514
+ alwaysLoad: z.ZodOptional<z.ZodBoolean>;
508
515
  version: z.ZodOptional<z.ZodNumber>;
509
516
  versions: z.ZodOptional<z.ZodArray<z.ZodObject<{
510
517
  version: z.ZodNumber;
@@ -628,6 +635,7 @@ export declare const AgentYAMLV3Schema: z.ZodObject<{
628
635
  }, z.core.$strip>>;
629
636
  runtime: z.ZodOptional<z.ZodObject<{
630
637
  model: z.ZodOptional<z.ZodString>;
638
+ personaModel: z.ZodOptional<z.ZodString>;
631
639
  }, z.core.$strip>>;
632
640
  prompts: z.ZodOptional<z.ZodObject<{
633
641
  system: z.ZodOptional<z.ZodString>;
@@ -640,6 +648,8 @@ export declare const AgentYAMLV3Schema: z.ZodObject<{
640
648
  }, z.core.$strip>>;
641
649
  behavior: z.ZodOptional<z.ZodObject<{
642
650
  responses: z.ZodOptional<z.ZodObject<{
651
+ maxImmediate: z.ZodOptional<z.ZodNumber>;
652
+ maxScheduled: z.ZodOptional<z.ZodNumber>;
643
653
  maxIntermediate: z.ZodOptional<z.ZodNumber>;
644
654
  requireFinal: z.ZodOptional<z.ZodBoolean>;
645
655
  allowSchedule: z.ZodOptional<z.ZodBoolean>;
@@ -269,6 +269,8 @@ var SkillRefSchema = import_v42.z.union([
269
269
  skill: import_v42.z.string(),
270
270
  description: import_v42.z.string().optional(),
271
271
  // For AI SDK Agent Skills discovery
272
+ /** Auto-inject this skill's instructions and tools on every agent turn */
273
+ alwaysLoad: import_v42.z.boolean().optional(),
272
274
  // Version selection (pick one):
273
275
  version: import_v42.z.number().optional(),
274
276
  // Pin to specific version number
@@ -473,8 +475,10 @@ var PoliciesConfigV3Schema = import_v44.z.object({
473
475
  }).optional()
474
476
  });
475
477
  var RuntimeConfigV3Schema = import_v44.z.object({
476
- /** LLM model identifier (e.g., "google/gemini-3.1-flash-lite") */
477
- model: import_v44.z.string().optional()
478
+ /** LLM model identifier for reasoning (e.g., "google/gemini-3.1-flash-lite") */
479
+ model: import_v44.z.string().optional(),
480
+ /** LLM model for persona transformation (e.g., "openai/gpt-5-nano") */
481
+ personaModel: import_v44.z.string().optional()
478
482
  });
479
483
  var TimeWindowTimeStampSchema = import_v44.z.union([
480
484
  import_v44.z.number().describe("Hour of day (0-23)"),
@@ -523,10 +527,21 @@ var TimeWindowDefaultSchema = TimeWindowBehaviorSchema.describe(
523
527
  "Fallback behavior when no time window matches"
524
528
  );
525
529
  var ResponsesBehaviorConfigSchema = import_v44.z.object({
530
+ /**
531
+ * Maximum immediate messages per agent run (acks, progress updates).
532
+ * @default 1
533
+ */
534
+ maxImmediate: import_v44.z.number().optional(),
535
+ /**
536
+ * Maximum scheduled messages per agent run (follow-ups via sendAt).
537
+ * @default 2
538
+ */
539
+ maxScheduled: import_v44.z.number().optional(),
526
540
  /**
527
541
  * Maximum intermediate messages per agent run.
528
542
  * Intermediate = progress updates, acknowledgments before task completion.
529
543
  * The final message slot is always reserved separately.
544
+ * @deprecated Use maxImmediate instead
530
545
  * @default 2
531
546
  */
532
547
  maxIntermediate: import_v44.z.number().optional(),
@@ -649,7 +664,7 @@ var AgentYAMLV3Schema = import_v44.z.object({
649
664
  memory: MemoryConfigV3Schema.optional(),
650
665
  // Policies - Business rules for the agent
651
666
  policies: PoliciesConfigV3Schema.optional(),
652
- // Runtime - Execution configuration (only model is used)
667
+ // Runtime - Execution configuration (model + personaModel)
653
668
  runtime: RuntimeConfigV3Schema.optional(),
654
669
  // Prompts - Agent-specific prompt injections
655
670
  prompts: PromptsConfigV3Schema.optional(),
@@ -216,6 +216,8 @@ var SkillRefSchema = z2.union([
216
216
  skill: z2.string(),
217
217
  description: z2.string().optional(),
218
218
  // For AI SDK Agent Skills discovery
219
+ /** Auto-inject this skill's instructions and tools on every agent turn */
220
+ alwaysLoad: z2.boolean().optional(),
219
221
  // Version selection (pick one):
220
222
  version: z2.number().optional(),
221
223
  // Pin to specific version number
@@ -420,8 +422,10 @@ var PoliciesConfigV3Schema = z4.object({
420
422
  }).optional()
421
423
  });
422
424
  var RuntimeConfigV3Schema = z4.object({
423
- /** LLM model identifier (e.g., "google/gemini-3.1-flash-lite") */
424
- model: z4.string().optional()
425
+ /** LLM model identifier for reasoning (e.g., "google/gemini-3.1-flash-lite") */
426
+ model: z4.string().optional(),
427
+ /** LLM model for persona transformation (e.g., "openai/gpt-5-nano") */
428
+ personaModel: z4.string().optional()
425
429
  });
426
430
  var TimeWindowTimeStampSchema = z4.union([
427
431
  z4.number().describe("Hour of day (0-23)"),
@@ -470,10 +474,21 @@ var TimeWindowDefaultSchema = TimeWindowBehaviorSchema.describe(
470
474
  "Fallback behavior when no time window matches"
471
475
  );
472
476
  var ResponsesBehaviorConfigSchema = z4.object({
477
+ /**
478
+ * Maximum immediate messages per agent run (acks, progress updates).
479
+ * @default 1
480
+ */
481
+ maxImmediate: z4.number().optional(),
482
+ /**
483
+ * Maximum scheduled messages per agent run (follow-ups via sendAt).
484
+ * @default 2
485
+ */
486
+ maxScheduled: z4.number().optional(),
473
487
  /**
474
488
  * Maximum intermediate messages per agent run.
475
489
  * Intermediate = progress updates, acknowledgments before task completion.
476
490
  * The final message slot is always reserved separately.
491
+ * @deprecated Use maxImmediate instead
477
492
  * @default 2
478
493
  */
479
494
  maxIntermediate: z4.number().optional(),
@@ -596,7 +611,7 @@ var AgentYAMLV3Schema = z4.object({
596
611
  memory: MemoryConfigV3Schema.optional(),
597
612
  // Policies - Business rules for the agent
598
613
  policies: PoliciesConfigV3Schema.optional(),
599
- // Runtime - Execution configuration (only model is used)
614
+ // Runtime - Execution configuration (model + personaModel)
600
615
  runtime: RuntimeConfigV3Schema.optional(),
601
616
  // Prompts - Agent-specific prompt injections
602
617
  prompts: PromptsConfigV3Schema.optional(),
@@ -230,6 +230,7 @@ export type SkillVersionWeight = z.infer<typeof SkillVersionWeightSchema>;
230
230
  export declare const SkillRefSchema: z.ZodUnion<readonly [z.ZodString, z.ZodObject<{
231
231
  skill: z.ZodString;
232
232
  description: z.ZodOptional<z.ZodString>;
233
+ alwaysLoad: z.ZodOptional<z.ZodBoolean>;
233
234
  version: z.ZodOptional<z.ZodNumber>;
234
235
  versions: z.ZodOptional<z.ZodArray<z.ZodObject<{
235
236
  version: z.ZodNumber;
@@ -129,6 +129,8 @@ var SkillRefSchema = import_v4.z.union([
129
129
  skill: import_v4.z.string(),
130
130
  description: import_v4.z.string().optional(),
131
131
  // For AI SDK Agent Skills discovery
132
+ /** Auto-inject this skill's instructions and tools on every agent turn */
133
+ alwaysLoad: import_v4.z.boolean().optional(),
132
134
  // Version selection (pick one):
133
135
  version: import_v4.z.number().optional(),
134
136
  // Pin to specific version number
@@ -83,6 +83,8 @@ var SkillRefSchema = z.union([
83
83
  skill: z.string(),
84
84
  description: z.string().optional(),
85
85
  // For AI SDK Agent Skills discovery
86
+ /** Auto-inject this skill's instructions and tools on every agent turn */
87
+ alwaysLoad: z.boolean().optional(),
86
88
  // Version selection (pick one):
87
89
  version: z.number().optional(),
88
90
  // Pin to specific version number
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "skedyul",
3
- "version": "1.2.48",
3
+ "version": "1.2.51",
4
4
  "description": "The Skedyul SDK for Node.js",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -64,7 +64,7 @@
64
64
  "build": "rm -rf dist tsconfig.tsbuildinfo && tsc --emitDeclarationOnly && tsup",
65
65
  "db:generate": "echo 'No database generation needed for this package'",
66
66
  "dev": "npx nodemon --watch src --ext js,ts --exec \"pnpm run build\"",
67
- "test": "tsc --project tsconfig.tests.json && node --test dist-tests/tests/server.test.js dist-tests/tests/cli.test.js"
67
+ "test": "tsc --project tsconfig.tests.json && node --test dist-tests/tests/server.test.js dist-tests/tests/cli.test.js dist-tests/tests/agent-schema-v3.test.js"
68
68
  },
69
69
  "keywords": [
70
70
  "mcp",