@ateam-ai-mobile/core 0.1.0 → 0.1.2
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 +375 -7
- package/dist/index.d.ts +375 -7
- package/dist/index.js +661 -5
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +641 -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 +75 -0
- package/src/config.ts +47 -9
- package/src/index.ts +39 -1
package/dist/index.js
CHANGED
|
@@ -30,9 +30,13 @@ __export(index_exports, {
|
|
|
30
30
|
borderRadius: () => borderRadius,
|
|
31
31
|
closeChatStream: () => closeChatStream,
|
|
32
32
|
colors: () => colors,
|
|
33
|
+
connectAcsWs: () => connectAcsWs,
|
|
33
34
|
connectorCall: () => connectorCall,
|
|
35
|
+
deleteArtifact: () => deleteArtifact,
|
|
36
|
+
disconnectAcsWs: () => disconnectAcsWs,
|
|
34
37
|
fontSize: () => fontSize,
|
|
35
38
|
getConfig: () => getConfig,
|
|
39
|
+
getConsumerAuthApiUrl: () => getConsumerAuthApiUrl,
|
|
36
40
|
getCoreApiUrl: () => getCoreApiUrl,
|
|
37
41
|
getCoreWsUrl: () => getCoreWsUrl,
|
|
38
42
|
getTenant: () => getTenant,
|
|
@@ -41,13 +45,28 @@ __export(index_exports, {
|
|
|
41
45
|
getVoiceApiUrl: () => getVoiceApiUrl,
|
|
42
46
|
initAdas: () => initAdas,
|
|
43
47
|
isAdasInitialized: () => isAdasInitialized,
|
|
48
|
+
listHomeActions: () => listHomeActions,
|
|
49
|
+
listMadeForYou: () => listMadeForYou,
|
|
50
|
+
listMyTenants: () => listMyTenants,
|
|
51
|
+
listSurface: () => listSurface,
|
|
44
52
|
mcpFetch: () => mcpFetch,
|
|
45
53
|
mcpToolCall: () => mcpToolCall,
|
|
54
|
+
notifyAcsWsForeground: () => notifyAcsWsForeground,
|
|
55
|
+
patchArtifact: () => patchArtifact,
|
|
56
|
+
patchHomeAction: () => patchHomeAction,
|
|
46
57
|
pluginCommandEmitter: () => pluginCommandEmitter,
|
|
47
58
|
postCommandResult: () => postCommandResult,
|
|
59
|
+
recordEvent: () => recordEvent,
|
|
60
|
+
setAcsCacheStorage: () => setAcsCacheStorage,
|
|
61
|
+
setAcsReachabilityReporter: () => setAcsReachabilityReporter,
|
|
62
|
+
setHomeActionOrder: () => setHomeActionOrder,
|
|
63
|
+
setOrder: () => setOrder,
|
|
48
64
|
spacing: () => spacing,
|
|
65
|
+
switchTenant: () => switchTenant,
|
|
49
66
|
unwrapMcpResult: () => unwrapMcpResult,
|
|
50
|
-
useChatStore: () => useChatStore
|
|
67
|
+
useChatStore: () => useChatStore,
|
|
68
|
+
useHomeActionsStore: () => useHomeActionsStore,
|
|
69
|
+
useWidgetsStore: () => useWidgetsStore
|
|
51
70
|
});
|
|
52
71
|
module.exports = __toCommonJS(index_exports);
|
|
53
72
|
|
|
@@ -65,8 +84,11 @@ function getConfig() {
|
|
|
65
84
|
}
|
|
66
85
|
return _config;
|
|
67
86
|
}
|
|
87
|
+
function resolveUrl(src) {
|
|
88
|
+
return (typeof src === "function" ? src() : src).replace(/\/$/, "");
|
|
89
|
+
}
|
|
68
90
|
function getCoreApiUrl() {
|
|
69
|
-
return getConfig().coreUrl
|
|
91
|
+
return resolveUrl(getConfig().coreUrl);
|
|
70
92
|
}
|
|
71
93
|
function getCoreWsUrl() {
|
|
72
94
|
return getCoreApiUrl().replace(/^http/, "ws");
|
|
@@ -74,10 +96,16 @@ function getCoreWsUrl() {
|
|
|
74
96
|
function getVoiceApiUrl() {
|
|
75
97
|
const url = getConfig().voiceUrl;
|
|
76
98
|
if (!url) throw new Error("[adas] voiceUrl not configured");
|
|
77
|
-
return url
|
|
99
|
+
return resolveUrl(url);
|
|
100
|
+
}
|
|
101
|
+
function getConsumerAuthApiUrl() {
|
|
102
|
+
const url = getConfig().consumerAuthUrl;
|
|
103
|
+
if (!url) throw new Error("[adas] consumerAuthUrl not configured \u2014 required for switchTenant()");
|
|
104
|
+
return resolveUrl(url);
|
|
78
105
|
}
|
|
79
106
|
function getTenant() {
|
|
80
|
-
|
|
107
|
+
const t = getConfig().tenant;
|
|
108
|
+
return (typeof t === "function" ? t() : t) || "";
|
|
81
109
|
}
|
|
82
110
|
function getUser() {
|
|
83
111
|
return getConfig().getUser?.() || null;
|
|
@@ -948,6 +976,41 @@ async function pollJob(jobId, token) {
|
|
|
948
976
|
});
|
|
949
977
|
}
|
|
950
978
|
|
|
979
|
+
// src/api/tenants.ts
|
|
980
|
+
async function listMyTenants() {
|
|
981
|
+
const data = await apiFetch("/api/tenants/list");
|
|
982
|
+
return data.ok && Array.isArray(data.tenants) ? data.tenants : [];
|
|
983
|
+
}
|
|
984
|
+
async function switchTenant(targetTenantId) {
|
|
985
|
+
const token = getToken();
|
|
986
|
+
if (!token) throw new Error("[adas] switchTenant: not signed in");
|
|
987
|
+
const res = await fetch(`${getConsumerAuthApiUrl()}/platform/consumer/switch-tenant`, {
|
|
988
|
+
method: "POST",
|
|
989
|
+
headers: {
|
|
990
|
+
"Content-Type": "application/json",
|
|
991
|
+
Authorization: `Bearer ${token}`
|
|
992
|
+
},
|
|
993
|
+
body: JSON.stringify({ target_tenant: targetTenantId })
|
|
994
|
+
});
|
|
995
|
+
const data = await res.json().catch(() => null);
|
|
996
|
+
if (!res.ok || !data?.ok || !data.jwt) {
|
|
997
|
+
throw new Error(data?.error || `switchTenant failed (${res.status})`);
|
|
998
|
+
}
|
|
999
|
+
const session = {
|
|
1000
|
+
jwt: data.jwt,
|
|
1001
|
+
tenant: data.tenant,
|
|
1002
|
+
actor: data.actor
|
|
1003
|
+
};
|
|
1004
|
+
const onSession = getConfig().onSession;
|
|
1005
|
+
if (!onSession) {
|
|
1006
|
+
throw new Error("[adas] switchTenant: config.onSession is required to persist the new session");
|
|
1007
|
+
}
|
|
1008
|
+
await onSession(session);
|
|
1009
|
+
closeChatStream();
|
|
1010
|
+
useChatStore.getState().clearChat();
|
|
1011
|
+
return session;
|
|
1012
|
+
}
|
|
1013
|
+
|
|
951
1014
|
// src/theme/tokens.ts
|
|
952
1015
|
var colors = {
|
|
953
1016
|
dark: {
|
|
@@ -1047,6 +1110,580 @@ var borderRadius = {
|
|
|
1047
1110
|
xl: 20,
|
|
1048
1111
|
full: 9999
|
|
1049
1112
|
};
|
|
1113
|
+
|
|
1114
|
+
// src/acs/providers.ts
|
|
1115
|
+
var _reachability = null;
|
|
1116
|
+
function setAcsReachabilityReporter(r) {
|
|
1117
|
+
_reachability = r;
|
|
1118
|
+
}
|
|
1119
|
+
function reportAcsServerUp() {
|
|
1120
|
+
try {
|
|
1121
|
+
_reachability?.up();
|
|
1122
|
+
} catch {
|
|
1123
|
+
}
|
|
1124
|
+
}
|
|
1125
|
+
function reportAcsServerDown() {
|
|
1126
|
+
try {
|
|
1127
|
+
_reachability?.down();
|
|
1128
|
+
} catch {
|
|
1129
|
+
}
|
|
1130
|
+
}
|
|
1131
|
+
var _kv = null;
|
|
1132
|
+
function setAcsCacheStorage(kv) {
|
|
1133
|
+
_kv = kv;
|
|
1134
|
+
}
|
|
1135
|
+
function getAcsCacheStorage() {
|
|
1136
|
+
return _kv;
|
|
1137
|
+
}
|
|
1138
|
+
|
|
1139
|
+
// src/acs/api.ts
|
|
1140
|
+
async function authedFetch(path, init) {
|
|
1141
|
+
const token = getToken();
|
|
1142
|
+
try {
|
|
1143
|
+
const res = await fetch(`${getCoreApiUrl()}${path}`, {
|
|
1144
|
+
...init,
|
|
1145
|
+
headers: {
|
|
1146
|
+
"Content-Type": "application/json",
|
|
1147
|
+
...token ? { Authorization: `Bearer ${token}` } : {},
|
|
1148
|
+
...init?.headers || {}
|
|
1149
|
+
}
|
|
1150
|
+
});
|
|
1151
|
+
reportAcsServerUp();
|
|
1152
|
+
return res;
|
|
1153
|
+
} catch (e) {
|
|
1154
|
+
reportAcsServerDown();
|
|
1155
|
+
throw e;
|
|
1156
|
+
}
|
|
1157
|
+
}
|
|
1158
|
+
async function listSurface(surface, context) {
|
|
1159
|
+
try {
|
|
1160
|
+
const res = await authedFetch("/api/acs/surface", {
|
|
1161
|
+
method: "POST",
|
|
1162
|
+
body: JSON.stringify({ surface, ...context ? { context } : {} })
|
|
1163
|
+
});
|
|
1164
|
+
if (!res.ok) {
|
|
1165
|
+
console.warn(`[acs] /surface ${surface} returned ${res.status}`);
|
|
1166
|
+
return [];
|
|
1167
|
+
}
|
|
1168
|
+
const data = await res.json();
|
|
1169
|
+
return Array.isArray(data?.items) ? data.items : [];
|
|
1170
|
+
} catch (e) {
|
|
1171
|
+
console.warn("[acs] /surface failed:", e?.message || e);
|
|
1172
|
+
return [];
|
|
1173
|
+
}
|
|
1174
|
+
}
|
|
1175
|
+
async function listMadeForYou() {
|
|
1176
|
+
try {
|
|
1177
|
+
const res = await authedFetch("/api/acs/made-for-you", { method: "GET" });
|
|
1178
|
+
if (!res.ok) {
|
|
1179
|
+
console.warn(`[acs] /made-for-you returned ${res.status}`);
|
|
1180
|
+
return [];
|
|
1181
|
+
}
|
|
1182
|
+
const data = await res.json();
|
|
1183
|
+
return Array.isArray(data?.artifacts) ? data.artifacts : [];
|
|
1184
|
+
} catch (e) {
|
|
1185
|
+
console.warn("[acs] /made-for-you failed:", e?.message || e);
|
|
1186
|
+
return [];
|
|
1187
|
+
}
|
|
1188
|
+
}
|
|
1189
|
+
async function deleteArtifact(artifactId, reason = "user_long_press_delete") {
|
|
1190
|
+
try {
|
|
1191
|
+
const res = await authedFetch(
|
|
1192
|
+
`/api/acs/artifacts/${encodeURIComponent(artifactId)}`,
|
|
1193
|
+
{ method: "DELETE", body: JSON.stringify({ reason }) }
|
|
1194
|
+
);
|
|
1195
|
+
const data = await res.json().catch(() => ({}));
|
|
1196
|
+
if (res.ok) {
|
|
1197
|
+
return { ok: true, already: !!data?.already, status: res.status };
|
|
1198
|
+
}
|
|
1199
|
+
if (res.status === 404) {
|
|
1200
|
+
return { ok: true, notFound: true, status: 404 };
|
|
1201
|
+
}
|
|
1202
|
+
return { ok: false, status: res.status, error: data?.error || `HTTP ${res.status}` };
|
|
1203
|
+
} catch (e) {
|
|
1204
|
+
return { ok: false, status: 0, error: e?.message || "network error" };
|
|
1205
|
+
}
|
|
1206
|
+
}
|
|
1207
|
+
async function patchArtifact(artifactId, body, reason) {
|
|
1208
|
+
try {
|
|
1209
|
+
const res = await authedFetch(
|
|
1210
|
+
`/api/acs/artifacts/${encodeURIComponent(artifactId)}`,
|
|
1211
|
+
{ method: "PATCH", body: JSON.stringify({ ...body, reason }) }
|
|
1212
|
+
);
|
|
1213
|
+
const data = await res.json().catch(() => ({}));
|
|
1214
|
+
if (res.ok) {
|
|
1215
|
+
return {
|
|
1216
|
+
ok: true,
|
|
1217
|
+
already: !!data?.already,
|
|
1218
|
+
artifact: data?.artifact || void 0,
|
|
1219
|
+
status: res.status
|
|
1220
|
+
};
|
|
1221
|
+
}
|
|
1222
|
+
if (res.status === 404) {
|
|
1223
|
+
return { ok: true, notFound: true, status: 404 };
|
|
1224
|
+
}
|
|
1225
|
+
return {
|
|
1226
|
+
ok: false,
|
|
1227
|
+
status: res.status,
|
|
1228
|
+
error: data?.error || `HTTP ${res.status}`
|
|
1229
|
+
};
|
|
1230
|
+
} catch (e) {
|
|
1231
|
+
return { ok: false, status: 0, error: e?.message || "network error" };
|
|
1232
|
+
}
|
|
1233
|
+
}
|
|
1234
|
+
async function setOrder(pinned) {
|
|
1235
|
+
try {
|
|
1236
|
+
const res = await authedFetch("/api/acs/order", {
|
|
1237
|
+
method: "PUT",
|
|
1238
|
+
body: JSON.stringify({ pinned })
|
|
1239
|
+
});
|
|
1240
|
+
if (res.ok) return { ok: true, status: res.status };
|
|
1241
|
+
const data = await res.json().catch(() => ({}));
|
|
1242
|
+
return { ok: false, status: res.status, error: data?.error || `HTTP ${res.status}` };
|
|
1243
|
+
} catch (e) {
|
|
1244
|
+
return { ok: false, status: 0, error: e?.message || "network error" };
|
|
1245
|
+
}
|
|
1246
|
+
}
|
|
1247
|
+
async function recordEvent(artifactId, event, surface) {
|
|
1248
|
+
try {
|
|
1249
|
+
await authedFetch("/api/acs/event", {
|
|
1250
|
+
method: "POST",
|
|
1251
|
+
body: JSON.stringify({ artifactId, event, ...surface ? { surface } : {} })
|
|
1252
|
+
});
|
|
1253
|
+
} catch {
|
|
1254
|
+
}
|
|
1255
|
+
}
|
|
1256
|
+
async function listHomeActions() {
|
|
1257
|
+
try {
|
|
1258
|
+
const res = await authedFetch("/api/acs/home-actions", { method: "GET" });
|
|
1259
|
+
if (!res.ok) {
|
|
1260
|
+
console.warn(`[acs] /home-actions returned ${res.status}`);
|
|
1261
|
+
return [];
|
|
1262
|
+
}
|
|
1263
|
+
const data = await res.json();
|
|
1264
|
+
return Array.isArray(data?.actions) ? data.actions : [];
|
|
1265
|
+
} catch (e) {
|
|
1266
|
+
console.warn("[acs] /home-actions failed:", e?.message || e);
|
|
1267
|
+
return [];
|
|
1268
|
+
}
|
|
1269
|
+
}
|
|
1270
|
+
async function patchHomeAction(actionId, body, reason) {
|
|
1271
|
+
try {
|
|
1272
|
+
const res = await authedFetch(
|
|
1273
|
+
`/api/acs/home-actions/${encodeURIComponent(actionId)}`,
|
|
1274
|
+
{ method: "PATCH", body: JSON.stringify({ ...body, reason }) }
|
|
1275
|
+
);
|
|
1276
|
+
const data = await res.json().catch(() => ({}));
|
|
1277
|
+
if (res.ok) return { ok: true, action: data?.action || void 0, status: res.status };
|
|
1278
|
+
if (res.status === 404) return { ok: true, status: 404 };
|
|
1279
|
+
return { ok: false, status: res.status, error: data?.error || `HTTP ${res.status}` };
|
|
1280
|
+
} catch (e) {
|
|
1281
|
+
return { ok: false, status: 0, error: e?.message || "network error" };
|
|
1282
|
+
}
|
|
1283
|
+
}
|
|
1284
|
+
async function setHomeActionOrder(order) {
|
|
1285
|
+
try {
|
|
1286
|
+
const res = await authedFetch("/api/acs/home-actions/order", {
|
|
1287
|
+
method: "PUT",
|
|
1288
|
+
body: JSON.stringify({ order })
|
|
1289
|
+
});
|
|
1290
|
+
if (res.ok) return { ok: true, status: res.status };
|
|
1291
|
+
const data = await res.json().catch(() => ({}));
|
|
1292
|
+
return { ok: false, status: res.status, error: data?.error || `HTTP ${res.status}` };
|
|
1293
|
+
} catch (e) {
|
|
1294
|
+
return { ok: false, status: 0, error: e?.message || "network error" };
|
|
1295
|
+
}
|
|
1296
|
+
}
|
|
1297
|
+
|
|
1298
|
+
// src/acs/widgetsStore.ts
|
|
1299
|
+
var import_zustand2 = require("zustand");
|
|
1300
|
+
var useWidgetsStore = (0, import_zustand2.create)((set, get) => ({
|
|
1301
|
+
tiles: [],
|
|
1302
|
+
hydrated: false,
|
|
1303
|
+
loading: false,
|
|
1304
|
+
error: null,
|
|
1305
|
+
hydrate: async () => {
|
|
1306
|
+
if (get().hydrated || get().loading) return;
|
|
1307
|
+
await get().refresh();
|
|
1308
|
+
},
|
|
1309
|
+
refresh: async () => {
|
|
1310
|
+
if (get().loading) return;
|
|
1311
|
+
set({ loading: true, error: null });
|
|
1312
|
+
try {
|
|
1313
|
+
const tiles = await listSurface("home");
|
|
1314
|
+
set({ tiles, loading: false, hydrated: true });
|
|
1315
|
+
} catch (e) {
|
|
1316
|
+
set({ loading: false, hydrated: true, error: e?.message || "Failed to load widgets" });
|
|
1317
|
+
}
|
|
1318
|
+
},
|
|
1319
|
+
clear: () => set({ tiles: [], hydrated: false, loading: false, error: null }),
|
|
1320
|
+
remove: async (artifactId, reason = "user_long_press_delete") => {
|
|
1321
|
+
const before = get().tiles;
|
|
1322
|
+
set({ tiles: before.filter((t) => t.id !== artifactId) });
|
|
1323
|
+
const result = await deleteArtifact(artifactId, reason);
|
|
1324
|
+
if (result.ok) {
|
|
1325
|
+
return { ok: true };
|
|
1326
|
+
}
|
|
1327
|
+
set({ tiles: before });
|
|
1328
|
+
return { ok: false, error: result.error || `HTTP ${result.status}` };
|
|
1329
|
+
},
|
|
1330
|
+
hide: async (artifactId) => {
|
|
1331
|
+
const before = get().tiles;
|
|
1332
|
+
set({
|
|
1333
|
+
tiles: before.map(
|
|
1334
|
+
(t) => t.id === artifactId ? { ...t, visibility: "hidden" } : t
|
|
1335
|
+
)
|
|
1336
|
+
});
|
|
1337
|
+
const r = await patchArtifact(artifactId, { visibility: "hidden" }, "user_long_press_hide");
|
|
1338
|
+
if (r.ok) {
|
|
1339
|
+
if (r.artifact) {
|
|
1340
|
+
set({
|
|
1341
|
+
tiles: get().tiles.map((t) => t.id === artifactId ? { ...t, ...r.artifact } : t)
|
|
1342
|
+
});
|
|
1343
|
+
}
|
|
1344
|
+
return { ok: true };
|
|
1345
|
+
}
|
|
1346
|
+
set({ tiles: before });
|
|
1347
|
+
return { ok: false, error: r.error || `HTTP ${r.status}` };
|
|
1348
|
+
},
|
|
1349
|
+
unhide: async (artifactId) => {
|
|
1350
|
+
const before = get().tiles;
|
|
1351
|
+
set({
|
|
1352
|
+
tiles: before.map(
|
|
1353
|
+
(t) => t.id === artifactId ? { ...t, visibility: "pinned" } : t
|
|
1354
|
+
)
|
|
1355
|
+
});
|
|
1356
|
+
const r = await patchArtifact(artifactId, { visibility: "pinned" }, "user_long_press_unhide");
|
|
1357
|
+
if (r.ok) {
|
|
1358
|
+
if (r.artifact) {
|
|
1359
|
+
set({
|
|
1360
|
+
tiles: get().tiles.map((t) => t.id === artifactId ? { ...t, ...r.artifact } : t)
|
|
1361
|
+
});
|
|
1362
|
+
}
|
|
1363
|
+
return { ok: true };
|
|
1364
|
+
}
|
|
1365
|
+
set({ tiles: before });
|
|
1366
|
+
return { ok: false, error: r.error || `HTTP ${r.status}` };
|
|
1367
|
+
},
|
|
1368
|
+
rename: async (artifactId, name) => {
|
|
1369
|
+
const trimmed = name.trim();
|
|
1370
|
+
if (!trimmed) return { ok: false, error: "Name cannot be empty" };
|
|
1371
|
+
if (trimmed.length > 60) return { ok: false, error: "Name must be 60 characters or less" };
|
|
1372
|
+
const before = get().tiles;
|
|
1373
|
+
set({
|
|
1374
|
+
tiles: before.map((t) => t.id === artifactId ? { ...t, name: trimmed } : t)
|
|
1375
|
+
});
|
|
1376
|
+
const r = await patchArtifact(artifactId, { name: trimmed }, "user_long_press_rename");
|
|
1377
|
+
if (r.ok) {
|
|
1378
|
+
if (r.artifact) {
|
|
1379
|
+
set({
|
|
1380
|
+
tiles: get().tiles.map((t) => t.id === artifactId ? { ...t, ...r.artifact } : t)
|
|
1381
|
+
});
|
|
1382
|
+
}
|
|
1383
|
+
return { ok: true };
|
|
1384
|
+
}
|
|
1385
|
+
set({ tiles: before });
|
|
1386
|
+
return { ok: false, error: r.error || `HTTP ${r.status}` };
|
|
1387
|
+
},
|
|
1388
|
+
reorder: async (pinnedIds) => {
|
|
1389
|
+
const before = get().tiles;
|
|
1390
|
+
const idToOrder = new Map(pinnedIds.map((id, i) => [id, i]));
|
|
1391
|
+
set({
|
|
1392
|
+
tiles: before.map((t) => {
|
|
1393
|
+
const o = idToOrder.get(t.id);
|
|
1394
|
+
return o == null ? t : { ...t, pinOrder: o };
|
|
1395
|
+
})
|
|
1396
|
+
});
|
|
1397
|
+
const r = await setOrder(pinnedIds);
|
|
1398
|
+
if (r.ok) return { ok: true };
|
|
1399
|
+
set({ tiles: before });
|
|
1400
|
+
return { ok: false, error: r.error || `HTTP ${r.status}` };
|
|
1401
|
+
},
|
|
1402
|
+
applyServerUpdate: (artifact) => {
|
|
1403
|
+
set({
|
|
1404
|
+
tiles: get().tiles.map((t) => t.id === artifact.id ? { ...t, ...artifact } : t)
|
|
1405
|
+
});
|
|
1406
|
+
},
|
|
1407
|
+
applyServerRetire: (artifactId) => {
|
|
1408
|
+
set({ tiles: get().tiles.filter((t) => t.id !== artifactId) });
|
|
1409
|
+
},
|
|
1410
|
+
applyServerOrder: (pinnedIds) => {
|
|
1411
|
+
const idToOrder = new Map(pinnedIds.map((id, i) => [id, i]));
|
|
1412
|
+
set({
|
|
1413
|
+
tiles: get().tiles.map((t) => {
|
|
1414
|
+
const o = idToOrder.get(t.id);
|
|
1415
|
+
return o == null ? t : { ...t, pinOrder: o };
|
|
1416
|
+
})
|
|
1417
|
+
});
|
|
1418
|
+
},
|
|
1419
|
+
track: (artifactId, event) => {
|
|
1420
|
+
recordEvent(artifactId, event, "home");
|
|
1421
|
+
}
|
|
1422
|
+
}));
|
|
1423
|
+
|
|
1424
|
+
// src/acs/homeActionsStore.ts
|
|
1425
|
+
var import_zustand3 = require("zustand");
|
|
1426
|
+
var CACHE_KEY = "ateam.homeActions.v1";
|
|
1427
|
+
function persist(actions) {
|
|
1428
|
+
getAcsCacheStorage()?.setItem(CACHE_KEY, JSON.stringify(actions)).catch(() => {
|
|
1429
|
+
});
|
|
1430
|
+
}
|
|
1431
|
+
function sortByPin(a, b) {
|
|
1432
|
+
if (!!a.pinned !== !!b.pinned) return a.pinned ? -1 : 1;
|
|
1433
|
+
const ao = typeof a.pinOrder === "number" ? a.pinOrder : Number.MAX_SAFE_INTEGER;
|
|
1434
|
+
const bo = typeof b.pinOrder === "number" ? b.pinOrder : Number.MAX_SAFE_INTEGER;
|
|
1435
|
+
return ao - bo;
|
|
1436
|
+
}
|
|
1437
|
+
var useHomeActionsStore = (0, import_zustand3.create)((set, get) => ({
|
|
1438
|
+
actions: [],
|
|
1439
|
+
hydrated: false,
|
|
1440
|
+
loading: false,
|
|
1441
|
+
hydrate: async () => {
|
|
1442
|
+
if (get().hydrated || get().loading) return;
|
|
1443
|
+
try {
|
|
1444
|
+
const cached = await getAcsCacheStorage()?.getItem(CACHE_KEY);
|
|
1445
|
+
if (cached) {
|
|
1446
|
+
const parsed = JSON.parse(cached);
|
|
1447
|
+
if (Array.isArray(parsed) && parsed.length > 0) {
|
|
1448
|
+
set({ actions: parsed, hydrated: true });
|
|
1449
|
+
}
|
|
1450
|
+
}
|
|
1451
|
+
} catch {
|
|
1452
|
+
}
|
|
1453
|
+
await get().refresh();
|
|
1454
|
+
},
|
|
1455
|
+
refresh: async () => {
|
|
1456
|
+
if (get().loading) return;
|
|
1457
|
+
set({ loading: true });
|
|
1458
|
+
const actions = await listHomeActions();
|
|
1459
|
+
if (actions.length > 0) {
|
|
1460
|
+
set({ actions, loading: false, hydrated: true });
|
|
1461
|
+
persist(actions);
|
|
1462
|
+
} else {
|
|
1463
|
+
set({ loading: false, hydrated: true });
|
|
1464
|
+
}
|
|
1465
|
+
},
|
|
1466
|
+
// clear() wipes in-memory state on sign-out AND drops the disk cache — a
|
|
1467
|
+
// different user must not see the prior user's cards.
|
|
1468
|
+
clear: () => {
|
|
1469
|
+
set({ actions: [], hydrated: false, loading: false });
|
|
1470
|
+
getAcsCacheStorage()?.setItem(CACHE_KEY, "[]").catch(() => {
|
|
1471
|
+
});
|
|
1472
|
+
},
|
|
1473
|
+
dismiss: async (actionId) => {
|
|
1474
|
+
const before = get().actions;
|
|
1475
|
+
const next = before.filter((a) => a.actionId !== actionId);
|
|
1476
|
+
set({ actions: next });
|
|
1477
|
+
persist(next);
|
|
1478
|
+
const r = await patchHomeAction(actionId, { dismissed: true }, "user_dismiss");
|
|
1479
|
+
if (r.ok) return { ok: true };
|
|
1480
|
+
set({ actions: before });
|
|
1481
|
+
persist(before);
|
|
1482
|
+
return { ok: false, error: r.error || `HTTP ${r.status}` };
|
|
1483
|
+
},
|
|
1484
|
+
setPinned: async (actionId, pinned) => {
|
|
1485
|
+
const before = get().actions;
|
|
1486
|
+
const next = before.map((a) => a.actionId === actionId ? { ...a, pinned } : a).sort(sortByPin);
|
|
1487
|
+
set({ actions: next });
|
|
1488
|
+
persist(next);
|
|
1489
|
+
const r = await patchHomeAction(actionId, { pinned }, pinned ? "user_pin" : "user_unpin");
|
|
1490
|
+
if (r.ok) {
|
|
1491
|
+
if (r.action) {
|
|
1492
|
+
const merged = get().actions.map((a) => a.actionId === actionId ? { ...a, ...r.action } : a).sort(sortByPin);
|
|
1493
|
+
set({ actions: merged });
|
|
1494
|
+
persist(merged);
|
|
1495
|
+
}
|
|
1496
|
+
return { ok: true };
|
|
1497
|
+
}
|
|
1498
|
+
set({ actions: before });
|
|
1499
|
+
persist(before);
|
|
1500
|
+
return { ok: false, error: r.error || `HTTP ${r.status}` };
|
|
1501
|
+
},
|
|
1502
|
+
reorder: async (orderedIds) => {
|
|
1503
|
+
const before = get().actions;
|
|
1504
|
+
const idx = new Map(orderedIds.map((id, i) => [id, i]));
|
|
1505
|
+
const next = before.map((a) => {
|
|
1506
|
+
const o = idx.get(a.actionId);
|
|
1507
|
+
return o == null ? a : { ...a, pinOrder: o };
|
|
1508
|
+
}).sort(sortByPin);
|
|
1509
|
+
set({ actions: next });
|
|
1510
|
+
persist(next);
|
|
1511
|
+
const r = await setHomeActionOrder(orderedIds);
|
|
1512
|
+
if (r.ok) return { ok: true };
|
|
1513
|
+
set({ actions: before });
|
|
1514
|
+
persist(before);
|
|
1515
|
+
return { ok: false, error: r.error || `HTTP ${r.status}` };
|
|
1516
|
+
},
|
|
1517
|
+
applyServerUpsert: (action) => {
|
|
1518
|
+
const rest = get().actions.filter((a) => a.actionId !== action.actionId);
|
|
1519
|
+
const next = [...rest, action].sort(sortByPin);
|
|
1520
|
+
set({ actions: next });
|
|
1521
|
+
persist(next);
|
|
1522
|
+
},
|
|
1523
|
+
applyServerRemove: (actionId) => {
|
|
1524
|
+
const next = get().actions.filter((a) => a.actionId !== actionId);
|
|
1525
|
+
set({ actions: next });
|
|
1526
|
+
persist(next);
|
|
1527
|
+
},
|
|
1528
|
+
applyServerOrder: (orderedIds) => {
|
|
1529
|
+
const idx = new Map(orderedIds.map((id, i) => [id, i]));
|
|
1530
|
+
const next = get().actions.map((a) => {
|
|
1531
|
+
const o = idx.get(a.actionId);
|
|
1532
|
+
return o == null ? a : { ...a, pinOrder: o };
|
|
1533
|
+
}).sort(sortByPin);
|
|
1534
|
+
set({ actions: next });
|
|
1535
|
+
persist(next);
|
|
1536
|
+
}
|
|
1537
|
+
}));
|
|
1538
|
+
|
|
1539
|
+
// src/acs/ws.ts
|
|
1540
|
+
var _ws2 = null;
|
|
1541
|
+
var _wantOpen = false;
|
|
1542
|
+
var _retryAttempt = 0;
|
|
1543
|
+
var _retryTimer = null;
|
|
1544
|
+
var _token = null;
|
|
1545
|
+
var _tenant = null;
|
|
1546
|
+
var TOPIC = "acs.artifacts";
|
|
1547
|
+
var TOPIC_HOME = "acs.home-actions";
|
|
1548
|
+
var MAX_BACKOFF_MS = 3e4;
|
|
1549
|
+
function backoffMs(attempt) {
|
|
1550
|
+
const base = Math.min(MAX_BACKOFF_MS, 500 * Math.pow(2, attempt));
|
|
1551
|
+
const jitter = Math.random() * 250;
|
|
1552
|
+
return base + jitter;
|
|
1553
|
+
}
|
|
1554
|
+
function send(obj) {
|
|
1555
|
+
if (_ws2 && _ws2.readyState === 1) {
|
|
1556
|
+
try {
|
|
1557
|
+
_ws2.send(JSON.stringify(obj));
|
|
1558
|
+
} catch (e) {
|
|
1559
|
+
console.warn("[acsWs] send failed", e);
|
|
1560
|
+
}
|
|
1561
|
+
}
|
|
1562
|
+
}
|
|
1563
|
+
function handleEvent(msg) {
|
|
1564
|
+
if (msg?.event === "subscribed") {
|
|
1565
|
+
console.log("[acsWs] subscribed to", msg?.data?.topic);
|
|
1566
|
+
return;
|
|
1567
|
+
}
|
|
1568
|
+
if (msg?.topic === TOPIC_HOME) {
|
|
1569
|
+
const home = useHomeActionsStore.getState();
|
|
1570
|
+
switch (msg.event) {
|
|
1571
|
+
case "updated":
|
|
1572
|
+
if (msg.action && typeof msg.action.actionId === "string") home.applyServerUpsert(msg.action);
|
|
1573
|
+
break;
|
|
1574
|
+
case "removed":
|
|
1575
|
+
if (typeof msg.actionId === "string") home.applyServerRemove(msg.actionId);
|
|
1576
|
+
break;
|
|
1577
|
+
case "order":
|
|
1578
|
+
if (Array.isArray(msg.order)) home.applyServerOrder(msg.order.filter((id) => typeof id === "string"));
|
|
1579
|
+
break;
|
|
1580
|
+
case "refreshed":
|
|
1581
|
+
home.refresh();
|
|
1582
|
+
break;
|
|
1583
|
+
default:
|
|
1584
|
+
break;
|
|
1585
|
+
}
|
|
1586
|
+
return;
|
|
1587
|
+
}
|
|
1588
|
+
if (msg?.topic !== TOPIC) return;
|
|
1589
|
+
const store = useWidgetsStore.getState();
|
|
1590
|
+
switch (msg.event) {
|
|
1591
|
+
case "updated":
|
|
1592
|
+
if (msg.artifact && typeof msg.artifact.id === "string") {
|
|
1593
|
+
store.applyServerUpdate(msg.artifact);
|
|
1594
|
+
}
|
|
1595
|
+
break;
|
|
1596
|
+
case "retired":
|
|
1597
|
+
if (typeof msg.artifactId === "string") {
|
|
1598
|
+
store.applyServerRetire(msg.artifactId);
|
|
1599
|
+
}
|
|
1600
|
+
break;
|
|
1601
|
+
case "order":
|
|
1602
|
+
if (Array.isArray(msg.pinned)) {
|
|
1603
|
+
store.applyServerOrder(msg.pinned.filter((id) => typeof id === "string"));
|
|
1604
|
+
}
|
|
1605
|
+
break;
|
|
1606
|
+
case "created":
|
|
1607
|
+
if (msg.artifact && typeof msg.artifact.id === "string") {
|
|
1608
|
+
store.applyServerUpdate(msg.artifact);
|
|
1609
|
+
}
|
|
1610
|
+
break;
|
|
1611
|
+
default:
|
|
1612
|
+
break;
|
|
1613
|
+
}
|
|
1614
|
+
}
|
|
1615
|
+
function openSocket() {
|
|
1616
|
+
if (_ws2) return;
|
|
1617
|
+
if (!_token || !_tenant) return;
|
|
1618
|
+
const url = `${getCoreWsUrl()}/ws?token=${encodeURIComponent(_token)}&tenant=${encodeURIComponent(_tenant)}`;
|
|
1619
|
+
console.log(`[acsWs] opening`);
|
|
1620
|
+
const ws = new WebSocket(url);
|
|
1621
|
+
_ws2 = ws;
|
|
1622
|
+
ws.onopen = () => {
|
|
1623
|
+
_retryAttempt = 0;
|
|
1624
|
+
send({ type: "subscribe", topic: TOPIC });
|
|
1625
|
+
send({ type: "subscribe", topic: TOPIC_HOME });
|
|
1626
|
+
};
|
|
1627
|
+
ws.onmessage = (e) => {
|
|
1628
|
+
try {
|
|
1629
|
+
const msg = JSON.parse(typeof e.data === "string" ? e.data : "");
|
|
1630
|
+
handleEvent(msg);
|
|
1631
|
+
} catch (err) {
|
|
1632
|
+
console.warn("[acsWs] parse failed", err);
|
|
1633
|
+
}
|
|
1634
|
+
};
|
|
1635
|
+
ws.onerror = (e) => {
|
|
1636
|
+
console.warn("[acsWs] error", e?.message || e);
|
|
1637
|
+
};
|
|
1638
|
+
ws.onclose = () => {
|
|
1639
|
+
_ws2 = null;
|
|
1640
|
+
if (!_wantOpen) return;
|
|
1641
|
+
const delay = backoffMs(_retryAttempt++);
|
|
1642
|
+
console.log(`[acsWs] closed; reconnecting in ${Math.round(delay)}ms (attempt ${_retryAttempt})`);
|
|
1643
|
+
if (_retryTimer) clearTimeout(_retryTimer);
|
|
1644
|
+
_retryTimer = setTimeout(openSocket, delay);
|
|
1645
|
+
};
|
|
1646
|
+
}
|
|
1647
|
+
function notifyAcsWsForeground() {
|
|
1648
|
+
if (_wantOpen && !_ws2) {
|
|
1649
|
+
if (_retryTimer) {
|
|
1650
|
+
clearTimeout(_retryTimer);
|
|
1651
|
+
_retryTimer = null;
|
|
1652
|
+
}
|
|
1653
|
+
_retryAttempt = 0;
|
|
1654
|
+
openSocket();
|
|
1655
|
+
}
|
|
1656
|
+
}
|
|
1657
|
+
function connectAcsWs(token, tenant) {
|
|
1658
|
+
if (_ws2 && _wantOpen && _token === token && _tenant === tenant) return;
|
|
1659
|
+
if (_ws2) {
|
|
1660
|
+
try {
|
|
1661
|
+
_ws2.close();
|
|
1662
|
+
} catch {
|
|
1663
|
+
}
|
|
1664
|
+
_ws2 = null;
|
|
1665
|
+
}
|
|
1666
|
+
_token = token;
|
|
1667
|
+
_tenant = tenant;
|
|
1668
|
+
_wantOpen = true;
|
|
1669
|
+
openSocket();
|
|
1670
|
+
}
|
|
1671
|
+
function disconnectAcsWs() {
|
|
1672
|
+
_wantOpen = false;
|
|
1673
|
+
_token = null;
|
|
1674
|
+
_tenant = null;
|
|
1675
|
+
if (_retryTimer) {
|
|
1676
|
+
clearTimeout(_retryTimer);
|
|
1677
|
+
_retryTimer = null;
|
|
1678
|
+
}
|
|
1679
|
+
if (_ws2) {
|
|
1680
|
+
try {
|
|
1681
|
+
_ws2.close();
|
|
1682
|
+
} catch {
|
|
1683
|
+
}
|
|
1684
|
+
_ws2 = null;
|
|
1685
|
+
}
|
|
1686
|
+
}
|
|
1050
1687
|
// Annotate the CommonJS export names for ESM import in node:
|
|
1051
1688
|
0 && (module.exports = {
|
|
1052
1689
|
PluginCommandEmitter,
|
|
@@ -1059,9 +1696,13 @@ var borderRadius = {
|
|
|
1059
1696
|
borderRadius,
|
|
1060
1697
|
closeChatStream,
|
|
1061
1698
|
colors,
|
|
1699
|
+
connectAcsWs,
|
|
1062
1700
|
connectorCall,
|
|
1701
|
+
deleteArtifact,
|
|
1702
|
+
disconnectAcsWs,
|
|
1063
1703
|
fontSize,
|
|
1064
1704
|
getConfig,
|
|
1705
|
+
getConsumerAuthApiUrl,
|
|
1065
1706
|
getCoreApiUrl,
|
|
1066
1707
|
getCoreWsUrl,
|
|
1067
1708
|
getTenant,
|
|
@@ -1070,12 +1711,27 @@ var borderRadius = {
|
|
|
1070
1711
|
getVoiceApiUrl,
|
|
1071
1712
|
initAdas,
|
|
1072
1713
|
isAdasInitialized,
|
|
1714
|
+
listHomeActions,
|
|
1715
|
+
listMadeForYou,
|
|
1716
|
+
listMyTenants,
|
|
1717
|
+
listSurface,
|
|
1073
1718
|
mcpFetch,
|
|
1074
1719
|
mcpToolCall,
|
|
1720
|
+
notifyAcsWsForeground,
|
|
1721
|
+
patchArtifact,
|
|
1722
|
+
patchHomeAction,
|
|
1075
1723
|
pluginCommandEmitter,
|
|
1076
1724
|
postCommandResult,
|
|
1725
|
+
recordEvent,
|
|
1726
|
+
setAcsCacheStorage,
|
|
1727
|
+
setAcsReachabilityReporter,
|
|
1728
|
+
setHomeActionOrder,
|
|
1729
|
+
setOrder,
|
|
1077
1730
|
spacing,
|
|
1731
|
+
switchTenant,
|
|
1078
1732
|
unwrapMcpResult,
|
|
1079
|
-
useChatStore
|
|
1733
|
+
useChatStore,
|
|
1734
|
+
useHomeActionsStore,
|
|
1735
|
+
useWidgetsStore
|
|
1080
1736
|
});
|
|
1081
1737
|
//# sourceMappingURL=index.js.map
|