@hailer/mcp 1.3.14 → 1.3.23

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.
Files changed (57) hide show
  1. package/.claude/skills/create-and-publish-app/SKILL.md +44 -56
  2. package/.claude/skills/hailer-app-builder/SKILL.md +414 -970
  3. package/.claude/skills/hailer-app-primitives/SKILL.md +742 -0
  4. package/.claude/skills/hailer-apps-pictures/SKILL.md +191 -87
  5. package/.claude/skills/hailer-design-patterns/SKILL.md +317 -0
  6. package/.claude/skills/hailer-design-system/SKILL.md +202 -149
  7. package/.claude/skills/hailer-workflow-archetypes/SKILL.md +301 -0
  8. package/.claude/skills/insight-join-patterns/SKILL.md +313 -0
  9. package/.claude/skills/publish-hailer-app/SKILL.md +211 -0
  10. package/.claude/skills/sdk-activity-patterns/SKILL.md +257 -105
  11. package/.claude/skills/sdk-function-fields/SKILL.md +253 -492
  12. package/.claude/skills/sdk-insight-calculations/SKILL.md +364 -0
  13. package/.claude/skills/sdk-insight-queries/SKILL.md +192 -397
  14. package/.claude/skills/sdk-ws-config-skill/SKILL.md +265 -720
  15. package/.claude/skills/tool-response-verification/SKILL.md +143 -0
  16. package/CLAUDE.md +50 -19
  17. package/dist/bot/bot.d.ts.map +1 -1
  18. package/dist/bot/bot.js +26 -34
  19. package/dist/bot/bot.js.map +1 -1
  20. package/dist/bot/services/helper-prompt.d.ts +1 -1
  21. package/dist/bot/services/helper-prompt.d.ts.map +1 -1
  22. package/dist/bot/services/helper-prompt.js +62 -82
  23. package/dist/bot/services/helper-prompt.js.map +1 -1
  24. package/dist/bot/services/system-prompt.js +4 -4
  25. package/dist/config.d.ts +1 -0
  26. package/dist/config.d.ts.map +1 -1
  27. package/dist/config.js +6 -0
  28. package/dist/config.js.map +1 -1
  29. package/dist/mcp/hailer-rpc.d.ts +1 -0
  30. package/dist/mcp/hailer-rpc.d.ts.map +1 -1
  31. package/dist/mcp/hailer-rpc.js +4 -0
  32. package/dist/mcp/hailer-rpc.js.map +1 -1
  33. package/dist/mcp/tools/activity.d.ts.map +1 -1
  34. package/dist/mcp/tools/activity.js +8 -2
  35. package/dist/mcp/tools/activity.js.map +1 -1
  36. package/dist/mcp/tools/app-core.d.ts.map +1 -1
  37. package/dist/mcp/tools/app-core.js +6 -3
  38. package/dist/mcp/tools/app-core.js.map +1 -1
  39. package/dist/mcp/tools/app-marketplace.d.ts.map +1 -1
  40. package/dist/mcp/tools/app-marketplace.js +5 -1
  41. package/dist/mcp/tools/app-marketplace.js.map +1 -1
  42. package/dist/mcp/webhook-handler.d.ts.map +1 -1
  43. package/dist/mcp/webhook-handler.js +27 -0
  44. package/dist/mcp/webhook-handler.js.map +1 -1
  45. package/dist/public-chat/graduate.d.ts.map +1 -1
  46. package/dist/public-chat/graduate.js +153 -53
  47. package/dist/public-chat/graduate.js.map +1 -1
  48. package/dist/public-chat/rate-limit.js +1 -1
  49. package/dist/public-chat/rate-limit.js.map +1 -1
  50. package/dist/public-chat/studio-prewarm.js +2 -2
  51. package/dist/public-chat/studio-prewarm.js.map +1 -1
  52. package/dist/public-chat/system-prompt.d.ts.map +1 -1
  53. package/dist/public-chat/system-prompt.js +41 -25
  54. package/dist/public-chat/system-prompt.js.map +1 -1
  55. package/package.json +1 -1
  56. package/.claude/skills/hailer-project-protocol/SKILL.md +0 -398
  57. package/.opencode/package-lock.json +0 -117
