my-pi-agent 0.1.0

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 (141) hide show
  1. package/README.md +318 -0
  2. package/package.json +45 -0
  3. package/pyproject.toml +50 -0
  4. package/src/my_agent_core/__init__.py +123 -0
  5. package/src/my_agent_core/agent.py +441 -0
  6. package/src/my_agent_core/background.py +121 -0
  7. package/src/my_agent_core/context.py +505 -0
  8. package/src/my_agent_core/events.py +153 -0
  9. package/src/my_agent_core/extensions/__init__.py +9 -0
  10. package/src/my_agent_core/extensions/core.py +197 -0
  11. package/src/my_agent_core/hooks.py +130 -0
  12. package/src/my_agent_core/loop.py +709 -0
  13. package/src/my_agent_core/main.py +134 -0
  14. package/src/my_agent_core/memory.py +241 -0
  15. package/src/my_agent_core/message_queue.py +110 -0
  16. package/src/my_agent_core/plugins.py +212 -0
  17. package/src/my_agent_core/registry.py +186 -0
  18. package/src/my_agent_core/session/__init__.py +79 -0
  19. package/src/my_agent_core/session/entries.py +197 -0
  20. package/src/my_agent_core/session/jsonl.py +60 -0
  21. package/src/my_agent_core/session/memory.py +137 -0
  22. package/src/my_agent_core/session/session.py +400 -0
  23. package/src/my_agent_core/session/storage.py +245 -0
  24. package/src/my_agent_core/session/store.py +131 -0
  25. package/src/my_agent_core/session/tree.py +86 -0
  26. package/src/my_agent_core/skills.py +149 -0
  27. package/src/my_agent_core/subagent_tasks.py +170 -0
  28. package/src/my_agent_core/subagents.py +148 -0
  29. package/src/my_agent_core/task_store.py +248 -0
  30. package/src/my_agent_core/tool_history.py +189 -0
  31. package/src/my_agent_core/tools/__init__.py +5 -0
  32. package/src/my_agent_core/tools/builtin/__init__.py +5 -0
  33. package/src/my_agent_core/tools/builtin/task.py +30 -0
  34. package/src/my_agent_core/tools/builtin/task_tools.py +215 -0
  35. package/src/my_agent_core/tools/core.py +239 -0
  36. package/src/my_agent_llm/__init__.py +45 -0
  37. package/src/my_agent_llm/auth/__init__.py +46 -0
  38. package/src/my_agent_llm/auth/antigravity.py +209 -0
  39. package/src/my_agent_llm/auth/manager.py +259 -0
  40. package/src/my_agent_llm/auth/quota.py +56 -0
  41. package/src/my_agent_llm/auth/schema.py +94 -0
  42. package/src/my_agent_llm/client.py +116 -0
  43. package/src/my_agent_llm/config.py +17 -0
  44. package/src/my_agent_llm/events.py +84 -0
  45. package/src/my_agent_llm/models.py +195 -0
  46. package/src/my_agent_llm/providers/__init__.py +4 -0
  47. package/src/my_agent_llm/providers/_base.py +94 -0
  48. package/src/my_agent_llm/providers/anthropic.py +298 -0
  49. package/src/my_agent_llm/providers/antigravity.py +480 -0
  50. package/src/my_agent_llm/providers/deepseek.py +196 -0
  51. package/src/my_agent_llm/providers/openai.py +364 -0
  52. package/src/my_agent_llm/providers/registry.py +16 -0
  53. package/src/my_agent_llm/stream.py +218 -0
  54. package/src/my_coding_agent/__init__.py +66 -0
  55. package/src/my_coding_agent/agent.py +208 -0
  56. package/src/my_coding_agent/cli.py +78 -0
  57. package/src/my_coding_agent/file_reference.py +80 -0
  58. package/src/my_coding_agent/macro.py +408 -0
  59. package/src/my_coding_agent/mcp.py +243 -0
  60. package/src/my_coding_agent/mutation_queue.py +37 -0
  61. package/src/my_coding_agent/paths.py +119 -0
  62. package/src/my_coding_agent/permissions.py +84 -0
  63. package/src/my_coding_agent/prompt.py +54 -0
  64. package/src/my_coding_agent/rpc_server.py +2817 -0
  65. package/src/my_coding_agent/settings.py +126 -0
  66. package/src/my_coding_agent/tools/__init__.py +55 -0
  67. package/src/my_coding_agent/tools/base.py +58 -0
  68. package/src/my_coding_agent/tools/bash.py +206 -0
  69. package/src/my_coding_agent/tools/edit.py +226 -0
  70. package/src/my_coding_agent/tools/find.py +118 -0
  71. package/src/my_coding_agent/tools/grep.py +177 -0
  72. package/src/my_coding_agent/tools/ls.py +112 -0
  73. package/src/my_coding_agent/tools/read.py +113 -0
  74. package/src/my_coding_agent/tools/write.py +72 -0
  75. package/tui/README.md +27 -0
  76. package/tui/bin/my-agent.js +98 -0
  77. package/tui/dist/app.d.ts +41 -0
  78. package/tui/dist/app.js +110 -0
  79. package/tui/dist/bridge/event-translator.d.ts +92 -0
  80. package/tui/dist/bridge/event-translator.js +216 -0
  81. package/tui/dist/bridge/kernel-bridge.d.ts +48 -0
  82. package/tui/dist/bridge/kernel-bridge.js +132 -0
  83. package/tui/dist/client.d.ts +63 -0
  84. package/tui/dist/client.js +239 -0
  85. package/tui/dist/components/assistant-message.d.ts +19 -0
  86. package/tui/dist/components/assistant-message.js +90 -0
  87. package/tui/dist/components/compaction-summary-message.d.ts +19 -0
  88. package/tui/dist/components/compaction-summary-message.js +46 -0
  89. package/tui/dist/components/custom-editor.d.ts +18 -0
  90. package/tui/dist/components/custom-editor.js +56 -0
  91. package/tui/dist/components/dynamic-border.d.ts +9 -0
  92. package/tui/dist/components/dynamic-border.js +14 -0
  93. package/tui/dist/components/footer.d.ts +39 -0
  94. package/tui/dist/components/footer.js +199 -0
  95. package/tui/dist/components/header.d.ts +4 -0
  96. package/tui/dist/components/header.js +21 -0
  97. package/tui/dist/components/keys.d.ts +5 -0
  98. package/tui/dist/components/keys.js +12 -0
  99. package/tui/dist/components/login-selector.d.ts +26 -0
  100. package/tui/dist/components/login-selector.js +181 -0
  101. package/tui/dist/components/logout-selector.d.ts +19 -0
  102. package/tui/dist/components/logout-selector.js +88 -0
  103. package/tui/dist/components/model-selector.d.ts +40 -0
  104. package/tui/dist/components/model-selector.js +268 -0
  105. package/tui/dist/components/session-selector.d.ts +54 -0
  106. package/tui/dist/components/session-selector.js +393 -0
  107. package/tui/dist/components/settings-selector.d.ts +24 -0
  108. package/tui/dist/components/settings-selector.js +146 -0
  109. package/tui/dist/components/status-indicator.d.ts +25 -0
  110. package/tui/dist/components/status-indicator.js +60 -0
  111. package/tui/dist/components/theme-selector.d.ts +14 -0
  112. package/tui/dist/components/theme-selector.js +77 -0
  113. package/tui/dist/components/thinking-selector.d.ts +21 -0
  114. package/tui/dist/components/thinking-selector.js +128 -0
  115. package/tui/dist/components/tool-execution.d.ts +31 -0
  116. package/tui/dist/components/tool-execution.js +206 -0
  117. package/tui/dist/components/tree-selector.d.ts +40 -0
  118. package/tui/dist/components/tree-selector.js +173 -0
  119. package/tui/dist/components/user-message-selector.d.ts +21 -0
  120. package/tui/dist/components/user-message-selector.js +103 -0
  121. package/tui/dist/components/user-message.d.ts +5 -0
  122. package/tui/dist/components/user-message.js +15 -0
  123. package/tui/dist/index.d.ts +11 -0
  124. package/tui/dist/index.js +11 -0
  125. package/tui/dist/interactive/chat-viewport.d.ts +19 -0
  126. package/tui/dist/interactive/chat-viewport.js +41 -0
  127. package/tui/dist/interactive/components.d.ts +1 -0
  128. package/tui/dist/interactive/components.js +1 -0
  129. package/tui/dist/interactive/interactive-mode.d.ts +89 -0
  130. package/tui/dist/interactive/interactive-mode.js +1625 -0
  131. package/tui/dist/interactive/theme.d.ts +1 -0
  132. package/tui/dist/interactive/theme.js +1 -0
  133. package/tui/dist/interactive/tui-renderer.d.ts +8 -0
  134. package/tui/dist/interactive/tui-renderer.js +10 -0
  135. package/tui/dist/protocol.d.ts +78 -0
  136. package/tui/dist/protocol.js +1 -0
  137. package/tui/dist/theme/dark.json +54 -0
  138. package/tui/dist/theme/light.json +71 -0
  139. package/tui/dist/theme/theme.d.ts +20 -0
  140. package/tui/dist/theme/theme.js +86 -0
  141. package/tui/package.json +25 -0
