exoagent 0.0.12 → 0.0.14

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 (59) hide show
  1. package/README.md +7 -10
  2. package/dist/code-mode.d.ts +2 -24
  3. package/dist/exoeval/allowed.d.ts +9 -0
  4. package/dist/exoeval/builtins.d.ts +188 -0
  5. package/dist/exoeval/evaluator.d.ts +68 -0
  6. package/dist/exoeval/expr.d.ts +50 -0
  7. package/dist/exoeval/index.d.ts +16 -0
  8. package/dist/exoeval/lib/index.d.ts +1 -0
  9. package/dist/exoeval/scope.d.ts +13 -0
  10. package/dist/exoeval/tool.d.ts +49 -0
  11. package/dist/exoeval/utils.d.ts +9 -0
  12. package/dist/index.d.ts +3 -5
  13. package/dist/index.mjs +8255 -205
  14. package/dist/rpc-toolset-test-helpers.d.ts +2 -5
  15. package/dist/runtime/daemon.d.ts +37 -0
  16. package/dist/runtime/dts.d.ts +21 -0
  17. package/dist/runtime/eslint-exo-rule.d.ts +3 -0
  18. package/dist/runtime/exo.d.ts +33 -0
  19. package/dist/runtime/providers/args.d.ts +13 -0
  20. package/dist/runtime/providers/pi.d.ts +68 -0
  21. package/dist/runtime/providers/review.d.ts +82 -0
  22. package/dist/runtime/providers/sandbox.d.ts +54 -0
  23. package/dist/runtime/providers/secrets.d.ts +18 -0
  24. package/dist/runtime/providers/storage.d.ts +16 -0
  25. package/dist/runtime/secrets-ui.d.ts +19 -0
  26. package/dist/runtime/start-agent.d.ts +2 -0
  27. package/dist/runtime/start.d.ts +2 -0
  28. package/dist/sql/builder.d.ts +6 -7
  29. package/dist/sql/expression.d.ts +1 -2
  30. package/dist/sql.mjs +61 -77
  31. package/dist/tool-5wSlXWJ2.js +176 -0
  32. package/dist/tool-wrapper.d.ts +6 -13
  33. package/package.json +11 -10
  34. package/dist/capnweb/LICENSE.txt +0 -21
  35. package/dist/capnweb/README.md +0 -734
  36. package/dist/capnweb/dist/index-workers.cjs +0 -2791
  37. package/dist/capnweb/dist/index-workers.cjs.map +0 -1
  38. package/dist/capnweb/dist/index-workers.d.cts +0 -2
  39. package/dist/capnweb/dist/index-workers.d.ts +0 -2
  40. package/dist/capnweb/dist/index-workers.js +0 -2754
  41. package/dist/capnweb/dist/index-workers.js.map +0 -1
  42. package/dist/capnweb/dist/index.cjs +0 -2768
  43. package/dist/capnweb/dist/index.cjs.map +0 -1
  44. package/dist/capnweb/dist/index.d.cts +0 -383
  45. package/dist/capnweb/dist/index.d.ts +0 -383
  46. package/dist/capnweb/dist/index.js +0 -2751
  47. package/dist/capnweb/dist/index.js.map +0 -1
  48. package/dist/capnweb/package.json +0 -59
  49. package/dist/capnweb-test-helpers.d.ts +0 -25
  50. package/dist/chunk-VBDAOXYI-BhoIkhUn.mjs +0 -831
  51. package/dist/code-mode-deno.d.ts +0 -13
  52. package/dist/code-mode-runtime.d.ts +0 -1
  53. package/dist/nodefs-C8H-6XZ_.mjs +0 -26
  54. package/dist/opfs-ahp-Dy9HQOrY.mjs +0 -367
  55. package/dist/rpc-toolset-BnC2BXPq.js +0 -146
  56. package/dist/rpc-toolset-test-helpers.d.mts +0 -254
  57. package/dist/rpc-toolset-test-helpers.mjs +0 -10364
  58. package/dist/rpc-toolset.d.ts +0 -34
  59. package/dist/stream-transport.d.ts +0 -11