@@ -0,0 +1,143 @@
1
+ ---
2
+ name: tool-response-verification
3
+ description: Verify MCP tool execution results before reporting success. Load when creating activities, updating activities, listing activities, or any MCP tool call where a silent failure could cause incorrect reporting. Covers the two distinct response envelopes (MCP wire result vs agent delegation report), create vs update response shapes, error asymmetry, empty-list shape, and MCP connection error detection.
4
+ ---
5
+
6
+ # Tool Response Verification
7
+
8
+ ## Purpose
9
+
10
+ Ensure agents verify actual tool execution results before reporting success. Prevents fabricated responses when MCP servers are disconnected or tools fail silently.
11
+
12
+ ---
13
+
14
+ ## Pattern 1: Always Check Tool Results
15
+
16
+ Every MCP tool call returns a result. Read it before proceeding.
17
+
18
+ ## Pattern 2: Never Assume Success
19
+
20
+ If you didn't see confirmation in the result, it didn't happen.
21
+
22
+ ## Pattern 3: Report Actual Errors
23
+
24
+ If a tool returned an error, report error status — don't fabricate success.
25
+
26
+ ## Pattern 4: No Fabrication
27
+
28
+ Never claim "created 5 activities" if you didn't see 5 activity IDs returned.
29
+
30
+ ## Pattern 5: Verification Checklist
31
+
32
+ Before returning success:
33
+ - Did the tool return a result (not an error)?
34
+ - Does the result contain expected data (IDs, counts, etc.)?
35
+ - Am I reporting data FROM the result, not data I expected?
36
+
37
+ ---
38
+
39
+ ## Pattern 6: Two Distinct Envelopes — Don't Confuse Them
40
+
41
+ **MCP tool wire result** — what the tool actually returns:
42
+ ```
43
+ { content: [{ type: "text", text: "..." }], isError?: boolean }
44
+ ```
45
+ Success and error both arrive as `text` content. Errors are signalled by a ❌ prefix in the text (e.g. `"❌ Activity not found"`), not by a structured status field. Activity/discussion tools do not set `isError: true` — read the text to determine outcome.
46
+
47
+ **Agent delegation report** — what the agent returns to the orchestrator after verifying the tool result:
48
+ ```json
49
+ { "status": "success|error", "result": { ... }, "summary": "..." }
50
+ ```
51
+ This `{status, result, summary}` shape is the agent's own output. It is NOT the MCP tool return value.
52
+
53
+ ---
54
+
55
+ ## Pattern 7: Runtime-Verified Wire Shapes for Activity Tools
56
+
57
+ The following shapes are runtime-verified against testspace 2026-06-07.
58
+
59
+ ### Success — create_activity (single and bulk)
60
+
61
+ Both single and bulk creates emit a fenced JSON block:
62
+ ```json
63
+ {"created_ids":["<24-hex-id>", ...]}
64
+ ```
65
+ Single create also includes a `discussionId` field alongside `created_ids`. There is NO prose-only success path for create — if you don't see `created_ids`, the create did not succeed.
66
+
67
+ ### Success — update_activity (single and bulk)
68
+
69
+ Update success is **prose only** — there is NO `created_ids` on update responses.
70
+
71
+ - Single: `✅ Successfully updated activity <id>!` + `API Response: 1`
72
+ - Bulk: `🎉 Successfully updated N activities!` + `Total Updated: N`
73
+
74
+ ### Error Envelope — Asymmetry Between create and update
75
+
76
+ Both create and update errors are prefixed with `❌`. There is no structured `isError`/`status` field on activity tool responses — read the text.
77
+
78
+ **create_activity errors are RICH:**
79
+ - 191 (field-level): full JSON `{"msg":"...","code":191,"details":{...},"debug":...}`
80
+ - Zod validation: structured `**Validation Error for create_activity**` block, e.g. `name: Activity name cannot be empty` / `workflowId: Required, phaseId: Required`
81
+
82
+ **update_activity errors are LOSSY:**
83
+ - Any rejection collapses to `❌ Error updating activity: [object Object]` — the underlying message is swallowed. Verify update outcomes via read-back (`show_activity_by_id`) rather than relying on the error text.
84
+
85
+ ### Empty-List Shape
86
+
87
+ `list_activities` with zero results returns:
88
+ ```
89
+ ✅ Found 0 activities in workflow "X"
90
+ 📊 PAGINATION INFO ... Activities on this page: 0
91
+ []
92
+ ```
93
+ A human-readable string + a bare `[]` — NOT a `{activities:[]}` JSON envelope. Do not flag a bare `[]` as a parse error or an offline-server symptom.
94
+
95
+ ---
96
+
97
+ ## Pattern 8: Detect MCP Connection Errors
98
+
99
+ When an MCP server is offline, tools may return unexpected text or transport-level errors.
100
+
101
+ **Red flags in the text content:**
102
+ - "0 Workflows Found" / "Activities on this page: 0" when the workspace is known to have data AND transport-layer error strings are present
103
+ - Error strings containing: "connection", "ECONNREFUSED", "timeout", "unavailable", "ENOTFOUND"
104
+
105
+ **Note:** `describe_workflows` returns a text blob like `"📋 N Workflows Found"` — there is no `workflows: []` JSON array. Read the text for the count and workflow names.
106
+
107
+ **What to do:**
108
+
109
+ ```json
110
+ {
111
+ "status": "error",
112
+ "result": { "tool": "tool_name", "error": "MCP server appears offline" },
113
+ "summary": "Cannot proceed: MCP server not responding"
114
+ }
115
+ ```
116
+
117
+ ---
118
+
119
+ ## Examples
120
+
121
+ ### Correct — Verify Before Reporting
122
+
123
+ ```
124
+ GOOD: Call create_activity → read result → if result.created_ids has entries → return success
125
+ GOOD: "Created customer with ID abc123" (ID from actual result)
126
+ ```
127
+
128
+ ### Wrong — Fabricating Success
129
+
130
+ ```
131
+ BAD: Call create_activity → immediately return {"status": "success", "created": 1}
132
+ BAD: "I created the customer" (without checking result)
133
+ ```
134
+
135
+ ### Correct — Error Reporting
136
+
137
+ ```json
138
+ {
139
+ "status": "error",
140
+ "result": { "tool": "create_activity", "error": "code 191: 'priority' must be a string" },
141
+ "summary": "Tool failed: field validation error"
142
+ }
143
+ ```
package/CLAUDE.md CHANGED
@@ -11,6 +11,12 @@ Remote = MCP tools for activities, discussions, calendar, insights, files, permi
11
11
 
