@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.
Files changed (117) hide show
  1. package/README.md +353 -0
  2. package/npm/bin/kagent-serve.js +6 -0
  3. package/npm/bin/kagent.js +6 -0
  4. package/npm/lib/App.js +524 -0
  5. package/npm/lib/app-state.js +224 -0
  6. package/npm/lib/approval-choice.js +25 -0
  7. package/npm/lib/commands.js +59 -0
  8. package/npm/lib/editor.js +188 -0
  9. package/npm/lib/ink-runner.js +41 -0
  10. package/npm/lib/kagent-home.js +39 -0
  11. package/npm/lib/launcher.js +221 -0
  12. package/npm/lib/protocol.js +33 -0
  13. package/npm/lib/provider-setup.js +139 -0
  14. package/npm/lib/python-runner.js +892 -0
  15. package/npm/lib/runtime-client.js +390 -0
  16. package/npm/lib/terminal-input.js +127 -0
  17. package/npm/lib/terminal-text.js +19 -0
  18. package/npm/lib/terminal-width.js +14 -0
  19. package/npm/lib/transcript.js +227 -0
  20. package/npm/lib/ui-components.js +247 -0
  21. package/npm/lib/update-manager.js +334 -0
  22. package/package.json +39 -0
  23. package/pyproject.toml +55 -0
  24. package/src/kagent/__init__.py +90 -0
  25. package/src/kagent/cli/__init__.py +5 -0
  26. package/src/kagent/cli/__main__.py +6 -0
  27. package/src/kagent/cli/commands.py +112 -0
  28. package/src/kagent/cli/conversation.py +127 -0
  29. package/src/kagent/cli/interactive.py +841 -0
  30. package/src/kagent/cli/main.py +685 -0
  31. package/src/kagent/cli/memory.py +460 -0
  32. package/src/kagent/cli/pending_approval.py +169 -0
  33. package/src/kagent/cli/provider.py +27 -0
  34. package/src/kagent/cli/session_commands.py +401 -0
  35. package/src/kagent/cli/stdio_runtime.py +784 -0
  36. package/src/kagent/cli/trace.py +67 -0
  37. package/src/kagent/cli/ui.py +931 -0
  38. package/src/kagent/core/__init__.py +0 -0
  39. package/src/kagent/core/agent.py +296 -0
  40. package/src/kagent/core/faults.py +11 -0
  41. package/src/kagent/core/invariants.py +47 -0
  42. package/src/kagent/core/normalization.py +81 -0
  43. package/src/kagent/core/planning.py +48 -0
  44. package/src/kagent/core/state.py +73 -0
  45. package/src/kagent/core/summary.py +64 -0
  46. package/src/kagent/core/tools.py +196 -0
  47. package/src/kagent/core/trace.py +57 -0
  48. package/src/kagent/eval/__init__.py +11 -0
  49. package/src/kagent/eval/cases.py +229 -0
  50. package/src/kagent/eval/evaluator.py +216 -0
  51. package/src/kagent/integrations/__init__.py +3 -0
  52. package/src/kagent/integrations/audit.py +95 -0
  53. package/src/kagent/integrations/backends.py +131 -0
  54. package/src/kagent/integrations/memory.py +301 -0
  55. package/src/kagent/ops/__init__.py +0 -0
  56. package/src/kagent/ops/batch.py +156 -0
  57. package/src/kagent/ops/doctor.py +255 -0
  58. package/src/kagent/ops/metrics.py +214 -0
  59. package/src/kagent/ops/release_evidence.py +877 -0
  60. package/src/kagent/ops/release_manifest.py +142 -0
  61. package/src/kagent/ops/trace_replay.py +285 -0
  62. package/src/kagent/providers/__init__.py +7 -0
  63. package/src/kagent/providers/embeddings.py +187 -0
  64. package/src/kagent/providers/llm.py +770 -0
  65. package/src/kagent/py.typed +1 -0
  66. package/src/kagent/runtime/__init__.py +28 -0
  67. package/src/kagent/runtime/action_graph.py +543 -0
  68. package/src/kagent/runtime/agent.py +2089 -0
  69. package/src/kagent/runtime/approval.py +64 -0
  70. package/src/kagent/runtime/cancellation.py +64 -0
  71. package/src/kagent/runtime/checkpoint_state.py +146 -0
  72. package/src/kagent/runtime/checkpoint_storage.py +270 -0
  73. package/src/kagent/runtime/context.py +65 -0
  74. package/src/kagent/runtime/file_transaction.py +195 -0
  75. package/src/kagent/runtime/hooks.py +74 -0
  76. package/src/kagent/runtime/metadata.py +116 -0
  77. package/src/kagent/runtime/patch_checkpoints.py +385 -0
  78. package/src/kagent/runtime/policy.py +50 -0
  79. package/src/kagent/runtime/presentation.py +205 -0
  80. package/src/kagent/runtime/redaction.py +130 -0
  81. package/src/kagent/runtime/sandbox.py +331 -0
  82. package/src/kagent/runtime/skills.py +66 -0
  83. package/src/kagent/runtime/steering.py +56 -0
  84. package/src/kagent/runtime/steps.py +255 -0
  85. package/src/kagent/runtime/task_state.py +40 -0
  86. package/src/kagent/runtime/tools.py +3532 -0
  87. package/src/kagent/runtime/types.py +240 -0
  88. package/src/kagent/runtime/workspace.py +597 -0
  89. package/src/kagent/service/__init__.py +26 -0
  90. package/src/kagent/service/__main__.py +6 -0
  91. package/src/kagent/service/active_runs.py +178 -0
  92. package/src/kagent/service/cli.py +737 -0
  93. package/src/kagent/service/contract.py +2571 -0
  94. package/src/kagent/service/errors.py +71 -0
  95. package/src/kagent/service/idempotency.py +584 -0
  96. package/src/kagent/service/router.py +884 -0
  97. package/src/kagent/service/run.py +150 -0
  98. package/src/kagent/service/runtime.py +1915 -0
  99. package/src/kagent/service/runtime_approval.py +20 -0
  100. package/src/kagent/service/runtime_cancel.py +192 -0
  101. package/src/kagent/service/runtime_lifecycle.py +229 -0
  102. package/src/kagent/service/runtime_metadata.py +21 -0
  103. package/src/kagent/service/runtime_policy.py +115 -0
  104. package/src/kagent/service/runtime_recovery.py +573 -0
  105. package/src/kagent/service/runtime_resume.py +382 -0
  106. package/src/kagent/service/runtime_resume_claim.py +116 -0
  107. package/src/kagent/service/runtime_run.py +350 -0
  108. package/src/kagent/service/runtime_status.py +2007 -0
  109. package/src/kagent/service/safety.py +139 -0
  110. package/src/kagent/service/server.py +114 -0
  111. package/src/kagent/service/status.py +233 -0
  112. package/src/kagent/service/trace_store.py +322 -0
  113. package/src/kagent/service/transport.py +24 -0
  114. package/src/kagent/utils/__init__.py +0 -0
  115. package/src/kagent/utils/config_validation.py +21 -0
  116. package/src/kagent/utils/json_output.py +23 -0
  117. package/src/kagent/utils/paths.py +473 -0
