@openagt/skill-github 0.1.9 → 0.1.11

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.
@@ -0,0 +1,27 @@
1
+ /**
2
+ * A GitHub user's public profile: the name and picture a person copies into OpenAgent as their
3
+ * own, once, when they press "Sync from GitHub". Read from GitHub's public API with no login, so
4
+ * no account of the person's, nor of OpenAgent's, is asked.
5
+ */
6
+ export type ProfileOutcome = {
7
+ ok: true;
8
+ login: string;
9
+ name?: string;
10
+ avatar?: string;
11
+ } | {
12
+ ok: false;
13
+ reason: 'no-user' | 'not-reached';
14
+ detail: string;
15
+ };
16
+ /** What fetches the profile: `fetch` by default. */
17
+ export type ProfileFetch = (url: string, init: {
18
+ headers: Record<string, string>;
19
+ signal: AbortSignal;
20
+ }) => Promise<{
21
+ ok: boolean;
22
+ status: number;
23
+ json(): Promise<unknown>;
24
+ }>;
25
+ export declare function isGithubLogin(login: string): boolean;
26
+ export declare function publicProfile(login: string, fetcher?: ProfileFetch): Promise<ProfileOutcome>;
27
+ //# sourceMappingURL=profile.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"profile.d.ts","sourceRoot":"","sources":["../src/profile.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,MAAM,MAAM,cAAc,GACtB;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,GAC3D;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,SAAS,GAAG,aAAa,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAA;AAEpE,oDAAoD;AACpD,MAAM,MAAM,YAAY,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE;IAAE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAAC,MAAM,EAAE,WAAW,CAAA;CAAE,KAAK,OAAO,CAAC;IAAE,EAAE,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,IAAI,IAAI,OAAO,CAAC,OAAO,CAAC,CAAA;CAAE,CAAC,CAAA;AAK9K,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAEpD;AAED,wBAAsB,aAAa,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,GAAE,YAAoB,GAAG,OAAO,CAAC,cAAc,CAAC,CAczG"}
@@ -0,0 +1,29 @@
1
+ /**
2
+ * A GitHub user's public profile: the name and picture a person copies into OpenAgent as their
3
+ * own, once, when they press "Sync from GitHub". Read from GitHub's public API with no login, so
4
+ * no account of the person's, nor of OpenAgent's, is asked.
5
+ */
6
+ /** A GitHub login, as GitHub allows one. */
7
+ const LOGIN = /^[A-Za-z0-9](?:[A-Za-z0-9-]{0,38})$/;
8
+ export function isGithubLogin(login) {
9
+ return LOGIN.test(login);
10
+ }
11
+ export async function publicProfile(login, fetcher = fetch) {
12
+ let answer;
13
+ try {
14
+ answer = await fetcher(`https://api.github.com/users/${encodeURIComponent(login)}`, { headers: { accept: 'application/vnd.github+json', 'user-agent': 'openagent' }, signal: AbortSignal.timeout(10_000) });
15
+ }
16
+ catch (err) {
17
+ return { ok: false, reason: 'not-reached', detail: err instanceof Error ? err.message : String(err) };
18
+ }
19
+ if (answer.status === 404)
20
+ return { ok: false, reason: 'no-user', detail: `GitHub has no user ${login}` };
21
+ if (!answer.ok)
22
+ return { ok: false, reason: 'not-reached', detail: `GitHub answered ${answer.status}` };
23
+ const body = ((await answer.json().catch(() => ({}))) ?? {});
24
+ const text = (value) => (typeof value === 'string' && value.trim() ? value.trim() : undefined);
25
+ const name = text(body['name']);
26
+ const avatar = text(body['avatar_url']);
27
+ return { ok: true, login: text(body['login']) ?? login, ...(name ? { name } : {}), ...(avatar?.startsWith('https://') ? { avatar } : {}) };
28
+ }
29
+ //# sourceMappingURL=profile.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"profile.js","sourceRoot":"","sources":["../src/profile.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AASH,4CAA4C;AAC5C,MAAM,KAAK,GAAG,qCAAqC,CAAA;AAEnD,MAAM,UAAU,aAAa,CAAC,KAAa;IACzC,OAAO,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;AAC1B,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,KAAa,EAAE,OAAO,GAAiB,KAAK;IAC9E,IAAI,MAAiE,CAAA;IACrE,IAAI,CAAC;QACH,MAAM,GAAG,MAAM,OAAO,CAAC,gCAAgC,kBAAkB,CAAC,KAAK,CAAC,EAAE,EAAE,EAAE,OAAO,EAAE,EAAE,MAAM,EAAE,6BAA6B,EAAE,YAAY,EAAE,WAAW,EAAE,EAAE,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC,CAAA;IAC7M,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAA;IACvG,CAAC;IACD,IAAI,MAAM,CAAC,MAAM,KAAK,GAAG;QAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,sBAAsB,KAAK,EAAE,EAAE,CAAA;IACzG,IAAI,CAAC,MAAM,CAAC,EAAE;QAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,EAAE,mBAAmB,MAAM,CAAC,MAAM,EAAE,EAAE,CAAA;IACvG,MAAM,IAAI,GAAG,CAAC,CAAC,MAAM,MAAM,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAA4B,CAAA;IACvF,MAAM,IAAI,GAAG,CAAC,KAAc,EAAsB,EAAE,CAAC,CAAC,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,CAAA;IAC3H,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAA;IAC/B,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,CAAA;IACvC,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,IAAI,KAAK,EAAE,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,UAAU,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAA;AAC5I,CAAC"}
@@ -0,0 +1,19 @@
1
+ import { type GhRunner } from './gh.js';
2
+ /**
3
+ * The repositories of a GitHub user or organization, as an account of OpenAgent's sees them:
4
+ * what the dashboard's project picker lists beside the repos on the computer, to be cloned when
5
+ * picked. Asked of `gh` as that account, so a private one it can read is listed too.
6
+ */
7
+ /** A repository as the picker lists it. */
8
+ export interface ListedRepo {
9
+ /** `github.com/<owner>/<name>`: the repository's one name on every machine. */
10
+ address: string;
11
+ url: string;
12
+ private: boolean;
13
+ pushedAt?: string;
14
+ description?: string;
15
+ }
16
+ /** How many repositories one listing asks for. */
17
+ export declare const REPOS_LIMIT = 300;
18
+ export declare function listRepos(gh: GhRunner, cwd: string, owner: string): Promise<ListedRepo[]>;
19
+ //# sourceMappingURL=repos.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"repos.d.ts","sourceRoot":"","sources":["../src/repos.ts"],"names":[],"mappings":"AACA,OAAO,EAAgB,KAAK,QAAQ,EAAE,MAAM,SAAS,CAAA;AAErD;;;;GAIG;AAEH,2CAA2C;AAC3C,MAAM,WAAW,UAAU;IACzB,+EAA+E;IAC/E,OAAO,EAAE,MAAM,CAAA;IACf,GAAG,EAAE,MAAM,CAAA;IACX,OAAO,EAAE,OAAO,CAAA;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,WAAW,CAAC,EAAE,MAAM,CAAA;CACrB;AAED,kDAAkD;AAClD,eAAO,MAAM,WAAW,MAAM,CAAA;AAE9B,wBAAsB,SAAS,CAAC,EAAE,EAAE,QAAQ,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC,CAoB/F"}
package/dist/repos.js ADDED
@@ -0,0 +1,28 @@
1
+ import { HOST } from './accounts.js';
2
+ import { errorMessage } from './gh.js';
3
+ /** How many repositories one listing asks for. */
4
+ export const REPOS_LIMIT = 300;
5
+ export async function listRepos(gh, cwd, owner) {
6
+ let said;
7
+ try {
8
+ said = JSON.parse(await gh(['repo', 'list', owner, '--limit', String(REPOS_LIMIT), '--json', 'nameWithOwner,url,isPrivate,pushedAt,description'], cwd));
9
+ }
10
+ catch (err) {
11
+ throw new Error(`GitHub did not list ${owner}'s repositories: ${errorMessage(err)}`);
12
+ }
13
+ const repos = [];
14
+ for (const row of Array.isArray(said) ? said : []) {
15
+ const { nameWithOwner, url, isPrivate, pushedAt, description } = (row ?? {});
16
+ if (typeof nameWithOwner !== 'string' || !/^[\w.-]+\/[\w.-]+$/.test(nameWithOwner) || typeof url !== 'string' || !url.startsWith('https://'))
17
+ continue;
18
+ repos.push({
19
+ address: `${HOST}/${nameWithOwner}`,
20
+ url,
21
+ private: isPrivate === true,
22
+ ...(typeof pushedAt === 'string' ? { pushedAt } : {}),
23
+ ...(typeof description === 'string' && description.trim() ? { description: description.trim() } : {}),
24
+ });
25
+ }
26
+ return repos.sort((a, b) => (b.pushedAt ?? '').localeCompare(a.pushedAt ?? ''));
27
+ }
28
+ //# sourceMappingURL=repos.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"repos.js","sourceRoot":"","sources":["../src/repos.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,eAAe,CAAA;AACpC,OAAO,EAAE,YAAY,EAAiB,MAAM,SAAS,CAAA;AAkBrD,kDAAkD;AAClD,MAAM,CAAC,MAAM,WAAW,GAAG,GAAG,CAAA;AAE9B,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,EAAY,EAAE,GAAW,EAAE,KAAa;IACtE,IAAI,IAAa,CAAA;IACjB,IAAI,CAAC;QACH,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,CAAC,WAAW,CAAC,EAAE,QAAQ,EAAE,kDAAkD,CAAC,EAAE,GAAG,CAAC,CAAC,CAAA;IACzJ,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,IAAI,KAAK,CAAC,uBAAuB,KAAK,oBAAoB,YAAY,CAAC,GAAG,CAAC,EAAE,CAAC,CAAA;IACtF,CAAC;IACD,MAAM,KAAK,GAAiB,EAAE,CAAA;IAC9B,KAAK,MAAM,GAAG,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;QAClD,MAAM,EAAE,aAAa,EAAE,GAAG,EAAE,SAAS,EAAE,QAAQ,EAAE,WAAW,EAAE,GAAG,CAAC,GAAG,IAAI,EAAE,CAA4B,CAAA;QACvG,IAAI,OAAO,aAAa,KAAK,QAAQ,IAAI,CAAC,oBAAoB,CAAC,IAAI,CAAC,aAAa,CAAC,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,UAAU,CAAC;YAAE,SAAQ;QACtJ,KAAK,CAAC,IAAI,CAAC;YACT,OAAO,EAAE,GAAG,IAAI,IAAI,aAAa,EAAE;YACnC,GAAG;YACH,OAAO,EAAE,SAAS,KAAK,IAAI;YAC3B,GAAG,CAAC,OAAO,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACrD,GAAG,CAAC,OAAO,WAAW,KAAK,QAAQ,IAAI,WAAW,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,WAAW,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SACtG,CAAC,CAAA;IACJ,CAAC;IACD,OAAO,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,QAAQ,IAAI,EAAE,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,QAAQ,IAAI,EAAE,CAAC,CAAC,CAAA;AACjF,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openagt/skill-github",
3
- "version": "0.1.9",
3
+ "version": "0.1.11",
4
4
  "description": "GitHub as a skill for coding agents: the project's pull requests and issues through gh, and the one command OpenAgent and the scheduler run for the git host: requests, open, merge, home, and replies, what came on the pull requests this machine's agents opened since each ended.",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -37,8 +37,8 @@
