@a3s-lab/code 2.6.0 → 3.0.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 (3) hide show
  1. package/README.md +35 -3
  2. package/index.d.ts +123 -0
  3. package/package.json +7 -7
package/README.md CHANGED
@@ -55,9 +55,8 @@ Scripts can also be loaded from workspace-relative `.js` or `.mjs` files with
55
55
  ## Workspace Backends And Direct Files
56
56
 
57
57
  The default workspace backend is the local filesystem rooted at the session
58
- workspace. SDK callers can pass the explicit typed backend now, using the same
59
- option surface that remote, browser, DFS, and container-backed workspaces will
60
- use:
58
+ workspace. SDK callers can pass an explicit typed backend through the same
59
+ option surface used by remote, browser, DFS, and container-backed workspaces:
61
60
 
62
61
  ```js
63
62
  const { Agent, LocalWorkspaceBackend } = require('@a3s-lab/code')
@@ -74,6 +73,39 @@ await session.editFile('notes.txt', 'one', 'uno')
74
73
  await session.patchFile('notes.txt', '@@ -1,2 +1,2 @@\n uno\n-two\n+dos')
75
74
  ```
76
75
 
76
+ ### S3-compatible object storage
77
+
78
+ `S3WorkspaceBackend` lets built-in file tools (`read`, `write`, `edit`,
79
+ `patch`, `ls`) target any S3-compatible endpoint — AWS S3, MinIO, RustFS,
80
+ Cloudflare R2, Backblaze B2, etc. `bash`, `git`, `grep`, and `glob` are
81
+ automatically hidden from the model because object storage cannot service
82
+ them.
83
+
84
+ ```js
85
+ const { Agent, S3WorkspaceBackend } = require('@a3s-lab/code')
86
+
87
+ const agent = await Agent.create('agent.acl')
88
+ const session = agent.session('s3://workspace/users/u1/sessions/s1', {
89
+ workspaceBackend: new S3WorkspaceBackend({
90
+ endpoint: 'https://minio.local:9000', // omit for AWS S3
91
+ region: 'us-east-1',
92
+ accessKeyId: 'AKIA...',
93
+ secretAccessKey: '...',
94
+ bucket: 'workspace',
95
+ prefix: 'users/u1/sessions/s1',
96
+ forcePathStyle: true, // true for MinIO/RustFS/R2
97
+ }),
98
+ })
99
+
100
+ await session.writeFile('notes/hello.txt', 'one\ntwo\n')
101
+ await session.readFile('notes/hello.txt')
102
+ await session.ls('notes')
103
+ ```
104
+
105
+ S3 has no atomic read-modify-write, so concurrent writers to the same key
106
+ overwrite each other (last-writer-wins). Partition workspaces per session or
107
+ user via the `prefix` field when running multi-tenant.
108
+
77
109
  ## Planning Events
78
110
 
79
111
  Planning is automatic by default. Prefer the explicit tri-state
package/index.d.ts CHANGED
@@ -71,6 +71,14 @@ export interface AgentEvent {
71
71
  verificationSummaryText?: string
72
72
  /** Extra data for events that don't map to standard fields (JSON-encoded) */
73
73
  data?: string
74
+ /**
75
+ * Structured discriminant for tool failures on `tool_end` events
76
+ * (JSON-encoded with a `type` field on the top level, e.g.
77
+ * `{"type":"version_conflict","path":"doc.md","expected":"etag-1","actual":"etag-2"}`).
78
+ * Undefined on success or untyped failure. Streaming consumers parse
79
+ * this to branch on the failure kind without scanning `toolOutput`.
80
+ */
81
+ errorKindJson?: string
74
82
  }
