@iloveagents/foundry-agent 0.9.0 → 0.10.0

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.
@@ -152,7 +152,8 @@ export class AGUIRunner {
152
152
  // The user's reasoning-effort choice rides on every turn as an
153
153
  // AG-UI forwardedProp — read at request time so changing it
154
154
  // mid-conversation takes effect on the next message. "default"
155
- // sends nothing so the backend keeps its configured level.
155
+ // sends nothing, which is what makes the backend's own configured
156
+ // level apply; the picker shows the user what that resolves to.
156
157
  const chosenEffort = reasoningEffortStore.getState().effort;
157
158
  const forwardedProps = chosenEffort === "default" ? {} : { reasoningEffort: chosenEffort };
158
159
  const runInputSnapshot = {
package/dist/index.d.ts CHANGED
@@ -3,7 +3,7 @@ export type { RunnerEvent } from "./client/runner-events.js";
3
3
  export { createServiceFetch, type ServiceFetch, type ServiceFetchOptions, } from "./client/service-fetch.js";
4
4
  export { clientToolRegistry, type ClientToolEntry, type ToolRegistry } from "./tools/registry.js";
5
5
  export { agentStateStore } from "./store/agent-state-store.js";
6
- export { reasoningEffortStore, REASONING_EFFORT_LABELS, type ReasoningEffort, } from "./store/reasoning-effort-store.js";
6
+ export { reasoningDefaultStore, reasoningEffortStore, REASONING_EFFORT_LABELS, type ReasoningEffort, type ResolvedReasoningEffort, } from "./store/reasoning-effort-store.js";
7
7
  export { streamingStatusStore, type StreamingStatus } from "./store/streaming-status-store.js";
8
8
  export { citationStore, type CitationResult, type CitationHandler, } from "./store/citation-store.js";
9
9
  export { linkStore, resolveLinkHandler, type LinkHandler, type ResolvedLinkHandler, } from "./store/link-store.js";
package/dist/index.js CHANGED
@@ -6,7 +6,7 @@ export { createServiceFetch, } from "./client/service-fetch.js";
6
6
  export { clientToolRegistry } from "./tools/registry.js";
7
7
  // --- Stores (vanilla) ---
8
8
  export { agentStateStore } from "./store/agent-state-store.js";
9
- export { reasoningEffortStore, REASONING_EFFORT_LABELS, } from "./store/reasoning-effort-store.js";
9
+ export { reasoningDefaultStore, reasoningEffortStore, REASONING_EFFORT_LABELS, } from "./store/reasoning-effort-store.js";
10
10
  export { streamingStatusStore } from "./store/streaming-status-store.js";
11
11
  export { citationStore, } from "./store/citation-store.js";
12
12
  export { linkStore, resolveLinkHandler, } from "./store/link-store.js";
@@ -1,18 +1,55 @@
1
1
  /**
2
2
  * How hard the model should think before answering.
3
3
  *
4
- * `"default"` sends nothing and leaves the backend's configured level
5
- * alone the user hasn't expressed a preference, so we don't override
6
- * one. The remaining levels map to the AG-UI/Responses reasoning effort.
4
+ * `"default"` is a deferral, not a level: it sends nothing, so whatever the
5
+ * backend is configured for applies. Every other member maps to a real
6
+ * AG-UI/Responses reasoning effort and is sent verbatim.
7
+ *
8
+ * A deferral is only honest if the user can see what it currently resolves
9
+ * to — otherwise you believe you are on Extra High and are quietly running
10
+ * Instant, and the control silently decides cost and latency. That is what
11
+ * {@link reasoningDefaultStore} is for.
7
12
  */
8
13
  export type ReasoningEffort = "default" | "low" | "medium" | "high" | "xhigh";
14
+ /** A real effort level — everything except the deferral. */
15
+ export type ResolvedReasoningEffort = Exclude<ReasoningEffort, "default">;
9
16
  /**
10
17
  * Level names follow the convention users already know from other assistants
11
18
  * (Instant / Medium / High / Extra High) rather than inventing a private
12
- * vocabulary. `Auto` is ours: it means "no preference use whatever the app
13
- * is configured for", which the protocol enum has no member for.
19
+ * vocabulary. `Auto` is ours, for the case the protocol enum has no member
20
+ * for: follow whatever the app is configured for.
14
21
  */
15
22
  export declare const REASONING_EFFORT_LABELS: Record<ReasoningEffort, string>;
23
+ interface ReasoningDefaultState {
24
+ /**
25
+ * What `"default"` resolves to right now, or `null` while unknown.
26
+ *
27
+ * `null` also covers a backend with reasoning switched off entirely, where
28
+ * there is no level to name.
29
+ */
30
+ resolved: ResolvedReasoningEffort | null;
31
+ /**
32
+ * Where that came from, for the picker's hint — e.g. `"this workspace"`.
33
+ * `null` means unattributed, and the hint stays generic.
34
+ */
35
+ scope: string | null;
36
+ setResolved: (resolved: ResolvedReasoningEffort | null, scope?: string | null) => void;
37
+ }
38
+ /**
39
+ * What the backend will actually do when the client sends no effort.
40
+ *
41
+ * Populated by the host app, never derived here. Re-deriving the backend's
42
+ * fallback chain client-side is exactly how a label goes stale and starts
43
+ * lying: the backend changes its default and the UI keeps claiming the old
44
+ * one. The app fetches this from the server and sets it, and updates it
45
+ * when the context it depends on changes — switching workspace, say — so
46
+ * `Auto` always names the level that will really be used.
47
+ *
48
+ * Left unset, the picker says it does not know rather than guessing.
49
+ *
50
+ * Vanilla store — this package stays zero-React.
51
+ */
52
+ export declare const reasoningDefaultStore: import("zustand/vanilla").StoreApi<ReasoningDefaultState>;
16
53
  interface ReasoningEffortState {
17
54
  effort: ReasoningEffort;
18
55
  setEffort: (effort: ReasoningEffort) => void;
@@ -23,6 +60,9 @@ interface ReasoningEffortState {
23
60
  * Vanilla store (this package is zero-React); the runner reads it when
24
61
  * building each request so the choice applies per turn — change it
25
62
  * mid-conversation and the next message uses the new level.
63
+ *
64
+ * An explicit level is a pin: nothing moves it, including a change of
65
+ * context. Only `"default"` follows.
26
66
  */
27
67
  export declare const reasoningEffortStore: import("zustand/vanilla").StoreApi<ReasoningEffortState>;
28
68
  export {};
@@ -2,8 +2,8 @@ import { createStore } from "zustand/vanilla";
2
2
  /**
3
3
  * Level names follow the convention users already know from other assistants
4
4
  * (Instant / Medium / High / Extra High) rather than inventing a private
5
- * vocabulary. `Auto` is ours: it means "no preference use whatever the app
6
- * is configured for", which the protocol enum has no member for.
5
+ * vocabulary. `Auto` is ours, for the case the protocol enum has no member
6
+ * for: follow whatever the app is configured for.
7
7
  */
8
8
  export const REASONING_EFFORT_LABELS = {
9
9
  default: "Auto",
@@ -12,6 +12,25 @@ export const REASONING_EFFORT_LABELS = {
12
12
  high: "High",
13
13
  xhigh: "Extra High",
14
14
  };
15
+ /**
16
+ * What the backend will actually do when the client sends no effort.
17
+ *
18
+ * Populated by the host app, never derived here. Re-deriving the backend's
19
+ * fallback chain client-side is exactly how a label goes stale and starts
20
+ * lying: the backend changes its default and the UI keeps claiming the old
21
+ * one. The app fetches this from the server and sets it, and updates it
22
+ * when the context it depends on changes — switching workspace, say — so
23
+ * `Auto` always names the level that will really be used.
24
+ *
25
+ * Left unset, the picker says it does not know rather than guessing.
26
+ *
27
+ * Vanilla store — this package stays zero-React.
28
+ */
29
+ export const reasoningDefaultStore = createStore((set) => ({
30
+ resolved: null,
31
+ scope: null,
32
+ setResolved: (resolved, scope) => set({ resolved, scope: scope ?? null }),
33
+ }));
15
34
  const STORAGE_KEY = "foundry:reasoning-effort";
16
35
  function readPersisted() {
17
36
  if (typeof localStorage === "undefined")
@@ -27,6 +46,9 @@ function readPersisted() {
27
46
  * Vanilla store (this package is zero-React); the runner reads it when
28
47
  * building each request so the choice applies per turn — change it
29
48
  * mid-conversation and the next message uses the new level.
49
+ *
50
+ * An explicit level is a pin: nothing moves it, including a change of
51
+ * context. Only `"default"` follows.
30
52
  */
31
53
  export const reasoningEffortStore = createStore((set) => ({
32
54
  effort: readPersisted(),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@iloveagents/foundry-agent",
3
- "version": "0.9.0",
3
+ "version": "0.10.0",
4
4
  "license": "MIT",
5
5
  "description": "Cross-runtime AG-UI transport for Foundry UI — AGUIRunner protocol engine, vanilla zustand stores, optional MSAL auth subpath, service-fetch factory. Zero React, zero DOM.",
6
6
  "keywords": [