fullstackgtm 0.15.0 → 0.17.0
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/CHANGELOG.md +84 -0
- package/dist/cli.js +240 -2
- package/dist/connectors/hubspot.js +1 -1
- package/dist/index.d.ts +3 -0
- package/dist/index.js +3 -0
- package/dist/llm.d.ts +7 -0
- package/dist/llm.js +7 -1
- package/dist/market.d.ts +166 -0
- package/dist/market.js +395 -0
- package/dist/marketClassify.d.ts +49 -0
- package/dist/marketClassify.js +201 -0
- package/dist/marketReport.d.ts +3 -0
- package/dist/marketReport.js +233 -0
- package/dist/mcp.js +45 -0
- package/dist/resolve.js +36 -17
- package/dist/types.d.ts +1 -1
- package/package.json +1 -1
- package/src/cli.ts +264 -3
- package/src/connectors/hubspot.ts +1 -1
- package/src/index.ts +38 -0
- package/src/llm.ts +7 -1
- package/src/market.ts +559 -0
- package/src/marketClassify.ts +286 -0
- package/src/marketReport.ts +272 -0
- package/src/mcp.ts +65 -0
- package/src/resolve.ts +39 -19
- package/src/types.ts +1 -0
package/src/resolve.ts
CHANGED
|
@@ -118,30 +118,50 @@ function resolveDeal(snapshot: CanonicalGtmSnapshot, c: ResolveCandidate): Resol
|
|
|
118
118
|
if (!c.name) {
|
|
119
119
|
return { ...base, verdict: "ambiguous", matches: [], reason: "Supply --name (and ideally --account-id) to resolve a deal." };
|
|
120
120
|
}
|
|
121
|
-
const
|
|
121
|
+
const nameKey = normalizeName(c.name);
|
|
122
122
|
const open = snapshot.deals.filter((d) => d.isClosed !== true && d.isWon !== true);
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
123
|
+
if (c.accountId) {
|
|
124
|
+
const key = `${c.accountId}:${nameKey}`;
|
|
125
|
+
const matches = open
|
|
126
|
+
.filter((d) => `${d.accountId ?? "unlinked"}:${normalizeName(d.name)}` === key)
|
|
127
|
+
.map((d) => match(d.id, d.name, "deal_key", `open deal with the same name on account ${c.accountId}`));
|
|
128
|
+
if (matches.length > 0) {
|
|
129
|
+
return {
|
|
130
|
+
...base,
|
|
131
|
+
verdict: "exists",
|
|
132
|
+
matches,
|
|
133
|
+
reason: `${matches.length} open deal(s) already match "${c.name}" on account ${c.accountId} — creating another would double-count pipeline. Update the existing deal.`,
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
const closedSameName = snapshot.deals.filter(
|
|
137
|
+
(d) =>
|
|
138
|
+
(d.isClosed === true || d.isWon === true) &&
|
|
139
|
+
d.accountId === c.accountId &&
|
|
140
|
+
normalizeName(d.name) === nameKey,
|
|
141
|
+
);
|
|
142
|
+
return {
|
|
143
|
+
...base,
|
|
144
|
+
verdict: "safe_to_create",
|
|
145
|
+
matches: [],
|
|
146
|
+
reason: closedSameName.length > 0
|
|
147
|
+
? `No open deal matches on account ${c.accountId}; ${closedSameName.length} closed deal(s) on it share the name (a re-open/renewal may be intended). Safe to create.`
|
|
148
|
+
: `No open deal matches "${c.name}" on account ${c.accountId}. Safe to create.`,
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
// No account scope: name-only matches across ALL open deals are ambiguous,
|
|
152
|
+
// never safe — a gate that ignores name collisions protects nobody.
|
|
153
|
+
const sameName = open
|
|
154
|
+
.filter((d) => normalizeName(d.name) === nameKey)
|
|
155
|
+
.map((d) => match(d.id, d.name, "name", `open deal with the same name on ${d.accountId ? `account ${d.accountId}` : "no account"}`));
|
|
156
|
+
if (sameName.length > 0) {
|
|
127
157
|
return {
|
|
128
158
|
...base,
|
|
129
|
-
verdict: "
|
|
130
|
-
matches,
|
|
131
|
-
reason: `${
|
|
159
|
+
verdict: "ambiguous",
|
|
160
|
+
matches: sameName,
|
|
161
|
+
reason: `${sameName.length} open deal(s) named "${c.name}" exist (no --account-id supplied to scope the check). Confirm before creating — supply --account-id to resolve definitively.`,
|
|
132
162
|
};
|
|
133
163
|
}
|
|
134
|
-
|
|
135
|
-
(d) => (d.isClosed === true || d.isWon === true) && normalizeName(d.name) === normalizeName(c.name!),
|
|
136
|
-
);
|
|
137
|
-
return {
|
|
138
|
-
...base,
|
|
139
|
-
verdict: "safe_to_create",
|
|
140
|
-
matches: [],
|
|
141
|
-
reason: closedSameName.length > 0
|
|
142
|
-
? `No open deal matches; ${closedSameName.length} closed deal(s) share the name (a re-open/renewal may be intended). Safe to create.`
|
|
143
|
-
: `No open deal matches "${c.name}". Safe to create.`,
|
|
144
|
-
};
|
|
164
|
+
return { ...base, verdict: "safe_to_create", matches: [], reason: `No open deal named "${c.name}" anywhere. Safe to create.` };
|
|
145
165
|
}
|
|
146
166
|
|
|
147
167
|
function contactName(row: { firstName?: string; lastName?: string }) {
|