@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,150 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import contextlib
|
|
4
|
+
import io
|
|
5
|
+
import json
|
|
6
|
+
import warnings
|
|
7
|
+
from concurrent.futures import ThreadPoolExecutor, TimeoutError
|
|
8
|
+
from typing import Any, Callable, Dict, Optional, Tuple
|
|
9
|
+
|
|
10
|
+
from kagent.service import errors as service_errors
|
|
11
|
+
from kagent.service.active_runs import ExecutionSlotLease
|
|
12
|
+
from kagent.service.errors import failure_payload
|
|
13
|
+
from kagent.service.runtime import ServiceConfig
|
|
14
|
+
from kagent.service.trace_store import persist_trace
|
|
15
|
+
from kagent.utils.config_validation import (
|
|
16
|
+
optional_json_bool,
|
|
17
|
+
optional_json_int,
|
|
18
|
+
)
|
|
19
|
+
from kagent.utils.json_output import json_ready
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def execute_run_request(
|
|
23
|
+
body: bytes,
|
|
24
|
+
service_config: ServiceConfig,
|
|
25
|
+
agent_runner: Optional[Callable[[str, Any], Dict[str, Any]]] = None,
|
|
26
|
+
execution_slot_lease: Optional[ExecutionSlotLease] = None,
|
|
27
|
+
) -> Tuple[int, Dict[str, Any]]:
|
|
28
|
+
try:
|
|
29
|
+
payload = json.loads(body.decode("utf-8"))
|
|
30
|
+
except (UnicodeDecodeError, json.JSONDecodeError) as exc:
|
|
31
|
+
return 400, failure_payload(service_errors.INVALID_JSON, f"invalid JSON: {exc}")
|
|
32
|
+
if not isinstance(payload, dict):
|
|
33
|
+
return 400, failure_payload(
|
|
34
|
+
service_errors.INVALID_REQUEST_BODY,
|
|
35
|
+
"request body must be a JSON object",
|
|
36
|
+
)
|
|
37
|
+
goal = str(payload.get("goal", ""))
|
|
38
|
+
if not goal.strip():
|
|
39
|
+
return 400, failure_payload(service_errors.MISSING_GOAL, "goal is required")
|
|
40
|
+
if len(goal) > service_config.max_goal_chars:
|
|
41
|
+
return 413, failure_payload(
|
|
42
|
+
service_errors.GOAL_TOO_LARGE,
|
|
43
|
+
"goal exceeds max_goal_chars",
|
|
44
|
+
)
|
|
45
|
+
try:
|
|
46
|
+
wants_full_trace = optional_json_bool(payload, "full_trace", False)
|
|
47
|
+
except ValueError as exc:
|
|
48
|
+
return 400, failure_payload(service_errors.INVALID_REQUEST_BODY, str(exc))
|
|
49
|
+
if wants_full_trace and not service_config.allow_full_trace_response:
|
|
50
|
+
return 403, failure_payload(
|
|
51
|
+
service_errors.FULL_TRACE_DISABLED,
|
|
52
|
+
"full_trace responses are disabled",
|
|
53
|
+
)
|
|
54
|
+
|
|
55
|
+
warning_sink = io.StringIO()
|
|
56
|
+
with contextlib.redirect_stderr(warning_sink), warnings.catch_warnings():
|
|
57
|
+
warnings.simplefilter("ignore")
|
|
58
|
+
from kagent.core.agent import AgentConfig, run_agent
|
|
59
|
+
from kagent.core.summary import summarize_run
|
|
60
|
+
|
|
61
|
+
try:
|
|
62
|
+
defaults = AgentConfig()
|
|
63
|
+
config = AgentConfig(
|
|
64
|
+
max_steps=optional_int(payload, "max_steps", defaults.max_steps),
|
|
65
|
+
max_retries=optional_int(payload, "max_retries", defaults.max_retries),
|
|
66
|
+
)
|
|
67
|
+
except ValueError as exc:
|
|
68
|
+
return 400, failure_payload(service_errors.INVALID_AGENT_CONFIG, str(exc))
|
|
69
|
+
|
|
70
|
+
def run_with_config() -> Dict[str, Any]:
|
|
71
|
+
if agent_runner is not None:
|
|
72
|
+
return agent_runner(goal, config)
|
|
73
|
+
return run_agent(goal, config=config)
|
|
74
|
+
|
|
75
|
+
try:
|
|
76
|
+
release_worker_slot = (
|
|
77
|
+
execution_slot_lease.transfer()
|
|
78
|
+
if execution_slot_lease is not None
|
|
79
|
+
else None
|
|
80
|
+
)
|
|
81
|
+
timeout_options = {"timeout_seconds": service_config.run_timeout_seconds}
|
|
82
|
+
if release_worker_slot is not None:
|
|
83
|
+
timeout_options["on_complete"] = release_worker_slot
|
|
84
|
+
trace = run_with_timeout(run_with_config, **timeout_options)
|
|
85
|
+
except TimeoutError:
|
|
86
|
+
return 504, failure_payload(
|
|
87
|
+
service_errors.AGENT_RUN_TIMEOUT,
|
|
88
|
+
"agent run timed out",
|
|
89
|
+
)
|
|
90
|
+
except Exception:
|
|
91
|
+
return 500, failure_payload(service_errors.AGENT_RUN_FAILED, "agent run failed")
|
|
92
|
+
trace_path = ""
|
|
93
|
+
if service_config.trace_dir:
|
|
94
|
+
try:
|
|
95
|
+
trace_path = persist_trace(trace, service_config.trace_dir)
|
|
96
|
+
except OSError as exc:
|
|
97
|
+
return 500, failure_payload(
|
|
98
|
+
service_errors.TRACE_PERSISTENCE_FAILED,
|
|
99
|
+
f"could not persist trace: {exc}",
|
|
100
|
+
)
|
|
101
|
+
result = trace if wants_full_trace else summarize_run(trace)
|
|
102
|
+
if trace_path:
|
|
103
|
+
result["trace_path"] = trace_path
|
|
104
|
+
return 200, json_ready(result)
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
def run_with_timeout(
|
|
108
|
+
call,
|
|
109
|
+
*,
|
|
110
|
+
timeout_seconds: float,
|
|
111
|
+
on_timeout: Optional[Callable[[], None]] = None,
|
|
112
|
+
on_complete: Optional[Callable[[], None]] = None,
|
|
113
|
+
) -> Dict[str, Any]:
|
|
114
|
+
executor = ThreadPoolExecutor(max_workers=1)
|
|
115
|
+
|
|
116
|
+
def run_and_complete() -> Dict[str, Any]:
|
|
117
|
+
try:
|
|
118
|
+
return call()
|
|
119
|
+
finally:
|
|
120
|
+
if on_complete is not None:
|
|
121
|
+
try:
|
|
122
|
+
on_complete()
|
|
123
|
+
except Exception:
|
|
124
|
+
# Lifecycle cleanup must not replace the worker result or error.
|
|
125
|
+
pass
|
|
126
|
+
|
|
127
|
+
future = executor.submit(run_and_complete)
|
|
128
|
+
try:
|
|
129
|
+
try:
|
|
130
|
+
return future.result(timeout=timeout_seconds)
|
|
131
|
+
except TimeoutError as timeout_error:
|
|
132
|
+
if future.done():
|
|
133
|
+
return future.result()
|
|
134
|
+
if on_timeout is not None:
|
|
135
|
+
on_timeout()
|
|
136
|
+
try:
|
|
137
|
+
future.result(timeout=timeout_seconds)
|
|
138
|
+
except TimeoutError:
|
|
139
|
+
pass
|
|
140
|
+
except Exception:
|
|
141
|
+
pass
|
|
142
|
+
raise timeout_error
|
|
143
|
+
finally:
|
|
144
|
+
if not future.done():
|
|
145
|
+
future.cancel()
|
|
146
|
+
executor.shutdown(wait=False, cancel_futures=True)
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
def optional_int(payload: Dict[str, Any], key: str, default: int) -> int:
|
|
150
|
+
return optional_json_int(payload, key, default)
|