12
12
  Before any MCP call, ask: "Is this answerable from `workspace/` files or a CLI?" If yes, do that instead. (SDK-profile connections don't even serve the shadowed tools; if you can see them, you're on a general connection — the rule still applies.)
13
13
 
14
+ ## Workflow, not dataset, for stage-based work
15
+
16
+ A "dataset" and a "workflow" are the **same backing entity** — the only difference is the `enableUnlinkedMode` flag in the workflow config. Unset/`false` = a phased workflow (activities live in phases and move between stages). `true` = a dataset (a flat list, activities detached from phase progression).
17
+
18
+ **If the brief involves phases, stages, statuses, a pipeline, or moving items between steps, build a phased workflow — leave `enableUnlinkedMode` unset (false).** Reserve datasets (`enableUnlinkedMode: true`) for flat reference data with no progression (contact lists, product catalogues). Why: when activities are spread across phases, generating an app that correctly displays records from ALL phases at once is error-prone and takes many retries — picking the right structure up front avoids the churn and wasted tokens.
19
+
14
20
  ## What Goes Where
15
21
 
16
22
  | Need | Do this | Don't |
@@ -59,7 +65,7 @@ workspace/
59
65
  ├── templates/ # Document templates
60
66
  └── <WorkflowName>_<id>/
61
67
  ├── fields.ts # Field definitions (type, label, key, options, required)
62
- ├── phases.ts # Phases (name, key, isInitial, isEndpoint, nextPhases)
68
+ ├── phases.ts # Phases (name, key, isInitial, isEndpoint, possibleNextPhase)
63
69
  ├── main.ts # Workflow config
64
70
  └── functions/ # Function field code (one file per function)
