@alisio/core 0.1.0-alpha.22 → 0.1.0-alpha.23

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.
@@ -983,6 +983,8 @@ export async function createApplication(options = {}) {
983
983
  case "limits.maxTurns":
984
984
  case "limits.maxOutputTokens":
985
985
  case "limits.maxContextChars":
986
+ case "limits.firstTokenTimeoutMs":
987
+ case "limits.firstTokenRetries":
986
988
  case "limits.timeoutMs": {
987
989
  const patch = limitLeaf(key.slice("limits.".length));
988
990
  config.limits = { ...config.limits, ...patch };
package/dist/config.d.ts CHANGED
@@ -175,6 +175,8 @@ export declare const configSchema: z.ZodPipe<z.ZodObject<{
175
175
  limits: z.ZodDefault<z.ZodObject<{
176
176
  maxTurns: z.ZodDefault<z.ZodNumber>;
177
177
  timeoutMs: z.ZodDefault<z.ZodNumber>;
178
+ firstTokenTimeoutMs: z.ZodDefault<z.ZodNumber>;
179
+ firstTokenRetries: z.ZodDefault<z.ZodNumber>;
178
180
  maxContextChars: z.ZodDefault<z.ZodNumber>;
179
181
  maxOutputTokens: z.ZodDefault<z.ZodNumber>;
180
182
  maxTokens: z.ZodOptional<z.ZodNumber>;
@@ -270,6 +272,8 @@ export declare const configSchema: z.ZodPipe<z.ZodObject<{
270
272
  limits: {
271
273
  maxTurns: number;
272
274
  timeoutMs: number;
275
+ firstTokenTimeoutMs: number;
276
+ firstTokenRetries: number;
273
277
  maxContextChars: number;
274
278
  maxOutputTokens: number;
275
279
  maxTokens?: number | undefined;
@@ -442,6 +446,8 @@ export declare const configSchema: z.ZodPipe<z.ZodObject<{
442
446
  limits: {
443
447
  maxTurns: number;
444
448
  timeoutMs: number;
449
+ firstTokenTimeoutMs: number;
450
+ firstTokenRetries: number;
445
451
  maxContextChars: number;
446
452
  maxOutputTokens: number;
447
453
  maxTokens?: number | undefined;
@@ -555,6 +561,8 @@ declare const SETTABLE_KEYS: {
555
561
  readonly "limits.maxOutputTokens": z.ZodDefault<z.ZodNumber>;
556
562
  readonly "limits.maxContextChars": z.ZodDefault<z.ZodNumber>;
557
563
  readonly "limits.timeoutMs": z.ZodDefault<z.ZodNumber>;
564
+ readonly "limits.firstTokenTimeoutMs": z.ZodDefault<z.ZodNumber>;
565
+ readonly "limits.firstTokenRetries": z.ZodDefault<z.ZodNumber>;
558
566
  readonly "pluginHooks.timeoutMs": z.ZodDefault<z.ZodNumber>;
559
567
  readonly "tui.paddingX": z.ZodDefault<z.ZodNumber>;
560
568
  readonly "tui.contentPaddingX": z.ZodDefault<z.ZodNumber>;
package/dist/config.js CHANGED
@@ -173,7 +173,20 @@ const configObjectSchema = z
173
173
  limits: z
174
174
  .object({
175
175
  maxTurns: z.number().int().min(1).max(100).default(100),
176
- timeoutMs: z.number().int().min(100).default(300000),
176
+ timeoutMs: z.number().int().min(100).default(600000),
177
+ /**
178
+ * Stop a model request that stays completely silent (no text, reasoning or tool-call
179
+ * delta) this long, so a queued or stuck provider is cut after 90 s instead of the
180
+ * whole-run `timeoutMs`. 0 disables it (models that do not stream their reasoning can stay
181
+ * silent for minutes: raise or disable it for those).
182
+ */
183
+ firstTokenTimeoutMs: z.number().int().min(0).default(90000),
184
+ /**
185
+ * How many times the SAME request is sent again after it stayed silent for
186
+ * `firstTokenTimeoutMs` (a stalled connection usually answers on the next try). 0
187
+ * disables the retry. Never counts as a turn.
188
+ */
189
+ firstTokenRetries: z.number().int().min(0).max(3).default(1),
177
190
  maxContextChars: z.number().int().positive().default(800000),
178
191
  /**
179
192
  * Per-call output token budget for one agent turn. 4096 starves reasoning-heavy models,
@@ -185,7 +198,9 @@ const configObjectSchema = z
185
198
  })
186
199
  .default(() => ({
187
200
  maxTurns: 100,
188
- timeoutMs: 300000,
201
+ timeoutMs: 600000,
202
+ firstTokenTimeoutMs: 90000,
203
+ firstTokenRetries: 1,
189
204
  maxContextChars: 800000,
190
205
  maxOutputTokens: 16384,
191
206
  })),
@@ -686,6 +701,8 @@ const SETTABLE_KEYS = {
686
701
  "limits.maxOutputTokens": SETTABLE_SECTIONS.limits.shape.maxOutputTokens,
687
702
  "limits.maxContextChars": SETTABLE_SECTIONS.limits.shape.maxContextChars,
688
703
  "limits.timeoutMs": SETTABLE_SECTIONS.limits.shape.timeoutMs,
704
+ "limits.firstTokenTimeoutMs": SETTABLE_SECTIONS.limits.shape.firstTokenTimeoutMs,
705
+ "limits.firstTokenRetries": SETTABLE_SECTIONS.limits.shape.firstTokenRetries,
689
706
  "pluginHooks.timeoutMs": SETTABLE_SECTIONS.pluginHooks.shape.timeoutMs,
690
707
  "tui.paddingX": SETTABLE_SECTIONS.tui.shape.paddingX,
691
708
  "tui.contentPaddingX": SETTABLE_SECTIONS.tui.shape.contentPaddingX,
@@ -24,6 +24,10 @@ export interface RunnerOptions {
24
24
  workspace: string;
25
25
  maxTurns?: number;
26
26
  timeoutMs?: number;
27
+ /** See `RunnerSettingsPatch.firstTokenTimeoutMs`. */
28
+ firstTokenTimeoutMs?: number;
29
+ /** See `RunnerSettingsPatch.firstTokenRetries`. */
30
+ firstTokenRetries?: number;
27
31
  maxContextChars?: number;
28
32
  maxOutputTokens?: number;
29
33
  maxTokens?: number;
@@ -70,6 +74,17 @@ export interface RunnerSettingsPatch {
70
74
  maxContextChars?: number;
71
75
  /** Per-run timeout in milliseconds; the next run honors it. */
72
76
  timeoutMs?: number;
77
+ /**
78
+ * Stop a model request that stays completely silent (no text, reasoning or tool-call delta)
79
+ * for this many milliseconds. `0` or unset disables it: only the run timeout applies.
80
+ */
81
+ firstTokenTimeoutMs?: number;
82
+ /**
83
+ * How many times the same request is sent again after a silent timeout (`firstTokenTimeoutMs`).
84
+ * `0` or unset disables it. A retry is not a turn; it only happens while nothing at all was
85
+ * received for the request.
86
+ */
87
+ firstTokenRetries?: number;
73
88
  }
74
89
  /**
75
90
  * Per-run overrides used by embedders and child sessions. Callers must only NARROW: `policy`
@@ -97,6 +112,10 @@ export interface RunOptions {
97
112
  /** Per-call output token budget for this run; beats the runner-level budget when set. */
98
113
  maxOutputTokens?: number;
99
114
  timeoutMs?: number;
115
+ /** Silent-request limit for this run; beats the runner-level `firstTokenTimeoutMs`. */
116
+ firstTokenTimeoutMs?: number;
117
+ /** Silent-request retries for this run; beats the runner-level `firstTokenRetries`. */
118
+ firstTokenRetries?: number;
100
119
  /** Reasoning effort level for this run; beats the runner-level default when set. */
101
120
  reasoningEffort?: string;
102
121
  /** Run id to use for this run's events (e.g. preassigned by an embedder); a UUID otherwise. */
@@ -1,5 +1,21 @@
1
1
  import { isEphemeralRunEventType, textProjection, textResult, } from "@alisio/sdk";
2
2
  import { checkpointInstructions, estimateTokens, MAX_TRUSTED_WINDOW, parseCheckpointOutput, planCompaction, reduceMessagesToBudget, shouldCompactContext, summarize, summaryMessage, } from "./compaction.js";
3
+ import { isTimeoutReason, providerLabel, RunTimeoutError } from "./timeout.js";
4
+ /** Pause before a silent request is sent again; short, and cut off by a stop or the run limit. */
5
+ const FIRST_TOKEN_RETRY_PAUSE_MS = 250;
6
+ function abortableDelay(ms, signal) {
7
+ return new Promise((resolve) => {
8
+ if (signal.aborted)
9
+ return resolve();
10
+ const done = () => {
11
+ clearTimeout(timer);
12
+ signal.removeEventListener("abort", done);
13
+ resolve();
14
+ };
15
+ const timer = setTimeout(done, ms);
16
+ signal.addEventListener("abort", done, { once: true });
17
+ });
18
+ }
3
19
  /**
4
20
  * Default cumulative token budget for one run: several context windows (each turn re-sends the
5
21
  * context), clamped; 1M tokens when the window is unknown.
@@ -593,7 +609,8 @@ export class AgentRunner {
593
609
  /* A journal write failure cannot invalidate an executed run. */
594
610
  }
595
611
  };
596
- const timeout = AbortSignal.timeout(options.timeoutMs ?? o.timeoutMs ?? 300_000);
612
+ const runTimeoutMs = options.timeoutMs ?? o.timeoutMs ?? 300_000;
613
+ const timeout = AbortSignal.timeout(runTimeoutMs);
597
614
  const combined = AbortSignal.any([
598
615
  controller.signal,
599
616
  timeout,
@@ -656,6 +673,17 @@ export class AgentRunner {
656
673
  return { runId, status: "completed", result };
657
674
  }
658
675
  catch (error) {
676
+ if (combined.aborted && isTimeoutReason(combined.reason)) {
677
+ const failure = new RunTimeoutError({
678
+ kind: "run",
679
+ ms: runTimeoutMs,
680
+ stage: "tool",
681
+ tool: name,
682
+ });
683
+ emit("run_failed", { error: failure.message, code: "timeout", timeout: failure.info });
684
+ finish("failed", failure.message);
685
+ throw failure;
686
+ }
659
687
  const cause = combined.aborted ? (combined.reason ?? error) : error;
660
688
  const message = cause instanceof Error ? cause.message : String(cause);
661
689
  emit(combined.aborted ? "run_cancelled" : "run_failed", { error: message });
@@ -684,8 +712,21 @@ export class AgentRunner {
684
712
  const limit = o.maxContextChars ?? 800_000;
685
713
  let tokens = 0, lastText = "", acquired = false;
686
714
  const usageTotal = { input: 0, output: 0 };
687
- const timeout = AbortSignal.timeout(options.timeoutMs ?? o.timeoutMs ?? 300_000);
715
+ const runTimeoutMs = options.timeoutMs ?? o.timeoutMs ?? 300_000;
716
+ const firstTokenMs = options.firstTokenTimeoutMs ?? o.firstTokenTimeoutMs ?? 0;
717
+ const firstTokenRetries = firstTokenMs > 0 ? Math.max(0, options.firstTokenRetries ?? o.firstTokenRetries ?? 0) : 0;
718
+ const runStartedAt = Date.now();
719
+ const timeout = AbortSignal.timeout(runTimeoutMs);
688
720
  const combined = AbortSignal.any([controller.signal, timeout, ...(signal ? [signal] : [])]);
721
+ // What the run was doing, so a timeout can say where it was stuck (see `RunTimeoutError`).
722
+ let stage = "other";
723
+ let stageTool;
724
+ let modelId;
725
+ let providerName;
726
+ let requests = 0;
727
+ let silentTimedOut = false;
728
+ /** Sends of the request that is (or was last) waiting for its first token. */
729
+ let silentAttempts = 0;
689
730
  const context = options.context ?? o.context;
690
731
  const workspace = options.workspace ?? o.workspace;
691
732
  const pathAccess = o.pathAccess;
@@ -712,6 +753,8 @@ export class AgentRunner {
712
753
  throw new Error("Session provider/workspace mismatch");
713
754
  // The session records the model; switching models is explicit via setModel.
714
755
  const model = session.model;
756
+ modelId = model;
757
+ providerName = providerLabel(provider.id);
715
758
  combined.throwIfAborted();
716
759
  if (o.extensions && o.store.messages(sessionId).length === 0) {
717
760
  // New session: extensions may inject budgeted context once, persisted with the session.
@@ -822,39 +865,104 @@ export class AgentRunner {
822
865
  // display-only extension of the persisted transcript and never reach a model prompt
823
866
  // (raw image bytes included). The store keeps the rich parts for TUI replay.
824
867
  const providerMessages = messages.map((m) => m.role === "tool" ? { ...m, result: textProjection(m.result) } : m);
825
- const requested = Date.now();
868
+ let requested = Date.now();
826
869
  let firstDelta;
827
- for await (const e of provider.stream({
828
- instructions,
829
- messages: providerMessages,
830
- tools,
831
- maxOutputTokens: options.maxOutputTokens ?? o.maxOutputTokens ?? 4096,
832
- signal: combined,
833
- model,
834
- sessionId,
835
- ...(o.nativeTools?.length ? { nativeTools: o.nativeTools } : {}),
836
- ...((options.reasoningEffort ?? o.reasoningEffort)
837
- ? { reasoningEffort: options.reasoningEffort ?? o.reasoningEffort }
838
- : {}),
839
- })) {
840
- combined.throwIfAborted();
841
- if (e.type !== "completed")
842
- firstDelta ??= Date.now();
843
- if (e.type === "text_delta")
844
- emit("text_delta", { delta: e.delta });
845
- else if (e.type === "reasoning_delta")
846
- emit("reasoning_delta", { delta: e.delta });
847
- else {
848
- if (completion)
849
- throw new Error("Provider emitted multiple completions");
850
- completion = e.message;
851
- truncated = e.message.truncated === true;
852
- usage = e.usage;
853
- tokens += (e.usage?.input ?? 0) + (e.usage?.output ?? 0);
854
- usageTotal.input += e.usage?.input ?? 0;
855
- usageTotal.output += e.usage?.output ?? 0;
870
+ stage = "waiting_model";
871
+ requests++;
872
+ silentAttempts = 0;
873
+ // The same request is sent again only while the provider stayed completely silent until
874
+ // `firstTokenTimeoutMs`. Nothing was received, appended or accounted for the aborted
875
+ // attempt, so the retry reuses the exact same inputs inside this turn.
876
+ for (;;) {
877
+ silentAttempts++;
878
+ silentTimedOut = false;
879
+ requested = Date.now();
880
+ // A request that stays completely silent can be stopped early (`firstTokenTimeoutMs`).
881
+ const silent = new AbortController();
882
+ let silentTimer = firstTokenMs > 0
883
+ ? setTimeout(() => {
884
+ silentTimedOut = true;
885
+ silent.abort();
886
+ }, firstTokenMs)
887
+ : undefined;
888
+ const stopSilentTimer = () => {
889
+ if (silentTimer)
890
+ clearTimeout(silentTimer);
891
+ silentTimer = undefined;
892
+ };
893
+ let failure;
894
+ try {
895
+ for await (const e of provider.stream({
896
+ instructions,
897
+ messages: providerMessages,
898
+ tools,
899
+ maxOutputTokens: options.maxOutputTokens ?? o.maxOutputTokens ?? 4096,
900
+ signal: firstTokenMs > 0 ? AbortSignal.any([combined, silent.signal]) : combined,
901
+ model,
902
+ sessionId,
903
+ ...(o.nativeTools?.length ? { nativeTools: o.nativeTools } : {}),
904
+ ...((options.reasoningEffort ?? o.reasoningEffort)
905
+ ? { reasoningEffort: options.reasoningEffort ?? o.reasoningEffort }
906
+ : {}),
907
+ })) {
908
+ combined.throwIfAborted();
909
+ stopSilentTimer();
910
+ if (stage === "waiting_model")
911
+ stage = "streaming";
912
+ if (e.type !== "completed")
913
+ firstDelta ??= Date.now();
914
+ if (e.type === "text_delta")
915
+ emit("text_delta", { delta: e.delta });
916
+ else if (e.type === "reasoning_delta")
917
+ emit("reasoning_delta", { delta: e.delta });
918
+ else {
919
+ if (completion)
920
+ throw new Error("Provider emitted multiple completions");
921
+ completion = e.message;
922
+ truncated = e.message.truncated === true;
923
+ usage = e.usage;
924
+ tokens += (e.usage?.input ?? 0) + (e.usage?.output ?? 0);
925
+ usageTotal.input += e.usage?.input ?? 0;
926
+ usageTotal.output += e.usage?.output ?? 0;
927
+ }
928
+ }
856
929
  }
930
+ catch (error) {
931
+ failure = error;
932
+ }
933
+ finally {
934
+ stopSilentTimer();
935
+ }
936
+ const silentFailure = silentTimedOut &&
937
+ firstDelta === undefined &&
938
+ !completion &&
939
+ !combined.aborted &&
940
+ silentAttempts <= firstTokenRetries;
941
+ if (!silentFailure) {
942
+ if (failure !== undefined)
943
+ throw failure;
944
+ break;
945
+ }
946
+ // Do not start an attempt the whole-run limit could not let finish.
947
+ const retryPauseMs = FIRST_TOKEN_RETRY_PAUSE_MS;
948
+ if (runTimeoutMs - (Date.now() - runStartedAt) < retryPauseMs + firstTokenMs) {
949
+ if (failure !== undefined)
950
+ throw failure;
951
+ break;
952
+ }
953
+ // From here the silence is handled: a later stop or run timeout is judged on its own.
954
+ silentTimedOut = false;
955
+ emit("request_retry", {
956
+ attempt: silentAttempts,
957
+ of: firstTokenRetries,
958
+ reason: "first_token_timeout",
959
+ afterMs: Date.now() - requested,
960
+ });
961
+ await abortableDelay(retryPauseMs, combined);
962
+ combined.throwIfAborted();
963
+ stage = "waiting_model";
857
964
  }
965
+ stage = "other";
858
966
  if (!completion)
859
967
  throw new Error("Provider stream ended without a completed response");
860
968
  const durationMs = Date.now() - requested;
@@ -944,6 +1052,8 @@ export class AgentRunner {
944
1052
  };
945
1053
  },
946
1054
  };
1055
+ stage = "tool";
1056
+ stageTool = prepared[0]?.call.name;
947
1057
  const execute = (p) => this.executeCall(scope, p);
948
1058
  const results = [];
949
1059
  // Bounded parallel batches for consecutive read or explicitly concurrent tools.
@@ -974,6 +1084,8 @@ export class AgentRunner {
974
1084
  if (c && r)
975
1085
  o.store.append(sessionId, { role: "tool", callId: c.id, result: r });
976
1086
  }
1087
+ stage = "other";
1088
+ stageTool = undefined;
977
1089
  if (tokens >= budget)
978
1090
  throw new Error("Token budget exhausted");
979
1091
  }
@@ -986,6 +1098,24 @@ export class AgentRunner {
986
1098
  return { sessionId, text: lastText, status: "turns-exceeded", usage: usageTotal };
987
1099
  }
988
1100
  catch (error) {
1101
+ const timedOut = silentTimedOut
1102
+ ? { kind: "first_token", ms: firstTokenMs, attempts: Math.max(1, silentAttempts) }
1103
+ : combined.aborted && isTimeoutReason(combined.reason)
1104
+ ? { kind: "run", ms: runTimeoutMs }
1105
+ : undefined;
1106
+ if (timedOut && !(combined.aborted && !isTimeoutReason(combined.reason))) {
1107
+ const failure = new RunTimeoutError({
1108
+ ...timedOut,
1109
+ ...(modelId ? { model: modelId } : {}),
1110
+ ...(providerName ? { provider: providerName } : {}),
1111
+ stage,
1112
+ ...(stage === "tool" && stageTool ? { tool: stageTool } : {}),
1113
+ ...(requests <= 1 ? { firstRequest: true } : {}),
1114
+ });
1115
+ emit("run_failed", { error: failure.message, code: "timeout", timeout: failure.info });
1116
+ finish("failed", failure.message);
1117
+ throw failure;
1118
+ }
989
1119
  // On cancellation report the abort reason, not the transport's secondary error.
990
1120
  const cause = combined.aborted ? (combined.reason ?? error) : error;
991
1121
  const message = cause instanceof Error ? cause.message : String(cause);
@@ -0,0 +1,15 @@
1
+ import type { RunTimeoutInfo } from "@alisio/sdk";
2
+ /** A run stopped by a time limit; the message says which limit, which model and what to do. */
3
+ export declare class RunTimeoutError extends Error {
4
+ readonly info: RunTimeoutInfo;
5
+ constructor(info: RunTimeoutInfo);
6
+ }
7
+ /** `AbortSignal.timeout` aborts with a `TimeoutError`; an explicit `abort()` does not. */
8
+ export declare function isTimeoutReason(reason: unknown): boolean;
9
+ /**
10
+ * A short, human label for a provider id: the host of an OpenAI-compatible endpoint
11
+ * (`openai-compatible:chat:https://api.example.com/v1` → `api.example.com`), else the id itself.
12
+ */
13
+ export declare function providerLabel(id: string | undefined): string | undefined;
14
+ /** Plain-text message of a timeout (TUI, headless, logs, the `runs.error` column). English only. */
15
+ export declare function describeTimeout(info: RunTimeoutInfo): string;
@@ -0,0 +1,61 @@
1
+ /** A run stopped by a time limit; the message says which limit, which model and what to do. */
2
+ export class RunTimeoutError extends Error {
3
+ info;
4
+ constructor(info) {
5
+ super(describeTimeout(info));
6
+ this.name = "RunTimeoutError";
7
+ this.info = info;
8
+ }
9
+ }
10
+ /** `AbortSignal.timeout` aborts with a `TimeoutError`; an explicit `abort()` does not. */
11
+ export function isTimeoutReason(reason) {
12
+ return (typeof reason === "object" &&
13
+ reason !== null &&
14
+ reason.name === "TimeoutError");
15
+ }
16
+ /**
17
+ * A short, human label for a provider id: the host of an OpenAI-compatible endpoint
18
+ * (`openai-compatible:chat:https://api.example.com/v1` → `api.example.com`), else the id itself.
19
+ */
20
+ export function providerLabel(id) {
21
+ if (!id)
22
+ return undefined;
23
+ const url = /(https?:\/\/[^\s]+)/.exec(id)?.[1];
24
+ if (url)
25
+ try {
26
+ return new URL(url).host;
27
+ }
28
+ catch {
29
+ /* fall through to the raw id */
30
+ }
31
+ return id;
32
+ }
33
+ const seconds = (ms) => Math.round(ms / 1000);
34
+ /** Plain-text message of a timeout (TUI, headless, logs, the `runs.error` column). English only. */
35
+ export function describeTimeout(info) {
36
+ const who = info.model
37
+ ? `The model ${info.model}${info.provider ? ` (${info.provider})` : ""}`
38
+ : "The model";
39
+ const limit = `${seconds(info.ms)} s`;
40
+ if (info.kind === "first_token" && info.attempts && info.attempts > 1)
41
+ return (`${who} did not respond after ${info.attempts} attempts of ${limit} each: no tokens were received, so the run was stopped. ` +
42
+ "Retry, switch to another model, or raise or disable limits.firstTokenTimeoutMs (0 disables it); " +
43
+ "limits.firstTokenRetries sets how many times a silent request is sent again.");
44
+ if (info.kind === "first_token")
45
+ return (`${who} sent nothing within ${limit} of the request, so the run was stopped. ` +
46
+ "Retry, switch to another model, or raise or disable limits.firstTokenTimeoutMs (0 disables it).");
47
+ if (info.stage === "waiting_model")
48
+ return info.firstRequest
49
+ ? `${who} did not respond within ${limit}: no tokens were received. ` +
50
+ "Retry, switch to another model, or raise limits.timeoutMs."
51
+ : `The run reached its ${limit} limit while waiting for ${info.model ? `the model ${info.model}` : "the model"}` +
52
+ `${info.provider ? ` (${info.provider})` : ""}. ` +
53
+ "Everything produced so far is kept: prompt again to continue, switch model, or raise limits.timeoutMs.";
54
+ const doing = info.stage === "tool" && info.tool
55
+ ? `while running ${info.tool}`
56
+ : info.stage === "streaming"
57
+ ? "while the model was answering"
58
+ : "";
59
+ return (`The run reached its ${limit} limit${doing ? ` ${doing}` : ""}. ` +
60
+ "Everything produced so far is kept: prompt again to continue, or raise limits.timeoutMs.");
61
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@alisio/core",
3
- "version": "0.1.0-alpha.22",
3
+ "version": "0.1.0-alpha.23",
4
4
  "description": "Embeddable provider-agnostic Alisio agent core: tool loop, context compaction, local tools, MCP, plugin host and SQLite session store. Runs on Node >=22.16 and Bun.",
5
5
  "author": "Gustavo Gutiérrez",
6
6
  "license": "MIT",
@@ -41,7 +41,7 @@
41
41
  "node": ">=22.16"
42
42
  },
43
43
  "dependencies": {
44
- "@alisio/sdk": "0.1.0-alpha.18",
44
+ "@alisio/sdk": "0.1.0-alpha.19",
45
45
  "@mixmark-io/domino": "2.2.0",
46
46
  "@modelcontextprotocol/client": "2.1.0",
47
47
  "ajv": "8.20.0",