@dudko.dev/agent-web 0.0.4 → 0.0.5

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.d.cts CHANGED
@@ -24,6 +24,29 @@ declare class MemoryStore implements ContextStore {
24
24
  clear(sessionId: string): Promise<void>;
25
25
  }
26
26
 
27
+ /**
28
+ * Leveled logging for the agent. The host passes a console-like sink and a
29
+ * level; everything below the level is a no-op. Default: 'warn' onto the
30
+ * global console — silent in normal operation, but salvage fallbacks, empty
31
+ * plans, degraded tool modes and failed tool calls stay visible.
32
+ *
33
+ * Set `logLevel: 'debug'` to see every phase's raw model output, parsed
34
+ * results and tool dispatches — the first thing to reach for when the agent
35
+ * "says it did something but nothing happened".
36
+ */
37
+ type LogLevel = 'silent' | 'error' | 'warn' | 'info' | 'debug';
38
+ /** Console-compatible sink (pass `console`, or your own collector). */
39
+ interface AgentLoggerSink {
40
+ error(...args: unknown[]): void;
41
+ warn(...args: unknown[]): void;
42
+ info(...args: unknown[]): void;
43
+ debug(...args: unknown[]): void;
44
+ }
45
+ interface AgentLogger extends AgentLoggerSink {
46
+ readonly level: LogLevel;
47
+ }
48
+ declare const createLogger: (level?: LogLevel, sink?: AgentLoggerSink) => AgentLogger;
49
+
27
50
  /**
28
51
  * Providers the browser registry can resolve from a spec. This is deliberately
29
52
  * a browser-safe subset of the Node sibling's list: Amazon Bedrock (SigV4
@@ -283,6 +306,10 @@ interface BrowserAgentConfig {
283
306
  synthesize?: boolean;
284
307
  /** Compress stored history past this many chars (0 = off, default 12000). */
285
308
  compressAfterChars?: number;
309
+ /** Verbosity: 'silent' | 'error' | 'warn' (default) | 'info' | 'debug'. */
310
+ logLevel?: LogLevel;
311
+ /** Console-like sink the logs go to (default: the global console). */
312
+ logger?: AgentLoggerSink;
286
313
  }