@@ -1,5 +1,4 @@
1
- import { RpcToolset } from './rpc-toolset';
2
- export declare class TestToolset extends RpcToolset {
1
+ export declare class TestToolset {
3
2
  add(input: {
4
3
  a: number;
5
4
  b: number;
@@ -9,7 +8,7 @@ export declare class TestToolset extends RpcToolset {
9
8
  id: string;
10
9
  }): Promise<typeof User>;
11
10
  }
12
- export declare class TestToolset2 extends RpcToolset {
11
+ export declare class TestToolset2 {
13
12
  subtract(input: {
14
13
  a: number;
15
14
  b: number;
@@ -20,7 +19,6 @@ declare const User_base: Omit<import('./sql').TableClass<"users">, keyof import(
20
19
  remapColumns?: boolean;
21
20
  };
22
21
  column: (this: InstanceType<import('./sql').TableClass<string>>, columnName: string) => import('./sql/expression').ColumnReferenceExpression;
23
- __RPC_TARGET_BRAND: never;
24
22
  });
25
23
  export declare class User extends User_base {
26
24
  id: import('./sql/expression').ColumnReferenceExpression;
@@ -34,7 +32,6 @@ declare const Post_base: Omit<import('./sql').TableClass<"posts">, keyof import(
34
32
  remapColumns?: boolean;
35
33
  };
36
34
  column: (this: InstanceType<import('./sql').TableClass<string>>, columnName: string) => import('./sql/expression').ColumnReferenceExpression;
37
- __RPC_TARGET_BRAND: never;
38
35
  });
39
36
  export declare class Post extends Post_base {
40
37
  id: import('./sql/expression').ColumnReferenceExpression;
@@ -0,0 +1,37 @@
1
+ import { Secrets } from './providers/secrets';
2
+ import { StorageCap } from './providers/storage';
3
+ /**
4
+ * exoagentd — runtime daemon.
5
+ *
6
+ * Owns shared infrastructure (storage, secrets) and manages
7
+ * agent processes via dtach (terminal session manager).
8
+ */
9
+ export interface DaemonConfig {
10
+ repoDir: string;
11
+ dataDir?: string;
12
+ }
13
+ export declare class Daemon {
14
+ readonly repoDir: string;
15
+ readonly dataDir: string;
16
+ readonly storage: StorageCap;
17
+ readonly secrets: Secrets;
18
+ private constructor();
19
+ static start(config: DaemonConfig): Promise<Daemon>;
20
+ /** Validate agentId — alphanumeric, hyphens, underscores only */
21
+ private validateAgentId;
22
+ /** Spawn an agent in a dtach session */
23
+ spawn(agentId: string): Promise<string>;
24
+ /** Attach to an agent — replaces current process with dtach */
25
+ attach(agentId: string): void;
26
+ /** List running agents (by socket files) */
27
+ list(): string[];
28
+ /** Kill an agent — terminates the dtach process tree */
29
+ kill(agentId: string): void;
30
+ /** Run an exo with daemon caps */
31
+ runExo(name: string, exoArgs?: string[]): Promise<unknown>;
32
+ /** Eval arbitrary code with daemon caps (like an inline exo) */
33
+ evalCode(code: string): Promise<unknown>;
34
+ /** Get a ReviewCap for the default clone (if exists) */
35
+ private getReviewCap;
36
+ stop(): Promise<void>;
37
+ }
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Generate a .d.ts declaration string from a TypeScript source file.
3
+ *
4
+ * Uses the TypeScript compiler API to emit declarations. Resolves imports
5
+ * so the output includes full type information.
6
+ *
7
+ * @param filePath - Absolute path to the .ts source file
8
+ * @returns The generated .d.ts content
9
+ */
10
+ export declare function generateDts(filePath: string): string;
11
+ /**
12
+ * Generate a .d.ts for a class, extracting only its public method signatures.
13
+ *
14
+ * This produces a minimal type declaration suitable for codemode — just the
15
+ * methods the LLM can call, without internal implementation details.
16
+ *
17
+ * @param filePath - Absolute path to the .ts source file
18
+ * @param className - Name of the class to extract
19
+ * @returns A declaration string like `{ method(args): ReturnType; ... }`
20
+ */
21
+ export declare function generateCapDts(filePath: string, className: string): string;
@@ -0,0 +1,3 @@
1
+ import { Rule } from 'eslint';
2
+ declare const rule: Rule.RuleModule;
3
+ export default rule;
@@ -0,0 +1,33 @@
1
+ /**
2
+ * An Exo is a sandboxed program. It declares its caps by destructuring
3
+ * the first argument of its default export.
4
+ *
5
+ * ```javascript
6
+ * export default async ({ sandbox, review, storage }) => {
7
+ * await sandbox.exec({ command: 'echo hello' })
8
+ * }
9
+ * ```
10
+ *
11
+ * Only the destructured caps are available — exoeval enforces this at
12
+ * the interpreter level. Every exo gets the full cap set; the destructure
13
+ * is the audit trail for what it actually uses.
14
+ */
15
+ /**
16
+ * An exo module's default export signature.
17
+ * Caps are received as a single object, destructured by the exo.
18
+ */
19
+ export type ExoFn = (caps: Record<string, object>) => void | Promise<void>;
20
+ /**
21
+ * Metadata for an exo — loaded from its module.
22
+ */
23
+ export interface ExoDef {
24
+ readonly name: string;
25
+ readonly run: ExoFn;
26
+ }
27
+ /**
28
+ * Loads an exo from source code via exoImport (the sandboxed interpreter).
29
+ * The source must `export default` a function that takes a caps object.
30
+ *
31
+ * Source should already be plain JS (run through esbuild if TypeScript).
32
+ */
33
+ export declare function loadExo(name: string, code: string): Promise<ExoDef>;
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Args cap — provides CLI arguments to exos.
3
+ */
4
+ export declare class ArgsCap {
5
+ private map;
6
+ constructor(args: string[]);
7
+ get({ key }: {
8
+ key: string;
9
+ }): Promise<string | undefined>;
10
+ has({ key }: {
11
+ key: string;
12
+ }): Promise<boolean>;
13
+ }
@@ -0,0 +1,68 @@
1
+ import { Model } from '@mariozechner/pi-ai';
2
+ import { ExtensionFactory, AgentSession, SessionManager, SettingsManager } from '@mariozechner/pi-coding-agent';
3
+ import { Secrets } from './secrets';
4
+ import { StorageCap } from './storage';
5
+ import { ReviewCap } from './review';
6
+ import { SandboxCap } from './sandbox';
7
+ export interface PiCapConfig {
8
+ sandbox: SandboxCap;
9
+ /** Arbitrary capability objects to expose via codemode */
10
+ caps?: Record<string, object>;
11
+ /** Additional system prompt text */
12
+ systemPrompt?: string;
13
+ /** Pre-generated .d.ts for caps (required when caps are provided) */
14
+ capsDts: string;
15
+ /** @internal */ model?: Model<any>;
16
+ /** @internal */ extensionFactories?: ExtensionFactory[];
17
+ /** @internal */ settingsManager?: SettingsManager;
18
+ /** @internal */ sessionManager?: SessionManager;
19
+ }
20
+ export declare class PiCap {
21
+ private config;
22
+ private session;
23
+ private modelFallbackMessage?;
24
+ constructor(config: PiCapConfig);
25
+ private sandboxBashOps;
26
+ /** Read a file via sandbox exec, returns base64-decoded content */
27
+ private sandboxRead;
28
+ /** Write a file via sandbox exec, content passed via stdin */
29
+ private sandboxWrite;
30
+ /** Check file access via sandbox exec */
31
+ private sandboxAccess;
32
+ private scopedReadOps;
33
+ private scopedWriteOps;
34
+ private scopedEditOps;
35
+ private buildCodemodeTool;
36
+ private ensureSession;
37
+ /** Send a prompt and return the final text response (background mode) */
38
+ prompt(message: string): Promise<string>;
39
+ /** Access the underlying session (for interactive TUI attach) */
40
+ get currentSession(): AgentSession | null;
41
+ /** Initialize session without prompting (for interactive mode) */
42
+ init(): Promise<AgentSession>;
43
+ /** Run pi's interactive TUI (handles /login, /model, etc.) */
44
+ runInteractive(options?: {
45
+ initialMessage?: string;
46
+ }): Promise<void>;
47
+ /** Dispose the session */
48
+ dispose(): void;
49
+ }
50
+ export interface SpawnAgentConfig {
51
+ id: string;
52
+ repoDir: string;
53
+ dataDir: string;
54
+ storage: StorageCap;
55
+ secrets: Secrets;
56
+ }
57
+ export interface Agent {
58
+ readonly id: string;
59
+ readonly pi: PiCap;
60
+ readonly review: ReviewCap | undefined;
61
+ readonly cloneDir: string;
62
+ }
63
+ /**
64
+ * Spawn a coding agent — wires sandbox + review + pi together.
65
+ * Creates a local clone, sets up sandbox and review caps, and returns
66
+ * a fully configured Agent.
67
+ */
68
+ export declare function spawnAgent(config: SpawnAgentConfig): Promise<Agent>;
@@ -0,0 +1,82 @@
1
+ /**
2
+ * Review provider — GitHub PR-based code review.
3
+ *
4
+ * Pushes branches to GitHub, opens PRs, fetches reviews.
5
+ * Git push assumes the host has SSH/credentials configured.
6
+ * Only GitHub API operations use the token (from secrets DB).
7
+ */
8
+ /** Review result — uses GitHub API shapes directly (no wrapper types) */
9
+ export interface ReviewResult {
10
+ approved: boolean;
11
+ body: string;
12
+ /** Inline review comments (GitHub PullRequestReviewComment objects) */
13
+ comments: any[];
14
+ /** PR-level issue comments (GitHub IssueComment objects) */
15
+ issueComments: any[];
16
+ pr: number;
17
+ url: string;
18
+ }
19
+ export interface ReviewCapConfig {
20
+ /** Path to the agent's local clone */
21
+ cloneDir: string;
22
+ /** Nix git store path */
23
+ git: string;
24
+ /** GitHub API token (pre-attenuated from secrets) */
25
+ token: string;
26
+ /** GitHub owner/repo (e.g. "user/repo") */
27
+ repo: string;
28
+ /** Base branch for PRs. Default: "main" */
29
+ baseBranch?: string;
30
+ /** Poll interval in ms. Default: 5000 */
31
+ pollInterval?: number;
32
+ /** Agent name for branch prefixing. Default: "default" */
33
+ agentName?: string;
34
+ }
35
+ export declare class ReviewCap {
36
+ private config;
37
+ constructor(config: ReviewCapConfig);
38
+ /** GitHub API token (pre-attenuated, single source of truth) */
39
+ private get token();
40
+ /** Prefix branch name with agent namespace. */
41
+ private qualifyBranch;
42
+ /**
43
+ * Push a branch to GitHub and open/update a PR.
44
+ * Returns immediately with the PR URL.
45
+ * Remote branch will be auto-prefixed with `exoagent-<agent>/`.
46
+ */
47
+ openPR({ branch, title, body }: {
48
+ branch: string;
49
+ title: string;
50
+ body?: string;
51
+ }): Promise<{
52
+ pr: number;
53
+ url: string;
54
+ sha: string;
55
+ }>;
56
+ /**
57
+ * Get the latest review on a PR. Returns immediately (non-blocking).
58
+ * Returns the most recent non-pending review with its comments.
59
+ */
60
+ getReviews({ pr }: {
61
+ pr: number;
62
+ }): Promise<ReviewResult>;
63
+ /**
64
+ * Reply to a specific review comment on a PR.
65
+ */
66
+ replyToComment({ pr, commentId, body }: {
67
+ pr: number;
68
+ commentId: number;
69
+ body: string;
70
+ }): Promise<{
71
+ id: number;
72
+ }>;
73
+ /**
74
+ * Post a general comment on a PR (issue-level comment).
75
+ */
76
+ commentOnPR({ pr, body }: {
77
+ pr: number;
78
+ body: string;
79
+ }): Promise<{
80
+ id: number;
81
+ }>;
82
+ }
@@ -0,0 +1,54 @@
1
+ import { StorageCap } from './storage';
2
+ /**
3
+ * Sandbox provider — bwrap-based execution environment with network
4
+ * isolation (internet yes, LAN/loopback blocked via pasta + nft).
5
+ *
6
+ * - exec: runs commands inside bwrap (PID-isolated, net-filtered, fs-scoped)
7
+ * - read/write/edit: host-side file ops, path-validated to workspace
8
+ */
9
+ /** Nix store paths for essential binaries */
10
+ export interface NixPaths {
11
+ bash: string;
12
+ coreutils: string;
13
+ bwrap: string;
14
+ pasta: string;
15
+ nft: string;
16
+ nix: string;
17
+ cacert: string;
18
+ git: string;
19
+ gnugrep: string;
20
+ dtach: string;
21
+ }
22
+ /** Read nix paths from EXOAGENT_NIX env var (JSON) set by flake.nix devShell */
23
+ export declare function nixPathsFromEnv(): NixPaths;
24
+ interface SandboxConfig {
25
+ nix: NixPaths;
26
+ storage: StorageCap;
27
+ sessionId: string;
28
+ workspace: string;
29
+ }
30
+ export declare class SandboxCap {
31
+ private config;
32
+ private rootDir;
33
+ private scriptWritten;
34
+ constructor(config: SandboxConfig);
35
+ private getRoot;
36
+ /** Compute the transitive closure of nix store paths needed in the sandbox */
37
+ private nixClosure;
38
+ /** Validate a path is safe to interpolate into a shell script (no special chars) */
39
+ private static assertSafePath;
40
+ /** Write the wrapper script once, reuse for every exec */
41
+ private ensureScript;
42
+ exec({ command, timeout, signal, stdin }: {
43
+ command: string;
44
+ timeout?: number;
45
+ signal?: AbortSignal;
46
+ stdin?: string;
47
+ }): Promise<{
48
+ stdout: string;
49
+ stderr: string;
50
+ exitCode: number;
51
+ }>;
52
+ get workspace(): string;
53
+ }
54
+ export {};
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Daemon-only secrets store. Never exposed to exos.
3
+ * Each provider gets its own set of named secrets (e.g. API keys).
4
+ */
5
+ export declare class Secrets {
6
+ private readonly root;
7
+ private readonly db;
8
+ private constructor();
9
+ /**
10
+ * Create a Secrets store backed by a SQLite DB in the given directory.
11
+ * Initializes the directory (mode 0700) and DB schema on first call.
12
+ */
13
+ static create(root: string): Secrets;
14
+ get(provider: string, name: string): string | null;
15
+ set(provider: string, name: string, value: string): void;
16
+ delete(provider: string, name: string): void;
17
+ close(): void;
18
+ }
@@ -0,0 +1,16 @@
1
+ export declare class StorageCap {
2
+ private readonly root;
3
+ private readonly provider;
4
+ private readonly db;
5
+ private constructor();
6
+ /**
7
+ * Create a StorageCap backed by a SQLite DB in the given directory.
8
+ * Initializes the directory and DB schema on first call.
9
+ */
10
+ static create(root: string, provider?: string): StorageCap;
11
+ get(key: string): Promise<unknown>;
12
+ set(key: string, value: unknown): Promise<void>;
13
+ delete(key: string): Promise<void>;
14
+ close(): void;
15
+ dir(name: string): Promise<string>;
16
+ }
@@ -0,0 +1,19 @@
1
+ import { Secrets } from './providers/secrets';
2
+ /**
3
+ * Secret declaration — providers declare what secrets they need.
4
+ */
5
+ export interface SecretDecl {
6
+ name: string;
7
+ required: boolean;
8
+ description: string;
9
+ }
10
+ export interface ProviderSecrets {
11
+ provider: string;
12
+ secrets: SecretDecl[];
13
+ }
14
+ /** Known providers and their secrets */
15
+ export declare const PROVIDER_SECRETS: ProviderSecrets[];
16
+ /**
17
+ * Interactive TUI for managing secrets.
18
+ */
19
+ export declare function runSecretsUI(db: Secrets): Promise<void>;
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
@@ -1,5 +1,4 @@
1
1
  import { CompiledQuery, Dialect } from 'kysely';
2
- import { ToolCallback, RpcToolset } from '../rpc-toolset';
3
2
  import { SqlExpressionIn, ColumnReferenceExpression, OrderByValue, SqlExpression } from './expression';
4
3
  import { RawSql } from './sql';
5
4
  type RowLikeRaw = {
@@ -26,7 +25,7 @@ export declare const isFromItem: (value: unknown) => value is FromItem<string, R
26
25
  type TableNamespace = {
27
26
  [key: string]: RowLike;
28
27
  };
29
- type OrderByItem<TN extends TableNamespace> = NamespacedExpression<TN, SqlExpression | SqlExpression[] | OrderByValue | OrderByValue[] | (SqlExpression | OrderByValue)[]>;
28
+ type OrderByItem = SqlExpression | SqlExpression[] | OrderByValue | OrderByValue[] | (SqlExpression | OrderByValue)[];
30
29
  type Tables<TN extends TableNamespace> = {
31
30
  [k in keyof TN & string]: {
32
31
  fromItem: FromItem<k, TN[k]>;
@@ -46,7 +45,7 @@ type QueryBuilderParams<N extends string, TN extends TableNamespace, S extends R
46
45
  offset?: number;
47
46
  rawTable: TableClass<N> | undefined;
48
47
  };
49
- declare class QueryBuilder<N extends string, TN extends TableNamespace, S extends RowLike> extends RpcToolset implements FromItem<N, S> {
48
+ declare class QueryBuilder<N extends string, TN extends TableNamespace, S extends RowLike> implements FromItem<N, S> {
50
49
  #private;
51
50
  readonly alias: N;
52
51
  private selectRowLike;
@@ -56,9 +55,9 @@ declare class QueryBuilder<N extends string, TN extends TableNamespace, S extend
56
55
  private arg;
57
56
  private rawTable;
58
57
  constructor(params: QueryBuilderParams<N, TN, S>);
59
- select<S2 extends RowLikeIn>(select: ToolCallback<(arg: TN) => S2>): QueryBuilder<N, TN, AsRowLike<S2>>;
60
- where(where: ToolCallback<(arg: TN) => SqlExpressionIn>): QueryBuilder<N, TN, S>;
61
- orderBy(orderBy: ToolCallback<OrderByItem<TN>>): QueryBuilder<N, TN, S>;
58
+ select<S2 extends RowLikeIn>(select: (arg: TN) => S2): QueryBuilder<N, TN, AsRowLike<S2>>;
59
+ where(where: (arg: TN) => SqlExpressionIn): QueryBuilder<N, TN, S>;
60
+ orderBy(orderBy: (arg: TN) => OrderByItem): QueryBuilder<N, TN, S>;
62
61
  limit(limit: number): QueryBuilder<N, TN, S>;
63
62
  offset(offset: number): QueryBuilder<N, TN, S>;
64
63
  join<N2 extends string, F2 extends TableClass<N2>>(fromItem: F2 | NamespacedExpression<TN, F2>, on?: NamespacedExpression<TN & {
@@ -84,7 +83,7 @@ declare class QueryBuilder<N extends string, TN extends TableNamespace, S extend
84
83
  isSubquery?: boolean;
85
84
  }) => import('kysely').RawBuilder<unknown>;
86
85
  }
87
- declare class TableBase extends RpcToolset {
86
+ declare class TableBase {
88
87
  opts?: {
89
88
  remapColumns?: boolean;
90
89
  };
@@ -1,10 +1,9 @@
1
1
  import { RawSql } from './sql';
2
- import { RpcToolset } from '../rpc-toolset';
3
2
  type LiteralValue = number | string | boolean | null;
4
3
  export type SqlExpressionIn = LiteralValue | SqlExpression;
5
4
  export declare const asSqlExpression: (value: LiteralValue | SqlExpression) => SqlExpression;
6
5
  export declare const isSqlExpressionIn: (value: unknown) => value is SqlExpressionIn;
7
- export declare class SqlExpression extends RpcToolset {
6
+ export declare class SqlExpression {
8
7
  precedence: number;
9
8
  constructor(precedence?: number);
10
9
  compile: () => RawSql;