65
71
  ```
@@ -89,13 +95,27 @@ Always use `:force` — the non-force variants prompt interactively.
89
95
  |--------|---------|-------|
90
96
  | New entities | Omit `_id` — server assigns it | Don't add `_id` manually |
91
97
  | After push | `npm run pull` to get server-assigned IDs | Don't assume local IDs are final |
92
- | Function fields | `npm run fields-push:force` only (non-force skips `functionVariables`) | Don't use non-force |
98
+ | Function fields | `npm run fields-push:force` function code + `functionVariables` push from `functions/` regardless of force | non-force only prompts on deletes and hangs agents |
93
99
  | Enum imports | Verify after pull — identical hex suffixes can collide | Don't blindly trust auto-generated imports |
94
100
  | `linkedfrom` fields | Don't work in isolated-vm; use `<` backlink dependency | Don't use in function fields |
95
101
  | Function field code | Plain JavaScript only | Not TypeScript |
96
- | Phase transitions | Exact string match on phase name | Don't guess phase names |
102
+ | Phase transitions | Move with the target `phaseId` (hex or key) from `describe_workflows` / enums | Don't pass the phase name string — it's not resolved |
97
103
  | Activity field values (MCP) | Date: Unix ms (`1730937600000`); Dropdown: exact string; ActivityLink: string ID; fields keyed by field ID, never label | Not ISO dates, not arrays, not field names |
98
104
 
105
+ ### New-workflow pull-wipe guard
106
+
107
+ `npm run pull` after `npm run workflows-sync` **wipes** any locally-staged field/phase edits on other workflows. Safe sequence:
108
+
109
+ 1. `npm run workflows-sync` → check CLI output for `✨ Created: N` (N ≥ 1). If N = 0, the create was a no-op — do NOT pull.
110
+ 2. `npm run pull` — only after confirming the workflow was created.
111
+ 3. Complete the new workflow end-to-end (fields-push → phases-push) before pulling for any other reason.
112
+
113
+ Never mix un-pushed field edits on existing workflows into the same batch as a new-workflow create-then-pull.
114
+
115
+ ### No multi-select field types
116
+
117
+ Hailer fields hold **one value**. There is no multi-select for activitylink, dropdown (textpredefinedoptions), users, or teams. Writing `["id1", "id2"]` for any of these is a bug — it will silently fail or be rejected. To attach multiple linked activities, use multiple separate ActivityLink fields (or the inverse backlink). To assign multiple users, use multiple user fields.
118
+
99
119
  ## App Lifecycle
100
120
 
101
121
  | Step | How |
@@ -126,25 +146,36 @@ Tools not in this list are either SDK-shadowed (see matrix above) or admin/dange
126
146
 
127
147
  ## Skills
128
148
 
129
- Load in sub-agents via the Skill tool. Never in main context.
149
+ Skills live in `.claude/skills/`. Load the relevant skill before starting that kind of work — it carries the patterns, gotchas, and correct formats for that domain.
150
+
151
+ ### Skill routing
152
+
153
+ | Task / symptom | Load this skill |
154
+ |----------------|-----------------|
155
+ | Creating or editing workflows, fields, phases, teams, groups — or debugging push errors, field-not-visible issues, phase ordering | `sdk-ws-config-skill` |
156
+ | Writing or debugging any function (calculated) field; code 191 compile errors; null returns; cross-workflow aggregation | `sdk-function-fields` |
157
+ | Creating or updating activities via MCP; bulk create; field format questions; `createMany`/`updateMany`; silent write failures | `sdk-activity-patterns` |
158
+ | Writing or debugging any insight SQL query; timestamp unit confusion (seconds vs ms); reserved column names; NULL aggregates | `sdk-insight-queries` |
159
+ | Insight calculations beyond plain SUM/COUNT — weighted sums, CASE bucketing, conversion rates, date truncation, top-N, percentage of total | `sdk-insight-calculations` |
160
+ | Cross-workflow insight JOINs; NULL join results; ActivityLink display values; row multiplication from one-to-many | `insight-join-patterns` |
161
+ | Verifying MCP tool results; checking create/update actually succeeded; detecting silent failures | `tool-response-verification` |
162
+ | Building a Hailer app UI — components, hooks, reads/writes, v1↔v2 migration, ActivityLink shapes | `hailer-app-builder` |
163
+ | Scaffolding and publishing an app — `@hailer/create-app`, `prep-app`, publish scripts, auth, marketplace publish | `create-and-publish-app` |
164
+ | Theme, colors, Chakra tokens, icons, layout patterns | `hailer-design-system` |
165
+ | Adding images or media to an app | `hailer-apps-pictures` |
166
+ | Chakra UI primitives — Select, ConfirmDialog, date pickers, state machines, REST calls from app | `hailer-app-primitives` |
167
+ | Publish script flags, `--market`, `--create`, post-publish app registration | `publish-hailer-app` |
168
+
169
+ ### Field-by-key resolver (apps)
130
170
 
131
- | Skill | When |
132
- |-------|------|
133
- | `sdk-ws-config-skill` | Workflows, fields, phases, teams, groups |
134
- | `sdk-function-fields` | Calculated fields, nameFunction |
135
- | `sdk-activity-patterns` | Creating/updating activities via MCP |
136
- | `sdk-insight-queries` | SQL insight queries |
137
- | `hailer-app-builder` | Building Hailer apps (React/Chakra) |
138
- | `hailer-design-system` | Theme, colors, icons, layout |
139
- | `create-and-publish-app` | Scaffolding + publishing apps (dev/prod/marketplace) |
140
- | `testing-patterns` | Vitest/playwright tests |
171
+ In app code, reference fields by their **key** via the generated field resolver — never hardcode hex field IDs. A field with `key: "status"` is accessible as `activity.fields.status` (with `returnFlat: true`) or via the resolver. This keeps apps workspace-portable if fields are recreated.
141
172
 
142
- ## Commands
173
+ Fields without a `key` fall back to hex ID lookup. Assign meaningful keys when creating fields.
143
174
 
144
- `/command <param>` angle brackets = required
175
+ ## Design before building
145
176
 
146
- **Essential:** `/save`, `/handoff`, `/prd`, `/autoplan`, `/ws-pull`
177
+ Before building a workspace, load `hailer-workflow-archetypes` to pick the structural shape (Register, Pipeline, Header+LineItems, etc.), then `hailer-design-patterns` for parent/child lifecycle, row progression, and integration patterns. Design the structure first — flat field-piles without archetype thinking cause expensive rework later.
147
178
 
148
- **Squads** (drive the native Workflow tool): `/review-squad [target]`, `/debug-squad "<bug>"`
179
+ ## Build strategy
149
180
 
150
- Build apps with a single agent + the `hailer-app-builder` / `create-and-publish-app` skills — faster than fanning out a squad (no shared-contract prep, no cross-agent integration fixups).
181
+ Build apps with a single agent (`agent-giuseppe-app-builder`) + the `hailer-app-builder` / `create-and-publish-app` skills — a focused agent dispatch is more efficient than multi-agent fan-out for app builds (no shared-contract prep, no cross-agent integration fixups).
@@ -1 +1 @@
1
- {"version":3,"file":"bot.d.ts","sourceRoot":"","sources":["../../src/bot/bot.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"bot.d.ts","sourceRoot":"","sources":["../../src/bot/bot.ts"],"names":[],"mappings":"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"}
package/dist/bot/bot.js CHANGED
@@ -62,7 +62,6 @@ const operation_logger_1 = require("./operation-logger");
62
62
  const services_1 = require("./services");
63
63
  const bot_config_1 = require("../bot-config");
64
64
  const logger_1 = require("../lib/logger");
65
- const config_1 = require("../config");
66
65
  // ===== CONSTANTS =====
67
66
  /**
68
67
  * Parse the optional `seedContext` field on the bot config — a JSON array
@@ -118,7 +117,7 @@ function parseSeedTurns(raw, log) {
118
117
  if (typeof summary === 'string' && summary.length > 0) {
119
118
  // Append explicit template names so the bot sees them clearly
120
119
  const namesHint = templateNames.length > 0
121
- ? `\n\n[INSTALL THESE TEMPLATES BY NAME: ${templateNames.join(', ')}]`
120
+ ? `\n\n[INSTALL THESE PRODUCTS BY NAME: ${templateNames.join(', ')}]`
122
121
  : '';
123
122
  return {
124
123
  turns: [{ role: 'user', content: `[Demo conversation summary]\n${summary}${namesHint}` }],
@@ -674,7 +673,7 @@ class Bot {
674
673
  accessLevel: this.config.accessLevel,
675
674
  allowBotMessages: this.config.allowBotMessages,
676
675
  });
677
- const { turns: seedTurns, viewedSlides, templateIds } = parseSeedTurns(this.config.seedContext, this.logger);
676
+ const { turns: seedTurns, viewedSlides, templateIds, templateNames } = parseSeedTurns(this.config.seedContext, this.logger);
678
677
  const hasSeed = seedTurns.length > 0;
679
678
  // Map slide ids → short human labels for the prompt. Anything not in
680
679
  // the map is dropped (defence against stale ids leaking through).
@@ -729,44 +728,35 @@ class Bot {
729
728
  }
730
729
  }
731
730
  const templatesInstalledHint = installedTemplateNames.length > 0
732
- ? `\n\nIMPORTANT: The marketplace template(s) the visitor chose during the demo have ALREADY been installed into this workspace automatically. Do NOT ask which template they want or offer to install anything — it's done. Just tell them it's installed and ready, and offer to walk them through what's inside (phases, fields, etc.).`
731
+ ? `\n\nIMPORTANT: Everything the visitor chose during the demo has ALREADY been installed. Do NOT ask what they want or offer to install anything — it's done. Do NOT name specific products. Just say everything is installed and ready, and offer to show them around.`
733
732
  : '';