287
314
  interface ResolvedConfig {
288
315
  clientName: string;
@@ -298,6 +325,7 @@ interface ResolvedConfig {
298
325
  replan: boolean;
299
326
  synthesize: boolean;
300
327
  compressAfterChars: number;
328
+ logLevel: LogLevel;
301
329
  }
302
330
  declare const resolveConfig: (c: BrowserAgentConfig) => ResolvedConfig;
303
331
 
@@ -494,6 +522,8 @@ interface AgentContext {
494
522
  toolCatalog: string;
495
523
  prompts: Prompts;
496
524
  emit: (event: AgentEvent) => void;
525
+ /** Leveled logger (config.logLevel over config.logger ?? console). */
526
+ log: AgentLogger;
497
527
  signal?: AbortSignal;
498
528
  /** Current world state for grounding, or undefined when no describeState is configured. */
499
529
  state: () => Promise<string | undefined>;
@@ -508,7 +538,9 @@ interface AgentContext {
508
538
  * throwing, so the run degrades gracefully. An empty `steps` list signals the
509
539
  * runner to answer directly (greeting / question / unclear).
510
540
  */
511
- declare const createPlan: (ctx: AgentContext, goal: string) => Promise<{
541
+ declare const createPlan: (ctx: AgentContext, goal: string,
542
+ /** Extra instruction appended to the goal (used by the empty-plan retry). */
543
+ nudge?: string) => Promise<{
512
544
  plan: IPlan;
513
545
  usage: IUsage;
514
546
  }>;
@@ -624,14 +656,45 @@ interface WebLLMModelOptions {
624
656
  progress: number;
625
657
  text: string;
626
658
  }) => void;
659
+ /**
660
+ * Download the weights and initialize the engine NOW (default true).
661
+ *
662
+ * The underlying provider initializes lazily on the first generation — with
663
+ * a multi-GB model that means the download would silently happen on the
664
+ * user's first message, with `initProgressCallback` never firing at a moment
665
+ * the host can show it. Preloading runs a 1-token warm-up so the returned
666
+ * model is truly ready and progress is reported during creation. Re-creating
667
+ * an already-downloaded model is fast (weights live in the browser cache).
668
+ *
669
+ * Set to `false` to keep the lazy behavior.
670
+ */
671
+ preload?: boolean;
627
672
  /** Any other @browser-ai/web-llm setting (temperature, worker handler, …). */
628
673
  [k: string]: unknown;
629
674
  }
675
+ /**
676
+ * Force a model to download its weights and initialize its engine by running
677
+ * a 1-token generation. Exposed for hosts that create models with
678
+ * `preload: false` and want to warm them up later (e.g. behind their own UI).
679
+ */
680
+ declare const preloadWebLLMModel: (model: LanguageModel) => Promise<void>;
681
+ /**
682
+ * Best-effort release of a model's GPU memory (call when switching models —
683
+ * an abandoned engine otherwise holds its buffers until the page reloads).
684
+ *
685
+ * `@browser-ai/web-llm` keeps its MLCEngine private and exposes no public
686
+ * `unload()`, so this reaches into the instance defensively; it is a no-op on
687
+ * an uninitialized model or if the provider's internals change shape.
688
+ */
689
+ declare const unloadWebLLMModel: (model: LanguageModel) => Promise<void>;
630
690
  /**
631
691
  * Build an AI SDK `LanguageModel` backed by WebLLM (WebGPU) via the community
632
692
  * provider `@browser-ai/web-llm` (an optional peer, dynamically imported so it
633
693
  * is code-split and never loads until a local model is actually used). Accepts
634
694
  * any WebLLM prebuilt model id, e.g. "Llama-3.2-3B-Instruct-q4f16_1-MLC".
695
+ *
696
+ * By default the weights are downloaded eagerly with progress (see
697
+ * `WebLLMModelOptions.preload`).
635
698
  */
636
699
  declare const createWebLLMModel: (model: string, options?: WebLLMModelOptions) => Promise<LanguageModel>;
637
700
 
@@ -863,4 +926,4 @@ interface CompressOptions {
863
926
  */
864
927
  declare const compressHistory: (messages: StoredMessage[], model: LanguageModel, opts?: CompressOptions) => Promise<StoredMessage[]>;
865
928
 
866
- export { type Agent, type AgentContext, type AgentEvent, type AgentEventHandler, type AgentTool, type AgentToolSet, type AgentWebDBOptions, type BrowserAgentConfig, type CompressOptions, type ContextStore, type CredentialStore, type EncryptedBlob, type ExecutorPromptContext, type ExecutorResult, type GenerateOptions, type IPlan, type IPlanStep, type IStepResult, type IToolCall, type IUsage, IndexedDBStore, type IndexedDBStoreOptions, IndexedDBVault, KEYS_STORE, MemoryCredentialStore, MemoryStore, type ModelInput, type Phase, type PhaseBudgets, PlanSchema, type PlanShape, PlanStepSchema, type PlannerPromptContext, type PlannerResult, type PromptParts, type Prompts, type ProviderModelSpec, type ProviderType, type RawAction, type ReplanDecision, type ReplanMode, ReplanSchema, type ReplanShape, type ReplannerPromptContext, type ReplannerResult, type ResolvedConfig, type ResolvedStage, type RunOptions, type RunResult, SECRETS_STORE, SESSIONS_STORE, type StageInput, type StageOverride, type StoredMessage, type SynthesizerPromptContext, type ToolCallMode, type ToolLoopCallbacks, type ToolLoopOptions, type ToolLoopResult, type ToolMode, type ToolSelectionStrategy, VaultCredentialStore, type VaultOptions, type WebLLMModelOptions, buildModelFromStage, compressHistory, createAgent, createPlan, createWebLLMModel, decideReplan, decryptJSON, defaultPrompts, defineTool, directBrowserOk, dispatch, encryptJSON, executeStep, generate, generateStructured, getOrCreateVaultKey, isDirectModel, isProviderSpec, isWebGPUAvailable, looksLikeJson, normalizeSteps, normalizeUsage, openAgentWebDB, parseExecutorResponse, parsePlainText, parsePlannerResponse, parseReplannerResponse, promptHintOf, renderCatalog, resolveConfig, resolveModel, resolveStage, runToolLoop, selectToolMode, shouldReplan, splitBlocker, stream, supportsNativeTools, supportsStructuredOutput, synthesizeAnswer, withSystem };
929
+ export { type Agent, type AgentContext, type AgentEvent, type AgentEventHandler, type AgentLogger, type AgentLoggerSink, type AgentTool, type AgentToolSet, type AgentWebDBOptions, type BrowserAgentConfig, type CompressOptions, type ContextStore, type CredentialStore, type EncryptedBlob, type ExecutorPromptContext, type ExecutorResult, type GenerateOptions, type IPlan, type IPlanStep, type IStepResult, type IToolCall, type IUsage, IndexedDBStore, type IndexedDBStoreOptions, IndexedDBVault, KEYS_STORE, type LogLevel, MemoryCredentialStore, MemoryStore, type ModelInput, type Phase, type PhaseBudgets, PlanSchema, type PlanShape, PlanStepSchema, type PlannerPromptContext, type PlannerResult, type PromptParts, type Prompts, type ProviderModelSpec, type ProviderType, type RawAction, type ReplanDecision, type ReplanMode, ReplanSchema, type ReplanShape, type ReplannerPromptContext, type ReplannerResult, type ResolvedConfig, type ResolvedStage, type RunOptions, type RunResult, SECRETS_STORE, SESSIONS_STORE, type StageInput, type StageOverride, type StoredMessage, type SynthesizerPromptContext, type ToolCallMode, type ToolLoopCallbacks, type ToolLoopOptions, type ToolLoopResult, type ToolMode, type ToolSelectionStrategy, VaultCredentialStore, type VaultOptions, type WebLLMModelOptions, buildModelFromStage, compressHistory, createAgent, createLogger, createPlan, createWebLLMModel, decideReplan, decryptJSON, defaultPrompts, defineTool, directBrowserOk, dispatch, encryptJSON, executeStep, generate, generateStructured, getOrCreateVaultKey, isDirectModel, isProviderSpec, isWebGPUAvailable, looksLikeJson, normalizeSteps, normalizeUsage, openAgentWebDB, parseExecutorResponse, parsePlainText, parsePlannerResponse, parseReplannerResponse, preloadWebLLMModel, promptHintOf, renderCatalog, resolveConfig, resolveModel, resolveStage, runToolLoop, selectToolMode, shouldReplan, splitBlocker, stream, supportsNativeTools, supportsStructuredOutput, synthesizeAnswer, unloadWebLLMModel, withSystem };
package/dist/index.d.ts CHANGED
@@ -24,6 +24,29 @@ declare class MemoryStore implements ContextStore {
24
24
  clear(sessionId: string): Promise<void>;
25
25
  }
26
26
 
27
+ /**
28
+ * Leveled logging for the agent. The host passes a console-like sink and a
29
+ * level; everything below the level is a no-op. Default: 'warn' onto the
30
+ * global console — silent in normal operation, but salvage fallbacks, empty
31
+ * plans, degraded tool modes and failed tool calls stay visible.
32
+ *
33
+ * Set `logLevel: 'debug'` to see every phase's raw model output, parsed
34
+ * results and tool dispatches — the first thing to reach for when the agent
35
+ * "says it did something but nothing happened".
36
+ */
37
+ type LogLevel = 'silent' | 'error' | 'warn' | 'info' | 'debug';
38
+ /** Console-compatible sink (pass `console`, or your own collector). */
39
+ interface AgentLoggerSink {
40
+ error(...args: unknown[]): void;
41
+ warn(...args: unknown[]): void;
42
+ info(...args: unknown[]): void;
43
+ debug(...args: unknown[]): void;
44
+ }
45
+ interface AgentLogger extends AgentLoggerSink {
46
+ readonly level: LogLevel;
47
+ }
48
+ declare const createLogger: (level?: LogLevel, sink?: AgentLoggerSink) => AgentLogger;
49
+
27
50
  /**
28
51
  * Providers the browser registry can resolve from a spec. This is deliberately
29
52
  * a browser-safe subset of the Node sibling's list: Amazon Bedrock (SigV4
@@ -283,6 +306,10 @@ interface BrowserAgentConfig {
283
306
  synthesize?: boolean;
284
307
  /** Compress stored history past this many chars (0 = off, default 12000). */
285
308
  compressAfterChars?: number;
309
+ /** Verbosity: 'silent' | 'error' | 'warn' (default) | 'info' | 'debug'. */
310
+ logLevel?: LogLevel;
311
+ /** Console-like sink the logs go to (default: the global console). */
312
+ logger?: AgentLoggerSink;
286
313
  }
287
314
  interface ResolvedConfig {
288
315
  clientName: string;
@@ -298,6 +325,7 @@ interface ResolvedConfig {
298
325
  replan: boolean;
299
326
  synthesize: boolean;
300
327
  compressAfterChars: number;
328
+ logLevel: LogLevel;
301
329
  }
302
330
  declare const resolveConfig: (c: BrowserAgentConfig) => ResolvedConfig;
303
331
 
@@ -494,6 +522,8 @@ interface AgentContext {
494
522
  toolCatalog: string;
495
523
  prompts: Prompts;
496
524
  emit: (event: AgentEvent) => void;
525
+ /** Leveled logger (config.logLevel over config.logger ?? console). */
526
+ log: AgentLogger;
497
527
  signal?: AbortSignal;
498
528
  /** Current world state for grounding, or undefined when no describeState is configured. */
499
529
  state: () => Promise<string | undefined>;
@@ -508,7 +538,9 @@ interface AgentContext {
508
538
  * throwing, so the run degrades gracefully. An empty `steps` list signals the
509
539
  * runner to answer directly (greeting / question / unclear).
510
540
  */
511
- declare const createPlan: (ctx: AgentContext, goal: string) => Promise<{
541
+ declare const createPlan: (ctx: AgentContext, goal: string,
542
+ /** Extra instruction appended to the goal (used by the empty-plan retry). */
543
+ nudge?: string) => Promise<{
512
544
  plan: IPlan;
513
545
  usage: IUsage;
514
546
  }>;
@@ -624,14 +656,45 @@ interface WebLLMModelOptions {
624
656
  progress: number;
625
657
  text: string;
626
658
  }) => void;
659
+ /**
660
+ * Download the weights and initialize the engine NOW (default true).
661
+ *
662
+ * The underlying provider initializes lazily on the first generation — with
663
+ * a multi-GB model that means the download would silently happen on the
664
+ * user's first message, with `initProgressCallback` never firing at a moment
665
+ * the host can show it. Preloading runs a 1-token warm-up so the returned
666
+ * model is truly ready and progress is reported during creation. Re-creating
667
+ * an already-downloaded model is fast (weights live in the browser cache).
668
+ *
669
+ * Set to `false` to keep the lazy behavior.
670
+ */
671
+ preload?: boolean;
627
672
  /** Any other @browser-ai/web-llm setting (temperature, worker handler, …). */
628
673
  [k: string]: unknown;
629
674
  }
675
+ /**
676
+ * Force a model to download its weights and initialize its engine by running
677
+ * a 1-token generation. Exposed for hosts that create models with
678
+ * `preload: false` and want to warm them up later (e.g. behind their own UI).
679
+ */
680
+ declare const preloadWebLLMModel: (model: LanguageModel) => Promise<void>;
681
+ /**
682
+ * Best-effort release of a model's GPU memory (call when switching models —
683
+ * an abandoned engine otherwise holds its buffers until the page reloads).
684
+ *
685
+ * `@browser-ai/web-llm` keeps its MLCEngine private and exposes no public
686
+ * `unload()`, so this reaches into the instance defensively; it is a no-op on
687
+ * an uninitialized model or if the provider's internals change shape.
688
+ */
689
+ declare const unloadWebLLMModel: (model: LanguageModel) => Promise<void>;
630
690
  /**
631
691
  * Build an AI SDK `LanguageModel` backed by WebLLM (WebGPU) via the community
632
692
  * provider `@browser-ai/web-llm` (an optional peer, dynamically imported so it
633
693
  * is code-split and never loads until a local model is actually used). Accepts
634
694
  * any WebLLM prebuilt model id, e.g. "Llama-3.2-3B-Instruct-q4f16_1-MLC".
695
+ *
696
+ * By default the weights are downloaded eagerly with progress (see
697
+ * `WebLLMModelOptions.preload`).
635
698
  */
636
699
  declare const createWebLLMModel: (model: string, options?: WebLLMModelOptions) => Promise<LanguageModel>;
637
700
 
@@ -863,4 +926,4 @@ interface CompressOptions {
863
926
  */
864
927
  declare const compressHistory: (messages: StoredMessage[], model: LanguageModel, opts?: CompressOptions) => Promise<StoredMessage[]>;
865
928
 
866
- export { type Agent, type AgentContext, type AgentEvent, type AgentEventHandler, type AgentTool, type AgentToolSet, type AgentWebDBOptions, type BrowserAgentConfig, type CompressOptions, type ContextStore, type CredentialStore, type EncryptedBlob, type ExecutorPromptContext, type ExecutorResult, type GenerateOptions, type IPlan, type IPlanStep, type IStepResult, type IToolCall, type IUsage, IndexedDBStore, type IndexedDBStoreOptions, IndexedDBVault, KEYS_STORE, MemoryCredentialStore, MemoryStore, type ModelInput, type Phase, type PhaseBudgets, PlanSchema, type PlanShape, PlanStepSchema, type PlannerPromptContext, type PlannerResult, type PromptParts, type Prompts, type ProviderModelSpec, type ProviderType, type RawAction, type ReplanDecision, type ReplanMode, ReplanSchema, type ReplanShape, type ReplannerPromptContext, type ReplannerResult, type ResolvedConfig, type ResolvedStage, type RunOptions, type RunResult, SECRETS_STORE, SESSIONS_STORE, type StageInput, type StageOverride, type StoredMessage, type SynthesizerPromptContext, type ToolCallMode, type ToolLoopCallbacks, type ToolLoopOptions, type ToolLoopResult, type ToolMode, type ToolSelectionStrategy, VaultCredentialStore, type VaultOptions, type WebLLMModelOptions, buildModelFromStage, compressHistory, createAgent, createPlan, createWebLLMModel, decideReplan, decryptJSON, defaultPrompts, defineTool, directBrowserOk, dispatch, encryptJSON, executeStep, generate, generateStructured, getOrCreateVaultKey, isDirectModel, isProviderSpec, isWebGPUAvailable, looksLikeJson, normalizeSteps, normalizeUsage, openAgentWebDB, parseExecutorResponse, parsePlainText, parsePlannerResponse, parseReplannerResponse, promptHintOf, renderCatalog, resolveConfig, resolveModel, resolveStage, runToolLoop, selectToolMode, shouldReplan, splitBlocker, stream, supportsNativeTools, supportsStructuredOutput, synthesizeAnswer, withSystem };
929
+ export { type Agent, type AgentContext, type AgentEvent, type AgentEventHandler, type AgentLogger, type AgentLoggerSink, type AgentTool, type AgentToolSet, type AgentWebDBOptions, type BrowserAgentConfig, type CompressOptions, type ContextStore, type CredentialStore, type EncryptedBlob, type ExecutorPromptContext, type ExecutorResult, type GenerateOptions, type IPlan, type IPlanStep, type IStepResult, type IToolCall, type IUsage, IndexedDBStore, type IndexedDBStoreOptions, IndexedDBVault, KEYS_STORE, type LogLevel, MemoryCredentialStore, MemoryStore, type ModelInput, type Phase, type PhaseBudgets, PlanSchema, type PlanShape, PlanStepSchema, type PlannerPromptContext, type PlannerResult, type PromptParts, type Prompts, type ProviderModelSpec, type ProviderType, type RawAction, type ReplanDecision, type ReplanMode, ReplanSchema, type ReplanShape, type ReplannerPromptContext, type ReplannerResult, type ResolvedConfig, type ResolvedStage, type RunOptions, type RunResult, SECRETS_STORE, SESSIONS_STORE, type StageInput, type StageOverride, type StoredMessage, type SynthesizerPromptContext, type ToolCallMode, type ToolLoopCallbacks, type ToolLoopOptions, type ToolLoopResult, type ToolMode, type ToolSelectionStrategy, VaultCredentialStore, type VaultOptions, type WebLLMModelOptions, buildModelFromStage, compressHistory, createAgent, createLogger, createPlan, createWebLLMModel, decideReplan, decryptJSON, defaultPrompts, defineTool, directBrowserOk, dispatch, encryptJSON, executeStep, generate, generateStructured, getOrCreateVaultKey, isDirectModel, isProviderSpec, isWebGPUAvailable, looksLikeJson, normalizeSteps, normalizeUsage, openAgentWebDB, parseExecutorResponse, parsePlainText, parsePlannerResponse, parseReplannerResponse, preloadWebLLMModel, promptHintOf, renderCatalog, resolveConfig, resolveModel, resolveStage, runToolLoop, selectToolMode, shouldReplan, splitBlocker, stream, supportsNativeTools, supportsStructuredOutput, synthesizeAnswer, unloadWebLLMModel, withSystem };
package/dist/index.js CHANGED
@@ -1,7 +1,9 @@
1
1
  import {
2
2
  createWebLLMModel,
3
- isWebGPUAvailable
4
- } from "./chunk-R7H4HSYT.js";
3
+ isWebGPUAvailable,
4
+ preloadWebLLMModel,
5
+ unloadWebLLMModel
6
+ } from "./chunk-IT65EW77.js";
5
7
 
6
8
  // src/config.ts
7
9
  var resolveConfig = (c) => ({
@@ -22,7 +24,8 @@ var resolveConfig = (c) => ({
22
24
  temperature: c.temperature,
23
25
  replan: c.replan ?? true,
24
26
  synthesize: c.synthesize ?? true,
25
- compressAfterChars: c.compressAfterChars ?? 12e3
27
+ compressAfterChars: c.compressAfterChars ?? 12e3,
28
+ logLevel: c.logLevel ?? "warn"
26
29
  });
27
30
 
28
31
  // src/llm/generate.ts
@@ -211,7 +214,7 @@ var buildModelFromStage = async (resolved, credentials, clientName = "agent-web"
211
214
  const apiKey = await resolveApiKey(spec, credentials);
212
215
  switch (spec.providerType) {
213
216
  case "web-llm": {
214
- const { createWebLLMModel: createWebLLMModel2 } = await import("./webllm-IM3UD6YI.js");
217
+ const { createWebLLMModel: createWebLLMModel2 } = await import("./webllm-XUBUNKFN.js");
215
218
  return createWebLLMModel2(spec.model, providerOptions);
216
219
  }
217
220
  case "gateway": {
@@ -741,10 +744,17 @@ var executeStep = async (ctx, goal, step, index, total, done) => {
741
744
  timeoutMs: ctx.config.chatTimeoutMs,
742
745
  callbacks: {
743
746
  onTextDelta: (delta) => ctx.emit({ type: "step.text-delta", step, delta }),
744
- onToolCall: (name, input) => ctx.emit({ type: "step.tool-call", step, name, input }),
745
- onToolResult: (name, output, ok) => ctx.emit({ type: "step.tool-result", step, name, output, ok })
747
+ onToolCall: (name, input) => {
748
+ ctx.log.info(`tool call: ${name}`, input);
749
+ ctx.emit({ type: "step.tool-call", step, name, input });
750
+ },
751
+ onToolResult: (name, output, ok) => {
752
+ ctx.log.debug(`tool result: ${name} ${ok ? "ok" : "FAILED"}`, output);
753
+ ctx.emit({ type: "step.tool-result", step, name, output, ok });
754
+ }
746
755
  }
747
756
  });
757
+ ctx.log.debug("executor text:", loop.text);
748
758
  const { summary, blocked } = splitBlocker(loop.text);
749
759
  return {
750
760
  result: {
@@ -792,11 +802,14 @@ var toSteps = (raw) => raw.filter((s) => s.description && s.description.trim()).
792
802
  expectedOutcome: s.expectedOutcome,
793
803
  suggestedTools: s.suggestedTools
794
804
  }));
795
- var createPlan = async (ctx, goal) => {
805
+ var createPlan = async (ctx, goal, nudge) => {
796
806
  const state = await ctx.state();
807
+ const effectiveGoal = nudge ? `${goal}
808
+
809
+ ${nudge}` : goal;
797
810
  const commonFor = (mode) => {
798
811
  const parts = ctx.prompts.planner({
799
- goal,
812
+ goal: effectiveGoal,
800
813
  state,
801
814
  toolCatalog: ctx.toolCatalog,
802
815
  mode,
@@ -814,16 +827,20 @@ var createPlan = async (ctx, goal) => {
814
827
  if (ctx.plannerMode === "native") {
815
828
  try {
816
829
  const result2 = await generateStructured(ctx.plannerModel, PlanSchema, commonFor("native"));
830
+ ctx.log.debug("planner (native):", result2.object);
817
831
  return {
818
832
  plan: { thought: result2.object.thought, steps: toSteps(result2.object.steps) },
819
833
  usage: normalizeUsage(result2.usage)
820
834
  };
821
835
  } catch (err) {
836
+ ctx.log.warn("planner: native structured output failed, salvaging:", asMessage(err));
822
837
  ctx.emit({ type: "retry", phase: "plan", attempt: 1, error: asMessage(err) });
823
838
  }
824
839
  }
825
840
  const result = await generate(ctx.plannerModel, commonFor("prompted"));
826
841
  const parsed = parsePlannerResponse(result.text);
842
+ ctx.log.debug("planner (prompted) raw:", result.text);
843
+ ctx.log.debug("planner (prompted) parsed:", parsed);
827
844
  return {
828
845
  plan: {
829
846
  thought: parsed.reply,
@@ -906,6 +923,27 @@ var synthesizeAnswer = async (ctx, goal, done) => {
906
923
  };
907
924
  };
908
925
 
926
+ // src/logger.ts
927
+ var WEIGHT = {
928
+ silent: 0,
929
+ error: 1,
930
+ warn: 2,
931
+ info: 3,
932
+ debug: 4
933
+ };
934
+ var PREFIX = "[agent-web]";
935
+ var noop = () => void 0;
936
+ var createLogger = (level = "warn", sink = console) => {
937
+ const at = (min, fn) => WEIGHT[level] >= WEIGHT[min] ? (...args) => fn.call(sink, PREFIX, ...args) : noop;
938
+ return {
939
+ level,
940
+ error: at("error", sink.error),
941
+ warn: at("warn", sink.warn),
942
+ info: at("info", sink.info),
943
+ debug: at("debug", sink.debug)
944
+ };
945
+ };
946
+
909
947
  // src/agent/runner.ts
910
948
  var errMessage = (err) => err instanceof Error ? err.message : String(err);
911
949
  var filterTools = (all, available, excluded) => {
@@ -936,6 +974,10 @@ var createAgent = async (config) => {
936
974
  );
937
975
  const toolCatalog = renderCatalog(tools);
938
976
  const prompts = { ...defaultPrompts, ...config.prompts };
977
+ const log = createLogger(cfg.logLevel, config.logger);
978
+ log.info(
979
+ `agent ready \u2014 tools: [${Object.keys(tools).join(", ") || "none"}], planner mode: ${plannerMode}, executor mode: ${executorMode}`
980
+ );
939
981
  const run = async (goal, opts = {}) => {
940
982
  const emit = (event) => {
941
983
  try {
@@ -991,14 +1033,34 @@ var createAgent = async (config) => {
991
1033
  toolCatalog,
992
1034
  prompts,
993
1035
  emit,
1036
+ log,
994
1037
  signal: opts.signal,
995
1038
  state,
996
1039
  history
997
1040
  };
998
1041
  await remember({ role: "user", content: text });
1042
+ log.info("run:", text);
999
1043
  try {
1000
- const planned = await createPlan(ctx, text);
1044
+ let planned = await createPlan(ctx, text);
1001
1045
  bumpUsage(planned.usage, "plan");
1046
+ if (isAborted()) {
1047
+ emit({ type: "stopped" });
1048
+ result.stopped = true;
1049
+ return result;
1050
+ }
1051
+ if (planned.plan.steps.length === 0 && text.split(/\s+/).length > 2) {
1052
+ log.warn(
1053
+ "planner returned no steps for a multi-word goal \u2014 retrying with a nudge. thought:",
1054
+ planned.plan.thought
1055
+ );
1056
+ const retried = await createPlan(
1057
+ ctx,
1058
+ text,
1059
+ "NOTE: If the message above asks to build, add, change, clear or delete ANYTHING, you MUST output 1-6 concrete steps. Output an empty plan ONLY for a pure greeting or question."
1060
+ );
1061
+ bumpUsage(retried.usage, "plan");
1062
+ if (retried.plan.steps.length > 0) planned = retried;
1063
+ }
1002
1064
  result.plan = planned.plan;
1003
1065
  if (isAborted()) {
1004
1066
  emit({ type: "stopped" });
@@ -1006,12 +1068,17 @@ var createAgent = async (config) => {
1006
1068
  return result;
1007
1069
  }
1008
1070
  if (planned.plan.steps.length === 0) {
1071
+ log.info("no plan \u2014 answering directly (no tools will run)");
1009
1072
  const answer = planned.plan.thought.trim() || "Tell me what you'd like to do.";
1010
1073
  emit({ type: "final", text: answer });
1011
1074
  await remember({ role: "assistant", content: answer });
1012
1075
  result.final = answer;
1013
1076
  return result;
1014
1077
  }
1078
+ log.info(
1079
+ `plan (${planned.plan.steps.length} steps):`,
1080
+ planned.plan.steps.map((s) => s.description)
1081
+ );
1015
1082
  emit({ type: "plan.created", plan: planned.plan });
1016
1083
  planned.plan.steps.forEach((step, index) => emit({ type: "plan.step-added", step, index }));
1017
1084
  const done = [];
@@ -1048,6 +1115,14 @@ var createAgent = async (config) => {
1048
1115
  const failed = stepResult.toolCalls.length - applied;
1049
1116
  result.applied += applied;
1050
1117
  result.steps = stepNo;
1118
+ log.info(
1119
+ `step ${stepNo}/${total} "${step.description}" \u2014 ${stepResult.toolCalls.length} tool call(s), ${applied} ok${failed ? `, ${failed} FAILED` : ""}${stepResult.blocked ? ", BLOCKED" : ""}`
1120
+ );
1121
+ if (stepResult.toolCalls.length === 0) {
1122
+ log.warn(`step ${stepNo} made no tool calls \u2014 nothing changed in this step`);
1123
+ }
1124
+ stepResult.toolCalls.filter((c) => !c.ok).forEach((c) => log.warn(`tool ${c.name} failed:`, c.output));
1125
+ log.debug(`step ${stepNo} detail:`, stepResult);
1051
1126
  emit({ type: "step.complete", step, result: stepResult });
1052
1127
  done.push(
1053
1128
  `${step.description} \u2014 ${applied} applied${failed ? `, ${failed} failed` : ""}${stepResult.blocked ? ", blocked" : ""}`
@@ -1087,6 +1162,7 @@ var createAgent = async (config) => {
1087
1162
  } catch {
1088
1163
  }
1089
1164
  }
1165
+ log.info(`done \u2014 ${result.applied} tool call(s) applied over ${result.steps} step(s)`);
1090
1166
  emit({ type: "final", text: summary });
1091
1167
  await remember({ role: "assistant", content: summary });
1092
1168
  result.final = summary;
@@ -1348,6 +1424,7 @@ export {
1348
1424
  buildModelFromStage,
1349
1425
  compressHistory,
1350
1426
  createAgent,
1427
+ createLogger,
1351
1428
  createPlan,
1352
1429
  createWebLLMModel,
1353
1430
  decideReplan,
@@ -1372,6 +1449,7 @@ export {
1372
1449
  parsePlainText,
1373
1450
  parsePlannerResponse,
1374
1451
  parseReplannerResponse,
1452
+ preloadWebLLMModel,
1375
1453
  promptHintOf,
1376
1454
  renderCatalog,
1377
1455
  resolveConfig,
@@ -1385,6 +1463,7 @@ export {
1385
1463
  supportsNativeTools,
1386
1464
  supportsStructuredOutput,
1387
1465
  synthesizeAnswer,
1466
+ unloadWebLLMModel,
1388
1467
  withSystem
1389
1468
  };
1390
1469
  //# sourceMappingURL=index.js.map