@openagt/dashboard 0.33.1 → 0.34.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.
- package/dist/dashboard/send-skills.js +1 -1
- package/dist/dashboard/send-skills.js.map +1 -1
- package/dist/dashboard/start-branch.js +1 -1
- package/dist/dashboard/start-branch.js.map +1 -1
- package/dist/dashboard-bundle/assets/{main-BJEMTscF.js → main-Bmnmb8kW.js} +13 -13
- package/dist/dashboard-bundle/assets/main-vGm5VAD9.css +2 -0
- package/dist/dashboard-bundle/assets/module-Bl9E9F3x.js +14 -0
- package/dist/dashboard-bundle/host/module.js +1 -1
- package/dist/dashboard-bundle/index.html +3 -3
- package/dist/dashboard-rpc/skills.d.ts +3 -4
- package/dist/dashboard-rpc/skills.d.ts.map +1 -1
- package/dist/dashboard-rpc/skills.js +4 -1
- package/dist/dashboard-rpc/skills.js.map +1 -1
- package/dist/module-types/src/dashboard-rpc/skills.d.ts +3 -4
- package/dist/module-types/src/project-skills/apply.d.ts +35 -0
- package/dist/module-types/src/project-skills/branch.d.ts +29 -0
- package/dist/module-types/src/project-skills/catalogue.d.ts +39 -0
- package/dist/module-types/src/project-skills/change.d.ts +29 -0
- package/dist/module-types/src/project-skills/commit.d.ts +16 -0
- package/dist/module-types/src/project-skills/project.d.ts +42 -0
- package/dist/module-types/src/project-skills/skill-file.d.ts +16 -0
- package/dist/project-skills/apply.d.ts +36 -0
- package/dist/project-skills/apply.d.ts.map +1 -0
- package/dist/project-skills/apply.js +89 -0
- package/dist/project-skills/apply.js.map +1 -0
- package/dist/project-skills/branch.d.ts +30 -0
- package/dist/project-skills/branch.d.ts.map +1 -0
- package/dist/project-skills/branch.js +82 -0
- package/dist/project-skills/branch.js.map +1 -0
- package/dist/project-skills/catalogue.d.ts +40 -0
- package/dist/project-skills/catalogue.d.ts.map +1 -0
- package/dist/project-skills/catalogue.js +39 -0
- package/dist/project-skills/catalogue.js.map +1 -0
- package/dist/project-skills/change.d.ts +30 -0
- package/dist/project-skills/change.d.ts.map +1 -0
- package/dist/project-skills/change.js +29 -0
- package/dist/project-skills/change.js.map +1 -0
- package/dist/project-skills/commit.d.ts +17 -0
- package/dist/project-skills/commit.d.ts.map +1 -0
- package/dist/project-skills/commit.js +40 -0
- package/dist/project-skills/commit.js.map +1 -0
- package/dist/project-skills/project.d.ts +43 -0
- package/dist/project-skills/project.d.ts.map +1 -0
- package/dist/project-skills/project.js +60 -0
- package/dist/project-skills/project.js.map +1 -0
- package/dist/project-skills/skill-file.d.ts +17 -0
- package/dist/project-skills/skill-file.d.ts.map +1 -0
- package/dist/project-skills/skill-file.js +39 -0
- package/dist/project-skills/skill-file.js.map +1 -0
- package/dist/project-skills/test-project.d.ts +6 -0
- package/dist/project-skills/test-project.d.ts.map +1 -0
- package/dist/project-skills/test-project.js +31 -0
- package/dist/project-skills/test-project.js.map +1 -0
- package/package.json +28 -11
- package/dist/dashboard-bundle/assets/main-aHhLUwxc.css +0 -2
- package/dist/dashboard-bundle/assets/module-D7LI75mm.js +0 -14
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The skills a project can pick in the dashboard's Skills list (#2023), in its groups, with what
|
|
3
|
+
* is ticked the first time. Every group is ticked except the skills that are useless until something of
|
|
4
|
+
* their own is set up. The skills every run gets by default are not here (the branches skill,
|
|
5
|
+
* and the ones `@openagt/start` names): they come with every run, with nothing written in the
|
|
6
|
+
* project.
|
|
7
|
+
*
|
|
8
|
+
* Each skill's text is its own package's `SKILL.md`, read from this package's install, so the
|
|
9
|
+
* dashboard carries the texts of the versions it was published with.
|
|
10
|
+
*/
|
|
11
|
+
export interface SkillGroup {
|
|
12
|
+
title: string;
|
|
13
|
+
skills: readonly string[];
|
|
14
|
+
/** Whether the group's skills are ticked in a project that has none of them yet. */
|
|
15
|
+
ticked: boolean;
|
|
16
|
+
}
|
|
17
|
+
export declare const GROUPS: readonly SkillGroup[];
|
|
18
|
+
/** Every skill of the list, in its order. */
|
|
19
|
+
export declare const SKILL_NAMES: readonly string[];
|
|
20
|
+
/**
|
|
21
|
+
* The scheduler's skill: written, it also gets the two lines that start the scheduler while the
|
|
22
|
+
* dashboard is open, in the project's hooks file, which is this machine's and outside git; deleted,
|
|
23
|
+
* it takes them out. Ticked by default: every automation starts switched off, so the scheduler
|
|
24
|
+
* starts no agent until a person says so.
|
|
25
|
+
*/
|
|
26
|
+
export declare const SCHEDULER = "scheduler";
|
|
27
|
+
/** One skill as the dashboard carries it. */
|
|
28
|
+
export interface CarriedSkill {
|
|
29
|
+
name: string;
|
|
30
|
+
/** The package the text is from, and its version: what a written text is stamped with. */
|
|
31
|
+
package: string;
|
|
32
|
+
version: string;
|
|
33
|
+
/** The whole `SKILL.md`. */
|
|
34
|
+
text: string;
|
|
35
|
+
/** The `description` of its front matter, in one line. */
|
|
36
|
+
description: string;
|
|
37
|
+
}
|
|
38
|
+
/** Every skill of the list with its text, read once from this package's own install. */
|
|
39
|
+
export declare function carriedSkills(): Promise<Map<string, CarriedSkill>>;
|
|
40
|
+
//# sourceMappingURL=catalogue.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"catalogue.d.ts","sourceRoot":"","sources":["../../src/project-skills/catalogue.ts"],"names":[],"mappings":"AAIA;;;;;;;;;GASG;AAEH,MAAM,WAAW,UAAU;IACzB,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,EAAE,SAAS,MAAM,EAAE,CAAA;IACzB,oFAAoF;IACpF,MAAM,EAAE,OAAO,CAAA;CAChB;AAED,eAAO,MAAM,MAAM,EAAE,SAAS,UAAU,EAOvC,CAAA;AAED,6CAA6C;AAC7C,eAAO,MAAM,WAAW,EAAE,SAAS,MAAM,EAA0C,CAAA;AAEnF;;;;;GAKG;AACH,eAAO,MAAM,SAAS,cAAc,CAAA;AAEpC,6CAA6C;AAC7C,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAA;IACZ,0FAA0F;IAC1F,OAAO,EAAE,MAAM,CAAA;IACf,OAAO,EAAE,MAAM,CAAA;IACf,4BAA4B;IAC5B,IAAI,EAAE,MAAM,CAAA;IACZ,0DAA0D;IAC1D,WAAW,EAAE,MAAM,CAAA;CACpB;AAID,wFAAwF;AACxF,wBAAgB,aAAa,IAAI,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC,CAElE"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { readFile, realpath } from 'node:fs/promises';
|
|
2
|
+
import { createRequire } from 'node:module';
|
|
3
|
+
import { dirname, join } from 'node:path';
|
|
4
|
+
export const GROUPS = [
|
|
5
|
+
{ title: 'Tickets and queue', ticked: true, skills: ['plan', 'plan-tickets', 'triage', 'update-tickets', 'work-queue', 'suggest-new-tickets', 'suggest-tickets-to-work-on'] },
|
|
6
|
+
{ title: 'Reviews and research', ticked: true, skills: ['maintainability', 'maintenance', 'readability', 'security-audit', 'ux', 'research', 'market-research', 'suggest-new-features'] },
|
|
7
|
+
{ title: 'Pull requests', ticked: true, skills: ['reply'] },
|
|
8
|
+
{ title: 'After a merge', ticked: true, skills: ['post-merge-cleanup'] },
|
|
9
|
+
{ title: 'Automations', ticked: true, skills: ['scheduler'] },
|
|
10
|
+
{ title: 'Needs its own setup', ticked: false, skills: ['browser', 'discord'] },
|
|
11
|
+
];
|
|
12
|
+
/** Every skill of the list, in its order. */
|
|
13
|
+
export const SKILL_NAMES = GROUPS.flatMap(group => group.skills);
|
|
14
|
+
/**
|
|
15
|
+
* The scheduler's skill: written, it also gets the two lines that start the scheduler while the
|
|
16
|
+
* dashboard is open, in the project's hooks file, which is this machine's and outside git; deleted,
|
|
17
|
+
* it takes them out. Ticked by default: every automation starts switched off, so the scheduler
|
|
18
|
+
* starts no agent until a person says so.
|
|
19
|
+
*/
|
|
20
|
+
export const SCHEDULER = 'scheduler';
|
|
21
|
+
let carried;
|
|
22
|
+
/** Every skill of the list with its text, read once from this package's own install. */
|
|
23
|
+
export function carriedSkills() {
|
|
24
|
+
return (carried ??= readCarried());
|
|
25
|
+
}
|
|
26
|
+
async function readCarried() {
|
|
27
|
+
const require = createRequire(import.meta.url);
|
|
28
|
+
const skills = new Map();
|
|
29
|
+
for (const name of SKILL_NAMES) {
|
|
30
|
+
const pkg = `@openagt/skill-${name}`;
|
|
31
|
+
const dir = await realpath(dirname(require.resolve(`${pkg}/package.json`)));
|
|
32
|
+
const manifest = JSON.parse(await readFile(join(dir, 'package.json'), 'utf8'));
|
|
33
|
+
const text = await readFile(join(dir, 'SKILL.md'), 'utf8');
|
|
34
|
+
const description = /^description:[ \t]*(.*)$/m.exec(text)?.[1]?.trim().replace(/^"(.*)"$/, '$1') ?? '';
|
|
35
|
+
skills.set(name, { name, package: pkg, version: manifest.version, text, description });
|
|
36
|
+
}
|
|
37
|
+
return skills;
|
|
38
|
+
}
|
|
39
|
+
//# sourceMappingURL=catalogue.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"catalogue.js","sourceRoot":"","sources":["../../src/project-skills/catalogue.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAA;AACrD,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAA;AAC3C,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AAoBzC,MAAM,CAAC,MAAM,MAAM,GAA0B;IAC3C,EAAE,KAAK,EAAE,mBAAmB,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,MAAM,EAAE,cAAc,EAAE,QAAQ,EAAE,gBAAgB,EAAE,YAAY,EAAE,qBAAqB,EAAE,4BAA4B,CAAC,EAAE;IAC7K,EAAE,KAAK,EAAE,sBAAsB,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,iBAAiB,EAAE,aAAa,EAAE,aAAa,EAAE,gBAAgB,EAAE,IAAI,EAAE,UAAU,EAAE,iBAAiB,EAAE,sBAAsB,CAAC,EAAE;IACzL,EAAE,KAAK,EAAE,eAAe,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,OAAO,CAAC,EAAE;IAC3D,EAAE,KAAK,EAAE,eAAe,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,oBAAoB,CAAC,EAAE;IACxE,EAAE,KAAK,EAAE,aAAa,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,WAAW,CAAC,EAAE;IAC7D,EAAE,KAAK,EAAE,qBAAqB,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,SAAS,EAAE,SAAS,CAAC,EAAE;CAChF,CAAA;AAED,6CAA6C;AAC7C,MAAM,CAAC,MAAM,WAAW,GAAsB,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,CAAA;AAEnF;;;;;GAKG;AACH,MAAM,CAAC,MAAM,SAAS,GAAG,WAAW,CAAA;AAcpC,IAAI,OAAuD,CAAA;AAE3D,wFAAwF;AACxF,MAAM,UAAU,aAAa;IAC3B,OAAO,CAAC,OAAO,KAAK,WAAW,EAAE,CAAC,CAAA;AACpC,CAAC;AAED,KAAK,UAAU,WAAW;IACxB,MAAM,OAAO,GAAG,aAAa,CAAC,OAAO,IAAI,CAAC,GAAG,CAAC,CAAA;IAC9C,MAAM,MAAM,GAAG,IAAI,GAAG,EAAwB,CAAA;IAC9C,KAAK,MAAM,IAAI,IAAI,WAAW,EAAE,CAAC;QAC/B,MAAM,GAAG,GAAG,kBAAkB,IAAI,EAAE,CAAA;QACpC,MAAM,GAAG,GAAG,MAAM,QAAQ,CAAC,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,GAAG,eAAe,CAAC,CAAC,CAAC,CAAA;QAC3E,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,QAAQ,CAAC,IAAI,CAAC,GAAG,EAAE,cAAc,CAAC,EAAE,MAAM,CAAC,CAAwB,CAAA;QACrG,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,CAAC,GAAG,EAAE,UAAU,CAAC,EAAE,MAAM,CAAC,CAAA;QAC1D,MAAM,WAAW,GAAG,2BAA2B,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,OAAO,CAAC,UAAU,EAAE,IAAI,CAAC,IAAI,EAAE,CAAA;QACvG,MAAM,CAAC,GAAG,CAAC,IAAI,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,EAAE,OAAO,EAAE,QAAQ,CAAC,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC,CAAA;IACxF,CAAC;IACD,OAAO,MAAM,CAAA;AACf,CAAC"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/** One change to a project's skills, from the dashboard's Skills list or its Update button. */
|
|
2
|
+
export interface Change {
|
|
3
|
+
/** Skills to write: a new one, or one written again over what is there. */
|
|
4
|
+
write?: readonly string[];
|
|
5
|
+
/** Skills to delete. */
|
|
6
|
+
remove?: readonly string[];
|
|
7
|
+
}
|
|
8
|
+
export interface Changed {
|
|
9
|
+
written: string[];
|
|
10
|
+
removed: string[];
|
|
11
|
+
/** Every tracked path the change wrote or deleted, from the project's root: what its commit holds. */
|
|
12
|
+
paths: string[];
|
|
13
|
+
/** What was left as it is, and why. */
|
|
14
|
+
left: {
|
|
15
|
+
path: string;
|
|
16
|
+
reason: string;
|
|
17
|
+
}[];
|
|
18
|
+
/** The scheduler after the change, when the change wrote or deleted its skill; `error` when it could not be switched. */
|
|
19
|
+
scheduler?: {
|
|
20
|
+
on: boolean;
|
|
21
|
+
changed: boolean;
|
|
22
|
+
} | {
|
|
23
|
+
on: boolean;
|
|
24
|
+
error: string;
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
/** Whether `name` is a skill of the list. */
|
|
28
|
+
export declare function isKnown(name: string): boolean;
|
|
29
|
+
export declare function applyChange(root: string, change: Change): Promise<Changed>;
|
|
30
|
+
//# sourceMappingURL=change.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"change.d.ts","sourceRoot":"","sources":["../../src/project-skills/change.ts"],"names":[],"mappings":"AAGA,+FAA+F;AAE/F,MAAM,WAAW,MAAM;IACrB,2EAA2E;IAC3E,KAAK,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;IACzB,wBAAwB;IACxB,MAAM,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;CAC3B;AAED,MAAM,WAAW,OAAO;IACtB,OAAO,EAAE,MAAM,EAAE,CAAA;IACjB,OAAO,EAAE,MAAM,EAAE,CAAA;IACjB,sGAAsG;IACtG,KAAK,EAAE,MAAM,EAAE,CAAA;IACf,uCAAuC;IACvC,IAAI,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,EAAE,CAAA;IACxC,yHAAyH;IACzH,SAAS,CAAC,EAAE;QAAE,EAAE,EAAE,OAAO,CAAC;QAAC,OAAO,EAAE,OAAO,CAAA;KAAE,GAAG;QAAE,EAAE,EAAE,OAAO,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAA;CAC/E;AAED,6CAA6C;AAC7C,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAE7C;AAED,wBAAsB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAoBhF"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { SCHEDULER, SKILL_NAMES } from './catalogue.js';
|
|
2
|
+
import { removeSkill, setScheduler, writeSkill } from './apply.js';
|
|
3
|
+
/** Whether `name` is a skill of the list. */
|
|
4
|
+
export function isKnown(name) {
|
|
5
|
+
return SKILL_NAMES.includes(name);
|
|
6
|
+
}
|
|
7
|
+
export async function applyChange(root, change) {
|
|
8
|
+
const changed = { written: [], removed: [], paths: [], left: [] };
|
|
9
|
+
for (const name of change.write ?? []) {
|
|
10
|
+
const touched = await writeSkill(root, name);
|
|
11
|
+
changed.written.push(name);
|
|
12
|
+
changed.paths.push(...touched.paths);
|
|
13
|
+
changed.left.push(...touched.left);
|
|
14
|
+
}
|
|
15
|
+
for (const name of change.remove ?? []) {
|
|
16
|
+
const touched = await removeSkill(root, name);
|
|
17
|
+
if (touched.paths.length > 0)
|
|
18
|
+
changed.removed.push(name);
|
|
19
|
+
changed.paths.push(...touched.paths);
|
|
20
|
+
changed.left.push(...touched.left);
|
|
21
|
+
}
|
|
22
|
+
const scheduler = change.write?.includes(SCHEDULER) ? true : change.remove?.includes(SCHEDULER) ? false : undefined;
|
|
23
|
+
if (scheduler !== undefined) {
|
|
24
|
+
const outcome = await setScheduler(root, scheduler);
|
|
25
|
+
changed.scheduler = outcome.ok ? { on: scheduler, changed: outcome.changed } : { on: scheduler, error: outcome.error };
|
|
26
|
+
}
|
|
27
|
+
return changed;
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=change.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"change.js","sourceRoot":"","sources":["../../src/project-skills/change.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAA;AACvD,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;AAsBlE,6CAA6C;AAC7C,MAAM,UAAU,OAAO,CAAC,IAAY;IAClC,OAAO,WAAW,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAA;AACnC,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,IAAY,EAAE,MAAc;IAC5D,MAAM,OAAO,GAAY,EAAE,OAAO,EAAE,EAAE,EAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE,CAAA;IAC1E,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,KAAK,IAAI,EAAE,EAAE,CAAC;QACtC,MAAM,OAAO,GAAG,MAAM,UAAU,CAAC,IAAI,EAAE,IAAI,CAAC,CAAA;QAC5C,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;QAC1B,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,KAAK,CAAC,CAAA;QACpC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IACpC,CAAC;IACD,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,MAAM,IAAI,EAAE,EAAE,CAAC;QACvC,MAAM,OAAO,GAAG,MAAM,WAAW,CAAC,IAAI,EAAE,IAAI,CAAC,CAAA;QAC7C,IAAI,OAAO,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC;YAAE,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;QACxD,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,KAAK,CAAC,CAAA;QACpC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IACpC,CAAC;IACD,MAAM,SAAS,GAAG,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAA;IACnH,IAAI,SAAS,KAAK,SAAS,EAAE,CAAC;QAC5B,MAAM,OAAO,GAAG,MAAM,YAAY,CAAC,IAAI,EAAE,SAAS,CAAC,CAAA;QACnD,OAAO,CAAC,SAAS,GAAG,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,EAAE,SAAS,EAAE,OAAO,EAAE,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,EAAE,SAAS,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,EAAE,CAAA;IACxH,CAAC;IACD,OAAO,OAAO,CAAA;AAChB,CAAC"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { type GitRunner } from '@openagt/agent-data';
|
|
2
|
+
/**
|
|
3
|
+
* The one commit of a change to a project's skills (#2023): only the skill files it wrote or
|
|
4
|
+
* deleted, on the branch the person is on, and nothing else they have open. Never a push: the person pushes, or
|
|
5
|
+
* opens a pull request where the default branch is protected.
|
|
6
|
+
*/
|
|
7
|
+
export type CommitOutcome = {
|
|
8
|
+
ok: true;
|
|
9
|
+
committed: boolean;
|
|
10
|
+
commit?: string;
|
|
11
|
+
} | {
|
|
12
|
+
ok: false;
|
|
13
|
+
error: string;
|
|
14
|
+
};
|
|
15
|
+
/** Commit what stands at `paths` (from the project's root) under `message`: a file written, a file deleted. Nothing changed there is no commit. */
|
|
16
|
+
export declare function commitPaths(root: string, paths: readonly string[], message: string, git?: GitRunner): Promise<CommitOutcome>;
|
|
17
|
+
//# sourceMappingURL=commit.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"commit.d.ts","sourceRoot":"","sources":["../../src/project-skills/commit.ts"],"names":[],"mappings":"AAEA,OAAO,EAA4B,KAAK,SAAS,EAAE,MAAM,qBAAqB,CAAA;AAE9E;;;;GAIG;AAEH,MAAM,MAAM,aAAa,GAAG;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,SAAS,EAAE,OAAO,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAA;AAE5G,mJAAmJ;AACnJ,wBAAsB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,MAAM,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,GAAE,SAA2B,GAAG,OAAO,CAAC,aAAa,CAAC,CAqBnJ"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { lstat } from 'node:fs/promises';
|
|
2
|
+
import { join } from 'node:path';
|
|
3
|
+
import { gitReason, nodeGitRunner } from '@openagt/agent-data';
|
|
4
|
+
/** Commit what stands at `paths` (from the project's root) under `message`: a file written, a file deleted. Nothing changed there is no commit. */
|
|
5
|
+
export async function commitPaths(root, paths, message, git = nodeGitRunner()) {
|
|
6
|
+
try {
|
|
7
|
+
// A path that is neither on disk nor known to git is nothing to commit, and git refuses to be handed one.
|
|
8
|
+
const tracked = new Set((await git(['ls-files', '-z', '--', ...paths], root)).split('\0').filter(Boolean));
|
|
9
|
+
const real = [];
|
|
10
|
+
for (const path of new Set(paths)) {
|
|
11
|
+
if (tracked.has(path) || (await lstat(join(root, path)).then(() => true, () => false)))
|
|
12
|
+
real.push(path);
|
|
13
|
+
}
|
|
14
|
+
if (real.length === 0)
|
|
15
|
+
return { ok: true, committed: false };
|
|
16
|
+
// A path one of the project's ignore rules covers can never be committed: said before anything is staged.
|
|
17
|
+
const ignored = (await git(['check-ignore', '--', ...real], root).catch(() => '')).split('\n').filter(Boolean);
|
|
18
|
+
if (ignored.length > 0)
|
|
19
|
+
return { ok: false, error: `git ignores ${ignored[0]}${ignored.length > 1 ? ` and ${ignored.length - 1} more` : ''}: an ignore rule of this project, or of yours, covers it` };
|
|
20
|
+
await git(['add', '-A', '--', ...real], root);
|
|
21
|
+
const staged = (await git(['diff', '--cached', '--name-only', '-z', '--', ...real], root)).split('\0').filter(Boolean);
|
|
22
|
+
if (staged.length === 0)
|
|
23
|
+
return { ok: true, committed: false };
|
|
24
|
+
// With paths, git commits those paths alone and leaves whatever else is staged where it was.
|
|
25
|
+
await git(['commit', '-q', '-m', message, '--', ...staged], root);
|
|
26
|
+
return { ok: true, committed: true, commit: (await git(['rev-parse', '--short', 'HEAD'], root)).trim() };
|
|
27
|
+
}
|
|
28
|
+
catch (err) {
|
|
29
|
+
return { ok: false, error: reason(err) };
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
/** Why git refused, in its own last words: a failing hook and a missing identity say so on their last lines, after the command's echo. */
|
|
33
|
+
function reason(err) {
|
|
34
|
+
const said = gitReason(err);
|
|
35
|
+
if (!said.startsWith('Command failed:'))
|
|
36
|
+
return said;
|
|
37
|
+
const lines = (err instanceof Error ? err.message : String(err)).split('\n').map(line => line.trim()).filter(line => line && !line.startsWith('hint:'));
|
|
38
|
+
return lines.length > 1 ? lines.at(-1) : 'git refused the commit';
|
|
39
|
+
}
|
|
40
|
+
//# sourceMappingURL=commit.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"commit.js","sourceRoot":"","sources":["../../src/project-skills/commit.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { type GitRunner } from '@openagt/agent-data';
|
|
2
|
+
import { type CarriedSkill } from './catalogue.js';
|
|
3
|
+
/**
|
|
4
|
+
* What a project has, read off its files (#2023): a project has a skill when the skill's text is
|
|
5
|
+
* in it, where the coding agents read it. Nothing else is asked: no `package.json`, no list kept
|
|
6
|
+
* anywhere. A folder deleted by hand is a skill removed.
|
|
7
|
+
*/
|
|
8
|
+
/** Where a skill's text is written, and where it is linked for Claude Code. Codex reads the first. */
|
|
9
|
+
export declare const TEXTS_DIR = ".agents/skills";
|
|
10
|
+
export declare const LINKS_DIR = ".claude/skills";
|
|
11
|
+
/**
|
|
12
|
+
* How a skill stands in a project:
|
|
13
|
+
* - `absent`: the project does not hold it.
|
|
14
|
+
* - `current`: its text is the one the dashboard carries.
|
|
15
|
+
* - `newer`: the dashboard carries a newer text than the one the project was given.
|
|
16
|
+
* - `changed`: the project's text was changed by hand since it was written.
|
|
17
|
+
* - `own`: the project holds a text under this name that OpenAgent did not write (no stamp).
|
|
18
|
+
* - `ahead`: the project's text is from a newer OpenAgent than this one.
|
|
19
|
+
*/
|
|
20
|
+
export type Standing = 'absent' | 'current' | 'newer' | 'changed' | 'own' | 'ahead';
|
|
21
|
+
export interface SkillState {
|
|
22
|
+
name: string;
|
|
23
|
+
standing: Standing;
|
|
24
|
+
/** The file the project's text is in, from the project's root; absent when the project holds none. */
|
|
25
|
+
file?: string;
|
|
26
|
+
}
|
|
27
|
+
export interface ProjectState {
|
|
28
|
+
skills: SkillState[];
|
|
29
|
+
/** Whether the folder is a git repository. */
|
|
30
|
+
git: boolean;
|
|
31
|
+
/** Whether a dashboard knows the folder as a project: its `.openagent/` is there. */
|
|
32
|
+
activated: boolean;
|
|
33
|
+
/** Whether the project has a remote named `origin`. */
|
|
34
|
+
remote: boolean;
|
|
35
|
+
/** Whether that remote is on GitHub, the one git host there is a skill for. */
|
|
36
|
+
github: boolean;
|
|
37
|
+
}
|
|
38
|
+
/** How the project's text of one skill stands against the one the dashboard carries. */
|
|
39
|
+
export declare function standingOf(file: string, carried: CarriedSkill): Exclude<Standing, 'absent'>;
|
|
40
|
+
export declare function readProject(root: string, git?: GitRunner): Promise<ProjectState>;
|
|
41
|
+
/** The skills a project holds, by name. */
|
|
42
|
+
export declare function held(state: ProjectState): string[];
|
|
43
|
+
//# sourceMappingURL=project.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"project.d.ts","sourceRoot":"","sources":["../../src/project-skills/project.ts"],"names":[],"mappings":"AAEA,OAAO,EAAgC,KAAK,SAAS,EAAE,MAAM,qBAAqB,CAAA;AAElF,OAAO,EAA8B,KAAK,YAAY,EAAE,MAAM,gBAAgB,CAAA;AAG9E;;;;GAIG;AAEH,sGAAsG;AACtG,eAAO,MAAM,SAAS,mBAAmB,CAAA;AACzC,eAAO,MAAM,SAAS,mBAAmB,CAAA;AAEzC;;;;;;;;GAQG;AACH,MAAM,MAAM,QAAQ,GAAG,QAAQ,GAAG,SAAS,GAAG,OAAO,GAAG,SAAS,GAAG,KAAK,GAAG,OAAO,CAAA;AAEnF,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAA;IACZ,QAAQ,EAAE,QAAQ,CAAA;IAClB,sGAAsG;IACtG,IAAI,CAAC,EAAE,MAAM,CAAA;CACd;AAED,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,UAAU,EAAE,CAAA;IACpB,8CAA8C;IAC9C,GAAG,EAAE,OAAO,CAAA;IACZ,qFAAqF;IACrF,SAAS,EAAE,OAAO,CAAA;IAClB,uDAAuD;IACvD,MAAM,EAAE,OAAO,CAAA;IACf,+EAA+E;IAC/E,MAAM,EAAE,OAAO,CAAA;CAChB;AAWD,wFAAwF;AACxF,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAO3F;AAED,wBAAsB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,GAAE,SAA2B,GAAG,OAAO,CAAC,YAAY,CAAC,CAiBvG;AAED,2CAA2C;AAC3C,wBAAgB,IAAI,CAAC,KAAK,EAAE,YAAY,GAAG,MAAM,EAAE,CAElD"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { lstat, readFile, stat } from 'node:fs/promises';
|
|
2
|
+
import { join } from 'node:path';
|
|
3
|
+
import { nodeGitRunner, OPENAGENT_DIR } from '@openagt/agent-data';
|
|
4
|
+
import { homeUrlFromRemote } from '@openagt/skill-github';
|
|
5
|
+
import { carriedSkills, SKILL_NAMES } from './catalogue.js';
|
|
6
|
+
import { olderThan, unstamped } from './skill-file.js';
|
|
7
|
+
/**
|
|
8
|
+
* What a project has, read off its files (#2023): a project has a skill when the skill's text is
|
|
9
|
+
* in it, where the coding agents read it. Nothing else is asked: no `package.json`, no list kept
|
|
10
|
+
* anywhere. A folder deleted by hand is a skill removed.
|
|
11
|
+
*/
|
|
12
|
+
/** Where a skill's text is written, and where it is linked for Claude Code. Codex reads the first. */
|
|
13
|
+
export const TEXTS_DIR = '.agents/skills';
|
|
14
|
+
export const LINKS_DIR = '.claude/skills';
|
|
15
|
+
/** The file a project's text of `name` is in, from the project's root: the folder written first, else Claude Code's. */
|
|
16
|
+
async function textFile(root, name) {
|
|
17
|
+
for (const dir of [TEXTS_DIR, LINKS_DIR]) {
|
|
18
|
+
const file = `${dir}/${name}/SKILL.md`;
|
|
19
|
+
if (await stat(join(root, file)).then(s => s.isFile(), () => false))
|
|
20
|
+
return file;
|
|
21
|
+
}
|
|
22
|
+
return undefined;
|
|
23
|
+
}
|
|
24
|
+
/** How the project's text of one skill stands against the one the dashboard carries. */
|
|
25
|
+
export function standingOf(file, carried) {
|
|
26
|
+
// A checkout that turned the line ends into CRLF holds the same text.
|
|
27
|
+
const { version, text } = unstamped(file.replaceAll('\r\n', '\n'));
|
|
28
|
+
if (text === carried.text)
|
|
29
|
+
return 'current';
|
|
30
|
+
if (version === undefined)
|
|
31
|
+
return 'own';
|
|
32
|
+
if (olderThan(version, carried.version))
|
|
33
|
+
return 'newer';
|
|
34
|
+
return olderThan(carried.version, version) ? 'ahead' : 'changed';
|
|
35
|
+
}
|
|
36
|
+
export async function readProject(root, git = nodeGitRunner()) {
|
|
37
|
+
const carried = await carriedSkills();
|
|
38
|
+
const skills = [];
|
|
39
|
+
for (const name of SKILL_NAMES) {
|
|
40
|
+
const file = await textFile(root, name);
|
|
41
|
+
if (file === undefined)
|
|
42
|
+
skills.push({ name, standing: 'absent' });
|
|
43
|
+
else
|
|
44
|
+
skills.push({ name, standing: standingOf(await readFile(join(root, file), 'utf8'), carried.get(name)), file });
|
|
45
|
+
}
|
|
46
|
+
const inRepo = await git(['rev-parse', '--is-inside-work-tree'], root).then(out => out.trim() === 'true', () => false);
|
|
47
|
+
const remote = inRepo ? await git(['remote', 'get-url', 'origin'], root).then(out => out.trim(), () => '') : '';
|
|
48
|
+
return {
|
|
49
|
+
skills,
|
|
50
|
+
git: inRepo,
|
|
51
|
+
activated: await lstat(join(root, OPENAGENT_DIR)).then(entry => entry.isDirectory(), () => false),
|
|
52
|
+
remote: remote !== '',
|
|
53
|
+
github: homeUrlFromRemote(remote) !== undefined,
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
/** The skills a project holds, by name. */
|
|
57
|
+
export function held(state) {
|
|
58
|
+
return state.skills.filter(skill => skill.standing !== 'absent').map(skill => skill.name);
|
|
59
|
+
}
|
|
60
|
+
//# sourceMappingURL=project.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"project.js","sourceRoot":"","sources":["../../src/project-skills/project.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A skill's text as the dashboard writes it into a project: the package's `SKILL.md`, with the
|
|
3
|
+
* version it is from stamped into its front matter as `metadata.version`. The stamp is what lets a
|
|
4
|
+
* later dashboard tell three things apart when a project's text is not the one it carries:
|
|
5
|
+
* the project's is older (a newer text is there to take), the project's was changed by hand (it is
|
|
6
|
+
* never written over unasked), or the reader itself is the older one (it says nothing).
|
|
7
|
+
*/
|
|
8
|
+
/** `text` with `version` stamped at the end of its front matter. A text with no front matter is given one. */
|
|
9
|
+
export declare function stamped(text: string, version: string): string;
|
|
10
|
+
/** A written file read back: the version it was stamped with, when it has a stamp, and the text without it. */
|
|
11
|
+
export declare function unstamped(file: string): {
|
|
12
|
+
version?: string;
|
|
13
|
+
text: string;
|
|
14
|
+
};
|
|
15
|
+
/** Whether version `a` is older than `b`, by their numbers: `0.1.2` is older than `0.1.10`. Anything that is not three numbers compares as equal. */
|
|
16
|
+
export declare function olderThan(a: string, b: string): boolean;
|
|
17
|
+
//# sourceMappingURL=skill-file.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"skill-file.d.ts","sourceRoot":"","sources":["../../src/project-skills/skill-file.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH,8GAA8G;AAC9G,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAK7D;AAED,+GAA+G;AAC/G,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG;IAAE,OAAO,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAI1E;AAED,qJAAqJ;AACrJ,wBAAgB,SAAS,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,OAAO,CAUvD"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A skill's text as the dashboard writes it into a project: the package's `SKILL.md`, with the
|
|
3
|
+
* version it is from stamped into its front matter as `metadata.version`. The stamp is what lets a
|
|
4
|
+
* later dashboard tell three things apart when a project's text is not the one it carries:
|
|
5
|
+
* the project's is older (a newer text is there to take), the project's was changed by hand (it is
|
|
6
|
+
* never written over unasked), or the reader itself is the older one (it says nothing).
|
|
7
|
+
*/
|
|
8
|
+
const STAMP = /\nmetadata:\n version: ([0-9A-Za-z.+-]+)\n---\n/;
|
|
9
|
+
/** `text` with `version` stamped at the end of its front matter. A text with no front matter is given one. */
|
|
10
|
+
export function stamped(text, version) {
|
|
11
|
+
const stamp = `metadata:\n version: ${version}\n`;
|
|
12
|
+
const end = text.startsWith('---\n') ? text.indexOf('\n---\n', 3) : -1;
|
|
13
|
+
if (end === -1)
|
|
14
|
+
return `---\n${stamp}---\n${text}`;
|
|
15
|
+
return `${text.slice(0, end + 1)}${stamp}${text.slice(end + 1)}`;
|
|
16
|
+
}
|
|
17
|
+
/** A written file read back: the version it was stamped with, when it has a stamp, and the text without it. */
|
|
18
|
+
export function unstamped(file) {
|
|
19
|
+
const match = file.startsWith('---\n') ? STAMP.exec(file) : null;
|
|
20
|
+
if (!match || match.index > file.indexOf('\n---\n', 3))
|
|
21
|
+
return { text: file };
|
|
22
|
+
return { version: match[1], text: `${file.slice(0, match.index)}\n---\n${file.slice(match.index + match[0].length)}` };
|
|
23
|
+
}
|
|
24
|
+
/** Whether version `a` is older than `b`, by their numbers: `0.1.2` is older than `0.1.10`. Anything that is not three numbers compares as equal. */
|
|
25
|
+
export function olderThan(a, b) {
|
|
26
|
+
const parts = (v) => {
|
|
27
|
+
const match = /^(\d+)\.(\d+)\.(\d+)/.exec(v);
|
|
28
|
+
return match ? [Number(match[1]), Number(match[2]), Number(match[3])] : undefined;
|
|
29
|
+
};
|
|
30
|
+
const x = parts(a);
|
|
31
|
+
const y = parts(b);
|
|
32
|
+
if (!x || !y)
|
|
33
|
+
return false;
|
|
34
|
+
for (let i = 0; i < 3; i++)
|
|
35
|
+
if (x[i] !== y[i])
|
|
36
|
+
return x[i] < y[i];
|
|
37
|
+
return false;
|
|
38
|
+
}
|
|
39
|
+
//# sourceMappingURL=skill-file.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"skill-file.js","sourceRoot":"","sources":["../../src/project-skills/skill-file.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,MAAM,KAAK,GAAG,kDAAkD,CAAA;AAEhE,8GAA8G;AAC9G,MAAM,UAAU,OAAO,CAAC,IAAY,EAAE,OAAe;IACnD,MAAM,KAAK,GAAG,yBAAyB,OAAO,IAAI,CAAA;IAClD,MAAM,GAAG,GAAG,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA;IACtE,IAAI,GAAG,KAAK,CAAC,CAAC;QAAE,OAAO,QAAQ,KAAK,QAAQ,IAAI,EAAE,CAAA;IAClD,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,GAAG,CAAC,CAAC,GAAG,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,GAAG,CAAC,CAAC,EAAE,CAAA;AAClE,CAAC;AAED,+GAA+G;AAC/G,MAAM,UAAU,SAAS,CAAC,IAAY;IACpC,MAAM,KAAK,GAAG,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAA;IAChE,IAAI,CAAC,KAAK,IAAI,KAAK,CAAC,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,CAAC,CAAC;QAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,CAAA;IAC7E,OAAO,EAAE,OAAO,EAAE,KAAK,CAAC,CAAC,CAAE,EAAE,IAAI,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,KAAK,CAAC,UAAU,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,KAAK,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,EAAE,CAAA;AACzH,CAAC;AAED,qJAAqJ;AACrJ,MAAM,UAAU,SAAS,CAAC,CAAS,EAAE,CAAS;IAC5C,MAAM,KAAK,GAAG,CAAC,CAAS,EAAwB,EAAE;QAChD,MAAM,KAAK,GAAG,sBAAsB,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;QAC5C,OAAO,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAA;IACnF,CAAC,CAAA;IACD,MAAM,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,CAAA;IAClB,MAAM,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,CAAA;IAClB,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC;QAAE,OAAO,KAAK,CAAA;IAC1B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE;QAAE,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;YAAE,OAAO,CAAC,CAAC,CAAC,CAAE,GAAG,CAAC,CAAC,CAAC,CAAE,CAAA;IACnE,OAAO,KAAK,CAAA;AACd,CAAC"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/** A folder for a test: empty, or a git repository with one commit on `main` and an identity of its own. */
|
|
2
|
+
export declare function folder(git: boolean): Promise<string>;
|
|
3
|
+
/** Git in `root`: its stdout. */
|
|
4
|
+
export declare function run(root: string, ...args: string[]): Promise<string>;
|
|
5
|
+
export declare const gone: (root: string) => Promise<void>;
|
|
6
|
+
//# sourceMappingURL=test-project.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"test-project.d.ts","sourceRoot":"","sources":["../../src/project-skills/test-project.ts"],"names":[],"mappings":"AAaA,4GAA4G;AAC5G,wBAAsB,MAAM,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,CAY1D;AAED,iCAAiC;AACjC,wBAAsB,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CAE1E;AAED,eAAO,MAAM,IAAI,SAAU,MAAM,KAAG,OAAO,CAAC,IAAI,CAA+C,CAAA"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { execFile } from 'node:child_process';
|
|
2
|
+
import { mkdtemp, realpath, rm, writeFile } from 'node:fs/promises';
|
|
3
|
+
import { tmpdir } from 'node:os';
|
|
4
|
+
import { join } from 'node:path';
|
|
5
|
+
import { promisify } from 'node:util';
|
|
6
|
+
// A folder made a repository by a test has no identity of its own to commit under, and a
|
|
7
|
+
// machine may have none either (GitHub's runner): the tests bring one, as a person's machine does.
|
|
8
|
+
for (const who of ['AUTHOR', 'COMMITTER']) {
|
|
9
|
+
process.env[`GIT_${who}_NAME`] ??= 'tester';
|
|
10
|
+
process.env[`GIT_${who}_EMAIL`] ??= 'tester@example.com';
|
|
11
|
+
}
|
|
12
|
+
/** A folder for a test: empty, or a git repository with one commit on `main` and an identity of its own. */
|
|
13
|
+
export async function folder(git) {
|
|
14
|
+
const root = await realpath(await mkdtemp(join(tmpdir(), 'openagent-skills-')));
|
|
15
|
+
if (git) {
|
|
16
|
+
await run(root, 'init', '-q', '-b', 'main');
|
|
17
|
+
await run(root, 'config', 'user.email', 'tester@example.com');
|
|
18
|
+
await run(root, 'config', 'user.name', 'tester');
|
|
19
|
+
await run(root, 'config', 'commit.gpgsign', 'false');
|
|
20
|
+
await writeFile(join(root, 'README.md'), '# a project\n');
|
|
21
|
+
await run(root, 'add', '-A');
|
|
22
|
+
await run(root, 'commit', '-q', '-m', 'init');
|
|
23
|
+
}
|
|
24
|
+
return root;
|
|
25
|
+
}
|
|
26
|
+
/** Git in `root`: its stdout. */
|
|
27
|
+
export async function run(root, ...args) {
|
|
28
|
+
return (await promisify(execFile)('git', args, { cwd: root })).stdout;
|
|
29
|
+
}
|
|
30
|
+
export const gone = (root) => rm(root, { recursive: true, force: true });
|
|
31
|
+
//# sourceMappingURL=test-project.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"test-project.js","sourceRoot":"","sources":["../../src/project-skills/test-project.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAA;AAC7C,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAA;AACnE,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAA;AAChC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AAChC,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAA;AAErC,yFAAyF;AACzF,mGAAmG;AACnG,KAAK,MAAM,GAAG,IAAI,CAAC,QAAQ,EAAE,WAAW,CAAC,EAAE,CAAC;IAC1C,OAAO,CAAC,GAAG,CAAC,OAAO,GAAG,OAAO,CAAC,KAAK,QAAQ,CAAA;IAC3C,OAAO,CAAC,GAAG,CAAC,OAAO,GAAG,QAAQ,CAAC,KAAK,oBAAoB,CAAA;AAC1D,CAAC;AAED,4GAA4G;AAC5G,MAAM,CAAC,KAAK,UAAU,MAAM,CAAC,GAAY;IACvC,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,MAAM,OAAO,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,mBAAmB,CAAC,CAAC,CAAC,CAAA;IAC/E,IAAI,GAAG,EAAE,CAAC;QACR,MAAM,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,CAAC,CAAA;QAC3C,MAAM,GAAG,CAAC,IAAI,EAAE,QAAQ,EAAE,YAAY,EAAE,oBAAoB,CAAC,CAAA;QAC7D,MAAM,GAAG,CAAC,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,QAAQ,CAAC,CAAA;QAChD,MAAM,GAAG,CAAC,IAAI,EAAE,QAAQ,EAAE,gBAAgB,EAAE,OAAO,CAAC,CAAA;QACpD,MAAM,SAAS,CAAC,IAAI,CAAC,IAAI,EAAE,WAAW,CAAC,EAAE,eAAe,CAAC,CAAA;QACzD,MAAM,GAAG,CAAC,IAAI,EAAE,KAAK,EAAE,IAAI,CAAC,CAAA;QAC5B,MAAM,GAAG,CAAC,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,CAAC,CAAA;IAC/C,CAAC;IACD,OAAO,IAAI,CAAA;AACb,CAAC;AAED,iCAAiC;AACjC,MAAM,CAAC,KAAK,UAAU,GAAG,CAAC,IAAY,EAAE,GAAG,IAAc;IACvD,OAAO,CAAC,MAAM,SAAS,CAAC,QAAQ,CAAC,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE,GAAG,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,MAAM,CAAA;AACvE,CAAC;AAED,MAAM,CAAC,MAAM,IAAI,GAAG,CAAC,IAAY,EAAiB,EAAE,CAAC,EAAE,CAAC,IAAI,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAA"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@openagt/dashboard",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.34.0",
|
|
4
4
|
"description": "OpenAgent: a local dashboard and daemon for coding agents. It starts an agent through the project's own start hook and shows every agent from the files it keeps; it runs no coding agent itself.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"ai",
|
|
@@ -64,23 +64,40 @@
|
|
|
64
64
|
"uqr": "0.1.3",
|
|
65
65
|
"yaml": "^2.5.0",
|
|
66
66
|
"@openagt/agent-driver-claude": "0.0.8",
|
|
67
|
-
"@openagt/agent-data": "0.0.9",
|
|
68
|
-
"@openagt/files": "0.0.8",
|
|
69
67
|
"@openagt/agent-driver-codex": "0.0.7",
|
|
70
68
|
"@openagt/remote-access": "0.0.9",
|
|
71
|
-
"@openagt/changes": "0.0.3",
|
|
72
69
|
"@openagt/servers": "0.0.11",
|
|
73
|
-
"@openagt/
|
|
70
|
+
"@openagt/skill-branches": "0.1.5",
|
|
71
|
+
"@openagt/agent-data": "0.0.9",
|
|
74
72
|
"@openagt/skill-browser": "0.1.2",
|
|
75
|
-
"@openagt/skill-branches": "0.1.4",
|
|
76
73
|
"@openagt/skill-github": "0.1.6",
|
|
77
|
-
"@openagt/
|
|
78
|
-
"@openagt/skill-orchestration": "0.1.12",
|
|
74
|
+
"@openagt/files": "0.0.8",
|
|
79
75
|
"@openagt/skill-queue": "0.1.3",
|
|
80
|
-
"@openagt/
|
|
76
|
+
"@openagt/skill-orchestration": "0.1.13",
|
|
77
|
+
"@openagt/changes": "0.0.3",
|
|
81
78
|
"@openagt/skill-tickets": "0.1.5",
|
|
82
|
-
"@openagt/skill-
|
|
83
|
-
"@openagt/
|
|
79
|
+
"@openagt/skill-discord": "0.1.1",
|
|
80
|
+
"@openagt/skill-scheduler": "0.1.15",
|
|
81
|
+
"@openagt/skill-plan": "0.1.0",
|
|
82
|
+
"@openagt/skill-logs": "0.1.5",
|
|
83
|
+
"@openagt/skill-market-research": "0.1.0",
|
|
84
|
+
"@openagt/skill-plan-tickets": "0.1.0",
|
|
85
|
+
"@openagt/skill-post-merge-cleanup": "0.1.0",
|
|
86
|
+
"@openagt/skill-maintenance": "0.1.0",
|
|
87
|
+
"@openagt/skill-maintainability": "0.1.0",
|
|
88
|
+
"@openagt/skill-reply": "0.1.2",
|
|
89
|
+
"@openagt/skill-security-audit": "0.1.0",
|
|
90
|
+
"@openagt/skill-readability": "0.1.0",
|
|
91
|
+
"@openagt/skill-research": "0.1.0",
|
|
92
|
+
"@openagt/skill-suggest-new-tickets": "0.1.0",
|
|
93
|
+
"@openagt/skill-triage": "0.1.0",
|
|
94
|
+
"@openagt/skill-ux": "0.1.0",
|
|
95
|
+
"@openagt/skill-suggest-tickets-to-work-on": "0.1.0",
|
|
96
|
+
"@openagt/skill-update-tickets": "0.1.1",
|
|
97
|
+
"@openagt/skill-suggest-new-features": "0.1.0",
|
|
98
|
+
"@openagt/skill-work-queue": "0.1.0",
|
|
99
|
+
"@openagt/agent-runner": "0.0.19",
|
|
100
|
+
"@openagt/agent-driver": "0.0.7"
|
|
84
101
|
},
|
|
85
102
|
"devDependencies": {
|
|
86
103
|
"@tailwindcss/vite": "^4.0.0",
|