@kivimedia/kmhub 2.9.1 → 2.11.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/README.md +170 -170
- package/bin/kmhub.mjs +896 -896
- package/coach-book-output-guard.mjs +760 -760
- package/index.mjs +57 -57
- package/package.json +56 -56
- package/prompts/briefing.md +29 -29
- package/prompts/luxury.md +70 -70
- package/prompts/play.md +49 -49
- package/prompts/run.md +37 -36
- package/prompts/setup.md +33 -33
- package/prompts/vs-booked.md +46 -46
- package/prompts/what-can-you-do.md +40 -40
- package/prompts.mjs +110 -110
- package/read-only-tools.json +143 -142
- package/remote.mjs +929 -929
- package/tools/balloon-costing.mjs +80 -80
- package/tools/booking-equipment.mjs +110 -110
- package/tools/bridges.mjs +54 -54
- package/tools/briefing.mjs +91 -91
- package/tools/calendar.mjs +170 -170
- package/tools/capabilities.mjs +155 -155
- package/tools/catalog.mjs +288 -288
- package/tools/clubs.mjs +176 -176
- package/tools/coach.mjs +771 -771
- package/tools/compare.mjs +76 -76
- package/tools/core.mjs +244 -244
- package/tools/crm.mjs +209 -209
- package/tools/dubsado.mjs +137 -137
- package/tools/exports.mjs +128 -128
- package/tools/fact-review.mjs +125 -125
- package/tools/flows.mjs +261 -261
- package/tools/forms.mjs +158 -158
- package/tools/gols.mjs +144 -134
- package/tools/hr.mjs +162 -162
- package/tools/knowledge.mjs +129 -125
- package/tools/marketing.mjs +396 -396
- package/tools/meta.mjs +245 -245
- package/tools/military.mjs +244 -244
- package/tools/money.mjs +235 -197
- package/tools/outreach.mjs +238 -238
- package/tools/pending.mjs +122 -122
- package/tools/photos.mjs +140 -140
- package/tools/plays.mjs +244 -244
- package/tools/profile.mjs +118 -118
- package/tools/radar.mjs +173 -173
- package/tools/recurring-invoices.mjs +149 -149
- package/tools/reengage.mjs +434 -434
- package/tools/schedules.mjs +55 -55
- package/tools/setup.mjs +168 -168
- package/tools/sops-bridges.mjs +86 -86
- package/tools/sops.mjs +314 -314
- package/tools/sourcing.mjs +268 -268
- package/tools/strategy.mjs +146 -146
- package/tools/studio.mjs +132 -132
- package/tools/venueradar.mjs +151 -151
- package/tools/voice.mjs +137 -134
- package/tools.mjs +407 -407
package/tools/fact-review.mjs
CHANGED
|
@@ -1,125 +1,125 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Tool family: fact-review - the owner confirms or rejects business facts from the terminal.
|
|
3
|
-
*
|
|
4
|
-
* km_list_pending_business_facts -> GET /knowledge/facts/pending
|
|
5
|
-
* km_confirm_business_facts -> POST /knowledge/facts/confirm (confirmed write)
|
|
6
|
-
* km_reject_business_facts -> POST /knowledge/facts/reject (confirmed write)
|
|
7
|
-
*
|
|
8
|
-
* WHY THIS EXISTS. km_propose_business_fact could only put a fact in the queue, so
|
|
9
|
-
* a conversation where the owner said "confirmed, these three are correct" still
|
|
10
|
-
* ended with "go and click confirm in the web app" (Brant Matthews, 23-Sep-26).
|
|
11
|
-
* Ziv: "you need to be able to confirm for me". The read and propose tools stay in
|
|
12
|
-
* knowledge.mjs, untouched in shape; this is the review half in its own family.
|
|
13
|
-
*
|
|
14
|
-
* 🚨 Both writes are confirmed writes. KM Hub answers 409 with a server-written
|
|
15
|
-
* list of the exact facts; put that to the person, wait for a real yes, then call
|
|
16
|
-
* again with the confirm_token and the SAME fact_ids. Reject is gated too because
|
|
17
|
-
* a rejection cannot be undone.
|
|
18
|
-
*
|
|
19
|
-
* The family contract this file follows is documented in ./README.md.
|
|
20
|
-
*/
|
|
21
|
-
import { z } from 'zod';
|
|
22
|
-
|
|
23
|
-
export const FAMILY = 'fact-review';
|
|
24
|
-
|
|
25
|
-
export const TOOLS = ['km_list_pending_business_facts', 'km_confirm_business_facts', 'km_reject_business_facts'];
|
|
26
|
-
|
|
27
|
-
// Same profiles as the knowledge family that proposes and reads these facts.
|
|
28
|
-
export const PROFILES = ['outreach', 'content', 'money'];
|
|
29
|
-
|
|
30
|
-
function routeMissing(r) {
|
|
31
|
-
return r.status === 404 || r.status === 405 || r.status === 501;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
const NOT_SUPPORTED =
|
|
35
|
-
'Your KM Hub cannot review business facts from the terminal yet. Nothing is wrong with the workspace and nothing ' +
|
|
36
|
-
'was changed. The owner can confirm or reject them in the web app at https://hub.kivimedia.co under Settings, ' +
|
|
37
|
-
'
|
|
38
|
-
|
|
39
|
-
const FACT_IDS = z
|
|
40
|
-
.array(z.string())
|
|
41
|
-
.min(1)
|
|
42
|
-
.max(25)
|
|
43
|
-
.describe('The ids of the facts, from km_list_pending_business_facts. Up to 25 at once.');
|
|
44
|
-
|
|
45
|
-
const CONFIRM_TOKEN = z
|
|
46
|
-
.string()
|
|
47
|
-
.optional()
|
|
48
|
-
.describe(
|
|
49
|
-
'Leave this out on the first call. KM Hub answers 409 with the list to put to the person and a token. Only ' +
|
|
50
|
-
'after they actually say yes, call again with the token and the SAME fact_ids and reason. A yes for one ' +
|
|
51
|
-
'list never authorises a different one.',
|
|
52
|
-
);
|
|
53
|
-
|
|
54
|
-
const REASON = z
|
|
55
|
-
.string()
|
|
56
|
-
.optional()
|
|
57
|
-
.describe('Optional, one line, in the owner\'s words, for example "Brant confirmed on the call". Kept with the decision.');
|
|
58
|
-
|
|
59
|
-
/** A 404 from a route that does not exist yet, as opposed to a fact that does not exist. */
|
|
60
|
-
function unsupported(r) {
|
|
61
|
-
if (!routeMissing(r)) return false;
|
|
62
|
-
const err = r.data && typeof r.data === 'object' ? r.data.error : undefined;
|
|
63
|
-
return err !== 'not_found' || /Unknown route/i.test(String(r.data?.message || ''));
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
export function register(server, call, { out, text }) {
|
|
67
|
-
server.tool(
|
|
68
|
-
'km_list_pending_business_facts',
|
|
69
|
-
'The business facts that are waiting for the owner to say yes or no: things somebody proposed with ' +
|
|
70
|
-
'km_propose_business_fact, or that KM Hub picked up from an uploaded document or the owner\'s emails. Each one ' +
|
|
71
|
-
'comes with its id, its exact text and where it came from. Call it when km_get_business_facts reports ' +
|
|
72
|
-
'pending_proposals above zero, when the person asks what is waiting for them, or before confirming anything, so ' +
|
|
73
|
-
'you have the ids. NONE of these is confirmed: never use one in a draft, a quote or an answer. Read each to the ' +
|
|
74
|
-
'owner in its exact words and let them decide. Read only.',
|
|
75
|
-
{},
|
|
76
|
-
async () => {
|
|
77
|
-
const r = await call('GET', '/knowledge/facts/pending');
|
|
78
|
-
if (unsupported(r)) return text(NOT_SUPPORTED, true);
|
|
79
|
-
return out(r);
|
|
80
|
-
},
|
|
81
|
-
);
|
|
82
|
-
|
|
83
|
-
server.tool(
|
|
84
|
-
'km_confirm_business_facts',
|
|
85
|
-
'Confirm business facts the owner says are TRUE, the same as the confirm button in KM Hub under Business ' +
|
|
86
|
-
'Knowledge. Once confirmed, every draft, quote, play and scout relies on the fact, so a wrong one ends up in ' +
|
|
87
|
-
'real messages to real clients. Use it when the person has read the facts and says they are right. Several ' +
|
|
88
|
-
'can go in one call, so the person answers once for the whole list. It is recorded as confirmed by the person ' +
|
|
89
|
-
'this connector belongs to, who has to be an owner or admin of the workspace. ' +
|
|
90
|
-
'Get the ids from km_list_pending_business_facts, and pass only the ones they actually said yes to. ' +
|
|
91
|
-
'🚨 A confirmed write. The first call, without confirm_token, returns 409 with `what_would_happen`: the list ' +
|
|
92
|
-
'of exact facts, written by KM Hub. Show it in those words, wait for a real yes, then call again with the ' +
|
|
93
|
-
'confirm_token and the SAME fact_ids. Once confirmed, a fact cannot be changed or withdrawn from the terminal, ' +
|
|
94
|
-
'and confirming a corrected wording later does NOT retire the old one (both would be in use), so confirm only ' +
|
|
95
|
-
'what the owner has read and said is right.',
|
|
96
|
-
{ fact_ids: FACT_IDS, reason: REASON, confirm_token: CONFIRM_TOKEN },
|
|
97
|
-
review('/knowledge/facts/confirm'),
|
|
98
|
-
);
|
|
99
|
-
|
|
100
|
-
server.tool(
|
|
101
|
-
'km_reject_business_facts',
|
|
102
|
-
'Reject business facts the owner says are WRONG, the same as the reject button in KM Hub under Business ' +
|
|
103
|
-
'Knowledge, so nothing ever uses them. Only on the owner\'s word about these specific facts, never on your own ' +
|
|
104
|
-
'judgement that one looks doubtful: if you think one is wrong, say so and let them decide. A rejected fact ' +
|
|
105
|
-
'cannot be reopened, and the same wording cannot be proposed again; if the owner wants a corrected version, ' +
|
|
106
|
-
'propose the corrected wording with km_propose_business_fact. ' +
|
|
107
|
-
'🚨 A confirmed write, because it cannot be undone: the first call returns 409 with the exact facts; show them, ' +
|
|
108
|
-
'wait for a real yes, then call again with the confirm_token and the SAME fact_ids. Afterwards, say plainly ' +
|
|
109
|
-
'which facts were rejected.',
|
|
110
|
-
{ fact_ids: FACT_IDS, reason: REASON, confirm_token: CONFIRM_TOKEN },
|
|
111
|
-
review('/knowledge/facts/reject'),
|
|
112
|
-
);
|
|
113
|
-
|
|
114
|
-
/** Same body on the ask and on the answer, so the confirm token's fingerprint matches. */
|
|
115
|
-
function review(path) {
|
|
116
|
-
return async ({ fact_ids, reason, confirm_token }) => {
|
|
117
|
-
const body = { fact_ids };
|
|
118
|
-
if (reason !== undefined) body.reason = reason;
|
|
119
|
-
if (confirm_token) body.confirm_token = String(confirm_token);
|
|
120
|
-
const r = await call('POST', path, body);
|
|
121
|
-
if (unsupported(r)) return text(NOT_SUPPORTED, true);
|
|
122
|
-
return out(r);
|
|
123
|
-
};
|
|
124
|
-
}
|
|
125
|
-
}
|
|
1
|
+
/**
|
|
2
|
+
* Tool family: fact-review - the owner confirms or rejects business facts from the terminal.
|
|
3
|
+
*
|
|
4
|
+
* km_list_pending_business_facts -> GET /knowledge/facts/pending
|
|
5
|
+
* km_confirm_business_facts -> POST /knowledge/facts/confirm (confirmed write)
|
|
6
|
+
* km_reject_business_facts -> POST /knowledge/facts/reject (confirmed write)
|
|
7
|
+
*
|
|
8
|
+
* WHY THIS EXISTS. km_propose_business_fact could only put a fact in the queue, so
|
|
9
|
+
* a conversation where the owner said "confirmed, these three are correct" still
|
|
10
|
+
* ended with "go and click confirm in the web app" (Brant Matthews, 23-Sep-26).
|
|
11
|
+
* Ziv: "you need to be able to confirm for me". The read and propose tools stay in
|
|
12
|
+
* knowledge.mjs, untouched in shape; this is the review half in its own family.
|
|
13
|
+
*
|
|
14
|
+
* 🚨 Both writes are confirmed writes. KM Hub answers 409 with a server-written
|
|
15
|
+
* list of the exact facts; put that to the person, wait for a real yes, then call
|
|
16
|
+
* again with the confirm_token and the SAME fact_ids. Reject is gated too because
|
|
17
|
+
* a rejection cannot be undone.
|
|
18
|
+
*
|
|
19
|
+
* The family contract this file follows is documented in ./README.md.
|
|
20
|
+
*/
|
|
21
|
+
import { z } from 'zod';
|
|
22
|
+
|
|
23
|
+
export const FAMILY = 'fact-review';
|
|
24
|
+
|
|
25
|
+
export const TOOLS = ['km_list_pending_business_facts', 'km_confirm_business_facts', 'km_reject_business_facts'];
|
|
26
|
+
|
|
27
|
+
// Same profiles as the knowledge family that proposes and reads these facts.
|
|
28
|
+
export const PROFILES = ['outreach', 'content', 'money'];
|
|
29
|
+
|
|
30
|
+
function routeMissing(r) {
|
|
31
|
+
return r.status === 404 || r.status === 405 || r.status === 501;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const NOT_SUPPORTED =
|
|
35
|
+
'Your KM Hub cannot review business facts from the terminal yet. Nothing is wrong with the workspace and nothing ' +
|
|
36
|
+
'was changed. The owner can confirm or reject them in the web app at https://hub.kivimedia.co under Settings, ' +
|
|
37
|
+
'Account, Business Knowledge.';
|
|
38
|
+
|
|
39
|
+
const FACT_IDS = z
|
|
40
|
+
.array(z.string())
|
|
41
|
+
.min(1)
|
|
42
|
+
.max(25)
|
|
43
|
+
.describe('The ids of the facts, from km_list_pending_business_facts. Up to 25 at once.');
|
|
44
|
+
|
|
45
|
+
const CONFIRM_TOKEN = z
|
|
46
|
+
.string()
|
|
47
|
+
.optional()
|
|
48
|
+
.describe(
|
|
49
|
+
'Leave this out on the first call. KM Hub answers 409 with the list to put to the person and a token. Only ' +
|
|
50
|
+
'after they actually say yes, call again with the token and the SAME fact_ids and reason. A yes for one ' +
|
|
51
|
+
'list never authorises a different one.',
|
|
52
|
+
);
|
|
53
|
+
|
|
54
|
+
const REASON = z
|
|
55
|
+
.string()
|
|
56
|
+
.optional()
|
|
57
|
+
.describe('Optional, one line, in the owner\'s words, for example "Brant confirmed on the call". Kept with the decision.');
|
|
58
|
+
|
|
59
|
+
/** A 404 from a route that does not exist yet, as opposed to a fact that does not exist. */
|
|
60
|
+
function unsupported(r) {
|
|
61
|
+
if (!routeMissing(r)) return false;
|
|
62
|
+
const err = r.data && typeof r.data === 'object' ? r.data.error : undefined;
|
|
63
|
+
return err !== 'not_found' || /Unknown route/i.test(String(r.data?.message || ''));
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export function register(server, call, { out, text }) {
|
|
67
|
+
server.tool(
|
|
68
|
+
'km_list_pending_business_facts',
|
|
69
|
+
'The business facts that are waiting for the owner to say yes or no: things somebody proposed with ' +
|
|
70
|
+
'km_propose_business_fact, or that KM Hub picked up from an uploaded document or the owner\'s emails. Each one ' +
|
|
71
|
+
'comes with its id, its exact text and where it came from. Call it when km_get_business_facts reports ' +
|
|
72
|
+
'pending_proposals above zero, when the person asks what is waiting for them, or before confirming anything, so ' +
|
|
73
|
+
'you have the ids. NONE of these is confirmed: never use one in a draft, a quote or an answer. Read each to the ' +
|
|
74
|
+
'owner in its exact words and let them decide. Read only.',
|
|
75
|
+
{},
|
|
76
|
+
async () => {
|
|
77
|
+
const r = await call('GET', '/knowledge/facts/pending');
|
|
78
|
+
if (unsupported(r)) return text(NOT_SUPPORTED, true);
|
|
79
|
+
return out(r);
|
|
80
|
+
},
|
|
81
|
+
);
|
|
82
|
+
|
|
83
|
+
server.tool(
|
|
84
|
+
'km_confirm_business_facts',
|
|
85
|
+
'Confirm business facts the owner says are TRUE, the same as the confirm button in KM Hub under Business ' +
|
|
86
|
+
'Knowledge. Once confirmed, every draft, quote, play and scout relies on the fact, so a wrong one ends up in ' +
|
|
87
|
+
'real messages to real clients. Use it when the person has read the facts and says they are right. Several ' +
|
|
88
|
+
'can go in one call, so the person answers once for the whole list. It is recorded as confirmed by the person ' +
|
|
89
|
+
'this connector belongs to, who has to be an owner or admin of the workspace. ' +
|
|
90
|
+
'Get the ids from km_list_pending_business_facts, and pass only the ones they actually said yes to. ' +
|
|
91
|
+
'🚨 A confirmed write. The first call, without confirm_token, returns 409 with `what_would_happen`: the list ' +
|
|
92
|
+
'of exact facts, written by KM Hub. Show it in those words, wait for a real yes, then call again with the ' +
|
|
93
|
+
'confirm_token and the SAME fact_ids. Once confirmed, a fact cannot be changed or withdrawn from the terminal, ' +
|
|
94
|
+
'and confirming a corrected wording later does NOT retire the old one (both would be in use), so confirm only ' +
|
|
95
|
+
'what the owner has read and said is right.',
|
|
96
|
+
{ fact_ids: FACT_IDS, reason: REASON, confirm_token: CONFIRM_TOKEN },
|
|
97
|
+
review('/knowledge/facts/confirm'),
|
|
98
|
+
);
|
|
99
|
+
|
|
100
|
+
server.tool(
|
|
101
|
+
'km_reject_business_facts',
|
|
102
|
+
'Reject business facts the owner says are WRONG, the same as the reject button in KM Hub under Business ' +
|
|
103
|
+
'Knowledge, so nothing ever uses them. Only on the owner\'s word about these specific facts, never on your own ' +
|
|
104
|
+
'judgement that one looks doubtful: if you think one is wrong, say so and let them decide. A rejected fact ' +
|
|
105
|
+
'cannot be reopened, and the same wording cannot be proposed again; if the owner wants a corrected version, ' +
|
|
106
|
+
'propose the corrected wording with km_propose_business_fact. ' +
|
|
107
|
+
'🚨 A confirmed write, because it cannot be undone: the first call returns 409 with the exact facts; show them, ' +
|
|
108
|
+
'wait for a real yes, then call again with the confirm_token and the SAME fact_ids. Afterwards, say plainly ' +
|
|
109
|
+
'which facts were rejected.',
|
|
110
|
+
{ fact_ids: FACT_IDS, reason: REASON, confirm_token: CONFIRM_TOKEN },
|
|
111
|
+
review('/knowledge/facts/reject'),
|
|
112
|
+
);
|
|
113
|
+
|
|
114
|
+
/** Same body on the ask and on the answer, so the confirm token's fingerprint matches. */
|
|
115
|
+
function review(path) {
|
|
116
|
+
return async ({ fact_ids, reason, confirm_token }) => {
|
|
117
|
+
const body = { fact_ids };
|
|
118
|
+
if (reason !== undefined) body.reason = reason;
|
|
119
|
+
if (confirm_token) body.confirm_token = String(confirm_token);
|
|
120
|
+
const r = await call('POST', path, body);
|
|
121
|
+
if (unsupported(r)) return text(NOT_SUPPORTED, true);
|
|
122
|
+
return out(r);
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
}
|