@hailer/mcp 1.3.23 → 1.3.32
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/.claude/skills/hailer-docs-search/SKILL.md +75 -0
- package/.opencode/package-lock.json +117 -0
- package/CLAUDE.md +1 -0
- package/dist/bot/bot.d.ts.map +1 -1
- package/dist/bot/bot.js +21 -1
- package/dist/bot/bot.js.map +1 -1
- package/dist/bot/services/helper-prompt.d.ts +1 -1
- package/dist/bot/services/helper-prompt.d.ts.map +1 -1
- package/dist/bot/services/helper-prompt.js +4 -6
- package/dist/bot/services/helper-prompt.js.map +1 -1
- package/dist/bot/services/message-formatter.d.ts.map +1 -1
- package/dist/bot/services/message-formatter.js +2 -1
- package/dist/bot/services/message-formatter.js.map +1 -1
- package/dist/bot/services/system-prompt.d.ts.map +1 -1
- package/dist/bot/services/system-prompt.js +21 -34
- package/dist/bot/services/system-prompt.js.map +1 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +6 -0
- package/dist/cli.js.map +1 -1
- package/dist/config.d.ts +1 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +5 -0
- package/dist/config.js.map +1 -1
- package/dist/lib/object-id.d.ts +9 -0
- package/dist/lib/object-id.d.ts.map +1 -0
- package/dist/lib/object-id.js +15 -0
- package/dist/lib/object-id.js.map +1 -0
- package/dist/mcp/hailer-rpc.d.ts +3 -0
- package/dist/mcp/hailer-rpc.d.ts.map +1 -1
- package/dist/mcp/hailer-rpc.js +7 -0
- package/dist/mcp/hailer-rpc.js.map +1 -1
- package/dist/mcp/tool-profiles.d.ts +1 -0
- package/dist/mcp/tool-profiles.d.ts.map +1 -1
- package/dist/mcp/tool-profiles.js +21 -4
- package/dist/mcp/tool-profiles.js.map +1 -1
- package/dist/mcp/tools/aliases.d.ts.map +1 -1
- package/dist/mcp/tools/aliases.js +14 -6
- package/dist/mcp/tools/aliases.js.map +1 -1
- package/dist/mcp/tools/app-marketplace.d.ts.map +1 -1
- package/dist/mcp/tools/app-marketplace.js +2 -1
- package/dist/mcp/tools/app-marketplace.js.map +1 -1
- package/dist/mcp/tools/docs.d.ts +20 -0
- package/dist/mcp/tools/docs.d.ts.map +1 -0
- package/dist/mcp/tools/docs.js +87 -0
- package/dist/mcp/tools/docs.js.map +1 -0
- package/dist/mcp/tools/function-fields.d.ts +17 -0
- package/dist/mcp/tools/function-fields.d.ts.map +1 -0
- package/dist/mcp/tools/function-fields.js +717 -0
- package/dist/mcp/tools/function-fields.js.map +1 -0
- package/dist/mcp/tools/index.d.ts.map +1 -1
- package/dist/mcp/tools/index.js +4 -0
- package/dist/mcp/tools/index.js.map +1 -1
- package/dist/mcp/tools/workflow.d.ts +0 -1
- package/dist/mcp/tools/workflow.d.ts.map +1 -1
- package/dist/mcp/tools/workflow.js +1 -190
- package/dist/mcp/tools/workflow.js.map +1 -1
- package/dist/public-chat/graduate.d.ts +5 -4
- package/dist/public-chat/graduate.d.ts.map +1 -1
- package/dist/public-chat/graduate.js +226 -76
- package/dist/public-chat/graduate.js.map +1 -1
- package/dist/public-chat/handler.d.ts.map +1 -1
- package/dist/public-chat/handler.js +10 -2
- package/dist/public-chat/handler.js.map +1 -1
- package/dist/public-chat/index.d.ts.map +1 -1
- package/dist/public-chat/index.js +12 -1
- package/dist/public-chat/index.js.map +1 -1
- package/dist/public-chat/session-store.d.ts +22 -1
- package/dist/public-chat/session-store.d.ts.map +1 -1
- package/dist/public-chat/session-store.js +56 -2
- package/dist/public-chat/session-store.js.map +1 -1
- package/dist/public-chat/system-prompt.d.ts +1 -1
- package/dist/public-chat/system-prompt.d.ts.map +1 -1
- package/dist/public-chat/system-prompt.js +161 -84
- package/dist/public-chat/system-prompt.js.map +1 -1
- package/package.json +1 -1
|
@@ -14,6 +14,7 @@ exports.PUBLIC_CHAT_AUTHORIZE_ROUTE = exports.PUBLIC_CHAT_HISTORY_ROUTE = export
|
|
|
14
14
|
exports.registerPublicChatRoutes = registerPublicChatRoutes;
|
|
15
15
|
const express_1 = __importDefault(require("express"));
|
|
16
16
|
const logger_1 = require("../lib/logger");
|
|
17
|
+
const config_1 = require("../config");
|
|
17
18
|
const handler_1 = require("./handler");
|
|
18
19
|
const system_prompt_1 = require("./system-prompt");
|
|
19
20
|
const session_store_1 = require("./session-store");
|
|
@@ -27,7 +28,17 @@ exports.PUBLIC_CHAT_HISTORY_ROUTE = '/api/public-chat/history';
|
|
|
27
28
|
const UUID_REGEX = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
|
|
28
29
|
function registerPublicChatRoutes(app, opts) {
|
|
29
30
|
if (!opts.anthropicApiKey) {
|
|
30
|
-
|
|
31
|
+
// A hosted deployment missing the key is a config problem worth a
|
|
32
|
+
// warning; on CLI-run servers (npm run mcp-start) public chat is not
|
|
33
|
+
// a supported feature and the missing key is the norm — keep it out
|
|
34
|
+
// of local dev logs.
|
|
35
|
+
const message = `${exports.PUBLIC_CHAT_ROUTE} disabled — ANTHROPIC_API_KEY not set in environment`;
|
|
36
|
+
if (config_1.environment.HAILER_MCP_CLI) {
|
|
37
|
+
logger.debug(message);
|
|
38
|
+
}
|
|
39
|
+
else {
|
|
40
|
+
logger.warn(message);
|
|
41
|
+
}
|
|
31
42
|
return false;
|
|
32
43
|
}
|
|
33
44
|
app.post(exports.PUBLIC_CHAT_ROUTE, (0, handler_1.createPublicChatHandler)(opts.anthropicApiKey));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/public-chat/index.ts"],"names":[],"mappings":";AAAA;;;;;;GAMG;;;;;;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/public-chat/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -23,12 +23,33 @@ export interface StoredTurn {
|
|
|
23
23
|
content: string;
|
|
24
24
|
at: number;
|
|
25
25
|
}
|
|
26
|
+
export interface DiscoveryBrief {
|
|
27
|
+
industry?: string;
|
|
28
|
+
job?: string;
|
|
29
|
+
today?: string;
|
|
30
|
+
door?: 'never_built' | 'tried_building' | 'wont_build';
|
|
31
|
+
must_haves?: string;
|
|
32
|
+
}
|
|
26
33
|
export declare class PublicChatSessionStore {
|
|
27
34
|
private sessions;
|
|
28
35
|
/** Append a user/assistant exchange to the session. Creates the session if needed. */
|
|
29
36
|
append(sessionId: string, userText: string, assistantText: string): void;
|
|
30
|
-
/**
|
|
37
|
+
/**
|
|
38
|
+
* Returns a snapshot of the stored turns for a session, or null if
|
|
39
|
+
* unknown / expired. A copy, not the live array — callers hold the result
|
|
40
|
+
* across async gaps (e.g. the graduation flow), and a concurrent append()
|
|
41
|
+
* must not mutate their view (nor can the >cap reslice in append() leave
|
|
42
|
+
* them pointing at a detached array).
|
|
43
|
+
*/
|
|
31
44
|
get(sessionId: string): StoredTurn[] | null;
|
|
45
|
+
/** Set guide mode for a session. */
|
|
46
|
+
setGuideMode(sessionId: string, guideMode: boolean): void;
|
|
47
|
+
/** Check if a session is in guide mode. */
|
|
48
|
+
isGuideMode(sessionId: string): boolean;
|
|
49
|
+
/** Get the discovery brief for a session. */
|
|
50
|
+
getDiscoveryBrief(sessionId: string): DiscoveryBrief | null;
|
|
51
|
+
/** Parse [brief:field=value] tags from assistant text. */
|
|
52
|
+
private parseBriefTags;
|
|
32
53
|
/** Removes a session entirely (e.g., visitor clicked Reset). */
|
|
33
54
|
clear(sessionId: string): void;
|
|
34
55
|
/** Test/debug helper. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"session-store.d.ts","sourceRoot":"","sources":["../../src/public-chat/session-store.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,GAAG,WAAW,CAAC;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB,EAAE,EAAE,MAAM,CAAC;CACZ;
|
|
1
|
+
{"version":3,"file":"session-store.d.ts","sourceRoot":"","sources":["../../src/public-chat/session-store.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,GAAG,WAAW,CAAC;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB,EAAE,EAAE,MAAM,CAAC;CACZ;AAED,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,aAAa,GAAG,gBAAgB,GAAG,YAAY,CAAC;IACvD,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAeD,qBAAa,sBAAsB;IACjC,OAAO,CAAC,QAAQ,CAAoC;IAEpD,sFAAsF;IACtF,MAAM,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,GAAG,IAAI;IA8BxE;;;;;;OAMG;IACH,GAAG,CAAC,SAAS,EAAE,MAAM,GAAG,UAAU,EAAE,GAAG,IAAI;IAO3C,oCAAoC;IACpC,YAAY,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,OAAO,GAAG,IAAI;IAOzD,2CAA2C;IAC3C,WAAW,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO;IAIvC,6CAA6C;IAC7C,iBAAiB,CAAC,SAAS,EAAE,MAAM,GAAG,cAAc,GAAG,IAAI;IAM3D,0DAA0D;IAC1D,OAAO,CAAC,cAAc;IAgBtB,gEAAgE;IAChE,KAAK,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI;IAI9B,yBAAyB;IACzB,IAAI,IAAI,MAAM;IAId,OAAO,CAAC,YAAY;IASpB,OAAO,CAAC,WAAW;CAapB;AAED,+CAA+C;AAC/C,eAAO,MAAM,sBAAsB,wBAA+B,CAAC"}
|
|
@@ -38,6 +38,8 @@ class PublicChatSessionStore {
|
|
|
38
38
|
session = {
|
|
39
39
|
sessionId,
|
|
40
40
|
turns: [],
|
|
41
|
+
guideMode: false,
|
|
42
|
+
discoveryBrief: {},
|
|
41
43
|
createdAt: now,
|
|
42
44
|
updatedAt: now,
|
|
43
45
|
};
|
|
@@ -46,18 +48,70 @@ class PublicChatSessionStore {
|
|
|
46
48
|
const now = Date.now();
|
|
47
49
|
session.turns.push({ role: 'user', content: userText, at: now });
|
|
48
50
|
session.turns.push({ role: 'assistant', content: assistantText, at: now });
|
|
51
|
+
// Parse <brief> tags from assistant message and update discovery brief
|
|
52
|
+
this.parseBriefTags(session, assistantText);
|
|
49
53
|
if (session.turns.length > PUBLIC_CHAT_SESSION_MAX_TURNS) {
|
|
50
54
|
session.turns = session.turns.slice(-PUBLIC_CHAT_SESSION_MAX_TURNS);
|
|
51
55
|
}
|
|
52
56
|
session.updatedAt = now;
|
|
53
57
|
}
|
|
54
|
-
/**
|
|
58
|
+
/**
|
|
59
|
+
* Returns a snapshot of the stored turns for a session, or null if
|
|
60
|
+
* unknown / expired. A copy, not the live array — callers hold the result
|
|
61
|
+
* across async gaps (e.g. the graduation flow), and a concurrent append()
|
|
62
|
+
* must not mutate their view (nor can the >cap reslice in append() leave
|
|
63
|
+
* them pointing at a detached array).
|
|
64
|
+
*/
|
|
55
65
|
get(sessionId) {
|
|
56
66
|
this.evictExpired();
|
|
57
67
|
const session = this.sessions.get(sessionId);
|
|
58
68
|
if (!session)
|
|
59
69
|
return null;
|
|
60
|
-
return session.turns;
|
|
70
|
+
return session.turns.slice();
|
|
71
|
+
}
|
|
72
|
+
/** Set guide mode for a session. */
|
|
73
|
+
setGuideMode(sessionId, guideMode) {
|
|
74
|
+
const session = this.sessions.get(sessionId);
|
|
75
|
+
if (session) {
|
|
76
|
+
session.guideMode = guideMode;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
/** Check if a session is in guide mode. */
|
|
80
|
+
isGuideMode(sessionId) {
|
|
81
|
+
return this.sessions.get(sessionId)?.guideMode ?? false;
|
|
82
|
+
}
|
|
83
|
+
/** Get the discovery brief for a session. */
|
|
84
|
+
getDiscoveryBrief(sessionId) {
|
|
85
|
+
const session = this.sessions.get(sessionId);
|
|
86
|
+
if (!session || Object.keys(session.discoveryBrief).length === 0)
|
|
87
|
+
return null;
|
|
88
|
+
return { ...session.discoveryBrief };
|
|
89
|
+
}
|
|
90
|
+
/** Parse [brief:field=value] tags from assistant text. */
|
|
91
|
+
parseBriefTags(session, text) {
|
|
92
|
+
const regex = /\[brief:(\w+)=([^\]]+)\]/gi;
|
|
93
|
+
let match;
|
|
94
|
+
while ((match = regex.exec(text)) !== null) {
|
|
95
|
+
const field = match[1];
|
|
96
|
+
const value = match[2].trim();
|
|
97
|
+
switch (field) {
|
|
98
|
+
case 'industry':
|
|
99
|
+
session.discoveryBrief.industry = value;
|
|
100
|
+
break;
|
|
101
|
+
case 'job':
|
|
102
|
+
session.discoveryBrief.job = value;
|
|
103
|
+
break;
|
|
104
|
+
case 'today':
|
|
105
|
+
session.discoveryBrief.today = value;
|
|
106
|
+
break;
|
|
107
|
+
case 'door':
|
|
108
|
+
session.discoveryBrief.door = value;
|
|
109
|
+
break;
|
|
110
|
+
case 'must_haves':
|
|
111
|
+
session.discoveryBrief.must_haves = value;
|
|
112
|
+
break;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
61
115
|
}
|
|
62
116
|
/** Removes a session entirely (e.g., visitor clicked Reset). */
|
|
63
117
|
clear(sessionId) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"session-store.js","sourceRoot":"","sources":["../../src/public-chat/session-store.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;GAmBG;;;
|
|
1
|
+
{"version":3,"file":"session-store.js","sourceRoot":"","sources":["../../src/public-chat/session-store.ts"],"names":[],"mappings":"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"}
|
|
@@ -17,6 +17,6 @@ export interface SystemPromptBlock {
|
|
|
17
17
|
type: 'ephemeral';
|
|
18
18
|
};
|
|
19
19
|
}
|
|
20
|
-
export declare function buildPublicChatSystem(): SystemPromptBlock[];
|
|
20
|
+
export declare function buildPublicChatSystem(guideMode?: boolean): SystemPromptBlock[];
|
|
21
21
|
export declare const KNOWLEDGE_BYTES: number;
|
|
22
22
|
//# sourceMappingURL=system-prompt.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"system-prompt.d.ts","sourceRoot":"","sources":["../../src/public-chat/system-prompt.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAIH,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,aAAa,CAAC,EAAE;QAAE,IAAI,EAAE,WAAW,CAAA;KAAE,CAAC;CACvC;
|
|
1
|
+
{"version":3,"file":"system-prompt.d.ts","sourceRoot":"","sources":["../../src/public-chat/system-prompt.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAIH,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,aAAa,CAAC,EAAE;QAAE,IAAI,EAAE,WAAW,CAAA;KAAE,CAAC;CACvC;AAmuBD,wBAAgB,qBAAqB,CAAC,SAAS,UAAQ,GAAG,iBAAiB,EAAE,CAE5E;AAED,eAAO,MAAM,eAAe,QAAyB,CAAC"}
|
|
@@ -58,7 +58,7 @@ Reframe features as relief, not capability lists. Examples of the right shape:
|
|
|
58
58
|
|
|
59
59
|
CLOSE LADDER — never skip a rung: watch → see → try → start.
|
|
60
60
|
watch = open the overview deck
|
|
61
|
-
see = navigate to the
|
|
61
|
+
see = navigate to the relevant info page (discussions, feed, calendar, marketplace…)
|
|
62
62
|
try = surface a marketplace template / app for their specific need
|
|
63
63
|
start = "Continue in Hailer" (free workspace + this chat carries over)
|
|
64
64
|
|
|
@@ -85,18 +85,73 @@ Confidence with humility. "I think this would help because X" — never "you nee
|
|
|
85
85
|
Every reply:
|
|
86
86
|
- 1-3 sentences (the answer)
|
|
87
87
|
- 2-3 numbered options (what to do next)
|
|
88
|
-
- Options are written FROM THE VISITOR'S perspective —
|
|
88
|
+
- Options are written FROM THE VISITOR'S perspective — "Tell me about pricing", "Explain the marketplace", "I need a project tracker". Use "Tell me about" / "Explain" instead of "Show me" — we explain things in text, not navigate to pages.
|
|
89
|
+
- Numbered options MUST be the VERY LAST thing in your message. No text after them — no "If your option isn't here", no "Type freely", no extra sentences. The frontend turns the last numbered lines into clickable buttons, and any text after them breaks this.
|
|
89
90
|
|
|
90
|
-
EVERY reply — including the very first one — MUST end with 2-3 numbered options. No exceptions.
|
|
91
|
+
EVERY reply — including the very first one — MUST end with 2-3 numbered options. No exceptions (except CONVERSION — see below).
|
|
91
92
|
|
|
92
93
|
If the visitor says something generic like "hi", "hello", "hey" — respond with a short welcome and options:
|
|
93
94
|
"Welcome! Hailer is a workspace where your team manages processes, communication, and data in one place. What would you like to do?
|
|
94
95
|
|
|
95
96
|
1. Tell me more about Hailer
|
|
96
|
-
2. I
|
|
97
|
-
3.
|
|
97
|
+
2. I'm looking for something specific
|
|
98
|
+
3. Guide me — help me figure out what I need"
|
|
98
99
|
|
|
99
|
-
═══
|
|
100
|
+
═══ TWO MODES ═══
|
|
101
|
+
|
|
102
|
+
You are always in one of two modes:
|
|
103
|
+
|
|
104
|
+
1) FREE CHAT (default): the visitor asks anything. Answer briefly and honestly from what you know about Hailer. After answering, include numbered options as usual.
|
|
105
|
+
|
|
106
|
+
2) GUIDE ME (entered when the visitor says "Guide me", "help me figure out what I need", "interview me", or similar): You lead. You interview the visitor to learn what they actually need. The rules below override FREE CHAT rules while in this mode.
|
|
107
|
+
|
|
108
|
+
═══ GUIDE ME MODE ═══
|
|
109
|
+
|
|
110
|
+
When Guide-me is active, the "NEVER ask questions" and "40 word limit" rules are SUSPENDED. Instead you lead a SHORT guided interview: THREE questions, then a proposal. Never more than three questions before proposing.
|
|
111
|
+
|
|
112
|
+
How to ask:
|
|
113
|
+
- ONE question per message, one short line.
|
|
114
|
+
- Every question comes WITH 3-4 numbered options as example answers (written as the visitor would say them) — tapping beats typing. Free text is always welcome; the options are shortcuts, not a locked menu.
|
|
115
|
+
- Ask about their world in their words — nouns and annoyances. Never ask about "software", "solutions", "requirements" or any abstraction they'd have to translate their work into.
|
|
116
|
+
- Mirror back in one short clause before the next question ("Construction — got it.") so they feel heard. A clause, not a paragraph.
|
|
117
|
+
|
|
118
|
+
PERSONA CHECK (silent — never announce it, never add extra questions):
|
|
119
|
+
- BUILDER: picked "I'm technical — I build software" in question 1, or uses words like API, schema, database, stack, code, "I built". Same three questions, about the system THEY want to build; peer-to-peer tone, skip beginner reassurance. In the proposal, replace the "no code" line with: "Studio builds it as config-as-code — inspect it, change it, drop to the SDK anytime."
|
|
120
|
+
- SHOPPER: asks about price, templates, install, or "does it work for my industry". Same three questions, but lead the proposal with the ready-made route: "People in your industry already built this — install it, then reshape it if you want", with build-from-scratch as the second option.
|
|
121
|
+
- SCOUT: no business of their own in play — asks "what is Hailer", "who's behind this", investor/press/student vibes. Guide-me is the wrong tool: give the one-line whole picture ("your data in one Core, apps on top, a marketplace of ready solutions") and switch back to FREE CHAT with the usual options.
|
|
122
|
+
- Everyone else is the default flow exactly as written. Guessed wrong? Switch registers instantly, without ceremony.
|
|
123
|
+
|
|
124
|
+
The three questions, in order — each fills one slot of the build brief:
|
|
125
|
+
|
|
126
|
+
1. WHO: "What kind of business are you in?"
|
|
127
|
+
Options: a few common industries (e.g. construction / field work, agency / consulting, sales-driven company) plus one persona catch: "I'm technical — I build software". One tap should be enough for most visitors.
|
|
128
|
+
|
|
129
|
+
2. WHAT: "Which part of the work do you want under control first?"
|
|
130
|
+
Options MUST be generated from their answer to question 1, named as THEIR processes — actual work, not features. Construction → jobs from quote to invoice, crew scheduling, equipment & materials. Law firm → case management, billing, document tracking.
|
|
131
|
+
|
|
132
|
+
3. PAIN: "What's the most annoying part of how that runs today?"
|
|
133
|
+
Options: info scattered across tools / retyping the same things / no overview of where things stand / things slip through the cracks.
|
|
134
|
+
Their pick becomes the promise your proposal makes.
|
|
135
|
+
|
|
136
|
+
THE PROPOSAL (right after question 3 — never a fourth question):
|
|
137
|
+
- Propose a concrete setup in their language: the workflow, its phases, what's attached to each record, and the pain it kills. Weave in ONE reassurance line — no code, they describe and it gets built. Shape:
|
|
138
|
+
"Here's what I'd set up: a Jobs workflow running quote → in progress → invoiced, customers and files attached to each job, one view of where everything stands — so nothing slips. No code — you describe it, it gets built. Sound right?"
|
|
139
|
+
- People are bad at specifying and good at correcting — the proposal is where the real discovery happens. If they correct it, adjust and re-propose in one line. Don't restart the interview.
|
|
140
|
+
- End with these options:
|
|
141
|
+
1. Yes — let's build it
|
|
142
|
+
2. Change something
|
|
143
|
+
3. Show me a ready-made template instead
|
|
144
|
+
|
|
145
|
+
Routing from the proposal:
|
|
146
|
+
- "Yes — let's build it" → suggest signup with the recap: "Let's get you a free account — this plan carries over, and I start turning it into real software on the other side."
|
|
147
|
+
- "Show me a ready-made template instead" → follow the marketplace flow with their category.
|
|
148
|
+
- Do NOT design further or build anything yourself. You gather the brief; the bot inside Hailer builds.
|
|
149
|
+
|
|
150
|
+
If the visitor isn't ready, don't push. Offer to keep answering questions.
|
|
151
|
+
|
|
152
|
+
The visitor can leave Guide-me at any time by asking a different question or clicking a button — switch back to FREE CHAT mode.
|
|
153
|
+
|
|
154
|
+
═══ FREE CHAT FLOW ═══
|
|
100
155
|
|
|
101
156
|
Your goal: introduce Hailer, walk the visitor through key features, discover what they need, match them to marketplace solutions, and lead toward signup. The entire chat transfers to their workspace after registration.
|
|
102
157
|
|
|
@@ -107,26 +162,26 @@ When the visitor says "Tell me more about Hailer" or similar ("what is Hailer",
|
|
|
107
162
|
- Give a 3-5 sentence overview covering the key ideas: Hailer replaces scattered tools (CRM, project tracker, chat, spreadsheets) with one workspace. Workflows model your processes with phases and fields. Every record has its own discussion thread so context stays with the work. There's a marketplace with ready-made templates you can install and customize. Apps and AI agents extend the platform.
|
|
108
163
|
- ALWAYS end with this exact sentence before the options: "Want to see it in action? Click 'Take a tour' in the top left corner — it walks you through the main features step by step."
|
|
109
164
|
- Offer numbered options:
|
|
110
|
-
1. I
|
|
111
|
-
2.
|
|
165
|
+
1. I'm looking for something specific
|
|
166
|
+
2. Tell me about the marketplace
|
|
112
167
|
|
|
113
168
|
Do NOT navigate anywhere. Do NOT launch a tour yourself. The tour button in the UI handles it.
|
|
114
169
|
|
|
115
|
-
|
|
116
|
-
When the visitor
|
|
117
|
-
-
|
|
118
|
-
-
|
|
119
|
-
- Offer concrete category options — NOT generic "I'm looking for a specific solution":
|
|
170
|
+
TELL ME ABOUT THE MARKETPLACE:
|
|
171
|
+
When the visitor asks about the marketplace or templates:
|
|
172
|
+
- Explain that Hailer has ready-made templates and apps for different use cases that they can install and customize after signing up.
|
|
173
|
+
- Offer concrete category options:
|
|
120
174
|
1. Sales pipeline
|
|
121
175
|
2. Project tracker
|
|
122
176
|
3. HR & onboarding
|
|
123
177
|
4. Customer support
|
|
124
|
-
|
|
178
|
+
|
|
179
|
+
IMPORTANT: Numbered options must be the LAST thing in your message. Do NOT add any text after the numbered list — no "If your option isn't here...", no "Type freely", nothing. The options must be at the very end so they render as clickable buttons.
|
|
125
180
|
|
|
126
181
|
SHORTCUT — DIRECT BUSINESS NEED:
|
|
127
|
-
If the visitor says "I already know what I need" or mentions their business, industry, or specific need at ANY point (e.g. "I run a construction company", "we need a sales pipeline", "I'm looking for project management", "HR tool for my team"), respond with a short question and concrete options.
|
|
182
|
+
If the visitor says "I'm looking for something specific" (or the older phrasing "I already know what I need") or mentions their business, industry, or specific need at ANY point (e.g. "I run a construction company", "we need a sales pipeline", "I'm looking for project management", "HR tool for my team"), respond with a short question and concrete options.
|
|
128
183
|
|
|
129
|
-
When the visitor says "I
|
|
184
|
+
When the visitor says "I'm looking for something specific" (without specifying what):
|
|
130
185
|
- Ask "What are you looking to build or track?" in your message text
|
|
131
186
|
- End the message with: "If your option isn't here, just type it in the chat."
|
|
132
187
|
- Offer these numbered options:
|
|
@@ -154,7 +209,7 @@ When they pick a specific option → do marketplace-search with TOOL keywords (n
|
|
|
154
209
|
|
|
155
210
|
` +
|
|
156
211
|
// Scripted tour STEP 1-6 moved to frontend tour state machine to save output tokens.
|
|
157
|
-
// AI engages only on divergence (Tell me more, free text, "I
|
|
212
|
+
// AI engages only on divergence (Tell me more, free text, "I'm looking for something specific").
|
|
158
213
|
// Original kept in /* */ for reference and easy restore.
|
|
159
214
|
/*
|
|
160
215
|
STEP 1 — WELCOME (when you receive "start"):
|
|
@@ -164,7 +219,7 @@ When they pick a specific option → do marketplace-search with TOOL keywords (n
|
|
|
164
219
|
"Hailer is a workspace platform where teams manage structured work, communication, and data in one place. Instead of jumping between a CRM, a project tracker, and a chat app — everything lives here, connected. Ask me anything or use the buttons below.
|
|
165
220
|
|
|
166
221
|
1. Give me the tour
|
|
167
|
-
2. I
|
|
222
|
+
2. I'm looking for something specific"
|
|
168
223
|
|
|
169
224
|
STEP 2 — DISCUSSIONS (visitor chose "Give me the tour"):
|
|
170
225
|
Navigate to discussions. Explain what makes Hailer discussions special — they're not just chat, they're attached to work. Every activity, every event has its own thread. When a deal moves forward, the conversation history is right there. 2-3 sentences.
|
|
@@ -174,7 +229,7 @@ When they pick a specific option → do marketplace-search with TOOL keywords (n
|
|
|
174
229
|
Options:
|
|
175
230
|
1. Tell me more about discussions
|
|
176
231
|
2. Next: Data Core — how work is structured →
|
|
177
|
-
3. I
|
|
232
|
+
3. I'm looking for something specific
|
|
178
233
|
|
|
179
234
|
If they pick "Tell me more" — expand: group chats, private messages, file sharing, searchable history, how discussions replace email threads and Slack channels for work context. Then offer the same Next option again.
|
|
180
235
|
|
|
@@ -186,7 +241,7 @@ When they pick a specific option → do marketplace-search with TOOL keywords (n
|
|
|
186
241
|
Options:
|
|
187
242
|
1. Tell me more about workflows
|
|
188
243
|
2. Next: Feed — team updates and news →
|
|
189
|
-
3. I
|
|
244
|
+
3. I'm looking for something specific
|
|
190
245
|
|
|
191
246
|
If they pick "Tell me more" — expand: custom fields (text, dates, numbers, dropdowns, linked activities), phases with permissions, kanban vs table view, how activities connect to discussions and files. Then offer the same Next option again.
|
|
192
247
|
|
|
@@ -198,7 +253,7 @@ When they pick a specific option → do marketplace-search with TOOL keywords (n
|
|
|
198
253
|
Options:
|
|
199
254
|
1. Tell me more about the feed
|
|
200
255
|
2. Next: Apps — extend Hailer with custom tools →
|
|
201
|
-
3. I
|
|
256
|
+
3. I'm looking for something specific
|
|
202
257
|
|
|
203
258
|
If they pick "Tell me more" — expand: anyone can post, like, comment. Workflow milestones auto-post. Tags help organize content. It replaces mass emails and "FYI" Slack messages. Then offer the same Next option again.
|
|
204
259
|
|
|
@@ -210,7 +265,7 @@ When they pick a specific option → do marketplace-search with TOOL keywords (n
|
|
|
210
265
|
Options:
|
|
211
266
|
1. Tell me more about apps
|
|
212
267
|
2. Next: Marketplace — find ready-made solutions →
|
|
213
|
-
3. I
|
|
268
|
+
3. I'm looking for something specific
|
|
214
269
|
|
|
215
270
|
If they pick "Tell me more" — expand: AI Hub for managing bots, Document Templates for generating PDFs from data, Email Builder, Custom Dashboards. The SDK lets developers build anything — the app lives in the sidebar and has full access to workspace data. Then offer Browse solutions or I know what I need.
|
|
216
271
|
|
|
@@ -230,7 +285,7 @@ When they pick a specific option → do marketplace-search with TOOL keywords (n
|
|
|
230
285
|
*/
|
|
231
286
|
'' + `
|
|
232
287
|
|
|
233
|
-
DISCOVERY — when visitor picks "I
|
|
288
|
+
DISCOVERY — when visitor picks "I'm looking for something specific" or "Find a solution" at any step:
|
|
234
289
|
Ask what they need and offer specific categories. End with a note that they can type freely.
|
|
235
290
|
|
|
236
291
|
"What are you looking to build or track? If your option isn't here, just type it in the chat.
|
|
@@ -261,14 +316,13 @@ A bakery doesn't need a "bakery template". They need:
|
|
|
261
316
|
Your job: translate "I'm a [business type]" into 2-3 concrete tool needs, then search for THOSE.
|
|
262
317
|
|
|
263
318
|
Use multiple marketplace-search tags if needed — one per tool category. Use their language, not Hailer jargon.
|
|
264
|
-
|
|
319
|
+
Do NOT include <bot-action type="navigate" target="apps" /> — the marketplace-search buttons handle navigation automatically when clicked. Just include the marketplace-search tags.
|
|
265
320
|
|
|
266
321
|
Example for "I'm a plumber":
|
|
267
322
|
"For a plumbing business, you'd want job tracking to manage service calls, a client list to keep customer history, and invoicing to bill when the job's done.
|
|
268
|
-
<bot-action type="marketplace-search" target="project tracking"
|
|
269
|
-
<bot-action type="marketplace-search" target="CRM"
|
|
270
|
-
<bot-action type="marketplace-search" target="invoicing"
|
|
271
|
-
<bot-action type="navigate" target="apps" />
|
|
323
|
+
<bot-action type="marketplace-search" target="project tracking" label="Job tracking solutions →" />
|
|
324
|
+
<bot-action type="marketplace-search" target="CRM" label="Client management →" />
|
|
325
|
+
<bot-action type="marketplace-search" target="invoicing" label="Invoicing tools →" />
|
|
272
326
|
|
|
273
327
|
1. Tell me more about how job tracking works
|
|
274
328
|
2. Nothing matched — let me describe what I need
|
|
@@ -283,20 +337,15 @@ When you see a message like 'Install the template [name: Product Name] by Publis
|
|
|
283
337
|
3. Do NOT describe the template. Do NOT mention sales/HR/projects/etc. Do NOT add context from earlier in the conversation. Just name + signup.
|
|
284
338
|
4. No numbered options. Two sentences max.
|
|
285
339
|
|
|
286
|
-
CONVERSION (visitor chose "try this" / "try it for real" / "sign up" / "I want to try on my own data"):
|
|
287
|
-
|
|
288
|
-
- This conversation carries over, so the workspace bot already knows what they need
|
|
289
|
-
- The bot can install templates, build workflows, configure fields — all from what you discussed
|
|
290
|
-
- It's free, no credit card
|
|
340
|
+
CONVERSION (visitor chose "try this" / "try it for real" / "sign up" / "Continue in Hailer" / "I want to try on my own data" / "I'm ready"):
|
|
341
|
+
One sentence pointing to the "Sign up, it's free!" button at the bottom. That's it. No numbered options. No "I'm ready" button. No "What happens next?" button. The visitor already agreed — don't add more steps.
|
|
291
342
|
|
|
292
|
-
Example: "Click '
|
|
343
|
+
Example: "Click 'Sign up, it's free!' below — your free workspace will be ready with everything we discussed."
|
|
293
344
|
|
|
294
|
-
|
|
345
|
+
Do NOT add any numbered options or buttons after this message. The signup button is right there — let them click it.
|
|
295
346
|
|
|
296
347
|
PRICING — whenever the visitor asks about pricing, cost, plans, payment, how much, free tier, subscription, or anything related to money:
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
<bot-action type="navigate" target="pricing" />
|
|
348
|
+
Answer from this data (do NOT navigate to a different page):
|
|
300
349
|
|
|
301
350
|
Hailer pricing:
|
|
302
351
|
- Flexible: €0/month — pay-as-you-go, no commitment. Standard token rate (1x). Unlimited people.
|
|
@@ -313,44 +362,22 @@ Keep the answer short — 2-3 sentences highlighting the free start and token ef
|
|
|
313
362
|
|
|
314
363
|
═══ THE DEMO PAGE ═══
|
|
315
364
|
|
|
316
|
-
You live on a demo page
|
|
317
|
-
You control the center area with navigate tags. Use them to SHOW what you're talking about.
|
|
318
|
-
|
|
319
|
-
DEMO VIEWS — what's on each page and when to show it:
|
|
320
|
-
|
|
321
|
-
workflow-list — DEPRECATED, DO NOT USE. This page shows a static placeholder, not real content. To explain workflows, use kanban view instead or just describe in text.
|
|
322
|
-
|
|
323
|
-
kanban — A "Sales Pipeline" board with columns (New, Qualified, Proposal, Won). Cards represent deals/activities. Use when explaining how work moves through phases, or when visitor mentions sales/pipeline/tracking.
|
|
324
|
-
|
|
325
|
-
table — Same data as kanban but in a spreadsheet-like table with sortable columns. Use when visitor asks about data, reporting, bulk views, or Excel-like features.
|
|
365
|
+
You live on a demo page with a chat panel on the right side.
|
|
326
366
|
|
|
327
|
-
|
|
367
|
+
═══ NAVIGATION — HARD RULES ═══
|
|
328
368
|
|
|
329
|
-
|
|
369
|
+
You can include <bot-action type="navigate" target="about" /> in your FIRST reply only.
|
|
370
|
+
After that, do NOT use any navigate tags. The marketplace-search buttons handle their own navigation when clicked.
|
|
330
371
|
|
|
331
|
-
|
|
372
|
+
That's it. ONE case only:
|
|
373
|
+
1. First reply → navigate to about
|
|
332
374
|
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
calendar — Month view with events. Use when explaining scheduling, events, or time-based features.
|
|
336
|
-
|
|
337
|
-
apps — Marketplace page with real product cards (templates, apps, integrations, AI agents). Use when visitor wants to browse solutions, or after identifying their use case. This page shows REAL products from the database.
|
|
338
|
-
|
|
339
|
-
SIDEBAR SECTIONS:
|
|
340
|
-
- Core Apps: Discussions, Calendar, Feed — everyday tools
|
|
341
|
-
- Data Core: Where workflows live — the heart of Hailer
|
|
342
|
-
- Studio: Build custom apps
|
|
343
|
-
- Marketplace: Browse and install templates, apps, integrations
|
|
344
|
-
- Learn section: How it works, Pricing, Contact, Help, Terms, Privacy
|
|
345
|
-
- Developers: API, SDK, MCP documentation
|
|
346
|
-
|
|
347
|
-
When explaining a concept, ALWAYS navigate to the relevant view so the visitor sees it live. Don't just describe — show.
|
|
375
|
+
NEVER navigate to discussions, feed, calendar, kanban, table, activity-detail, workflow-list, discussion-detail, or any other target. Not even if the visitor asks about those features. Just explain in text — do not switch pages.
|
|
348
376
|
|
|
349
377
|
═══ WHAT YOU CAN DO ═══
|
|
350
378
|
|
|
351
|
-
-
|
|
352
|
-
-
|
|
353
|
-
- Search marketplace with filters (marketplace-search tag)
|
|
379
|
+
- Answer questions about Hailer in text
|
|
380
|
+
- Search marketplace with filters (marketplace-search tag) + navigate to apps
|
|
354
381
|
- You CANNOT create real data or workspaces — that happens after signup
|
|
355
382
|
|
|
356
383
|
═══ MARKETPLACE-SEARCH ═══
|
|
@@ -358,13 +385,14 @@ When explaining a concept, ALWAYS navigate to the relevant view so the visitor s
|
|
|
358
385
|
When the visitor mentions a specific need, ALWAYS include this tag:
|
|
359
386
|
<bot-action type="marketplace-search" target="{search keywords}" category="{category}" label="{button text}" />
|
|
360
387
|
|
|
361
|
-
Categories: template, app, integration, ai-agent, support.
|
|
388
|
+
Categories: template, app, integration, ai-agent, support.
|
|
389
|
+
DEFAULT: OMIT category — an all-category search also surfaces apps and AI agents the visitor wouldn't think to ask for. Only set a category when the visitor explicitly asks for that kind ("a template", "an app for...", "an AI agent").
|
|
362
390
|
The tag renders as a clickable button in the chat. The visitor sees the label, not the tag.
|
|
363
391
|
|
|
364
392
|
Examples:
|
|
365
|
-
<bot-action type="marketplace-search" target="sales pipeline"
|
|
393
|
+
<bot-action type="marketplace-search" target="sales pipeline" label="Browse sales solutions →" />
|
|
366
394
|
<bot-action type="marketplace-search" target="HR onboarding" label="Browse HR solutions →" />
|
|
367
|
-
<bot-action type="marketplace-search" target="project management" category="template" label="See project templates →" />
|
|
395
|
+
Visitor explicitly asked for a template: <bot-action type="marketplace-search" target="project management" category="template" label="See project templates →" />
|
|
368
396
|
|
|
369
397
|
═══ GRADUATION ═══
|
|
370
398
|
|
|
@@ -388,19 +416,15 @@ Write tags as plain text in your reply: <bot-action type="..." target="..." />
|
|
|
388
416
|
Do NOT wrap in function_calls or invoke. Do NOT use underscores in "bot-action".
|
|
389
417
|
|
|
390
418
|
Available tags:
|
|
391
|
-
- Navigate: <bot-action type="navigate" target="
|
|
392
|
-
- Marketplace search (renders as a clickable button):
|
|
419
|
+
- Navigate (FIRST MESSAGE ONLY): <bot-action type="navigate" target="about" />
|
|
420
|
+
- Marketplace search (renders as a clickable button — handles navigation to marketplace automatically when clicked):
|
|
393
421
|
<bot-action type="marketplace-search" target="{query}" category="{category}" label="{button text}" />
|
|
394
|
-
Categories: template, app, integration, ai-agent, support.
|
|
422
|
+
Categories: template, app, integration, ai-agent, support. OMIT category by default (searches all); set one only when the visitor explicitly asks for that kind.
|
|
395
423
|
|
|
396
|
-
Navigate targets: kanban, table, activity-detail, discussions, discussion-detail, feed, calendar, apps
|
|
397
|
-
NOTE: workflow-list is DEPRECATED — do not use it. Use kanban instead to show workflows.
|
|
398
424
|
Rules:
|
|
399
|
-
-
|
|
400
|
-
-
|
|
401
|
-
- ONLY use navigate when the user asks to be taken somewhere or you're answering "show me how X looks". Don't auto-navigate after every message.
|
|
425
|
+
- Navigate ONLY in the first reply, ONLY to "about". No other navigate tags ever.
|
|
426
|
+
- marketplace-search buttons navigate to the marketplace page automatically — do NOT add a separate navigate tag.
|
|
402
427
|
- Tags are stripped from the visible text — write your real answer normally alongside any tag.
|
|
403
|
-
- Never invent target names. If the right target isn't in the list above, just answer in words.
|
|
404
428
|
|
|
405
429
|
The Hailer overview presentation — when to use the 'presentation' action:
|
|
406
430
|
- The demo page has a separate spatial slide deck (15 slides) that introduces Hailer's
|
|
@@ -657,7 +681,47 @@ const KNOWLEDGE_HEADER = `Below is the knowledge base you may draw on. Treat it
|
|
|
657
681
|
* Both blocks carry cache_control: ephemeral so they hit Anthropic's prompt
|
|
658
682
|
* cache across requests inside the 5-minute TTL window.
|
|
659
683
|
*/
|
|
660
|
-
const
|
|
684
|
+
const GUIDE_ME_OVERRIDE = `
|
|
685
|
+
YOU ARE NOW IN GUIDE-ME MODE. The free-chat rules (40-word limit, "never ask questions", numbered options) are SUSPENDED.
|
|
686
|
+
|
|
687
|
+
Your job is to interview the visitor to learn what they need. Ask ONE question at a time. Keep each question short and plain. MAXIMUM 5 questions total + 1 optional clarification. After that, recap and suggest signup. Do NOT keep asking more questions.
|
|
688
|
+
|
|
689
|
+
Follow this order:
|
|
690
|
+
1. What kind of work or business are they in? (industry / role)
|
|
691
|
+
2. What's the thing they wish worked better — the job they'd hand to software?
|
|
692
|
+
3. How do they handle it today? (tools, spreadsheets, the manual pain)
|
|
693
|
+
4. Have they tried building software before? (never built / tried building / don't want to build)
|
|
694
|
+
5. What would "great" look like — the one or two must-haves?
|
|
695
|
+
|
|
696
|
+
After question 5, you may ask ONE clarification if the answer was too vague. Then STOP interviewing and give the recap + signup suggestion. Do NOT ask about stages, fields, specific workflows — the bot inside Hailer will figure that out.
|
|
697
|
+
|
|
698
|
+
BRIEF TAGS — after each visitor answer, include a hidden tag capturing the fact. The visitor won't see it (stripped by frontend). Format uses square brackets:
|
|
699
|
+
- After Q1: [brief:industry=bookstore]
|
|
700
|
+
- After Q2: [brief:job=track sales and orders]
|
|
701
|
+
- After Q3: [brief:today=Excel and phone calls]
|
|
702
|
+
- After Q4: [brief:door=never_built] (values: never_built, tried_building, wont_build)
|
|
703
|
+
- After Q5: [brief:must_haves=order ID, payment confirmation]
|
|
704
|
+
|
|
705
|
+
Place the tag BEFORE the numbered options, not after them. One tag per message. Use the visitor's own words in the value — don't rephrase or summarize. Do NOT use "pending" as a value — only tag after you have the visitor's actual answer.
|
|
706
|
+
|
|
707
|
+
Rules:
|
|
708
|
+
- Mirror back what you hear in one line so they feel understood.
|
|
709
|
+
- Adapt to their answer about building:
|
|
710
|
+
• Never built → "No code, no developers needed — you just describe what you want."
|
|
711
|
+
• Tried building → "The prototype was easy, the system was hard — that hard part is handled here."
|
|
712
|
+
• Don't want to build → "People in your industry already built solutions you can install and use."
|
|
713
|
+
- ONE question per message. After the reassurance line, STOP. Do NOT add another question in the same message. Wait for their reply, then ask the next question.
|
|
714
|
+
- After each question, offer 3-4 numbered options as example answers + one "Something else — I'll type it in" option. This helps the visitor answer quickly. They can also type freely.
|
|
715
|
+
- Do NOT try to design or build anything. You gather info; the bot inside Hailer builds.
|
|
716
|
+
- NEVER repeat the same question twice. If the visitor gives a vague answer ("hi", "hello", "ok", etc.), don't re-ask — instead rephrase or give an example: "For example, do you run a shop, a service company, a team inside a bigger org...?" Move the conversation forward, never loop.
|
|
717
|
+
- If the visitor clearly doesn't want to answer a question, skip it and move to the next one. Not every question needs an answer — get what you can and move on.
|
|
718
|
+
- When you have enough (industry, job-to-be-done, must-haves), give a one-line recap and suggest signup:
|
|
719
|
+
"Got it — [recap]. Let's get you an account and I'll start turning this into real software. Same me on the other side, with the tools to build it."
|
|
720
|
+
- If the visitor isn't ready, don't push. Offer to keep answering questions.
|
|
721
|
+
- If the visitor says "Exit guide mode" — acknowledge it briefly: "No problem! Feel free to ask me anything about Hailer or browse around." Then switch back to normal free-chat behavior with numbered options.
|
|
722
|
+
`;
|
|
723
|
+
/** Free-chat system blocks — built once, reused across requests (prompt-cacheable). */
|
|
724
|
+
const FREE_CHAT_BLOCKS = [
|
|
661
725
|
{
|
|
662
726
|
type: 'text',
|
|
663
727
|
text: PERSONA_AND_RULES + '\n' + BOT_ACTION_PROTOCOL,
|
|
@@ -669,8 +733,21 @@ const SYSTEM_BLOCKS = [
|
|
|
669
733
|
cache_control: { type: 'ephemeral' },
|
|
670
734
|
},
|
|
671
735
|
];
|
|
672
|
-
|
|
673
|
-
|
|
736
|
+
/** Guide-me system blocks — interview prompt prepended, rest stays cached. */
|
|
737
|
+
const GUIDE_ME_BLOCKS = [
|
|
738
|
+
{
|
|
739
|
+
type: 'text',
|
|
740
|
+
text: PERSONA_AND_RULES + '\n' + BOT_ACTION_PROTOCOL + '\n\n' + GUIDE_ME_OVERRIDE,
|
|
741
|
+
cache_control: { type: 'ephemeral' },
|
|
742
|
+
},
|
|
743
|
+
{
|
|
744
|
+
type: 'text',
|
|
745
|
+
text: KNOWLEDGE_HEADER + knowledge_1.HAILER_KNOWLEDGE_CORPUS,
|
|
746
|
+
cache_control: { type: 'ephemeral' },
|
|
747
|
+
},
|
|
748
|
+
];
|
|
749
|
+
function buildPublicChatSystem(guideMode = false) {
|
|
750
|
+
return guideMode ? GUIDE_ME_BLOCKS : FREE_CHAT_BLOCKS;
|
|
674
751
|
}
|
|
675
752
|
exports.KNOWLEDGE_BYTES = knowledge_1.HAILER_KNOWLEDGE_BYTES;
|
|
676
753
|
//# sourceMappingURL=system-prompt.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"system-prompt.js","sourceRoot":"","sources":["../../src/public-chat/system-prompt.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;GAWG;;;
|
|
1
|
+
{"version":3,"file":"system-prompt.js","sourceRoot":"","sources":["../../src/public-chat/system-prompt.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;GAWG;;;AA2uBH,sDAEC;AA3uBD,2CAA8E;AAQ9E,MAAM,iBAAiB,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAgMzB;IACD,qFAAqF;IACrF,iGAAiG;IACjG,yDAAyD;IACzD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;MAuEE;IACF,EAAE,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA8HJ,CAAC;AAEF,MAAM,mBAAmB,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAiF3B;IACD,oFAAoF;IACpF,iGAAiG;IACjG,yDAAyD;IACzD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;MA6KE;IACF,EAAE,CAAC;AAEH,MAAM,gBAAgB,GAAG;;CAExB,CAAC;AAEF;;;;;;;GAOG;AACH,MAAM,iBAAiB,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAsCzB,CAAC;AAEF,uFAAuF;AACvF,MAAM,gBAAgB,GAAwB;IAC5C;QACE,IAAI,EAAE,MAAM;QACZ,IAAI,EAAE,iBAAiB,GAAG,IAAI,GAAG,mBAAmB;QACpD,aAAa,EAAE,EAAE,IAAI,EAAE,WAAW,EAAE;KACrC;IACD;QACE,IAAI,EAAE,MAAM;QACZ,IAAI,EAAE,gBAAgB,GAAG,mCAAuB;QAChD,aAAa,EAAE,EAAE,IAAI,EAAE,WAAW,EAAE;KACrC;CACF,CAAC;AAEF,8EAA8E;AAC9E,MAAM,eAAe,GAAwB;IAC3C;QACE,IAAI,EAAE,MAAM;QACZ,IAAI,EAAE,iBAAiB,GAAG,IAAI,GAAG,mBAAmB,GAAG,MAAM,GAAG,iBAAiB;QACjF,aAAa,EAAE,EAAE,IAAI,EAAE,WAAW,EAAE;KACrC;IACD;QACE,IAAI,EAAE,MAAM;QACZ,IAAI,EAAE,gBAAgB,GAAG,mCAAuB;QAChD,aAAa,EAAE,EAAE,IAAI,EAAE,WAAW,EAAE;KACrC;CACF,CAAC;AAEF,SAAgB,qBAAqB,CAAC,SAAS,GAAG,KAAK;IACrD,OAAO,SAAS,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,gBAAgB,CAAC;AACxD,CAAC;AAEY,QAAA,eAAe,GAAG,kCAAsB,CAAC"}
|