ikie-cli 0.1.33 → 0.1.34

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 CHANGED
@@ -79,7 +79,7 @@ Ikie has 28 built-in tools, grouped by purpose:
79
79
  - **Memory** — `memory_write` (persist notes across sessions, project- or global-scoped)
80
80
  - **Delegation** — `spawn_agent` (hand isolated/parallel work to a focused sub-agent), `ask_user`
81
81
  - **Skills** — `use_skill`, `install_skill`, `remove_skill`
82
- - **MCP** — `mcp_list`, `mcp_add`, `mcp_install`, `mcp_start`, `mcp_stop`, `mcp_call`, `mcp_uninstall`
82
+ - **MCP** — `mcp_list`, `mcp_add` (configured servers expose tools as `mcp__server__tool`)
83
83
  - **Mode** — `switch_mode`
84
84
 
85
85
  ---
@@ -102,21 +102,37 @@ You can also manage them with `/skills`.
102
102
 
103
103
  ## MCP (Model Context Protocol)
104
104
 
105
- Extend Ikie with external MCP servers. Paste a Claude/Cline-style config and Ikie
106
- will wire it up:
105
+ Extend Ikie with external MCP servers. When a server is configured, each of its
106
+ tools appears as a first-class tool named `mcp__<server>__<tool>` — call them
107
+ directly, no meta-tool dance.
108
+
109
+ Paste a Claude/Cline-style config and Ikie will wire it up:
107
110
 
108
111
  ```
109
112
  claude mcp add magic --scope user --env API_KEY="…" -- npx -y @21st-dev/magic@latest
110
113
  ```
111
114
 
112
- Then start it and its tools become available:
113
-
114
- ```
115
- / (use the slash menu) → mcp_start magic
115
+ Or create a `.mcp.json` file in the project root (or `.mcp.local.json` for
116
+ machine-local overrides, or `~/.ikie/mcp.json` for global ones):
117
+
118
+ ```json
119
+ {
120
+ "mcpServers": {
121
+ "magic": {
122
+ "type": "stdio",
123
+ "command": "npx",
124
+ "args": ["-y", "@21st-dev/magic@latest"],
125
+ "env": { "API_KEY": "…" },
126
+ "enabled": true,
127
+ "autoStart": true
128
+ }
129
+ }
130
+ }
116
131
  ```
117
132
 
118
- Built-in MCPs include **filesystem**, **github**, **database** (SQLite/Postgres),
119
- and **puppeteer** (browser automation).
133
+ In the REPL, use `/mcp` to list servers and their tools, `/mcp add <line>` to
134
+ add one from a `claude mcp add …` line, `/mcp remove <name>`, and `/mcp reconnect
135
+ <name>`.
120
136
 
121
137
  ---
122
138
 
@@ -136,6 +152,7 @@ Type `/` to open the command menu. Highlights:
136
152
  | `/model <name>` · `/models` | Switch or list models |
137
153
  | `/settings [show\|model\|reset]` | View/change persisted settings |
138
154
  | `/skills` | List, show, install, or remove skills |
155
+ | `/mcp` · `/mcp add` · `/mcp remove` · `/mcp reconnect` | MCP server status and management |
139
156
  | `/theme [name]` | Change the color theme |
140
157
  | `/usage` · `/tokens` | Account usage/credit and token estimate |
141
158
  | `/rpm <n>` | Set the model request-per-minute limit |
package/dist/agent.d.ts CHANGED
@@ -6,7 +6,13 @@ export interface AgentOptions {
6
6
  autoApprove?: boolean;
7
7
  signal?: AbortSignal;
8
8
  startedAt?: number;
9
+ /** Max model→tool round-trips in a single turn before forcing a graceful stop. */
10
+ maxSteps?: number;
9
11
  }
12
+ /** Default per-turn step budget — guards against runaway tool loops. */
13
+ export declare const DEFAULT_MAX_STEPS = 60;
14
+ /** Result synthesized for a tool call that never produced one (cancel/crash). */
15
+ export declare const INTERRUPTED_TOOL_RESULT = "Interrupted: this tool did not run to completion (the turn was cancelled).";
10
16
  /** Plan = read-only research + propose; Agent = full execution. */
11
17
  export type AgentMode = 'agent' | 'plan';
12
18
  export interface AgentTurnStats {
@@ -20,6 +26,32 @@ export declare function estimateTokens(chars: number): number;
20
26
  * The SDK wraps provider responses; we prefer the nested error.message if it exists.
21
27
  */
22
28
  export declare function extractUpstreamError(err: unknown): string;
29
+ /**
30
+ * Guarantee the OpenAI invariant: every `assistant` message that carries
31
+ * `tool_calls` is followed by a `tool` message for each call id. A turn that is
32
+ * cancelled (ESC/Ctrl-C), throws mid-stream, or is restored from a session saved
33
+ * mid-flight can leave "dangling" tool calls with no result — and the provider
34
+ * then rejects the *next* request ("an assistant message with 'tool_calls' must
35
+ * be followed by tool messages"). This splices a synthetic result for any
36
+ * unanswered call so history is always replayable. Pure and idempotent.
37
+ */
38
+ export declare function repairDanglingToolCalls(messages: ChatCompletionMessageParam[]): ChatCompletionMessageParam[];
39
+ /**
40
+ * Whether the agent loop should make another model call. We continue purely on
41
+ * "there were tool calls to answer" — NOT on `finishReason`, because some
42
+ * providers send `finish_reason: 'stop'` (or null) alongside tool calls, which
43
+ * would otherwise silently drop the calls. `maxSteps` caps runaway loops.
44
+ */
45
+ export declare function shouldContinue(toolCallCount: number, _finishReason: string, step: number, maxSteps: number): boolean;
46
+ /**
47
+ * Drop malformed tool calls (no function name) accumulated from a stream. An
48
+ * unnamed call can't be dispatched or answered, so keeping it would create an
49
+ * un-satisfiable `tool_calls` entry. Applied to both the dispatch list and the
50
+ * assistant message so they stay in lockstep.
51
+ */
52
+ export declare function normalizeToolCalls<T extends {
53
+ name: string;
54
+ }>(calls: T[]): T[];
23
55
  /**
24
56
  * Safely restore previously-saved stdin listeners after a raw-mode interaction
25
57
  * (permission prompt, ask_user, theme picker, agent turn).
@@ -62,16 +94,28 @@ export declare class Agent {
62
94
  private groupToolCalls;
63
95
  private formatGroupSummary;
64
96
  private runLoop;
97
+ /**
98
+ * Final wrap-up when the per-turn step budget is exhausted. One model call with
99
+ * tools disabled, so it produces a plain summary and can never leave a dangling
100
+ * tool call. Best-effort: failures here don't throw out of the turn.
101
+ */
102
+ private summarizeAndStop;
65
103
  private callModel;
66
104
  private buildParams;
67
105
  private throttleModelRequest;
68
106
  private callModelStreaming;
69
107
  private callModelNonStreaming;
70
108
  private handleToolCall;
109
+ private handleUseSkill;
71
110
  private handleSwitchMode;
72
111
  private requestModeSwitch;
73
112
  private askUser;
74
113
  private runSubagent;
114
+ /**
115
+ * Best-effort: one tool-less model call asking for a concise, self-contained
116
+ * summary of the work so far. Used to guarantee a non-empty subagent result.
117
+ */
118
+ requestFinalSummary(signal?: AbortSignal): Promise<string>;
75
119
  getLastAssistantText(): string;
76
120
  private checkPermission;
77
121
  }