@athenaintel/react 0.32.0 → 0.35.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.
- package/README.md +99 -9
- package/dist/agent-runtime/src/composer-markdown.cjs.map +1 -1
- package/dist/agent-runtime/src/composer-markdown.js.map +1 -1
- package/dist/agent-runtime/src/deep-agent-transport-recipe.cjs +2 -3
- package/dist/agent-runtime/src/deep-agent-transport-recipe.cjs.map +1 -1
- package/dist/agent-runtime/src/deep-agent-transport-recipe.js +3 -4
- package/dist/agent-runtime/src/deep-agent-transport-recipe.js.map +1 -1
- package/dist/agent-runtime/src/edit-command.cjs.map +1 -1
- package/dist/agent-runtime/src/edit-command.js.map +1 -1
- package/dist/agent-runtime/src/messages.cjs +57 -2
- package/dist/agent-runtime/src/messages.cjs.map +1 -1
- package/dist/agent-runtime/src/messages.js +57 -2
- package/dist/agent-runtime/src/messages.js.map +1 -1
- package/dist/agent-runtime/src/quota-safe-local-storage-session.cjs +24 -3
- package/dist/agent-runtime/src/quota-safe-local-storage-session.cjs.map +1 -1
- package/dist/agent-runtime/src/quota-safe-local-storage-session.js +24 -3
- package/dist/agent-runtime/src/quota-safe-local-storage-session.js.map +1 -1
- package/dist/agent-runtime/src/statewire-transport.cjs +4 -13
- package/dist/agent-runtime/src/statewire-transport.cjs.map +1 -1
- package/dist/agent-runtime/src/statewire-transport.js +5 -14
- package/dist/agent-runtime/src/statewire-transport.js.map +1 -1
- package/dist/agent-runtime/src/tool-metadata.cjs +1 -1
- package/dist/agent-runtime/src/tool-metadata.cjs.map +1 -1
- package/dist/agent-runtime/src/tool-metadata.js +1 -1
- package/dist/agent-runtime/src/tool-metadata.js.map +1 -1
- package/dist/agent-runtime/src/use-deep-agent-thread.cjs.map +1 -1
- package/dist/agent-runtime/src/use-deep-agent-thread.js.map +1 -1
- package/dist/assets/AthenaAssetEmbed.cjs +3 -1
- package/dist/assets/AthenaAssetEmbed.cjs.map +1 -1
- package/dist/assets/AthenaAssetEmbed.d.ts +7 -0
- package/dist/assets/AthenaAssetEmbed.js +4 -2
- package/dist/assets/AthenaAssetEmbed.js.map +1 -1
- package/dist/assets/use-asset-embed.cjs +71 -71
- package/dist/assets/use-asset-embed.cjs.map +1 -1
- package/dist/assets/use-asset-embed.d.ts +20 -7
- package/dist/assets/use-asset-embed.js +72 -72
- package/dist/assets/use-asset-embed.js.map +1 -1
- package/dist/catalog/agent-model-options.cjs +122 -0
- package/dist/catalog/agent-model-options.cjs.map +1 -0
- package/dist/catalog/agent-model-options.d.ts +115 -0
- package/dist/catalog/agent-model-options.js +122 -0
- package/dist/catalog/agent-model-options.js.map +1 -0
- package/dist/catalog/chat-pickers.cjs +184 -4
- package/dist/catalog/chat-pickers.cjs.map +1 -1
- package/dist/catalog/chat-pickers.d.ts +27 -3
- package/dist/catalog/chat-pickers.js +187 -7
- package/dist/catalog/chat-pickers.js.map +1 -1
- package/dist/catalog/runtime-catalog.cjs +117 -3
- package/dist/catalog/runtime-catalog.cjs.map +1 -1
- package/dist/catalog/runtime-catalog.d.ts +104 -0
- package/dist/catalog/runtime-catalog.js +119 -5
- package/dist/catalog/runtime-catalog.js.map +1 -1
- package/dist/chat/AthenaChat.cjs.map +1 -1
- package/dist/chat/AthenaChat.d.ts +8 -7
- package/dist/chat/AthenaChat.js.map +1 -1
- package/dist/chat/super-grouping/SuperGroupingCard.cjs +30 -3
- package/dist/chat/super-grouping/SuperGroupingCard.cjs.map +1 -1
- package/dist/chat/super-grouping/SuperGroupingCard.d.ts +12 -9
- package/dist/chat/super-grouping/SuperGroupingCard.js +31 -4
- package/dist/chat/super-grouping/SuperGroupingCard.js.map +1 -1
- package/dist/chat/super-grouping/SuperGroupingTranscript.cjs.map +1 -1
- package/dist/chat/super-grouping/SuperGroupingTranscript.d.ts +8 -8
- package/dist/chat/super-grouping/SuperGroupingTranscript.js.map +1 -1
- package/dist/chat/super-grouping/activity-timeline.cjs.map +1 -1
- package/dist/chat/super-grouping/activity-timeline.d.ts +4 -4
- package/dist/chat/super-grouping/activity-timeline.js.map +1 -1
- package/dist/chat/super-grouping/index.d.ts +6 -5
- package/dist/chat/super-grouping/toolkit-map.cjs +3 -1
- package/dist/chat/super-grouping/toolkit-map.cjs.map +1 -1
- package/dist/chat/super-grouping/toolkit-map.js +3 -1
- package/dist/chat/super-grouping/toolkit-map.js.map +1 -1
- package/dist/chat-ui/index.cjs +1 -0
- package/dist/chat-ui/index.cjs.map +1 -1
- package/dist/chat-ui/index.d.ts +1 -1
- package/dist/chat-ui/index.js +2 -1
- package/dist/chat-ui/mentions/suggestions/data/api-client.cjs +33 -2
- package/dist/chat-ui/mentions/suggestions/data/api-client.cjs.map +1 -1
- package/dist/chat-ui/mentions/suggestions/data/api-client.d.ts +14 -0
- package/dist/chat-ui/mentions/suggestions/data/api-client.js +33 -2
- package/dist/chat-ui/mentions/suggestions/data/api-client.js.map +1 -1
- package/dist/index.cjs +1 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +3 -2
- package/dist/index.js +2 -1
- package/dist/lib/use-athena-rest-query.cjs +4 -0
- package/dist/lib/use-athena-rest-query.cjs.map +1 -1
- package/dist/lib/use-athena-rest-query.d.ts +6 -0
- package/dist/lib/use-athena-rest-query.js +4 -0
- package/dist/lib/use-athena-rest-query.js.map +1 -1
- package/dist/provider/AthenaProvider.cjs +29 -8
- package/dist/provider/AthenaProvider.cjs.map +1 -1
- package/dist/provider/AthenaProvider.d.ts +14 -4
- package/dist/provider/AthenaProvider.js +31 -10
- package/dist/provider/AthenaProvider.js.map +1 -1
- package/dist/provider/agent-selection-context.cjs +6 -0
- package/dist/provider/agent-selection-context.cjs.map +1 -0
- package/dist/provider/agent-selection-context.d.ts +14 -0
- package/dist/provider/agent-selection-context.js +6 -0
- package/dist/provider/agent-selection-context.js.map +1 -0
- package/dist/react/package.json.cjs +1 -1
- package/dist/react/package.json.js +1 -1
- package/dist/runtime/StatewireThreadConfigLaneSync.cjs +125 -0
- package/dist/runtime/StatewireThreadConfigLaneSync.cjs.map +1 -0
- package/dist/runtime/StatewireThreadConfigLaneSync.d.ts +54 -0
- package/dist/runtime/StatewireThreadConfigLaneSync.js +125 -0
- package/dist/runtime/StatewireThreadConfigLaneSync.js.map +1 -0
- package/dist/runtime/statewire-model-lane.cjs +0 -12
- package/dist/runtime/statewire-model-lane.cjs.map +1 -1
- package/dist/runtime/statewire-model-lane.d.ts +3 -1
- package/dist/runtime/statewire-model-lane.js +0 -12
- package/dist/runtime/statewire-model-lane.js.map +1 -1
- package/dist/runtime/statewire-server-lane-context.cjs.map +1 -1
- package/dist/runtime/statewire-server-lane-context.d.ts +2 -2
- package/dist/runtime/statewire-server-lane-context.js.map +1 -1
- package/dist/runtime/statewire-thread-config-lane.cjs +84 -0
- package/dist/runtime/statewire-thread-config-lane.cjs.map +1 -0
- package/dist/runtime/statewire-thread-config-lane.d.ts +94 -0
- package/dist/runtime/statewire-thread-config-lane.js +84 -0
- package/dist/runtime/statewire-thread-config-lane.js.map +1 -0
- package/dist/runtime/useAthenaStatewireRuntime.cjs +2 -2
- package/dist/runtime/useAthenaStatewireRuntime.cjs.map +1 -1
- package/dist/runtime/useAthenaStatewireRuntime.js +2 -2
- package/dist/runtime/useAthenaStatewireRuntime.js.map +1 -1
- package/dist/threads/use-athena-thread-model.cjs +11 -3
- package/dist/threads/use-athena-thread-model.cjs.map +1 -1
- package/dist/threads/use-athena-thread-model.d.ts +5 -0
- package/dist/threads/use-athena-thread-model.js +12 -4
- package/dist/threads/use-athena-thread-model.js.map +1 -1
- package/package.json +3 -3
- package/dist/runtime/StatewireModelLaneSync.cjs +0 -96
- package/dist/runtime/StatewireModelLaneSync.cjs.map +0 -1
- package/dist/runtime/StatewireModelLaneSync.d.ts +0 -45
- package/dist/runtime/StatewireModelLaneSync.js +0 -96
- package/dist/runtime/StatewireModelLaneSync.js.map +0 -1
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import { useStatewireSendCommand } from "@assistant-ui/react-statewire";
|
|
2
|
+
import { useRef, useState, useEffect } from "react";
|
|
3
|
+
import { athenaDiagnostics } from "../diagnostics/athena-diagnostics.js";
|
|
4
|
+
import { PROVIDER_THREAD_CONFIG_KEYS, sameThreadConfigValue, decideThreadConfigLanePatch, patchedThreadConfigKeys } from "./statewire-thread-config-lane.js";
|
|
5
|
+
import { useDeepAgentConfigController, isConfigWriteForbiddenRejection, isConfigSyncUnavailableRejection } from "../agent-runtime/src/use-deep-agent-config.js";
|
|
6
|
+
import { statewireTransportOutcome } from "../agent-runtime/src/errors.js";
|
|
7
|
+
const MAX_PATCH_ATTEMPTS_PER_CHANGE = 3;
|
|
8
|
+
const RETRY_BACKOFF_MS = [1e3, 4e3];
|
|
9
|
+
function configWriteData({
|
|
10
|
+
threadId,
|
|
11
|
+
patch
|
|
12
|
+
}) {
|
|
13
|
+
const otherKeys = patchedThreadConfigKeys(patch).filter((key) => key !== "model");
|
|
14
|
+
return {
|
|
15
|
+
thread_id: threadId,
|
|
16
|
+
...Object.hasOwn(patch, "model") && { model: patch.model },
|
|
17
|
+
...otherKeys.length > 0 && { config_keys: otherKeys }
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
function StatewireThreadConfigLaneSync({
|
|
21
|
+
threadId,
|
|
22
|
+
config,
|
|
23
|
+
lane,
|
|
24
|
+
channelLive
|
|
25
|
+
}) {
|
|
26
|
+
const send = useStatewireSendCommand();
|
|
27
|
+
const sendCommand = (command) => Promise.resolve(send(command));
|
|
28
|
+
const { configVersion, custom, patchConfig } = useDeepAgentConfigController({
|
|
29
|
+
serverConfig: lane.config,
|
|
30
|
+
sendCommand
|
|
31
|
+
});
|
|
32
|
+
const seenRef = useRef(config);
|
|
33
|
+
const pendingRef = useRef(/* @__PURE__ */ new Set());
|
|
34
|
+
const attemptsRef = useRef(/* @__PURE__ */ new Map());
|
|
35
|
+
const closedRef = useRef(false);
|
|
36
|
+
const patchConfigRef = useRef(patchConfig);
|
|
37
|
+
patchConfigRef.current = patchConfig;
|
|
38
|
+
const [retryTick, setRetryTick] = useState(0);
|
|
39
|
+
const retryTimerRef = useRef(null);
|
|
40
|
+
useEffect(
|
|
41
|
+
() => () => {
|
|
42
|
+
if (retryTimerRef.current !== null) clearTimeout(retryTimerRef.current);
|
|
43
|
+
},
|
|
44
|
+
[]
|
|
45
|
+
);
|
|
46
|
+
const landed = lane.landed;
|
|
47
|
+
useEffect(() => {
|
|
48
|
+
const pending = pendingRef.current;
|
|
49
|
+
const attempts = attemptsRef.current;
|
|
50
|
+
for (const key of PROVIDER_THREAD_CONFIG_KEYS) {
|
|
51
|
+
if (sameThreadConfigValue(config[key], seenRef.current[key])) continue;
|
|
52
|
+
pending.add(key);
|
|
53
|
+
attempts.set(key, 0);
|
|
54
|
+
}
|
|
55
|
+
seenRef.current = config;
|
|
56
|
+
if (pending.size === 0 || closedRef.current || !channelLive) return;
|
|
57
|
+
const decision = decideThreadConfigLanePatch({
|
|
58
|
+
desired: config,
|
|
59
|
+
keys: pending,
|
|
60
|
+
landed,
|
|
61
|
+
configVersion,
|
|
62
|
+
custom
|
|
63
|
+
});
|
|
64
|
+
if (decision.kind === "wait") return;
|
|
65
|
+
pending.clear();
|
|
66
|
+
if (decision.kind === "done") return;
|
|
67
|
+
const { patch } = decision;
|
|
68
|
+
const patchKeys = patchedThreadConfigKeys(patch);
|
|
69
|
+
for (const key of patchKeys) attempts.set(key, (attempts.get(key) ?? 0) + 1);
|
|
70
|
+
const modelOnly = patchKeys.length === 1 && patchKeys[0] === "model";
|
|
71
|
+
patchConfigRef.current(patch).catch((error) => {
|
|
72
|
+
const data = configWriteData({ threadId, patch });
|
|
73
|
+
if (isConfigWriteForbiddenRejection(error) || isConfigSyncUnavailableRejection(error)) {
|
|
74
|
+
closedRef.current = true;
|
|
75
|
+
athenaDiagnostics.emit("statewire.config", {
|
|
76
|
+
level: "warn",
|
|
77
|
+
data: {
|
|
78
|
+
...data,
|
|
79
|
+
reason: isConfigWriteForbiddenRejection(error) ? "config_write_forbidden" : "config_sync_unavailable"
|
|
80
|
+
}
|
|
81
|
+
});
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
const outcome = statewireTransportOutcome(error);
|
|
85
|
+
if (outcome !== null) {
|
|
86
|
+
athenaDiagnostics.emit("statewire.config", {
|
|
87
|
+
level: "debug",
|
|
88
|
+
data: { ...data, outcome }
|
|
89
|
+
});
|
|
90
|
+
if (outcome === "unmount") return;
|
|
91
|
+
const retryKeys = patchKeys.filter(
|
|
92
|
+
(key) => sameThreadConfigValue(seenRef.current[key], patch[key] ?? null) && (attempts.get(key) ?? 0) < MAX_PATCH_ATTEMPTS_PER_CHANGE
|
|
93
|
+
);
|
|
94
|
+
if (retryKeys.length === 0) return;
|
|
95
|
+
for (const key of retryKeys) pendingRef.current.add(key);
|
|
96
|
+
const written = Math.max(...retryKeys.map((key) => attempts.get(key) ?? 1));
|
|
97
|
+
const delay = RETRY_BACKOFF_MS[Math.min(written - 1, RETRY_BACKOFF_MS.length - 1)];
|
|
98
|
+
retryTimerRef.current = setTimeout(() => {
|
|
99
|
+
retryTimerRef.current = null;
|
|
100
|
+
setRetryTick((tick) => tick + 1);
|
|
101
|
+
}, delay);
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
athenaDiagnostics.error(
|
|
105
|
+
"statewire.config",
|
|
106
|
+
error,
|
|
107
|
+
modelOnly ? {
|
|
108
|
+
code: "statewire_rejected",
|
|
109
|
+
message: "The statewire host refused the model change",
|
|
110
|
+
hint: "Inspect error.detail: agora rejections carry a structured {code, message}. The thread keeps running with the model its server config holds."
|
|
111
|
+
} : {
|
|
112
|
+
code: "statewire_rejected",
|
|
113
|
+
message: "The statewire host refused the thread config change",
|
|
114
|
+
hint: "Inspect error.detail: agora rejections carry a structured {code, message}. The thread keeps running with the config its server config holds."
|
|
115
|
+
},
|
|
116
|
+
data
|
|
117
|
+
);
|
|
118
|
+
});
|
|
119
|
+
}, [config, landed, configVersion, custom, channelLive, retryTick, threadId]);
|
|
120
|
+
return null;
|
|
121
|
+
}
|
|
122
|
+
export {
|
|
123
|
+
StatewireThreadConfigLaneSync
|
|
124
|
+
};
|
|
125
|
+
//# sourceMappingURL=StatewireThreadConfigLaneSync.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"StatewireThreadConfigLaneSync.js","sources":["../../src/runtime/StatewireThreadConfigLaneSync.tsx"],"sourcesContent":["import { useStatewireSendCommand } from '@assistant-ui/react-statewire';\nimport {\n type DeepAgentConfigControllerInputs,\n isConfigSyncUnavailableRejection,\n isConfigWriteForbiddenRejection,\n statewireTransportOutcome,\n useDeepAgentConfigController,\n} from '@athenaintel/agent-runtime';\nimport { useEffect, useRef, useState } from 'react';\nimport { athenaDiagnostics } from '../diagnostics/athena-diagnostics';\nimport type { AthenaStatewireServerLane } from './statewire-server-lane-context';\nimport {\n decideThreadConfigLanePatch,\n PROVIDER_THREAD_CONFIG_KEYS,\n type ProviderThreadConfig,\n type ProviderThreadConfigKey,\n type ProviderThreadConfigPatch,\n patchedThreadConfigKeys,\n sameThreadConfigValue,\n} from './statewire-thread-config-lane';\n\n/** Writes of one change, the first included, before the sync gives up on it. */\nconst MAX_PATCH_ATTEMPTS_PER_CHANGE = 3;\n\n/** Wait before re-writing a change the channel dropped: 1 s, then 4 s. */\nconst RETRY_BACKOFF_MS = [1_000, 4_000] as const;\n\n/**\n * What a `statewire.config` event says about a write: the thread, the model it\n * set (`null`: unset), and the other provider-owned keys it set\n * (`config_keys`), never their values (a system prompt is the host's text).\n */\nfunction configWriteData({\n threadId,\n patch,\n}: {\n threadId: string;\n patch: ProviderThreadConfigPatch;\n}): Record<string, unknown> {\n const otherKeys = patchedThreadConfigKeys(patch).filter((key) => key !== 'model');\n return {\n thread_id: threadId,\n ...(Object.hasOwn(patch, 'model') && { model: patch.model }),\n ...(otherKeys.length > 0 && { config_keys: otherKeys }),\n };\n}\n\n/**\n * Writes the provider-owned thread-config keys to the thread's server config\n * lane when the host changes the props that feed them during an attach:\n * `model`, `systemPrompt` (`system_prompt`), `tools` and `frontendTools`\n * (`enabled_tools`), `workbench` and `knowledgeBase` (`knowledge_base`).\n *\n * Once a thread has a lane (version > 0), agora composes every run from the\n * lane and drops the thread-config keys a send carries, so a model, prompt,\n * tool list or asset list changed after the thread's first turn would never\n * apply. A change of such a prop therefore becomes one `config/patch`\n * carrying exactly the changed keys, each with the value the send would carry\n * (`null` when the send carries none: the key is unset, so the collab agent's\n * own value, or the default, applies). An empty tool or asset list is `null`,\n * as the send omits it.\n *\n * Only a CHANGE is written. A prop's value when the attach starts is never\n * written, even when the lane holds another value: that value is another\n * client's (or an earlier session's) choice for this thread, and an SDK app's\n * global setting must not overwrite it just by opening the thread. Hosts that\n * want the picker to follow the thread read `useAthenaThreadModel`.\n *\n * Decisions read the lane the host itself sent on this attach (`lane`, from\n * the transport), never the rendered thread state: before the attach snapshot\n * lands that state is a placeholder without a lane, or a remembered snapshot\n * with an older one, and comparing a change against either would write over\n * the session's real config. A change made before the snapshot lands waits\n * for it.\n *\n * A version-0 thread needs no write: the next send carries the values and\n * agora's deferral seed persists them. A change stays pending until the lane\n * exists, so a lane an earlier send seeds with the previous values is\n * corrected when it lands. A refusal that can never succeed (a view-only\n * collaborator, a workspace without server config) stops the sync for the\n * attach and is reported on the diagnostics bus. A write the channel dropped\n * (a lost stream, the host's expired verdict) stays pending and is written\n * again after a backoff once the channel is live, at most\n * {@link MAX_PATCH_ATTEMPTS_PER_CHANGE} times per change.\n *\n * The writes go through the `config/*` command family, which agora gates on\n * EDIT on the thread's session asset (`_authorize_config_write`).\n *\n * Mounted under the runtime's `AuiProvider`, keyed by the thread, so each\n * attach starts with nothing pending.\n */\nexport function StatewireThreadConfigLaneSync({\n threadId,\n config,\n lane,\n channelLive,\n}: {\n threadId: string;\n /** The values this thread's sends carry, published with the thread (see the provider). */\n config: ProviderThreadConfig;\n lane: AthenaStatewireServerLane;\n /** Whether the channel can take a command now; writes wait for it. */\n channelLive: boolean;\n}): null {\n const send = useStatewireSendCommand();\n const sendCommand: DeepAgentConfigControllerInputs['sendCommand'] = (command) =>\n Promise.resolve(send(command));\n const { configVersion, custom, patchConfig } = useDeepAgentConfigController({\n serverConfig: lane.config,\n sendCommand,\n });\n\n const seenRef = useRef(config);\n const pendingRef = useRef(new Set<ProviderThreadConfigKey>());\n const attemptsRef = useRef(new Map<ProviderThreadConfigKey, number>());\n const closedRef = useRef(false);\n const patchConfigRef = useRef(patchConfig);\n patchConfigRef.current = patchConfig;\n // Bumped (after a backoff) to re-run the effect for a write the channel dropped.\n const [retryTick, setRetryTick] = useState(0);\n const retryTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n useEffect(\n () => () => {\n if (retryTimerRef.current !== null) clearTimeout(retryTimerRef.current);\n },\n [],\n );\n const landed = lane.landed;\n\n useEffect(() => {\n const pending = pendingRef.current;\n const attempts = attemptsRef.current;\n for (const key of PROVIDER_THREAD_CONFIG_KEYS) {\n if (sameThreadConfigValue(config[key], seenRef.current[key])) continue;\n pending.add(key);\n attempts.set(key, 0);\n }\n seenRef.current = config;\n if (pending.size === 0 || closedRef.current || !channelLive) return;\n const decision = decideThreadConfigLanePatch({\n desired: config,\n keys: pending,\n landed,\n configVersion,\n custom,\n });\n if (decision.kind === 'wait') return;\n pending.clear();\n if (decision.kind === 'done') return;\n\n const { patch } = decision;\n const patchKeys = patchedThreadConfigKeys(patch);\n for (const key of patchKeys) attempts.set(key, (attempts.get(key) ?? 0) + 1);\n const modelOnly = patchKeys.length === 1 && patchKeys[0] === 'model';\n patchConfigRef.current(patch).catch((error: unknown) => {\n const data = configWriteData({ threadId, patch });\n if (isConfigWriteForbiddenRejection(error) || isConfigSyncUnavailableRejection(error)) {\n closedRef.current = true;\n athenaDiagnostics.emit('statewire.config', {\n level: 'warn',\n data: {\n ...data,\n reason: isConfigWriteForbiddenRejection(error)\n ? 'config_write_forbidden'\n : 'config_sync_unavailable',\n },\n });\n return;\n }\n const outcome = statewireTransportOutcome(error);\n if (outcome !== null) {\n // Channel weather (a dropped stream, the host's expired verdict): keep\n // each change pending and write it again after a backoff, once the\n // channel is live, unless its prop has moved on or the attach is gone.\n athenaDiagnostics.emit('statewire.config', {\n level: 'debug',\n data: { ...data, outcome },\n });\n if (outcome === 'unmount') return;\n const retryKeys = patchKeys.filter(\n (key) =>\n sameThreadConfigValue(seenRef.current[key], patch[key] ?? null) &&\n (attempts.get(key) ?? 0) < MAX_PATCH_ATTEMPTS_PER_CHANGE,\n );\n if (retryKeys.length === 0) return;\n for (const key of retryKeys) pendingRef.current.add(key);\n const written = Math.max(...retryKeys.map((key) => attempts.get(key) ?? 1));\n const delay = RETRY_BACKOFF_MS[Math.min(written - 1, RETRY_BACKOFF_MS.length - 1)];\n retryTimerRef.current = setTimeout(() => {\n retryTimerRef.current = null;\n setRetryTick((tick) => tick + 1);\n }, delay);\n return;\n }\n athenaDiagnostics.error(\n 'statewire.config',\n error,\n modelOnly\n ? {\n code: 'statewire_rejected',\n message: 'The statewire host refused the model change',\n hint: 'Inspect error.detail: agora rejections carry a structured {code, message}. The thread keeps running with the model its server config holds.',\n }\n : {\n code: 'statewire_rejected',\n message: 'The statewire host refused the thread config change',\n hint: 'Inspect error.detail: agora rejections carry a structured {code, message}. The thread keeps running with the config its server config holds.',\n },\n data,\n );\n });\n }, [config, landed, configVersion, custom, channelLive, retryTick, threadId]);\n\n return null;\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -11,18 +11,6 @@ function threadModelFromLane({
|
|
|
11
11
|
if (!ready || lane === null) return { model: null, configured: false, ready };
|
|
12
12
|
return { model: readLaneModel(lane.custom), configured: true, ready };
|
|
13
13
|
}
|
|
14
|
-
function decideModelLanePatch({
|
|
15
|
-
desiredModel,
|
|
16
|
-
landed,
|
|
17
|
-
configVersion,
|
|
18
|
-
custom
|
|
19
|
-
}) {
|
|
20
|
-
if (!landed || configVersion <= 0) return { kind: "wait" };
|
|
21
|
-
const desired = desiredModel === void 0 || desiredModel === "" ? null : desiredModel;
|
|
22
|
-
if (readLaneModel(custom) === desired) return { kind: "done" };
|
|
23
|
-
return { kind: "patch", patch: { model: desired } };
|
|
24
|
-
}
|
|
25
|
-
exports.decideModelLanePatch = decideModelLanePatch;
|
|
26
14
|
exports.readLaneModel = readLaneModel;
|
|
27
15
|
exports.threadModelFromLane = threadModelFromLane;
|
|
28
16
|
//# sourceMappingURL=statewire-model-lane.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"statewire-model-lane.cjs","sources":["../../src/runtime/statewire-model-lane.ts"],"sourcesContent":["import type { DeepAgentServerConfig, ThreadConfigCustom } from '@athenaintel/agent-runtime';\n\n/**\n * The model a thread's server config lane (`state.config.custom`) pins, as the\n * host app should read it, plus whether there is a lane at all.\n *\n * Once a thread has a lane (version > 0), agora runs every turn with the lane's\n * thread-config keys and drops the ones a send carries, `model` included: the\n * lane, not the provider's `model` prop, decides which model a turn uses.\n */\nexport interface AthenaThreadModel {\n /**\n * The model the lane pins, or `null` when it pins none: the run then uses the\n * selected collab agent's own model, or the deployment default.\n */\n model: string | null;\n /** `true` once the thread has a server config lane (version > 0). */\n configured: boolean;\n /**\n * `true` once the statewire host's snapshot of this thread has arrived (the\n * placeholder or remembered snapshot a thread shows while it loads does not\n * count: it may carry no lane, or an older one). Before that `model` is\n * `null` and `configured` is `false` whatever the thread holds, so wait for\n * `ready` before treating \"no model\" as an answer.\n */\n ready: boolean;\n}\n\n/** The lane's `model` key, or `null` when it carries none (or a non-string). */\nexport function readLaneModel(custom: ThreadConfigCustom): string | null {\n const model = custom.model;\n return typeof model === 'string' && model !== '' ? model : null;\n}\n\n/** {@link AthenaThreadModel} from the lane and the landed flag. Pure. */\nexport function threadModelFromLane({\n lane,\n ready,\n}: {\n lane: DeepAgentServerConfig | null;\n ready: boolean;\n}): AthenaThreadModel {\n if (!ready || lane === null) return { model: null, configured: false, ready };\n return { model: readLaneModel(lane.custom), configured: true, ready };\n}\n\n/**\n * What to do with a `model` prop change the host made during an attach:\n *\n * - `wait`: keep the change pending. The thread's snapshot has not landed, or\n * the thread has no lane yet (version 0). A version-0 thread needs nothing:\n * the next send carries the model and agora's deferral seed persists it. The\n * change stays pending only so that a lane an EARLIER send seeds (with the\n * previous model) is corrected once it lands.\n * - `done`: the lane already holds the model (this client's own unacknowledged\n * writes folded over); nothing to write.\n * - `patch`: issue `config/patch {model}`; `null` unsets the lane's model so\n * the agent's own model (or the deployment default) applies.\n */\nexport type ModelLaneDecision =\n | { kind: 'wait' }\n | { kind: 'done' }\n | { kind: 'patch'; patch: { model: string | null } };\n\nexport function decideModelLanePatch({\n desiredModel,\n landed,\n configVersion,\n custom,\n}: {\n /** The provider's `model` prop after the change (`undefined` = no explicit model). */\n desiredModel: string | undefined;\n landed: boolean;\n configVersion: number;\n /** The effective lane: the server config with this client's pending writes folded over. */\n custom: ThreadConfigCustom;\n}): ModelLaneDecision {\n
|
|
1
|
+
{"version":3,"file":"statewire-model-lane.cjs","sources":["../../src/runtime/statewire-model-lane.ts"],"sourcesContent":["import type { DeepAgentServerConfig, ThreadConfigCustom } from '@athenaintel/agent-runtime';\nimport { decideThreadConfigLanePatch } from './statewire-thread-config-lane';\n\n/**\n * The model a thread's server config lane (`state.config.custom`) pins, as the\n * host app should read it, plus whether there is a lane at all.\n *\n * Once a thread has a lane (version > 0), agora runs every turn with the lane's\n * thread-config keys and drops the ones a send carries, `model` included: the\n * lane, not the provider's `model` prop, decides which model a turn uses.\n */\nexport interface AthenaThreadModel {\n /**\n * The model the lane pins, or `null` when it pins none: the run then uses the\n * selected collab agent's own model, or the deployment default.\n */\n model: string | null;\n /** `true` once the thread has a server config lane (version > 0). */\n configured: boolean;\n /**\n * `true` once the statewire host's snapshot of this thread has arrived (the\n * placeholder or remembered snapshot a thread shows while it loads does not\n * count: it may carry no lane, or an older one). Before that `model` is\n * `null` and `configured` is `false` whatever the thread holds, so wait for\n * `ready` before treating \"no model\" as an answer.\n */\n ready: boolean;\n}\n\n/** The lane's `model` key, or `null` when it carries none (or a non-string). */\nexport function readLaneModel(custom: ThreadConfigCustom): string | null {\n const model = custom.model;\n return typeof model === 'string' && model !== '' ? model : null;\n}\n\n/** {@link AthenaThreadModel} from the lane and the landed flag. Pure. */\nexport function threadModelFromLane({\n lane,\n ready,\n}: {\n lane: DeepAgentServerConfig | null;\n ready: boolean;\n}): AthenaThreadModel {\n if (!ready || lane === null) return { model: null, configured: false, ready };\n return { model: readLaneModel(lane.custom), configured: true, ready };\n}\n\n/**\n * What to do with a `model` prop change the host made during an attach (the\n * `model` key of {@link decideThreadConfigLanePatch}, which decides every\n * provider-owned key the same way):\n *\n * - `wait`: keep the change pending. The thread's snapshot has not landed, or\n * the thread has no lane yet (version 0). A version-0 thread needs nothing:\n * the next send carries the model and agora's deferral seed persists it. The\n * change stays pending only so that a lane an EARLIER send seeds (with the\n * previous model) is corrected once it lands.\n * - `done`: the lane already holds the model (this client's own unacknowledged\n * writes folded over); nothing to write.\n * - `patch`: issue `config/patch {model}`; `null` unsets the lane's model so\n * the agent's own model (or the deployment default) applies.\n */\nexport type ModelLaneDecision =\n | { kind: 'wait' }\n | { kind: 'done' }\n | { kind: 'patch'; patch: { model: string | null } };\n\nexport function decideModelLanePatch({\n desiredModel,\n landed,\n configVersion,\n custom,\n}: {\n /** The provider's `model` prop after the change (`undefined` = no explicit model). */\n desiredModel: string | undefined;\n landed: boolean;\n configVersion: number;\n /** The effective lane: the server config with this client's pending writes folded over. */\n custom: ThreadConfigCustom;\n}): ModelLaneDecision {\n const desired = desiredModel === undefined || desiredModel === '' ? null : desiredModel;\n const decision = decideThreadConfigLanePatch({\n desired: {\n model: desired,\n system_prompt: null,\n enabled_tools: null,\n workbench: null,\n knowledge_base: null,\n },\n keys: ['model'],\n landed,\n configVersion,\n custom,\n });\n if (decision.kind !== 'patch') return decision;\n return { kind: 'patch', patch: { model: desired } };\n}\n"],"names":[],"mappings":";;AA8BO,SAAS,cAAc,QAA2C;AACvE,QAAM,QAAQ,OAAO;AACrB,SAAO,OAAO,UAAU,YAAY,UAAU,KAAK,QAAQ;AAC7D;AAGO,SAAS,oBAAoB;AAAA,EAClC;AAAA,EACA;AACF,GAGsB;AACpB,MAAI,CAAC,SAAS,SAAS,KAAM,QAAO,EAAE,OAAO,MAAM,YAAY,OAAO,MAAA;AACtE,SAAO,EAAE,OAAO,cAAc,KAAK,MAAM,GAAG,YAAY,MAAM,MAAA;AAChE;;;"}
|
|
@@ -32,7 +32,9 @@ export declare function threadModelFromLane({ lane, ready, }: {
|
|
|
32
32
|
ready: boolean;
|
|
33
33
|
}): AthenaThreadModel;
|
|
34
34
|
/**
|
|
35
|
-
* What to do with a `model` prop change the host made during an attach
|
|
35
|
+
* What to do with a `model` prop change the host made during an attach (the
|
|
36
|
+
* `model` key of {@link decideThreadConfigLanePatch}, which decides every
|
|
37
|
+
* provider-owned key the same way):
|
|
36
38
|
*
|
|
37
39
|
* - `wait`: keep the change pending. The thread's snapshot has not landed, or
|
|
38
40
|
* the thread has no lane yet (version 0). A version-0 thread needs nothing:
|
|
@@ -9,19 +9,7 @@ function threadModelFromLane({
|
|
|
9
9
|
if (!ready || lane === null) return { model: null, configured: false, ready };
|
|
10
10
|
return { model: readLaneModel(lane.custom), configured: true, ready };
|
|
11
11
|
}
|
|
12
|
-
function decideModelLanePatch({
|
|
13
|
-
desiredModel,
|
|
14
|
-
landed,
|
|
15
|
-
configVersion,
|
|
16
|
-
custom
|
|
17
|
-
}) {
|
|
18
|
-
if (!landed || configVersion <= 0) return { kind: "wait" };
|
|
19
|
-
const desired = desiredModel === void 0 || desiredModel === "" ? null : desiredModel;
|
|
20
|
-
if (readLaneModel(custom) === desired) return { kind: "done" };
|
|
21
|
-
return { kind: "patch", patch: { model: desired } };
|
|
22
|
-
}
|
|
23
12
|
export {
|
|
24
|
-
decideModelLanePatch,
|
|
25
13
|
readLaneModel,
|
|
26
14
|
threadModelFromLane
|
|
27
15
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"statewire-model-lane.js","sources":["../../src/runtime/statewire-model-lane.ts"],"sourcesContent":["import type { DeepAgentServerConfig, ThreadConfigCustom } from '@athenaintel/agent-runtime';\n\n/**\n * The model a thread's server config lane (`state.config.custom`) pins, as the\n * host app should read it, plus whether there is a lane at all.\n *\n * Once a thread has a lane (version > 0), agora runs every turn with the lane's\n * thread-config keys and drops the ones a send carries, `model` included: the\n * lane, not the provider's `model` prop, decides which model a turn uses.\n */\nexport interface AthenaThreadModel {\n /**\n * The model the lane pins, or `null` when it pins none: the run then uses the\n * selected collab agent's own model, or the deployment default.\n */\n model: string | null;\n /** `true` once the thread has a server config lane (version > 0). */\n configured: boolean;\n /**\n * `true` once the statewire host's snapshot of this thread has arrived (the\n * placeholder or remembered snapshot a thread shows while it loads does not\n * count: it may carry no lane, or an older one). Before that `model` is\n * `null` and `configured` is `false` whatever the thread holds, so wait for\n * `ready` before treating \"no model\" as an answer.\n */\n ready: boolean;\n}\n\n/** The lane's `model` key, or `null` when it carries none (or a non-string). */\nexport function readLaneModel(custom: ThreadConfigCustom): string | null {\n const model = custom.model;\n return typeof model === 'string' && model !== '' ? model : null;\n}\n\n/** {@link AthenaThreadModel} from the lane and the landed flag. Pure. */\nexport function threadModelFromLane({\n lane,\n ready,\n}: {\n lane: DeepAgentServerConfig | null;\n ready: boolean;\n}): AthenaThreadModel {\n if (!ready || lane === null) return { model: null, configured: false, ready };\n return { model: readLaneModel(lane.custom), configured: true, ready };\n}\n\n/**\n * What to do with a `model` prop change the host made during an attach:\n *\n * - `wait`: keep the change pending. The thread's snapshot has not landed, or\n * the thread has no lane yet (version 0). A version-0 thread needs nothing:\n * the next send carries the model and agora's deferral seed persists it. The\n * change stays pending only so that a lane an EARLIER send seeds (with the\n * previous model) is corrected once it lands.\n * - `done`: the lane already holds the model (this client's own unacknowledged\n * writes folded over); nothing to write.\n * - `patch`: issue `config/patch {model}`; `null` unsets the lane's model so\n * the agent's own model (or the deployment default) applies.\n */\nexport type ModelLaneDecision =\n | { kind: 'wait' }\n | { kind: 'done' }\n | { kind: 'patch'; patch: { model: string | null } };\n\nexport function decideModelLanePatch({\n desiredModel,\n landed,\n configVersion,\n custom,\n}: {\n /** The provider's `model` prop after the change (`undefined` = no explicit model). */\n desiredModel: string | undefined;\n landed: boolean;\n configVersion: number;\n /** The effective lane: the server config with this client's pending writes folded over. */\n custom: ThreadConfigCustom;\n}): ModelLaneDecision {\n
|
|
1
|
+
{"version":3,"file":"statewire-model-lane.js","sources":["../../src/runtime/statewire-model-lane.ts"],"sourcesContent":["import type { DeepAgentServerConfig, ThreadConfigCustom } from '@athenaintel/agent-runtime';\nimport { decideThreadConfigLanePatch } from './statewire-thread-config-lane';\n\n/**\n * The model a thread's server config lane (`state.config.custom`) pins, as the\n * host app should read it, plus whether there is a lane at all.\n *\n * Once a thread has a lane (version > 0), agora runs every turn with the lane's\n * thread-config keys and drops the ones a send carries, `model` included: the\n * lane, not the provider's `model` prop, decides which model a turn uses.\n */\nexport interface AthenaThreadModel {\n /**\n * The model the lane pins, or `null` when it pins none: the run then uses the\n * selected collab agent's own model, or the deployment default.\n */\n model: string | null;\n /** `true` once the thread has a server config lane (version > 0). */\n configured: boolean;\n /**\n * `true` once the statewire host's snapshot of this thread has arrived (the\n * placeholder or remembered snapshot a thread shows while it loads does not\n * count: it may carry no lane, or an older one). Before that `model` is\n * `null` and `configured` is `false` whatever the thread holds, so wait for\n * `ready` before treating \"no model\" as an answer.\n */\n ready: boolean;\n}\n\n/** The lane's `model` key, or `null` when it carries none (or a non-string). */\nexport function readLaneModel(custom: ThreadConfigCustom): string | null {\n const model = custom.model;\n return typeof model === 'string' && model !== '' ? model : null;\n}\n\n/** {@link AthenaThreadModel} from the lane and the landed flag. Pure. */\nexport function threadModelFromLane({\n lane,\n ready,\n}: {\n lane: DeepAgentServerConfig | null;\n ready: boolean;\n}): AthenaThreadModel {\n if (!ready || lane === null) return { model: null, configured: false, ready };\n return { model: readLaneModel(lane.custom), configured: true, ready };\n}\n\n/**\n * What to do with a `model` prop change the host made during an attach (the\n * `model` key of {@link decideThreadConfigLanePatch}, which decides every\n * provider-owned key the same way):\n *\n * - `wait`: keep the change pending. The thread's snapshot has not landed, or\n * the thread has no lane yet (version 0). A version-0 thread needs nothing:\n * the next send carries the model and agora's deferral seed persists it. The\n * change stays pending only so that a lane an EARLIER send seeds (with the\n * previous model) is corrected once it lands.\n * - `done`: the lane already holds the model (this client's own unacknowledged\n * writes folded over); nothing to write.\n * - `patch`: issue `config/patch {model}`; `null` unsets the lane's model so\n * the agent's own model (or the deployment default) applies.\n */\nexport type ModelLaneDecision =\n | { kind: 'wait' }\n | { kind: 'done' }\n | { kind: 'patch'; patch: { model: string | null } };\n\nexport function decideModelLanePatch({\n desiredModel,\n landed,\n configVersion,\n custom,\n}: {\n /** The provider's `model` prop after the change (`undefined` = no explicit model). */\n desiredModel: string | undefined;\n landed: boolean;\n configVersion: number;\n /** The effective lane: the server config with this client's pending writes folded over. */\n custom: ThreadConfigCustom;\n}): ModelLaneDecision {\n const desired = desiredModel === undefined || desiredModel === '' ? null : desiredModel;\n const decision = decideThreadConfigLanePatch({\n desired: {\n model: desired,\n system_prompt: null,\n enabled_tools: null,\n workbench: null,\n knowledge_base: null,\n },\n keys: ['model'],\n landed,\n configVersion,\n custom,\n });\n if (decision.kind !== 'patch') return decision;\n return { kind: 'patch', patch: { model: desired } };\n}\n"],"names":[],"mappings":"AA8BO,SAAS,cAAc,QAA2C;AACvE,QAAM,QAAQ,OAAO;AACrB,SAAO,OAAO,UAAU,YAAY,UAAU,KAAK,QAAQ;AAC7D;AAGO,SAAS,oBAAoB;AAAA,EAClC;AAAA,EACA;AACF,GAGsB;AACpB,MAAI,CAAC,SAAS,SAAS,KAAM,QAAO,EAAE,OAAO,MAAM,YAAY,OAAO,MAAA;AACtE,SAAO,EAAE,OAAO,cAAc,KAAK,MAAM,GAAG,YAAY,MAAM,MAAA;AAChE;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"statewire-server-lane-context.cjs","sources":["../../src/runtime/statewire-server-lane-context.ts"],"sourcesContent":["import type { DeepAgentServerConfig } from '@athenaintel/agent-runtime';\nimport { createContext } from 'react';\n\n/**\n * The thread's server config lane as the statewire host last sent it on this\n * attach, read off the transport's own state (`onStateChange`) rather than the\n * thread state the chat renders.\n *\n * The rendered state starts as a placeholder (or a remembered snapshot) before\n * the attach snapshot lands, and neither says what the server holds: a\n * placeholder has no lane at all and a remembered snapshot may carry an older\n * one. Anything that decides from the lane (`useAthenaThreadModel`, the
|
|
1
|
+
{"version":3,"file":"statewire-server-lane-context.cjs","sources":["../../src/runtime/statewire-server-lane-context.ts"],"sourcesContent":["import type { DeepAgentServerConfig } from '@athenaintel/agent-runtime';\nimport { createContext } from 'react';\n\n/**\n * The thread's server config lane as the statewire host last sent it on this\n * attach, read off the transport's own state (`onStateChange`) rather than the\n * thread state the chat renders.\n *\n * The rendered state starts as a placeholder (or a remembered snapshot) before\n * the attach snapshot lands, and neither says what the server holds: a\n * placeholder has no lane at all and a remembered snapshot may carry an older\n * one. Anything that decides from the lane (`useAthenaThreadModel`, the\n * thread-config writes in `StatewireThreadConfigLaneSync`) waits for `landed`.\n */\nexport interface AthenaStatewireServerLane {\n /** `true` once this attach's snapshot from the host has arrived. */\n landed: boolean;\n /** The lane in that snapshot (and every later host frame), `null` at version 0. */\n config: DeepAgentServerConfig | null;\n}\n\nexport const STATEWIRE_SERVER_LANE_PENDING: AthenaStatewireServerLane = Object.freeze({\n landed: false,\n config: null,\n});\n\n/** Provided by `AthenaProvider` around the host's children, per attached thread. */\nexport const AthenaStatewireServerLaneContext = createContext<AthenaStatewireServerLane | null>(\n null,\n);\n\n/**\n * The next lane value for a host frame: the same object while the lane's\n * version is unchanged, so a frame that moved only messages (every streamed\n * token) re-renders nothing.\n */\nexport function nextServerLane({\n previous,\n config,\n}: {\n previous: AthenaStatewireServerLane;\n config: DeepAgentServerConfig | null;\n}): AthenaStatewireServerLane {\n if (previous.landed && (previous.config?.version ?? 0) === (config?.version ?? 0)) {\n return previous;\n }\n return { landed: true, config };\n}\n"],"names":["createContext"],"mappings":";;;AAqBO,MAAM,gCAA2D,OAAO,OAAO;AAAA,EACpF,QAAQ;AAAA,EACR,QAAQ;AACV,CAAC;AAGM,MAAM,mCAAmCA,MAAAA;AAAAA,EAC9C;AACF;AAOO,SAAS,eAAe;AAAA,EAC7B;AAAA,EACA;AACF,GAG8B;;AAC5B,MAAI,SAAS,aAAW,cAAS,WAAT,mBAAiB,YAAW,SAAQ,iCAAQ,YAAW,IAAI;AACjF,WAAO;AAAA,EACT;AACA,SAAO,EAAE,QAAQ,MAAM,OAAA;AACzB;;;;"}
|
|
@@ -7,8 +7,8 @@ import type { DeepAgentServerConfig } from '@athenaintel/agent-runtime';
|
|
|
7
7
|
* The rendered state starts as a placeholder (or a remembered snapshot) before
|
|
8
8
|
* the attach snapshot lands, and neither says what the server holds: a
|
|
9
9
|
* placeholder has no lane at all and a remembered snapshot may carry an older
|
|
10
|
-
* one. Anything that decides from the lane (`useAthenaThreadModel`, the
|
|
11
|
-
*
|
|
10
|
+
* one. Anything that decides from the lane (`useAthenaThreadModel`, the
|
|
11
|
+
* thread-config writes in `StatewireThreadConfigLaneSync`) waits for `landed`.
|
|
12
12
|
*/
|
|
13
13
|
export interface AthenaStatewireServerLane {
|
|
14
14
|
/** `true` once this attach's snapshot from the host has arrived. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"statewire-server-lane-context.js","sources":["../../src/runtime/statewire-server-lane-context.ts"],"sourcesContent":["import type { DeepAgentServerConfig } from '@athenaintel/agent-runtime';\nimport { createContext } from 'react';\n\n/**\n * The thread's server config lane as the statewire host last sent it on this\n * attach, read off the transport's own state (`onStateChange`) rather than the\n * thread state the chat renders.\n *\n * The rendered state starts as a placeholder (or a remembered snapshot) before\n * the attach snapshot lands, and neither says what the server holds: a\n * placeholder has no lane at all and a remembered snapshot may carry an older\n * one. Anything that decides from the lane (`useAthenaThreadModel`, the
|
|
1
|
+
{"version":3,"file":"statewire-server-lane-context.js","sources":["../../src/runtime/statewire-server-lane-context.ts"],"sourcesContent":["import type { DeepAgentServerConfig } from '@athenaintel/agent-runtime';\nimport { createContext } from 'react';\n\n/**\n * The thread's server config lane as the statewire host last sent it on this\n * attach, read off the transport's own state (`onStateChange`) rather than the\n * thread state the chat renders.\n *\n * The rendered state starts as a placeholder (or a remembered snapshot) before\n * the attach snapshot lands, and neither says what the server holds: a\n * placeholder has no lane at all and a remembered snapshot may carry an older\n * one. Anything that decides from the lane (`useAthenaThreadModel`, the\n * thread-config writes in `StatewireThreadConfigLaneSync`) waits for `landed`.\n */\nexport interface AthenaStatewireServerLane {\n /** `true` once this attach's snapshot from the host has arrived. */\n landed: boolean;\n /** The lane in that snapshot (and every later host frame), `null` at version 0. */\n config: DeepAgentServerConfig | null;\n}\n\nexport const STATEWIRE_SERVER_LANE_PENDING: AthenaStatewireServerLane = Object.freeze({\n landed: false,\n config: null,\n});\n\n/** Provided by `AthenaProvider` around the host's children, per attached thread. */\nexport const AthenaStatewireServerLaneContext = createContext<AthenaStatewireServerLane | null>(\n null,\n);\n\n/**\n * The next lane value for a host frame: the same object while the lane's\n * version is unchanged, so a frame that moved only messages (every streamed\n * token) re-renders nothing.\n */\nexport function nextServerLane({\n previous,\n config,\n}: {\n previous: AthenaStatewireServerLane;\n config: DeepAgentServerConfig | null;\n}): AthenaStatewireServerLane {\n if (previous.landed && (previous.config?.version ?? 0) === (config?.version ?? 0)) {\n return previous;\n }\n return { landed: true, config };\n}\n"],"names":[],"mappings":";AAqBO,MAAM,gCAA2D,OAAO,OAAO;AAAA,EACpF,QAAQ;AAAA,EACR,QAAQ;AACV,CAAC;AAGM,MAAM,mCAAmC;AAAA,EAC9C;AACF;AAOO,SAAS,eAAe;AAAA,EAC7B;AAAA,EACA;AACF,GAG8B;;AAC5B,MAAI,SAAS,aAAW,cAAS,WAAT,mBAAiB,YAAW,SAAQ,iCAAQ,YAAW,IAAI;AACjF,WAAO;AAAA,EACT;AACA,SAAO,EAAE,QAAQ,MAAM,OAAA;AACzB;"}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
+
const statewireRunConfig = require("./statewire-run-config.cjs");
|
|
4
|
+
const PROVIDER_THREAD_CONFIG_KEYS = [
|
|
5
|
+
"model",
|
|
6
|
+
"system_prompt",
|
|
7
|
+
"enabled_tools",
|
|
8
|
+
"workbench",
|
|
9
|
+
"knowledge_base"
|
|
10
|
+
];
|
|
11
|
+
const nonBlankString = (value) => typeof value === "string" && value.trim() !== "" ? value : null;
|
|
12
|
+
const stringItems = (value) => value.filter((item) => typeof item === "string");
|
|
13
|
+
const propList = (value) => value !== void 0 && value.length > 0 ? value : null;
|
|
14
|
+
const extraList = (value) => Array.isArray(value) ? stringItems(value) : null;
|
|
15
|
+
function providerThreadConfig({
|
|
16
|
+
model,
|
|
17
|
+
systemPrompt,
|
|
18
|
+
tools,
|
|
19
|
+
frontendToolIds,
|
|
20
|
+
workbench,
|
|
21
|
+
knowledgeBase,
|
|
22
|
+
extraRunConfig
|
|
23
|
+
}) {
|
|
24
|
+
const extra = extraRunConfig ?? {};
|
|
25
|
+
const overrides = (key) => Object.hasOwn(extra, key);
|
|
26
|
+
const enabledTools = Array.from(/* @__PURE__ */ new Set([...tools ?? [], ...frontendToolIds ?? []]));
|
|
27
|
+
const trimmedPrompt = (systemPrompt == null ? void 0 : systemPrompt.trim()) ?? "";
|
|
28
|
+
return {
|
|
29
|
+
model: statewireRunConfig.effectiveStatewireModel({ model, extraRunConfig }) ?? null,
|
|
30
|
+
system_prompt: overrides("system_prompt") ? nonBlankString(extra.system_prompt) : trimmedPrompt === "" ? null : trimmedPrompt,
|
|
31
|
+
enabled_tools: overrides("enabled_tools") ? extraList(extra.enabled_tools) : propList(enabledTools),
|
|
32
|
+
workbench: overrides("workbench") ? extraList(extra.workbench) : propList(workbench),
|
|
33
|
+
knowledge_base: overrides("knowledge_base") ? extraList(extra.knowledge_base) : propList(knowledgeBase)
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
function readLaneThreadConfigValue({
|
|
37
|
+
custom,
|
|
38
|
+
key
|
|
39
|
+
}) {
|
|
40
|
+
const value = custom[key];
|
|
41
|
+
if (key === "model") return typeof value === "string" && value !== "" ? value : null;
|
|
42
|
+
if (key === "system_prompt") return nonBlankString(value);
|
|
43
|
+
return Array.isArray(value) ? stringItems(value) : null;
|
|
44
|
+
}
|
|
45
|
+
function sameThreadConfigValue(left, right) {
|
|
46
|
+
if (left === right) return true;
|
|
47
|
+
if (!Array.isArray(left) || !Array.isArray(right)) return false;
|
|
48
|
+
return left.length === right.length && left.every((item, index) => item === right[index]);
|
|
49
|
+
}
|
|
50
|
+
function decideThreadConfigLanePatch({
|
|
51
|
+
desired,
|
|
52
|
+
keys,
|
|
53
|
+
landed,
|
|
54
|
+
configVersion,
|
|
55
|
+
custom
|
|
56
|
+
}) {
|
|
57
|
+
if (!landed || configVersion <= 0) return { kind: "wait" };
|
|
58
|
+
const pending = new Set(keys);
|
|
59
|
+
const patch = {};
|
|
60
|
+
for (const key of PROVIDER_THREAD_CONFIG_KEYS) {
|
|
61
|
+
if (!pending.has(key)) continue;
|
|
62
|
+
if (!sameThreadConfigValue(readLaneThreadConfigValue({ custom, key }), desired[key])) {
|
|
63
|
+
copyThreadConfigKey({ target: patch, source: desired, key });
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
return patchedThreadConfigKeys(patch).length === 0 ? { kind: "done" } : { kind: "patch", patch };
|
|
67
|
+
}
|
|
68
|
+
function copyThreadConfigKey({
|
|
69
|
+
target,
|
|
70
|
+
source,
|
|
71
|
+
key
|
|
72
|
+
}) {
|
|
73
|
+
target[key] = source[key];
|
|
74
|
+
}
|
|
75
|
+
function patchedThreadConfigKeys(patch) {
|
|
76
|
+
return PROVIDER_THREAD_CONFIG_KEYS.filter((key) => Object.hasOwn(patch, key));
|
|
77
|
+
}
|
|
78
|
+
exports.PROVIDER_THREAD_CONFIG_KEYS = PROVIDER_THREAD_CONFIG_KEYS;
|
|
79
|
+
exports.decideThreadConfigLanePatch = decideThreadConfigLanePatch;
|
|
80
|
+
exports.patchedThreadConfigKeys = patchedThreadConfigKeys;
|
|
81
|
+
exports.providerThreadConfig = providerThreadConfig;
|
|
82
|
+
exports.readLaneThreadConfigValue = readLaneThreadConfigValue;
|
|
83
|
+
exports.sameThreadConfigValue = sameThreadConfigValue;
|
|
84
|
+
//# sourceMappingURL=statewire-thread-config-lane.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"statewire-thread-config-lane.cjs","sources":["../../src/runtime/statewire-thread-config-lane.ts"],"sourcesContent":["import type { ThreadConfigCustom } from '@athenaintel/agent-runtime';\nimport { effectiveStatewireModel } from './statewire-run-config';\n\n/**\n * The thread-config keys the provider's props own, in the order a\n * `config/patch` lists them.\n *\n * Once a thread has a server config lane (version > 0), agora composes every\n * run from the lane and drops these keys from a send\n * (`merge_custom_over_server_config`), so a change of the prop that feeds one\n * is written to the lane instead (see `StatewireThreadConfigLaneSync`).\n */\nexport const PROVIDER_THREAD_CONFIG_KEYS = [\n 'model',\n 'system_prompt',\n 'enabled_tools',\n 'workbench',\n 'knowledge_base',\n] as const;\n\nexport type ProviderThreadConfigKey = (typeof PROVIDER_THREAD_CONFIG_KEYS)[number];\n\n/**\n * The provider-owned thread-config values as a send carries them and as the\n * lane stores them; `null` is \"the send carries none\": written to the lane it\n * unsets the key, so the collab agent's own value (or the default) applies.\n */\nexport interface ProviderThreadConfig {\n model: string | null;\n system_prompt: string | null;\n enabled_tools: readonly string[] | null;\n workbench: readonly string[] | null;\n knowledge_base: readonly string[] | null;\n}\n\n/** A `config/patch` payload over provider-owned keys: exactly the keys to change. */\nexport type ProviderThreadConfigPatch = Partial<ProviderThreadConfig>;\n\nconst nonBlankString = (value: unknown): string | null =>\n typeof value === 'string' && value.trim() !== '' ? value : null;\n\nconst stringItems = (value: readonly unknown[]): string[] =>\n value.filter((item): item is string => typeof item === 'string');\n\n/** A list prop as the send carries it: omitted (`null`) when empty, as `buildStatewireRunConfig` does. */\nconst propList = (value: readonly string[] | undefined): readonly string[] | null =>\n value !== undefined && value.length > 0 ? value : null;\n\n/**\n * An `extraRunConfig` list as the send carries it: `buildStatewireRunConfig`\n * merges `extraRunConfig` last and verbatim, so an explicit list (an empty one\n * included) is what the send holds.\n */\nconst extraList = (value: unknown): readonly string[] | null =>\n Array.isArray(value) ? stringItems(value) : null;\n\n/**\n * The provider-owned thread-config values a send built from these props\n * carries, with `buildStatewireRunConfig`'s precedence: `extraRunConfig` is\n * merged last, so a key it holds wins over the prop that feeds it.\n *\n * - `model`: the explicit model only (`effectiveStatewireModel`); the SDK's\n * own default is never a choice to write.\n * - `system_prompt`: the trimmed prompt, `null` when blank.\n * - `enabled_tools`: `tools` ∪ `frontendToolIds`; `null` when empty, since the\n * send omits an empty list (it would erase a collab agent's own tools).\n * - `workbench`, `knowledge_base`: the list, `null` when empty.\n *\n * Pure.\n */\nexport function providerThreadConfig({\n model,\n systemPrompt,\n tools,\n frontendToolIds,\n workbench,\n knowledgeBase,\n extraRunConfig,\n}: {\n model: string | undefined;\n systemPrompt: string | undefined;\n tools: readonly string[] | undefined;\n frontendToolIds: readonly string[] | undefined;\n workbench: readonly string[] | undefined;\n knowledgeBase: readonly string[] | undefined;\n extraRunConfig: Record<string, unknown> | undefined;\n}): ProviderThreadConfig {\n const extra = extraRunConfig ?? {};\n const overrides = (key: ProviderThreadConfigKey) => Object.hasOwn(extra, key);\n const enabledTools = Array.from(new Set([...(tools ?? []), ...(frontendToolIds ?? [])]));\n const trimmedPrompt = systemPrompt?.trim() ?? '';\n return {\n model: effectiveStatewireModel({ model, extraRunConfig }) ?? null,\n system_prompt: overrides('system_prompt')\n ? nonBlankString(extra.system_prompt)\n : trimmedPrompt === ''\n ? null\n : trimmedPrompt,\n enabled_tools: overrides('enabled_tools')\n ? extraList(extra.enabled_tools)\n : propList(enabledTools),\n workbench: overrides('workbench') ? extraList(extra.workbench) : propList(workbench),\n knowledge_base: overrides('knowledge_base')\n ? extraList(extra.knowledge_base)\n : propList(knowledgeBase),\n };\n}\n\n/**\n * A key of the lane (`state.config.custom`) read as a provider-owned value:\n * a text key is its non-blank string, a list key its string items (an\n * explicit empty list included), anything else `null` (unset).\n */\nexport function readLaneThreadConfigValue({\n custom,\n key,\n}: {\n custom: ThreadConfigCustom;\n key: ProviderThreadConfigKey;\n}): string | readonly string[] | null {\n const value = custom[key];\n // `model` keeps `readLaneModel`'s reading: any non-empty string.\n if (key === 'model') return typeof value === 'string' && value !== '' ? value : null;\n if (key === 'system_prompt') return nonBlankString(value);\n return Array.isArray(value) ? stringItems(value) : null;\n}\n\n/** Whether two provider-owned values are the same (lists compared item by item, in order). */\nexport function sameThreadConfigValue(\n left: string | readonly string[] | null,\n right: string | readonly string[] | null,\n): boolean {\n if (left === right) return true;\n if (!Array.isArray(left) || !Array.isArray(right)) return false;\n return left.length === right.length && left.every((item, index) => item === right[index]);\n}\n\n/**\n * What to do with the pending changes of provider-owned keys:\n *\n * - `wait`: keep them pending. The thread's snapshot has not landed, or the\n * thread has no lane yet (version 0): the next send carries the values and\n * agora's deferral seed persists the ones it keeps. They stay pending so that\n * a lane an EARLIER send seeds (with the previous values) is corrected once\n * it lands.\n * - `done`: the lane already holds every one of them (this client's own\n * unacknowledged writes folded over); nothing to write.\n * - `patch`: issue one `config/patch` carrying exactly the keys whose lane\n * value differs; `null` unsets a key so the agent's own value (or the\n * default) applies.\n */\nexport type ThreadConfigLaneDecision =\n | { kind: 'wait' }\n | { kind: 'done' }\n | { kind: 'patch'; patch: ProviderThreadConfigPatch };\n\nexport function decideThreadConfigLanePatch({\n desired,\n keys,\n landed,\n configVersion,\n custom,\n}: {\n /** The provider's values after the changes. */\n desired: ProviderThreadConfig;\n /** The keys whose prop changed during this attach and is not yet written. */\n keys: Iterable<ProviderThreadConfigKey>;\n landed: boolean;\n configVersion: number;\n /** The effective lane: the server config with this client's pending writes folded over. */\n custom: ThreadConfigCustom;\n}): ThreadConfigLaneDecision {\n if (!landed || configVersion <= 0) return { kind: 'wait' };\n const pending = new Set(keys);\n const patch: ProviderThreadConfigPatch = {};\n for (const key of PROVIDER_THREAD_CONFIG_KEYS) {\n if (!pending.has(key)) continue;\n if (!sameThreadConfigValue(readLaneThreadConfigValue({ custom, key }), desired[key])) {\n copyThreadConfigKey({ target: patch, source: desired, key });\n }\n }\n return patchedThreadConfigKeys(patch).length === 0 ? { kind: 'done' } : { kind: 'patch', patch };\n}\n\nfunction copyThreadConfigKey<K extends ProviderThreadConfigKey>({\n target,\n source,\n key,\n}: {\n target: ProviderThreadConfigPatch;\n source: ProviderThreadConfig;\n key: K;\n}): void {\n target[key] = source[key];\n}\n\n/** The keys a patch carries, in {@link PROVIDER_THREAD_CONFIG_KEYS} order. */\nexport function patchedThreadConfigKeys(patch: ProviderThreadConfigPatch): ProviderThreadConfigKey[] {\n return PROVIDER_THREAD_CONFIG_KEYS.filter((key) => Object.hasOwn(patch, key));\n}\n"],"names":["effectiveStatewireModel"],"mappings":"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"}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import type { ThreadConfigCustom } from '@athenaintel/agent-runtime';
|
|
2
|
+
/**
|
|
3
|
+
* The thread-config keys the provider's props own, in the order a
|
|
4
|
+
* `config/patch` lists them.
|
|
5
|
+
*
|
|
6
|
+
* Once a thread has a server config lane (version > 0), agora composes every
|
|
7
|
+
* run from the lane and drops these keys from a send
|
|
8
|
+
* (`merge_custom_over_server_config`), so a change of the prop that feeds one
|
|
9
|
+
* is written to the lane instead (see `StatewireThreadConfigLaneSync`).
|
|
10
|
+
*/
|
|
11
|
+
export declare const PROVIDER_THREAD_CONFIG_KEYS: readonly ['model', 'system_prompt', 'enabled_tools', 'workbench', 'knowledge_base'];
|
|
12
|
+
export type ProviderThreadConfigKey = (typeof PROVIDER_THREAD_CONFIG_KEYS)[number];
|
|
13
|
+
/**
|
|
14
|
+
* The provider-owned thread-config values as a send carries them and as the
|
|
15
|
+
* lane stores them; `null` is "the send carries none": written to the lane it
|
|
16
|
+
* unsets the key, so the collab agent's own value (or the default) applies.
|
|
17
|
+
*/
|
|
18
|
+
export interface ProviderThreadConfig {
|
|
19
|
+
model: string | null;
|
|
20
|
+
system_prompt: string | null;
|
|
21
|
+
enabled_tools: readonly string[] | null;
|
|
22
|
+
workbench: readonly string[] | null;
|
|
23
|
+
knowledge_base: readonly string[] | null;
|
|
24
|
+
}
|
|
25
|
+
/** A `config/patch` payload over provider-owned keys: exactly the keys to change. */
|
|
26
|
+
export type ProviderThreadConfigPatch = Partial<ProviderThreadConfig>;
|
|
27
|
+
/**
|
|
28
|
+
* The provider-owned thread-config values a send built from these props
|
|
29
|
+
* carries, with `buildStatewireRunConfig`'s precedence: `extraRunConfig` is
|
|
30
|
+
* merged last, so a key it holds wins over the prop that feeds it.
|
|
31
|
+
*
|
|
32
|
+
* - `model`: the explicit model only (`effectiveStatewireModel`); the SDK's
|
|
33
|
+
* own default is never a choice to write.
|
|
34
|
+
* - `system_prompt`: the trimmed prompt, `null` when blank.
|
|
35
|
+
* - `enabled_tools`: `tools` ∪ `frontendToolIds`; `null` when empty, since the
|
|
36
|
+
* send omits an empty list (it would erase a collab agent's own tools).
|
|
37
|
+
* - `workbench`, `knowledge_base`: the list, `null` when empty.
|
|
38
|
+
*
|
|
39
|
+
* Pure.
|
|
40
|
+
*/
|
|
41
|
+
export declare function providerThreadConfig({ model, systemPrompt, tools, frontendToolIds, workbench, knowledgeBase, extraRunConfig, }: {
|
|
42
|
+
model: string | undefined;
|
|
43
|
+
systemPrompt: string | undefined;
|
|
44
|
+
tools: readonly string[] | undefined;
|
|
45
|
+
frontendToolIds: readonly string[] | undefined;
|
|
46
|
+
workbench: readonly string[] | undefined;
|
|
47
|
+
knowledgeBase: readonly string[] | undefined;
|
|
48
|
+
extraRunConfig: Record<string, unknown> | undefined;
|
|
49
|
+
}): ProviderThreadConfig;
|
|
50
|
+
/**
|
|
51
|
+
* A key of the lane (`state.config.custom`) read as a provider-owned value:
|
|
52
|
+
* a text key is its non-blank string, a list key its string items (an
|
|
53
|
+
* explicit empty list included), anything else `null` (unset).
|
|
54
|
+
*/
|
|
55
|
+
export declare function readLaneThreadConfigValue({ custom, key, }: {
|
|
56
|
+
custom: ThreadConfigCustom;
|
|
57
|
+
key: ProviderThreadConfigKey;
|
|
58
|
+
}): string | readonly string[] | null;
|
|
59
|
+
/** Whether two provider-owned values are the same (lists compared item by item, in order). */
|
|
60
|
+
export declare function sameThreadConfigValue(left: string | readonly string[] | null, right: string | readonly string[] | null): boolean;
|
|
61
|
+
/**
|
|
62
|
+
* What to do with the pending changes of provider-owned keys:
|
|
63
|
+
*
|
|
64
|
+
* - `wait`: keep them pending. The thread's snapshot has not landed, or the
|
|
65
|
+
* thread has no lane yet (version 0): the next send carries the values and
|
|
66
|
+
* agora's deferral seed persists the ones it keeps. They stay pending so that
|
|
67
|
+
* a lane an EARLIER send seeds (with the previous values) is corrected once
|
|
68
|
+
* it lands.
|
|
69
|
+
* - `done`: the lane already holds every one of them (this client's own
|
|
70
|
+
* unacknowledged writes folded over); nothing to write.
|
|
71
|
+
* - `patch`: issue one `config/patch` carrying exactly the keys whose lane
|
|
72
|
+
* value differs; `null` unsets a key so the agent's own value (or the
|
|
73
|
+
* default) applies.
|
|
74
|
+
*/
|
|
75
|
+
export type ThreadConfigLaneDecision = {
|
|
76
|
+
kind: 'wait';
|
|
77
|
+
} | {
|
|
78
|
+
kind: 'done';
|
|
79
|
+
} | {
|
|
80
|
+
kind: 'patch';
|
|
81
|
+
patch: ProviderThreadConfigPatch;
|
|
82
|
+
};
|
|
83
|
+
export declare function decideThreadConfigLanePatch({ desired, keys, landed, configVersion, custom, }: {
|
|
84
|
+
/** The provider's values after the changes. */
|
|
85
|
+
desired: ProviderThreadConfig;
|
|
86
|
+
/** The keys whose prop changed during this attach and is not yet written. */
|
|
87
|
+
keys: Iterable<ProviderThreadConfigKey>;
|
|
88
|
+
landed: boolean;
|
|
89
|
+
configVersion: number;
|
|
90
|
+
/** The effective lane: the server config with this client's pending writes folded over. */
|
|
91
|
+
custom: ThreadConfigCustom;
|
|
92
|
+
}): ThreadConfigLaneDecision;
|
|
93
|
+
/** The keys a patch carries, in {@link PROVIDER_THREAD_CONFIG_KEYS} order. */
|
|
94
|
+
export declare function patchedThreadConfigKeys(patch: ProviderThreadConfigPatch): ProviderThreadConfigKey[];
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { effectiveStatewireModel } from "./statewire-run-config.js";
|
|
2
|
+
const PROVIDER_THREAD_CONFIG_KEYS = [
|
|
3
|
+
"model",
|
|
4
|
+
"system_prompt",
|
|
5
|
+
"enabled_tools",
|
|
6
|
+
"workbench",
|
|
7
|
+
"knowledge_base"
|
|
8
|
+
];
|
|
9
|
+
const nonBlankString = (value) => typeof value === "string" && value.trim() !== "" ? value : null;
|
|
10
|
+
const stringItems = (value) => value.filter((item) => typeof item === "string");
|
|
11
|
+
const propList = (value) => value !== void 0 && value.length > 0 ? value : null;
|
|
12
|
+
const extraList = (value) => Array.isArray(value) ? stringItems(value) : null;
|
|
13
|
+
function providerThreadConfig({
|
|
14
|
+
model,
|
|
15
|
+
systemPrompt,
|
|
16
|
+
tools,
|
|
17
|
+
frontendToolIds,
|
|
18
|
+
workbench,
|
|
19
|
+
knowledgeBase,
|
|
20
|
+
extraRunConfig
|
|
21
|
+
}) {
|
|
22
|
+
const extra = extraRunConfig ?? {};
|
|
23
|
+
const overrides = (key) => Object.hasOwn(extra, key);
|
|
24
|
+
const enabledTools = Array.from(/* @__PURE__ */ new Set([...tools ?? [], ...frontendToolIds ?? []]));
|
|
25
|
+
const trimmedPrompt = (systemPrompt == null ? void 0 : systemPrompt.trim()) ?? "";
|
|
26
|
+
return {
|
|
27
|
+
model: effectiveStatewireModel({ model, extraRunConfig }) ?? null,
|
|
28
|
+
system_prompt: overrides("system_prompt") ? nonBlankString(extra.system_prompt) : trimmedPrompt === "" ? null : trimmedPrompt,
|
|
29
|
+
enabled_tools: overrides("enabled_tools") ? extraList(extra.enabled_tools) : propList(enabledTools),
|
|
30
|
+
workbench: overrides("workbench") ? extraList(extra.workbench) : propList(workbench),
|
|
31
|
+
knowledge_base: overrides("knowledge_base") ? extraList(extra.knowledge_base) : propList(knowledgeBase)
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
function readLaneThreadConfigValue({
|
|
35
|
+
custom,
|
|
36
|
+
key
|
|
37
|
+
}) {
|
|
38
|
+
const value = custom[key];
|
|
39
|
+
if (key === "model") return typeof value === "string" && value !== "" ? value : null;
|
|
40
|
+
if (key === "system_prompt") return nonBlankString(value);
|
|
41
|
+
return Array.isArray(value) ? stringItems(value) : null;
|
|
42
|
+
}
|
|
43
|
+
function sameThreadConfigValue(left, right) {
|
|
44
|
+
if (left === right) return true;
|
|
45
|
+
if (!Array.isArray(left) || !Array.isArray(right)) return false;
|
|
46
|
+
return left.length === right.length && left.every((item, index) => item === right[index]);
|
|
47
|
+
}
|
|
48
|
+
function decideThreadConfigLanePatch({
|
|
49
|
+
desired,
|
|
50
|
+
keys,
|
|
51
|
+
landed,
|
|
52
|
+
configVersion,
|
|
53
|
+
custom
|
|
54
|
+
}) {
|
|
55
|
+
if (!landed || configVersion <= 0) return { kind: "wait" };
|
|
56
|
+
const pending = new Set(keys);
|
|
57
|
+
const patch = {};
|
|
58
|
+
for (const key of PROVIDER_THREAD_CONFIG_KEYS) {
|
|
59
|
+
if (!pending.has(key)) continue;
|
|
60
|
+
if (!sameThreadConfigValue(readLaneThreadConfigValue({ custom, key }), desired[key])) {
|
|
61
|
+
copyThreadConfigKey({ target: patch, source: desired, key });
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
return patchedThreadConfigKeys(patch).length === 0 ? { kind: "done" } : { kind: "patch", patch };
|
|
65
|
+
}
|
|
66
|
+
function copyThreadConfigKey({
|
|
67
|
+
target,
|
|
68
|
+
source,
|
|
69
|
+
key
|
|
70
|
+
}) {
|
|
71
|
+
target[key] = source[key];
|
|
72
|
+
}
|
|
73
|
+
function patchedThreadConfigKeys(patch) {
|
|
74
|
+
return PROVIDER_THREAD_CONFIG_KEYS.filter((key) => Object.hasOwn(patch, key));
|
|
75
|
+
}
|
|
76
|
+
export {
|
|
77
|
+
PROVIDER_THREAD_CONFIG_KEYS,
|
|
78
|
+
decideThreadConfigLanePatch,
|
|
79
|
+
patchedThreadConfigKeys,
|
|
80
|
+
providerThreadConfig,
|
|
81
|
+
readLaneThreadConfigValue,
|
|
82
|
+
sameThreadConfigValue
|
|
83
|
+
};
|
|
84
|
+
//# sourceMappingURL=statewire-thread-config-lane.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"statewire-thread-config-lane.js","sources":["../../src/runtime/statewire-thread-config-lane.ts"],"sourcesContent":["import type { ThreadConfigCustom } from '@athenaintel/agent-runtime';\nimport { effectiveStatewireModel } from './statewire-run-config';\n\n/**\n * The thread-config keys the provider's props own, in the order a\n * `config/patch` lists them.\n *\n * Once a thread has a server config lane (version > 0), agora composes every\n * run from the lane and drops these keys from a send\n * (`merge_custom_over_server_config`), so a change of the prop that feeds one\n * is written to the lane instead (see `StatewireThreadConfigLaneSync`).\n */\nexport const PROVIDER_THREAD_CONFIG_KEYS = [\n 'model',\n 'system_prompt',\n 'enabled_tools',\n 'workbench',\n 'knowledge_base',\n] as const;\n\nexport type ProviderThreadConfigKey = (typeof PROVIDER_THREAD_CONFIG_KEYS)[number];\n\n/**\n * The provider-owned thread-config values as a send carries them and as the\n * lane stores them; `null` is \"the send carries none\": written to the lane it\n * unsets the key, so the collab agent's own value (or the default) applies.\n */\nexport interface ProviderThreadConfig {\n model: string | null;\n system_prompt: string | null;\n enabled_tools: readonly string[] | null;\n workbench: readonly string[] | null;\n knowledge_base: readonly string[] | null;\n}\n\n/** A `config/patch` payload over provider-owned keys: exactly the keys to change. */\nexport type ProviderThreadConfigPatch = Partial<ProviderThreadConfig>;\n\nconst nonBlankString = (value: unknown): string | null =>\n typeof value === 'string' && value.trim() !== '' ? value : null;\n\nconst stringItems = (value: readonly unknown[]): string[] =>\n value.filter((item): item is string => typeof item === 'string');\n\n/** A list prop as the send carries it: omitted (`null`) when empty, as `buildStatewireRunConfig` does. */\nconst propList = (value: readonly string[] | undefined): readonly string[] | null =>\n value !== undefined && value.length > 0 ? value : null;\n\n/**\n * An `extraRunConfig` list as the send carries it: `buildStatewireRunConfig`\n * merges `extraRunConfig` last and verbatim, so an explicit list (an empty one\n * included) is what the send holds.\n */\nconst extraList = (value: unknown): readonly string[] | null =>\n Array.isArray(value) ? stringItems(value) : null;\n\n/**\n * The provider-owned thread-config values a send built from these props\n * carries, with `buildStatewireRunConfig`'s precedence: `extraRunConfig` is\n * merged last, so a key it holds wins over the prop that feeds it.\n *\n * - `model`: the explicit model only (`effectiveStatewireModel`); the SDK's\n * own default is never a choice to write.\n * - `system_prompt`: the trimmed prompt, `null` when blank.\n * - `enabled_tools`: `tools` ∪ `frontendToolIds`; `null` when empty, since the\n * send omits an empty list (it would erase a collab agent's own tools).\n * - `workbench`, `knowledge_base`: the list, `null` when empty.\n *\n * Pure.\n */\nexport function providerThreadConfig({\n model,\n systemPrompt,\n tools,\n frontendToolIds,\n workbench,\n knowledgeBase,\n extraRunConfig,\n}: {\n model: string | undefined;\n systemPrompt: string | undefined;\n tools: readonly string[] | undefined;\n frontendToolIds: readonly string[] | undefined;\n workbench: readonly string[] | undefined;\n knowledgeBase: readonly string[] | undefined;\n extraRunConfig: Record<string, unknown> | undefined;\n}): ProviderThreadConfig {\n const extra = extraRunConfig ?? {};\n const overrides = (key: ProviderThreadConfigKey) => Object.hasOwn(extra, key);\n const enabledTools = Array.from(new Set([...(tools ?? []), ...(frontendToolIds ?? [])]));\n const trimmedPrompt = systemPrompt?.trim() ?? '';\n return {\n model: effectiveStatewireModel({ model, extraRunConfig }) ?? null,\n system_prompt: overrides('system_prompt')\n ? nonBlankString(extra.system_prompt)\n : trimmedPrompt === ''\n ? null\n : trimmedPrompt,\n enabled_tools: overrides('enabled_tools')\n ? extraList(extra.enabled_tools)\n : propList(enabledTools),\n workbench: overrides('workbench') ? extraList(extra.workbench) : propList(workbench),\n knowledge_base: overrides('knowledge_base')\n ? extraList(extra.knowledge_base)\n : propList(knowledgeBase),\n };\n}\n\n/**\n * A key of the lane (`state.config.custom`) read as a provider-owned value:\n * a text key is its non-blank string, a list key its string items (an\n * explicit empty list included), anything else `null` (unset).\n */\nexport function readLaneThreadConfigValue({\n custom,\n key,\n}: {\n custom: ThreadConfigCustom;\n key: ProviderThreadConfigKey;\n}): string | readonly string[] | null {\n const value = custom[key];\n // `model` keeps `readLaneModel`'s reading: any non-empty string.\n if (key === 'model') return typeof value === 'string' && value !== '' ? value : null;\n if (key === 'system_prompt') return nonBlankString(value);\n return Array.isArray(value) ? stringItems(value) : null;\n}\n\n/** Whether two provider-owned values are the same (lists compared item by item, in order). */\nexport function sameThreadConfigValue(\n left: string | readonly string[] | null,\n right: string | readonly string[] | null,\n): boolean {\n if (left === right) return true;\n if (!Array.isArray(left) || !Array.isArray(right)) return false;\n return left.length === right.length && left.every((item, index) => item === right[index]);\n}\n\n/**\n * What to do with the pending changes of provider-owned keys:\n *\n * - `wait`: keep them pending. The thread's snapshot has not landed, or the\n * thread has no lane yet (version 0): the next send carries the values and\n * agora's deferral seed persists the ones it keeps. They stay pending so that\n * a lane an EARLIER send seeds (with the previous values) is corrected once\n * it lands.\n * - `done`: the lane already holds every one of them (this client's own\n * unacknowledged writes folded over); nothing to write.\n * - `patch`: issue one `config/patch` carrying exactly the keys whose lane\n * value differs; `null` unsets a key so the agent's own value (or the\n * default) applies.\n */\nexport type ThreadConfigLaneDecision =\n | { kind: 'wait' }\n | { kind: 'done' }\n | { kind: 'patch'; patch: ProviderThreadConfigPatch };\n\nexport function decideThreadConfigLanePatch({\n desired,\n keys,\n landed,\n configVersion,\n custom,\n}: {\n /** The provider's values after the changes. */\n desired: ProviderThreadConfig;\n /** The keys whose prop changed during this attach and is not yet written. */\n keys: Iterable<ProviderThreadConfigKey>;\n landed: boolean;\n configVersion: number;\n /** The effective lane: the server config with this client's pending writes folded over. */\n custom: ThreadConfigCustom;\n}): ThreadConfigLaneDecision {\n if (!landed || configVersion <= 0) return { kind: 'wait' };\n const pending = new Set(keys);\n const patch: ProviderThreadConfigPatch = {};\n for (const key of PROVIDER_THREAD_CONFIG_KEYS) {\n if (!pending.has(key)) continue;\n if (!sameThreadConfigValue(readLaneThreadConfigValue({ custom, key }), desired[key])) {\n copyThreadConfigKey({ target: patch, source: desired, key });\n }\n }\n return patchedThreadConfigKeys(patch).length === 0 ? { kind: 'done' } : { kind: 'patch', patch };\n}\n\nfunction copyThreadConfigKey<K extends ProviderThreadConfigKey>({\n target,\n source,\n key,\n}: {\n target: ProviderThreadConfigPatch;\n source: ProviderThreadConfig;\n key: K;\n}): void {\n target[key] = source[key];\n}\n\n/** The keys a patch carries, in {@link PROVIDER_THREAD_CONFIG_KEYS} order. */\nexport function patchedThreadConfigKeys(patch: ProviderThreadConfigPatch): ProviderThreadConfigKey[] {\n return PROVIDER_THREAD_CONFIG_KEYS.filter((key) => Object.hasOwn(patch, key));\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -157,8 +157,8 @@ function useAthenaStatewireRuntime(config) {
|
|
|
157
157
|
// core's per-render ref; the value-stable key re-registers (and so
|
|
158
158
|
// notifies) only when the built runConfig actually changed. On a thread
|
|
159
159
|
// with a server config lane, agora keeps only the per-send keys of what
|
|
160
|
-
// this carries; `
|
|
161
|
-
// lane itself.
|
|
160
|
+
// this carries; `StatewireThreadConfigLaneSync` writes a changed model,
|
|
161
|
+
// system prompt, tool list, workbench or knowledge base to the lane itself.
|
|
162
162
|
runConfig: {
|
|
163
163
|
get: () => runConfigValue,
|
|
164
164
|
key: runConfigKey
|