75
83
  export interface VerificationCommand {
76
84
  id: string
@@ -88,7 +96,32 @@ export interface ToolResult {
88
96
  metadataJson?: string
89
97
  /** Convenience JSON view of `metadata.document_runtime` when present. */
90
98
  documentRuntimeJson?: string
99
+ /**
100
+ * Structured discriminant for tool failures, JSON-encoded with a
101
+ * `type` field on the top level — e.g.
102
+ * `{"type":"version_conflict","path":"doc.md","expected":"etag-1","actual":"etag-2"}`.
103
+ * Undefined on success or untyped failure. SDK callers parse it to
104
+ * branch on the failure kind without scanning the `output` string.
105
+ */
106
+ errorKindJson?: string
91
107
  }
108
+
109
+ /**
110
+ * Parsed shape of `ToolResult.errorKindJson` / `AgentEvent.errorKindJson`.
111
+ *
112
+ * Use a discriminated union on the `type` field; new variants may be
113
+ * added in future minor releases — callers should match exhaustively on
114
+ * the kinds they care about and fall through to a default branch for
115
+ * unknown ones.
116
+ */
117
+ export type ToolErrorKind =
118
+ | { type: 'version_conflict'; path: string; expected: string; actual: string | null }
119
+ | { type: 'remote_git_conflict'; code: string; message: string }
120
+ | { type: 'not_found'; path: string }
121
+ | { type: 'invalid_argument'; message: string }
122
+ | { type: 'unsupported'; message: string }
123
+ | { type: 'timeout'; op: string; duration_ms: number }
124
+
92
125
  /** Execution limits for `Session.program`. */
93
126
  export interface ProgramScriptLimits {
94
127
  timeoutMs?: number
@@ -212,6 +245,79 @@ export interface JsS3BackendConfig {
212
245
  prefix: string
213
246
  /** `true` for MinIO / RustFS / most non-AWS endpoints; `false` for AWS S3. */
214
247
  forcePathStyle?: boolean
248
+ /**
249
+ * Maximum bytes a single `read` may return. The backend rejects any
250
+ * response with `Content-Length` greater than this without buffering
251
+ * the body. Defaults to 10 MiB on the Rust side when omitted.
252
+ */
253
+ maxReadBytes?: number
254
+ /**
255
+ * Enable degraded `grep` / `glob` against this S3 backend. Off by
256
+ * default — object storage has no native search, so the only viable
257
+ * strategy is `LIST` + `GET` + regex, which can be slow and expensive.
258
+ */
259
+ searchEnabled?: boolean
260
+ /**
261
+ * Upper bound on objects considered per `grep` / `glob` call. Defaults
262
+ * to 500 on the Rust side. Ignored when `searchEnabled` is `false`.
263
+ */
264
+ maxObjectsScanned?: number
265
+ /**
266
+ * Per-object body-size ceiling for `grep` downloads. Larger objects are
267
+ * skipped (debug-traced). Defaults to 1 MiB on the Rust side. Ignored
268
+ * when `searchEnabled` is `false`.
269
+ */
270
+ maxGrepBytesPerObject?: number
271
+ /**
272
+ * Concurrent object downloads during `grep`. Defaults to 8 on the Rust
273
+ * side. Set lower when the gitserver / S3 endpoint rate-limits
274
+ * aggressively; set higher when latency dominates. Ignored when
275
+ * `searchEnabled` is `false`.
276
+ */
277
+ searchConcurrency?: number
278
+ }
279
+ /**
280
+ * Configuration for a `RemoteGitBackend` — an HTTP/JSON client that
281
+ * brings the `git` tool to non-local workspaces (S3, future container /
282
+ * DFS).
283
+ *
284
+ * Pass alongside `workspaceBackend` on a session to attach remote git
285
+ * on top of any filesystem backend.
286
+ */
287
+ export interface JsRemoteGitBackendConfig {
288
+ /**
289
+ * Base URL of the gitserver, no trailing slash. The client builds
290
+ * `{baseUrl}/v1/repos/{repoId}/git/{op}` per the RFC.
291
+ */
292
+ baseUrl: string
293
+ /**
294
+ * Opaque repository identifier, URL-safe. Negotiated out of band
295
+ * with the gitserver operator.
296
+ */
297
+ repoId: string
298
+ /**
299
+ * Bearer token sent as `Authorization: Bearer <token>`. Required in
300
+ * production; omitting it emits a server-side warning and is only safe
301
+ * on a trusted localhost gitserver.
302
+ */
303
+ bearerToken?: string
304
+ /**
305
+ * mTLS client certificate path (PEM). When set together with `clientKeyPem`,
306
+ * the backend reads both files at construction and configures mTLS on the
307
+ * HTTP client. Setting only one of the pair errors at construction.
308
+ */
309
+ clientCertPem?: string
310
+ /**
311
+ * mTLS client private key path (PEM). PKCS#8 format expected for the
312
+ * `rustls-tls` backend. See `clientCertPem`.
313
+ */
314
+ clientKeyPem?: string
315
+ /** Per-call HTTP timeout in milliseconds. Defaults to 30 000. */
316
+ requestTimeoutMs?: number
317
+ /** Client-side cap on `diff` response bytes. Defaults to 1 MiB. */
318
+ maxDiffBytes?: number
319
+ /** Client-side cap on `log` `max_count`. Defaults to 200. */
320
+ maxLogEntries?: number
215
321
  }
216
322
  /**
217
323
  * Union type for AHP transport configuration.
@@ -386,6 +492,23 @@ export interface SessionOptions {
386
492
  * ```
387
493
  */
388
494
  workspaceBackend?: JsWorkspaceBackend
495
+ /**
496
+ * Optional remote git provider. When set, the resulting session attaches
497
+ * a `RemoteGitBackend` on top of `workspaceBackend` so the built-in
498
+ * `git` tool is available even on object-storage workspaces.
499
+ *
500
+ * ```js
501
+ * agent.session('s3://workspace/u1/s1', {
502
+ * workspaceBackend: new S3WorkspaceBackend({ ... }),
503
+ * remoteGit: {
504
+ * baseUrl: 'https://gitserver.internal',
505
+ * repoId: 'u1/s1',
506
+ * bearerToken: token,
507
+ * },
508
+ * });
509
+ * ```
510
+ */
511
+ remoteGit?: JsRemoteGitBackendConfig
389
512
  /**
390
513
  * Custom role/identity prepended before the core agentic prompt.
391
514
  * Example: "You are a senior Python developer specializing in FastAPI."
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@a3s-lab/code",
3
- "version": "2.6.0",
3
+ "version": "3.0.0",
4
4
  "description": "A3S Code - Native Node.js bindings for the coding-agent runtime",
5
5
  "main": "index.js",
6
6
  "types": "index.d.ts",
@@ -40,11 +40,11 @@
40
40
  "test:helpers": "node test-helpers.mjs"
41
41
  },
42
42
  "optionalDependencies": {
43
- "@a3s-lab/code-darwin-arm64": "2.6.0",
44
- "@a3s-lab/code-linux-x64-gnu": "2.6.0",
45
- "@a3s-lab/code-linux-x64-musl": "2.6.0",
46
- "@a3s-lab/code-linux-arm64-gnu": "2.6.0",
47
- "@a3s-lab/code-linux-arm64-musl": "2.6.0",
48
- "@a3s-lab/code-win32-x64-msvc": "2.6.0"
43
+ "@a3s-lab/code-darwin-arm64": "3.0.0",
44
+ "@a3s-lab/code-linux-x64-gnu": "3.0.0",
45
+ "@a3s-lab/code-linux-x64-musl": "3.0.0",
46
+ "@a3s-lab/code-linux-arm64-gnu": "3.0.0",
47
+ "@a3s-lab/code-linux-arm64-musl": "3.0.0",
48
+ "@a3s-lab/code-win32-x64-msvc": "3.0.0"
49
49
  }
50
50
  }