@lensagent/core 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 (104) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +48 -0
  3. package/config/lens.example.jsonc +92 -0
  4. package/config/pair.example.json +3 -0
  5. package/dist/adapters/executor.d.ts +35 -0
  6. package/dist/adapters/executor.js +296 -0
  7. package/dist/adapters/lsp.d.ts +18 -0
  8. package/dist/adapters/lsp.js +218 -0
  9. package/dist/adapters/mcp.d.ts +32 -0
  10. package/dist/adapters/mcp.js +283 -0
  11. package/dist/adapters/revert.d.ts +12 -0
  12. package/dist/adapters/revert.js +155 -0
  13. package/dist/config/runtime.d.ts +55 -0
  14. package/dist/config/runtime.js +371 -0
  15. package/dist/config/schema.d.ts +292 -0
  16. package/dist/config/schema.js +177 -0
  17. package/dist/contracts/adapter.d.ts +28 -0
  18. package/dist/contracts/adapter.js +8 -0
  19. package/dist/contracts/capability.d.ts +41 -0
  20. package/dist/contracts/capability.js +1 -0
  21. package/dist/contracts/domain.d.ts +61 -0
  22. package/dist/contracts/domain.js +1 -0
  23. package/dist/contracts/index.d.ts +5 -0
  24. package/dist/contracts/index.js +5 -0
  25. package/dist/contracts/model.d.ts +77 -0
  26. package/dist/contracts/model.js +1 -0
  27. package/dist/contracts/ports.d.ts +14 -0
  28. package/dist/contracts/ports.js +14 -0
  29. package/dist/core/access.d.ts +24 -0
  30. package/dist/core/access.js +205 -0
  31. package/dist/core/codec.d.ts +33 -0
  32. package/dist/core/codec.js +105 -0
  33. package/dist/core/domain.d.ts +13 -0
  34. package/dist/core/domain.js +24 -0
  35. package/dist/core/host.d.ts +19 -0
  36. package/dist/core/host.js +249 -0
  37. package/dist/core/identity.d.ts +19 -0
  38. package/dist/core/identity.js +54 -0
  39. package/dist/entry/bun.d.ts +1 -0
  40. package/dist/entry/bun.js +2 -0
  41. package/dist/entry/node.d.ts +2 -0
  42. package/dist/entry/node.js +3 -0
  43. package/dist/entry/rebuild.d.ts +1 -0
  44. package/dist/entry/rebuild.js +47 -0
  45. package/dist/entry/run.d.ts +1 -0
  46. package/dist/entry/run.js +43 -0
  47. package/dist/execution/lsp-process.d.ts +14 -0
  48. package/dist/execution/lsp-process.js +234 -0
  49. package/dist/http/server.d.ts +34 -0
  50. package/dist/http/server.js +1332 -0
  51. package/dist/launch.d.ts +3 -0
  52. package/dist/launch.js +4 -0
  53. package/dist/runtime/agent.d.ts +35 -0
  54. package/dist/runtime/agent.js +853 -0
  55. package/dist/runtime/artifacts.d.ts +15 -0
  56. package/dist/runtime/artifacts.js +72 -0
  57. package/dist/runtime/cache.d.ts +20 -0
  58. package/dist/runtime/cache.js +44 -0
  59. package/dist/runtime/calls.d.ts +21 -0
  60. package/dist/runtime/calls.js +130 -0
  61. package/dist/runtime/capabilities.d.ts +58 -0
  62. package/dist/runtime/capabilities.js +196 -0
  63. package/dist/runtime/cleanup.d.ts +7 -0
  64. package/dist/runtime/cleanup.js +33 -0
  65. package/dist/runtime/context.d.ts +34 -0
  66. package/dist/runtime/context.js +169 -0
  67. package/dist/runtime/diagnostics.d.ts +8 -0
  68. package/dist/runtime/diagnostics.js +71 -0
  69. package/dist/runtime/events.d.ts +22 -0
  70. package/dist/runtime/events.js +131 -0
  71. package/dist/runtime/kernel-capabilities.d.ts +32 -0
  72. package/dist/runtime/kernel-capabilities.js +200 -0
  73. package/dist/runtime/manifests.d.ts +14 -0
  74. package/dist/runtime/manifests.js +117 -0
  75. package/dist/runtime/model.d.ts +20 -0
  76. package/dist/runtime/model.js +241 -0
  77. package/dist/runtime/observability.d.ts +22 -0
  78. package/dist/runtime/observability.js +104 -0
  79. package/dist/runtime/policy.d.ts +8 -0
  80. package/dist/runtime/policy.js +31 -0
  81. package/dist/runtime/profile.d.ts +8 -0
  82. package/dist/runtime/profile.js +52 -0
  83. package/dist/runtime/projects.d.ts +40 -0
  84. package/dist/runtime/projects.js +115 -0
  85. package/dist/runtime/results.d.ts +7 -0
  86. package/dist/runtime/results.js +55 -0
  87. package/dist/runtime/review.d.ts +9 -0
  88. package/dist/runtime/review.js +54 -0
  89. package/dist/runtime/scheduler.d.ts +15 -0
  90. package/dist/runtime/scheduler.js +85 -0
  91. package/dist/runtime/skills.d.ts +2 -0
  92. package/dist/runtime/skills.js +83 -0
  93. package/dist/runtime/tokenizer.d.ts +8 -0
  94. package/dist/runtime/tokenizer.js +30 -0
  95. package/dist/store/database.d.ts +3 -0
  96. package/dist/store/database.js +49 -0
  97. package/dist/store/event-log.d.ts +19 -0
  98. package/dist/store/event-log.js +61 -0
  99. package/dist/store/schema.d.ts +1 -0
  100. package/dist/store/schema.js +347 -0
  101. package/dist/store/store.d.ts +344 -0
  102. package/dist/store/store.js +2554 -0
  103. package/package.json +73 -0
  104. package/proto/executor.proto +314 -0
