@openlucaskaka/kagent 0.1.7
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 +353 -0
- package/npm/bin/kagent-serve.js +6 -0
- package/npm/bin/kagent.js +6 -0
- package/npm/lib/App.js +524 -0
- package/npm/lib/app-state.js +224 -0
- package/npm/lib/approval-choice.js +25 -0
- package/npm/lib/commands.js +59 -0
- package/npm/lib/editor.js +188 -0
- package/npm/lib/ink-runner.js +41 -0
- package/npm/lib/kagent-home.js +39 -0
- package/npm/lib/launcher.js +221 -0
- package/npm/lib/protocol.js +33 -0
- package/npm/lib/provider-setup.js +139 -0
- package/npm/lib/python-runner.js +892 -0
- package/npm/lib/runtime-client.js +390 -0
- package/npm/lib/terminal-input.js +127 -0
- package/npm/lib/terminal-text.js +19 -0
- package/npm/lib/terminal-width.js +14 -0
- package/npm/lib/transcript.js +227 -0
- package/npm/lib/ui-components.js +247 -0
- package/npm/lib/update-manager.js +334 -0
- package/package.json +39 -0
- package/pyproject.toml +55 -0
- package/src/kagent/__init__.py +90 -0
- package/src/kagent/cli/__init__.py +5 -0
- package/src/kagent/cli/__main__.py +6 -0
- package/src/kagent/cli/commands.py +112 -0
- package/src/kagent/cli/conversation.py +127 -0
- package/src/kagent/cli/interactive.py +841 -0
- package/src/kagent/cli/main.py +685 -0
- package/src/kagent/cli/memory.py +460 -0
- package/src/kagent/cli/pending_approval.py +169 -0
- package/src/kagent/cli/provider.py +27 -0
- package/src/kagent/cli/session_commands.py +401 -0
- package/src/kagent/cli/stdio_runtime.py +784 -0
- package/src/kagent/cli/trace.py +67 -0
- package/src/kagent/cli/ui.py +931 -0
- package/src/kagent/core/__init__.py +0 -0
- package/src/kagent/core/agent.py +296 -0
- package/src/kagent/core/faults.py +11 -0
- package/src/kagent/core/invariants.py +47 -0
- package/src/kagent/core/normalization.py +81 -0
- package/src/kagent/core/planning.py +48 -0
- package/src/kagent/core/state.py +73 -0
- package/src/kagent/core/summary.py +64 -0
- package/src/kagent/core/tools.py +196 -0
- package/src/kagent/core/trace.py +57 -0
- package/src/kagent/eval/__init__.py +11 -0
- package/src/kagent/eval/cases.py +229 -0
- package/src/kagent/eval/evaluator.py +216 -0
- package/src/kagent/integrations/__init__.py +3 -0
- package/src/kagent/integrations/audit.py +95 -0
- package/src/kagent/integrations/backends.py +131 -0
- package/src/kagent/integrations/memory.py +301 -0
- package/src/kagent/ops/__init__.py +0 -0
- package/src/kagent/ops/batch.py +156 -0
- package/src/kagent/ops/doctor.py +255 -0
- package/src/kagent/ops/metrics.py +214 -0
- package/src/kagent/ops/release_evidence.py +877 -0
- package/src/kagent/ops/release_manifest.py +142 -0
- package/src/kagent/ops/trace_replay.py +285 -0
- package/src/kagent/providers/__init__.py +7 -0
- package/src/kagent/providers/embeddings.py +187 -0
- package/src/kagent/providers/llm.py +770 -0
- package/src/kagent/py.typed +1 -0
- package/src/kagent/runtime/__init__.py +28 -0
- package/src/kagent/runtime/action_graph.py +543 -0
- package/src/kagent/runtime/agent.py +2089 -0
- package/src/kagent/runtime/approval.py +64 -0
- package/src/kagent/runtime/cancellation.py +64 -0
- package/src/kagent/runtime/checkpoint_state.py +146 -0
- package/src/kagent/runtime/checkpoint_storage.py +270 -0
- package/src/kagent/runtime/context.py +65 -0
- package/src/kagent/runtime/file_transaction.py +195 -0
- package/src/kagent/runtime/hooks.py +74 -0
- package/src/kagent/runtime/metadata.py +116 -0
- package/src/kagent/runtime/patch_checkpoints.py +385 -0
- package/src/kagent/runtime/policy.py +50 -0
- package/src/kagent/runtime/presentation.py +205 -0
- package/src/kagent/runtime/redaction.py +130 -0
- package/src/kagent/runtime/sandbox.py +331 -0
- package/src/kagent/runtime/skills.py +66 -0
- package/src/kagent/runtime/steering.py +56 -0
- package/src/kagent/runtime/steps.py +255 -0
- package/src/kagent/runtime/task_state.py +40 -0
- package/src/kagent/runtime/tools.py +3532 -0
- package/src/kagent/runtime/types.py +240 -0
- package/src/kagent/runtime/workspace.py +597 -0
- package/src/kagent/service/__init__.py +26 -0
- package/src/kagent/service/__main__.py +6 -0
- package/src/kagent/service/active_runs.py +178 -0
- package/src/kagent/service/cli.py +737 -0
- package/src/kagent/service/contract.py +2571 -0
- package/src/kagent/service/errors.py +71 -0
- package/src/kagent/service/idempotency.py +584 -0
- package/src/kagent/service/router.py +884 -0
- package/src/kagent/service/run.py +150 -0
- package/src/kagent/service/runtime.py +1915 -0
- package/src/kagent/service/runtime_approval.py +20 -0
- package/src/kagent/service/runtime_cancel.py +192 -0
- package/src/kagent/service/runtime_lifecycle.py +229 -0
- package/src/kagent/service/runtime_metadata.py +21 -0
- package/src/kagent/service/runtime_policy.py +115 -0
- package/src/kagent/service/runtime_recovery.py +573 -0
- package/src/kagent/service/runtime_resume.py +382 -0
- package/src/kagent/service/runtime_resume_claim.py +116 -0
- package/src/kagent/service/runtime_run.py +350 -0
- package/src/kagent/service/runtime_status.py +2007 -0
- package/src/kagent/service/safety.py +139 -0
- package/src/kagent/service/server.py +114 -0
- package/src/kagent/service/status.py +233 -0
- package/src/kagent/service/trace_store.py +322 -0
- package/src/kagent/service/transport.py +24 -0
- package/src/kagent/utils/__init__.py +0 -0
- package/src/kagent/utils/config_validation.py +21 -0
- package/src/kagent/utils/json_output.py +23 -0
- package/src/kagent/utils/paths.py +473 -0
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createAppRuntimeState = createAppRuntimeState;
|
|
4
|
+
exports.appRuntimeReducer = appRuntimeReducer;
|
|
5
|
+
const provider_setup_1 = require("./provider-setup");
|
|
6
|
+
const transcript_1 = require("./transcript");
|
|
7
|
+
function createAppRuntimeState() {
|
|
8
|
+
return {
|
|
9
|
+
transcript: (0, transcript_1.createTranscriptState)(),
|
|
10
|
+
status: "starting",
|
|
11
|
+
statusText: "",
|
|
12
|
+
approval: null,
|
|
13
|
+
provider: null,
|
|
14
|
+
setup: null,
|
|
15
|
+
commandCatalog: [],
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
function appRuntimeReducer(state, action) {
|
|
19
|
+
if (action.type === "submit") {
|
|
20
|
+
return {
|
|
21
|
+
...state,
|
|
22
|
+
transcript: (0, transcript_1.transcriptReducer)(state.transcript, {
|
|
23
|
+
type: "user_submitted",
|
|
24
|
+
text: action.text,
|
|
25
|
+
}),
|
|
26
|
+
status: "thinking",
|
|
27
|
+
statusText: action.command ? "Running command" : "Thinking",
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
if (action.type === "setup_action") {
|
|
31
|
+
return state.setup
|
|
32
|
+
? { ...state, setup: (0, provider_setup_1.providerSetupReducer)(state.setup, action.action) }
|
|
33
|
+
: state;
|
|
34
|
+
}
|
|
35
|
+
if (action.type === "approval_response") {
|
|
36
|
+
return {
|
|
37
|
+
...state,
|
|
38
|
+
approval: null,
|
|
39
|
+
status: "thinking",
|
|
40
|
+
statusText: action.approved ? "Continuing" : "Cancelling",
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
if (action.type === "cancel_requested") {
|
|
44
|
+
return { ...state, status: "cancelling", statusText: action.label };
|
|
45
|
+
}
|
|
46
|
+
if (action.type === "transcript_action") {
|
|
47
|
+
return {
|
|
48
|
+
...state,
|
|
49
|
+
transcript: (0, transcript_1.transcriptReducer)(state.transcript, action.action),
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
if (action.type === "error") {
|
|
53
|
+
return failureState(state, action.message);
|
|
54
|
+
}
|
|
55
|
+
return reduceRuntimeEvent(state, action.channel, action.event);
|
|
56
|
+
}
|
|
57
|
+
function reduceRuntimeEvent(state, channel, event) {
|
|
58
|
+
if (channel === "lifecycle") {
|
|
59
|
+
return reduceLifecycleEvent(state, event);
|
|
60
|
+
}
|
|
61
|
+
if (channel === "provider") {
|
|
62
|
+
return reduceProviderEvent(state, event);
|
|
63
|
+
}
|
|
64
|
+
if (channel === "command") {
|
|
65
|
+
return reduceCommandEvent(state, event);
|
|
66
|
+
}
|
|
67
|
+
return reduceRunEvent(state, event);
|
|
68
|
+
}
|
|
69
|
+
function reduceLifecycleEvent(state, event) {
|
|
70
|
+
if (event.type === "runtime_ready") {
|
|
71
|
+
try {
|
|
72
|
+
return {
|
|
73
|
+
...state,
|
|
74
|
+
provider: event.provider,
|
|
75
|
+
commandCatalog: event.session_commands || [],
|
|
76
|
+
setup: event.provider.configured
|
|
77
|
+
? null
|
|
78
|
+
: (0, provider_setup_1.createProviderSetupState)(event.provider_options),
|
|
79
|
+
status: "idle",
|
|
80
|
+
statusText: "",
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
catch (error) {
|
|
84
|
+
return failureState(state, errorMessage(error));
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
if (event.type === "runtime_unavailable" || event.type === "client_failed") {
|
|
88
|
+
return failureState(state, event.message);
|
|
89
|
+
}
|
|
90
|
+
return state;
|
|
91
|
+
}
|
|
92
|
+
function reduceProviderEvent(state, event) {
|
|
93
|
+
if (event.type === "provider_configured") {
|
|
94
|
+
return {
|
|
95
|
+
...state,
|
|
96
|
+
provider: event.provider,
|
|
97
|
+
setup: null,
|
|
98
|
+
status: "idle",
|
|
99
|
+
statusText: "",
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
if (event.type === "provider_configuration_failed" || event.type === "client_failed") {
|
|
103
|
+
if (!state.setup) {
|
|
104
|
+
return failureState(state, event.message);
|
|
105
|
+
}
|
|
106
|
+
return {
|
|
107
|
+
...state,
|
|
108
|
+
setup: (0, provider_setup_1.providerSetupReducer)(state.setup, {
|
|
109
|
+
type: "failure",
|
|
110
|
+
message: event.message,
|
|
111
|
+
field: event.type === "provider_configuration_failed" ? event.field : undefined,
|
|
112
|
+
}),
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
return state;
|
|
116
|
+
}
|
|
117
|
+
function reduceCommandEvent(state, event) {
|
|
118
|
+
if (event.type === "session_command_completed") {
|
|
119
|
+
return {
|
|
120
|
+
...state,
|
|
121
|
+
status: "idle",
|
|
122
|
+
statusText: "",
|
|
123
|
+
transcript: (0, transcript_1.transcriptReducer)(state.transcript, {
|
|
124
|
+
type: "command_completed",
|
|
125
|
+
title: event.title,
|
|
126
|
+
text: event.message,
|
|
127
|
+
clear: event.clear_messages,
|
|
128
|
+
}),
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
if (event.type === "session_command_failed" || event.type === "client_failed") {
|
|
132
|
+
return failureState(state, event.message);
|
|
133
|
+
}
|
|
134
|
+
return state;
|
|
135
|
+
}
|
|
136
|
+
function reduceRunEvent(state, event) {
|
|
137
|
+
if (event.type === "run_started") {
|
|
138
|
+
return { ...state, status: "thinking", statusText: "Thinking" };
|
|
139
|
+
}
|
|
140
|
+
if (event.type === "run_progress") {
|
|
141
|
+
const transcriptAction = (0, transcript_1.progressTranscriptAction)(event.event);
|
|
142
|
+
return {
|
|
143
|
+
...state,
|
|
144
|
+
statusText: progressLabel(event.event),
|
|
145
|
+
transcript: transcriptAction
|
|
146
|
+
? (0, transcript_1.transcriptReducer)(state.transcript, transcriptAction)
|
|
147
|
+
: state.transcript,
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
if (event.type === "run_cancel_requested") {
|
|
151
|
+
return { ...state, status: "cancelling", statusText: "Stopping" };
|
|
152
|
+
}
|
|
153
|
+
if (event.type === "run_steer_queued") {
|
|
154
|
+
return {
|
|
155
|
+
...state,
|
|
156
|
+
status: "thinking",
|
|
157
|
+
statusText: event.replaced === "true" ? "Instruction updated" : "Instruction queued",
|
|
158
|
+
};
|
|
159
|
+
}
|
|
160
|
+
if (event.type === "run_steer_rejected") {
|
|
161
|
+
return {
|
|
162
|
+
...state,
|
|
163
|
+
statusText: "Instruction was not applied",
|
|
164
|
+
};
|
|
165
|
+
}
|
|
166
|
+
if (event.type === "approval_required") {
|
|
167
|
+
return { ...state, approval: event, status: "approval", statusText: "" };
|
|
168
|
+
}
|
|
169
|
+
if (event.type === "run_completed") {
|
|
170
|
+
const fallback = event.status === "cancelled" ? "Action cancelled." : "Done.";
|
|
171
|
+
return {
|
|
172
|
+
...state,
|
|
173
|
+
approval: null,
|
|
174
|
+
status: "idle",
|
|
175
|
+
statusText: "",
|
|
176
|
+
transcript: (0, transcript_1.transcriptReducer)(state.transcript, {
|
|
177
|
+
type: "assistant_completed",
|
|
178
|
+
text: event.answer || fallback,
|
|
179
|
+
outcome: event.status === "cancelled" ? "cancelled" : "complete",
|
|
180
|
+
}),
|
|
181
|
+
};
|
|
182
|
+
}
|
|
183
|
+
if (event.type === "run_failed") {
|
|
184
|
+
const message = event.error_code === "approval_execution_interrupted"
|
|
185
|
+
? "Action outcome is uncertain. kagent did not retry it. Check the target before trying again."
|
|
186
|
+
: event.message;
|
|
187
|
+
return failureState({ ...state, approval: null }, message);
|
|
188
|
+
}
|
|
189
|
+
if (event.type === "client_failed") {
|
|
190
|
+
return failureState({ ...state, approval: null }, event.message);
|
|
191
|
+
}
|
|
192
|
+
return state;
|
|
193
|
+
}
|
|
194
|
+
function failureState(state, message) {
|
|
195
|
+
return {
|
|
196
|
+
...state,
|
|
197
|
+
approval: null,
|
|
198
|
+
status: "error",
|
|
199
|
+
statusText: "",
|
|
200
|
+
transcript: (0, transcript_1.transcriptReducer)(state.transcript, { type: "error", text: message }),
|
|
201
|
+
};
|
|
202
|
+
}
|
|
203
|
+
function progressLabel(event) {
|
|
204
|
+
const type = String(event.type || "");
|
|
205
|
+
if (type === "steering_applied") {
|
|
206
|
+
return "Updating direction";
|
|
207
|
+
}
|
|
208
|
+
if (type === "planner_started") {
|
|
209
|
+
return "Thinking";
|
|
210
|
+
}
|
|
211
|
+
if (type === "plan_ready") {
|
|
212
|
+
return "Planning next steps";
|
|
213
|
+
}
|
|
214
|
+
if (type === "tool_started") {
|
|
215
|
+
return "Working";
|
|
216
|
+
}
|
|
217
|
+
if (type === "tool_completed") {
|
|
218
|
+
return "Reviewing result";
|
|
219
|
+
}
|
|
220
|
+
return type.endsWith("failed") ? "Retrying" : "Working";
|
|
221
|
+
}
|
|
222
|
+
function errorMessage(error) {
|
|
223
|
+
return error instanceof Error ? error.message : String(error);
|
|
224
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.resolveApprovalInput = resolveApprovalInput;
|
|
4
|
+
function resolveApprovalInput(choice, value, keyName = "") {
|
|
5
|
+
const answer = value.toLowerCase();
|
|
6
|
+
if (answer === "d") {
|
|
7
|
+
return { type: "toggle_details" };
|
|
8
|
+
}
|
|
9
|
+
if (answer === "y") {
|
|
10
|
+
return { type: "submit", approved: true };
|
|
11
|
+
}
|
|
12
|
+
if (answer === "n") {
|
|
13
|
+
return { type: "submit", approved: false };
|
|
14
|
+
}
|
|
15
|
+
if (keyName === "left" || keyName === "up") {
|
|
16
|
+
return { type: "select", choice: "allow" };
|
|
17
|
+
}
|
|
18
|
+
if (keyName === "right" || keyName === "down") {
|
|
19
|
+
return { type: "select", choice: "deny" };
|
|
20
|
+
}
|
|
21
|
+
if (keyName === "enter" || keyName === "return") {
|
|
22
|
+
return { type: "submit", approved: choice === "allow" };
|
|
23
|
+
}
|
|
24
|
+
return null;
|
|
25
|
+
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.updateCommandMenu = updateCommandMenu;
|
|
4
|
+
exports.moveCommandSelection = moveCommandSelection;
|
|
5
|
+
exports.commandCompletion = commandCompletion;
|
|
6
|
+
function updateCommandMenu(catalog, input, previous) {
|
|
7
|
+
const query = commandQuery(input);
|
|
8
|
+
if (query === null) {
|
|
9
|
+
return null;
|
|
10
|
+
}
|
|
11
|
+
const normalized = query.toLowerCase();
|
|
12
|
+
const options = catalog.filter((option) => commandNames(option).some((name) => name.toLowerCase().startsWith(normalized)));
|
|
13
|
+
if (options.length === 0) {
|
|
14
|
+
return null;
|
|
15
|
+
}
|
|
16
|
+
const selectedCommand = typeof previous === "string" ? previous : previous?.selectedCommand;
|
|
17
|
+
const previousIndex = selectedCommand
|
|
18
|
+
? options.findIndex((option) => option.command === selectedCommand)
|
|
19
|
+
: -1;
|
|
20
|
+
const selectedIndex = previousIndex >= 0 ? previousIndex : 0;
|
|
21
|
+
return {
|
|
22
|
+
query,
|
|
23
|
+
options,
|
|
24
|
+
selectedIndex,
|
|
25
|
+
selectedCommand: options[selectedIndex].command,
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
function moveCommandSelection(state, offset) {
|
|
29
|
+
if (offset === 0 || state.options.length === 0) {
|
|
30
|
+
return state;
|
|
31
|
+
}
|
|
32
|
+
const selectedIndex = wrapIndex(state.selectedIndex + offset, state.options.length);
|
|
33
|
+
return {
|
|
34
|
+
...state,
|
|
35
|
+
selectedIndex,
|
|
36
|
+
selectedCommand: state.options[selectedIndex].command,
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
function commandCompletion(state) {
|
|
40
|
+
const selected = state.options[state.selectedIndex];
|
|
41
|
+
if (!selected) {
|
|
42
|
+
return state.query;
|
|
43
|
+
}
|
|
44
|
+
const commandName = selected.command.split(/\s+/, 1)[0];
|
|
45
|
+
return selected.command.includes(" ") ? `${commandName} ` : commandName;
|
|
46
|
+
}
|
|
47
|
+
function commandQuery(input) {
|
|
48
|
+
const value = input.trimStart();
|
|
49
|
+
if (!value.startsWith("/") || /\s/.test(value)) {
|
|
50
|
+
return null;
|
|
51
|
+
}
|
|
52
|
+
return value;
|
|
53
|
+
}
|
|
54
|
+
function commandNames(option) {
|
|
55
|
+
return [option.command.split(/\s+/, 1)[0], ...option.aliases];
|
|
56
|
+
}
|
|
57
|
+
function wrapIndex(value, length) {
|
|
58
|
+
return ((value % length) + length) % length;
|
|
59
|
+
}
|
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.splitGraphemes = void 0;
|
|
4
|
+
exports.createEditorState = createEditorState;
|
|
5
|
+
exports.insertInput = insertInput;
|
|
6
|
+
exports.deleteBeforeCursor = deleteBeforeCursor;
|
|
7
|
+
exports.deleteAtCursor = deleteAtCursor;
|
|
8
|
+
exports.moveCursor = moveCursor;
|
|
9
|
+
exports.moveCursorVertical = moveCursorVertical;
|
|
10
|
+
exports.editorVisualLineCount = editorVisualLineCount;
|
|
11
|
+
exports.moveCursorToStart = moveCursorToStart;
|
|
12
|
+
exports.moveCursorToEnd = moveCursorToEnd;
|
|
13
|
+
exports.submitInput = submitInput;
|
|
14
|
+
exports.navigateHistory = navigateHistory;
|
|
15
|
+
const terminal_text_1 = require("./terminal-text");
|
|
16
|
+
var terminal_text_2 = require("./terminal-text");
|
|
17
|
+
Object.defineProperty(exports, "splitGraphemes", { enumerable: true, get: function () { return terminal_text_2.splitGraphemes; } });
|
|
18
|
+
function createEditorState(history = []) {
|
|
19
|
+
return {
|
|
20
|
+
value: "",
|
|
21
|
+
cursor: 0,
|
|
22
|
+
history: history.slice(),
|
|
23
|
+
historyIndex: null,
|
|
24
|
+
draft: "",
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
function insertInput(state, rawInput) {
|
|
28
|
+
const characters = (0, terminal_text_1.splitGraphemes)(state.value);
|
|
29
|
+
const cursor = clampCursor(state.cursor, characters.length);
|
|
30
|
+
const before = characters.slice(0, cursor).join("");
|
|
31
|
+
const inserted = (0, terminal_text_1.splitGraphemes)(rawInput).filter(isPrintableGrapheme).join("");
|
|
32
|
+
const after = characters.slice(cursor).join("");
|
|
33
|
+
const prefix = before + inserted;
|
|
34
|
+
return editBuffer(state, prefix + after, (0, terminal_text_1.splitGraphemes)(prefix).length);
|
|
35
|
+
}
|
|
36
|
+
function deleteBeforeCursor(state) {
|
|
37
|
+
const characters = (0, terminal_text_1.splitGraphemes)(state.value);
|
|
38
|
+
const cursor = clampCursor(state.cursor, characters.length);
|
|
39
|
+
if (cursor === 0) {
|
|
40
|
+
return state;
|
|
41
|
+
}
|
|
42
|
+
characters.splice(cursor - 1, 1);
|
|
43
|
+
return editBuffer(state, characters.join(""), cursor - 1);
|
|
44
|
+
}
|
|
45
|
+
function deleteAtCursor(state) {
|
|
46
|
+
const characters = (0, terminal_text_1.splitGraphemes)(state.value);
|
|
47
|
+
const cursor = clampCursor(state.cursor, characters.length);
|
|
48
|
+
if (cursor === characters.length) {
|
|
49
|
+
return state;
|
|
50
|
+
}
|
|
51
|
+
characters.splice(cursor, 1);
|
|
52
|
+
return editBuffer(state, characters.join(""), cursor);
|
|
53
|
+
}
|
|
54
|
+
function moveCursor(state, offset) {
|
|
55
|
+
const length = (0, terminal_text_1.splitGraphemes)(state.value).length;
|
|
56
|
+
return {
|
|
57
|
+
...state,
|
|
58
|
+
cursor: clampCursor(state.cursor + offset, length),
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
function moveCursorVertical(state, direction, columns = Number.MAX_SAFE_INTEGER) {
|
|
62
|
+
const characters = (0, terminal_text_1.splitGraphemes)(state.value);
|
|
63
|
+
const cursor = clampCursor(state.cursor, characters.length);
|
|
64
|
+
const positions = visualCursorPositions(characters, columns);
|
|
65
|
+
const current = positions[cursor];
|
|
66
|
+
const targetRow = current.row + direction;
|
|
67
|
+
if (targetRow < 0 || targetRow >= positions.at(-1).row + 1) {
|
|
68
|
+
return state;
|
|
69
|
+
}
|
|
70
|
+
let targetCursor = cursor;
|
|
71
|
+
let targetDistance = Number.MAX_SAFE_INTEGER;
|
|
72
|
+
positions.forEach((position, index) => {
|
|
73
|
+
if (position.row !== targetRow) {
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
const distance = Math.abs(position.column - current.column);
|
|
77
|
+
if (distance < targetDistance) {
|
|
78
|
+
targetCursor = index;
|
|
79
|
+
targetDistance = distance;
|
|
80
|
+
}
|
|
81
|
+
});
|
|
82
|
+
return {
|
|
83
|
+
...state,
|
|
84
|
+
cursor: targetCursor,
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
function editorVisualLineCount(value, columns) {
|
|
88
|
+
const positions = visualCursorPositions((0, terminal_text_1.splitGraphemes)(value), columns);
|
|
89
|
+
const finalPosition = positions.at(-1);
|
|
90
|
+
return finalPosition.row + 1;
|
|
91
|
+
}
|
|
92
|
+
function moveCursorToStart(state) {
|
|
93
|
+
return { ...state, cursor: 0 };
|
|
94
|
+
}
|
|
95
|
+
function moveCursorToEnd(state) {
|
|
96
|
+
return { ...state, cursor: (0, terminal_text_1.splitGraphemes)(state.value).length };
|
|
97
|
+
}
|
|
98
|
+
function submitInput(state) {
|
|
99
|
+
const value = state.value.trim();
|
|
100
|
+
if (!value) {
|
|
101
|
+
return { value: null, state };
|
|
102
|
+
}
|
|
103
|
+
return {
|
|
104
|
+
value,
|
|
105
|
+
state: createEditorState(state.history.concat(value)),
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
function navigateHistory(state, offset) {
|
|
109
|
+
if (state.history.length === 0 || offset === 0) {
|
|
110
|
+
return state;
|
|
111
|
+
}
|
|
112
|
+
if (offset < 0) {
|
|
113
|
+
const historyIndex = state.historyIndex === null
|
|
114
|
+
? state.history.length - 1
|
|
115
|
+
: Math.max(state.historyIndex - 1, 0);
|
|
116
|
+
return historyState(state, historyIndex, state.historyIndex === null ? state.value : state.draft);
|
|
117
|
+
}
|
|
118
|
+
if (state.historyIndex === null) {
|
|
119
|
+
return state;
|
|
120
|
+
}
|
|
121
|
+
if (state.historyIndex < state.history.length - 1) {
|
|
122
|
+
return historyState(state, state.historyIndex + 1, state.draft);
|
|
123
|
+
}
|
|
124
|
+
return {
|
|
125
|
+
...state,
|
|
126
|
+
value: state.draft,
|
|
127
|
+
cursor: (0, terminal_text_1.splitGraphemes)(state.draft).length,
|
|
128
|
+
historyIndex: null,
|
|
129
|
+
draft: "",
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
function historyState(state, historyIndex, draft) {
|
|
133
|
+
const value = state.history[historyIndex];
|
|
134
|
+
return {
|
|
135
|
+
...state,
|
|
136
|
+
value,
|
|
137
|
+
cursor: (0, terminal_text_1.splitGraphemes)(value).length,
|
|
138
|
+
historyIndex,
|
|
139
|
+
draft,
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
function editBuffer(state, value, cursor) {
|
|
143
|
+
return {
|
|
144
|
+
...state,
|
|
145
|
+
value,
|
|
146
|
+
cursor,
|
|
147
|
+
...(isEditorState(state) ? { historyIndex: null, draft: "" } : {}),
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
function isEditorState(state) {
|
|
151
|
+
return "history" in state;
|
|
152
|
+
}
|
|
153
|
+
function clampCursor(cursor, length) {
|
|
154
|
+
return Math.min(Math.max(cursor, 0), length);
|
|
155
|
+
}
|
|
156
|
+
function visualCursorPositions(characters, columns) {
|
|
157
|
+
const safeColumns = Math.max(1, Math.trunc(columns));
|
|
158
|
+
const positions = [{ row: 0, column: 0 }];
|
|
159
|
+
let row = 0;
|
|
160
|
+
let column = 0;
|
|
161
|
+
characters.forEach((character) => {
|
|
162
|
+
if (character === "\n") {
|
|
163
|
+
row += 1;
|
|
164
|
+
column = 0;
|
|
165
|
+
}
|
|
166
|
+
else {
|
|
167
|
+
const width = (0, terminal_text_1.terminalGraphemeWidth)(character);
|
|
168
|
+
if (column > 0 && column + width > safeColumns) {
|
|
169
|
+
row += 1;
|
|
170
|
+
column = 0;
|
|
171
|
+
}
|
|
172
|
+
column += width;
|
|
173
|
+
if (column >= safeColumns) {
|
|
174
|
+
row += 1;
|
|
175
|
+
column = 0;
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
positions.push({ row, column });
|
|
179
|
+
});
|
|
180
|
+
return positions;
|
|
181
|
+
}
|
|
182
|
+
function isPrintableGrapheme(character) {
|
|
183
|
+
if (character === "\n") {
|
|
184
|
+
return true;
|
|
185
|
+
}
|
|
186
|
+
const codePoint = character.codePointAt(0) || 0;
|
|
187
|
+
return codePoint >= 32 && codePoint !== 127;
|
|
188
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.shouldRunInkTui = shouldRunInkTui;
|
|
4
|
+
exports.runKagentInk = runKagentInk;
|
|
5
|
+
const App_1 = require("./App");
|
|
6
|
+
const dynamicImport = new Function("specifier", "return import(specifier)");
|
|
7
|
+
function shouldRunInkTui(args, stdin) {
|
|
8
|
+
if (process.env.KAGENT_CLASSIC_UI) {
|
|
9
|
+
return false;
|
|
10
|
+
}
|
|
11
|
+
if (args.includes("--classic")) {
|
|
12
|
+
return false;
|
|
13
|
+
}
|
|
14
|
+
if (args.length > 0) {
|
|
15
|
+
return false;
|
|
16
|
+
}
|
|
17
|
+
return Boolean(stdin && stdin.isTTY);
|
|
18
|
+
}
|
|
19
|
+
async function runKagentInk(_args, options = {}) {
|
|
20
|
+
try {
|
|
21
|
+
const React = (await dynamicImport("react"));
|
|
22
|
+
const Ink = (await dynamicImport("ink"));
|
|
23
|
+
const element = React.createElement(App_1.KagentInkApp, { React, Ink: Ink });
|
|
24
|
+
Ink.render(element, { exitOnCtrlC: false });
|
|
25
|
+
}
|
|
26
|
+
catch (error) {
|
|
27
|
+
if (typeof options.fallback === "function") {
|
|
28
|
+
process.stderr.write(`kagent: terminal UI unavailable: ${errorMessage(error)}; using classic CLI\n`);
|
|
29
|
+
options.fallback();
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
throw error;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
function errorMessage(error) {
|
|
36
|
+
return error instanceof Error ? error.message : String(error);
|
|
37
|
+
}
|
|
38
|
+
module.exports = {
|
|
39
|
+
runKagentInk,
|
|
40
|
+
shouldRunInkTui,
|
|
41
|
+
};
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.resolveKagentHome = resolveKagentHome;
|
|
7
|
+
exports.kagentStatePath = kagentStatePath;
|
|
8
|
+
exports.kagentCachePath = kagentCachePath;
|
|
9
|
+
const node_os_1 = __importDefault(require("node:os"));
|
|
10
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
11
|
+
function requiredHome(env) {
|
|
12
|
+
const home = env.HOME?.trim();
|
|
13
|
+
return home || node_os_1.default.homedir();
|
|
14
|
+
}
|
|
15
|
+
function resolveKagentHome(env = process.env) {
|
|
16
|
+
const configured = env.KAGENT_HOME;
|
|
17
|
+
if (Object.prototype.hasOwnProperty.call(env, "KAGENT_HOME")) {
|
|
18
|
+
if (!configured?.trim()) {
|
|
19
|
+
throw new Error("KAGENT_HOME must not be empty");
|
|
20
|
+
}
|
|
21
|
+
if (configured === "~") {
|
|
22
|
+
return node_path_1.default.resolve(requiredHome(env));
|
|
23
|
+
}
|
|
24
|
+
if (configured.startsWith("~/")) {
|
|
25
|
+
return node_path_1.default.resolve(requiredHome(env), configured.slice(2));
|
|
26
|
+
}
|
|
27
|
+
if (!node_path_1.default.isAbsolute(configured)) {
|
|
28
|
+
throw new Error("KAGENT_HOME must be an absolute or tilde-prefixed path");
|
|
29
|
+
}
|
|
30
|
+
return node_path_1.default.resolve(configured);
|
|
31
|
+
}
|
|
32
|
+
return node_path_1.default.resolve(requiredHome(env), ".kagent");
|
|
33
|
+
}
|
|
34
|
+
function kagentStatePath(name, env = process.env) {
|
|
35
|
+
return node_path_1.default.join(resolveKagentHome(env), "state", name);
|
|
36
|
+
}
|
|
37
|
+
function kagentCachePath(name, env = process.env) {
|
|
38
|
+
return node_path_1.default.join(resolveKagentHome(env), "cache", name);
|
|
39
|
+
}
|