sproutkit-code 1.16.0 → 1.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/dist/index.js +102 -30
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -121,6 +121,49 @@ var require_runtime = __commonJS({
|
|
|
121
121
|
}
|
|
122
122
|
});
|
|
123
123
|
|
|
124
|
+
// ../desktop/dist/main/lib/outreach-template.js
|
|
125
|
+
var require_outreach_template = __commonJS({
|
|
126
|
+
"../desktop/dist/main/lib/outreach-template.js"(exports2) {
|
|
127
|
+
"use strict";
|
|
128
|
+
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
129
|
+
exports2.PREVIOUS_DEFAULT_TEMPLATE = exports2.OUTREACH_TEMPLATE = void 0;
|
|
130
|
+
exports2.OUTREACH_TEMPLATE = `Hello,
|
|
131
|
+
|
|
132
|
+
I came across {name} on Google and noticed you don't have a website yet, so I put together a free demo to show what one could look like:
|
|
133
|
+
|
|
134
|
+
{site_url}
|
|
135
|
+
|
|
136
|
+
It's built from your real reviews and photos.
|
|
137
|
+
|
|
138
|
+
I also recorded a short video walking you through it: {video}
|
|
139
|
+
|
|
140
|
+
And I've set up a virtual front desk for {name}. It answers your calls when you can't get to the phone, knows your services, prices and opening hours, and texts you a summary of every call. Try it the way a customer would \u2014 ask if you're open on Saturday, or what something costs:
|
|
141
|
+
|
|
142
|
+
{front_desk}
|
|
143
|
+
|
|
144
|
+
If you like the website, I can put it live on your own domain for a one-off fee of \xA3199, with no monthly charges. The front desk can be switched on for your number whenever you're ready.
|
|
145
|
+
|
|
146
|
+
Would you be open to a quick chat this week?
|
|
147
|
+
|
|
148
|
+
Best regards
|
|
149
|
+
|
|
150
|
+
If you'd rather not hear from me again, just reply and let me know.`;
|
|
151
|
+
exports2.PREVIOUS_DEFAULT_TEMPLATE = `Hello,
|
|
152
|
+
|
|
153
|
+
I came across {name} on Google and noticed you don't have a website yet, so I put together a free demo to show what one could look like:
|
|
154
|
+
|
|
155
|
+
{site_url}
|
|
156
|
+
|
|
157
|
+
It's built from your real reviews and photos. If you like it, I can put it live on your own domain with your details for a one-off fee of \xA3199 \u2014 no monthly charges.
|
|
158
|
+
|
|
159
|
+
Would you be open to a quick chat this week?
|
|
160
|
+
|
|
161
|
+
Best regards
|
|
162
|
+
|
|
163
|
+
If you'd rather not hear from me again, just reply and let me know.`;
|
|
164
|
+
}
|
|
165
|
+
});
|
|
166
|
+
|
|
124
167
|
// ../desktop/dist/main/db.js
|
|
125
168
|
var require_db = __commonJS({
|
|
126
169
|
"../desktop/dist/main/db.js"(exports2) {
|
|
@@ -131,6 +174,7 @@ var require_db = __commonJS({
|
|
|
131
174
|
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
132
175
|
exports2.databasePath = databasePath;
|
|
133
176
|
exports2.initDatabase = initDatabase2;
|
|
177
|
+
exports2.upgradeDefaultTemplate = upgradeDefaultTemplate;
|
|
134
178
|
exports2.getDb = getDb2;
|
|
135
179
|
var node_sqlite3_wasm_1 = require("node-sqlite3-wasm");
|
|
136
180
|
var path_1 = __importDefault(require("path"));
|
|
@@ -187,6 +231,30 @@ var require_db = __commonJS({
|
|
|
187
231
|
} catch {
|
|
188
232
|
}
|
|
189
233
|
db2.exec(`
|
|
234
|
+
CREATE TABLE IF NOT EXISTS chat_threads (
|
|
235
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
236
|
+
title TEXT,
|
|
237
|
+
session_id TEXT,
|
|
238
|
+
created_at TEXT DEFAULT (datetime('now')),
|
|
239
|
+
updated_at TEXT DEFAULT (datetime('now'))
|
|
240
|
+
);
|
|
241
|
+
`);
|
|
242
|
+
try {
|
|
243
|
+
db2.exec("ALTER TABLE chat_messages ADD COLUMN thread_id INTEGER");
|
|
244
|
+
} catch {
|
|
245
|
+
}
|
|
246
|
+
{
|
|
247
|
+
const orphan = db2.get("SELECT COUNT(*) AS n, MIN(created_at) AS first, MAX(created_at) AS last FROM chat_messages WHERE thread_id IS NULL", []);
|
|
248
|
+
if (orphan && orphan.n > 0) {
|
|
249
|
+
db2.run("INSERT INTO chat_threads (title, created_at, updated_at) VALUES ('Earlier chat', ?, ?)", [
|
|
250
|
+
orphan.first ?? (/* @__PURE__ */ new Date()).toISOString(),
|
|
251
|
+
orphan.last ?? (/* @__PURE__ */ new Date()).toISOString()
|
|
252
|
+
]);
|
|
253
|
+
const t = db2.get("SELECT MAX(id) AS id FROM chat_threads", []);
|
|
254
|
+
db2.run("UPDATE chat_messages SET thread_id = ? WHERE thread_id IS NULL", [t.id]);
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
db2.exec(`
|
|
190
258
|
CREATE TABLE IF NOT EXISTS invoices (
|
|
191
259
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
192
260
|
number TEXT UNIQUE NOT NULL,
|
|
@@ -426,6 +494,16 @@ var require_db = __commonJS({
|
|
|
426
494
|
}
|
|
427
495
|
}
|
|
428
496
|
}
|
|
497
|
+
function upgradeDefaultTemplate() {
|
|
498
|
+
try {
|
|
499
|
+
const t = require_outreach_template();
|
|
500
|
+
db2.run("UPDATE settings SET value = ? WHERE key = 'outreach_template' AND value = ?", [
|
|
501
|
+
t.OUTREACH_TEMPLATE,
|
|
502
|
+
t.PREVIOUS_DEFAULT_TEMPLATE
|
|
503
|
+
]);
|
|
504
|
+
} catch {
|
|
505
|
+
}
|
|
506
|
+
}
|
|
429
507
|
function getDb2() {
|
|
430
508
|
return db2;
|
|
431
509
|
}
|
|
@@ -84500,7 +84578,7 @@ var require_pitch_text = __commonJS({
|
|
|
84500
84578
|
exports2.prettyNumber = prettyNumber;
|
|
84501
84579
|
function withVideo(message, videoUrl) {
|
|
84502
84580
|
if (!videoUrl)
|
|
84503
|
-
return message
|
|
84581
|
+
return omit(message, /\{video\}/, /\bvideo\b/i);
|
|
84504
84582
|
if (message.includes("{video}"))
|
|
84505
84583
|
return message.replace(/\{video\}/g, videoUrl);
|
|
84506
84584
|
const line = `I also recorded a short video walking you through it: ${videoUrl}`;
|
|
@@ -84517,7 +84595,7 @@ ${line}`;
|
|
|
84517
84595
|
void demoNumber;
|
|
84518
84596
|
message = message.replace(/\{front_desk\}/g, "{receptionist}");
|
|
84519
84597
|
if (!url)
|
|
84520
|
-
return message
|
|
84598
|
+
return omit(message, /\{receptionist\}/, /front desk|receptionist/i);
|
|
84521
84599
|
if (message.includes("{receptionist}"))
|
|
84522
84600
|
return message.replace(/\{receptionist\}/g, url);
|
|
84523
84601
|
const line = `I've also set up a virtual front desk for ${businessName ?? "you"}: it answers your calls when you can't${chatOn ? ", and questions on your website" : ""}, 24/7. You can try it here: ${url}`;
|
|
@@ -84544,6 +84622,23 @@ ${line}`;
|
|
|
84544
84622
|
return `(${d.slice(2, 5)}) ${d.slice(5, 8)}-${d.slice(8)}`;
|
|
84545
84623
|
return e164;
|
|
84546
84624
|
}
|
|
84625
|
+
function omit(message, placeholder, mention) {
|
|
84626
|
+
const blocks = message.split(/\n[ \t]*\n/);
|
|
84627
|
+
const drop = /* @__PURE__ */ new Set();
|
|
84628
|
+
blocks.forEach((b, i) => {
|
|
84629
|
+
if (!placeholder.test(b))
|
|
84630
|
+
return;
|
|
84631
|
+
const rest = b.replace(placeholder, "").trim();
|
|
84632
|
+
if (!rest || /:$/.test(rest)) {
|
|
84633
|
+
drop.add(i);
|
|
84634
|
+
if (!rest && i > 0 && /:\s*$/.test(blocks[i - 1]))
|
|
84635
|
+
drop.add(i - 1);
|
|
84636
|
+
} else {
|
|
84637
|
+
blocks[i] = b.split("\n").filter((line) => !placeholder.test(line)).join("\n");
|
|
84638
|
+
}
|
|
84639
|
+
});
|
|
84640
|
+
return blocks.filter((_, i) => !drop.has(i)).map((b) => b.split(/(?<=[.!?])\s+/).filter((sent) => !mention.test(sent)).join(" ") || "").filter((b) => b.trim()).join("\n\n");
|
|
84641
|
+
}
|
|
84547
84642
|
}
|
|
84548
84643
|
});
|
|
84549
84644
|
|
|
@@ -97737,6 +97832,7 @@ var require_chat_tools = __commonJS({
|
|
|
97737
97832
|
var lead_search_1 = require_lead_search();
|
|
97738
97833
|
var ai_search_1 = require_ai_search();
|
|
97739
97834
|
var pitch_text_1 = require_pitch_text();
|
|
97835
|
+
var outreach_template_1 = require_outreach_template();
|
|
97740
97836
|
var receptionist_1 = require_receptionist();
|
|
97741
97837
|
var places_1 = require_places();
|
|
97742
97838
|
var booking_detect_1 = require_booking_detect();
|
|
@@ -98242,19 +98338,7 @@ Want it live on your own domain?`;
|
|
|
98242
98338
|
}
|
|
98243
98339
|
function outreachTemplate(db2) {
|
|
98244
98340
|
const row = db2.get("SELECT value FROM settings WHERE key = ?", ["outreach_template"]);
|
|
98245
|
-
return row?.value ??
|
|
98246
|
-
|
|
98247
|
-
I came across {name} on Google and noticed you don't have a website yet, so I put together a free demo to show what one could look like:
|
|
98248
|
-
|
|
98249
|
-
{site_url}
|
|
98250
|
-
|
|
98251
|
-
It's built from your real reviews and photos. If you like it, I can put it live on your own domain with your details for a one-off fee of \xA3199 \u2014 no monthly charges.
|
|
98252
|
-
|
|
98253
|
-
Would you be open to a quick chat this week?
|
|
98254
|
-
|
|
98255
|
-
Best regards
|
|
98256
|
-
|
|
98257
|
-
If you'd rather not hear from me again, just reply and let me know.`;
|
|
98341
|
+
return row?.value ?? outreach_template_1.OUTREACH_TEMPLATE;
|
|
98258
98342
|
}
|
|
98259
98343
|
function normaliseChannel(value) {
|
|
98260
98344
|
switch (String(value ?? "").toLowerCase()) {
|
|
@@ -98416,19 +98500,7 @@ If you'd rather not hear from me again, just reply and let me know.`;
|
|
|
98416
98500
|
const phone = (lead.phone ?? "").replace(/[^\d+]/g, "");
|
|
98417
98501
|
const e164 = phone.startsWith("+") ? phone : phone.startsWith("0") ? `+44${phone.slice(1)}` : phone;
|
|
98418
98502
|
const tplRow = db2.get("SELECT value FROM settings WHERE key = ?", ["outreach_template"]);
|
|
98419
|
-
const template = tplRow?.value ??
|
|
98420
|
-
|
|
98421
|
-
I came across {name} on Google and noticed you don't have a website yet, so I put together a free demo to show what one could look like:
|
|
98422
|
-
|
|
98423
|
-
{site_url}
|
|
98424
|
-
|
|
98425
|
-
It's built from your real reviews and photos. If you like it, I can put it live on your own domain with your details for a one-off fee of \xA3199 \u2014 no monthly charges.
|
|
98426
|
-
|
|
98427
|
-
Would you be open to a quick chat this week?
|
|
98428
|
-
|
|
98429
|
-
Best regards
|
|
98430
|
-
|
|
98431
|
-
If you'd rather not hear from me again, just reply and let me know.`;
|
|
98503
|
+
const template = tplRow?.value ?? outreach_template_1.OUTREACH_TEMPLATE;
|
|
98432
98504
|
const body = input.message ?? template.replace(/\{name\}/g, lead.name).replace(/\{site_url\}/g, lead.site_url ?? "");
|
|
98433
98505
|
const url = `https://wa.me/${e164.replace(/^\+/, "")}?text=${encodeURIComponent(body)}`;
|
|
98434
98506
|
return { url, message: body, phone: e164 };
|
|
@@ -98473,7 +98545,7 @@ If you'd rather not hear from me again, just reply and let me know.`;
|
|
|
98473
98545
|
}
|
|
98474
98546
|
let receptionistUrl = r.receptionist_url ?? null;
|
|
98475
98547
|
let receptionistLine = r.receptionist_line ?? null;
|
|
98476
|
-
if (!isBookingLead && !receptionistUrl && r.site_url && getDecryptedSetting("receptionist_auto")
|
|
98548
|
+
if (!isBookingLead && !receptionistUrl && r.site_url && getDecryptedSetting("receptionist_auto") !== "0") {
|
|
98477
98549
|
ctx.emitProgress?.({ channel: "outreach:progress", payload: { msg: `Setting up Front Desk for ${r.name}\u2026` } });
|
|
98478
98550
|
try {
|
|
98479
98551
|
const t = await (0, receptionist_1.createTrial)(r.id);
|
|
@@ -100494,7 +100566,7 @@ var require_package2 = __commonJS({
|
|
|
100494
100566
|
"package.json"(exports2, module2) {
|
|
100495
100567
|
module2.exports = {
|
|
100496
100568
|
name: "sproutkit-code",
|
|
100497
|
-
version: "1.
|
|
100569
|
+
version: "1.17.0",
|
|
100498
100570
|
description: "Sproutkit in your terminal \u2014 find leads, build sites, run outreach, all via chat.",
|
|
100499
100571
|
bin: {
|
|
100500
100572
|
sproutkit: "./dist/index.js"
|