@openlucaskaka/kagent 0.1.8 → 0.1.9

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/npm/lib/App.js CHANGED
@@ -462,6 +462,14 @@ function KagentInkApp({ React, Ink, runtimeSessionFactory = runtime_client_1.cre
462
462
  rows: layout.rows,
463
463
  reservedRows: layout.reservedRows + (transcriptOffset > 0 ? 1 : 0),
464
464
  }, transcriptOffset);
465
+ const promptDisabled = status === "cancelling" || status === "approval";
466
+ const promptCursorControl = (0, ui_components_1.createPromptTerminalCursorControl)({
467
+ input: editor.value,
468
+ cursor: editor.cursor,
469
+ columns: layout.promptColumns,
470
+ maxRows: layout.promptRowLimit,
471
+ horizontalPadding: layout.horizontalPadding,
472
+ });
465
473
  return React.createElement(Box, { flexDirection: "column", paddingX: layout.horizontalPadding }, transcript.entries.length === 0
466
474
  ? React.createElement(ui_components_1.Header, {
467
475
  React,
@@ -504,16 +512,31 @@ function KagentInkApp({ React, Ink, runtimeSessionFactory = runtime_client_1.cre
504
512
  })
505
513
  : null, status === "starting"
506
514
  ? null
507
- : React.createElement(ui_components_1.PromptLine, {
515
+ : React.createElement(React.Fragment, null, React.createElement(ui_components_1.PromptLine, {
508
516
  React,
509
517
  Box,
510
518
  Text,
511
519
  cursor: editor.cursor,
512
520
  input: editor.value,
513
- disabled: status === "cancelling" || status === "approval",
521
+ disabled: promptDisabled,
514
522
  columns: layout.promptColumns,
515
523
  maxRows: layout.promptRowLimit,
516
- }));
524
+ }), React.createElement(TerminalCursorSync, {
525
+ React,
526
+ control: promptDisabled ? null : promptCursorControl,
527
+ })));
528
+ }
529
+ function TerminalCursorSync({ React, control, }) {
530
+ React.useLayoutEffect(() => {
531
+ if (!control || !process.stdout.isTTY) {
532
+ return undefined;
533
+ }
534
+ process.stdout.write(control.position);
535
+ return () => {
536
+ process.stdout.write(control.restore);
537
+ };
538
+ });
539
+ return null;
517
540
  }
518
541
  function currentTerminalSize() {
519
542
  return {
@@ -4,6 +4,7 @@ exports.TERMINAL_SPINNER_FRAMES = void 0;
4
4
  exports.createTerminalLayout = createTerminalLayout;
5
5
  exports.NarrowTerminal = NarrowTerminal;
6
6
  exports.createPromptViewport = createPromptViewport;
7
+ exports.createPromptTerminalCursorControl = createPromptTerminalCursorControl;
7
8
  exports.Header = Header;
8
9
  exports.ProviderSetupPanel = ProviderSetupPanel;
9
10
  exports.MessageList = MessageList;
@@ -115,6 +116,18 @@ function createPromptViewport(input, cursor, columns, maxRows) {
115
116
  }
116
117
  return promptViewportParts(characters, safeCursor, start, end, preserveActiveNewline);
117
118
  }
119
+ function createPromptTerminalCursorControl({ input, cursor, columns, maxRows, horizontalPadding, }) {
120
+ const viewport = createPromptViewport(input, cursor, columns, maxRows);
121
+ const safeColumns = Math.max(4, columns);
122
+ const cursorPosition = textEndPosition(viewport.before, safeColumns);
123
+ const promptRows = (0, terminal_width_1.estimateTextRows)(viewport.rendered, safeColumns);
124
+ const up = Math.max(1, promptRows - cursorPosition.row);
125
+ const right = Math.max(0, horizontalPadding + 2 + cursorPosition.column);
126
+ return {
127
+ position: `${showTerminalCursor()}${moveCursorUp(up)}${moveCursorRight(right)}`,
128
+ restore: `\r${moveCursorDown(up)}`,
129
+ };
130
+ }
118
131
  function promptViewportRows(characters, cursor, start, end, columns, preserveActiveNewline) {
119
132
  return (0, terminal_width_1.estimateTextRows)(promptViewportParts(characters, cursor, start, end, preserveActiveNewline).rendered, columns);
120
133
  }
@@ -136,6 +149,38 @@ function promptViewportParts(characters, cursor, start, end, preserveActiveNewli
136
149
  suffixClipped,
137
150
  };
138
151
  }