734
733
  // Only promise an automatic build when Studio session creation is
735
734
  // configured for this deployment; otherwise nothing builds the
736
735
  // workspace and the bot must not promise a build that never runs. The
737
736
  // graduation flow gates createStudioSession on the same env var, so
738
737
  // "build promised" matches "build attempted".
739
- const studioBuilding = !!config_1.environment.STUDIO_SESSIONS_CREATE_URL;
740
738
  const introInstruction = hasSeed
741
- ? (studioBuilding
742
- ? `You are being posted in your own activity discussion for the first time. The user just graduated from a public demo chat with you — the messages above are the conversation you both had there.
743
-
744
- What this first message needs to do:
745
-
746
- 1. Greet them warmly and acknowledge you remember the demo. Be specific — name the thing they were exploring (e.g. "the plumbing-company job tracker you were sketching out" rather than "your business").
747
-
748
- 2. Tell them what's happening RIGHT NOW: based on that conversation, their workspace is being set up for them automatically — the workflow(s) to run that process, a few sample records so they can see it in action, and a custom app on top. It takes a couple of minutes. Do NOT offer to build it yourself and do NOT ask "want me to set this up?" — it is already being built. You are not the one building it; just let them know it's underway.
749
-
750
- 3. Tell them what comes next: as soon as the workflows are ready you'll walk them through their new workspace with a quick guided tour, so there's nothing they need to do yet — they can sit tight or keep chatting with you here.
751
-
752
- 4. Mention in passing that they can shape how you behave (tone, persona, language, even your picture) just by asking you here, and that account-level settings live in the AI Hub app.
753
-
754
- Tone: conversational, friendly, reassuring. No section headers, no bullet lists. Keep it under ~150 words.`
755
- : `You are being posted in your own activity discussion for the first time. The user just graduated from a public demo chat with you — the messages above are the conversation you both had there.
739
+ ? (`You are being posted in your own activity discussion for the first time. The user just graduated from a public demo chat with you — the messages above are the conversation you both had there.
756
740
 
757
741
  CRITICAL: This is a plain text greeting. No tool calls, no bot-action tags, no JSON, no XML, no code blocks. Just normal sentences.
758
742
 
759
743
  Write exactly this structure:
760
- 1. "Welcome to Hailer!" — warm greeting, one sentence.
761
- 2. If a template was mentioned in the demo context: "I see you chose [template name] — shall I install it?" Ask for confirmation, nothing more.
762
- 3. If no template was mentioned: "What would you like to set up first?" — one sentence.
763
-
764
744
  ${installedTemplateNames.length > 0
765
- ? `The template(s) have been auto-installed. Say: "Welcome to Hailer! I've already installed [name] for you — want me to show you what's inside?"`
766
- : ``}
745
+ ? `Products were auto-installed. Say: "Welcome to Hailer! ${installedTemplateNames.join(', ')} ${installedTemplateNames.length === 1 ? 'has' : 'have'} been installed and ${installedTemplateNames.length === 1 ? 'is' : 'are'} ready to use — want me to show you around?"`
746
+ : templateNames.length > 0
747
+ ? `Products were selected but not yet installed. Say: "Welcome to Hailer! I see you picked ${templateNames.join(', ')} — shall I install ${templateNames.length === 1 ? 'it' : 'them'} for you?"`
748
+ : `The user signed up without choosing anything. Say: "Welcome to Hailer! I noticed you haven't picked anything yet — no worries. Want me to find something from the marketplace that fits your needs, or would you like me to explain how things work here first?"`}
749
+
750
+ Under 60 words. No headers, no lists. Plain text only — no tool calls, no bot-action tags, no JSON.`)
751
+ : this.config.helperMode
752
+ ? `You are being posted in your own activity discussion for the first time. This is a new user who just signed up — their workspace is empty.
753
+
754
+ CRITICAL: This is a plain text greeting. No tool calls, no bot-action tags, no JSON, no code blocks.
755
+
756
+ Say: "Welcome to Hailer! Your workspace is empty for now — I can help you set it up. Want me to find something from the marketplace that fits your needs, or would you like me to explain how things work here first?"
767
757
 