@@ -0,0 +1,268 @@
1
+ import { Container, fuzzyFilter, Input, matchesKey, Spacer, Text, } from "@earendil-works/pi-tui";
2
+ import { theme } from "../theme/theme.js";
3
+ import { DynamicBorder } from "./dynamic-border.js";
4
+ import { isEnterKey } from "./keys.js";
5
+ export class ModelSelectorComponent extends Container {
6
+ currentModel;
7
+ onSelect;
8
+ onCancel;
9
+ onSelectAsDefault;
10
+ defaultModelId;
11
+ requestRender;
12
+ searchInput;
13
+ headerContainer;
14
+ listContainer;
15
+ allModels = [];
16
+ scopedModelItems = [];
17
+ activeModels = [];
18
+ filteredModels = [];
19
+ selectedIndex = 0;
20
+ scope = "all";
21
+ loader;
22
+ _focused = false;
23
+ get focused() {
24
+ return this._focused;
25
+ }
26
+ set focused(value) {
27
+ this._focused = value;
28
+ this.searchInput.focused = value;
29
+ }
30
+ constructor(currentModel, modelsOrLoader, onSelect, onCancel, initialSearch, onSelectAsDefault, defaultModelId, requestRender, scopedModels = []) {
31
+ super();
32
+ this.currentModel = currentModel;
33
+ this.onSelect = onSelect;
34
+ this.onCancel = onCancel;
35
+ this.onSelectAsDefault = onSelectAsDefault;
36
+ this.defaultModelId = defaultModelId;
37
+ this.requestRender = requestRender;
38
+ this.headerContainer = new Container();
39
+ this.listContainer = new Container();
40
+ this.searchInput = new Input();
41
+ this.scopedModelItems = [...scopedModels];
42
+ this.scope = this.scopedModelItems.length > 0 ? "scoped" : "all";
43
+ if (typeof modelsOrLoader === "function") {
44
+ this.loader = modelsOrLoader;
45
+ }
46
+ else {
47
+ this.allModels = this.sortModels(modelsOrLoader);
48
+ this.activeModels =
49
+ this.scope === "scoped" ? this.scopedModelItems : this.allModels;
50
+ this.filteredModels = [...this.activeModels];
51
+ }
52
+ this.rebuildStaticLayout(initialSearch);
53
+ if (this.loader) {
54
+ void this.reload(initialSearch);
55
+ }
56
+ else {
57
+ this.updateHeader();
58
+ if (initialSearch) {
59
+ this.filterModels(initialSearch);
60
+ }
61
+ else {
62
+ const curIdx = this.filteredModels.findIndex((m) => m.id === currentModel || `${m.provider}/${m.id}` === currentModel);
63
+ this.selectedIndex = curIdx >= 0 ? curIdx : 0;
64
+ this.updateList();
65
+ }
66
+ }
67
+ }
68
+ rebuildStaticLayout(initialSearch) {
69
+ this.addChild(new DynamicBorder());
70
+ this.addChild(new Spacer(1));
71
+ this.addChild(this.headerContainer);
72
+ this.addChild(new Spacer(1));
73
+ if (initialSearch) {
74
+ this.searchInput.setValue(initialSearch);
75
+ }
76
+ this.searchInput.onSubmit = () => {
77
+ const selected = this.filteredModels[this.selectedIndex];
78
+ if (selected)
79
+ this.onSelect(selected);
80
+ };
81
+ this.addChild(this.searchInput);
82
+ this.addChild(new Spacer(1));
83
+ this.addChild(this.listContainer);
84
+ this.addChild(new Spacer(1));
85
+ const defaultHint = this.onSelectAsDefault
86
+ ? " · Ctrl+S to set as default"
87
+ : "";
88
+ this.addChild(new Text(theme.fg("dim", ` Enter to select${defaultHint} · Escape to cancel`), 0, 0));
89
+ this.addChild(new DynamicBorder());
90
+ }
91
+ getScopeText() {
92
+ const allText = this.scope === "all"
93
+ ? theme.fg("accent", "all")
94
+ : theme.fg("muted", "all");
95
+ const scopedText = this.scope === "scoped"
96
+ ? theme.fg("accent", "scoped")
97
+ : theme.fg("muted", "scoped");
98
+ return `${theme.fg("muted", "Scope: ")}${allText}${theme.fg("muted", " | ")}${scopedText}`;
99
+ }
100
+ getScopeHintText() {
101
+ return theme.fg("dim", "tab scope (all/scoped)");
102
+ }
103
+ updateHeader() {
104
+ this.headerContainer.clear();
105
+ if (this.scopedModelItems.length > 0) {
106
+ this.headerContainer.addChild(new Text(this.getScopeText(), 0, 0));
107
+ this.headerContainer.addChild(new Text(this.getScopeHintText(), 0, 0));
108
+ }
109
+ else {
110
+ const hintText = "Only showing models from configured providers. Use /login to add providers.";
111
+ this.headerContainer.addChild(new Text(theme.fg("warning", hintText), 0, 0));
112
+ }
113
+ }
114
+ async reload(initialSearch) {
115
+ if (!this.loader)
116
+ return;
117
+ try {
118
+ const models = await this.loader();
119
+ this.allModels = this.sortModels(models);
120
+ this.activeModels =
121
+ this.scope === "scoped" && this.scopedModelItems.length > 0
122
+ ? this.scopedModelItems
123
+ : this.allModels;
124
+ this.updateHeader();
125
+ const q = initialSearch === undefined
126
+ ? this.searchInput.getValue()
127
+ : initialSearch;
128
+ if (q) {
129
+ this.filterModels(q);
130
+ }
131
+ else {
132
+ this.filteredModels = [...this.activeModels];
133
+ const curIdx = this.filteredModels.findIndex((m) => m.id === this.currentModel ||
134
+ `${m.provider}/${m.id}` === this.currentModel);
135
+ this.selectedIndex = curIdx >= 0 ? curIdx : 0;
136
+ this.updateList();
137
+ }
138
+ }
139
+ catch {
140
+ this.allModels = [];
141
+ this.filteredModels = [];
142
+ this.updateList();
143
+ }
144
+ if (this.requestRender) {
145
+ this.requestRender();
146
+ }
147
+ }
148
+ sortModels(models) {
149
+ return [...models].sort((a, b) => {
150
+ const aCur = a.id === this.currentModel ||
151
+ `${a.provider}/${a.id}` === this.currentModel;
152
+ const bCur = b.id === this.currentModel ||
153
+ `${b.provider}/${b.id}` === this.currentModel;
154
+ if (aCur && !bCur)
155
+ return -1;
156
+ if (!aCur && bCur)
157
+ return 1;
158
+ const aDef = a.id === this.defaultModelId;
159
+ const bDef = b.id === this.defaultModelId;
160
+ if (aDef && !bDef)
161
+ return -1;
162
+ if (!aDef && bDef)
163
+ return 1;
164
+ return a.provider.localeCompare(b.provider);
165
+ });
166
+ }
167
+ filterModels(query) {
168
+ const q = query.trim();
169
+ if (q) {
170
+ this.filteredModels = fuzzyFilter(this.activeModels, q, (item) => {
171
+ const isDefault = item.id === this.defaultModelId ? " default" : "";
172
+ const name = item.name ? ` ${item.name}` : "";
173
+ return `${item.provider} ${item.provider}/${item.id} ${item.provider} ${item.id}${name}${isDefault}`;
174
+ });
175
+ this.selectedIndex = 0;
176
+ }
177
+ else {
178
+ this.filteredModels = [...this.activeModels];
179
+ this.selectedIndex = Math.min(this.selectedIndex, Math.max(0, this.filteredModels.length - 1));
180
+ }
181
+ this.updateList();
182
+ }
183
+ updateList() {
184
+ this.listContainer.clear();
185
+ const maxVisible = 10;
186
+ const startIndex = Math.max(0, Math.min(this.selectedIndex - Math.floor(maxVisible / 2), this.filteredModels.length - maxVisible));
187
+ const endIndex = Math.min(startIndex + maxVisible, this.filteredModels.length);
188
+ for (let i = startIndex; i < endIndex; i++) {
189
+ const item = this.filteredModels[i];
190
+ if (!item)
191
+ continue;
192
+ const isSelected = i === this.selectedIndex;
193
+ const isCurrent = item.id === this.currentModel ||
194
+ `${item.provider}/${item.id}` === this.currentModel;
195
+ const isDefault = item.id === this.defaultModelId;
196
+ const cursor = isSelected ? theme.fg("accent", "→ ") : " ";
197
+ const currentMarker = isCurrent ? theme.fg("accent", "✓ ") : " ";
198
+ const modelText = isSelected ? theme.fg("accent", item.id) : item.id;
199
+ const providerBadge = theme.fg("muted", `[${item.provider}]`);
200
+ const defaultBadge = isDefault ? theme.fg("muted", " · default") : "";
201
+ const line = `${cursor}${currentMarker}${modelText} ${providerBadge}${defaultBadge}`;
202
+ this.listContainer.addChild(new Text(line, 0, 0));
203
+ }
204
+ if (startIndex > 0 || endIndex < this.filteredModels.length) {
205
+ const scrollInfo = theme.fg("muted", ` (${this.selectedIndex + 1}/${this.filteredModels.length})`);
206
+ this.listContainer.addChild(new Text(scrollInfo, 0, 0));
207
+ }
208
+ if (this.filteredModels.length === 0) {
209
+ this.listContainer.addChild(new Text(theme.fg("muted", " No matching models"), 0, 0));
210
+ }
211
+ else {
212
+ const selected = this.filteredModels[this.selectedIndex];
213
+ if (selected?.name) {
214
+ this.listContainer.addChild(new Spacer(1));
215
+ this.listContainer.addChild(new Text(theme.fg("muted", ` Model Name: ${selected.name}`), 0, 0));
216
+ }
217
+ }
218
+ }
219
+ handleInput(data) {
220
+ if (matchesKey(data, "tab")) {
221
+ if (this.scopedModelItems.length > 0) {
222
+ this.scope = this.scope === "all" ? "scoped" : "all";
223
+ this.activeModels =
224
+ this.scope === "scoped" ? this.scopedModelItems : this.allModels;
225
+ this.updateHeader();
226
+ this.filterModels(this.searchInput.getValue());
227
+ if (this.requestRender)
228
+ this.requestRender();
229
+ }
230
+ return;
231
+ }
232
+ if (matchesKey(data, "up")) {
233
+ if (this.filteredModels.length === 0)
234
+ return;
235
+ this.selectedIndex =
236
+ this.selectedIndex === 0
237
+ ? this.filteredModels.length - 1
238
+ : this.selectedIndex - 1;
239
+ this.updateList();
240
+ }
241
+ else if (matchesKey(data, "down")) {
242
+ if (this.filteredModels.length === 0)
243
+ return;
244
+ this.selectedIndex =
245
+ this.selectedIndex === this.filteredModels.length - 1
246
+ ? 0
247
+ : this.selectedIndex + 1;
248
+ this.updateList();
249
+ }
250
+ else if (isEnterKey(data)) {
251
+ const selected = this.filteredModels[this.selectedIndex];
252
+ if (selected)
253
+ this.onSelect(selected);
254
+ }
255
+ else if (matchesKey(data, "escape") || matchesKey(data, "ctrl+c")) {
256
+ this.onCancel();
257
+ }
258
+ else if (matchesKey(data, "ctrl+s") && this.onSelectAsDefault) {
259
+ const selected = this.filteredModels[this.selectedIndex];
260
+ if (selected)
261
+ this.onSelectAsDefault(selected);
262
+ }
263
+ else {
264
+ this.searchInput.handleInput(data);
265
+ this.filterModels(this.searchInput.getValue());
266
+ }
267
+ }
268
+ }
@@ -0,0 +1,54 @@
1
+ import { Container, Input } from "@earendil-works/pi-tui";
2
+ export interface SessionItem {
3
+ id: string;
4
+ name?: string;
5
+ path?: string;
6
+ cwd?: string;
7
+ modified: number;
8
+ message_count?: number;
9
+ parent_session?: string;
10
+ parent_session_path?: string;
11
+ }
12
+ export interface SessionTreeNode {
13
+ session: SessionItem;
14
+ children: SessionTreeNode[];
15
+ latestActivity: number;
16
+ }
17
+ export interface FlattenedSessionNode {
18
+ session: SessionItem;
19
+ depth: number;
20
+ isLast: boolean;
21
+ ancestorContinues: boolean[];
22
+ }
23
+ export declare function buildSessionTree(sessions: SessionItem[]): SessionTreeNode[];
24
+ export declare function flattenSessionTree(roots: SessionTreeNode[]): FlattenedSessionNode[];
25
+ export declare function buildTreePrefix(node: FlattenedSessionNode): string;
26
+ export declare class SessionSelectorComponent extends Container {
27
+ private loadSessions;
28
+ private onSelect;
29
+ private onCancel;
30
+ private requestRender?;
31
+ private activeSessionId?;
32
+ private onDelete?;
33
+ searchInput: Input;
34
+ private allSessions;
35
+ private filteredSessions;
36
+ private displayNodes;
37
+ private selectedIndex;
38
+ private maxVisible;
39
+ private scope;
40
+ private showPath;
41
+ private confirmingDeleteId;
42
+ private errorMessage;
43
+ private errorTimeout;
44
+ private _focused;
45
+ get focused(): boolean;
46
+ set focused(value: boolean);
47
+ constructor(loadSessions: (allProjects: boolean) => Promise<SessionItem[]>, onSelect: (session: SessionItem) => void, onCancel: () => void, requestRender?: (() => void) | undefined, activeSessionId?: string | undefined, onDelete?: ((session: SessionItem) => Promise<void> | void) | undefined);
48
+ reload(): Promise<void>;
49
+ private applyFilter;
50
+ private rebuildUI;
51
+ handleInput(data: string): void;
52
+ private setErrorMessage;
53
+ private executeDelete;
54
+ }