152
+ function textEndPosition(text, columns) {
153
+ let row = 0;
154
+ let column = 0;
155
+ for (const grapheme of (0, editor_1.splitGraphemes)(text)) {
156
+ if (grapheme === "\n") {
157
+ row += 1;
158
+ column = 0;
159
+ continue;
160
+ }
161
+ const width = Math.max(0, (0, terminal_text_1.terminalGraphemeWidth)(grapheme));
162
+ if (column + width >= columns) {
163
+ row += 1;
164
+ column = 0;
165
+ }
166
+ else {
167
+ column += width;
168
+ }
169
+ }
170
+ return { row, column };
171
+ }
172
+ function showTerminalCursor() {
173
+ return "\u001b[?25h";
174
+ }
175
+ function moveCursorUp(rows) {
176
+ return rows > 0 ? `\u001b[${rows}A` : "";
177
+ }
178
+ function moveCursorDown(rows) {
179
+ return rows > 0 ? `\u001b[${rows}B` : "";
180
+ }
181
+ function moveCursorRight(columns) {
182
+ return columns > 0 ? `\u001b[${columns}C` : "";
183
+ }
139
184
  function Header({ React, Box, Text, compact, provider, setup, workspace, }) {
140
185
  const providerLabel = provider?.configured
141
186
  ? `${(0, terminal_text_1.terminalSafeText)(provider.display_name)}${provider.model ? ` · ${(0, terminal_text_1.terminalSafeText)(provider.model)}` : ""}`
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openlucaskaka/kagent",
3
- "version": "0.1.8",
3
+ "version": "0.1.9",
4
4
  "description": "Codex-style LangGraph agent runtime for internal non-coding workflows.",
5
5
  "license": "UNLICENSED",
6
6
  "bin": {
package/pyproject.toml CHANGED
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "kagent"
7
- version = "0.1.8"
7
+ version = "0.1.9"
8
8
  description = "A bounded kagent built with LangGraph."
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.9"
@@ -22,7 +22,7 @@ def _source_tree_version() -> str:
22
22
  try:
23
23
  __version__ = _source_tree_version() or version("kagent")
24
24
  except PackageNotFoundError:
25
- __version__ = "0.1.8"
25
+ __version__ = "0.1.9"
26
26
 
27
27
  __all__ = [
28
28
  "AgentConfig",
@@ -128,6 +128,10 @@ _EMBEDDING_RETRY_BACKOFF_ENV_VAR = "KAGENT_EMBEDDING_RETRY_BACKOFF_SECONDS"
128
128
  _EXTERNAL_BACKEND_TIMEOUT_ENV_VAR = "KAGENT_EXTERNAL_BACKEND_TIMEOUT_SECONDS"
129
129
  _APP_NAME_MAX_LENGTH = 120
130
130
  _APP_NAME_ALLOWED_PATTERN = re.compile(r"^[\w .+()#&-]+$", re.UNICODE)
131
+ _APP_NAME_ALIASES = {
132
+ "飞书": "Feishu",
133
+ "feishu": "Feishu",
134
+ }
131
135
  _OPEN_COMMAND_TIMEOUT_SECONDS = 10.0
132
136
 
133
137
 
@@ -3005,24 +3009,47 @@ def _open_app(input_payload: Dict[str, Any]) -> Dict[str, Any]:
3005
3009
  if not isinstance(application, str) or not application.strip():
3006
3010
  raise ValueError("application must be a non-empty string")
3007
3011
  normalized_application = " ".join(application.strip().split())
3012
+ normalized_application = _APP_NAME_ALIASES.get(
3013
+ normalized_application.casefold(),
3014
+ normalized_application,
3015
+ )
3008
3016
  _validate_open_app_name(normalized_application)
3009
- try:
3010
- subprocess.run(
3011
- ["open", "-a", normalized_application],
3012
- check=True,
3013
- capture_output=True,
3014
- text=True,
3015
- timeout=_OPEN_COMMAND_TIMEOUT_SECONDS,
3016
- )
3017
- except subprocess.TimeoutExpired as exc:
3018
- raise TimeoutError("open app command timed out") from exc
3019
- except (OSError, subprocess.CalledProcessError) as exc:
3020
- raise ValueError("open app failed") from exc
3021
- return {
3022
- "application": normalized_application,
3023
- "opened": True,
3024
- "command": "open -a",
3025
- }
3017
+ attempts = [
3018
+ (
3019
+ ["osascript", "-e", _app_frontmost_script(normalized_application)],
3020
+ "osascript frontmost",
3021
+ ),
3022
+ (["open", "-a", normalized_application], "open -a"),
3023
+ ]
3024
+ last_error: BaseException | None = None
3025
+ for command_args, command_label in attempts:
3026
+ try:
3027
+ subprocess.run(
3028
+ command_args,
3029
+ check=True,
3030
+ capture_output=True,
3031
+ text=True,
3032
+ timeout=_OPEN_COMMAND_TIMEOUT_SECONDS,
3033
+ )
3034
+ return {
3035
+ "application": normalized_application,
3036
+ "opened": True,
3037
+ "command": command_label,
3038
+ }
3039
+ except subprocess.TimeoutExpired as exc:
3040
+ raise TimeoutError("open app command timed out") from exc
3041
+ except (OSError, subprocess.CalledProcessError) as exc:
3042
+ last_error = exc
3043
+ continue
3044
+ raise ValueError("open app failed") from last_error
3045
+
3046
+
3047
+ def _app_frontmost_script(application: str) -> str:
3048
+ escaped = application.replace("\\", "\\\\").replace('"', '\\"')
3049
+ return (
3050
+ 'tell application "System Events" to set frontmost of '
3051
+ f'first application process whose name is "{escaped}" to true'
3052
+ )
3026
3053
 
3027
3054
 
3028
3055
  def _validate_open_app_name(application: str) -> None:
@@ -42,7 +42,7 @@ def service_openapi() -> Dict[str, Any]:
42
42
  "openapi": "3.1.0",
43
43
  "info": {
44
44
  "title": "kagent API",
45
- "version": "0.1.8",
45
+ "version": "0.1.9",
46
46
  },
47
47
  "components": {
48
48
  "securitySchemes": {