@ateam-ai-mobile/core 0.1.0 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +340 -7
- package/dist/index.d.ts +340 -7
- package/dist/index.js +623 -5
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +605 -4
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
- package/src/acs/api.ts +345 -0
- package/src/acs/homeActionsStore.ts +178 -0
- package/src/acs/providers.ts +44 -0
- package/src/acs/widgetsStore.ts +229 -0
- package/src/acs/ws.ts +198 -0
- package/src/api/tenants.ts +22 -0
- package/src/config.ts +25 -9
- package/src/index.ts +37 -0
package/dist/index.mjs
CHANGED
|
@@ -12,8 +12,11 @@ function getConfig() {
|
|
|
12
12
|
}
|
|
13
13
|
return _config;
|
|
14
14
|
}
|
|
15
|
+
function resolveUrl(src) {
|
|
16
|
+
return (typeof src === "function" ? src() : src).replace(/\/$/, "");
|
|
17
|
+
}
|
|
15
18
|
function getCoreApiUrl() {
|
|
16
|
-
return getConfig().coreUrl
|
|
19
|
+
return resolveUrl(getConfig().coreUrl);
|
|
17
20
|
}
|
|
18
21
|
function getCoreWsUrl() {
|
|
19
22
|
return getCoreApiUrl().replace(/^http/, "ws");
|
|
@@ -21,10 +24,11 @@ function getCoreWsUrl() {
|
|
|
21
24
|
function getVoiceApiUrl() {
|
|
22
25
|
const url = getConfig().voiceUrl;
|
|
23
26
|
if (!url) throw new Error("[adas] voiceUrl not configured");
|
|
24
|
-
return url
|
|
27
|
+
return resolveUrl(url);
|
|
25
28
|
}
|
|
26
29
|
function getTenant() {
|
|
27
|
-
|
|
30
|
+
const t = getConfig().tenant;
|
|
31
|
+
return (typeof t === "function" ? t() : t) || "";
|
|
28
32
|
}
|
|
29
33
|
function getUser() {
|
|
30
34
|
return getConfig().getUser?.() || null;
|
|
@@ -161,6 +165,12 @@ function unwrapMcpResult(result) {
|
|
|
161
165
|
}
|
|
162
166
|
}
|
|
163
167
|
|
|
168
|
+
// src/api/tenants.ts
|
|
169
|
+
async function listMyTenants() {
|
|
170
|
+
const data = await apiFetch("/api/tenants/list");
|
|
171
|
+
return data.ok && Array.isArray(data.tenants) ? data.tenants : [];
|
|
172
|
+
}
|
|
173
|
+
|
|
164
174
|
// src/chat/store.ts
|
|
165
175
|
import { create } from "zustand";
|
|
166
176
|
|
|
@@ -994,6 +1004,580 @@ var borderRadius = {
|
|
|
994
1004
|
xl: 20,
|
|
995
1005
|
full: 9999
|
|
996
1006
|
};
|
|
1007
|
+
|
|
1008
|
+
// src/acs/providers.ts
|
|
1009
|
+
var _reachability = null;
|
|
1010
|
+
function setAcsReachabilityReporter(r) {
|
|
1011
|
+
_reachability = r;
|
|
1012
|
+
}
|
|
1013
|
+
function reportAcsServerUp() {
|
|
1014
|
+
try {
|
|
1015
|
+
_reachability?.up();
|
|
1016
|
+
} catch {
|
|
1017
|
+
}
|
|
1018
|
+
}
|
|
1019
|
+
function reportAcsServerDown() {
|
|
1020
|
+
try {
|
|
1021
|
+
_reachability?.down();
|
|
1022
|
+
} catch {
|
|
1023
|
+
}
|
|
1024
|
+
}
|
|
1025
|
+
var _kv = null;
|
|
1026
|
+
function setAcsCacheStorage(kv) {
|
|
1027
|
+
_kv = kv;
|
|
1028
|
+
}
|
|
1029
|
+
function getAcsCacheStorage() {
|
|
1030
|
+
return _kv;
|
|
1031
|
+
}
|
|
1032
|
+
|
|
1033
|
+
// src/acs/api.ts
|
|
1034
|
+
async function authedFetch(path, init) {
|
|
1035
|
+
const token = getToken();
|
|
1036
|
+
try {
|
|
1037
|
+
const res = await fetch(`${getCoreApiUrl()}${path}`, {
|
|
1038
|
+
...init,
|
|
1039
|
+
headers: {
|
|
1040
|
+
"Content-Type": "application/json",
|
|
1041
|
+
...token ? { Authorization: `Bearer ${token}` } : {},
|
|
1042
|
+
...init?.headers || {}
|
|
1043
|
+
}
|
|
1044
|
+
});
|
|
1045
|
+
reportAcsServerUp();
|
|
1046
|
+
return res;
|
|
1047
|
+
} catch (e) {
|
|
1048
|
+
reportAcsServerDown();
|
|
1049
|
+
throw e;
|
|
1050
|
+
}
|
|
1051
|
+
}
|
|
1052
|
+
async function listSurface(surface, context) {
|
|
1053
|
+
try {
|
|
1054
|
+
const res = await authedFetch("/api/acs/surface", {
|
|
1055
|
+
method: "POST",
|
|
1056
|
+
body: JSON.stringify({ surface, ...context ? { context } : {} })
|
|
1057
|
+
});
|
|
1058
|
+
if (!res.ok) {
|
|
1059
|
+
console.warn(`[acs] /surface ${surface} returned ${res.status}`);
|
|
1060
|
+
return [];
|
|
1061
|
+
}
|
|
1062
|
+
const data = await res.json();
|
|
1063
|
+
return Array.isArray(data?.items) ? data.items : [];
|
|
1064
|
+
} catch (e) {
|
|
1065
|
+
console.warn("[acs] /surface failed:", e?.message || e);
|
|
1066
|
+
return [];
|
|
1067
|
+
}
|
|
1068
|
+
}
|
|
1069
|
+
async function listMadeForYou() {
|
|
1070
|
+
try {
|
|
1071
|
+
const res = await authedFetch("/api/acs/made-for-you", { method: "GET" });
|
|
1072
|
+
if (!res.ok) {
|
|
1073
|
+
console.warn(`[acs] /made-for-you returned ${res.status}`);
|
|
1074
|
+
return [];
|
|
1075
|
+
}
|
|
1076
|
+
const data = await res.json();
|
|
1077
|
+
return Array.isArray(data?.artifacts) ? data.artifacts : [];
|
|
1078
|
+
} catch (e) {
|
|
1079
|
+
console.warn("[acs] /made-for-you failed:", e?.message || e);
|
|
1080
|
+
return [];
|
|
1081
|
+
}
|
|
1082
|
+
}
|
|
1083
|
+
async function deleteArtifact(artifactId, reason = "user_long_press_delete") {
|
|
1084
|
+
try {
|
|
1085
|
+
const res = await authedFetch(
|
|
1086
|
+
`/api/acs/artifacts/${encodeURIComponent(artifactId)}`,
|
|
1087
|
+
{ method: "DELETE", body: JSON.stringify({ reason }) }
|
|
1088
|
+
);
|
|
1089
|
+
const data = await res.json().catch(() => ({}));
|
|
1090
|
+
if (res.ok) {
|
|
1091
|
+
return { ok: true, already: !!data?.already, status: res.status };
|
|
1092
|
+
}
|
|
1093
|
+
if (res.status === 404) {
|
|
1094
|
+
return { ok: true, notFound: true, status: 404 };
|
|
1095
|
+
}
|
|
1096
|
+
return { ok: false, status: res.status, error: data?.error || `HTTP ${res.status}` };
|
|
1097
|
+
} catch (e) {
|
|
1098
|
+
return { ok: false, status: 0, error: e?.message || "network error" };
|
|
1099
|
+
}
|
|
1100
|
+
}
|
|
1101
|
+
async function patchArtifact(artifactId, body, reason) {
|
|
1102
|
+
try {
|
|
1103
|
+
const res = await authedFetch(
|
|
1104
|
+
`/api/acs/artifacts/${encodeURIComponent(artifactId)}`,
|
|
1105
|
+
{ method: "PATCH", body: JSON.stringify({ ...body, reason }) }
|
|
1106
|
+
);
|
|
1107
|
+
const data = await res.json().catch(() => ({}));
|
|
1108
|
+
if (res.ok) {
|
|
1109
|
+
return {
|
|
1110
|
+
ok: true,
|
|
1111
|
+
already: !!data?.already,
|
|
1112
|
+
artifact: data?.artifact || void 0,
|
|
1113
|
+
status: res.status
|
|
1114
|
+
};
|
|
1115
|
+
}
|
|
1116
|
+
if (res.status === 404) {
|
|
1117
|
+
return { ok: true, notFound: true, status: 404 };
|
|
1118
|
+
}
|
|
1119
|
+
return {
|
|
1120
|
+
ok: false,
|
|
1121
|
+
status: res.status,
|
|
1122
|
+
error: data?.error || `HTTP ${res.status}`
|
|
1123
|
+
};
|
|
1124
|
+
} catch (e) {
|
|
1125
|
+
return { ok: false, status: 0, error: e?.message || "network error" };
|
|
1126
|
+
}
|
|
1127
|
+
}
|
|
1128
|
+
async function setOrder(pinned) {
|
|
1129
|
+
try {
|
|
1130
|
+
const res = await authedFetch("/api/acs/order", {
|
|
1131
|
+
method: "PUT",
|
|
1132
|
+
body: JSON.stringify({ pinned })
|
|
1133
|
+
});
|
|
1134
|
+
if (res.ok) return { ok: true, status: res.status };
|
|
1135
|
+
const data = await res.json().catch(() => ({}));
|
|
1136
|
+
return { ok: false, status: res.status, error: data?.error || `HTTP ${res.status}` };
|
|
1137
|
+
} catch (e) {
|
|
1138
|
+
return { ok: false, status: 0, error: e?.message || "network error" };
|
|
1139
|
+
}
|
|
1140
|
+
}
|
|
1141
|
+
async function recordEvent(artifactId, event, surface) {
|
|
1142
|
+
try {
|
|
1143
|
+
await authedFetch("/api/acs/event", {
|
|
1144
|
+
method: "POST",
|
|
1145
|
+
body: JSON.stringify({ artifactId, event, ...surface ? { surface } : {} })
|
|
1146
|
+
});
|
|
1147
|
+
} catch {
|
|
1148
|
+
}
|
|
1149
|
+
}
|
|
1150
|
+
async function listHomeActions() {
|
|
1151
|
+
try {
|
|
1152
|
+
const res = await authedFetch("/api/acs/home-actions", { method: "GET" });
|
|
1153
|
+
if (!res.ok) {
|
|
1154
|
+
console.warn(`[acs] /home-actions returned ${res.status}`);
|
|
1155
|
+
return [];
|
|
1156
|
+
}
|
|
1157
|
+
const data = await res.json();
|
|
1158
|
+
return Array.isArray(data?.actions) ? data.actions : [];
|
|
1159
|
+
} catch (e) {
|
|
1160
|
+
console.warn("[acs] /home-actions failed:", e?.message || e);
|
|
1161
|
+
return [];
|
|
1162
|
+
}
|
|
1163
|
+
}
|
|
1164
|
+
async function patchHomeAction(actionId, body, reason) {
|
|
1165
|
+
try {
|
|
1166
|
+
const res = await authedFetch(
|
|
1167
|
+
`/api/acs/home-actions/${encodeURIComponent(actionId)}`,
|
|
1168
|
+
{ method: "PATCH", body: JSON.stringify({ ...body, reason }) }
|
|
1169
|
+
);
|
|
1170
|
+
const data = await res.json().catch(() => ({}));
|
|
1171
|
+
if (res.ok) return { ok: true, action: data?.action || void 0, status: res.status };
|
|
1172
|
+
if (res.status === 404) return { ok: true, status: 404 };
|
|
1173
|
+
return { ok: false, status: res.status, error: data?.error || `HTTP ${res.status}` };
|
|
1174
|
+
} catch (e) {
|
|
1175
|
+
return { ok: false, status: 0, error: e?.message || "network error" };
|
|
1176
|
+
}
|
|
1177
|
+
}
|
|
1178
|
+
async function setHomeActionOrder(order) {
|
|
1179
|
+
try {
|
|
1180
|
+
const res = await authedFetch("/api/acs/home-actions/order", {
|
|
1181
|
+
method: "PUT",
|
|
1182
|
+
body: JSON.stringify({ order })
|
|
1183
|
+
});
|
|
1184
|
+
if (res.ok) return { ok: true, status: res.status };
|
|
1185
|
+
const data = await res.json().catch(() => ({}));
|
|
1186
|
+
return { ok: false, status: res.status, error: data?.error || `HTTP ${res.status}` };
|
|
1187
|
+
} catch (e) {
|
|
1188
|
+
return { ok: false, status: 0, error: e?.message || "network error" };
|
|
1189
|
+
}
|
|
1190
|
+
}
|
|
1191
|
+
|
|
1192
|
+
// src/acs/widgetsStore.ts
|
|
1193
|
+
import { create as create2 } from "zustand";
|
|
1194
|
+
var useWidgetsStore = create2((set, get) => ({
|
|
1195
|
+
tiles: [],
|
|
1196
|
+
hydrated: false,
|
|
1197
|
+
loading: false,
|
|
1198
|
+
error: null,
|
|
1199
|
+
hydrate: async () => {
|
|
1200
|
+
if (get().hydrated || get().loading) return;
|
|
1201
|
+
await get().refresh();
|
|
1202
|
+
},
|
|
1203
|
+
refresh: async () => {
|
|
1204
|
+
if (get().loading) return;
|
|
1205
|
+
set({ loading: true, error: null });
|
|
1206
|
+
try {
|
|
1207
|
+
const tiles = await listSurface("home");
|
|
1208
|
+
set({ tiles, loading: false, hydrated: true });
|
|
1209
|
+
} catch (e) {
|
|
1210
|
+
set({ loading: false, hydrated: true, error: e?.message || "Failed to load widgets" });
|
|
1211
|
+
}
|
|
1212
|
+
},
|
|
1213
|
+
clear: () => set({ tiles: [], hydrated: false, loading: false, error: null }),
|
|
1214
|
+
remove: async (artifactId, reason = "user_long_press_delete") => {
|
|
1215
|
+
const before = get().tiles;
|
|
1216
|
+
set({ tiles: before.filter((t) => t.id !== artifactId) });
|
|
1217
|
+
const result = await deleteArtifact(artifactId, reason);
|
|
1218
|
+
if (result.ok) {
|
|
1219
|
+
return { ok: true };
|
|
1220
|
+
}
|
|
1221
|
+
set({ tiles: before });
|
|
1222
|
+
return { ok: false, error: result.error || `HTTP ${result.status}` };
|
|
1223
|
+
},
|
|
1224
|
+
hide: async (artifactId) => {
|
|
1225
|
+
const before = get().tiles;
|
|
1226
|
+
set({
|
|
1227
|
+
tiles: before.map(
|
|
1228
|
+
(t) => t.id === artifactId ? { ...t, visibility: "hidden" } : t
|
|
1229
|
+
)
|
|
1230
|
+
});
|
|
1231
|
+
const r = await patchArtifact(artifactId, { visibility: "hidden" }, "user_long_press_hide");
|
|
1232
|
+
if (r.ok) {
|
|
1233
|
+
if (r.artifact) {
|
|
1234
|
+
set({
|
|
1235
|
+
tiles: get().tiles.map((t) => t.id === artifactId ? { ...t, ...r.artifact } : t)
|
|
1236
|
+
});
|
|
1237
|
+
}
|
|
1238
|
+
return { ok: true };
|
|
1239
|
+
}
|
|
1240
|
+
set({ tiles: before });
|
|
1241
|
+
return { ok: false, error: r.error || `HTTP ${r.status}` };
|
|
1242
|
+
},
|
|
1243
|
+
unhide: async (artifactId) => {
|
|
1244
|
+
const before = get().tiles;
|
|
1245
|
+
set({
|
|
1246
|
+
tiles: before.map(
|
|
1247
|
+
(t) => t.id === artifactId ? { ...t, visibility: "pinned" } : t
|
|
1248
|
+
)
|
|
1249
|
+
});
|
|
1250
|
+
const r = await patchArtifact(artifactId, { visibility: "pinned" }, "user_long_press_unhide");
|
|
1251
|
+
if (r.ok) {
|
|
1252
|
+
if (r.artifact) {
|
|
1253
|
+
set({
|
|
1254
|
+
tiles: get().tiles.map((t) => t.id === artifactId ? { ...t, ...r.artifact } : t)
|
|
1255
|
+
});
|
|
1256
|
+
}
|
|
1257
|
+
return { ok: true };
|
|
1258
|
+
}
|
|
1259
|
+
set({ tiles: before });
|
|
1260
|
+
return { ok: false, error: r.error || `HTTP ${r.status}` };
|
|
1261
|
+
},
|
|
1262
|
+
rename: async (artifactId, name) => {
|
|
1263
|
+
const trimmed = name.trim();
|
|
1264
|
+
if (!trimmed) return { ok: false, error: "Name cannot be empty" };
|
|
1265
|
+
if (trimmed.length > 60) return { ok: false, error: "Name must be 60 characters or less" };
|
|
1266
|
+
const before = get().tiles;
|
|
1267
|
+
set({
|
|
1268
|
+
tiles: before.map((t) => t.id === artifactId ? { ...t, name: trimmed } : t)
|
|
1269
|
+
});
|
|
1270
|
+
const r = await patchArtifact(artifactId, { name: trimmed }, "user_long_press_rename");
|
|
1271
|
+
if (r.ok) {
|
|
1272
|
+
if (r.artifact) {
|
|
1273
|
+
set({
|
|
1274
|
+
tiles: get().tiles.map((t) => t.id === artifactId ? { ...t, ...r.artifact } : t)
|
|
1275
|
+
});
|
|
1276
|
+
}
|
|
1277
|
+
return { ok: true };
|
|
1278
|
+
}
|
|
1279
|
+
set({ tiles: before });
|
|
1280
|
+
return { ok: false, error: r.error || `HTTP ${r.status}` };
|
|
1281
|
+
},
|
|
1282
|
+
reorder: async (pinnedIds) => {
|
|
1283
|
+
const before = get().tiles;
|
|
1284
|
+
const idToOrder = new Map(pinnedIds.map((id, i) => [id, i]));
|
|
1285
|
+
set({
|
|
1286
|
+
tiles: before.map((t) => {
|
|
1287
|
+
const o = idToOrder.get(t.id);
|
|
1288
|
+
return o == null ? t : { ...t, pinOrder: o };
|
|
1289
|
+
})
|
|
1290
|
+
});
|
|
1291
|
+
const r = await setOrder(pinnedIds);
|
|
1292
|
+
if (r.ok) return { ok: true };
|
|
1293
|
+
set({ tiles: before });
|
|
1294
|
+
return { ok: false, error: r.error || `HTTP ${r.status}` };
|
|
1295
|
+
},
|
|
1296
|
+
applyServerUpdate: (artifact) => {
|
|
1297
|
+
set({
|
|
1298
|
+
tiles: get().tiles.map((t) => t.id === artifact.id ? { ...t, ...artifact } : t)
|
|
1299
|
+
});
|
|
1300
|
+
},
|
|
1301
|
+
applyServerRetire: (artifactId) => {
|
|
1302
|
+
set({ tiles: get().tiles.filter((t) => t.id !== artifactId) });
|
|
1303
|
+
},
|
|
1304
|
+
applyServerOrder: (pinnedIds) => {
|
|
1305
|
+
const idToOrder = new Map(pinnedIds.map((id, i) => [id, i]));
|
|
1306
|
+
set({
|
|
1307
|
+
tiles: get().tiles.map((t) => {
|
|
1308
|
+
const o = idToOrder.get(t.id);
|
|
1309
|
+
return o == null ? t : { ...t, pinOrder: o };
|
|
1310
|
+
})
|
|
1311
|
+
});
|
|
1312
|
+
},
|
|
1313
|
+
track: (artifactId, event) => {
|
|
1314
|
+
recordEvent(artifactId, event, "home");
|
|
1315
|
+
}
|
|
1316
|
+
}));
|
|
1317
|
+
|
|
1318
|
+
// src/acs/homeActionsStore.ts
|
|
1319
|
+
import { create as create3 } from "zustand";
|
|
1320
|
+
var CACHE_KEY = "ateam.homeActions.v1";
|
|
1321
|
+
function persist(actions) {
|
|
1322
|
+
getAcsCacheStorage()?.setItem(CACHE_KEY, JSON.stringify(actions)).catch(() => {
|
|
1323
|
+
});
|
|
1324
|
+
}
|
|
1325
|
+
function sortByPin(a, b) {
|
|
1326
|
+
if (!!a.pinned !== !!b.pinned) return a.pinned ? -1 : 1;
|
|
1327
|
+
const ao = typeof a.pinOrder === "number" ? a.pinOrder : Number.MAX_SAFE_INTEGER;
|
|
1328
|
+
const bo = typeof b.pinOrder === "number" ? b.pinOrder : Number.MAX_SAFE_INTEGER;
|
|
1329
|
+
return ao - bo;
|
|
1330
|
+
}
|
|
1331
|
+
var useHomeActionsStore = create3((set, get) => ({
|
|
1332
|
+
actions: [],
|
|
1333
|
+
hydrated: false,
|
|
1334
|
+
loading: false,
|
|
1335
|
+
hydrate: async () => {
|
|
1336
|
+
if (get().hydrated || get().loading) return;
|
|
1337
|
+
try {
|
|
1338
|
+
const cached = await getAcsCacheStorage()?.getItem(CACHE_KEY);
|
|
1339
|
+
if (cached) {
|
|
1340
|
+
const parsed = JSON.parse(cached);
|
|
1341
|
+
if (Array.isArray(parsed) && parsed.length > 0) {
|
|
1342
|
+
set({ actions: parsed, hydrated: true });
|
|
1343
|
+
}
|
|
1344
|
+
}
|
|
1345
|
+
} catch {
|
|
1346
|
+
}
|
|
1347
|
+
await get().refresh();
|
|
1348
|
+
},
|
|
1349
|
+
refresh: async () => {
|
|
1350
|
+
if (get().loading) return;
|
|
1351
|
+
set({ loading: true });
|
|
1352
|
+
const actions = await listHomeActions();
|
|
1353
|
+
if (actions.length > 0) {
|
|
1354
|
+
set({ actions, loading: false, hydrated: true });
|
|
1355
|
+
persist(actions);
|
|
1356
|
+
} else {
|
|
1357
|
+
set({ loading: false, hydrated: true });
|
|
1358
|
+
}
|
|
1359
|
+
},
|
|
1360
|
+
// clear() wipes in-memory state on sign-out AND drops the disk cache — a
|
|
1361
|
+
// different user must not see the prior user's cards.
|
|
1362
|
+
clear: () => {
|
|
1363
|
+
set({ actions: [], hydrated: false, loading: false });
|
|
1364
|
+
getAcsCacheStorage()?.setItem(CACHE_KEY, "[]").catch(() => {
|
|
1365
|
+
});
|
|
1366
|
+
},
|
|
1367
|
+
dismiss: async (actionId) => {
|
|
1368
|
+
const before = get().actions;
|
|
1369
|
+
const next = before.filter((a) => a.actionId !== actionId);
|
|
1370
|
+
set({ actions: next });
|
|
1371
|
+
persist(next);
|
|
1372
|
+
const r = await patchHomeAction(actionId, { dismissed: true }, "user_dismiss");
|
|
1373
|
+
if (r.ok) return { ok: true };
|
|
1374
|
+
set({ actions: before });
|
|
1375
|
+
persist(before);
|
|
1376
|
+
return { ok: false, error: r.error || `HTTP ${r.status}` };
|
|
1377
|
+
},
|
|
1378
|
+
setPinned: async (actionId, pinned) => {
|
|
1379
|
+
const before = get().actions;
|
|
1380
|
+
const next = before.map((a) => a.actionId === actionId ? { ...a, pinned } : a).sort(sortByPin);
|
|
1381
|
+
set({ actions: next });
|
|
1382
|
+
persist(next);
|
|
1383
|
+
const r = await patchHomeAction(actionId, { pinned }, pinned ? "user_pin" : "user_unpin");
|
|
1384
|
+
if (r.ok) {
|
|
1385
|
+
if (r.action) {
|
|
1386
|
+
const merged = get().actions.map((a) => a.actionId === actionId ? { ...a, ...r.action } : a).sort(sortByPin);
|
|
1387
|
+
set({ actions: merged });
|
|
1388
|
+
persist(merged);
|
|
1389
|
+
}
|
|
1390
|
+
return { ok: true };
|
|
1391
|
+
}
|
|
1392
|
+
set({ actions: before });
|
|
1393
|
+
persist(before);
|
|
1394
|
+
return { ok: false, error: r.error || `HTTP ${r.status}` };
|
|
1395
|
+
},
|
|
1396
|
+
reorder: async (orderedIds) => {
|
|
1397
|
+
const before = get().actions;
|
|
1398
|
+
const idx = new Map(orderedIds.map((id, i) => [id, i]));
|
|
1399
|
+
const next = before.map((a) => {
|
|
1400
|
+
const o = idx.get(a.actionId);
|
|
1401
|
+
return o == null ? a : { ...a, pinOrder: o };
|
|
1402
|
+
}).sort(sortByPin);
|
|
1403
|
+
set({ actions: next });
|
|
1404
|
+
persist(next);
|
|
1405
|
+
const r = await setHomeActionOrder(orderedIds);
|
|
1406
|
+
if (r.ok) return { ok: true };
|
|
1407
|
+
set({ actions: before });
|
|
1408
|
+
persist(before);
|
|
1409
|
+
return { ok: false, error: r.error || `HTTP ${r.status}` };
|
|
1410
|
+
},
|
|
1411
|
+
applyServerUpsert: (action) => {
|
|
1412
|
+
const rest = get().actions.filter((a) => a.actionId !== action.actionId);
|
|
1413
|
+
const next = [...rest, action].sort(sortByPin);
|
|
1414
|
+
set({ actions: next });
|
|
1415
|
+
persist(next);
|
|
1416
|
+
},
|
|
1417
|
+
applyServerRemove: (actionId) => {
|
|
1418
|
+
const next = get().actions.filter((a) => a.actionId !== actionId);
|
|
1419
|
+
set({ actions: next });
|
|
1420
|
+
persist(next);
|
|
1421
|
+
},
|
|
1422
|
+
applyServerOrder: (orderedIds) => {
|
|
1423
|
+
const idx = new Map(orderedIds.map((id, i) => [id, i]));
|
|
1424
|
+
const next = get().actions.map((a) => {
|
|
1425
|
+
const o = idx.get(a.actionId);
|
|
1426
|
+
return o == null ? a : { ...a, pinOrder: o };
|
|
1427
|
+
}).sort(sortByPin);
|
|
1428
|
+
set({ actions: next });
|
|
1429
|
+
persist(next);
|
|
1430
|
+
}
|
|
1431
|
+
}));
|
|
1432
|
+
|
|
1433
|
+
// src/acs/ws.ts
|
|
1434
|
+
var _ws2 = null;
|
|
1435
|
+
var _wantOpen = false;
|
|
1436
|
+
var _retryAttempt = 0;
|
|
1437
|
+
var _retryTimer = null;
|
|
1438
|
+
var _token = null;
|
|
1439
|
+
var _tenant = null;
|
|
1440
|
+
var TOPIC = "acs.artifacts";
|
|
1441
|
+
var TOPIC_HOME = "acs.home-actions";
|
|
1442
|
+
var MAX_BACKOFF_MS = 3e4;
|
|
1443
|
+
function backoffMs(attempt) {
|
|
1444
|
+
const base = Math.min(MAX_BACKOFF_MS, 500 * Math.pow(2, attempt));
|
|
1445
|
+
const jitter = Math.random() * 250;
|
|
1446
|
+
return base + jitter;
|
|
1447
|
+
}
|
|
1448
|
+
function send(obj) {
|
|
1449
|
+
if (_ws2 && _ws2.readyState === 1) {
|
|
1450
|
+
try {
|
|
1451
|
+
_ws2.send(JSON.stringify(obj));
|
|
1452
|
+
} catch (e) {
|
|
1453
|
+
console.warn("[acsWs] send failed", e);
|
|
1454
|
+
}
|
|
1455
|
+
}
|
|
1456
|
+
}
|
|
1457
|
+
function handleEvent(msg) {
|
|
1458
|
+
if (msg?.event === "subscribed") {
|
|
1459
|
+
console.log("[acsWs] subscribed to", msg?.data?.topic);
|
|
1460
|
+
return;
|
|
1461
|
+
}
|
|
1462
|
+
if (msg?.topic === TOPIC_HOME) {
|
|
1463
|
+
const home = useHomeActionsStore.getState();
|
|
1464
|
+
switch (msg.event) {
|
|
1465
|
+
case "updated":
|
|
1466
|
+
if (msg.action && typeof msg.action.actionId === "string") home.applyServerUpsert(msg.action);
|
|
1467
|
+
break;
|
|
1468
|
+
case "removed":
|
|
1469
|
+
if (typeof msg.actionId === "string") home.applyServerRemove(msg.actionId);
|
|
1470
|
+
break;
|
|
1471
|
+
case "order":
|
|
1472
|
+
if (Array.isArray(msg.order)) home.applyServerOrder(msg.order.filter((id) => typeof id === "string"));
|
|
1473
|
+
break;
|
|
1474
|
+
case "refreshed":
|
|
1475
|
+
home.refresh();
|
|
1476
|
+
break;
|
|
1477
|
+
default:
|
|
1478
|
+
break;
|
|
1479
|
+
}
|
|
1480
|
+
return;
|
|
1481
|
+
}
|
|
1482
|
+
if (msg?.topic !== TOPIC) return;
|
|
1483
|
+
const store = useWidgetsStore.getState();
|
|
1484
|
+
switch (msg.event) {
|
|
1485
|
+
case "updated":
|
|
1486
|
+
if (msg.artifact && typeof msg.artifact.id === "string") {
|
|
1487
|
+
store.applyServerUpdate(msg.artifact);
|
|
1488
|
+
}
|
|
1489
|
+
break;
|
|
1490
|
+
case "retired":
|
|
1491
|
+
if (typeof msg.artifactId === "string") {
|
|
1492
|
+
store.applyServerRetire(msg.artifactId);
|
|
1493
|
+
}
|
|
1494
|
+
break;
|
|
1495
|
+
case "order":
|
|
1496
|
+
if (Array.isArray(msg.pinned)) {
|
|
1497
|
+
store.applyServerOrder(msg.pinned.filter((id) => typeof id === "string"));
|
|
1498
|
+
}
|
|
1499
|
+
break;
|
|
1500
|
+
case "created":
|
|
1501
|
+
if (msg.artifact && typeof msg.artifact.id === "string") {
|
|
1502
|
+
store.applyServerUpdate(msg.artifact);
|
|
1503
|
+
}
|
|
1504
|
+
break;
|
|
1505
|
+
default:
|
|
1506
|
+
break;
|
|
1507
|
+
}
|
|
1508
|
+
}
|
|
1509
|
+
function openSocket() {
|
|
1510
|
+
if (_ws2) return;
|
|
1511
|
+
if (!_token || !_tenant) return;
|
|
1512
|
+
const url = `${getCoreWsUrl()}/ws?token=${encodeURIComponent(_token)}&tenant=${encodeURIComponent(_tenant)}`;
|
|
1513
|
+
console.log(`[acsWs] opening`);
|
|
1514
|
+
const ws = new WebSocket(url);
|
|
1515
|
+
_ws2 = ws;
|
|
1516
|
+
ws.onopen = () => {
|
|
1517
|
+
_retryAttempt = 0;
|
|
1518
|
+
send({ type: "subscribe", topic: TOPIC });
|
|
1519
|
+
send({ type: "subscribe", topic: TOPIC_HOME });
|
|
1520
|
+
};
|
|
1521
|
+
ws.onmessage = (e) => {
|
|
1522
|
+
try {
|
|
1523
|
+
const msg = JSON.parse(typeof e.data === "string" ? e.data : "");
|
|
1524
|
+
handleEvent(msg);
|
|
1525
|
+
} catch (err) {
|
|
1526
|
+
console.warn("[acsWs] parse failed", err);
|
|
1527
|
+
}
|
|
1528
|
+
};
|
|
1529
|
+
ws.onerror = (e) => {
|
|
1530
|
+
console.warn("[acsWs] error", e?.message || e);
|
|
1531
|
+
};
|
|
1532
|
+
ws.onclose = () => {
|
|
1533
|
+
_ws2 = null;
|
|
1534
|
+
if (!_wantOpen) return;
|
|
1535
|
+
const delay = backoffMs(_retryAttempt++);
|
|
1536
|
+
console.log(`[acsWs] closed; reconnecting in ${Math.round(delay)}ms (attempt ${_retryAttempt})`);
|
|
1537
|
+
if (_retryTimer) clearTimeout(_retryTimer);
|
|
1538
|
+
_retryTimer = setTimeout(openSocket, delay);
|
|
1539
|
+
};
|
|
1540
|
+
}
|
|
1541
|
+
function notifyAcsWsForeground() {
|
|
1542
|
+
if (_wantOpen && !_ws2) {
|
|
1543
|
+
if (_retryTimer) {
|
|
1544
|
+
clearTimeout(_retryTimer);
|
|
1545
|
+
_retryTimer = null;
|
|
1546
|
+
}
|
|
1547
|
+
_retryAttempt = 0;
|
|
1548
|
+
openSocket();
|
|
1549
|
+
}
|
|
1550
|
+
}
|
|
1551
|
+
function connectAcsWs(token, tenant) {
|
|
1552
|
+
if (_ws2 && _wantOpen && _token === token && _tenant === tenant) return;
|
|
1553
|
+
if (_ws2) {
|
|
1554
|
+
try {
|
|
1555
|
+
_ws2.close();
|
|
1556
|
+
} catch {
|
|
1557
|
+
}
|
|
1558
|
+
_ws2 = null;
|
|
1559
|
+
}
|
|
1560
|
+
_token = token;
|
|
1561
|
+
_tenant = tenant;
|
|
1562
|
+
_wantOpen = true;
|
|
1563
|
+
openSocket();
|
|
1564
|
+
}
|
|
1565
|
+
function disconnectAcsWs() {
|
|
1566
|
+
_wantOpen = false;
|
|
1567
|
+
_token = null;
|
|
1568
|
+
_tenant = null;
|
|
1569
|
+
if (_retryTimer) {
|
|
1570
|
+
clearTimeout(_retryTimer);
|
|
1571
|
+
_retryTimer = null;
|
|
1572
|
+
}
|
|
1573
|
+
if (_ws2) {
|
|
1574
|
+
try {
|
|
1575
|
+
_ws2.close();
|
|
1576
|
+
} catch {
|
|
1577
|
+
}
|
|
1578
|
+
_ws2 = null;
|
|
1579
|
+
}
|
|
1580
|
+
}
|
|
997
1581
|
export {
|
|
998
1582
|
PluginCommandEmitter,
|
|
999
1583
|
TABLE_BLOCK_CLOSE,
|
|
@@ -1005,7 +1589,10 @@ export {
|
|
|
1005
1589
|
borderRadius,
|
|
1006
1590
|
closeChatStream,
|
|
1007
1591
|
colors,
|
|
1592
|
+
connectAcsWs,
|
|
1008
1593
|
connectorCall,
|
|
1594
|
+
deleteArtifact,
|
|
1595
|
+
disconnectAcsWs,
|
|
1009
1596
|
fontSize,
|
|
1010
1597
|
getConfig,
|
|
1011
1598
|
getCoreApiUrl,
|
|
@@ -1016,12 +1603,26 @@ export {
|
|
|
1016
1603
|
getVoiceApiUrl,
|
|
1017
1604
|
initAdas,
|
|
1018
1605
|
isAdasInitialized,
|
|
1606
|
+
listHomeActions,
|
|
1607
|
+
listMadeForYou,
|
|
1608
|
+
listMyTenants,
|
|
1609
|
+
listSurface,
|
|
1019
1610
|
mcpFetch,
|
|
1020
1611
|
mcpToolCall,
|
|
1612
|
+
notifyAcsWsForeground,
|
|
1613
|
+
patchArtifact,
|
|
1614
|
+
patchHomeAction,
|
|
1021
1615
|
pluginCommandEmitter,
|
|
1022
1616
|
postCommandResult,
|
|
1617
|
+
recordEvent,
|
|
1618
|
+
setAcsCacheStorage,
|
|
1619
|
+
setAcsReachabilityReporter,
|
|
1620
|
+
setHomeActionOrder,
|
|
1621
|
+
setOrder,
|
|
1023
1622
|
spacing,
|
|
1024
1623
|
unwrapMcpResult,
|
|
1025
|
-
useChatStore
|
|
1624
|
+
useChatStore,
|
|
1625
|
+
useHomeActionsStore,
|
|
1626
|
+
useWidgetsStore
|
|
1026
1627
|
};
|
|
1027
1628
|
//# sourceMappingURL=index.mjs.map
|