@rubytech/create-sitedesk-code 0.1.530 → 0.1.531
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/package.json +1 -1
- package/payload/platform/lib/graph-write/dist/index.d.ts.map +1 -1
- package/payload/platform/lib/graph-write/dist/index.js +4 -0
- package/payload/platform/lib/graph-write/dist/index.js.map +1 -1
- package/payload/platform/lib/graph-write/src/index.ts +4 -0
- package/payload/platform/lib/learning-constants/dist/index.d.ts +35 -0
- package/payload/platform/lib/learning-constants/dist/index.d.ts.map +1 -0
- package/payload/platform/lib/learning-constants/dist/index.js +50 -0
- package/payload/platform/lib/learning-constants/dist/index.js.map +1 -0
- package/payload/platform/lib/learning-constants/package.json +7 -0
- package/payload/platform/lib/learning-constants/src/index.test.ts +47 -0
- package/payload/platform/lib/learning-constants/src/index.ts +57 -0
- package/payload/platform/lib/learning-constants/tsconfig.json +9 -0
- package/payload/platform/neo4j/schema.cypher +24 -0
- package/payload/platform/package.json +1 -1
- package/payload/platform/plugins/admin/.claude-plugin/plugin.json +1 -1
- package/payload/platform/plugins/admin/PLUGIN.md +1 -1
- package/payload/platform/plugins/admin/mcp/dist/index.js +2 -2
- package/payload/platform/plugins/admin/mcp/dist/index.js.map +1 -1
- package/payload/platform/plugins/admin/skills/insight/SKILL.md +1 -1
- package/payload/platform/plugins/admin/skills/platform-architecture/SKILL.md +58 -10
- package/payload/platform/plugins/admin/skills/whats-new/SKILL.md +7 -0
- package/payload/platform/plugins/docs/references/linkedin-extension.md +18 -9
- package/payload/platform/plugins/docs/references/session-retrospective.md +39 -0
- package/payload/platform/plugins/linkedin-extension/.claude-plugin/plugin.json +1 -1
- package/payload/platform/plugins/linkedin-extension/PLUGIN.md +7 -10
- package/payload/platform/plugins/linkedin-extension/extension/README.md +20 -17
- package/payload/platform/plugins/linkedin-extension/extension/background/sw.js +96 -13
- package/payload/platform/plugins/linkedin-extension/extension/manifest.json +3 -18
- package/payload/platform/plugins/linkedin-extension/extension/options/options.html +2 -2
- package/payload/platform/plugins/linkedin-extension/extension/options/options.js +1 -1
- package/payload/platform/plugins/memory/.claude-plugin/plugin.json +1 -1
- package/payload/platform/plugins/memory/PLUGIN.md +15 -1
- package/payload/platform/plugins/memory/mcp/dist/index.js +169 -0
- package/payload/platform/plugins/memory/mcp/dist/index.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/session-jsonl.test.d.ts +2 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/session-jsonl.test.d.ts.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/session-jsonl.test.js +95 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/session-jsonl.test.js.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/session-jsonl.d.ts +60 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/session-jsonl.d.ts.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/session-jsonl.js +153 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/session-jsonl.js.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/cross-account.test.js +6 -4
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/cross-account.test.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/learnings-derive.test.d.ts +2 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/learnings-derive.test.d.ts.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/learnings-derive.test.js +160 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/learnings-derive.test.js.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/learnings-recall.test.d.ts +2 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/learnings-recall.test.d.ts.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/learnings-recall.test.js +64 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/learnings-recall.test.js.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/learnings-scan.test.d.ts +2 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/learnings-scan.test.d.ts.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/learnings-scan.test.js +78 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/learnings-scan.test.js.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/learnings-derive.d.ts +41 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/learnings-derive.d.ts.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/learnings-derive.js +225 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/learnings-derive.js.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/learnings-recall.d.ts +31 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/learnings-recall.d.ts.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/learnings-recall.js +67 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/learnings-recall.js.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/learnings-scan.d.ts +40 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/learnings-scan.d.ts.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/learnings-scan.js +55 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/learnings-scan.js.map +1 -0
- package/payload/platform/plugins/memory/references/schema-base.md +3 -0
- package/payload/platform/plugins/memory/skills/learnings-recall/SKILL.md +27 -0
- package/payload/platform/plugins/whatsapp/mcp/dist/index.js +4 -4
- package/payload/platform/plugins/whatsapp/mcp/dist/index.js.map +1 -1
- package/payload/platform/plugins/whatsapp/references/channels-whatsapp.md +3 -3
- package/payload/platform/plugins/whatsapp/skills/connect-whatsapp/SKILL.md +6 -2
- package/payload/platform/plugins/whatsapp/skills/manage-whatsapp-config/SKILL.md +5 -1
- package/payload/platform/services/claude-session-manager/dist/canonical-tool-names.generated.d.ts.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/canonical-tool-names.generated.js +3 -0
- package/payload/platform/services/claude-session-manager/dist/canonical-tool-names.generated.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/learning-index.d.ts +28 -0
- package/payload/platform/services/claude-session-manager/dist/learning-index.d.ts.map +1 -0
- package/payload/platform/services/claude-session-manager/dist/learning-index.js +70 -0
- package/payload/platform/services/claude-session-manager/dist/learning-index.js.map +1 -0
- package/payload/platform/services/claude-session-manager/dist/pty-spawner.d.ts.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/pty-spawner.js +18 -0
- package/payload/platform/services/claude-session-manager/dist/pty-spawner.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/system-prompt.d.ts +6 -0
- package/payload/platform/services/claude-session-manager/dist/system-prompt.d.ts.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/system-prompt.js +17 -0
- package/payload/platform/services/claude-session-manager/dist/system-prompt.js.map +1 -1
- package/payload/platform/templates/specialists/agents/librarian.md +1 -1
- package/payload/server/{chunk-2YMGNYA3.js → chunk-SVB5NZ64.js} +41 -30
- package/payload/server/{manager-XPRN5UF5.js → manager-4Q3DTLXO.js} +5 -1
- package/payload/server/server.js +65 -17
- package/payload/platform/plugins/linkedin-extension/extension/assets/pill.css +0 -52
- package/payload/platform/plugins/linkedin-extension/extension/content/profile.js +0 -100
- package/payload/platform/plugins/linkedin-extension/extension/content/thread.js +0 -102
|
@@ -2710,6 +2710,12 @@ function enumerateValidAccountIds(accountsDir) {
|
|
|
2710
2710
|
cache2.set(accountsDir, valid);
|
|
2711
2711
|
return valid;
|
|
2712
2712
|
}
|
|
2713
|
+
function isProvisionedAccount(accountsDir, id) {
|
|
2714
|
+
const cached = cache2.get(accountsDir);
|
|
2715
|
+
if (cached?.includes(id)) return true;
|
|
2716
|
+
cache2.delete(accountsDir);
|
|
2717
|
+
return enumerateValidAccountIds(accountsDir).includes(id);
|
|
2718
|
+
}
|
|
2713
2719
|
function resolveHouseOrSoleAccountId(accountsDir) {
|
|
2714
2720
|
const valid = enumerateValidAccountIds(accountsDir);
|
|
2715
2721
|
const houses = [];
|
|
@@ -2784,10 +2790,19 @@ function readChannelRoutingOverride(accountsDir, houseId) {
|
|
|
2784
2790
|
}
|
|
2785
2791
|
return target;
|
|
2786
2792
|
}
|
|
2787
|
-
function
|
|
2793
|
+
function resolvePlatformAccountIdWithSource(accountsDir = ACCOUNTS_DIR) {
|
|
2788
2794
|
const houseId = resolveHouseId(accountsDir);
|
|
2789
2795
|
const routed = readChannelRoutingOverride(accountsDir, houseId);
|
|
2790
|
-
return routed
|
|
2796
|
+
return routed !== null ? { accountId: routed, source: "routing" } : { accountId: houseId, source: "house" };
|
|
2797
|
+
}
|
|
2798
|
+
function resolvePlatformAccountId(accountsDir = ACCOUNTS_DIR) {
|
|
2799
|
+
return resolvePlatformAccountIdWithSource(accountsDir).accountId;
|
|
2800
|
+
}
|
|
2801
|
+
function resolveConnectionPlatformAccountId(credentialAccountId, accountsDir = ACCOUNTS_DIR) {
|
|
2802
|
+
if (isProvisionedAccount(accountsDir, credentialAccountId)) {
|
|
2803
|
+
return { accountId: credentialAccountId, source: "self" };
|
|
2804
|
+
}
|
|
2805
|
+
return resolvePlatformAccountIdWithSource(accountsDir);
|
|
2791
2806
|
}
|
|
2792
2807
|
function resolveHouseAccountId(accountsDir = ACCOUNTS_DIR) {
|
|
2793
2808
|
return resolveHouseId(accountsDir);
|
|
@@ -3964,22 +3979,14 @@ async function init(opts) {
|
|
|
3964
3979
|
});
|
|
3965
3980
|
}
|
|
3966
3981
|
}
|
|
3967
|
-
|
|
3968
|
-
if (!configDir) throw new Error("WhatsApp manager not initialized");
|
|
3969
|
-
const authDir = resolveAuthDir(configDir, accountId);
|
|
3970
|
-
const hasAuth = await authExists(authDir);
|
|
3971
|
-
if (!hasAuth) {
|
|
3972
|
-
console.error(`${TAG17} no credentials for account=${accountId}`);
|
|
3973
|
-
throw new Error(`no credentials for account=${accountId}`);
|
|
3974
|
-
}
|
|
3975
|
-
let platformAccountId;
|
|
3976
|
-
let houseAccountId;
|
|
3982
|
+
function resolveConnectionAccountIds(accountId, accountsDir) {
|
|
3977
3983
|
try {
|
|
3978
|
-
|
|
3979
|
-
houseAccountId = resolveHouseAccountId();
|
|
3984
|
+
const resolved = resolveConnectionPlatformAccountId(accountId, accountsDir);
|
|
3985
|
+
const houseAccountId = resolveHouseAccountId(accountsDir);
|
|
3980
3986
|
console.error(
|
|
3981
|
-
`[whatsapp-persist] resolved-account-id waname=${accountId} uuid=${
|
|
3987
|
+
`[whatsapp-persist] resolved-account-id waname=${accountId} uuid=${resolved.accountId} house=${houseAccountId} source=${resolved.source}`
|
|
3982
3988
|
);
|
|
3989
|
+
return { platformAccountId: resolved.accountId, houseAccountId };
|
|
3983
3990
|
} catch (err) {
|
|
3984
3991
|
const reason = err instanceof Error ? err.message : String(err);
|
|
3985
3992
|
console.error(
|
|
@@ -3987,6 +3994,16 @@ async function startConnection(accountId) {
|
|
|
3987
3994
|
);
|
|
3988
3995
|
throw err;
|
|
3989
3996
|
}
|
|
3997
|
+
}
|
|
3998
|
+
async function startConnection(accountId) {
|
|
3999
|
+
if (!configDir) throw new Error("WhatsApp manager not initialized");
|
|
4000
|
+
const authDir = resolveAuthDir(configDir, accountId);
|
|
4001
|
+
const hasAuth = await authExists(authDir);
|
|
4002
|
+
if (!hasAuth) {
|
|
4003
|
+
console.error(`${TAG17} no credentials for account=${accountId}`);
|
|
4004
|
+
throw new Error(`no credentials for account=${accountId}`);
|
|
4005
|
+
}
|
|
4006
|
+
const { platformAccountId, houseAccountId } = resolveConnectionAccountIds(accountId);
|
|
3990
4007
|
await stopConnection(accountId);
|
|
3991
4008
|
const conn = {
|
|
3992
4009
|
accountId,
|
|
@@ -4111,23 +4128,15 @@ function isAnyConnected() {
|
|
|
4111
4128
|
function listConnectionPlatformAccountIds() {
|
|
4112
4129
|
return [...connections.values()].map((conn) => conn.platformAccountId);
|
|
4113
4130
|
}
|
|
4131
|
+
function listConnectionAccountStamps() {
|
|
4132
|
+
return [...connections.values()].map((conn) => ({
|
|
4133
|
+
accountId: conn.accountId,
|
|
4134
|
+
platformAccountId: conn.platformAccountId
|
|
4135
|
+
}));
|
|
4136
|
+
}
|
|
4114
4137
|
async function registerLoginSocket(accountId, sock, authDir) {
|
|
4115
4138
|
if (!configDir) throw new Error("WhatsApp manager not initialized");
|
|
4116
|
-
|
|
4117
|
-
let houseAccountId;
|
|
4118
|
-
try {
|
|
4119
|
-
platformAccountId = resolvePlatformAccountId();
|
|
4120
|
-
houseAccountId = resolveHouseAccountId();
|
|
4121
|
-
console.error(
|
|
4122
|
-
`[whatsapp-persist] resolved-account-id waname=${accountId} uuid=${platformAccountId} house=${houseAccountId}`
|
|
4123
|
-
);
|
|
4124
|
-
} catch (err) {
|
|
4125
|
-
const reason = err instanceof Error ? err.message : String(err);
|
|
4126
|
-
console.error(
|
|
4127
|
-
`[whatsapp-persist] resolved-account-id FAIL waname=${accountId} reason=${reason}`
|
|
4128
|
-
);
|
|
4129
|
-
throw err;
|
|
4130
|
-
}
|
|
4139
|
+
const { platformAccountId, houseAccountId } = resolveConnectionAccountIds(accountId);
|
|
4131
4140
|
await stopConnection(accountId);
|
|
4132
4141
|
const conn = {
|
|
4133
4142
|
accountId,
|
|
@@ -5269,6 +5278,7 @@ export {
|
|
|
5269
5278
|
deriveCacheKey,
|
|
5270
5279
|
buildSelfChatDispatch,
|
|
5271
5280
|
init,
|
|
5281
|
+
resolveConnectionAccountIds,
|
|
5272
5282
|
startConnection,
|
|
5273
5283
|
stopConnection,
|
|
5274
5284
|
getStatus,
|
|
@@ -5282,6 +5292,7 @@ export {
|
|
|
5282
5292
|
resolveConversationPersistAccount,
|
|
5283
5293
|
isAnyConnected,
|
|
5284
5294
|
listConnectionPlatformAccountIds,
|
|
5295
|
+
listConnectionAccountStamps,
|
|
5285
5296
|
registerLoginSocket,
|
|
5286
5297
|
reloadConfig,
|
|
5287
5298
|
getMessages,
|
|
@@ -11,6 +11,7 @@ import {
|
|
|
11
11
|
isAnyConnected,
|
|
12
12
|
isManagerRoutedToHouse,
|
|
13
13
|
isObserveAccount,
|
|
14
|
+
listConnectionAccountStamps,
|
|
14
15
|
listConnectionPlatformAccountIds,
|
|
15
16
|
listConnections,
|
|
16
17
|
listConversationJids,
|
|
@@ -18,6 +19,7 @@ import {
|
|
|
18
19
|
messageStoreKey,
|
|
19
20
|
registerLoginSocket,
|
|
20
21
|
reloadConfig,
|
|
22
|
+
resolveConnectionAccountIds,
|
|
21
23
|
resolveConversationPersistAccount,
|
|
22
24
|
resolveInboundPersistAccount,
|
|
23
25
|
resolveReadStoreKey,
|
|
@@ -28,7 +30,7 @@ import {
|
|
|
28
30
|
startConnection,
|
|
29
31
|
stopConnection,
|
|
30
32
|
storeMessage
|
|
31
|
-
} from "./chunk-
|
|
33
|
+
} from "./chunk-SVB5NZ64.js";
|
|
32
34
|
import "./chunk-BP7LH7MC.js";
|
|
33
35
|
import "./chunk-PFF6I7KP.js";
|
|
34
36
|
export {
|
|
@@ -43,6 +45,7 @@ export {
|
|
|
43
45
|
isAnyConnected,
|
|
44
46
|
isManagerRoutedToHouse,
|
|
45
47
|
isObserveAccount,
|
|
48
|
+
listConnectionAccountStamps,
|
|
46
49
|
listConnectionPlatformAccountIds,
|
|
47
50
|
listConnections,
|
|
48
51
|
listConversationJids,
|
|
@@ -50,6 +53,7 @@ export {
|
|
|
50
53
|
messageStoreKey,
|
|
51
54
|
registerLoginSocket,
|
|
52
55
|
reloadConfig,
|
|
56
|
+
resolveConnectionAccountIds,
|
|
53
57
|
resolveConversationPersistAccount,
|
|
54
58
|
resolveInboundPersistAccount,
|
|
55
59
|
resolveReadStoreKey,
|
package/payload/server/server.js
CHANGED
|
@@ -124,6 +124,7 @@ import {
|
|
|
124
124
|
isUserJid,
|
|
125
125
|
isWithinOwnAccountPartition,
|
|
126
126
|
jidToE164,
|
|
127
|
+
listConnectionAccountStamps,
|
|
127
128
|
listConnectionPlatformAccountIds,
|
|
128
129
|
listConnections,
|
|
129
130
|
listLedgerAccounts,
|
|
@@ -183,7 +184,7 @@ import {
|
|
|
183
184
|
waitForConnection,
|
|
184
185
|
warnNonUuidAccount,
|
|
185
186
|
writeChatMetadataMerged
|
|
186
|
-
} from "./chunk-
|
|
187
|
+
} from "./chunk-SVB5NZ64.js";
|
|
187
188
|
import {
|
|
188
189
|
ACCOUNTS_DIR,
|
|
189
190
|
BIN_DIR,
|
|
@@ -1586,7 +1587,11 @@ var require_dist5 = __commonJS({
|
|
|
1586
1587
|
"Risk",
|
|
1587
1588
|
"Source",
|
|
1588
1589
|
"Finding",
|
|
1589
|
-
"Hypothesis"
|
|
1590
|
+
"Hypothesis",
|
|
1591
|
+
// Task 2220 — :Learning carries learning_embedding, which learnings-derive
|
|
1592
|
+
// queries by name to reconcile a claim against an existing learning. Without
|
|
1593
|
+
// it here the chokepoint cannot detect a null-embedding Learning write.
|
|
1594
|
+
"Learning"
|
|
1590
1595
|
]);
|
|
1591
1596
|
exports.DOCUMENT_ARCHIVE_LABELS = /* @__PURE__ */ new Set([
|
|
1592
1597
|
"KnowledgeDocument",
|
|
@@ -4999,7 +5004,7 @@ async function defaultHttpGet(url) {
|
|
|
4999
5004
|
}
|
|
5000
5005
|
}
|
|
5001
5006
|
async function defaultResolve(accountId) {
|
|
5002
|
-
const { resolveSocket: resolveSocket2 } = await import("./manager-
|
|
5007
|
+
const { resolveSocket: resolveSocket2 } = await import("./manager-4Q3DTLXO.js");
|
|
5003
5008
|
return resolveSocket2(accountId);
|
|
5004
5009
|
}
|
|
5005
5010
|
async function fetchAvatar(accountId, jid, deps = {}) {
|
|
@@ -6144,6 +6149,15 @@ function reconcileMessageStoreAccountKeys(input) {
|
|
|
6144
6149
|
return { ok: orphanLiveKeys.length === 0, orphanLiveKeys };
|
|
6145
6150
|
}
|
|
6146
6151
|
|
|
6152
|
+
// app/lib/whatsapp/connection-account-reconcile.ts
|
|
6153
|
+
function reconcileConnectionAccountStamps(input) {
|
|
6154
|
+
const registered = new Set(input.registeredAccountIds);
|
|
6155
|
+
const mismatches = input.connections.filter(
|
|
6156
|
+
(c) => registered.has(c.accountId) && c.platformAccountId !== c.accountId
|
|
6157
|
+
);
|
|
6158
|
+
return { ok: mismatches.length === 0, mismatches };
|
|
6159
|
+
}
|
|
6160
|
+
|
|
6147
6161
|
// app/lib/whatsapp/outbound/send-document.ts
|
|
6148
6162
|
import { realpathSync } from "fs";
|
|
6149
6163
|
import { readFile as readFile3, stat as stat2 } from "fs/promises";
|
|
@@ -6513,20 +6527,39 @@ function houseSocketScopeDenial(c, op) {
|
|
|
6513
6527
|
console.error(`${TAG14} op=authz-deny route=${op} caller=${callerAccountId ?? "none"} houseAdmin=${houseAdminScope ? "y" : "n"}`);
|
|
6514
6528
|
return c.json({ ok: false, error: "Not authorized. The WhatsApp connection and its settings are house-scoped; this session may only act on its own account." }, 403);
|
|
6515
6529
|
}
|
|
6516
|
-
function selfOrHouseScopeDenial(c, targetAccountId, op) {
|
|
6530
|
+
function selfOrHouseScopeDenial(c, targetAccountId, op, targetSource = "explicit") {
|
|
6517
6531
|
const { decision, callerAccountId, houseAdminScope } = evaluateCallerScope(c, targetAccountId);
|
|
6532
|
+
const tail = `target=${targetAccountId} targetSource=${targetSource} caller=${callerAccountId ?? "none"} houseAdmin=${houseAdminScope ? "y" : "n"}`;
|
|
6518
6533
|
if (decision.authorized) {
|
|
6519
|
-
console.error(`${TAG14} op=authz-ok route=${op}
|
|
6534
|
+
console.error(`${TAG14} op=authz-ok route=${op} ${tail}`);
|
|
6520
6535
|
return null;
|
|
6521
6536
|
}
|
|
6522
|
-
console.error(`${TAG14} op=authz-deny route=${op}
|
|
6537
|
+
console.error(`${TAG14} op=authz-deny route=${op} ${tail}`);
|
|
6523
6538
|
return c.json({ ok: false, error: "Not authorized. This session may only pair or manage its own account." }, 403);
|
|
6524
6539
|
}
|
|
6540
|
+
function resolveLifecycleAccountId(c, raw) {
|
|
6541
|
+
if (typeof raw === "string" && raw.trim().length > 0) {
|
|
6542
|
+
return { accountId: validateAccountId(raw), targetSource: "explicit" };
|
|
6543
|
+
}
|
|
6544
|
+
const callerAccountId = c.req.header("x-maxy-caller-account")?.trim() || null;
|
|
6545
|
+
const houseAdminScope = c.req.header("x-maxy-house-admin-scope")?.trim() || null;
|
|
6546
|
+
const houseAccountId = resolveAccount()?.accountId ?? "";
|
|
6547
|
+
const callerIsHouse = !!houseAdminScope || !!callerAccountId && callerAccountId === houseAccountId;
|
|
6548
|
+
if (callerIsHouse || !callerAccountId) {
|
|
6549
|
+
return { accountId: "default", targetSource: "house-default" };
|
|
6550
|
+
}
|
|
6551
|
+
return { accountId: validateAccountId(callerAccountId), targetSource: "caller-default" };
|
|
6552
|
+
}
|
|
6525
6553
|
var app3 = new Hono();
|
|
6526
6554
|
app3.get("/status", (c) => {
|
|
6527
6555
|
try {
|
|
6528
|
-
const
|
|
6529
|
-
|
|
6556
|
+
const houseAccountId = resolveAccount()?.accountId ?? "";
|
|
6557
|
+
const { decision, callerAccountId, houseAdminScope } = evaluateCallerScope(c, houseAccountId);
|
|
6558
|
+
const houseScoped = decision.authorized;
|
|
6559
|
+
if (!houseScoped && !callerAccountId) {
|
|
6560
|
+
console.error(`${TAG14} op=authz-deny route=status caller=none houseAdmin=${houseAdminScope ? "y" : "n"}`);
|
|
6561
|
+
return c.json({ ok: false, error: "Not authorized. The WhatsApp connection and its settings are house-scoped; this session may only act on its own account." }, 403);
|
|
6562
|
+
}
|
|
6530
6563
|
const live = getStatus();
|
|
6531
6564
|
const liveIds = new Set(live.map((a) => a.accountId));
|
|
6532
6565
|
const activeLoginIds = new Set(listActiveLoginAccountIds());
|
|
@@ -6540,6 +6573,11 @@ app3.get("/status", (c) => {
|
|
|
6540
6573
|
}));
|
|
6541
6574
|
const summary = accounts.map((a) => `${a.accountId}:${a.connected ? "up" : a.linkedUnconfigured ? "linked-unconfigured" : "down"}:${a.dispatchInbound ? "dispatch" : "observe"}`).join(", ");
|
|
6542
6575
|
console.error(`${TAG14} status accounts=${accounts.length} [${summary}]`);
|
|
6576
|
+
if (!houseScoped) {
|
|
6577
|
+
const own = accounts.filter((a) => a.accountId === callerAccountId);
|
|
6578
|
+
console.error(`${TAG14} op=status-projection caller=${callerAccountId.slice(0, 8)} scope=self rows=${own.length}`);
|
|
6579
|
+
return c.json({ accounts: own });
|
|
6580
|
+
}
|
|
6543
6581
|
const reachableAccountIds = [
|
|
6544
6582
|
.../* @__PURE__ */ new Set([...listStoredAccountIds(), ...listConnectionPlatformAccountIds()])
|
|
6545
6583
|
];
|
|
@@ -6550,7 +6588,16 @@ app3.get("/status", (c) => {
|
|
|
6550
6588
|
if (!storeKeyReconcile.ok) {
|
|
6551
6589
|
console.warn(`${TAG14} store-key-drift orphanLiveKeys=[${storeKeyReconcile.orphanLiveKeys.join(",")}] \u2014 in-memory cache keyed by a value with no disk account; read tools will miss`);
|
|
6552
6590
|
}
|
|
6553
|
-
|
|
6591
|
+
const connectionAccountReconcile = reconcileConnectionAccountStamps({
|
|
6592
|
+
connections: listConnectionAccountStamps(),
|
|
6593
|
+
registeredAccountIds: listValidAccounts().map((a) => a.accountId)
|
|
6594
|
+
});
|
|
6595
|
+
if (!connectionAccountReconcile.ok) {
|
|
6596
|
+
const pairs = connectionAccountReconcile.mismatches.map((m) => `${m.accountId}:${m.platformAccountId}`).join(",");
|
|
6597
|
+
console.warn(`${TAG14} connection-account-drift mismatches=[${pairs}] \u2014 a socket keyed by a registered account is stamping a different one; its messages persist and read under that account`);
|
|
6598
|
+
}
|
|
6599
|
+
console.error(`${TAG14} op=status-projection caller=${callerAccountId?.slice(0, 8) ?? "none"} scope=house rows=${accounts.length}`);
|
|
6600
|
+
return c.json({ accounts, storeKeyReconcile, connectionAccountReconcile });
|
|
6554
6601
|
} catch (err) {
|
|
6555
6602
|
console.error(`${TAG14} status error: ${String(err)}`);
|
|
6556
6603
|
return c.json({ error: String(err) }, 500);
|
|
@@ -6559,8 +6606,8 @@ app3.get("/status", (c) => {
|
|
|
6559
6606
|
app3.post("/login/start", async (c) => {
|
|
6560
6607
|
try {
|
|
6561
6608
|
const body = await c.req.json().catch(() => ({}));
|
|
6562
|
-
const accountId =
|
|
6563
|
-
const denial = selfOrHouseScopeDenial(c, accountId, "login/start");
|
|
6609
|
+
const { accountId, targetSource } = resolveLifecycleAccountId(c, body.accountId);
|
|
6610
|
+
const denial = selfOrHouseScopeDenial(c, accountId, "login/start", targetSource);
|
|
6564
6611
|
if (denial) return denial;
|
|
6565
6612
|
const force = body.force ?? false;
|
|
6566
6613
|
const phone = typeof body.phone === "string" ? body.phone.trim() : "";
|
|
@@ -6580,8 +6627,8 @@ app3.post("/login/start", async (c) => {
|
|
|
6580
6627
|
app3.post("/login/wait", async (c) => {
|
|
6581
6628
|
try {
|
|
6582
6629
|
const body = await c.req.json().catch(() => ({}));
|
|
6583
|
-
const accountId =
|
|
6584
|
-
const denial = selfOrHouseScopeDenial(c, accountId, "login/wait");
|
|
6630
|
+
const { accountId, targetSource } = resolveLifecycleAccountId(c, body.accountId);
|
|
6631
|
+
const denial = selfOrHouseScopeDenial(c, accountId, "login/wait", targetSource);
|
|
6585
6632
|
if (denial) return denial;
|
|
6586
6633
|
const timeoutMs = body.timeoutMs ?? 6e4;
|
|
6587
6634
|
const result = await waitForLogin({ accountId, timeoutMs });
|
|
@@ -6600,8 +6647,8 @@ app3.post("/login/wait", async (c) => {
|
|
|
6600
6647
|
app3.post("/disconnect", async (c) => {
|
|
6601
6648
|
try {
|
|
6602
6649
|
const body = await c.req.json().catch(() => ({}));
|
|
6603
|
-
const accountId =
|
|
6604
|
-
const denial = selfOrHouseScopeDenial(c, accountId, "disconnect");
|
|
6650
|
+
const { accountId, targetSource } = resolveLifecycleAccountId(c, body.accountId);
|
|
6651
|
+
const denial = selfOrHouseScopeDenial(c, accountId, "disconnect", targetSource);
|
|
6605
6652
|
if (denial) return denial;
|
|
6606
6653
|
await stopConnection(accountId);
|
|
6607
6654
|
return c.json({ disconnected: true, accountId });
|
|
@@ -6614,8 +6661,9 @@ app3.post("/reconnect", async (c) => {
|
|
|
6614
6661
|
let accountId = "(unresolved)";
|
|
6615
6662
|
try {
|
|
6616
6663
|
const body = await c.req.json().catch(() => ({}));
|
|
6617
|
-
|
|
6618
|
-
|
|
6664
|
+
const resolved = resolveLifecycleAccountId(c, body.accountId);
|
|
6665
|
+
accountId = resolved.accountId;
|
|
6666
|
+
const denial = selfOrHouseScopeDenial(c, accountId, "reconnect", resolved.targetSource);
|
|
6619
6667
|
if (denial) return denial;
|
|
6620
6668
|
await startConnection(accountId);
|
|
6621
6669
|
console.error(
|
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
/* "Add to SiteDesk" pill injected into LinkedIn profile and DM thread pages. */
|
|
2
|
-
|
|
3
|
-
#maxy-linkedin-pill.maxy-pill {
|
|
4
|
-
position: relative;
|
|
5
|
-
z-index: 9999;
|
|
6
|
-
display: inline-flex;
|
|
7
|
-
align-items: center;
|
|
8
|
-
gap: 6px;
|
|
9
|
-
margin: 12px;
|
|
10
|
-
padding: 6px 14px;
|
|
11
|
-
border: 1px solid #0a66c2;
|
|
12
|
-
border-radius: 999px;
|
|
13
|
-
background: #ffffff;
|
|
14
|
-
color: #0a66c2;
|
|
15
|
-
font: 600 13px/1.2 -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
|
|
16
|
-
cursor: pointer;
|
|
17
|
-
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.06);
|
|
18
|
-
transition: background 120ms ease, color 120ms ease, border-color 120ms ease;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
#maxy-linkedin-pill.maxy-pill:hover {
|
|
22
|
-
background: #0a66c2;
|
|
23
|
-
color: #ffffff;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
#maxy-linkedin-pill.maxy-pill[data-state="busy"] {
|
|
27
|
-
background: #f4f7fb;
|
|
28
|
-
border-color: #a3b6c9;
|
|
29
|
-
color: #46596d;
|
|
30
|
-
cursor: progress;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
#maxy-linkedin-pill.maxy-pill[data-state="ok"] {
|
|
34
|
-
background: #e6f4ea;
|
|
35
|
-
border-color: #2e7d32;
|
|
36
|
-
color: #2e7d32;
|
|
37
|
-
cursor: default;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
#maxy-linkedin-pill.maxy-pill[data-state="error"] {
|
|
41
|
-
background: #fdecea;
|
|
42
|
-
border-color: #b00020;
|
|
43
|
-
color: #b00020;
|
|
44
|
-
cursor: pointer;
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
#maxy-linkedin-pill.maxy-pill[data-state="auth"] {
|
|
48
|
-
background: #fff7e0;
|
|
49
|
-
border-color: #b8860b;
|
|
50
|
-
color: #b8860b;
|
|
51
|
-
cursor: pointer;
|
|
52
|
-
}
|
|
@@ -1,100 +0,0 @@
|
|
|
1
|
-
// Profile content script. Runs on linkedin.com/in/*.
|
|
2
|
-
// Manifest concatenates extractors.js + this file, so MaxyLinkedinExtractors
|
|
3
|
-
// is in scope. One click → scrape → post to the service worker → pill state.
|
|
4
|
-
|
|
5
|
-
;(function () {
|
|
6
|
-
const TAG_MOUNT = '[linkedin-ext-mount]'
|
|
7
|
-
const TAG_SCRAPE = '[linkedin-ext-scrape]'
|
|
8
|
-
const TAG_ERROR = '[linkedin-ext-error]'
|
|
9
|
-
const PILL_ID = 'maxy-linkedin-pill'
|
|
10
|
-
|
|
11
|
-
function setState(pill, state, label) {
|
|
12
|
-
pill.dataset.state = state
|
|
13
|
-
if (label) pill.textContent = label
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
async function onClick(pill) {
|
|
17
|
-
const dispatchId = crypto.randomUUID()
|
|
18
|
-
setState(pill, 'busy', 'Capturing…')
|
|
19
|
-
|
|
20
|
-
const result = globalThis.MaxyLinkedinExtractors.extractProfile(document)
|
|
21
|
-
if (!result.ok) {
|
|
22
|
-
console.error(TAG_SCRAPE + ' page=profile ok=false missing=' + result.missing.join(','))
|
|
23
|
-
setState(pill, 'error', 'Missing: ' + result.missing.join(', '))
|
|
24
|
-
return
|
|
25
|
-
}
|
|
26
|
-
console.log(TAG_SCRAPE + ' page=profile ok=true fields=' + Object.keys(result.payload).join(','))
|
|
27
|
-
|
|
28
|
-
const envelope = {
|
|
29
|
-
source: 'linkedin',
|
|
30
|
-
kind: 'profile',
|
|
31
|
-
capturedAt: new Date().toISOString(),
|
|
32
|
-
pageUrl: location.href.split('?')[0].split('#')[0],
|
|
33
|
-
dispatchId: dispatchId,
|
|
34
|
-
profile: result.payload,
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
let reply
|
|
38
|
-
try {
|
|
39
|
-
reply = await chrome.runtime.sendMessage({ type: 'linkedin-ingest', envelope: envelope })
|
|
40
|
-
} catch (err) {
|
|
41
|
-
console.error(TAG_ERROR + ' reason=worker-unreachable detail=' + (err && err.message ? err.message : String(err)))
|
|
42
|
-
setState(pill, 'error', 'Capture failed')
|
|
43
|
-
return
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
if (!reply || !reply.ok) {
|
|
47
|
-
// `worker-unreachable` is the extension's OWN service worker failing to
|
|
48
|
-
// answer. It is not `unreachable`, which means the admin host did not
|
|
49
|
-
// answer — blaming SiteDesk here sends the operator to check a tunnel that
|
|
50
|
-
// was never involved.
|
|
51
|
-
const reason = (reply && reply.reason) || 'worker-unreachable'
|
|
52
|
-
const detail = (reply && reply.detail) || ''
|
|
53
|
-
console.error(TAG_ERROR + ' reason=' + reason + ' detail=' + detail)
|
|
54
|
-
// Task 2208 — the ingest token is missing or was refused. There is no
|
|
55
|
-
// sign-in to perform: the operator asks the SiteDesk agent for the token and
|
|
56
|
-
// pastes it on the options page.
|
|
57
|
-
if (reason === 'auth') {
|
|
58
|
-
setState(pill, 'auth', 'Paste SiteDesk token')
|
|
59
|
-
pill.onclick = function () { chrome.runtime.openOptionsPage() }
|
|
60
|
-
return
|
|
61
|
-
}
|
|
62
|
-
// Task 2185 — the admin host was never granted, so the POST never left
|
|
63
|
-
// the browser. Sending the operator to the options page is the fix.
|
|
64
|
-
if (reason === 'permission') {
|
|
65
|
-
setState(pill, 'auth', 'Grant access')
|
|
66
|
-
pill.onclick = function () { chrome.runtime.openOptionsPage() }
|
|
67
|
-
return
|
|
68
|
-
}
|
|
69
|
-
if (reason === 'unreachable') {
|
|
70
|
-
setState(pill, 'error', 'SiteDesk unreachable')
|
|
71
|
-
return
|
|
72
|
-
}
|
|
73
|
-
setState(pill, 'error', 'Capture failed')
|
|
74
|
-
return
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
setState(pill, 'ok', 'Captured ✓')
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
function mount() {
|
|
81
|
-
if (document.getElementById(PILL_ID)) return
|
|
82
|
-
const anchor = document.querySelector('section.top-card-layout, main') || document.body
|
|
83
|
-
if (!anchor) return
|
|
84
|
-
const pill = document.createElement('button')
|
|
85
|
-
pill.id = PILL_ID
|
|
86
|
-
pill.className = 'maxy-pill'
|
|
87
|
-
pill.type = 'button'
|
|
88
|
-
pill.textContent = 'Add to SiteDesk'
|
|
89
|
-
pill.dataset.state = 'idle'
|
|
90
|
-
pill.addEventListener('click', function () { onClick(pill) })
|
|
91
|
-
anchor.prepend(pill)
|
|
92
|
-
console.log(TAG_MOUNT + ' page=profile url=' + location.href)
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
if (document.readyState === 'loading') {
|
|
96
|
-
document.addEventListener('DOMContentLoaded', mount, { once: true })
|
|
97
|
-
} else {
|
|
98
|
-
mount()
|
|
99
|
-
}
|
|
100
|
-
})()
|
|
@@ -1,102 +0,0 @@
|
|
|
1
|
-
// Thread content script. Runs on linkedin.com/messaging/thread/*.
|
|
2
|
-
// Manifest concatenates extractors.js + this file.
|
|
3
|
-
|
|
4
|
-
;(function () {
|
|
5
|
-
const TAG_MOUNT = '[linkedin-ext-mount]'
|
|
6
|
-
const TAG_SCRAPE = '[linkedin-ext-scrape]'
|
|
7
|
-
const TAG_ERROR = '[linkedin-ext-error]'
|
|
8
|
-
const PILL_ID = 'maxy-linkedin-pill'
|
|
9
|
-
|
|
10
|
-
function setState(pill, state, label) {
|
|
11
|
-
pill.dataset.state = state
|
|
12
|
-
if (label) pill.textContent = label
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
async function onClick(pill) {
|
|
16
|
-
const dispatchId = crypto.randomUUID()
|
|
17
|
-
setState(pill, 'busy', 'Capturing…')
|
|
18
|
-
|
|
19
|
-
const result = globalThis.MaxyLinkedinExtractors.extractThread(document)
|
|
20
|
-
if (!result.ok) {
|
|
21
|
-
console.error(TAG_SCRAPE + ' page=thread ok=false missing=' + result.missing.join(','))
|
|
22
|
-
setState(pill, 'error', 'Missing: ' + result.missing.join(', '))
|
|
23
|
-
return
|
|
24
|
-
}
|
|
25
|
-
console.log(
|
|
26
|
-
TAG_SCRAPE + ' page=thread ok=true fields=participants,bodyText participantCount=' +
|
|
27
|
-
result.payload.participants.length,
|
|
28
|
-
)
|
|
29
|
-
|
|
30
|
-
const envelope = {
|
|
31
|
-
source: 'linkedin',
|
|
32
|
-
kind: 'thread',
|
|
33
|
-
capturedAt: new Date().toISOString(),
|
|
34
|
-
pageUrl: location.href.split('?')[0].split('#')[0],
|
|
35
|
-
dispatchId: dispatchId,
|
|
36
|
-
thread: result.payload,
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
let reply
|
|
40
|
-
try {
|
|
41
|
-
reply = await chrome.runtime.sendMessage({ type: 'linkedin-ingest', envelope: envelope })
|
|
42
|
-
} catch (err) {
|
|
43
|
-
console.error(TAG_ERROR + ' reason=worker-unreachable detail=' + (err && err.message ? err.message : String(err)))
|
|
44
|
-
setState(pill, 'error', 'Capture failed')
|
|
45
|
-
return
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
if (!reply || !reply.ok) {
|
|
49
|
-
// `worker-unreachable` is the extension's OWN service worker failing to
|
|
50
|
-
// answer. It is not `unreachable`, which means the admin host did not
|
|
51
|
-
// answer — blaming SiteDesk here sends the operator to check a tunnel that
|
|
52
|
-
// was never involved.
|
|
53
|
-
const reason = (reply && reply.reason) || 'worker-unreachable'
|
|
54
|
-
const detail = (reply && reply.detail) || ''
|
|
55
|
-
console.error(TAG_ERROR + ' reason=' + reason + ' detail=' + detail)
|
|
56
|
-
// Task 2208 — the ingest token is missing or was refused. There is no
|
|
57
|
-
// sign-in to perform: the operator asks the SiteDesk agent for the token and
|
|
58
|
-
// pastes it on the options page.
|
|
59
|
-
if (reason === 'auth') {
|
|
60
|
-
setState(pill, 'auth', 'Paste SiteDesk token')
|
|
61
|
-
pill.onclick = function () { chrome.runtime.openOptionsPage() }
|
|
62
|
-
return
|
|
63
|
-
}
|
|
64
|
-
// Task 2185 — the admin host was never granted, so the POST never left
|
|
65
|
-
// the browser. Sending the operator to the options page is the fix.
|
|
66
|
-
if (reason === 'permission') {
|
|
67
|
-
setState(pill, 'auth', 'Grant access')
|
|
68
|
-
pill.onclick = function () { chrome.runtime.openOptionsPage() }
|
|
69
|
-
return
|
|
70
|
-
}
|
|
71
|
-
if (reason === 'unreachable') {
|
|
72
|
-
setState(pill, 'error', 'SiteDesk unreachable')
|
|
73
|
-
return
|
|
74
|
-
}
|
|
75
|
-
setState(pill, 'error', 'Capture failed')
|
|
76
|
-
return
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
setState(pill, 'ok', 'Captured ✓')
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
function mount() {
|
|
83
|
-
if (document.getElementById(PILL_ID)) return
|
|
84
|
-
const anchor = document.querySelector('.msg-thread, header.msg-overlay-bubble-header, main') || document.body
|
|
85
|
-
if (!anchor) return
|
|
86
|
-
const pill = document.createElement('button')
|
|
87
|
-
pill.id = PILL_ID
|
|
88
|
-
pill.className = 'maxy-pill'
|
|
89
|
-
pill.type = 'button'
|
|
90
|
-
pill.textContent = 'Add to SiteDesk'
|
|
91
|
-
pill.dataset.state = 'idle'
|
|
92
|
-
pill.addEventListener('click', function () { onClick(pill) })
|
|
93
|
-
anchor.prepend(pill)
|
|
94
|
-
console.log(TAG_MOUNT + ' page=thread url=' + location.href)
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
if (document.readyState === 'loading') {
|
|
98
|
-
document.addEventListener('DOMContentLoaded', mount, { once: true })
|
|
99
|
-
} else {
|
|
100
|
-
mount()
|
|
101
|
-
}
|
|
102
|
-
})()
|