sf-intelligence 0.1.1 → 0.1.4
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.js +107 -15
- package/package.json +6 -6
package/dist/index.js
CHANGED
|
@@ -944,7 +944,7 @@ var init_resolve_index = __esm({
|
|
|
944
944
|
});
|
|
945
945
|
|
|
946
946
|
// ../graph/dist/src/resolve.js
|
|
947
|
-
var DEFAULT_LIMIT, MAX_LIMIT, MIN_BASE, MATCHED_FLOOR, NONE_THRESHOLD, EXACT_THRESHOLD, EXACT_COVERAGE, CONTENDER_RATIO, LENGTH_RATIO_FLOOR, SYNONYM_SCORE, POP_K, COVERAGE_EXP, STRONG_ANCHOR,
|
|
947
|
+
var DEFAULT_LIMIT, MAX_LIMIT, MIN_BASE, MATCHED_FLOOR, NONE_THRESHOLD, EXACT_THRESHOLD, EXACT_COVERAGE, CONTENDER_RATIO, LENGTH_RATIO_FLOOR, SYNONYM_SCORE, POP_K, COVERAGE_EXP, STRONG_ANCHOR, TYPE_WEIGHT, typeWeight, scoreToken, rollupKind, buildEvidence, resolveComponents;
|
|
948
948
|
var init_resolve = __esm({
|
|
949
949
|
"../graph/dist/src/resolve.js"() {
|
|
950
950
|
"use strict";
|
|
@@ -964,7 +964,6 @@ var init_resolve = __esm({
|
|
|
964
964
|
POP_K = 0.08;
|
|
965
965
|
COVERAGE_EXP = 0.5;
|
|
966
966
|
STRONG_ANCHOR = 0.9;
|
|
967
|
-
PARENT_MATCH_BONUS = 1.1;
|
|
968
967
|
TYPE_WEIGHT = {
|
|
969
968
|
CustomObject: 1,
|
|
970
969
|
CustomField: 0.95,
|
|
@@ -1092,6 +1091,7 @@ var init_resolve = __esm({
|
|
|
1092
1091
|
const scored = [];
|
|
1093
1092
|
const coverageById = /* @__PURE__ */ new Map();
|
|
1094
1093
|
const wholeExactIds = /* @__PURE__ */ new Set();
|
|
1094
|
+
const parentMatchedIds = /* @__PURE__ */ new Set();
|
|
1095
1095
|
for (const c of pass1) {
|
|
1096
1096
|
const matched = c.perToken.filter((t) => t.score >= MATCHED_FLOOR);
|
|
1097
1097
|
if (matched.length === 0 && !c.wholeExact)
|
|
@@ -1106,13 +1106,15 @@ var init_resolve = __esm({
|
|
|
1106
1106
|
continue;
|
|
1107
1107
|
const type = c.node.type;
|
|
1108
1108
|
const refs = c.node.inbound;
|
|
1109
|
-
const score = base * typeWeight(type) * (1 + POP_K * Math.log10(1 + refs))
|
|
1109
|
+
const score = base * typeWeight(type) * (1 + POP_K * Math.log10(1 + refs));
|
|
1110
1110
|
const kind = c.wholeExact ? "exact" : rollupKind(matched);
|
|
1111
1111
|
const nodeTokenSet = new Set(c.node.tokens);
|
|
1112
1112
|
const matchedNodeTokens = new Set(matched.map((m) => m.matchedToken).filter((t) => nodeTokenSet.has(t)));
|
|
1113
1113
|
coverageById.set(c.node.id, c.wholeExact ? 1 : matchedNodeTokens.size / c.node.tokens.length);
|
|
1114
1114
|
if (c.wholeExact)
|
|
1115
1115
|
wholeExactIds.add(c.node.id);
|
|
1116
|
+
if (c.parentMatched)
|
|
1117
|
+
parentMatchedIds.add(c.node.id);
|
|
1116
1118
|
scored.push({
|
|
1117
1119
|
id: c.node.id,
|
|
1118
1120
|
type,
|
|
@@ -1134,6 +1136,10 @@ var init_resolve = __esm({
|
|
|
1134
1136
|
const tierB = b.base >= EXACT_THRESHOLD ? 0 : 1;
|
|
1135
1137
|
if (tierA !== tierB)
|
|
1136
1138
|
return tierA - tierB;
|
|
1139
|
+
const pmA = parentMatchedIds.has(a.id) ? 0 : 1;
|
|
1140
|
+
const pmB = parentMatchedIds.has(b.id) ? 0 : 1;
|
|
1141
|
+
if (pmA !== pmB)
|
|
1142
|
+
return pmA - pmB;
|
|
1137
1143
|
if (a.score !== b.score)
|
|
1138
1144
|
return b.score - a.score;
|
|
1139
1145
|
return a.id < b.id ? -1 : 1;
|
|
@@ -1145,7 +1151,7 @@ var init_resolve = __esm({
|
|
|
1145
1151
|
if (top === void 0 || bestBase < NONE_THRESHOLD) {
|
|
1146
1152
|
disposition = "none";
|
|
1147
1153
|
} else {
|
|
1148
|
-
const contenders = candidates.filter((c) => c.score >= top.score * CONTENDER_RATIO);
|
|
1154
|
+
const contenders = candidates.filter((c) => c.score >= top.score * CONTENDER_RATIO || parentMatchedIds.has(c.id));
|
|
1149
1155
|
const topCoverage = coverageById.get(top.id) ?? 0;
|
|
1150
1156
|
disposition = top.base >= EXACT_THRESHOLD && contenders.length === 1 && topCoverage >= EXACT_COVERAGE ? "exact" : "ambiguous";
|
|
1151
1157
|
}
|
|
@@ -21353,10 +21359,11 @@ var init_soe_payload_bounds = __esm({
|
|
|
21353
21359
|
SOE_MAX_PAYLOAD_BYTES = 4e4;
|
|
21354
21360
|
KEEP_ALL_AT_OR_BELOW = 4;
|
|
21355
21361
|
sizeOf = (payload) => Buffer.byteLength(JSON.stringify(payload), "utf8");
|
|
21356
|
-
enforceSoeByteBudget = (payload,
|
|
21362
|
+
enforceSoeByteBudget = (payload, containers) => {
|
|
21357
21363
|
if (sizeOf(payload) <= SOE_MAX_PAYLOAD_BYTES) {
|
|
21358
|
-
return { truncated: false, actionsOmitted: 0 };
|
|
21364
|
+
return { truncated: false, actionsOmitted: 0, conditionalsTrimmed: 0, stepsOmitted: 0 };
|
|
21359
21365
|
}
|
|
21366
|
+
const steps = containers.flat();
|
|
21360
21367
|
let totalOmitted = 0;
|
|
21361
21368
|
const trimTo = (step3, keep) => {
|
|
21362
21369
|
if (keep >= step3.actions.length)
|
|
@@ -21395,9 +21402,76 @@ var init_soe_payload_bounds = __esm({
|
|
|
21395
21402
|
break;
|
|
21396
21403
|
trimTo(target, Math.floor(target.actions.length / 2));
|
|
21397
21404
|
}
|
|
21398
|
-
|
|
21405
|
+
let conditionalsTrimmed = 0;
|
|
21406
|
+
for (let guard = 0; guard < 1e5; guard += 1) {
|
|
21407
|
+
if (sizeOf(payload) <= SOE_MAX_PAYLOAD_BYTES)
|
|
21408
|
+
break;
|
|
21409
|
+
let target;
|
|
21410
|
+
let targetBytes = 0;
|
|
21411
|
+
for (const s of steps) {
|
|
21412
|
+
const cond = s.conditional;
|
|
21413
|
+
if (cond === void 0 || s.conditionalTruncated)
|
|
21414
|
+
continue;
|
|
21415
|
+
if (cond.expression === "" && cond.fieldRefs.length === 0)
|
|
21416
|
+
continue;
|
|
21417
|
+
const b = Buffer.byteLength(JSON.stringify(cond), "utf8");
|
|
21418
|
+
if (target === void 0 || b > targetBytes) {
|
|
21419
|
+
target = s;
|
|
21420
|
+
targetBytes = b;
|
|
21421
|
+
}
|
|
21422
|
+
}
|
|
21423
|
+
if (target === void 0)
|
|
21424
|
+
break;
|
|
21425
|
+
target.conditional = {
|
|
21426
|
+
conditionContextId: target.conditional.conditionContextId,
|
|
21427
|
+
expression: "",
|
|
21428
|
+
fieldRefs: []
|
|
21429
|
+
};
|
|
21430
|
+
target.conditionalTruncated = true;
|
|
21431
|
+
conditionalsTrimmed += 1;
|
|
21432
|
+
}
|
|
21433
|
+
let stepsOmitted = 0;
|
|
21434
|
+
for (let guard = 0; guard < 1e6; guard += 1) {
|
|
21435
|
+
if (sizeOf(payload) <= SOE_MAX_PAYLOAD_BYTES)
|
|
21436
|
+
break;
|
|
21437
|
+
let target;
|
|
21438
|
+
let targetBytes = 0;
|
|
21439
|
+
for (const c of containers) {
|
|
21440
|
+
if (c.length <= 1)
|
|
21441
|
+
continue;
|
|
21442
|
+
const b = Buffer.byteLength(JSON.stringify(c), "utf8");
|
|
21443
|
+
if (target === void 0 || b > targetBytes) {
|
|
21444
|
+
target = c;
|
|
21445
|
+
targetBytes = b;
|
|
21446
|
+
}
|
|
21447
|
+
}
|
|
21448
|
+
if (target === void 0)
|
|
21449
|
+
break;
|
|
21450
|
+
target.pop();
|
|
21451
|
+
stepsOmitted += 1;
|
|
21452
|
+
}
|
|
21453
|
+
return {
|
|
21454
|
+
truncated: totalOmitted > 0 || conditionalsTrimmed > 0 || stepsOmitted > 0,
|
|
21455
|
+
actionsOmitted: totalOmitted,
|
|
21456
|
+
conditionalsTrimmed,
|
|
21457
|
+
stepsOmitted
|
|
21458
|
+
};
|
|
21459
|
+
};
|
|
21460
|
+
soeTruncationNote = (result) => {
|
|
21461
|
+
const budgetKb = Math.round(SOE_MAX_PAYLOAD_BYTES / 1e3);
|
|
21462
|
+
const parts = [];
|
|
21463
|
+
if (result.actionsOmitted > 0) {
|
|
21464
|
+
parts.push(`${result.actionsOmitted} per-step action edge(s) across the heaviest steps were omitted (see each step's \`actionsOmitted\`)`);
|
|
21465
|
+
}
|
|
21466
|
+
if (result.conditionalsTrimmed > 0) {
|
|
21467
|
+
parts.push(`${result.conditionalsTrimmed} step condition(s) had their expression/fieldRefs dropped \u2014 the \`conditionContextId\` remains, fetch it with \`get_component\` for the full condition (see each step's \`conditionalTruncated\`)`);
|
|
21468
|
+
}
|
|
21469
|
+
if (result.stepsOmitted > 0) {
|
|
21470
|
+
parts.push(`${result.stepsOmitted} trailing step(s) were dropped to fit (the tail-most async/post-save steps; \`summary.totalSteps\` still reports the true total) \u2014 query a single event with \`what_happens_on_save\` to see them all`);
|
|
21471
|
+
}
|
|
21472
|
+
const lead = result.stepsOmitted > 0 ? `Response trimmed to fit the ~${budgetKb} KB MCP response budget` : `Response trimmed to fit the ~${budgetKb} KB MCP response budget: every save-order STEP is present and in order, but`;
|
|
21473
|
+
return `${lead} ${parts.join("; ")}. Query a single object/event for full detail.`;
|
|
21399
21474
|
};
|
|
21400
|
-
soeTruncationNote = (n) => `Response trimmed to fit the ~${Math.round(SOE_MAX_PAYLOAD_BYTES / 1e3)} KB MCP response budget: every save-order STEP is present and in order, but ${n} per-step action edge(s) across the heaviest steps were omitted (see each step's \`actionsOmitted\`). Query a single object/event or use \`get_edges\` on a specific step's component for its full action list.`;
|
|
21401
21475
|
}
|
|
21402
21476
|
});
|
|
21403
21477
|
|
|
@@ -21764,11 +21838,11 @@ var init_order_of_execution = __esm({
|
|
|
21764
21838
|
byEvent,
|
|
21765
21839
|
disclosure: composeSoeDisclosure(DISCLOSURE6, objectModeled)
|
|
21766
21840
|
};
|
|
21767
|
-
const
|
|
21768
|
-
const budget = enforceSoeByteBudget(data,
|
|
21841
|
+
const containers = SOE_EVENTS.map((event) => byEvent[event].soe);
|
|
21842
|
+
const budget = enforceSoeByteBudget(data, containers);
|
|
21769
21843
|
if (budget.truncated) {
|
|
21770
21844
|
data.truncated = true;
|
|
21771
|
-
data.disclosure = `${data.disclosure} ${soeTruncationNote(budget
|
|
21845
|
+
data.disclosure = `${data.disclosure} ${soeTruncationNote(budget)}`;
|
|
21772
21846
|
}
|
|
21773
21847
|
return ok({
|
|
21774
21848
|
data,
|
|
@@ -26611,10 +26685,10 @@ var init_what_happens_on_save = __esm({
|
|
|
26611
26685
|
},
|
|
26612
26686
|
disclosure: composeSoeDisclosure(DISCLOSURE7, objectModeled)
|
|
26613
26687
|
};
|
|
26614
|
-
const budget = enforceSoeByteBudget(data, soe);
|
|
26688
|
+
const budget = enforceSoeByteBudget(data, [soe]);
|
|
26615
26689
|
if (budget.truncated) {
|
|
26616
26690
|
data.truncated = true;
|
|
26617
|
-
data.disclosure = `${data.disclosure} ${soeTruncationNote(budget
|
|
26691
|
+
data.disclosure = `${data.disclosure} ${soeTruncationNote(budget)}`;
|
|
26618
26692
|
}
|
|
26619
26693
|
return ok({
|
|
26620
26694
|
data,
|
|
@@ -26627,6 +26701,23 @@ var init_what_happens_on_save = __esm({
|
|
|
26627
26701
|
}
|
|
26628
26702
|
});
|
|
26629
26703
|
|
|
26704
|
+
// ../mcp/dist/src/tools/phantom-node.js
|
|
26705
|
+
var phantomAwareNotFoundMessage;
|
|
26706
|
+
var init_phantom_node = __esm({
|
|
26707
|
+
"../mcp/dist/src/tools/phantom-node.js"() {
|
|
26708
|
+
"use strict";
|
|
26709
|
+
init_src();
|
|
26710
|
+
phantomAwareNotFoundMessage = async (ctx, id, kindLabel) => {
|
|
26711
|
+
const inbound = await listEdges(ctx.graph, id, { direction: "in" });
|
|
26712
|
+
const refs = inbound.ok ? inbound.value.length : 0;
|
|
26713
|
+
if (refs === 0) {
|
|
26714
|
+
return `no ${kindLabel} with id ${id}`;
|
|
26715
|
+
}
|
|
26716
|
+
return `\`${id}\` is referenced by ${refs} other component(s) in this org (e.g. code, tests, or permission grants) but its own ${kindLabel} definition was never retrieved into the vault \u2014 typically a managed-package component or one outside the retrieve scope. Run \`sfi refresh\` if it should be retrievable; otherwise treat it as external.`;
|
|
26717
|
+
};
|
|
26718
|
+
}
|
|
26719
|
+
});
|
|
26720
|
+
|
|
26630
26721
|
// ../mcp/dist/src/tools/what-if-change-method-signature.js
|
|
26631
26722
|
import { z as z104 } from "zod";
|
|
26632
26723
|
var APEX_CLASS_PREFIX9, DISCLOSURE8, whatIfChangeMethodSignatureInputSchema, readMethodName, isTestClass8, buildExplanation2, classifyCaller, aggregateVerdict4, compareImpacts, compareIds, collectCallers, collectCoveringTests, whatIfChangeMethodSignatureHandler;
|
|
@@ -26637,6 +26728,7 @@ var init_what_if_change_method_signature = __esm({
|
|
|
26637
26728
|
init_src();
|
|
26638
26729
|
init_coerce_id();
|
|
26639
26730
|
init_coverage_trust();
|
|
26731
|
+
init_phantom_node();
|
|
26640
26732
|
APEX_CLASS_PREFIX9 = "ApexClass:";
|
|
26641
26733
|
DISCLOSURE8 = "callers identified via the v1.4 apex-scanner are at heuristic confidence; dynamic dispatch via Type.forName + invoke is invisible. Test classes are identified by @isTest + naming convention (className + 'Test' suffix) and by coversTest edges; a test class that doesn't follow the naming convention and doesn't carry a @TestVisible-tagged covering reference may be missed.";
|
|
26642
26734
|
whatIfChangeMethodSignatureInputSchema = z104.object({
|
|
@@ -26776,7 +26868,7 @@ var init_what_if_change_method_signature = __esm({
|
|
|
26776
26868
|
if (nodeResult.value === null) {
|
|
26777
26869
|
return err({
|
|
26778
26870
|
kind: "component-not-found",
|
|
26779
|
-
message:
|
|
26871
|
+
message: await phantomAwareNotFoundMessage(ctx, classId, "ApexClass"),
|
|
26780
26872
|
path: classId
|
|
26781
26873
|
});
|
|
26782
26874
|
}
|
|
@@ -46748,7 +46840,7 @@ var registerStatusCommand = (program) => {
|
|
|
46748
46840
|
// dist/src/program.js
|
|
46749
46841
|
var readVersion = () => {
|
|
46750
46842
|
if (true)
|
|
46751
|
-
return "0.1.
|
|
46843
|
+
return "0.1.4";
|
|
46752
46844
|
const pkgUrl = new URL("../../package.json", import.meta.url);
|
|
46753
46845
|
const raw = readFileSync2(fileURLToPath(pkgUrl), "utf8");
|
|
46754
46846
|
const parsed = JSON.parse(raw);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "sf-intelligence",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.4",
|
|
4
4
|
"description": "Offline-first, MCP-first knowledge base for a Salesforce org. Ask about your org's metadata, dependencies, permissions, and automation — grounded in real retrieved metadata. Ships the sfi CLI and an MCP server.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"homepage": "https://github.com/PranavNagrecha/Salesforce-Intelligence",
|
|
@@ -52,14 +52,14 @@
|
|
|
52
52
|
"devDependencies": {
|
|
53
53
|
"esbuild": "^0.28.0",
|
|
54
54
|
"vitest": "^1.6.0",
|
|
55
|
-
"@sf-intelligence/mcp": "0.1.0",
|
|
56
|
-
"@sf-intelligence/core": "0.1.0",
|
|
57
|
-
"@sf-intelligence/contracts": "0.1.0",
|
|
58
|
-
"@sf-intelligence/patterns": "0.1.0",
|
|
59
55
|
"@sf-intelligence/extractors": "0.1.0",
|
|
60
|
-
"@sf-intelligence/renderers": "0.1.0",
|
|
61
56
|
"@sf-intelligence/graph": "0.1.0",
|
|
57
|
+
"@sf-intelligence/patterns": "0.1.0",
|
|
58
|
+
"@sf-intelligence/core": "0.1.0",
|
|
62
59
|
"@sf-intelligence/vault": "0.1.0",
|
|
60
|
+
"@sf-intelligence/contracts": "0.1.0",
|
|
61
|
+
"@sf-intelligence/mcp": "0.1.0",
|
|
62
|
+
"@sf-intelligence/renderers": "0.1.0",
|
|
63
63
|
"@sf-intelligence/tooling-api": "0.1.0"
|
|
64
64
|
},
|
|
65
65
|
"scripts": {
|