package/package.json ADDED
@@ -0,0 +1,73 @@
1
+ {
2
+ "name": "@lensagent/core",
3
+ "version": "0.1.0",
4
+ "description": "Lens Harness kernel and HTTP server.",
5
+ "license": "MIT",
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "git+https://github.com/LensAgent/lens-core.git"
9
+ },
10
+ "type": "module",
11
+ "engines": {
12
+ "node": ">=24.0.0"
13
+ },
14
+ "exports": {
15
+ ".": {
16
+ "types": "./dist/launch.d.ts",
17
+ "import": "./dist/launch.js"
18
+ }
19
+ },
20
+ "types": "./dist/launch.d.ts",
21
+ "bin": {
22
+ "lens-core": "dist/entry/node.js"
23
+ },
24
+ "lens": {
25
+ "component": "lens-core",
26
+ "protocols": {
27
+ "facet-core-api": 4,
28
+ "core-executor-rpc": 4
29
+ }
30
+ },
31
+ "files": [
32
+ "dist",
33
+ "proto",
34
+ "config/lens.example.jsonc",
35
+ "config/pair.example.json",
36
+ "README.md"
37
+ ],
38
+ "publishConfig": {
39
+ "access": "public"
40
+ },
41
+ "dependencies": {
42
+ "@ai-sdk/anthropic": "4.0.30",
43
+ "@ai-sdk/openai": "4.0.30",
44
+ "@ai-sdk/openai-compatible": "3.0.23",
45
+ "@grpc/grpc-js": "1.14.4",
46
+ "@grpc/proto-loader": "0.8.1",
47
+ "@sinclair/typebox": "0.34.52",
48
+ "ai": "7.0.52",
49
+ "ajv": "8.20.0",
50
+ "better-sqlite3": "13.0.3",
51
+ "fastify": "5.11.2",
52
+ "json-canonicalize": "2.0.0",
53
+ "jsonc-parser": "3.3.1"
54
+ },
55
+ "devDependencies": {
56
+ "@eslint/js": "9.39.2",
57
+ "@types/better-sqlite3": "7.6.13",
58
+ "@types/node": "24.10.1",
59
+ "eslint": "9.39.2",
60
+ "tsx": "4.21.0",
61
+ "typescript": "5.9.3",
62
+ "typescript-eslint": "8.53.1"
63
+ },
64
+ "scripts": {
65
+ "build": "node --input-type=module -e \"import{rmSync}from'node:fs';rmSync('dist',{recursive:true,force:true})\" && tsc -p tsconfig.build.json",
66
+ "dev": "tsx src/entry/node.ts",
67
+ "start": "node dist/entry/node.js",
68
+ "storage:rebuild": "tsx src/entry/rebuild.ts",
69
+ "typecheck": "tsc -p tsconfig.json --noEmit",
70
+ "lint": "eslint .",
71
+ "secret-scan": "node scripts/secret-scan.mjs"
72
+ }
73
+ }
@@ -0,0 +1,314 @@
1
+ syntax = "proto3";
2
+
3
+ package lens.executor.v1;
4
+
5
+ service Executor {
6
+ rpc Health(HealthRequest) returns (HealthResponse);
7
+ rpc Identity(IdentityRequest) returns (IdentityResponse);
8
+ rpc Shutdown(ShutdownRequest) returns (ShutdownResponse);
9
+ rpc ReadFile(ReadFileRequest) returns (ReadFileResponse);
10
+ rpc WriteFile(WriteFileRequest) returns (WriteFileResponse);
11
+ rpc EditFile(EditFileRequest) returns (EditFileResponse);
12
+ rpc RevertCall(RevertCallRequest) returns (RevertCallResponse);
13
+ rpc DescribeCallHistory(DescribeCallHistoryRequest) returns (DescribeCallHistoryResponse);
14
+ rpc DeleteCallHistory(DeleteCallHistoryRequest) returns (DeleteCallHistoryResponse);
15
+ rpc Glob(GlobRequest) returns (GlobResponse);
16
+ rpc Grep(GrepRequest) returns (GrepResponse);
17
+ rpc BrowseProject(BrowseProjectRequest) returns (BrowseProjectResponse);
18
+ rpc RunCommand(RunCommandRequest) returns (RunCommandResponse);
19
+ rpc GitRun(GitRunRequest) returns (GitRunResponse);
20
+ rpc InternetSearch(InternetSearchRequest) returns (InternetSearchResponse);
21
+ rpc ListAllowedParent(ListAllowedParentRequest) returns (ListAllowedParentResponse);
22
+ rpc ValidateWorkspacePaths(ValidateWorkspacePathsRequest) returns (ValidateWorkspacePathsResponse);
23
+ rpc OpenInFileManager(OpenInFileManagerRequest) returns (OpenInFileManagerResponse);
24
+ rpc ChooseWorkspaceFolder(ChooseWorkspaceFolderRequest) returns (ChooseWorkspaceFolderResponse);
25
+ }
26
+
27
+ message HealthRequest {}
28
+ message HealthResponse {
29
+ string status = 1;
30
+ string allowed_parent_dir = 2;
31
+ // Where the file history lives and a stable id for that store. A new state_id from the same
32
+ // Executor means the store was replaced and every earlier Call is now unrevertable.
33
+ string state_dir = 3;
34
+ string state_id = 4;
35
+ string state_created_at = 5;
36
+ }
37
+
38
+ // Identity for an external process manager: which program answers this port, which independent
39
+ // software version it is, which integer protocol version it speaks, and which OS process serves it.
40
+ //
41
+ // Deliberately separate from Health rather than added to it. Health requires a verified client and
42
+ // reports allowed_parent_dir and state_dir, so it cannot answer a manager: identifying the process
43
+ // is what a manager does *before* it can be verified, and it has to work while the Executor is
44
+ // unhealthy. This message therefore carries no filesystem paths and no client-identifying values,
45
+ // which is what lets it be served without verification.
46
+ message IdentityRequest {}
47
+ message IdentityResponse {
48
+ string component = 1;
49
+ string software_version = 2;
50
+ // Compared against the adjacent component by strict equality. Not SemVer, no ranges.
51
+ map<string, int32> protocols = 3;
52
+ int32 pid = 4;
53
+ string status = 5;
54
+ }
55
+
56
+ // Graceful stop as a component control path rather than an OS signal. Served without client
57
+ // verification for the same reason as Identity -- stopping an Executor whose pair file is invalid
58
+ // is the main case -- and therefore restricted to loopback callers, since the listen host may be
59
+ // reachable from a LAN and an unauthenticated remote stop would be a trivial denial of service.
60
+ message ShutdownRequest {}
61
+ message ShutdownResponse {
62
+ string status = 1;
63
+ string component = 2;
64
+ string software_version = 3;
65
+ map<string, int32> protocols = 4;
66
+ int32 pid = 5;
67
+ }
68
+
69
+ message ReadFileRequest {
70
+ repeated string workspace_paths = 1;
71
+ string path = 2;
72
+ bool full_access = 3;
73
+ }
74
+ message ReadFileResponse {
75
+ string content = 1;
76
+ bool truncated = 2;
77
+ }
78
+
79
+ message WriteFileRequest {
80
+ repeated string workspace_paths = 1;
81
+ string path = 2;
82
+ string content = 3;
83
+ bool full_access = 4;
84
+ // Identify the change in the Executor's file history. Both are required: the Executor records
85
+ // the exact before/after bytes under (workspace_id, call_id) so RevertCall can restore them.
86
+ string workspace_id = 5;
87
+ string call_id = 6;
88
+ }
89
+ message WriteFileResponse {
90
+ string relative_path = 1;
91
+ int64 bytes = 2;
92
+ }
93
+
94
+ message EditFileRequest {
95
+ repeated string workspace_paths = 1;
96
+ string path = 2;
97
+ string old_string = 3;
98
+ string new_string = 4;
99
+ bool replace_all = 5;
100
+ bool full_access = 6;
101
+ string workspace_id = 7;
102
+ string call_id = 8;
103
+ }
104
+ message EditFileResponse {
105
+ string relative_path = 1;
106
+ int32 replacements = 2;
107
+ int64 bytes = 3;
108
+ }
109
+
110
+ // Restores the files recorded for one or more previous WriteFile/EditFile Calls. The Executor
111
+ // orders them by its own per-Workspace sequence and verifies, for every path, that the content on
112
+ // disk is still what the Call left behind. Any mismatch is reported in `conflicts` and nothing is
113
+ // written unless `force` is set.
114
+ message RevertCallRequest {
115
+ repeated string workspace_paths = 1;
116
+ string workspace_id = 2;
117
+ repeated string call_ids = 3;
118
+ bool force = 4;
119
+ bool full_access = 5;
120
+ // The reverting Call itself, recorded as a new change so a revert can be reverted.
121
+ string call_id = 6;
122
+ }
123
+ message RevertCallResponse {
124
+ repeated RevertedCall calls = 1;
125
+ repeated RevertConflict conflicts = 2;
126
+ }
127
+ message RevertedCall {
128
+ string call_id = 1;
129
+ repeated RevertedFile files = 2;
130
+ }
131
+ message RevertedFile {
132
+ string path = 1;
133
+ // restored | deleted
134
+ string action = 2;
135
+ }
136
+ message RevertConflict {
137
+ string call_id = 1;
138
+ string path = 2;
139
+ // content_changed: the file no longer holds what the Call wrote.
140
+ // unresolved: the record's outcome could not be determined.
141
+ // missing_record: this Workspace has history, but not for that Call id.
142
+ // no_history: this Workspace has no history store at all.
143
+ // outside_workspace: the recorded path is no longer inside the Workspace roots. `force` never
144
+ // waives this one -- it is a containment boundary, not a content disagreement.
145
+ string reason = 3;
146
+ }
147
+
148
+ // Answers what RevertCall would do right now, without doing it. Runs the identical simulation, so a
149
+ // clean preview and a failing revert cannot disagree about the same input. Read-only: the answer is
150
+ // a snapshot another writer can invalidate, so RevertCall re-simulates rather than trusting it.
151
+ message DescribeCallHistoryRequest {
152
+ repeated string workspace_paths = 1;
153
+ string workspace_id = 2;
154
+ repeated string call_ids = 3;
155
+ bool full_access = 4;
156
+ }
157
+ message DescribeCallHistoryResponse {
158
+ bool revertable = 1;
159
+ repeated DescribedCall calls = 2;
160
+ repeated RevertConflict conflicts = 3;
161
+ // The net effect on each path if the revert ran now.
162
+ repeated RevertedFile files = 4;
163
+ }
164
+ message DescribedCall {
165
+ string call_id = 1;
166
+ bool found = 2;
167
+ // PREPARED | COMMITTED | ABORTED | UNKNOWN, empty when found is false.
168
+ string status = 3;
169
+ int64 sequence = 4;
170
+ repeated string paths = 5;
171
+ }
172
+
173
+ // Drops the recorded history for these Calls, making them permanently unrevertable, and frees the
174
+ // objects. Driven by Core's controlled cleanup: the Executor never expires history on its own.
175
+ message DeleteCallHistoryRequest {
176
+ string workspace_id = 1;
177
+ repeated string call_ids = 2;
178
+ }
179
+ message DeleteCallHistoryResponse {
180
+ int32 deleted = 1;
181
+ int32 missing = 2;
182
+ }
183
+
184
+ message GlobRequest {
185
+ repeated string workspace_paths = 1;
186
+ string pattern = 2;
187
+ string path = 3;
188
+ bool include_hidden = 4;
189
+ int32 max_results = 5;
190
+ bool full_access = 6;
191
+ }
192
+ message GlobResponse {
193
+ repeated string matches = 1;
194
+ int32 count = 2;
195
+ bool truncated = 3;
196
+ }
197
+
198
+ message GrepRequest {
199
+ repeated string workspace_paths = 1;
200
+ string pattern = 2;
201
+ string path = 3;
202
+ string glob = 4;
203
+ bool include_hidden = 5;
204
+ bool literal = 6;
205
+ bool case_insensitive = 7;
206
+ int32 max_results = 8;
207
+ int32 max_bytes_per_file = 9;
208
+ bool full_access = 10;
209
+ }
210
+ message GrepMatch {
211
+ string path = 1;
212
+ int32 line = 2;
213
+ string text = 3;
214
+ }
215
+ message GrepResponse {
216
+ repeated GrepMatch matches = 1;
217
+ int32 count = 2;
218
+ bool truncated = 3;
219
+ }
220
+
221
+ message BrowseProjectRequest {
222
+ repeated string workspace_paths = 1;
223
+ string path = 2;
224
+ bool full_access = 3;
225
+ }
226
+ message BrowseEntry {
227
+ string name = 1;
228
+ bool is_directory = 2;
229
+ }
230
+ message BrowseProjectResponse {
231
+ string relative_path = 1;
232
+ repeated BrowseEntry entries = 2;
233
+ }
234
+
235
+ message RunCommandRequest {
236
+ repeated string workspace_paths = 1;
237
+ string command = 2;
238
+ repeated string args = 3;
239
+ string cwd = 4;
240
+ map<string, string> env = 5;
241
+ int32 timeout_ms = 6;
242
+ int32 output_limit_bytes = 7;
243
+ bool full_access = 8;
244
+ }
245
+ message RunCommandResponse {
246
+ int32 exit_code = 1;
247
+ string signal = 2;
248
+ string stdout = 3;
249
+ string stderr = 4;
250
+ int64 duration_ms = 5;
251
+ bool stdout_truncated = 6;
252
+ bool stderr_truncated = 7;
253
+ }
254
+
255
+ message GitRunRequest {
256
+ repeated string workspace_paths = 1;
257
+ repeated string args = 2;
258
+ string cwd = 3;
259
+ int32 timeout_ms = 4;
260
+ int32 output_limit_bytes = 5;
261
+ bool full_access = 6;
262
+ }
263
+ message GitRunResponse {
264
+ int32 exit_code = 1;
265
+ string stdout = 2;
266
+ string stderr = 3;
267
+ int64 duration_ms = 4;
268
+ bool stdout_truncated = 5;
269
+ bool stderr_truncated = 6;
270
+ }
271
+
272
+ message InternetSearchRequest {
273
+ string query = 1;
274
+ int32 max_results = 2;
275
+ }
276
+ message SearchResult {
277
+ string title = 1;
278
+ string url = 2;
279
+ string snippet = 3;
280
+ }
281
+ message InternetSearchResponse {
282
+ repeated SearchResult results = 1;
283
+ string provider = 2;
284
+ }
285
+
286
+ message ListAllowedParentRequest { string path = 1; }
287
+ message ListAllowedParentResponse {
288
+ string allowed_parent_dir = 1;
289
+ string relative_path = 2;
290
+ repeated BrowseEntry entries = 3;
291
+ }
292
+ message ValidateWorkspacePathsRequest {
293
+ repeated string workspace_paths = 1;
294
+ bool create_if_missing = 2;
295
+ }
296
+ message ValidateWorkspacePathsResponse {
297
+ repeated string resolved_paths = 1;
298
+ bool created = 2;
299
+ }
300
+ message OpenInFileManagerRequest {
301
+ repeated string workspace_paths = 1;
302
+ string path = 2;
303
+ bool full_access = 3;
304
+ }
305
+ message OpenInFileManagerResponse {
306
+ string opened_path = 1;
307
+ string platform = 2;
308
+ }
309
+ message ChooseWorkspaceFolderRequest {}
310
+ message ChooseWorkspaceFolderResponse {
311
+ bool cancelled = 1;
312
+ string chosen_path = 2;
313
+ string platform = 3;
314
+ }