toolfunnel 0.7.0 → 0.8.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 +238 -235
- package/SECURITY.md +84 -84
- package/bin/toolfunnel.js +530 -451
- package/docs/KNOWN_BUGS.md +100 -80
- package/docs/MANUAL.pdf +0 -0
- package/docs/design.md +84 -84
- package/docs/packaging.md +116 -115
- package/hooks/hooks.manifest.json +27 -27
- package/hooks/scripts/example-audit.js +21 -21
- package/hooks/scripts/example-deny-dangerous.js +39 -39
- package/mcp/expose.example.json +30 -30
- package/mcp/servers/mock-modern/server.js +147 -147
- package/mcp/servers/mock-upstream/server.js +379 -380
- package/package.json +67 -67
- package/src/auth/config.js +172 -174
- package/src/auth/install.js +181 -181
- package/src/auth/resource-server.js +358 -353
- package/src/core/atomic-write.js +97 -0
- package/src/core/child-reaper.js +61 -61
- package/src/core/config-home.js +226 -134
- package/src/core/events.js +105 -105
- package/src/core/hook-engine.js +304 -329
- package/src/core/hook-loader.js +766 -824
- package/src/core/hook-runner.js +615 -566
- package/src/core/logger.js +295 -297
- package/src/core/matcher.js +100 -100
- package/src/core/metrics.js +90 -75
- package/src/core/output-cap.js +31 -0
- package/src/core/rename-migration.js +178 -163
- package/src/core/requires.js +138 -138
- package/src/core/server-config.js +98 -98
- package/src/extend/add-hook.md +155 -152
- package/src/extend/add-mcp.md +119 -119
- package/src/extend/configure.md +88 -88
- package/src/extend/create-tool.md +168 -168
- package/src/extend/howto.js +102 -102
- package/src/extend/package.md +190 -190
- package/src/extend/wrap.md +99 -99
- package/src/mcp/aggregator.js +2248 -1674
- package/src/mcp/expose-store.js +755 -577
- package/src/mcp/gated-run.js +210 -210
- package/src/mcp/http-transport.js +1657 -1563
- package/src/mcp/mcp-client.js +1174 -1070
- package/src/mcp/modern.js +409 -406
- package/src/mcp/protocol.js +473 -468
- package/src/mcp/server.js +3317 -3112
- package/src/mcp/tool-approvals.js +396 -0
- package/src/tools/registry.js +607 -661
- package/src/tools/tool-state.js +170 -170
- package/src/ui/public/app.js +1246 -1187
- package/src/ui/public/index.html +286 -286
- package/src/ui/public/styles.css +535 -535
- package/src/ui/server.js +1742 -1616
- package/tools/scripts/base64.js +139 -139
- package/tools/scripts/danger.js +61 -61
- package/tools/scripts/echo.js +39 -39
- package/tools/scripts/hash.js +101 -101
- package/tools/scripts/json.js +109 -109
- package/tools/scripts/text-stats.js +131 -131
- package/tools/scripts/tf-accept-change.js +67 -0
- package/tools/scripts/tf-env.js +43 -43
- package/tools/scripts/tf-hook-add.js +151 -151
- package/tools/scripts/tf-hook-set.js +120 -120
- package/tools/scripts/tf-list.js +192 -192
- package/tools/scripts/tf-log.js +86 -86
- package/tools/scripts/tf-mcp-add.js +130 -117
- package/tools/scripts/tf-mcp-set.js +121 -121
- package/tools/scripts/tf-pack.js +237 -237
- package/tools/scripts/tf-tool-add.js +134 -134
- package/tools/scripts/tf-tool-set.js +142 -142
- package/tools/scripts/tf-wrap.js +103 -103
- package/tools/scripts/uuid.js +102 -102
- package/tools/tools.register.json +16 -5
package/src/core/events.js
CHANGED
|
@@ -1,105 +1,105 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* events.js - lifecycle event names + per-event stdin payload builder.
|
|
5
|
-
*
|
|
6
|
-
* This is the hook contract surface: the six lifecycle events and
|
|
7
|
-
* (the exact stdin JSON shape). Field names are FROZEN - they are the hook wire contract and must
|
|
8
|
-
* match Claude Code's documented hook input byte-for-byte so the real hook
|
|
9
|
-
* scripts run unchanged. Do not rename or add fields.
|
|
10
|
-
*
|
|
11
|
-
* CommonJS only. Zero host imports (core/ must run headless under node --test).
|
|
12
|
-
*/
|
|
13
|
-
|
|
14
|
-
/**
|
|
15
|
-
* The six lifecycle events v3 supports.
|
|
16
|
-
* Values equal the `hook_event_name` written into the stdin payload.
|
|
17
|
-
* Frozen so callers can rely on identity comparison and can't mutate the set.
|
|
18
|
-
*/
|
|
19
|
-
const EVENTS = Object.freeze({
|
|
20
|
-
SessionStart: 'SessionStart',
|
|
21
|
-
UserPromptSubmit: 'UserPromptSubmit',
|
|
22
|
-
PreToolUse: 'PreToolUse',
|
|
23
|
-
PostToolUse: 'PostToolUse',
|
|
24
|
-
Stop: 'Stop',
|
|
25
|
-
PreCompact: 'PreCompact',
|
|
26
|
-
});
|
|
27
|
-
|
|
28
|
-
// Set of valid event names for fast membership checks / validation.
|
|
29
|
-
const EVENT_NAMES = Object.freeze(Object.values(EVENTS));
|
|
30
|
-
|
|
31
|
-
/**
|
|
32
|
-
* Build the stdin JSON object the runner pipes to a hook command.
|
|
33
|
-
*
|
|
34
|
-
* Every event carries the same four common fields:
|
|
35
|
-
* session_id, transcript_path, cwd, hook_event_name
|
|
36
|
-
* supplied by `ctx`. Each event then adds its own fields from `extra`:
|
|
37
|
-
*
|
|
38
|
-
* SessionStart -> source : "startup" | "resume" | "compact"
|
|
39
|
-
* UserPromptSubmit -> prompt : "<user text>"
|
|
40
|
-
* PreToolUse -> tool_name, tool_input
|
|
41
|
-
* PostToolUse -> tool_name, tool_input, tool_response
|
|
42
|
-
* Stop -> stop_hook_active : true | false
|
|
43
|
-
* PreCompact -> trigger ("manual"|"auto"), custom_instructions
|
|
44
|
-
*
|
|
45
|
-
* @param {string} event one of EVENTS (the hook_event_name).
|
|
46
|
-
* @param {object} ctx common fields: { session_id, transcript_path, cwd }.
|
|
47
|
-
* @param {object} [extra] event-specific fields (see table above).
|
|
48
|
-
* @returns {object} the stdin payload, with the contract's frozen field names.
|
|
49
|
-
* @throws {Error} if `event` is not one of the six known events.
|
|
50
|
-
*/
|
|
51
|
-
function buildPayload(event, ctx, extra) {
|
|
52
|
-
if (!EVENT_NAMES.includes(event)) {
|
|
53
|
-
throw new Error(`buildPayload: unknown event "${event}"`);
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
const c = ctx || {};
|
|
57
|
-
const e = extra || {};
|
|
58
|
-
|
|
59
|
-
// Common fields - present on EVERY event, in their contract order.
|
|
60
|
-
// hook_event_name is always the canonical event string (not whatever ctx held).
|
|
61
|
-
const payload = {
|
|
62
|
-
session_id: c.session_id,
|
|
63
|
-
transcript_path: c.transcript_path,
|
|
64
|
-
cwd: c.cwd,
|
|
65
|
-
hook_event_name: event,
|
|
66
|
-
};
|
|
67
|
-
|
|
68
|
-
// Event-specific additions. Each branch sets EXACTLY the fields the contract names -
|
|
69
|
-
// no more, no fewer - so the payload matches Claude Code's shape precisely.
|
|
70
|
-
switch (event) {
|
|
71
|
-
case EVENTS.SessionStart:
|
|
72
|
-
payload.source = e.source;
|
|
73
|
-
break;
|
|
74
|
-
|
|
75
|
-
case EVENTS.UserPromptSubmit:
|
|
76
|
-
payload.prompt = e.prompt;
|
|
77
|
-
break;
|
|
78
|
-
|
|
79
|
-
case EVENTS.PreToolUse:
|
|
80
|
-
payload.tool_name = e.tool_name;
|
|
81
|
-
payload.tool_input = e.tool_input;
|
|
82
|
-
break;
|
|
83
|
-
|
|
84
|
-
case EVENTS.PostToolUse:
|
|
85
|
-
payload.tool_name = e.tool_name;
|
|
86
|
-
payload.tool_input = e.tool_input;
|
|
87
|
-
payload.tool_response = e.tool_response;
|
|
88
|
-
break;
|
|
89
|
-
|
|
90
|
-
case EVENTS.Stop:
|
|
91
|
-
payload.stop_hook_active = e.stop_hook_active;
|
|
92
|
-
break;
|
|
93
|
-
|
|
94
|
-
case EVENTS.PreCompact:
|
|
95
|
-
payload.trigger = e.trigger;
|
|
96
|
-
payload.custom_instructions = e.custom_instructions;
|
|
97
|
-
break;
|
|
98
|
-
|
|
99
|
-
// No default: the membership check above already rejected unknown events.
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
return payload;
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
module.exports = { EVENTS, EVENT_NAMES, buildPayload };
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* events.js - lifecycle event names + per-event stdin payload builder.
|
|
5
|
+
*
|
|
6
|
+
* This is the hook contract surface: the six lifecycle events and
|
|
7
|
+
* (the exact stdin JSON shape). Field names are FROZEN - they are the hook wire contract and must
|
|
8
|
+
* match Claude Code's documented hook input byte-for-byte so the real hook
|
|
9
|
+
* scripts run unchanged. Do not rename or add fields.
|
|
10
|
+
*
|
|
11
|
+
* CommonJS only. Zero host imports (core/ must run headless under node --test).
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* The six lifecycle events v3 supports.
|
|
16
|
+
* Values equal the `hook_event_name` written into the stdin payload.
|
|
17
|
+
* Frozen so callers can rely on identity comparison and can't mutate the set.
|
|
18
|
+
*/
|
|
19
|
+
const EVENTS = Object.freeze({
|
|
20
|
+
SessionStart: 'SessionStart',
|
|
21
|
+
UserPromptSubmit: 'UserPromptSubmit',
|
|
22
|
+
PreToolUse: 'PreToolUse',
|
|
23
|
+
PostToolUse: 'PostToolUse',
|
|
24
|
+
Stop: 'Stop',
|
|
25
|
+
PreCompact: 'PreCompact',
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
// Set of valid event names for fast membership checks / validation.
|
|
29
|
+
const EVENT_NAMES = Object.freeze(Object.values(EVENTS));
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Build the stdin JSON object the runner pipes to a hook command.
|
|
33
|
+
*
|
|
34
|
+
* Every event carries the same four common fields:
|
|
35
|
+
* session_id, transcript_path, cwd, hook_event_name
|
|
36
|
+
* supplied by `ctx`. Each event then adds its own fields from `extra`:
|
|
37
|
+
*
|
|
38
|
+
* SessionStart -> source : "startup" | "resume" | "compact"
|
|
39
|
+
* UserPromptSubmit -> prompt : "<user text>"
|
|
40
|
+
* PreToolUse -> tool_name, tool_input
|
|
41
|
+
* PostToolUse -> tool_name, tool_input, tool_response
|
|
42
|
+
* Stop -> stop_hook_active : true | false
|
|
43
|
+
* PreCompact -> trigger ("manual"|"auto"), custom_instructions
|
|
44
|
+
*
|
|
45
|
+
* @param {string} event one of EVENTS (the hook_event_name).
|
|
46
|
+
* @param {object} ctx common fields: { session_id, transcript_path, cwd }.
|
|
47
|
+
* @param {object} [extra] event-specific fields (see table above).
|
|
48
|
+
* @returns {object} the stdin payload, with the contract's frozen field names.
|
|
49
|
+
* @throws {Error} if `event` is not one of the six known events.
|
|
50
|
+
*/
|
|
51
|
+
function buildPayload(event, ctx, extra) {
|
|
52
|
+
if (!EVENT_NAMES.includes(event)) {
|
|
53
|
+
throw new Error(`buildPayload: unknown event "${event}"`);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
const c = ctx || {};
|
|
57
|
+
const e = extra || {};
|
|
58
|
+
|
|
59
|
+
// Common fields - present on EVERY event, in their contract order.
|
|
60
|
+
// hook_event_name is always the canonical event string (not whatever ctx held).
|
|
61
|
+
const payload = {
|
|
62
|
+
session_id: c.session_id,
|
|
63
|
+
transcript_path: c.transcript_path,
|
|
64
|
+
cwd: c.cwd,
|
|
65
|
+
hook_event_name: event,
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
// Event-specific additions. Each branch sets EXACTLY the fields the contract names -
|
|
69
|
+
// no more, no fewer - so the payload matches Claude Code's shape precisely.
|
|
70
|
+
switch (event) {
|
|
71
|
+
case EVENTS.SessionStart:
|
|
72
|
+
payload.source = e.source;
|
|
73
|
+
break;
|
|
74
|
+
|
|
75
|
+
case EVENTS.UserPromptSubmit:
|
|
76
|
+
payload.prompt = e.prompt;
|
|
77
|
+
break;
|
|
78
|
+
|
|
79
|
+
case EVENTS.PreToolUse:
|
|
80
|
+
payload.tool_name = e.tool_name;
|
|
81
|
+
payload.tool_input = e.tool_input;
|
|
82
|
+
break;
|
|
83
|
+
|
|
84
|
+
case EVENTS.PostToolUse:
|
|
85
|
+
payload.tool_name = e.tool_name;
|
|
86
|
+
payload.tool_input = e.tool_input;
|
|
87
|
+
payload.tool_response = e.tool_response;
|
|
88
|
+
break;
|
|
89
|
+
|
|
90
|
+
case EVENTS.Stop:
|
|
91
|
+
payload.stop_hook_active = e.stop_hook_active;
|
|
92
|
+
break;
|
|
93
|
+
|
|
94
|
+
case EVENTS.PreCompact:
|
|
95
|
+
payload.trigger = e.trigger;
|
|
96
|
+
payload.custom_instructions = e.custom_instructions;
|
|
97
|
+
break;
|
|
98
|
+
|
|
99
|
+
// No default: the membership check above already rejected unknown events.
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
return payload;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
module.exports = { EVENTS, EVENT_NAMES, buildPayload };
|