@@ -0,0 +1,178 @@
1
+ from __future__ import annotations
2
+
3
+ from dataclasses import dataclass
4
+ from datetime import datetime, timezone
5
+ from threading import Lock
6
+ from typing import Callable, Dict, Optional
7
+ from uuid import uuid4
8
+
9
+ from kagent.runtime.cancellation import RuntimeCancellationToken
10
+
11
+
12
+ class ExecutionSlotLease:
13
+ """Transfers a router-owned concurrency slot to an asynchronous worker."""
14
+
15
+ def __init__(self, release: Optional[Callable[[], None]]) -> None:
16
+ self._release = release
17
+ self._lock = Lock()
18
+ self._transferred = False
19
+ self._released = False
20
+
21
+ def transfer(self) -> Callable[[], None]:
22
+ with self._lock:
23
+ if self._released:
24
+ raise RuntimeError("execution slot lease is already released")
25
+ if self._transferred:
26
+ raise RuntimeError("execution slot lease is already transferred")
27
+ self._transferred = True
28
+ return self.release_transferred
29
+
30
+ def release_if_owned(self) -> None:
31
+ with self._lock:
32
+ if self._transferred or self._released:
33
+ return
34
+ self._released = True
35
+ release = self._release
36
+ if release is not None:
37
+ release()
38
+
39
+ def release_transferred(self) -> None:
40
+ with self._lock:
41
+ if self._released:
42
+ return
43
+ self._released = True
44
+ release = self._release
45
+ if release is not None:
46
+ release()
47
+
48
+
49
+ @dataclass(frozen=True)
50
+ class ActiveRunSnapshot:
51
+ run_id: str
52
+ owner_auth_subject: str
53
+ state: str
54
+ started_at: str
55
+ cancel_reason: str = ""
56
+ cancelled_at: str = ""
57
+
58
+
59
+ @dataclass
60
+ class _ActiveRun:
61
+ run_id: str
62
+ owner_auth_subject: str
63
+ token: RuntimeCancellationToken
64
+ started_at: str
65
+ release: Optional[Callable[[], None]] = None
66
+ state: str = "running"
67
+ cancel_reason: str = ""
68
+ cancelled_at: str = ""
69
+
70
+
71
+ class ActiveRunRegistry:
72
+ """Process-local registry for live runtime workers and cancellation signals."""
73
+
74
+ def __init__(self, *, instance_id: str = "") -> None:
75
+ self._lock = Lock()
76
+ self._runs: Dict[str, _ActiveRun] = {}
77
+ self._instance_id = instance_id.strip() or str(uuid4())
78
+
79
+ @property
80
+ def instance_id(self) -> str:
81
+ return self._instance_id
82
+
83
+ def is_empty(self) -> bool:
84
+ with self._lock:
85
+ return not self._runs
86
+
87
+ def register(
88
+ self,
89
+ run_id: str,
90
+ owner_auth_subject: str,
91
+ token: RuntimeCancellationToken,
92
+ *,
93
+ release: Optional[Callable[[], None]] = None,
94
+ ) -> None:
95
+ with self._lock:
96
+ if run_id in self._runs:
97
+ raise ValueError(f"runtime run is already active: {run_id}")
98
+ self._runs[run_id] = _ActiveRun(
99
+ run_id=run_id,
100
+ owner_auth_subject=owner_auth_subject,
101
+ token=token,
102
+ started_at=datetime.now(timezone.utc).isoformat(),
103
+ release=release,
104
+ )
105
+
106
+ def get(self, run_id: str) -> Optional[ActiveRunSnapshot]:
107
+ with self._lock:
108
+ active_run = self._runs.get(run_id)
109
+ return _snapshot(active_run) if active_run is not None else None
110
+
111
+ def request_cancel(
112
+ self,
113
+ run_id: str,
114
+ *,
115
+ requested_by_auth_subject: str = "",
116
+ request_auth_is_admin: bool = False,
117
+ reason: str = "",
118
+ ) -> Optional[ActiveRunSnapshot]:
119
+ with self._lock:
120
+ active_run = self._runs.get(run_id)
121
+ if active_run is None:
122
+ return None
123
+ if (
124
+ requested_by_auth_subject
125
+ and not request_auth_is_admin
126
+ and active_run.owner_auth_subject != requested_by_auth_subject
127
+ ):
128
+ return None
129
+ if active_run.state != "running":
130
+ return _snapshot(active_run)
131
+ active_run.state = "cancelled"
132
+ active_run.cancel_reason = reason.strip()
133
+ active_run.token.cancel(active_run.cancel_reason)
134
+ token_snapshot = active_run.token.snapshot()
135
+ active_run.cancelled_at = token_snapshot["cancelled_at"]
136
+ return _snapshot(active_run)
137
+
138
+ def mark_timed_out(self, run_id: str, *, reason: str) -> Optional[ActiveRunSnapshot]:
139
+ with self._lock:
140
+ active_run = self._runs.get(run_id)
141
+ if active_run is None:
142
+ return None
143
+ if active_run.state == "running":
144
+ active_run.state = "timed_out"
145
+ active_run.cancel_reason = reason.strip()
146
+ active_run.token.cancel(active_run.cancel_reason)
147
+ token_snapshot = active_run.token.snapshot()
148
+ active_run.cancelled_at = token_snapshot["cancelled_at"]
149
+ return _snapshot(active_run)
150
+
151
+ def complete(self, run_id: str) -> None:
152
+ with self._lock:
153
+ active_run = self._runs.pop(run_id, None)
154
+ if active_run is not None and active_run.release is not None:
155
+ active_run.release()
156
+
157
+ def snapshot(self) -> Dict[str, str]:
158
+ with self._lock:
159
+ state_counts: Dict[str, int] = {}
160
+ for active_run in self._runs.values():
161
+ state_counts[active_run.state] = state_counts.get(active_run.state, 0) + 1
162
+ return {
163
+ "active_runtime_runs": str(len(self._runs)),
164
+ "active_runtime_runs_by_state": ",".join(
165
+ f"{state}:{count}" for state, count in sorted(state_counts.items())
166
+ ),
167
+ }
168
+
169
+
170
+ def _snapshot(active_run: _ActiveRun) -> ActiveRunSnapshot:
171
+ return ActiveRunSnapshot(
172
+ run_id=active_run.run_id,
173
+ owner_auth_subject=active_run.owner_auth_subject,
174
+ state=active_run.state,
175
+ started_at=active_run.started_at,
176
+ cancel_reason=active_run.cancel_reason,
177
+ cancelled_at=active_run.cancelled_at,
178
+ )