agentic-pi 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 (53) hide show
  1. package/README.md +418 -0
  2. package/dist/args.d.ts +31 -0
  3. package/dist/args.js +109 -0
  4. package/dist/args.js.map +1 -0
  5. package/dist/cli.d.ts +9 -0
  6. package/dist/cli.js +47 -0
  7. package/dist/cli.js.map +1 -0
  8. package/dist/emitter.d.ts +49 -0
  9. package/dist/emitter.js +67 -0
  10. package/dist/emitter.js.map +1 -0
  11. package/dist/extensions/github/auth.d.ts +54 -0
  12. package/dist/extensions/github/auth.js +116 -0
  13. package/dist/extensions/github/auth.js.map +1 -0
  14. package/dist/extensions/github/client.d.ts +6387 -0
  15. package/dist/extensions/github/client.js +358 -0
  16. package/dist/extensions/github/client.js.map +1 -0
  17. package/dist/extensions/github/credentials.d.ts +24 -0
  18. package/dist/extensions/github/credentials.js +44 -0
  19. package/dist/extensions/github/credentials.js.map +1 -0
  20. package/dist/extensions/github/index.d.ts +46 -0
  21. package/dist/extensions/github/index.js +67 -0
  22. package/dist/extensions/github/index.js.map +1 -0
  23. package/dist/extensions/github/profiles.d.ts +17 -0
  24. package/dist/extensions/github/profiles.js +71 -0
  25. package/dist/extensions/github/profiles.js.map +1 -0
  26. package/dist/extensions/github/tools.d.ts +18 -0
  27. package/dist/extensions/github/tools.js +289 -0
  28. package/dist/extensions/github/tools.js.map +1 -0
  29. package/dist/index.d.ts +38 -0
  30. package/dist/index.js +34 -0
  31. package/dist/index.js.map +1 -0
  32. package/dist/models.d.ts +13 -0
  33. package/dist/models.js +31 -0
  34. package/dist/models.js.map +1 -0
  35. package/dist/run.d.ts +139 -0
  36. package/dist/run.js +131 -0
  37. package/dist/run.js.map +1 -0
  38. package/dist/runner.d.ts +22 -0
  39. package/dist/runner.js +143 -0
  40. package/dist/runner.js.map +1 -0
  41. package/dist/sandbox/gondolin.d.ts +39 -0
  42. package/dist/sandbox/gondolin.js +210 -0
  43. package/dist/sandbox/gondolin.js.map +1 -0
  44. package/dist/sandbox/index.d.ts +37 -0
  45. package/dist/sandbox/index.js +55 -0
  46. package/dist/sandbox/index.js.map +1 -0
  47. package/dist/sandbox/preflight.d.ts +24 -0
  48. package/dist/sandbox/preflight.js +93 -0
  49. package/dist/sandbox/preflight.js.map +1 -0
  50. package/dist/stdin.d.ts +1 -0
  51. package/dist/stdin.js +11 -0
  52. package/dist/stdin.js.map +1 -0
  53. package/package.json +44 -0
