@percena/weft 0.4.0-next.4 → 0.4.0-next.6

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.
Files changed (71) hide show
  1. package/dist/chat.cjs +7 -883
  2. package/dist/chat.d.cts +13 -13
  3. package/dist/chat.d.ts +13 -13
  4. package/dist/chat.js +7 -883
  5. package/dist/index.cjs +96 -103
  6. package/dist/index.js +96 -103
  7. package/dist/providers-flitro.cjs +2 -276
  8. package/dist/providers-flitro.d.cts +2 -1
  9. package/dist/providers-flitro.d.ts +2 -1
  10. package/dist/providers-flitro.js +1 -260
  11. package/dist/styles/fonts/KaTeX_AMS-Regular.ttf +0 -0
  12. package/dist/styles/fonts/KaTeX_AMS-Regular.woff +0 -0
  13. package/dist/styles/fonts/KaTeX_AMS-Regular.woff2 +0 -0
  14. package/dist/styles/fonts/KaTeX_Caligraphic-Bold.ttf +0 -0
  15. package/dist/styles/fonts/KaTeX_Caligraphic-Bold.woff +0 -0
  16. package/dist/styles/fonts/KaTeX_Caligraphic-Bold.woff2 +0 -0
  17. package/dist/styles/fonts/KaTeX_Caligraphic-Regular.ttf +0 -0
  18. package/dist/styles/fonts/KaTeX_Caligraphic-Regular.woff +0 -0
  19. package/dist/styles/fonts/KaTeX_Caligraphic-Regular.woff2 +0 -0
  20. package/dist/styles/fonts/KaTeX_Fraktur-Bold.ttf +0 -0
  21. package/dist/styles/fonts/KaTeX_Fraktur-Bold.woff +0 -0
  22. package/dist/styles/fonts/KaTeX_Fraktur-Bold.woff2 +0 -0
  23. package/dist/styles/fonts/KaTeX_Fraktur-Regular.ttf +0 -0
  24. package/dist/styles/fonts/KaTeX_Fraktur-Regular.woff +0 -0
  25. package/dist/styles/fonts/KaTeX_Fraktur-Regular.woff2 +0 -0
  26. package/dist/styles/fonts/KaTeX_Main-Bold.ttf +0 -0
  27. package/dist/styles/fonts/KaTeX_Main-Bold.woff +0 -0
  28. package/dist/styles/fonts/KaTeX_Main-Bold.woff2 +0 -0
  29. package/dist/styles/fonts/KaTeX_Main-BoldItalic.ttf +0 -0
  30. package/dist/styles/fonts/KaTeX_Main-BoldItalic.woff +0 -0
  31. package/dist/styles/fonts/KaTeX_Main-BoldItalic.woff2 +0 -0
  32. package/dist/styles/fonts/KaTeX_Main-Italic.ttf +0 -0
  33. package/dist/styles/fonts/KaTeX_Main-Italic.woff +0 -0
  34. package/dist/styles/fonts/KaTeX_Main-Italic.woff2 +0 -0
  35. package/dist/styles/fonts/KaTeX_Main-Regular.ttf +0 -0
  36. package/dist/styles/fonts/KaTeX_Main-Regular.woff +0 -0
  37. package/dist/styles/fonts/KaTeX_Main-Regular.woff2 +0 -0
  38. package/dist/styles/fonts/KaTeX_Math-BoldItalic.ttf +0 -0
  39. package/dist/styles/fonts/KaTeX_Math-BoldItalic.woff +0 -0
  40. package/dist/styles/fonts/KaTeX_Math-BoldItalic.woff2 +0 -0
  41. package/dist/styles/fonts/KaTeX_Math-Italic.ttf +0 -0
  42. package/dist/styles/fonts/KaTeX_Math-Italic.woff +0 -0
  43. package/dist/styles/fonts/KaTeX_Math-Italic.woff2 +0 -0
  44. package/dist/styles/fonts/KaTeX_SansSerif-Bold.ttf +0 -0
  45. package/dist/styles/fonts/KaTeX_SansSerif-Bold.woff +0 -0
  46. package/dist/styles/fonts/KaTeX_SansSerif-Bold.woff2 +0 -0
  47. package/dist/styles/fonts/KaTeX_SansSerif-Italic.ttf +0 -0
  48. package/dist/styles/fonts/KaTeX_SansSerif-Italic.woff +0 -0
  49. package/dist/styles/fonts/KaTeX_SansSerif-Italic.woff2 +0 -0
  50. package/dist/styles/fonts/KaTeX_SansSerif-Regular.ttf +0 -0
  51. package/dist/styles/fonts/KaTeX_SansSerif-Regular.woff +0 -0
  52. package/dist/styles/fonts/KaTeX_SansSerif-Regular.woff2 +0 -0
  53. package/dist/styles/fonts/KaTeX_Script-Regular.ttf +0 -0
  54. package/dist/styles/fonts/KaTeX_Script-Regular.woff +0 -0
  55. package/dist/styles/fonts/KaTeX_Script-Regular.woff2 +0 -0
  56. package/dist/styles/fonts/KaTeX_Size1-Regular.ttf +0 -0
  57. package/dist/styles/fonts/KaTeX_Size1-Regular.woff +0 -0
  58. package/dist/styles/fonts/KaTeX_Size1-Regular.woff2 +0 -0
  59. package/dist/styles/fonts/KaTeX_Size2-Regular.ttf +0 -0
  60. package/dist/styles/fonts/KaTeX_Size2-Regular.woff +0 -0
  61. package/dist/styles/fonts/KaTeX_Size2-Regular.woff2 +0 -0
  62. package/dist/styles/fonts/KaTeX_Size3-Regular.ttf +0 -0
  63. package/dist/styles/fonts/KaTeX_Size3-Regular.woff +0 -0
  64. package/dist/styles/fonts/KaTeX_Size3-Regular.woff2 +0 -0
  65. package/dist/styles/fonts/KaTeX_Size4-Regular.ttf +0 -0
  66. package/dist/styles/fonts/KaTeX_Size4-Regular.woff +0 -0
  67. package/dist/styles/fonts/KaTeX_Size4-Regular.woff2 +0 -0
  68. package/dist/styles/fonts/KaTeX_Typewriter-Regular.ttf +0 -0
  69. package/dist/styles/fonts/KaTeX_Typewriter-Regular.woff +0 -0
  70. package/dist/styles/fonts/KaTeX_Typewriter-Regular.woff2 +0 -0
  71. package/package.json +1 -1