768
- Under 40 words. No headers, no lists.`)
769
- : `You are being posted in your own activity discussion for the first time. Introduce yourself briefly in your own voice.
758
+ Under 50 words. No headers, no lists.`
759
+ : `You are being posted in your own activity discussion for the first time. Introduce yourself briefly in your own voice.
770
760
 
771
761
  CRITICAL: do NOT invent a backstory or claim to be a real person, celebrity, or fictional character based on your name alone. Your name was just chosen by the user — they may have meant a specific person/character, or they may have just liked the sound of it. If you don't have explicit persona instructions, acknowledge your name but be honest that you're a fresh assistant without a defined persona yet, and ask what kind of assistant they want you to be (or invite them to configure you).
772
762
 
@@ -1439,8 +1429,9 @@ Keep it short and conversational. No bullet lists, no headers.`;
1439
1429
  results.push({ type: 'tool_result', tool_use_id: block.id, content: 'You are already responding in this discussion. Your text response will be posted automatically — do not use add_discussion_message for the current discussion. Use it only for OTHER discussions.', is_error: true });
1440
1430
  continue;
1441
1431
  }
1442
- // Dedup cache: serve cached result for read-only tools (same sender + same args)
1443
- if (Bot.DEDUP_TOOLS.has(block.name)) {
1432
+ // Dedup cache: serve cached result for read-only tools (same sender + same args).
1433
+ // helperMode only — never alters the tool path for normal bots.
1434
+ if (this.config.helperMode && Bot.DEDUP_TOOLS.has(block.name)) {
1444
1435
  const dedupKey = `${block.name}:${message.senderId}:${JSON.stringify(args)}`;
1445
1436
  const cached = this.toolDedupCache.get(dedupKey);
1446
1437
  if (cached) {
@@ -1498,12 +1489,13 @@ Keep it short and conversational. No bullet lists, no headers.`;
1498
1489
  contentStr = `${contentStr.slice(0, MAX_TOOL_RESULT_CHARS)}\n\n[Tool result truncated. Original: ${originalLen} chars (~${Math.round(originalLen / 4)} tokens). Narrow your query: use 'fields' parameter, add filters, lower 'limit', or use run_insight with aggregate SQL.]`;
1499
1490
  this.logger.warn('Tool result truncated', { tool: block.name, originalLen, truncatedTo: MAX_TOOL_RESULT_CHARS });
1500
1491
  }
1501
- // Invalidate dedup cache when a write tool executes
1502
- if (Bot.WRITE_TOOLS_FOR_CACHE.has(block.name)) {
1492
+ // Invalidate dedup cache when a write tool executes (helperMode only)
1493
+ if (this.config.helperMode && Bot.WRITE_TOOLS_FOR_CACHE.has(block.name)) {
1503
1494
  this.toolDedupCache.clear();
1504
1495
  }
1505
- // Store read-only results in dedup cache (post-filter, so permissions are baked in)
1506
- if (Bot.DEDUP_TOOLS.has(block.name)) {
1496
+ // Store read-only results in dedup cache (post-filter, so permissions are baked in).
1497
+ // helperMode only — never alters the tool path for normal bots.
1498
+ if (this.config.helperMode && Bot.DEDUP_TOOLS.has(block.name)) {
1507
1499
  const dedupKey = `${block.name}:${message.senderId}:${JSON.stringify(args)}`;
1508
1500
  this.toolDedupCache.set(dedupKey, contentStr);
1509
1501
  }