@@ -0,0 +1,49 @@
1
+ /**
2
+ * JSONL event emitter.
3
+ *
4
+ * Two sinks ship: `StdoutSink` (used by the CLI) and `CollectorSink` (used
5
+ * by the programmatic `run()` API to capture events in-process). The
6
+ * `Emitter` wraps a sink and injects `sessionId` + `timestamp` into every
7
+ * record, plus the session header.
8
+ *
9
+ * Consumers can provide their own sink — e.g. lastlight could write
10
+ * straight to the dashboard's shim jsonl while also calling onEvent for
11
+ * accumulator-side state updates.
12
+ */
13
+ export interface EmitterRecord {
14
+ type: string;
15
+ [key: string]: unknown;
16
+ }
17
+ export interface EmitterSink {
18
+ write(record: EmitterRecord): void;
19
+ }
20
+ export interface EmitterContext {
21
+ sessionId: string;
22
+ cwd: string;
23
+ startedAt: string;
24
+ }
25
+ /** Writes JSONL to process.stdout. Used by the CLI. */
26
+ export declare class StdoutSink implements EmitterSink {
27
+ write(record: EmitterRecord): void;
28
+ }
29
+ /** Captures every record in an in-memory array. Used by `run()`. */
30
+ export declare class CollectorSink implements EmitterSink {
31
+ private readonly onRecord?;
32
+ readonly records: EmitterRecord[];
33
+ /** Optional pass-through (e.g. for live observation by the programmatic caller). */
34
+ constructor(onRecord?: ((r: EmitterRecord) => void) | undefined);
35
+ write(record: EmitterRecord): void;
36
+ }
37
+ /** Fan-out sink — writes the same record to every downstream sink. */
38
+ export declare class TeeSink implements EmitterSink {
39
+ private readonly sinks;
40
+ constructor(sinks: EmitterSink[]);
41
+ write(record: EmitterRecord): void;
42
+ }
43
+ export declare class Emitter {
44
+ private readonly ctx;
45
+ private readonly sink;
46
+ constructor(ctx: EmitterContext, sink: EmitterSink);
47
+ sessionHeader(): void;
48
+ event(event: EmitterRecord): void;
49
+ }
@@ -0,0 +1,67 @@
1
+ /**
2
+ * JSONL event emitter.
3
+ *
4
+ * Two sinks ship: `StdoutSink` (used by the CLI) and `CollectorSink` (used
5
+ * by the programmatic `run()` API to capture events in-process). The
6
+ * `Emitter` wraps a sink and injects `sessionId` + `timestamp` into every
7
+ * record, plus the session header.
8
+ *
9
+ * Consumers can provide their own sink — e.g. lastlight could write
10
+ * straight to the dashboard's shim jsonl while also calling onEvent for
11
+ * accumulator-side state updates.
12
+ */
13
+ /** Writes JSONL to process.stdout. Used by the CLI. */
14
+ export class StdoutSink {
15
+ write(record) {
16
+ process.stdout.write(JSON.stringify(record) + "\n");
17
+ }
18
+ }
19
+ /** Captures every record in an in-memory array. Used by `run()`. */
20
+ export class CollectorSink {
21
+ onRecord;
22
+ records = [];
23
+ /** Optional pass-through (e.g. for live observation by the programmatic caller). */
24
+ constructor(onRecord) {
25
+ this.onRecord = onRecord;
26
+ }
27
+ write(record) {
28
+ this.records.push(record);
29
+ this.onRecord?.(record);
30
+ }
31
+ }
32
+ /** Fan-out sink — writes the same record to every downstream sink. */
33
+ export class TeeSink {
34
+ sinks;
35
+ constructor(sinks) {
36
+ this.sinks = sinks;
37
+ }
38
+ write(record) {
39
+ for (const s of this.sinks)
40
+ s.write(record);
41
+ }
42
+ }
43
+ export class Emitter {
44
+ ctx;
45
+ sink;
46
+ constructor(ctx, sink) {
47
+ this.ctx = ctx;
48
+ this.sink = sink;
49
+ }
50
+ sessionHeader() {
51
+ this.sink.write({
52
+ type: "session",
53
+ version: 3,
54
+ id: this.ctx.sessionId,
55
+ timestamp: this.ctx.startedAt,
56
+ cwd: this.ctx.cwd,
57
+ });
58
+ }
59
+ event(event) {
60
+ this.sink.write({
61
+ ...event,
62
+ sessionId: this.ctx.sessionId,
63
+ timestamp: new Date().toISOString(),
64
+ });
65
+ }
66
+ }
67
+ //# sourceMappingURL=emitter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"emitter.js","sourceRoot":"","sources":["../src/emitter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAiBH,uDAAuD;AACvD,MAAM,OAAO,UAAU;IACrB,KAAK,CAAC,MAAqB;QACzB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,GAAG,IAAI,CAAC,CAAC;IACtD,CAAC;CACF;AAED,oEAAoE;AACpE,MAAM,OAAO,aAAa;IAGK;IAFpB,OAAO,GAAoB,EAAE,CAAC;IACvC,oFAAoF;IACpF,YAA6B,QAAqC;QAArC,aAAQ,GAAR,QAAQ,CAA6B;IAAG,CAAC;IACtE,KAAK,CAAC,MAAqB;QACzB,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAC1B,IAAI,CAAC,QAAQ,EAAE,CAAC,MAAM,CAAC,CAAC;IAC1B,CAAC;CACF;AAED,sEAAsE;AACtE,MAAM,OAAO,OAAO;IACW;IAA7B,YAA6B,KAAoB;QAApB,UAAK,GAAL,KAAK,CAAe;IAAG,CAAC;IACrD,KAAK,CAAC,MAAqB;QACzB,KAAK,MAAM,CAAC,IAAI,IAAI,CAAC,KAAK;YAAE,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IAC9C,CAAC;CACF;AAED,MAAM,OAAO,OAAO;IAEC;IACA;IAFnB,YACmB,GAAmB,EACnB,IAAiB;QADjB,QAAG,GAAH,GAAG,CAAgB;QACnB,SAAI,GAAJ,IAAI,CAAa;IACjC,CAAC;IAEJ,aAAa;QACX,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC;YACd,IAAI,EAAE,SAAS;YACf,OAAO,EAAE,CAAC;YACV,EAAE,EAAE,IAAI,CAAC,GAAG,CAAC,SAAS;YACtB,SAAS,EAAE,IAAI,CAAC,GAAG,CAAC,SAAS;YAC7B,GAAG,EAAE,IAAI,CAAC,GAAG,CAAC,GAAG;SAClB,CAAC,CAAC;IACL,CAAC;IAED,KAAK,CAAC,KAAoB;QACxB,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC;YACd,GAAG,KAAK;YACR,SAAS,EAAE,IAAI,CAAC,GAAG,CAAC,SAAS;YAC7B,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;SACpC,CAAC,CAAC;IACL,CAAC;CACF"}
@@ -0,0 +1,54 @@
1
+ /**
2
+ * GitHub App authentication.
3
+ *
4
+ * Ported from lastlight/mcp-github-app/src/auth.js with minimal changes:
5
+ * - TypeScript types
6
+ * - Static-token fallback wrapped into a shared GitHubAuth interface
7
+ */
8
+ export interface GitHubAuth {
9
+ /** Returns a currently-valid GitHub installation token (or the static token). */
10
+ getToken(): Promise<string>;
11
+ /** When the cached App token expires (null for static-token mode). */
12
+ readonly expiresAt: Date | null;
13
+ }
14
+ export interface GitHubAppAuthOptions {
15
+ appId: string;
16
+ privateKeyPath: string;
17
+ installationId: string;
18
+ }
19
+ export declare class GitHubAppAuth implements GitHubAuth {
20
+ private readonly appId;
21
+ private readonly installationId;
22
+ private readonly privateKey;
23
+ private _token;
24
+ private _expiresAt;
25
+ constructor({ appId, privateKeyPath, installationId }: GitHubAppAuthOptions);
26
+ private generateJwt;
27
+ getToken(): Promise<string>;
28
+ get expiresAt(): Date | null;
29
+ }
30
+ export interface GitHubAuthEnv {
31
+ GITHUB_APP_ID?: string;
32
+ GITHUB_APP_PRIVATE_KEY_PATH?: string;
33
+ GITHUB_APP_INSTALLATION_ID?: string;
34
+ GITHUB_TOKEN?: string;
35
+ }
36
+ /** Why auth could not be built. Consumers can distinguish silent skips from misconfiguration. */
37
+ export type AuthFailureReason = "no-credentials" | "pem-unreadable" | "invalid-config";
38
+ export interface BuildAuthResult {
39
+ auth: GitHubAuth | null;
40
+ reason?: AuthFailureReason;
41
+ message?: string;
42
+ }
43
+ /**
44
+ * Construct the appropriate auth backend from env vars.
45
+ *
46
+ * Prefer GitHub App credentials when all three are present. Static-token mode
47
+ * is the fallback for low-trust sandboxes that intentionally clear the App env
48
+ * vars — this stops a stale host-side GITHUB_TOKEN PAT from silently
49
+ * downgrading the agent's auth. Mirrors mcp-github-app's behaviour.
50
+ *
51
+ * Returns a structured result so the caller can decide whether to warn or
52
+ * just silently skip GitHub-tool registration.
53
+ */
54
+ export declare function buildAuthFromEnv(env?: GitHubAuthEnv): BuildAuthResult;
@@ -0,0 +1,116 @@
1
+ /**
2
+ * GitHub App authentication.
3
+ *
4
+ * Ported from lastlight/mcp-github-app/src/auth.js with minimal changes:
5
+ * - TypeScript types
6
+ * - Static-token fallback wrapped into a shared GitHubAuth interface
7
+ */
8
+ import { readFileSync } from "node:fs";
9
+ import { resolve } from "node:path";
10
+ import jwt from "jsonwebtoken";
11
+ export class GitHubAppAuth {
12
+ appId;
13
+ installationId;
14
+ privateKey;
15
+ _token = null;
16
+ _expiresAt = null;
17
+ constructor({ appId, privateKeyPath, installationId }) {
18
+ this.appId = appId;
19
+ this.installationId = installationId;
20
+ try {
21
+ this.privateKey = readFileSync(resolve(privateKeyPath), "utf8");
22
+ }
23
+ catch (err) {
24
+ throw new Error(`GitHubAppAuth: cannot read private key at '${privateKeyPath}': ${err.message}`);
25
+ }
26
+ }
27
+ generateJwt() {
28
+ const now = Math.floor(Date.now() / 1000);
29
+ return jwt.sign({ iat: now - 60, exp: now + 600, iss: this.appId }, this.privateKey, { algorithm: "RS256" });
30
+ }
31
+ async getToken() {
32
+ if (this._token && this._expiresAt) {
33
+ const bufferMs = 5 * 60 * 1000;
34
+ if (Date.now() + bufferMs < this._expiresAt.getTime()) {
35
+ return this._token;
36
+ }
37
+ }
38
+ const jwtToken = this.generateJwt();
39
+ const res = await fetch(`https://api.github.com/app/installations/${this.installationId}/access_tokens`, {
40
+ method: "POST",
41
+ headers: {
42
+ Authorization: `Bearer ${jwtToken}`,
43
+ Accept: "application/vnd.github+json",
44
+ },
45
+ });
46
+ if (!res.ok) {
47
+ const body = await res.text();
48
+ throw new Error(`Failed to get installation token (${res.status}): ${body}`);
49
+ }
50
+ const data = (await res.json());
51
+ this._token = data.token;
52
+ this._expiresAt = new Date(data.expires_at);
53
+ return this._token;
54
+ }
55
+ get expiresAt() {
56
+ return this._expiresAt;
57
+ }
58
+ }
59
+ class StaticTokenAuth {
60
+ token;
61
+ constructor(token) {
62
+ this.token = token;
63
+ }
64
+ async getToken() {
65
+ return this.token;
66
+ }
67
+ get expiresAt() {
68
+ return null;
69
+ }
70
+ }
71
+ /**
72
+ * Construct the appropriate auth backend from env vars.
73
+ *
74
+ * Prefer GitHub App credentials when all three are present. Static-token mode
75
+ * is the fallback for low-trust sandboxes that intentionally clear the App env
76
+ * vars — this stops a stale host-side GITHUB_TOKEN PAT from silently
77
+ * downgrading the agent's auth. Mirrors mcp-github-app's behaviour.
78
+ *
79
+ * Returns a structured result so the caller can decide whether to warn or
80
+ * just silently skip GitHub-tool registration.
81
+ */
82
+ export function buildAuthFromEnv(env = process.env) {
83
+ const { GITHUB_APP_ID, GITHUB_APP_PRIVATE_KEY_PATH, GITHUB_APP_INSTALLATION_ID, GITHUB_TOKEN } = env;
84
+ const appParts = [GITHUB_APP_ID, GITHUB_APP_PRIVATE_KEY_PATH, GITHUB_APP_INSTALLATION_ID];
85
+ const appPartsSet = appParts.filter(Boolean).length;
86
+ if (appPartsSet === 3) {
87
+ try {
88
+ const auth = new GitHubAppAuth({
89
+ appId: GITHUB_APP_ID,
90
+ privateKeyPath: GITHUB_APP_PRIVATE_KEY_PATH,
91
+ installationId: GITHUB_APP_INSTALLATION_ID,
92
+ });
93
+ return { auth };
94
+ }
95
+ catch (err) {
96
+ return {
97
+ auth: null,
98
+ reason: "pem-unreadable",
99
+ message: err.message,
100
+ };
101
+ }
102
+ }
103
+ if (appPartsSet > 0 && appPartsSet < 3) {
104
+ return {
105
+ auth: null,
106
+ reason: "invalid-config",
107
+ message: `Partial GitHub App credentials: ${appPartsSet}/3 of GITHUB_APP_ID, GITHUB_APP_PRIVATE_KEY_PATH, GITHUB_APP_INSTALLATION_ID are set. ` +
108
+ `Set all three to use App auth, or unset all three to fall back to GITHUB_TOKEN.`,
109
+ };
110
+ }
111
+ if (GITHUB_TOKEN) {
112
+ return { auth: new StaticTokenAuth(GITHUB_TOKEN) };
113
+ }
114
+ return { auth: null, reason: "no-credentials" };
115
+ }
116
+ //# sourceMappingURL=auth.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.js","sourceRoot":"","sources":["../../../src/extensions/github/auth.ts"],"names":[],"mappings":"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"}