@kkelly-offical/kkcode 0.1.6 → 0.2.1
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/LICENSE +674 -674
- package/README.md +452 -387
- package/package.json +50 -46
- package/src/agent/agent.mjs +19 -2
- package/src/agent/custom-agent-loader.mjs +6 -3
- package/src/agent/generator.mjs +2 -2
- package/src/agent/prompt/assistant.txt +12 -0
- package/src/agent/prompt/bug-hunter.txt +90 -0
- package/src/agent/prompt/frontend-designer.txt +58 -58
- package/src/agent/prompt/guide.txt +1 -1
- package/src/agent/prompt/longagent-blueprint-agent.txt +83 -83
- package/src/agent/prompt/longagent-coding-agent.txt +37 -37
- package/src/agent/prompt/longagent-debugging-agent.txt +46 -46
- package/src/agent/prompt/longagent-preview-agent.txt +63 -63
- package/src/command/custom-commands.mjs +2 -2
- package/src/commands/agent.mjs +1 -1
- package/src/commands/background.mjs +145 -4
- package/src/commands/chat.mjs +117 -76
- package/src/commands/config.mjs +148 -1
- package/src/commands/doctor.mjs +30 -6
- package/src/commands/init.mjs +32 -6
- package/src/commands/longagent.mjs +117 -0
- package/src/commands/mcp.mjs +275 -43
- package/src/commands/permission.mjs +1 -1
- package/src/commands/session.mjs +195 -140
- package/src/commands/skill.mjs +63 -0
- package/src/commands/theme.mjs +1 -1
- package/src/config/defaults.mjs +280 -260
- package/src/config/import-config.mjs +1 -1
- package/src/config/load-config.mjs +61 -4
- package/src/config/schema.mjs +591 -574
- package/src/context.mjs +4 -1
- package/src/core/constants.mjs +97 -91
- package/src/core/types.mjs +1 -1
- package/src/github/api.mjs +78 -78
- package/src/github/auth.mjs +294 -286
- package/src/github/flow.mjs +298 -298
- package/src/github/workspace.mjs +225 -212
- package/src/index.mjs +84 -82
- package/src/knowledge/frontend-aesthetics.txt +38 -38
- package/src/mcp/client-http.mjs +139 -141
- package/src/mcp/client-sse.mjs +297 -288
- package/src/mcp/client-stdio.mjs +534 -533
- package/src/mcp/constants.mjs +2 -2
- package/src/mcp/registry.mjs +498 -479
- package/src/mcp/stdio-framing.mjs +135 -133
- package/src/mcp/tool-result.mjs +24 -24
- package/src/observability/edit-diagnostics.mjs +449 -0
- package/src/observability/index.mjs +42 -42
- package/src/observability/metrics.mjs +165 -137
- package/src/observability/tracer.mjs +137 -137
- package/src/onboarding.mjs +209 -0
- package/src/orchestration/background-manager.mjs +567 -372
- package/src/orchestration/background-worker.mjs +419 -305
- package/src/orchestration/interruption-reason.mjs +21 -0
- package/src/orchestration/longagent-manager.mjs +197 -171
- package/src/orchestration/stage-scheduler.mjs +733 -728
- package/src/orchestration/subagent-router.mjs +7 -1
- package/src/orchestration/task-scheduler.mjs +219 -7
- package/src/permission/engine.mjs +1 -1
- package/src/permission/exec-policy.mjs +370 -370
- package/src/permission/file-edit-policy.mjs +108 -0
- package/src/permission/prompt.mjs +1 -1
- package/src/permission/rules.mjs +116 -7
- package/src/plugin/builtin-hooks/post-edit-format.mjs +2 -1
- package/src/plugin/builtin-hooks/post-edit-typecheck.mjs +104 -40
- package/src/plugin/hook-bus.mjs +19 -5
- package/src/plugin/manifest-loader.mjs +222 -0
- package/src/provider/anthropic.mjs +396 -390
- package/src/provider/ollama.mjs +7 -1
- package/src/provider/openai.mjs +382 -340
- package/src/provider/retry-policy.mjs +74 -68
- package/src/provider/router.mjs +242 -241
- package/src/provider/sse.mjs +104 -104
- package/src/provider/wizard.mjs +556 -0
- package/src/repl/capability-facade.mjs +30 -0
- package/src/repl/command-surface.mjs +23 -0
- package/src/repl/controller-entry.mjs +40 -0
- package/src/repl/core-shell.mjs +208 -0
- package/src/repl/dialog-router.mjs +87 -0
- package/src/repl/input-engine.mjs +76 -0
- package/src/repl/keymap.mjs +7 -0
- package/src/repl/operator-surface.mjs +15 -0
- package/src/repl/permission-flow.mjs +49 -0
- package/src/repl/runtime-facade.mjs +36 -0
- package/src/repl/slash-router.mjs +62 -0
- package/src/repl/state-store.mjs +29 -0
- package/src/repl/turn-controller.mjs +58 -0
- package/src/repl/verification.mjs +23 -0
- package/src/repl.mjs +3368 -2929
- package/src/rules/load-rules.mjs +3 -3
- package/src/runtime.mjs +1 -1
- package/src/session/agent-transaction.mjs +86 -0
- package/src/session/checkpoint.mjs +302 -302
- package/src/session/compaction.mjs +36 -14
- package/src/session/engine.mjs +417 -227
- package/src/session/longagent-4stage.mjs +467 -460
- package/src/session/longagent-hybrid.mjs +1344 -1081
- package/src/session/longagent-plan.mjs +376 -365
- package/src/session/longagent-project-memory.mjs +53 -53
- package/src/session/longagent-scaffold.mjs +291 -291
- package/src/session/longagent-task-bus.mjs +138 -54
- package/src/session/longagent-utils.mjs +828 -472
- package/src/session/longagent.mjs +911 -884
- package/src/session/loop.mjs +1005 -905
- package/src/session/prompt/agent.txt +25 -0
- package/src/session/prompt/anthropic.txt +150 -150
- package/src/session/prompt/beast.txt +1 -1
- package/src/session/prompt/plan.txt +28 -6
- package/src/session/prompt/qwen.txt +46 -46
- package/src/session/recovery.mjs +21 -0
- package/src/session/rollback.mjs +197 -0
- package/src/session/routing-observability.mjs +72 -0
- package/src/session/runtime-state.mjs +47 -0
- package/src/session/store.mjs +523 -510
- package/src/session/system-prompt.mjs +56 -8
- package/src/session/task-validator.mjs +267 -267
- package/src/session/usability-gates.mjs +2 -2
- package/src/skill/builtin/commit.mjs +64 -64
- package/src/skill/builtin/design.mjs +76 -76
- package/src/skill/generator.mjs +18 -2
- package/src/skill/registry.mjs +642 -390
- package/src/storage/audit-store.mjs +18 -11
- package/src/storage/event-log.mjs +7 -1
- package/src/storage/ghost-commit-store.mjs +243 -245
- package/src/storage/paths.mjs +13 -0
- package/src/theme/default-theme.mjs +1 -1
- package/src/theme/markdown.mjs +4 -0
- package/src/theme/schema.mjs +1 -1
- package/src/theme/status-bar.mjs +162 -158
- package/src/tool/audit-wrapper.mjs +18 -2
- package/src/tool/edit-transaction.mjs +23 -0
- package/src/tool/executor.mjs +26 -1
- package/src/tool/file-read-state.mjs +65 -0
- package/src/tool/git-auto.mjs +526 -526
- package/src/tool/git-full-auto.mjs +487 -478
- package/src/tool/mutation-guard.mjs +54 -0
- package/src/tool/prompt/edit.txt +3 -3
- package/src/tool/prompt/multiedit.txt +1 -0
- package/src/tool/prompt/notebookedit.txt +2 -1
- package/src/tool/prompt/patch.txt +25 -24
- package/src/tool/prompt/read.txt +3 -3
- package/src/tool/prompt/sysinfo.txt +29 -0
- package/src/tool/prompt/task.txt +66 -4
- package/src/tool/prompt/write.txt +2 -2
- package/src/tool/question-prompt.mjs +17 -4
- package/src/tool/registry.mjs +1701 -1343
- package/src/tool/task-tool.mjs +14 -6
- package/src/ui/activity-renderer.mjs +667 -664
- package/src/ui/repl-background-panel.mjs +7 -0
- package/src/ui/repl-capability-panel.mjs +9 -0
- package/src/ui/repl-dashboard.mjs +54 -4
- package/src/ui/repl-help.mjs +110 -0
- package/src/ui/repl-operator-panel.mjs +12 -0
- package/src/ui/repl-route-feedback.mjs +35 -0
- package/src/ui/repl-status-view.mjs +76 -0
- package/src/ui/repl-task-panel.mjs +5 -0
- package/src/ui/repl-transcript-panel.mjs +56 -0
- package/src/ui/repl-turn-summary.mjs +135 -0
- package/src/usage/pricing.mjs +122 -121
- package/src/usage/usage-meter.mjs +1 -0
- package/src/util/git.mjs +562 -519
- package/src/util/template.mjs +6 -1
|
@@ -1,39 +1,39 @@
|
|
|
1
|
-
<frontend_aesthetics>
|
|
2
|
-
## Frontend Design Quality Rules
|
|
3
|
-
|
|
4
|
-
When building frontend UI, avoid generic "AI-generated" aesthetics. Make creative, distinctive choices.
|
|
5
|
-
|
|
6
|
-
### Typography
|
|
7
|
-
- Avoid default fonts (Inter, Roboto, Arial, system-ui). Choose distinctive fonts.
|
|
8
|
-
- Use high contrast: pair display fonts with monospace, serif with geometric sans.
|
|
9
|
-
- Use extreme weight differences (200 vs 800) and 3x+ size jumps.
|
|
10
|
-
- Load fonts from Google Fonts via <link> or @import.
|
|
11
|
-
|
|
12
|
-
### Color
|
|
13
|
-
- Define ALL colors as CSS variables in :root.
|
|
14
|
-
- Use a dominant color with 1-2 sharp accents. Avoid evenly-distributed palettes.
|
|
15
|
-
- Draw from real palettes: IDE themes (Nord, Catppuccin, Dracula), nature, cultural aesthetics.
|
|
16
|
-
- AVOID: purple gradients on white, generic blue buttons, gray-on-gray cards.
|
|
17
|
-
|
|
18
|
-
### Motion
|
|
19
|
-
- One high-impact animation per page (staggered reveal on load).
|
|
20
|
-
- Micro-interactions: hover lift, focus glow, press feedback.
|
|
21
|
-
- Use CSS transitions/animations. Use animation-delay for staggered effects.
|
|
22
|
-
|
|
23
|
-
### Layout
|
|
24
|
-
- CSS Grid for page structure, Flexbox for components.
|
|
25
|
-
- Generous whitespace. Consistent spacing scale (4/8/12/16/24/32/48/64px).
|
|
26
|
-
- Mobile-first responsive design.
|
|
27
|
-
|
|
28
|
-
### Depth & Atmosphere
|
|
29
|
-
- Layered gradients, subtle patterns, backdrop-filter for glass effects.
|
|
30
|
-
- Elevation hierarchy via box-shadow (not just border).
|
|
31
|
-
- Noise/grain textures for premium feel.
|
|
32
|
-
|
|
33
|
-
### What NOT to do
|
|
34
|
-
- Cookie-cutter card grids with identical rounded corners
|
|
35
|
-
- Generic hero with centered text + gradient
|
|
36
|
-
- border-radius: 9999px on everything
|
|
37
|
-
- Gray placeholder text that looks like wireframe
|
|
38
|
-
- No visual rhythm (identical spacing everywhere)
|
|
1
|
+
<frontend_aesthetics>
|
|
2
|
+
## Frontend Design Quality Rules
|
|
3
|
+
|
|
4
|
+
When building frontend UI, avoid generic "AI-generated" aesthetics. Make creative, distinctive choices.
|
|
5
|
+
|
|
6
|
+
### Typography
|
|
7
|
+
- Avoid default fonts (Inter, Roboto, Arial, system-ui). Choose distinctive fonts.
|
|
8
|
+
- Use high contrast: pair display fonts with monospace, serif with geometric sans.
|
|
9
|
+
- Use extreme weight differences (200 vs 800) and 3x+ size jumps.
|
|
10
|
+
- Load fonts from Google Fonts via <link> or @import.
|
|
11
|
+
|
|
12
|
+
### Color
|
|
13
|
+
- Define ALL colors as CSS variables in :root.
|
|
14
|
+
- Use a dominant color with 1-2 sharp accents. Avoid evenly-distributed palettes.
|
|
15
|
+
- Draw from real palettes: IDE themes (Nord, Catppuccin, Dracula), nature, cultural aesthetics.
|
|
16
|
+
- AVOID: purple gradients on white, generic blue buttons, gray-on-gray cards.
|
|
17
|
+
|
|
18
|
+
### Motion
|
|
19
|
+
- One high-impact animation per page (staggered reveal on load).
|
|
20
|
+
- Micro-interactions: hover lift, focus glow, press feedback.
|
|
21
|
+
- Use CSS transitions/animations. Use animation-delay for staggered effects.
|
|
22
|
+
|
|
23
|
+
### Layout
|
|
24
|
+
- CSS Grid for page structure, Flexbox for components.
|
|
25
|
+
- Generous whitespace. Consistent spacing scale (4/8/12/16/24/32/48/64px).
|
|
26
|
+
- Mobile-first responsive design.
|
|
27
|
+
|
|
28
|
+
### Depth & Atmosphere
|
|
29
|
+
- Layered gradients, subtle patterns, backdrop-filter for glass effects.
|
|
30
|
+
- Elevation hierarchy via box-shadow (not just border).
|
|
31
|
+
- Noise/grain textures for premium feel.
|
|
32
|
+
|
|
33
|
+
### What NOT to do
|
|
34
|
+
- Cookie-cutter card grids with identical rounded corners
|
|
35
|
+
- Generic hero with centered text + gradient
|
|
36
|
+
- border-radius: 9999px on everything
|
|
37
|
+
- Gray placeholder text that looks like wireframe
|
|
38
|
+
- No visual rhythm (identical spacing everywhere)
|
|
39
39
|
</frontend_aesthetics>
|
package/src/mcp/client-http.mjs
CHANGED
|
@@ -1,141 +1,139 @@
|
|
|
1
|
-
import { McpError } from "../core/errors.mjs"
|
|
2
|
-
import { EventBus } from "../core/events.mjs"
|
|
3
|
-
import { EVENT_TYPES } from "../core/constants.mjs"
|
|
4
|
-
import { normalizeToolResult } from "./tool-result.mjs"
|
|
5
|
-
|
|
6
|
-
function timeoutSignal(ms, parentSignal = null) {
|
|
7
|
-
const own = AbortSignal.timeout(ms)
|
|
8
|
-
if (!parentSignal) return own
|
|
9
|
-
return AbortSignal.any([parentSignal, own])
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
function classifyHttpError(error, status = null) {
|
|
13
|
-
const msg = String(error?.message || error || "")
|
|
14
|
-
if (msg.includes("AbortError") || msg.includes("timeout") || msg.includes("abort")) return "timeout"
|
|
15
|
-
if (msg.includes("ECONNREFUSED") || msg.includes("fetch failed")) return "connection_refused"
|
|
16
|
-
if (status && status >= 500) return "server_crash"
|
|
17
|
-
if (status && status >= 400) return "bad_response"
|
|
18
|
-
return "unknown"
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
async function requestJson({ serverName, method, url, body = null, timeoutMs = 10000, headers = {}, signal = null }) {
|
|
22
|
-
const action = method === "GET" ? url.split("/").pop() : body?.args ? "call_tool" : "request"
|
|
23
|
-
const startedAt = Date.now()
|
|
24
|
-
let status = null
|
|
25
|
-
|
|
26
|
-
try {
|
|
27
|
-
const res = await fetch(url, {
|
|
28
|
-
method,
|
|
29
|
-
headers: {
|
|
30
|
-
"content-type": "application/json",
|
|
31
|
-
...headers
|
|
32
|
-
},
|
|
33
|
-
body: body ? JSON.stringify(body) : undefined,
|
|
34
|
-
signal: timeoutSignal(timeoutMs, signal)
|
|
35
|
-
})
|
|
36
|
-
|
|
37
|
-
status = res.status
|
|
38
|
-
const elapsed = Date.now() - startedAt
|
|
39
|
-
|
|
40
|
-
EventBus.emit({
|
|
41
|
-
type: EVENT_TYPES.MCP_REQUEST,
|
|
42
|
-
payload: { server: serverName, action, method, elapsed, status }
|
|
43
|
-
}).catch(() => {})
|
|
44
|
-
|
|
45
|
-
if (!res.ok) {
|
|
46
|
-
const text = await res.text().catch(() => "")
|
|
47
|
-
const reason = classifyHttpError(null, status)
|
|
48
|
-
throw new McpError(
|
|
49
|
-
`mcp server "${serverName}" HTTP ${status} on ${method} ${url}: ${text.slice(0, 500)}`,
|
|
50
|
-
{ reason, server: serverName, action, phase: "request", statusCode: status }
|
|
51
|
-
)
|
|
52
|
-
}
|
|
53
|
-
return res.json().catch((parseErr) => {
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
const
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
return { ok:
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
return
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
return
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
return
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
}
|
|
141
|
-
}
|
|
1
|
+
import { McpError } from "../core/errors.mjs"
|
|
2
|
+
import { EventBus } from "../core/events.mjs"
|
|
3
|
+
import { EVENT_TYPES } from "../core/constants.mjs"
|
|
4
|
+
import { normalizeToolResult } from "./tool-result.mjs"
|
|
5
|
+
|
|
6
|
+
function timeoutSignal(ms, parentSignal = null) {
|
|
7
|
+
const own = AbortSignal.timeout(ms)
|
|
8
|
+
if (!parentSignal) return own
|
|
9
|
+
return AbortSignal.any([parentSignal, own])
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
function classifyHttpError(error, status = null) {
|
|
13
|
+
const msg = String(error?.message || error || "")
|
|
14
|
+
if (msg.includes("AbortError") || msg.includes("timeout") || msg.includes("abort")) return "timeout"
|
|
15
|
+
if (msg.includes("ECONNREFUSED") || msg.includes("fetch failed")) return "connection_refused"
|
|
16
|
+
if (status && status >= 500) return "server_crash"
|
|
17
|
+
if (status && status >= 400) return "bad_response"
|
|
18
|
+
return "unknown"
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
async function requestJson({ serverName, method, url, body = null, timeoutMs = 10000, headers = {}, signal = null }) {
|
|
22
|
+
const action = method === "GET" ? url.split("/").pop() : body?.args ? "call_tool" : "request"
|
|
23
|
+
const startedAt = Date.now()
|
|
24
|
+
let status = null
|
|
25
|
+
|
|
26
|
+
try {
|
|
27
|
+
const res = await fetch(url, {
|
|
28
|
+
method,
|
|
29
|
+
headers: {
|
|
30
|
+
"content-type": "application/json",
|
|
31
|
+
...headers
|
|
32
|
+
},
|
|
33
|
+
body: body ? JSON.stringify(body) : undefined,
|
|
34
|
+
signal: timeoutSignal(timeoutMs, signal)
|
|
35
|
+
})
|
|
36
|
+
|
|
37
|
+
status = res.status
|
|
38
|
+
const elapsed = Date.now() - startedAt
|
|
39
|
+
|
|
40
|
+
EventBus.emit({
|
|
41
|
+
type: EVENT_TYPES.MCP_REQUEST,
|
|
42
|
+
payload: { server: serverName, action, method, elapsed, status }
|
|
43
|
+
}).catch(() => {})
|
|
44
|
+
|
|
45
|
+
if (!res.ok) {
|
|
46
|
+
const text = await res.text().catch(() => "")
|
|
47
|
+
const reason = classifyHttpError(null, status)
|
|
48
|
+
throw new McpError(
|
|
49
|
+
`mcp server "${serverName}" HTTP ${status} on ${method} ${url}: ${text.slice(0, 500)}`,
|
|
50
|
+
{ reason, server: serverName, action, phase: "request", statusCode: status }
|
|
51
|
+
)
|
|
52
|
+
}
|
|
53
|
+
return res.json().catch((parseErr) => {
|
|
54
|
+
throw new McpError(
|
|
55
|
+
`mcp server "${serverName}" malformed JSON response: ${parseErr.message}`,
|
|
56
|
+
{ reason: "bad_response", server: serverName, action: body?.method || "request", phase: "request" }
|
|
57
|
+
)
|
|
58
|
+
})
|
|
59
|
+
} catch (error) {
|
|
60
|
+
if (error instanceof McpError) throw error
|
|
61
|
+
const reason = classifyHttpError(error, status)
|
|
62
|
+
throw new McpError(
|
|
63
|
+
`mcp server "${serverName}" ${reason} on ${method} ${url}: ${error.message}`,
|
|
64
|
+
{ reason, server: serverName, action, phase: "request", statusCode: status }
|
|
65
|
+
)
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
export function createHttpMcpClient(serverName, config) {
|
|
70
|
+
const baseUrl = String(config.url || "").replace(/\/$/, "")
|
|
71
|
+
const timeoutMs = Number(config.timeout_ms || 10000)
|
|
72
|
+
const headers = config.headers || {}
|
|
73
|
+
|
|
74
|
+
return {
|
|
75
|
+
serverName,
|
|
76
|
+
transport: "http",
|
|
77
|
+
async health() {
|
|
78
|
+
try {
|
|
79
|
+
await requestJson({ serverName, method: "GET", url: `${baseUrl}/health`, timeoutMs, headers })
|
|
80
|
+
return { ok: true }
|
|
81
|
+
} catch (error) {
|
|
82
|
+
return { ok: false, error: error.message, reason: error.reason || "unknown" }
|
|
83
|
+
}
|
|
84
|
+
},
|
|
85
|
+
async listTools() {
|
|
86
|
+
const out = await requestJson({ serverName, method: "GET", url: `${baseUrl}/tools`, timeoutMs, headers })
|
|
87
|
+
return Array.isArray(out?.tools) ? out.tools : []
|
|
88
|
+
},
|
|
89
|
+
async listPrompts() {
|
|
90
|
+
try {
|
|
91
|
+
const out = await requestJson({ serverName, method: "GET", url: `${baseUrl}/prompts`, timeoutMs, headers })
|
|
92
|
+
return Array.isArray(out?.prompts) ? out.prompts : []
|
|
93
|
+
} catch {
|
|
94
|
+
return []
|
|
95
|
+
}
|
|
96
|
+
},
|
|
97
|
+
async getPrompt(name, args = {}) {
|
|
98
|
+
return requestJson({
|
|
99
|
+
serverName,
|
|
100
|
+
method: "POST",
|
|
101
|
+
url: `${baseUrl}/prompts/${encodeURIComponent(name)}`,
|
|
102
|
+
body: { arguments: args },
|
|
103
|
+
timeoutMs,
|
|
104
|
+
headers
|
|
105
|
+
})
|
|
106
|
+
},
|
|
107
|
+
async listResources() {
|
|
108
|
+
try {
|
|
109
|
+
const out = await requestJson({ serverName, method: "GET", url: `${baseUrl}/resources`, timeoutMs, headers })
|
|
110
|
+
return Array.isArray(out?.resources) ? out.resources : []
|
|
111
|
+
} catch {
|
|
112
|
+
return []
|
|
113
|
+
}
|
|
114
|
+
},
|
|
115
|
+
async listTemplates() {
|
|
116
|
+
try {
|
|
117
|
+
const out = await requestJson({ serverName, method: "GET", url: `${baseUrl}/templates`, timeoutMs, headers })
|
|
118
|
+
return Array.isArray(out?.templates) ? out.templates : []
|
|
119
|
+
} catch {
|
|
120
|
+
return []
|
|
121
|
+
}
|
|
122
|
+
},
|
|
123
|
+
async callTool(name, args = {}, signal = null) {
|
|
124
|
+
const result = await requestJson({
|
|
125
|
+
serverName,
|
|
126
|
+
method: "POST",
|
|
127
|
+
url: `${baseUrl}/tools/${encodeURIComponent(name)}`,
|
|
128
|
+
body: { arguments: args },
|
|
129
|
+
timeoutMs,
|
|
130
|
+
headers,
|
|
131
|
+
signal
|
|
132
|
+
})
|
|
133
|
+
return normalizeToolResult(result, serverName, name)
|
|
134
|
+
},
|
|
135
|
+
shutdown() {
|
|
136
|
+
// HTTP client is stateless — no persistent connections to clean up
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
}
|