package/dist/chat.cjs CHANGED
@@ -7119,27 +7119,6 @@ var import_react18 = require("react");
7119
7119
  var import_react19 = require("react");
7120
7120
 
7121
7121
  // ../packages/timeline/dist/index.js
7122
- function createTimelineCursor(cursor) {
7123
- return {
7124
- epoch: cursor.epoch,
7125
- afterSeq: cursor.afterSeq
7126
- };
7127
- }
7128
- function fetchTimeline(timeline, request = {}) {
7129
- const ordered = sortTimeline(timeline);
7130
- const cursor = request.cursor ?? cursorFromTimelineStart(ordered);
7131
- const items = ordered.filter((item) => item.epoch === cursor.epoch && item.seq > cursor.afterSeq).slice(0, request.limit);
7132
- const lastSeq = items.at(-1)?.seq ?? cursor.afterSeq;
7133
- const firstSeq = items[0]?.seq;
7134
- return {
7135
- items,
7136
- nextCursor: {
7137
- epoch: cursor.epoch,
7138
- afterSeq: lastSeq
7139
- },
7140
- hasGap: firstSeq !== void 0 && firstSeq > cursor.afterSeq + 1
7141
- };
7142
- }
7143
7122
  function mergeTimeline(existing, incoming) {
7144
7123
  const byKey = /* @__PURE__ */ new Map();
7145
7124
  for (const item of [...existing, ...incoming]) {
@@ -7147,12 +7126,6 @@ function mergeTimeline(existing, incoming) {
7147
7126
  }
7148
7127
  return sortTimeline([...byKey.values()]);
7149
7128
  }
7150
- function cursorFromTimelineStart(timeline) {
7151
- return {
7152
- epoch: timeline[0]?.epoch ?? "default",
7153
- afterSeq: 0
7154
- };
7155
- }
7156
7129
  function sortTimeline(timeline) {
7157
7130
  return [...timeline].sort((left, right) => {
7158
7131
  if (left.epoch !== right.epoch) return left.epoch.localeCompare(right.epoch);
@@ -7930,879 +7903,30 @@ function TimelineAgentChatPanel({
7930
7903
  var import_react21 = require("react");
7931
7904
 
7932
7905
  // ../packages/runtime-core/dist/index.js
7933
- var RUNTIME_KINDS = ["native-sdk", "app-server", "compatible-sdk", "cli-fallback"];
7934
7906
  var initialRuntimeState = {
7935
7907
  status: "idle",
7936
7908
  acceptedMessages: [],
7937
7909
  queuedMessages: []
7938
7910
  };
7939
- function reduceRuntimeState(state = initialRuntimeState, action) {
7940
- switch (action.type) {
7941
- case "preflight_start":
7942
- return { ...state, status: "preflighting", lastError: void 0 };
7943
- case "preflight_ok":
7944
- return { ...state, status: "ready", lastError: void 0 };
7945
- case "preflight_error":
7946
- return { ...state, status: "failed", lastError: action.error };
7947
- case "starting":
7948
- if (state.status === "ready" || state.status === "idle") {
7949
- return { ...state, status: "starting" };
7950
- }
7951
- return state;
7952
- case "send_message":
7953
- if (state.status === "running" || state.status === "waiting_for_permission") {
7954
- return {
7955
- ...state,
7956
- queuedMessages: [...state.queuedMessages, action.message]
7957
- };
7958
- }
7959
- return {
7960
- ...state,
7961
- status: "running",
7962
- acceptedMessages: [...state.acceptedMessages, action.message]
7963
- };
7964
- case "permission_request":
7965
- return {
7966
- ...state,
7967
- status: "waiting_for_permission",
7968
- waitingPermissionRequestId: action.requestId
7969
- };
7970
- case "permission_response":
7971
- return {
7972
- ...state,
7973
- status: "running",
7974
- waitingPermissionRequestId: void 0
7975
- };
7976
- case "turn_completed":
7977
- if (state.status === "running") {
7978
- return { ...state, status: "turn_completed" };
7979
- }
7980
- return state;
7981
- case "complete": {
7982
- if (state.status === "turn_completed") {
7983
- const [nextMessage2, ...remaining2] = state.queuedMessages;
7984
- if (nextMessage2) {
7985
- return {
7986
- ...state,
7987
- status: "running",
7988
- acceptedMessages: [...state.acceptedMessages, nextMessage2],
7989
- queuedMessages: remaining2
7990
- };
7991
- }
7992
- return { ...state, status: "ready" };
7993
- }
7994
- const [nextMessage, ...remaining] = state.queuedMessages;
7995
- if (nextMessage) {
7996
- return {
7997
- ...state,
7998
- status: "running",
7999
- acceptedMessages: [...state.acceptedMessages, nextMessage],
8000
- queuedMessages: remaining
8001
- };
8002
- }
8003
- return { ...state, status: "ready" };
8004
- }
8005
- case "abort":
8006
- return {
8007
- ...state,
8008
- status: "ready",
8009
- lastError: action.reason,
8010
- queuedMessages: [],
8011
- waitingPermissionRequestId: void 0
8012
- };
8013
- case "error":
8014
- return { ...state, status: "failed", lastError: action.error };
8015
- case "dispose":
8016
- return {
8017
- ...state,
8018
- status: "disposed",
8019
- queuedMessages: [],
8020
- waitingPermissionRequestId: void 0
8021
- };
8022
- }
8023
- }
8024
- function createRuntimeExtensionContext(context = {}) {
8025
- return {
8026
- policy: context.policy,
8027
- sources: context.sources ? { enabledSourceSlugs: unique(context.sources.enabledSourceSlugs) } : void 0,
8028
- skills: context.skills ? { activeSkillSlugs: unique(context.skills.activeSkillSlugs) } : void 0,
8029
- commandOrigin: context.commandOrigin,
8030
- hostServices: context.hostServices
8031
- };
8032
- }
8033
- function unique(values) {
8034
- return [...new Set(values)];
8035
- }
8036
- function findCandidate(candidates, kind) {
8037
- return candidates.find((candidate) => candidate.kind === kind);
8038
- }
8039
- function defaultRuntimeKindOrder(provider) {
8040
- if (provider === "codex") {
8041
- return ["app-server", "native-sdk", "compatible-sdk", "cli-fallback"];
8042
- }
8043
- return RUNTIME_KINDS;
8044
- }
8045
- function firstAvailableCandidate(candidates, provider) {
8046
- for (const kind of defaultRuntimeKindOrder(provider)) {
8047
- const candidate = findCandidate(candidates, kind);
8048
- if (candidate?.available) return candidate;
8049
- }
8050
- return void 0;
8051
- }
8052
- function selectRuntimeCandidate(options) {
8053
- const preferred = options.preferredRuntime ? findCandidate(options.candidates, options.preferredRuntime) : void 0;
8054
- if (preferred?.available) {
8055
- return { selected: preferred.kind, fallback: false };
8056
- }
8057
- if (preferred && options.allowFallback !== true) {
8058
- return {
8059
- fallback: false,
8060
- error: preferred.reason ?? `${preferred.kind} runtime is unavailable`
8061
- };
8062
- }
8063
- const selected = firstAvailableCandidate(options.candidates, options.provider);
8064
- if (!selected) {
8065
- return {
8066
- fallback: false,
8067
- error: options.candidates.map((candidate) => candidate.reason).filter(Boolean).join("; ") || "No runtime candidates are available"
8068
- };
8069
- }
8070
- const fallback = Boolean(preferred && selected.kind !== preferred.kind);
8071
- return {
8072
- selected: selected.kind,
8073
- fallback,
8074
- fallbackReason: fallback ? preferred?.reason ?? `${preferred?.kind ?? "preferred"} runtime is unavailable` : void 0
8075
- };
8076
- }
8077
- function createRuntimeCapabilityReport(options) {
8078
- const selection = selectRuntimeCandidate(options);
8079
- const extensionCapabilities = normalizeExtensionCapabilities(options.extensionCapabilities);
8080
- return {
8081
- provider: options.provider,
8082
- candidates: options.candidates,
8083
- preferredRuntime: options.preferredRuntime,
8084
- allowFallback: options.allowFallback === true,
8085
- auth: options.auth,
8086
- ...extensionCapabilities,
8087
- ...selection
8088
- };
8089
- }
8090
- function normalizeExtensionCapabilities(capabilities = {}) {
8091
- return {
8092
- policyCapabilities: capabilities.policy ?? {
8093
- supported: false,
8094
- modes: [],
8095
- approvals: false,
8096
- toolPolicy: false
8097
- },
8098
- sourceCapabilities: capabilities.sources ?? {
8099
- supported: false
8100
- },
8101
- skillCapabilities: capabilities.skills ?? {
8102
- supported: false
8103
- },
8104
- automationCapabilities: capabilities.automations ?? {
8105
- supported: false,
8106
- eventBus: false,
8107
- schedulerHost: false,
8108
- promptAction: false,
8109
- webhookAction: false
8110
- },
8111
- hostToolCapabilities: capabilities.hostTools ?? {
8112
- supported: false,
8113
- sessionTools: false,
8114
- workflowTransitions: false,
8115
- browserActions: false,
8116
- metadataWrites: false
8117
- }
8118
- };
8119
- }
8120
-
8121
- // ../packages/client/dist/index.js
8122
- var FlitroHttpClient = class {
8123
- baseUrl;
8124
- timeout;
8125
- apiKey;
8126
- tenantId;
8127
- onTokenExpired;
8128
- token;
8129
- constructor(options) {
8130
- this.baseUrl = options.baseUrl.replace(/\/$/, "");
8131
- this.timeout = options.timeout ?? 3e4;
8132
- this.apiKey = options.apiKey ?? "";
8133
- this.tenantId = options.tenantId ?? "";
8134
- this.token = options.token ?? "";
8135
- this.onTokenExpired = options.onTokenExpired;
8136
- }
8137
- /** Current Authorization bearer (scoped token wins over apiKey). */
8138
- getBearerToken() {
8139
- return this.token || this.apiKey;
8140
- }
8141
- /** Replace the scoped token (e.g. after a host-backend refresh). */
8142
- setToken(token) {
8143
- this.token = token;
8144
- }
8145
- buildHeaders() {
8146
- const headers = { "Content-Type": "application/json" };
8147
- const bearer = this.getBearerToken();
8148
- if (bearer) headers["Authorization"] = `Bearer ${bearer}`;
8149
- if (!this.token && this.tenantId) headers["X-Tenant-ID"] = this.tenantId;
8150
- return headers;
8151
- }
8152
- async preflight() {
8153
- return this.get("/v1/capabilities");
8154
- }
8155
- async health() {
8156
- return this.get("/v1/health");
8157
- }
8158
- async createSession(options) {
8159
- return this.post("/v1/sessions", {
8160
- title: options?.title ?? "Weft session",
8161
- model: options?.model,
8162
- skill_names: options?.skillNames,
8163
- mcp_server_names: options?.mcpServerNames
8164
- });
8165
- }
8166
- async getSession(sessionId) {
8167
- return this.get(`/v1/sessions/${encodeURIComponent(sessionId)}`);
8168
- }
8169
- async sendMessage(sessionId, message, options) {
8170
- const budget = options?.budget ? {
8171
- max_steps: options.budget.maxSteps,
8172
- max_tokens: options.budget.maxTokens,
8173
- max_wall_time_sec: options.budget.maxWallTimeSec
8174
- } : void 0;
8175
- return this.post(`/v1/sessions/${encodeURIComponent(sessionId)}/runs`, {
8176
- message,
8177
- model: options?.model,
8178
- skill_names: options?.skillNames,
8179
- mcp_server_names: options?.mcpServerNames,
8180
- tool_names: options?.toolNames,
8181
- approval_policy: options?.approvalPolicy,
8182
- execution_mode: options?.executionMode,
8183
- workspace_id: options?.workspaceId,
8184
- budget
8185
- });
8186
- }
8187
- async cancelRun(runId) {
8188
- return this.post(`/v1/runs/${encodeURIComponent(runId)}/cancel`, {});
8189
- }
8190
- async resumeTool(runId, resumeData) {
8191
- return this.post(
8192
- `/v1/runs/${encodeURIComponent(runId)}/resume-tool`,
8193
- { resume_data: resumeData }
8194
- );
8195
- }
8196
- async respondToPermission(sessionId, requestId, allowed, options) {
8197
- return this.post(
8198
- `/v1/sessions/${encodeURIComponent(sessionId)}/permission-response`,
8199
- { requestId, allowed, remember: options?.remember, text: options?.text, answer: options?.answer }
8200
- );
8201
- }
8202
- async patchSession(sessionId, patch) {
8203
- return this.patch(
8204
- `/v1/sessions/${encodeURIComponent(sessionId)}`,
8205
- patch
8206
- );
8207
- }
8208
- async listModels() {
8209
- return this.get("/v1/models");
8210
- }
8211
- async fetchTimeline(sessionId, afterSeq, limit) {
8212
- const params = new URLSearchParams();
8213
- if (afterSeq !== void 0) params.set("after_seq", String(afterSeq));
8214
- if (limit !== void 0) params.set("limit", String(limit));
8215
- const qs = params.toString();
8216
- const url = `/v1/sessions/${encodeURIComponent(sessionId)}/timeline/fetch${qs ? `?${qs}` : ""}`;
8217
- return this.get(url);
8218
- }
8219
- /** Returns the SSE stream URL for a session's canonical timeline. */
8220
- sessionTimelineUrl(sessionId) {
8221
- return `${this.baseUrl}/v1/sessions/${encodeURIComponent(sessionId)}/timeline`;
8222
- }
8223
- async get(path) {
8224
- return this.request("GET", path, void 0);
8225
- }
8226
- async post(path, body) {
8227
- return this.request("POST", path, body);
8228
- }
8229
- async patch(path, body) {
8230
- return this.request("PATCH", path, body);
8231
- }
8232
- async request(method, path, body, isRetry = false) {
8233
- const url = `${this.baseUrl}${path}`;
8234
- const controller = new AbortController();
8235
- const timer = setTimeout(() => controller.abort(), this.timeout);
8236
- try {
8237
- const response = await fetch(url, {
8238
- method,
8239
- headers: this.buildHeaders(),
8240
- body: body !== void 0 ? JSON.stringify(body) : void 0,
8241
- signal: controller.signal
8242
- });
8243
- if (response.status === 401 && this.token && this.onTokenExpired && !isRetry) {
8244
- const fresh = await this.onTokenExpired();
8245
- if (fresh) {
8246
- this.token = fresh;
8247
- return this.request(method, path, body, true);
8248
- }
8249
- }
8250
- if (!response.ok) {
8251
- let errorMsg = `Flitro HTTP ${response.status}`;
8252
- try {
8253
- const errBody = await response.json();
8254
- if (errBody.error) errorMsg = `${errorMsg}: ${errBody.error}`;
8255
- } catch {
8256
- }
8257
- throw new Error(errorMsg);
8258
- }
8259
- return response.json();
8260
- } finally {
8261
- clearTimeout(timer);
8262
- }
8263
- }
8264
- };
8265
- var FlitroFetchSseTimelineStream = class {
8266
- listeners = /* @__PURE__ */ new Set();
8267
- abortController = null;
8268
- connected = false;
8269
- disposed = false;
8270
- afterSeq;
8271
- reconnectAttempts = 0;
8272
- tokenOverride = "";
8273
- getBearerToken;
8274
- onTokenExpired;
8275
- options;
8276
- constructor(options) {
8277
- this.afterSeq = options.initialAfterSeq ?? 0;
8278
- this.getBearerToken = options.getBearerToken;
8279
- this.onTokenExpired = options.onTokenExpired;
8280
- this.options = {
8281
- url: options.url,
8282
- apiKey: options.apiKey ?? "",
8283
- tenantId: options.tenantId ?? "",
8284
- reconnectDelayMs: options.reconnectDelayMs ?? 1500,
8285
- maxReconnectAttempts: options.maxReconnectAttempts ?? 20,
8286
- initialAfterSeq: this.afterSeq,
8287
- now: options.now ?? (() => Date.now())
8288
- };
8289
- }
8290
- connect(onEvent, onError, onClose) {
8291
- this.disposed = false;
8292
- this.listeners.add({ onEvent, onError, onClose });
8293
- if (!this.connected) {
8294
- this.connected = true;
8295
- this.reconnectAttempts = 0;
8296
- this.startFetch();
8297
- }
8298
- }
8299
- disconnect() {
8300
- this.disposed = true;
8301
- this.connected = false;
8302
- this.abortController?.abort();
8303
- for (const listener of this.listeners) {
8304
- listener.onClose?.();
8305
- }
8306
- this.listeners.clear();
8307
- }
8308
- isConnected() {
8309
- return this.connected && !this.disposed;
8310
- }
8311
- buildUrl() {
8312
- let url = this.options.url;
8313
- if (this.afterSeq > 0) {
8314
- url += (url.includes("?") ? "&" : "?") + `after_seq=${this.afterSeq}`;
8315
- }
8316
- return url;
8317
- }
8318
- buildHeaders() {
8319
- const h = { Accept: "text/event-stream" };
8320
- const bearer = this.tokenOverride || this.getBearerToken?.() || this.options.apiKey;
8321
- if (bearer) h["Authorization"] = `Bearer ${bearer}`;
8322
- if (this.options.tenantId) h["X-Tenant-ID"] = this.options.tenantId;
8323
- return h;
8324
- }
8325
- async startFetch() {
8326
- if (this.disposed) return;
8327
- this.abortController = new AbortController();
8328
- try {
8329
- const response = await fetch(this.buildUrl(), {
8330
- headers: this.buildHeaders(),
8331
- signal: this.abortController.signal
8332
- });
8333
- if (response.status === 401 && this.onTokenExpired) {
8334
- const fresh = await this.onTokenExpired();
8335
- if (fresh) this.tokenOverride = fresh;
8336
- }
8337
- if (!response.ok || !response.body) {
8338
- throw new Error(`Flitro SSE: HTTP ${response.status}`);
8339
- }
8340
- this.reconnectAttempts = 0;
8341
- const reader = response.body.getReader();
8342
- const decoder = new TextDecoder();
8343
- let buffer = "";
8344
- while (true) {
8345
- const { done, value } = await reader.read();
8346
- if (done) break;
8347
- buffer += decoder.decode(value, { stream: true });
8348
- const envelopes = parseSseBuffer(buffer);
8349
- buffer = envelopes.remainder;
8350
- for (const envelope of envelopes.items) {
8351
- if (envelope.seq > this.afterSeq) {
8352
- this.afterSeq = envelope.seq;
8353
- }
8354
- for (const listener of this.listeners) {
8355
- listener.onEvent(envelope);
8356
- }
8357
- }
8358
- }
8359
- if (!this.disposed) {
8360
- this.connected = false;
8361
- this.scheduleReconnect();
8362
- }
8363
- } catch (err) {
8364
- if (this.disposed) return;
8365
- if (err instanceof Error && err.name === "AbortError") return;
8366
- this.connected = false;
8367
- this.scheduleReconnect();
8368
- }
8369
- }
8370
- scheduleReconnect() {
8371
- if (this.disposed) return;
8372
- if (this.reconnectAttempts >= this.options.maxReconnectAttempts) {
8373
- this.emitError(new Error(`Flitro SSE: max reconnect attempts reached`));
8374
- return;
8375
- }
8376
- this.reconnectAttempts++;
8377
- const delay = Math.min(this.options.reconnectDelayMs * this.reconnectAttempts, 3e4);
8378
- setTimeout(() => {
8379
- this.connected = true;
8380
- this.startFetch();
8381
- }, delay);
8382
- }
8383
- emitError(err) {
8384
- for (const listener of this.listeners) listener.onError?.(err);
8385
- }
8386
- };
8387
- function parseSseBuffer(buffer) {
8388
- const items = [];
8389
- const blocks = buffer.split("\n\n");
8390
- const remainder = blocks.pop() ?? "";
8391
- for (const block of blocks) {
8392
- let eventType = "";
8393
- let data = "";
8394
- for (const line of block.split("\n")) {
8395
- if (line.startsWith("event: ")) {
8396
- eventType = line.slice(7).trim();
8397
- } else if (line.startsWith("data: ")) {
8398
- data = line.slice(6).trim();
8399
- }
8400
- }
8401
- if (eventType === "timeline" && data) {
8402
- try {
8403
- items.push(JSON.parse(data));
8404
- } catch {
8405
- }
8406
- }
8407
- }
8408
- return { items, remainder };
8409
- }
8410
- function createFlitroTimelineStream(options) {
8411
- return new FlitroFetchSseTimelineStream(options);
8412
- }
8413
-
8414
- // ../packages/provider-flitro/dist/index.js
8415
- function mapPermissionModeToApprovalPolicy(mode) {
8416
- if (mode === "allow-all") return "auto";
8417
- if (mode === "safe") return "never";
8418
- if (mode === "ask") return "on-request";
8419
- return void 0;
8420
- }
8421
- function createFlitroDriver(options) {
8422
- let activeRunId;
8423
- return {
8424
- async sendMessage(input, _sequencer) {
8425
- const run = await options.client.sendMessage(
8426
- options.sessionId,
8427
- input.message,
8428
- {
8429
- model: input.options?.model ?? options.model,
8430
- skillNames: options.skillNames,
8431
- mcpServerNames: options.mcpServerNames,
8432
- // Per-message permission choice (from the chat panel selector) wins
8433
- // over the runtime's creation-time default.
8434
- approvalPolicy: mapPermissionModeToApprovalPolicy(input.options?.permissionMode) ?? options.approvalPolicy
8435
- }
8436
- );
8437
- activeRunId = run.run_id;
8438
- },
8439
- async abort(reason) {
8440
- if (activeRunId) {
8441
- await options.client.cancelRun(activeRunId).catch(() => {
8442
- });
8443
- activeRunId = void 0;
8444
- }
8445
- },
8446
- async respondToPermission(requestId, allowed, remember) {
8447
- await options.client.respondToPermission(options.sessionId, requestId, allowed, {
8448
- remember
8449
- });
8450
- },
8451
- async resumeTool(runId, resumeData) {
8452
- await options.client.resumeTool(runId, resumeData);
8453
- },
8454
- async dispose() {
8455
- if (activeRunId) {
8456
- await options.client.cancelRun(activeRunId).catch(() => {
8457
- });
8458
- activeRunId = void 0;
8459
- }
8460
- }
8461
- };
8462
- }
8463
- function createFlitroRuntimeCapabilityReport(options) {
8464
- const appServerAvailable = options.candidates.some((c) => c.kind === "app-server" && c.available);
8465
- return createRuntimeCapabilityReport({
8466
- provider: "flitro",
8467
- candidates: options.candidates,
8468
- preferredRuntime: "app-server",
8469
- allowFallback: options.allowFallback,
8470
- auth: options.auth,
8471
- extensionCapabilities: {
8472
- policy: {
8473
- supported: true,
8474
- degraded: !appServerAvailable || void 0,
8475
- modes: ["safe", "ask", "allow-all"],
8476
- approvals: appServerAvailable,
8477
- toolPolicy: appServerAvailable,
8478
- reason: appServerAvailable ? void 0 : "Flitro server is unavailable"
8479
- },
8480
- sources: {
8481
- supported: appServerAvailable,
8482
- registry: appServerAvailable,
8483
- mcpTools: appServerAvailable,
8484
- credentialGateway: false,
8485
- reason: appServerAvailable ? void 0 : "Source tools require a running Flitro server"
8486
- },
8487
- skills: {
8488
- supported: appServerAvailable,
8489
- registry: appServerAvailable,
8490
- activationPlan: appServerAvailable,
8491
- scopedPolicy: appServerAvailable,
8492
- reason: appServerAvailable ? void 0 : "Skill activation requires a running Flitro server"
8493
- },
8494
- automations: {
8495
- supported: appServerAvailable,
8496
- degraded: !appServerAvailable || void 0,
8497
- eventBus: appServerAvailable,
8498
- schedulerHost: appServerAvailable,
8499
- promptAction: appServerAvailable,
8500
- webhookAction: false,
8501
- reason: appServerAvailable ? void 0 : "Automations require a running Flitro server"
8502
- },
8503
- hostTools: {
8504
- supported: appServerAvailable,
8505
- sessionTools: false,
8506
- workflowTransitions: false,
8507
- browserActions: false,
8508
- metadataWrites: appServerAvailable
8509
- }
8510
- }
8511
- });
8512
- }
8513
- function createFlitroProviderRuntime(options) {
8514
- const report = createFlitroRuntimeCapabilityReport(options);
8515
- const extensions = createRuntimeExtensionContext(options.extensions);
8516
- const client = new FlitroHttpClient(options.server);
8517
- let resolvedSessionId = options.sessionId ?? "";
8518
- let epoch = options.epoch ?? (resolvedSessionId ? `flitro-${resolvedSessionId}` : "flitro-pending");
8519
- const now = options.now ?? (() => Date.now());
8520
- const timeline = [];
8521
- const seenTimelineKeys = /* @__PURE__ */ new Set();
8522
- const stream = new PushTimelineStream();
8523
- let state = initialRuntimeState;
8524
- let runtimeDriver = options.driver;
8525
- let sseStream;
8526
- const pendingMessages = [];
8527
- function dispatch(action) {
8528
- state = reduceRuntimeState(state, action);
8529
- }
8530
- function syncStateFromEnvelope(envelope) {
8531
- const item = envelope.item;
8532
- if (item.type === "permission_requested") {
8533
- dispatch({ type: "permission_request", requestId: item.request.requestId });
8534
- } else if (item.type === "permission_resolved") {
8535
- dispatch({ type: "permission_response" });
8536
- } else if (item.type === "turn_completed") {
8537
- dispatch({ type: "turn_completed" });
8538
- dispatch({ type: "complete" });
8539
- void sendNextPendingMessage();
8540
- } else if (item.type === "turn_failed") {
8541
- const err = item.error;
8542
- dispatch({ type: "error", error: err?.message ?? "turn failed" });
8543
- } else if (item.type === "tool_suspended") {
8544
- dispatch({ type: "permission_request", requestId: `tool-suspend:${item.callId}` });
8545
- } else if (item.type === "tool_resumed") {
8546
- dispatch({ type: "permission_response" });
8547
- } else if (item.type === "session_status") {
8548
- if (item.status === "running") {
8549
- dispatch({ type: "starting" });
8550
- } else if (item.status === "ended") {
8551
- dispatch({ type: "abort" });
8552
- }
8553
- }
8554
- }
8555
- function appendEnvelope(envelope) {
8556
- if (envelope.seq > 0) {
8557
- const key = `${envelope.epoch || envelope.sessionId || "unknown"}:${envelope.seq}`;
8558
- if (seenTimelineKeys.has(key)) return;
8559
- seenTimelineKeys.add(key);
8560
- }
8561
- syncStateFromEnvelope(envelope);
8562
- timeline.push(envelope);
8563
- stream.emit(envelope);
8564
- }
8565
- function appendFailure(message) {
8566
- const item = { type: "turn_failed", turnId: "provider-runtime", error: { message } };
8567
- const envelope = {
8568
- sessionId: resolvedSessionId,
8569
- provider: "flitro",
8570
- seq: timeline.length + 1,
8571
- epoch,
8572
- timestamp: now(),
8573
- item
8574
- };
8575
- appendEnvelope(envelope);
8576
- }
8577
- function getDriver() {
8578
- if (runtimeDriver) return runtimeDriver;
8579
- runtimeDriver = createFlitroDriver({
8580
- client,
8581
- sessionId: resolvedSessionId,
8582
- model: options.model,
8583
- skillNames: options.skillNames,
8584
- mcpServerNames: options.mcpServerNames,
8585
- approvalPolicy: options.approvalPolicy
8586
- });
8587
- return runtimeDriver;
8588
- }
8589
- async function sendToFlitro(message, sendOptions) {
8590
- const driver = getDriver();
8591
- try {
8592
- await driver.sendMessage({ message, options: sendOptions }, {
8593
- append: (item, rawRef) => {
8594
- const envelope = {
8595
- sessionId: resolvedSessionId,
8596
- provider: "flitro",
8597
- seq: timeline.length + 1,
8598
- epoch,
8599
- timestamp: now(),
8600
- item,
8601
- rawRef
8602
- };
8603
- appendEnvelope(envelope);
8604
- return envelope;
8605
- }
8606
- });
8607
- } catch (err) {
8608
- const error = err instanceof Error ? err.message : String(err);
8609
- dispatch({ type: "error", error });
8610
- appendFailure(error);
8611
- throw err;
8612
- }
8613
- }
8614
- async function sendNextPendingMessage() {
8615
- const next = pendingMessages.shift();
8616
- if (!next) return;
8617
- try {
8618
- await sendToFlitro(next.message, next.options);
8619
- } catch {
8620
- }
8621
- }
8622
- async function ensureSession() {
8623
- if (resolvedSessionId) return;
8624
- const session = await client.createSession({
8625
- model: options.model,
8626
- skillNames: options.skillNames,
8627
- mcpServerNames: options.mcpServerNames
8628
- });
8629
- resolvedSessionId = session.session_id;
8630
- if (!options.epoch) {
8631
- epoch = `flitro-${resolvedSessionId}`;
8632
- }
8633
- connectSse();
8634
- }
8635
- function connectSse() {
8636
- if (!resolvedSessionId || sseStream) return;
8637
- sseStream = createFlitroTimelineStream({
8638
- url: client.sessionTimelineUrl(resolvedSessionId),
8639
- apiKey: options.server.apiKey,
8640
- tenantId: options.server.tenantId,
8641
- // Scoped embed tokens rotate; always read the client's current bearer
8642
- // and propagate refreshed tokens back to it.
8643
- getBearerToken: () => client.getBearerToken(),
8644
- onTokenExpired: options.server.onTokenExpired ? async () => {
8645
- const fresh = await options.server.onTokenExpired?.();
8646
- if (fresh) client.setToken(fresh);
8647
- return fresh;
8648
- } : void 0
8649
- });
8650
- sseStream.connect(
8651
- // The client package types `item` as unknown; the server emits the
8652
- // canonical Weft envelope, so this is the narrowing point.
8653
- (envelope) => appendEnvelope(envelope),
8654
- (_err) => {
8655
- }
8656
- );
8657
- }
8658
- if (resolvedSessionId) {
8659
- connectSse();
8660
- }
8661
- return {
8662
- get sessionId() {
8663
- return resolvedSessionId;
8664
- },
8665
- provider: "flitro",
8666
- runtimeKind: report.selected ?? "app-server",
8667
- events: stream,
8668
- commands: {
8669
- async sendMessage(message, sendOptions) {
8670
- await ensureSession();
8671
- const shouldQueue = state.status === "running" || state.status === "waiting_for_permission";
8672
- dispatch({ type: "send_message", message });
8673
- if (shouldQueue) {
8674
- pendingMessages.push({ message, options: sendOptions });
8675
- return;
8676
- }
8677
- await sendToFlitro(message, sendOptions);
8678
- },
8679
- async abort(reason) {
8680
- dispatch({ type: "abort", reason });
8681
- pendingMessages.length = 0;
8682
- await runtimeDriver?.abort?.(reason);
8683
- },
8684
- async respondToPermission(requestId, allowed, remember) {
8685
- await getDriver().respondToPermission?.(requestId, allowed, remember);
8686
- dispatch({ type: "permission_response" });
8687
- },
8688
- async resumeTool(runId, resumeData) {
8689
- await getDriver().resumeTool?.(runId, resumeData);
8690
- },
8691
- async dispose() {
8692
- dispatch({ type: "dispose" });
8693
- pendingMessages.length = 0;
8694
- sseStream?.disconnect();
8695
- sseStream = void 0;
8696
- await runtimeDriver?.dispose?.();
8697
- }
8698
- },
8699
- async preflight() {
8700
- dispatch({ type: "preflight_start" });
8701
- if (!report.selected) {
8702
- dispatch({ type: "preflight_error", error: report.error ?? "No runtime selected" });
8703
- } else {
8704
- dispatch({ type: "preflight_ok" });
8705
- }
8706
- const capItem = { type: "runtime_capability_report", report };
8707
- const capEnvelope = {
8708
- sessionId: resolvedSessionId,
8709
- provider: "flitro",
8710
- seq: timeline.length + 1,
8711
- epoch,
8712
- timestamp: now(),
8713
- item: capItem
8714
- };
8715
- appendEnvelope(capEnvelope);
8716
- return report;
8717
- },
8718
- async fetchTimeline(request = {}) {
8719
- if (request.cursor?.epoch === epoch || !request.cursor) {
8720
- const localResult = fetchTimeline(timeline, request);
8721
- if (localResult.items.length > 0) return localResult;
8722
- }
8723
- if (resolvedSessionId) {
8724
- try {
8725
- const afterSeq = request.cursor?.afterSeq ?? 0;
8726
- const result = await client.fetchTimeline(resolvedSessionId, afterSeq, request.limit);
8727
- return {
8728
- items: result.items,
8729
- nextCursor: createTimelineCursor({
8730
- epoch: result.nextCursor.epoch,
8731
- afterSeq: result.nextCursor.afterSeq
8732
- }),
8733
- hasGap: result.hasGap
8734
- };
8735
- } catch {
8736
- }
8737
- }
8738
- return {
8739
- items: [],
8740
- nextCursor: createTimelineCursor({ epoch, afterSeq: 0 }),
8741
- hasGap: false
8742
- };
8743
- },
8744
- getState() {
8745
- return state;
8746
- }
8747
- };
8748
- }
8749
- function createFlitroEmbedRuntime(options) {
8750
- return createFlitroProviderRuntime({
8751
- server: {
8752
- baseUrl: options.baseUrl,
8753
- token: options.token,
8754
- onTokenExpired: options.onTokenExpired
8755
- },
8756
- sessionId: options.sessionId,
8757
- epoch: options.epoch,
8758
- now: options.now,
8759
- extensions: options.extensions,
8760
- candidates: [{ kind: "app-server", available: true }],
8761
- auth: { mode: "provider-owned", configured: true, source: "flitro-embed" }
8762
- });
8763
- }
8764
- var PushTimelineStream = class {
8765
- listeners = /* @__PURE__ */ new Set();
8766
- connect(onEvent, onError, onClose) {
8767
- this.listeners.add({ onEvent, onError, onClose });
8768
- }
8769
- disconnect() {
8770
- for (const l of this.listeners) l.onClose?.();
8771
- this.listeners.clear();
8772
- }
8773
- isConnected() {
8774
- return this.listeners.size > 0;
8775
- }
8776
- emit(event) {
8777
- for (const l of this.listeners) l.onEvent(event);
8778
- }
8779
- };
8780
7911
 
8781
7912
  // ../packages/react/src/use-agent-session.ts
8782
7913
  function useAgentSession(options) {
8783
- const onTokenExpiredRef = (0, import_react21.useRef)(options.onTokenExpired);
8784
- onTokenExpiredRef.current = options.onTokenExpired;
8785
- const tokenRef = (0, import_react21.useRef)(options.token);
8786
- tokenRef.current = options.token;
7914
+ const createRuntimeRef = (0, import_react21.useRef)(options.createRuntime);
7915
+ createRuntimeRef.current = options.createRuntime;
8787
7916
  const runtime = (0, import_react21.useMemo)(() => {
8788
7917
  return createDeferredAgentRuntime({
8789
- provider: "flitro",
8790
- runtimeKind: "app-server",
7918
+ provider: options.provider ?? "agent",
7919
+ runtimeKind: options.runtimeKind ?? "app-server",
8791
7920
  sessionId: options.sessionId,
8792
- createRuntime: () => createFlitroEmbedRuntime({
8793
- baseUrl: options.server,
8794
- token: tokenRef.current,
8795
- sessionId: options.sessionId,
8796
- onTokenExpired: () => onTokenExpiredRef.current?.()
8797
- })
7921
+ createRuntime: () => createRuntimeRef.current()
8798
7922
  });
8799
- }, [options.server, options.sessionId]);
7923
+ }, [options.sessionId]);
8800
7924
  (0, import_react21.useEffect)(() => {
8801
7925
  return () => {
8802
7926
  void runtime.disposeIfCreated();
8803
7927
  };
8804
7928
  }, [runtime]);
8805
- return { runtime, sessionId: options.sessionId, server: options.server };
7929
+ return { runtime, sessionId: options.sessionId };
8806
7930
  }
8807
7931
  function createDeferredAgentRuntime(options) {
8808
7932
  let runtime = null;