37
37
  "./SKILL.md": "./SKILL.md"
38
38
  },
39
39
  "dependencies": {
40
- "@openagt/agent-data": "0.0.9",
41
- "@openagt/skill-logs": "0.1.7"
40
+ "@openagt/agent-data": "0.0.14",
41
+ "@openagt/skill-logs": "0.1.11"
42
42
  },
43
43
  "devDependencies": {
44
44
  "@types/node": "^20.0.0",
@@ -47,7 +47,7 @@
47
47
  "scripts": {
48
48
  "build": "cp ../../skills/github/SKILL.md SKILL.md && tsc -p tsconfig.build.json",
49
49
  "typecheck": "tsc --noEmit",
50
- "test": "tsc -p tsconfig.test.json && node --test --test-timeout=60000 'dist-test/**/*.test.js'",
50
+ "test": "tsc -p tsconfig.test.json && XDG_CONFIG_HOME=$(mktemp -d) node --test --test-timeout=60000 'dist-test/**/*.test.js'",
51
51
  "clean": "rm -rf dist dist-test SKILL.md"
52
52
  }
53
53
  }
package/dist/me.d.ts DELETED
@@ -1,17 +0,0 @@
1
- import { type GhRunner } from './gh.js';
2
- /**
3
- * Who is signed in to GitHub through `gh`: what OpenAgent shows of the person at the foot of its
4
- * sidebar, their login, name and picture. Asked of `gh` as `create` asks for the account.
5
- */
6
- export type MeOutcome = {
7
- ok: true;
8
- login: string;
9
- name?: string;
10
- avatar?: string;
11
- } | {
12
- ok: false;
13
- reason: 'not-logged-in';
14
- detail: string;
15
- };
16
- export declare function signedIn(cwd: string, gh: GhRunner): Promise<MeOutcome>;
17
- //# sourceMappingURL=me.d.ts.map
package/dist/me.d.ts.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"file":"me.d.ts","sourceRoot":"","sources":["../src/me.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgB,KAAK,QAAQ,EAAE,MAAM,SAAS,CAAA;AAErD;;;GAGG;AAEH,MAAM,MAAM,SAAS,GACjB;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,GAC3D;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,eAAe,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAA;AAE1D,wBAAsB,QAAQ,CAAC,GAAG,EAAE,MAAM,EAAE,EAAE,EAAE,QAAQ,GAAG,OAAO,CAAC,SAAS,CAAC,CAa5E"}
package/dist/me.js DELETED
@@ -1,18 +0,0 @@
1
- import { errorMessage } from './gh.js';
2
- export async function signedIn(cwd, gh) {
3
- let answer;
4
- try {
5
- answer = JSON.parse(await gh(['api', 'user', '--jq', '{login: .login, name: .name, avatar: .avatar_url}'], cwd));
6
- }
7
- catch (err) {
8
- return { ok: false, reason: 'not-logged-in', detail: errorMessage(err) };
9
- }
10
- const text = (value) => (typeof value === 'string' && value.trim() ? value.trim() : undefined);
11
- const login = text(answer['login']);
12
- if (!login)
13
- return { ok: false, reason: 'not-logged-in', detail: 'gh named no account' };
14
- const name = text(answer['name']);
15
- const avatar = text(answer['avatar']);
16
- return { ok: true, login, ...(name ? { name } : {}), ...(avatar?.startsWith('https://') ? { avatar } : {}) };
17
- }
18
- //# sourceMappingURL=me.js.map
package/dist/me.js.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"file":"me.js","sourceRoot":"","sources":["../src/me.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAiB,MAAM,SAAS,CAAA;AAWrD,MAAM,CAAC,KAAK,UAAU,QAAQ,CAAC,GAAW,EAAE,EAAY;IACtD,IAAI,MAA+B,CAAA;IACnC,IAAI,CAAC;QACH,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,mDAAmD,CAAC,EAAE,GAAG,CAAC,CAA4B,CAAA;IAC7I,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,EAAE,YAAY,CAAC,GAAG,CAAC,EAAE,CAAA;IAC1E,CAAC;IACD,MAAM,IAAI,GAAG,CAAC,KAAc,EAAsB,EAAE,CAAC,CAAC,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,CAAA;IAC3H,MAAM,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAA;IACnC,IAAI,CAAC,KAAK;QAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,EAAE,qBAAqB,EAAE,CAAA;IACxF,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAA;IACjC,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAA;IACrC,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,UAAU,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAA;AAC9G,CAAC"}