@ethlete/agent-rules 0.1.0-next.0 → 0.1.0-next.10
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/CHANGELOG.md +102 -0
- package/README.md +363 -16
- package/content/git-hooks/post-checkout.sh +10 -0
- package/content/git-hooks/pre-push.sh +5 -0
- package/content/hooks/context-warning.py +430 -0
- package/content/output-styles/ste-clarity.md +131 -0
- package/content/rules/comments.md +50 -20
- package/content/skills/angular-patterns/SKILL.md +1 -1
- package/content/skills/api-source/SKILL.md +118 -0
- package/content/skills/figma-export/SKILL.md +193 -0
- package/content/skills/figma-export/dump-figma-layers.py +83 -0
- package/content/skills/figma-export/dump-figma-svg.py +235 -0
- package/content/skills/figma-export/measure-template.mjs +87 -0
- package/content/skills/git-commit/SKILL.md +6 -7
- package/content/skills/git-flow/SKILL.md +87 -0
- package/content/skills/handoff/SKILL.md +4 -0
- package/content/skills/query/SKILL.md +23 -13
- package/content/skills/rxjs-signals/SKILL.md +1 -1
- package/content/skills/sdk-docs/SKILL.md +10 -2
- package/content/skills/sdk-local-build/SKILL.md +115 -0
- package/content/skills/sdk-source/SKILL.md +133 -0
- package/content/skills/styleguide/STYLEGUIDE.md +2 -2
- package/content/skills/theming/SKILL.md +1 -1
- package/content/skills/timetrack/SKILL.md +66 -0
- package/package.json +12 -1
- package/src/index.js +35 -14
- package/src/index.js.map +1 -1
- package/src/lib/commitlint.d.ts +10 -0
- package/src/lib/commitlint.js +51 -0
- package/src/lib/commitlint.js.map +1 -0
- package/src/lib/config.d.ts +64 -2
- package/src/lib/config.js +54 -9
- package/src/lib/config.js.map +1 -1
- package/src/lib/git-flow/build.d.ts +35 -0
- package/src/lib/git-flow/build.js +24 -0
- package/src/lib/git-flow/build.js.map +1 -0
- package/src/lib/git-flow/config.d.ts +59 -0
- package/src/lib/git-flow/config.js +50 -0
- package/src/lib/git-flow/config.js.map +1 -0
- package/src/lib/git-flow/index.d.ts +6 -0
- package/src/lib/git-flow/index.js +10 -0
- package/src/lib/git-flow/index.js.map +1 -0
- package/src/lib/git-flow/parse.d.ts +49 -0
- package/src/lib/git-flow/parse.js +274 -0
- package/src/lib/git-flow/parse.js.map +1 -0
- package/src/lib/git-flow/rename.d.ts +24 -0
- package/src/lib/git-flow/rename.js +70 -0
- package/src/lib/git-flow/rename.js.map +1 -0
- package/src/lib/git-flow/start.d.ts +49 -0
- package/src/lib/git-flow/start.js +57 -0
- package/src/lib/git-flow/start.js.map +1 -0
- package/src/lib/git-flow/validate.d.ts +34 -0
- package/src/lib/git-flow/validate.js +72 -0
- package/src/lib/git-flow/validate.js.map +1 -0
- package/src/lib/git-flow-command.d.ts +4 -0
- package/src/lib/git-flow-command.js +157 -0
- package/src/lib/git-flow-command.js.map +1 -0
- package/src/lib/git-flow-repair.d.ts +17 -0
- package/src/lib/git-flow-repair.js +146 -0
- package/src/lib/git-flow-repair.js.map +1 -0
- package/src/lib/git-flow-start.d.ts +20 -0
- package/src/lib/git-flow-start.js +132 -0
- package/src/lib/git-flow-start.js.map +1 -0
- package/src/lib/git.d.ts +27 -0
- package/src/lib/git.js +49 -0
- package/src/lib/git.js.map +1 -0
- package/src/lib/gitlab.d.ts +35 -0
- package/src/lib/gitlab.js +98 -0
- package/src/lib/gitlab.js.map +1 -0
- package/src/lib/index.d.ts +2 -0
- package/src/lib/index.js +2 -0
- package/src/lib/index.js.map +1 -1
- package/src/lib/migrate.d.ts +6 -0
- package/src/lib/migrate.js +155 -0
- package/src/lib/migrate.js.map +1 -0
- package/src/lib/output-style-command.d.ts +3 -0
- package/src/lib/output-style-command.js +69 -0
- package/src/lib/output-style-command.js.map +1 -0
- package/src/lib/output-style.d.ts +38 -0
- package/src/lib/output-style.js +126 -0
- package/src/lib/output-style.js.map +1 -0
- package/src/lib/owned-paths.js +22 -1
- package/src/lib/owned-paths.js.map +1 -1
- package/src/lib/plan.d.ts +4 -1
- package/src/lib/plan.js +141 -8
- package/src/lib/plan.js.map +1 -1
- package/src/lib/prompt.d.ts +8 -0
- package/src/lib/prompt.js +27 -0
- package/src/lib/prompt.js.map +1 -0
- package/src/lib/render.d.ts +20 -2
- package/src/lib/render.js +31 -8
- package/src/lib/render.js.map +1 -1
- package/src/lib/sync.d.ts +0 -1
- package/src/lib/sync.js +8 -2
- package/src/lib/sync.js.map +1 -1
- package/src/lib/targets/agents-skills.d.ts +8 -0
- package/src/lib/targets/agents-skills.js +18 -0
- package/src/lib/targets/agents-skills.js.map +1 -0
- package/src/lib/targets/claude-hooks.d.ts +11 -0
- package/src/lib/targets/claude-hooks.js +28 -0
- package/src/lib/targets/claude-hooks.js.map +1 -0
- package/src/lib/targets/claude.d.ts +3 -1
- package/src/lib/targets/claude.js +14 -21
- package/src/lib/targets/claude.js.map +1 -1
- package/src/lib/targets/codex-hooks.d.ts +12 -0
- package/src/lib/targets/codex-hooks.js +33 -0
- package/src/lib/targets/codex-hooks.js.map +1 -0
- package/src/lib/targets/codex.d.ts +5 -3
- package/src/lib/targets/codex.js +9 -8
- package/src/lib/targets/codex.js.map +1 -1
- package/src/lib/targets/copilot.d.ts +3 -3
- package/src/lib/targets/copilot.js +6 -29
- package/src/lib/targets/copilot.js.map +1 -1
- package/src/lib/targets/cursor.d.ts +3 -3
- package/src/lib/targets/cursor.js +7 -12
- package/src/lib/targets/cursor.js.map +1 -1
- package/src/lib/targets/git-hooks.d.ts +24 -0
- package/src/lib/targets/git-hooks.js +70 -0
- package/src/lib/targets/git-hooks.js.map +1 -0
- package/src/lib/targets/hooks-shared.d.ts +37 -0
- package/src/lib/targets/hooks-shared.js +95 -0
- package/src/lib/targets/hooks-shared.js.map +1 -0
- package/src/lib/targets/shared.d.ts +22 -13
- package/src/lib/targets/shared.js +32 -15
- package/src/lib/targets/shared.js.map +1 -1
- package/src/lib/timetrack-command.d.ts +11 -0
- package/src/lib/timetrack-command.js +199 -0
- package/src/lib/timetrack-command.js.map +1 -0
- package/src/lib/timetrack.d.ts +86 -0
- package/src/lib/timetrack.js +112 -0
- package/src/lib/timetrack.js.map +1 -0
- package/src/lib/targets/neutral.d.ts +0 -8
- package/src/lib/targets/neutral.js +0 -29
- package/src/lib/targets/neutral.js.map +0 -1
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.emitHookSettings = exports.emitHookScripts = exports.mergeHookSettings = exports.assertKnownHooks = exports.KNOWN_HOOKS = void 0;
|
|
4
|
+
const fs_1 = require("fs");
|
|
5
|
+
const path_1 = require("path");
|
|
6
|
+
const load_content_1 = require("../load-content");
|
|
7
|
+
const render_1 = require("../render");
|
|
8
|
+
/**
|
|
9
|
+
* Hooks a repo can opt into via the config's `hooks` array. Hooks run arbitrary commands on the
|
|
10
|
+
* developer's machine, so unlike rules and skills they are never emitted by default.
|
|
11
|
+
*/
|
|
12
|
+
exports.KNOWN_HOOKS = {
|
|
13
|
+
'context-warning': { event: 'UserPromptSubmit', file: 'context-warning.py', timeout: 10 },
|
|
14
|
+
};
|
|
15
|
+
const assertKnownHooks = (hooks) => {
|
|
16
|
+
const unknown = hooks.filter((name) => !(name in exports.KNOWN_HOOKS));
|
|
17
|
+
if (unknown.length > 0) {
|
|
18
|
+
throw new Error(`Unknown hook(s): ${unknown.join(', ')}. Known hooks: ${Object.keys(exports.KNOWN_HOOKS).join(', ')}.`);
|
|
19
|
+
}
|
|
20
|
+
};
|
|
21
|
+
exports.assertKnownHooks = assertKnownHooks;
|
|
22
|
+
/** Placed after the shebang so the file stays runnable. */
|
|
23
|
+
const withBanner = (raw) => {
|
|
24
|
+
var _a;
|
|
25
|
+
const lines = raw.split('\n');
|
|
26
|
+
if ((_a = lines[0]) === null || _a === void 0 ? void 0 : _a.startsWith('#!'))
|
|
27
|
+
return [lines[0], render_1.SHELL_BANNER, ...lines.slice(1)].join('\n');
|
|
28
|
+
return `${render_1.SHELL_BANNER}\n${raw}`;
|
|
29
|
+
};
|
|
30
|
+
/**
|
|
31
|
+
* Rewrites the generated entries declaratively: every entry whose command points into the
|
|
32
|
+
* agent's `hooks/ethlete/` directory is dropped and the currently enabled hooks are re-added, so
|
|
33
|
+
* disabling a hook in the config also unregisters it. Everything else in the file is untouched.
|
|
34
|
+
*/
|
|
35
|
+
const mergeHookSettings = (options) => {
|
|
36
|
+
var _a, _b;
|
|
37
|
+
const { existing, hooks, hooksDir, commandFor } = options;
|
|
38
|
+
const settings = JSON.parse(existing.trim() || '{}');
|
|
39
|
+
const events = Object.assign({}, ((_a = settings.hooks) !== null && _a !== void 0 ? _a : {}));
|
|
40
|
+
for (const [event, groups] of Object.entries(events)) {
|
|
41
|
+
const kept = groups
|
|
42
|
+
.map((group) => {
|
|
43
|
+
var _a;
|
|
44
|
+
return (Object.assign(Object.assign({}, group), { hooks: ((_a = group.hooks) !== null && _a !== void 0 ? _a : []).filter((hook) => { var _a; return !((_a = hook.command) !== null && _a !== void 0 ? _a : '').includes(hooksDir); }) }));
|
|
45
|
+
})
|
|
46
|
+
.filter((group) => group.hooks.length > 0);
|
|
47
|
+
if (kept.length > 0)
|
|
48
|
+
events[event] = kept;
|
|
49
|
+
else
|
|
50
|
+
delete events[event];
|
|
51
|
+
}
|
|
52
|
+
for (const name of hooks) {
|
|
53
|
+
const definition = exports.KNOWN_HOOKS[name];
|
|
54
|
+
if (!definition)
|
|
55
|
+
continue;
|
|
56
|
+
events[definition.event] = [
|
|
57
|
+
...((_b = events[definition.event]) !== null && _b !== void 0 ? _b : []),
|
|
58
|
+
{ hooks: [{ type: 'command', command: commandFor(definition.file), timeout: definition.timeout }] },
|
|
59
|
+
];
|
|
60
|
+
}
|
|
61
|
+
if (Object.keys(events).length > 0)
|
|
62
|
+
settings.hooks = events;
|
|
63
|
+
else
|
|
64
|
+
delete settings.hooks;
|
|
65
|
+
return `${JSON.stringify(settings, null, 2)}\n`;
|
|
66
|
+
};
|
|
67
|
+
exports.mergeHookSettings = mergeHookSettings;
|
|
68
|
+
const emitHookScripts = (options) => {
|
|
69
|
+
const { hooks, hooksDir } = options;
|
|
70
|
+
return hooks.flatMap((name) => {
|
|
71
|
+
const definition = exports.KNOWN_HOOKS[name];
|
|
72
|
+
if (!definition)
|
|
73
|
+
return [];
|
|
74
|
+
const raw = (0, fs_1.readFileSync)((0, path_1.join)((0, load_content_1.resolveContentRoot)(), 'hooks', definition.file), 'utf8');
|
|
75
|
+
return [{ path: `${hooksDir}/${definition.file}`, contents: withBanner(raw) }];
|
|
76
|
+
});
|
|
77
|
+
};
|
|
78
|
+
exports.emitHookScripts = emitHookScripts;
|
|
79
|
+
/** Only planned when the parsed content actually changes; an unparseable file is left alone. */
|
|
80
|
+
const emitHookSettings = (options) => {
|
|
81
|
+
const { path, existing, hooks, hooksDir, commandFor, createWhenEmpty } = options;
|
|
82
|
+
if (existing.trim().length === 0 && hooks.length === 0 && !createWhenEmpty)
|
|
83
|
+
return [];
|
|
84
|
+
try {
|
|
85
|
+
const merged = (0, exports.mergeHookSettings)({ existing, hooks, hooksDir, commandFor });
|
|
86
|
+
if (JSON.stringify(JSON.parse(existing.trim() || '{}')) === JSON.stringify(JSON.parse(merged)))
|
|
87
|
+
return [];
|
|
88
|
+
return [{ path, contents: merged }];
|
|
89
|
+
}
|
|
90
|
+
catch (_a) {
|
|
91
|
+
return [];
|
|
92
|
+
}
|
|
93
|
+
};
|
|
94
|
+
exports.emitHookSettings = emitHookSettings;
|
|
95
|
+
//# sourceMappingURL=hooks-shared.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hooks-shared.js","sourceRoot":"","sources":["../../../../../../libs/agent-rules/src/lib/targets/hooks-shared.ts"],"names":[],"mappings":";;;AAAA,2BAAkC;AAClC,+BAA4B;AAC5B,kDAAqD;AACrD,sCAAyC;AAKzC;;;GAGG;AACU,QAAA,WAAW,GAAmC;IACzD,iBAAiB,EAAE,EAAE,KAAK,EAAE,kBAAkB,EAAE,IAAI,EAAE,oBAAoB,EAAE,OAAO,EAAE,EAAE,EAAE;CAC1F,CAAC;AAEK,MAAM,gBAAgB,GAAG,CAAC,KAAe,EAAE,EAAE;IAClD,MAAM,OAAO,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,IAAI,mBAAW,CAAC,CAAC,CAAC;IAE/D,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACvB,MAAM,IAAI,KAAK,CAAC,oBAAoB,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,kBAAkB,MAAM,CAAC,IAAI,CAAC,mBAAW,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAClH,CAAC;AACH,CAAC,CAAC;AANW,QAAA,gBAAgB,oBAM3B;AAEF,2DAA2D;AAC3D,MAAM,UAAU,GAAG,CAAC,GAAW,EAAE,EAAE;;IACjC,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAE9B,IAAI,MAAA,KAAK,CAAC,CAAC,CAAC,0CAAE,UAAU,CAAC,IAAI,CAAC;QAAE,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,qBAAY,EAAE,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAE9F,OAAO,GAAG,qBAAY,KAAK,GAAG,EAAE,CAAC;AACnC,CAAC,CAAC;AAMF;;;;GAIG;AACI,MAAM,iBAAiB,GAAG,CAAC,OAKjC,EAAE,EAAE;;IACH,MAAM,EAAE,QAAQ,EAAE,KAAK,EAAE,QAAQ,EAAE,UAAU,EAAE,GAAG,OAAO,CAAC;IAC1D,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,EAAE,IAAI,IAAI,CAAiB,CAAC;IACrE,MAAM,MAAM,qBAAQ,CAAC,MAAA,QAAQ,CAAC,KAAK,mCAAI,EAAE,CAAC,CAAE,CAAC;IAE7C,KAAK,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;QACrD,MAAM,IAAI,GAAG,MAAM;aAChB,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE;;YAAC,OAAA,iCACX,KAAK,KACR,KAAK,EAAE,CAAC,MAAA,KAAK,CAAC,KAAK,mCAAI,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,WAAC,OAAA,CAAC,CAAC,MAAA,IAAI,CAAC,OAAO,mCAAI,EAAE,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAA,EAAA,CAAC,IACrF,CAAA;SAAA,CAAC;aACF,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;QAE7C,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC;YAAE,MAAM,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC;;YACrC,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC;IAC5B,CAAC;IAED,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,UAAU,GAAG,mBAAW,CAAC,IAAI,CAAC,CAAC;QAErC,IAAI,CAAC,UAAU;YAAE,SAAS;QAE1B,MAAM,CAAC,UAAU,CAAC,KAAK,CAAC,GAAG;YACzB,GAAG,CAAC,MAAA,MAAM,CAAC,UAAU,CAAC,KAAK,CAAC,mCAAI,EAAE,CAAC;YACnC,EAAE,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,UAAU,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,UAAU,CAAC,OAAO,EAAE,CAAC,EAAE;SACpG,CAAC;IACJ,CAAC;IAED,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,MAAM,GAAG,CAAC;QAAE,QAAQ,CAAC,KAAK,GAAG,MAAM,CAAC;;QACvD,OAAO,QAAQ,CAAC,KAAK,CAAC;IAE3B,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC;AAClD,CAAC,CAAC;AArCW,QAAA,iBAAiB,qBAqC5B;AAEK,MAAM,eAAe,GAAG,CAAC,OAA8C,EAAiB,EAAE;IAC/F,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,GAAG,OAAO,CAAC;IAEpC,OAAO,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE;QAC5B,MAAM,UAAU,GAAG,mBAAW,CAAC,IAAI,CAAC,CAAC;QAErC,IAAI,CAAC,UAAU;YAAE,OAAO,EAAE,CAAC;QAE3B,MAAM,GAAG,GAAG,IAAA,iBAAY,EAAC,IAAA,WAAI,EAAC,IAAA,iCAAkB,GAAE,EAAE,OAAO,EAAE,UAAU,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC,CAAC;QAEvF,OAAO,CAAC,EAAE,IAAI,EAAE,GAAG,QAAQ,IAAI,UAAU,CAAC,IAAI,EAAE,EAAE,QAAQ,EAAE,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IACjF,CAAC,CAAC,CAAC;AACL,CAAC,CAAC;AAZW,QAAA,eAAe,mBAY1B;AAEF,gGAAgG;AACzF,MAAM,gBAAgB,GAAG,CAAC,OAOhC,EAAiB,EAAE;IAClB,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,QAAQ,EAAE,UAAU,EAAE,eAAe,EAAE,GAAG,OAAO,CAAC;IAEjF,IAAI,QAAQ,CAAC,IAAI,EAAE,CAAC,MAAM,KAAK,CAAC,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,IAAI,CAAC,eAAe;QAAE,OAAO,EAAE,CAAC;IAEtF,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,IAAA,yBAAiB,EAAC,EAAE,QAAQ,EAAE,KAAK,EAAE,QAAQ,EAAE,UAAU,EAAE,CAAC,CAAC;QAE5E,IAAI,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,EAAE,IAAI,IAAI,CAAC,CAAC,KAAK,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;YAAE,OAAO,EAAE,CAAC;QAE1G,OAAO,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC,CAAC;IACtC,CAAC;IAAC,WAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC,CAAC;AArBW,QAAA,gBAAgB,oBAqB3B"}
|
|
@@ -11,14 +11,17 @@ export type EmitContext = {
|
|
|
11
11
|
/** Names of the skills that actually survived filtering, so links can't point at a missing file. */
|
|
12
12
|
emittedSkills: Set<string>;
|
|
13
13
|
vars: Record<string, string | string[]>;
|
|
14
|
-
|
|
14
|
+
/**
|
|
15
|
+
* The repo's `CLAUDE.md` is an `@AGENTS.md` import (or symlink), so Claude already receives the
|
|
16
|
+
* rules through the `AGENTS.md` marker block and must not get a second copy in `.claude/rules/`.
|
|
17
|
+
*/
|
|
18
|
+
claudeMdImportsAgentsMd: boolean;
|
|
19
|
+
/** Opt-in Claude Code hooks from the config. */
|
|
20
|
+
hooks: string[];
|
|
15
21
|
};
|
|
16
|
-
export declare const
|
|
17
|
-
export declare const
|
|
18
|
-
export declare const
|
|
19
|
-
skillName: string;
|
|
20
|
-
fileName: string;
|
|
21
|
-
}) => string;
|
|
22
|
+
export declare const AGENTS_SKILLS_DIR = ".agents/skills";
|
|
23
|
+
export declare const agentsSkillDir: (name: string) => string;
|
|
24
|
+
export declare const agentsSkillPath: (name: string) => string;
|
|
22
25
|
/**
|
|
23
26
|
* A guide can be filtered out of a given repo while another still references it. Degrade such a
|
|
24
27
|
* link to the bare name rather than emitting a path to a file that was never written.
|
|
@@ -31,7 +34,7 @@ export declare const makeLinks: (options: {
|
|
|
31
34
|
fileName: string;
|
|
32
35
|
}) => string;
|
|
33
36
|
}) => LinkResolver;
|
|
34
|
-
export declare const
|
|
37
|
+
export declare const agentsSkillsLinks: (context: EmitContext) => LinkResolver;
|
|
35
38
|
export declare const body: (options: {
|
|
36
39
|
item: ContentItem;
|
|
37
40
|
context: EmitContext;
|
|
@@ -49,12 +52,18 @@ export declare const resourceFiles: (options: {
|
|
|
49
52
|
path: string;
|
|
50
53
|
contents: string;
|
|
51
54
|
}[];
|
|
55
|
+
/**
|
|
56
|
+
* One skill in the agentskills.io layout: a `SKILL.md` with `name`/`description` frontmatter plus
|
|
57
|
+
* its resource files as siblings. The same bundle serves `.claude/skills/` and `.agents/skills/`;
|
|
58
|
+
* only the directory and the link resolver differ per target.
|
|
59
|
+
*/
|
|
60
|
+
export declare const skillBundle: (options: {
|
|
61
|
+
item: ContentItem;
|
|
62
|
+
context: EmitContext;
|
|
63
|
+
dir: string;
|
|
64
|
+
links: LinkResolver;
|
|
65
|
+
}) => EmittedFile[];
|
|
52
66
|
/** Descriptions routinely contain `:` and `-`, so always quote them rather than guess. */
|
|
53
67
|
export declare const yamlString: (value: string) => string;
|
|
54
68
|
/** Every generated document ends with exactly one trailing newline so Prettier stays quiet. */
|
|
55
69
|
export declare const document: (parts: string[]) => string;
|
|
56
|
-
export declare const pointerTable: (options: {
|
|
57
|
-
skills: ContentItem[];
|
|
58
|
-
context: EmitContext;
|
|
59
|
-
pathFor: (name: string) => string;
|
|
60
|
-
}) => string;
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.document = exports.yamlString = exports.skillBundle = exports.resourceFiles = exports.description = exports.body = exports.agentsSkillsLinks = exports.makeLinks = exports.agentsSkillPath = exports.agentsSkillDir = exports.AGENTS_SKILLS_DIR = void 0;
|
|
4
4
|
const fs_1 = require("fs");
|
|
5
5
|
const render_1 = require("../render");
|
|
6
|
-
exports.
|
|
7
|
-
const
|
|
8
|
-
exports.
|
|
9
|
-
const
|
|
10
|
-
exports.
|
|
6
|
+
exports.AGENTS_SKILLS_DIR = '.agents/skills';
|
|
7
|
+
const agentsSkillDir = (name) => `${exports.AGENTS_SKILLS_DIR}/ethlete-${name}`;
|
|
8
|
+
exports.agentsSkillDir = agentsSkillDir;
|
|
9
|
+
const agentsSkillPath = (name) => `${(0, exports.agentsSkillDir)(name)}/SKILL.md`;
|
|
10
|
+
exports.agentsSkillPath = agentsSkillPath;
|
|
11
11
|
/**
|
|
12
12
|
* A guide can be filtered out of a given repo while another still references it. Degrade such a
|
|
13
13
|
* link to the bare name rather than emitting a path to a file that was never written.
|
|
@@ -17,12 +17,12 @@ const makeLinks = (options) => ({
|
|
|
17
17
|
resource: options.resource,
|
|
18
18
|
});
|
|
19
19
|
exports.makeLinks = makeLinks;
|
|
20
|
-
const
|
|
20
|
+
const agentsSkillsLinks = (context) => (0, exports.makeLinks)({
|
|
21
21
|
context,
|
|
22
|
-
skill: (name) => `\`${(0, exports.
|
|
23
|
-
resource: (target) => `\`${(0, exports.
|
|
22
|
+
skill: (name) => `\`${(0, exports.agentsSkillPath)(name)}\``,
|
|
23
|
+
resource: (target) => `\`${(0, exports.agentsSkillDir)(target.skillName)}/${target.fileName}\``,
|
|
24
24
|
});
|
|
25
|
-
exports.
|
|
25
|
+
exports.agentsSkillsLinks = agentsSkillsLinks;
|
|
26
26
|
const body = (options) => (0, render_1.renderBody)({ item: options.item, vars: options.context.vars, links: options.links });
|
|
27
27
|
exports.body = body;
|
|
28
28
|
const description = (options) => (0, render_1.renderDescription)({ item: options.item, vars: options.context.vars });
|
|
@@ -36,15 +36,32 @@ const resourceFiles = (options) => options.item.resources.map((resource) => ({
|
|
|
36
36
|
}),
|
|
37
37
|
}));
|
|
38
38
|
exports.resourceFiles = resourceFiles;
|
|
39
|
+
/**
|
|
40
|
+
* One skill in the agentskills.io layout: a `SKILL.md` with `name`/`description` frontmatter plus
|
|
41
|
+
* its resource files as siblings. The same bundle serves `.claude/skills/` and `.agents/skills/`;
|
|
42
|
+
* only the directory and the link resolver differ per target.
|
|
43
|
+
*/
|
|
44
|
+
const skillBundle = (options) => {
|
|
45
|
+
const { item, context, dir, links } = options;
|
|
46
|
+
const frontmatter = [
|
|
47
|
+
'---',
|
|
48
|
+
`name: ethlete-${item.frontmatter.name}`,
|
|
49
|
+
`description: ${(0, exports.yamlString)((0, exports.description)({ item, context }))}`,
|
|
50
|
+
'---',
|
|
51
|
+
].join('\n');
|
|
52
|
+
return [
|
|
53
|
+
{
|
|
54
|
+
path: `${dir}/SKILL.md`,
|
|
55
|
+
contents: (0, exports.document)([frontmatter, render_1.BANNER, (0, exports.body)({ item, context, links })]),
|
|
56
|
+
},
|
|
57
|
+
...(0, exports.resourceFiles)({ item, context, pathFor: (fileName) => `${dir}/${fileName}` }),
|
|
58
|
+
];
|
|
59
|
+
};
|
|
60
|
+
exports.skillBundle = skillBundle;
|
|
39
61
|
/** Descriptions routinely contain `:` and `-`, so always quote them rather than guess. */
|
|
40
62
|
const yamlString = (value) => `"${value.replace(/\\/g, '\\\\').replace(/"/g, '\\"')}"`;
|
|
41
63
|
exports.yamlString = yamlString;
|
|
42
64
|
/** Every generated document ends with exactly one trailing newline so Prettier stays quiet. */
|
|
43
65
|
const document = (parts) => `${parts.filter((part) => part.length > 0).join('\n\n')}\n`;
|
|
44
66
|
exports.document = document;
|
|
45
|
-
const pointerTable = (options) => {
|
|
46
|
-
const rows = options.skills.map((item) => `| \`${options.pathFor(item.frontmatter.name)}\` | ${(0, exports.description)({ item, context: options.context })} |`);
|
|
47
|
-
return ['| Read this file | When |', '| --- | --- |', ...rows].join('\n');
|
|
48
|
-
};
|
|
49
|
-
exports.pointerTable = pointerTable;
|
|
50
67
|
//# sourceMappingURL=shared.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"shared.js","sourceRoot":"","sources":["../../../../../../libs/agent-rules/src/lib/targets/shared.ts"],"names":[],"mappings":";;;AAAA,2BAAkC;AAElC,
|
|
1
|
+
{"version":3,"file":"shared.js","sourceRoot":"","sources":["../../../../../../libs/agent-rules/src/lib/targets/shared.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The agent-facing half of Timetrack: everything here is one call into the running app.
|
|
3
|
+
*
|
|
4
|
+
* Nothing in this file knows a Jira host or a token. That is the point — an agent working in any
|
|
5
|
+
* repository asks the one process that holds them, so a machine has one secret to rotate rather than
|
|
6
|
+
* one per checkout.
|
|
7
|
+
*/
|
|
8
|
+
export declare const timetrackCommand: (options: {
|
|
9
|
+
root: string;
|
|
10
|
+
argv: string[];
|
|
11
|
+
}) => Promise<number>;
|
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.timetrackCommand = void 0;
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
5
|
+
const timetrack_1 = require("./timetrack");
|
|
6
|
+
const FLAGS_WITH_VALUE = [
|
|
7
|
+
'--root',
|
|
8
|
+
'--project',
|
|
9
|
+
'--limit',
|
|
10
|
+
'--summary',
|
|
11
|
+
'--description',
|
|
12
|
+
'--type',
|
|
13
|
+
'--parent',
|
|
14
|
+
'--subject',
|
|
15
|
+
'--issue',
|
|
16
|
+
'--minutes',
|
|
17
|
+
'--at',
|
|
18
|
+
];
|
|
19
|
+
const positionalArgs = (args) => args.filter((entry, index) => { var _a; return !entry.startsWith('--') && !FLAGS_WITH_VALUE.includes((_a = args[index - 1]) !== null && _a !== void 0 ? _a : ''); });
|
|
20
|
+
const flagValue = (args, flag) => {
|
|
21
|
+
const index = args.indexOf(flag);
|
|
22
|
+
return index === -1 ? undefined : args[index + 1];
|
|
23
|
+
};
|
|
24
|
+
const numberFlag = (args, flag) => {
|
|
25
|
+
const raw = flagValue(args, flag);
|
|
26
|
+
if (raw === undefined)
|
|
27
|
+
return undefined;
|
|
28
|
+
const value = Number(raw);
|
|
29
|
+
if (!Number.isFinite(value))
|
|
30
|
+
throw new Error(`${flag} takes a number, not ${raw}.`);
|
|
31
|
+
return value;
|
|
32
|
+
};
|
|
33
|
+
/** `--at` takes anything `Date` reads, so an agent may pass an ISO instant or leave it out for now. */
|
|
34
|
+
const instantFlag = (args) => {
|
|
35
|
+
const raw = flagValue(args, '--at');
|
|
36
|
+
if (!raw)
|
|
37
|
+
return Date.now();
|
|
38
|
+
const at = new Date(raw);
|
|
39
|
+
if (Number.isNaN(at.getTime()))
|
|
40
|
+
throw new Error(`--at takes a date, not ${raw}.`);
|
|
41
|
+
return at.getTime();
|
|
42
|
+
};
|
|
43
|
+
const issueLine = (issue) => [
|
|
44
|
+
issue.key,
|
|
45
|
+
issue.issueType,
|
|
46
|
+
issue.summary,
|
|
47
|
+
...(issue.parentKey ? [`under ${issue.parentKey}`] : []),
|
|
48
|
+
...(issue.subject ? [`subject ${issue.subject}`] : []),
|
|
49
|
+
].join(' ');
|
|
50
|
+
const printed = (value, json) => {
|
|
51
|
+
if (json)
|
|
52
|
+
console.log(JSON.stringify(value, null, 2));
|
|
53
|
+
return 0;
|
|
54
|
+
};
|
|
55
|
+
const USAGE = `ethlete-agents timetrack — ask the running Timetrack app about Jira
|
|
56
|
+
|
|
57
|
+
The app holds this machine's Jira credentials, so no repository needs a token of its own.
|
|
58
|
+
|
|
59
|
+
timetrack status Whether the app is reachable, and which projects it holds
|
|
60
|
+
timetrack instance The instance's own levels and its branch-subject candidates
|
|
61
|
+
timetrack issue <KEY> One issue: its summary, type, parent and branch subject
|
|
62
|
+
timetrack search [text] Open issues of the picked projects, most recently touched first
|
|
63
|
+
timetrack project [path] Which Jira project a repository logs into
|
|
64
|
+
timetrack create --summary … File a new issue with the instance's own ticket settings
|
|
65
|
+
timetrack log --issue <KEY> --minutes <n>
|
|
66
|
+
Add a row nothing observed to the day it belongs to
|
|
67
|
+
|
|
68
|
+
Options for search
|
|
69
|
+
--project <KEY> Search this project instead of the picked ones
|
|
70
|
+
--mine Only the issues assigned to the account
|
|
71
|
+
--limit <n> How many issues to read (default 100)
|
|
72
|
+
|
|
73
|
+
Options for create
|
|
74
|
+
--summary <text> Required
|
|
75
|
+
--description <text>
|
|
76
|
+
--project <KEY> Required unless the app holds exactly one picked project
|
|
77
|
+
--type <name> Issue type by name (default: the app's configured type)
|
|
78
|
+
--parent <KEY> The story or epic it rolls up to
|
|
79
|
+
--subject <text> The branch subject, written to the instance's subject field
|
|
80
|
+
|
|
81
|
+
Options for log
|
|
82
|
+
--issue <KEY> Required
|
|
83
|
+
--minutes <n> Required
|
|
84
|
+
--at <date> When the work started (default: now)
|
|
85
|
+
--description <text>
|
|
86
|
+
|
|
87
|
+
Options everywhere
|
|
88
|
+
--json Print the raw answer instead of lines
|
|
89
|
+
`;
|
|
90
|
+
/**
|
|
91
|
+
* The agent-facing half of Timetrack: everything here is one call into the running app.
|
|
92
|
+
*
|
|
93
|
+
* Nothing in this file knows a Jira host or a token. That is the point — an agent working in any
|
|
94
|
+
* repository asks the one process that holds them, so a machine has one secret to rotate rather than
|
|
95
|
+
* one per checkout.
|
|
96
|
+
*/
|
|
97
|
+
const timetrackCommand = (options) => tslib_1.__awaiter(void 0, void 0, void 0, function* () {
|
|
98
|
+
const { root, argv } = options;
|
|
99
|
+
const [subcommand, value] = positionalArgs(argv);
|
|
100
|
+
const json = argv.includes('--json');
|
|
101
|
+
if (subcommand === 'status') {
|
|
102
|
+
const status = yield (0, timetrack_1.timetrackStatus)();
|
|
103
|
+
if (!json) {
|
|
104
|
+
console.log(`Timetrack ${(0, timetrack_1.timetrackDiscoveryPath)()}`);
|
|
105
|
+
console.log(` jira ${status.jiraReady ? 'configured' : 'not configured — set it in Timetrack Settings'}`);
|
|
106
|
+
console.log(` projects ${status.projects.map((project) => project.key).join(', ') || '— none picked'}`);
|
|
107
|
+
console.log(` subject ${status.subjectField || '— no field configured, the summary is used'}`);
|
|
108
|
+
}
|
|
109
|
+
return printed(status, json);
|
|
110
|
+
}
|
|
111
|
+
if (subcommand === 'instance') {
|
|
112
|
+
const instance = yield (0, timetrack_1.timetrackInstance)();
|
|
113
|
+
if (!json) {
|
|
114
|
+
console.log('Levels, highest first');
|
|
115
|
+
instance.levels.forEach((level) => console.log(` ${level.hierarchyLevel} ${level.typeNames.join(', ')}`));
|
|
116
|
+
console.log(`A parent can be named by ${instance.suggestedParenting}`);
|
|
117
|
+
console.log(`Branch-subject candidates (${instance.subjectFieldCandidates.length})`);
|
|
118
|
+
instance.subjectFieldCandidates.forEach((field) => console.log(` ${field.id} ${field.name}`));
|
|
119
|
+
}
|
|
120
|
+
return printed(instance, json);
|
|
121
|
+
}
|
|
122
|
+
if (subcommand === 'issue') {
|
|
123
|
+
if (!value)
|
|
124
|
+
throw new Error('Pass an issue key, e.g. `ethlete-agents timetrack issue FIP-2177`.');
|
|
125
|
+
const issue = yield (0, timetrack_1.timetrackIssue)(value);
|
|
126
|
+
if (!json)
|
|
127
|
+
console.log(issueLine(issue));
|
|
128
|
+
return printed(issue, json);
|
|
129
|
+
}
|
|
130
|
+
if (subcommand === 'search') {
|
|
131
|
+
const issues = yield (0, timetrack_1.timetrackSearch)({
|
|
132
|
+
text: value,
|
|
133
|
+
projectKey: flagValue(argv, '--project'),
|
|
134
|
+
assignedToMe: argv.includes('--mine'),
|
|
135
|
+
limit: numberFlag(argv, '--limit'),
|
|
136
|
+
});
|
|
137
|
+
if (!json) {
|
|
138
|
+
if (issues.length === 0)
|
|
139
|
+
console.log('No issue matches.');
|
|
140
|
+
issues.forEach((issue) => console.log(issueLine(issue)));
|
|
141
|
+
}
|
|
142
|
+
return printed(issues, json);
|
|
143
|
+
}
|
|
144
|
+
if (subcommand === 'project') {
|
|
145
|
+
const found = yield (0, timetrack_1.timetrackRepoProject)(value !== null && value !== void 0 ? value : root);
|
|
146
|
+
if (!json) {
|
|
147
|
+
const where = found.inherited ? ' (from a directory above it)' : '';
|
|
148
|
+
if (found.private)
|
|
149
|
+
console.log(`${found.repoPath} is marked private — work there is logged nowhere${where}.`);
|
|
150
|
+
else if (found.projectKey)
|
|
151
|
+
console.log(`${found.repoPath} logs into ${found.projectKey}${where}.`);
|
|
152
|
+
else if (found.suggestedProjectKey) {
|
|
153
|
+
console.log(`${found.repoPath} is linked to nothing. Its name suggests ${found.suggestedProjectKey}.`);
|
|
154
|
+
}
|
|
155
|
+
else
|
|
156
|
+
console.log(`${found.repoPath} is linked to no project. Link it in Timetrack Settings.`);
|
|
157
|
+
}
|
|
158
|
+
return printed(found, json);
|
|
159
|
+
}
|
|
160
|
+
if (subcommand === 'create') {
|
|
161
|
+
const summary = flagValue(argv, '--summary');
|
|
162
|
+
if (!summary)
|
|
163
|
+
throw new Error('Pass --summary "…".');
|
|
164
|
+
const issue = yield (0, timetrack_1.timetrackCreateIssue)({
|
|
165
|
+
summary,
|
|
166
|
+
description: flagValue(argv, '--description'),
|
|
167
|
+
projectKey: flagValue(argv, '--project'),
|
|
168
|
+
issueTypeName: flagValue(argv, '--type'),
|
|
169
|
+
parentKey: flagValue(argv, '--parent'),
|
|
170
|
+
subject: flagValue(argv, '--subject'),
|
|
171
|
+
});
|
|
172
|
+
if (!json)
|
|
173
|
+
console.log(`${issue.key} ${summary}`);
|
|
174
|
+
return printed(issue, json);
|
|
175
|
+
}
|
|
176
|
+
if (subcommand === 'log') {
|
|
177
|
+
const issueKey = flagValue(argv, '--issue');
|
|
178
|
+
const minutes = numberFlag(argv, '--minutes');
|
|
179
|
+
if (!issueKey)
|
|
180
|
+
throw new Error('Pass --issue <KEY>.');
|
|
181
|
+
if (!minutes || minutes <= 0)
|
|
182
|
+
throw new Error('Pass --minutes <n> above zero.');
|
|
183
|
+
const worklog = yield (0, timetrack_1.timetrackAddWorklog)({
|
|
184
|
+
issueKey,
|
|
185
|
+
description: flagValue(argv, '--description'),
|
|
186
|
+
fromMs: instantFlag(argv),
|
|
187
|
+
durationMs: Math.round(minutes * 60000),
|
|
188
|
+
});
|
|
189
|
+
if (!json) {
|
|
190
|
+
console.log(`${worklog.issueKey} ${minutes}m on ${worklog.day}`);
|
|
191
|
+
console.log('It is a row on the day, not a Tempo entry — review the day in Timetrack, then sync it.');
|
|
192
|
+
}
|
|
193
|
+
return printed(worklog, json);
|
|
194
|
+
}
|
|
195
|
+
console.log(USAGE);
|
|
196
|
+
return subcommand === undefined || subcommand === '--help' || subcommand === '-h' ? 0 : 1;
|
|
197
|
+
});
|
|
198
|
+
exports.timetrackCommand = timetrackCommand;
|
|
199
|
+
//# sourceMappingURL=timetrack-command.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"timetrack-command.js","sourceRoot":"","sources":["../../../../../libs/agent-rules/src/lib/timetrack-command.ts"],"names":[],"mappings":";;;;AAAA,2CAUqB;AAErB,MAAM,gBAAgB,GAAG;IACvB,QAAQ;IACR,WAAW;IACX,SAAS;IACT,WAAW;IACX,eAAe;IACf,QAAQ;IACR,UAAU;IACV,WAAW;IACX,SAAS;IACT,WAAW;IACX,MAAM;CACP,CAAC;AAEF,MAAM,cAAc,GAAG,CAAC,IAAc,EAAE,EAAE,CACxC,IAAI,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE,WAAC,OAAA,CAAC,KAAK,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,gBAAgB,CAAC,QAAQ,CAAC,MAAA,IAAI,CAAC,KAAK,GAAG,CAAC,CAAC,mCAAI,EAAE,CAAC,CAAA,EAAA,CAAC,CAAC;AAE9G,MAAM,SAAS,GAAG,CAAC,IAAc,EAAE,IAAY,EAAE,EAAE;IACjD,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IAEjC,OAAO,KAAK,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC;AACpD,CAAC,CAAC;AAEF,MAAM,UAAU,GAAG,CAAC,IAAc,EAAE,IAAY,EAAE,EAAE;IAClD,MAAM,GAAG,GAAG,SAAS,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;IAElC,IAAI,GAAG,KAAK,SAAS;QAAE,OAAO,SAAS,CAAC;IAExC,MAAM,KAAK,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC;IAE1B,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,GAAG,IAAI,wBAAwB,GAAG,GAAG,CAAC,CAAC;IAEpF,OAAO,KAAK,CAAC;AACf,CAAC,CAAC;AAEF,uGAAuG;AACvG,MAAM,WAAW,GAAG,CAAC,IAAc,EAAE,EAAE;IACrC,MAAM,GAAG,GAAG,SAAS,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IAEpC,IAAI,CAAC,GAAG;QAAE,OAAO,IAAI,CAAC,GAAG,EAAE,CAAC;IAE5B,MAAM,EAAE,GAAG,IAAI,IAAI,CAAC,GAAG,CAAC,CAAC;IAEzB,IAAI,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,0BAA0B,GAAG,GAAG,CAAC,CAAC;IAElF,OAAO,EAAE,CAAC,OAAO,EAAE,CAAC;AACtB,CAAC,CAAC;AAEF,MAAM,SAAS,GAAG,CAAC,KAAqB,EAAE,EAAE,CAC1C;IACE,KAAK,CAAC,GAAG;IACT,KAAK,CAAC,SAAS;IACf,KAAK,CAAC,OAAO;IACb,GAAG,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,SAAS,KAAK,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IACxD,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,WAAW,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;CACvD,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAEf,MAAM,OAAO,GAAG,CAAC,KAAc,EAAE,IAAa,EAAE,EAAE;IAChD,IAAI,IAAI;QAAE,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;IAEtD,OAAO,CAAC,CAAC;AACX,CAAC,CAAC;AAEF,MAAM,KAAK,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAkCb,CAAC;AAEF;;;;;;GAMG;AACI,MAAM,gBAAgB,GAAG,CAAO,OAAyC,EAAE,EAAE;IAClF,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,OAAO,CAAC;IAC/B,MAAM,CAAC,UAAU,EAAE,KAAK,CAAC,GAAG,cAAc,CAAC,IAAI,CAAC,CAAC;IACjD,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;IAErC,IAAI,UAAU,KAAK,QAAQ,EAAE,CAAC;QAC5B,MAAM,MAAM,GAAG,MAAM,IAAA,2BAAe,GAAE,CAAC;QAEvC,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,OAAO,CAAC,GAAG,CAAC,eAAe,IAAA,kCAAsB,GAAE,EAAE,CAAC,CAAC;YACvD,OAAO,CAAC,GAAG,CAAC,eAAe,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,+CAA+C,EAAE,CAAC,CAAC;YAChH,OAAO,CAAC,GAAG,CAAC,eAAe,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,eAAe,EAAE,CAAC,CAAC;YAC1G,OAAO,CAAC,GAAG,CAAC,eAAe,MAAM,CAAC,YAAY,IAAI,4CAA4C,EAAE,CAAC,CAAC;QACpG,CAAC;QAED,OAAO,OAAO,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;IAC/B,CAAC;IAED,IAAI,UAAU,KAAK,UAAU,EAAE,CAAC;QAC9B,MAAM,QAAQ,GAAG,MAAM,IAAA,6BAAiB,GAAE,CAAC;QAE3C,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,OAAO,CAAC,GAAG,CAAC,uBAAuB,CAAC,CAAC;YACrC,QAAQ,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,KAAK,CAAC,cAAc,KAAK,KAAK,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;YAC5G,OAAO,CAAC,GAAG,CAAC,6BAA6B,QAAQ,CAAC,kBAAkB,EAAE,CAAC,CAAC;YACxE,OAAO,CAAC,GAAG,CAAC,8BAA8B,QAAQ,CAAC,sBAAsB,CAAC,MAAM,GAAG,CAAC,CAAC;YACrF,QAAQ,CAAC,sBAAsB,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,KAAK,CAAC,EAAE,KAAK,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;QAClG,CAAC;QAED,OAAO,OAAO,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;IACjC,CAAC;IAED,IAAI,UAAU,KAAK,OAAO,EAAE,CAAC;QAC3B,IAAI,CAAC,KAAK;YAAE,MAAM,IAAI,KAAK,CAAC,oEAAoE,CAAC,CAAC;QAElG,MAAM,KAAK,GAAG,MAAM,IAAA,0BAAc,EAAC,KAAK,CAAC,CAAC;QAE1C,IAAI,CAAC,IAAI;YAAE,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC;QAEzC,OAAO,OAAO,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;IAC9B,CAAC;IAED,IAAI,UAAU,KAAK,QAAQ,EAAE,CAAC;QAC5B,MAAM,MAAM,GAAG,MAAM,IAAA,2BAAe,EAAC;YACnC,IAAI,EAAE,KAAK;YACX,UAAU,EAAE,SAAS,CAAC,IAAI,EAAE,WAAW,CAAC;YACxC,YAAY,EAAE,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC;YACrC,KAAK,EAAE,UAAU,CAAC,IAAI,EAAE,SAAS,CAAC;SACnC,CAAC,CAAC;QAEH,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC;gBAAE,OAAO,CAAC,GAAG,CAAC,mBAAmB,CAAC,CAAC;YAC1D,MAAM,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;QAC3D,CAAC;QAED,OAAO,OAAO,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;IAC/B,CAAC;IAED,IAAI,UAAU,KAAK,SAAS,EAAE,CAAC;QAC7B,MAAM,KAAK,GAAG,MAAM,IAAA,gCAAoB,EAAC,KAAK,aAAL,KAAK,cAAL,KAAK,GAAI,IAAI,CAAC,CAAC;QAExD,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,MAAM,KAAK,GAAG,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,8BAA8B,CAAC,CAAC,CAAC,EAAE,CAAC;YAEpE,IAAI,KAAK,CAAC,OAAO;gBAAE,OAAO,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC,QAAQ,oDAAoD,KAAK,GAAG,CAAC,CAAC;iBACzG,IAAI,KAAK,CAAC,UAAU;gBAAE,OAAO,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC,QAAQ,cAAc,KAAK,CAAC,UAAU,GAAG,KAAK,GAAG,CAAC,CAAC;iBAC9F,IAAI,KAAK,CAAC,mBAAmB,EAAE,CAAC;gBACnC,OAAO,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC,QAAQ,4CAA4C,KAAK,CAAC,mBAAmB,GAAG,CAAC,CAAC;YACzG,CAAC;;gBAAM,OAAO,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC,QAAQ,0DAA0D,CAAC,CAAC;QAClG,CAAC;QAED,OAAO,OAAO,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;IAC9B,CAAC;IAED,IAAI,UAAU,KAAK,QAAQ,EAAE,CAAC;QAC5B,MAAM,OAAO,GAAG,SAAS,CAAC,IAAI,EAAE,WAAW,CAAC,CAAC;QAE7C,IAAI,CAAC,OAAO;YAAE,MAAM,IAAI,KAAK,CAAC,qBAAqB,CAAC,CAAC;QAErD,MAAM,KAAK,GAAG,MAAM,IAAA,gCAAoB,EAAC;YACvC,OAAO;YACP,WAAW,EAAE,SAAS,CAAC,IAAI,EAAE,eAAe,CAAC;YAC7C,UAAU,EAAE,SAAS,CAAC,IAAI,EAAE,WAAW,CAAC;YACxC,aAAa,EAAE,SAAS,CAAC,IAAI,EAAE,QAAQ,CAAC;YACxC,SAAS,EAAE,SAAS,CAAC,IAAI,EAAE,UAAU,CAAC;YACtC,OAAO,EAAE,SAAS,CAAC,IAAI,EAAE,WAAW,CAAC;SACtC,CAAC,CAAC;QAEH,IAAI,CAAC,IAAI;YAAE,OAAO,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC,GAAG,KAAK,OAAO,EAAE,CAAC,CAAC;QAEnD,OAAO,OAAO,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;IAC9B,CAAC;IAED,IAAI,UAAU,KAAK,KAAK,EAAE,CAAC;QACzB,MAAM,QAAQ,GAAG,SAAS,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC;QAC5C,MAAM,OAAO,GAAG,UAAU,CAAC,IAAI,EAAE,WAAW,CAAC,CAAC;QAE9C,IAAI,CAAC,QAAQ;YAAE,MAAM,IAAI,KAAK,CAAC,qBAAqB,CAAC,CAAC;QACtD,IAAI,CAAC,OAAO,IAAI,OAAO,IAAI,CAAC;YAAE,MAAM,IAAI,KAAK,CAAC,gCAAgC,CAAC,CAAC;QAEhF,MAAM,OAAO,GAAG,MAAM,IAAA,+BAAmB,EAAC;YACxC,QAAQ;YACR,WAAW,EAAE,SAAS,CAAC,IAAI,EAAE,eAAe,CAAC;YAC7C,MAAM,EAAE,WAAW,CAAC,IAAI,CAAC;YACzB,UAAU,EAAE,IAAI,CAAC,KAAK,CAAC,OAAO,GAAG,KAAM,CAAC;SACzC,CAAC,CAAC;QAEH,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,OAAO,CAAC,GAAG,CAAC,GAAG,OAAO,CAAC,QAAQ,KAAK,OAAO,QAAQ,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC;YAClE,OAAO,CAAC,GAAG,CAAC,wFAAwF,CAAC,CAAC;QACxG,CAAC;QAED,OAAO,OAAO,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;IAChC,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;IAEnB,OAAO,UAAU,KAAK,SAAS,IAAI,UAAU,KAAK,QAAQ,IAAI,UAAU,KAAK,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAC5F,CAAC,CAAA,CAAC;AAtHW,QAAA,gBAAgB,oBAsH3B"}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
export type TimetrackIssue = {
|
|
2
|
+
key: string;
|
|
3
|
+
id: string;
|
|
4
|
+
summary: string;
|
|
5
|
+
issueType: string;
|
|
6
|
+
parentKey?: string;
|
|
7
|
+
subject?: string;
|
|
8
|
+
};
|
|
9
|
+
export type TimetrackStatus = {
|
|
10
|
+
version: number;
|
|
11
|
+
jiraReady: boolean;
|
|
12
|
+
projects: {
|
|
13
|
+
key: string;
|
|
14
|
+
name: string;
|
|
15
|
+
}[];
|
|
16
|
+
subjectField: string;
|
|
17
|
+
};
|
|
18
|
+
export type TimetrackInstance = {
|
|
19
|
+
levels: {
|
|
20
|
+
hierarchyLevel: number;
|
|
21
|
+
typeNames: string[];
|
|
22
|
+
}[];
|
|
23
|
+
suggestedParenting: 'parent-field' | 'issue-link';
|
|
24
|
+
subjectFieldCandidates: {
|
|
25
|
+
id: string;
|
|
26
|
+
name: string;
|
|
27
|
+
}[];
|
|
28
|
+
};
|
|
29
|
+
export type TimetrackRepoProject = {
|
|
30
|
+
repoPath: string;
|
|
31
|
+
projectKey?: string;
|
|
32
|
+
private: boolean;
|
|
33
|
+
inherited: boolean;
|
|
34
|
+
suggestedProjectKey?: string;
|
|
35
|
+
};
|
|
36
|
+
export type TimetrackWorklog = {
|
|
37
|
+
day: string;
|
|
38
|
+
issueKey: string;
|
|
39
|
+
description: string;
|
|
40
|
+
fromMs: number;
|
|
41
|
+
toMs: number;
|
|
42
|
+
durationMs: number;
|
|
43
|
+
};
|
|
44
|
+
/**
|
|
45
|
+
* Where the app writes the port and the token, which is its data directory on each platform.
|
|
46
|
+
*
|
|
47
|
+
* `TIMETRACK_AGENT_DISCOVERY` names the file directly, for a machine whose app data lives somewhere
|
|
48
|
+
* else and for a test.
|
|
49
|
+
*/
|
|
50
|
+
export declare const timetrackDiscoveryPath: () => string;
|
|
51
|
+
/**
|
|
52
|
+
* Asks the running Timetrack app to carry out one operation.
|
|
53
|
+
*
|
|
54
|
+
* It is the only way this package reaches Jira. The token lives in the app's keychain entry and in no
|
|
55
|
+
* repository, so a checkout an agent works in holds nothing worth stealing and nothing to rotate.
|
|
56
|
+
*/
|
|
57
|
+
export declare const askTimetrack: <T>(request: Record<string, unknown> & {
|
|
58
|
+
op: string;
|
|
59
|
+
}) => Promise<T>;
|
|
60
|
+
export declare const timetrackStatus: () => Promise<TimetrackStatus>;
|
|
61
|
+
export declare const timetrackInstance: () => Promise<TimetrackInstance>;
|
|
62
|
+
export declare const timetrackIssue: (key: string) => Promise<TimetrackIssue>;
|
|
63
|
+
export declare const timetrackSearch: (options: {
|
|
64
|
+
text?: string;
|
|
65
|
+
projectKey?: string;
|
|
66
|
+
assignedToMe?: boolean;
|
|
67
|
+
limit?: number;
|
|
68
|
+
}) => Promise<TimetrackIssue[]>;
|
|
69
|
+
export declare const timetrackRepoProject: (repoPath: string) => Promise<TimetrackRepoProject>;
|
|
70
|
+
export declare const timetrackCreateIssue: (options: {
|
|
71
|
+
summary: string;
|
|
72
|
+
description?: string;
|
|
73
|
+
projectKey?: string;
|
|
74
|
+
issueTypeName?: string;
|
|
75
|
+
parentKey?: string;
|
|
76
|
+
subject?: string;
|
|
77
|
+
}) => Promise<{
|
|
78
|
+
key: string;
|
|
79
|
+
id: string;
|
|
80
|
+
}>;
|
|
81
|
+
export declare const timetrackAddWorklog: (options: {
|
|
82
|
+
issueKey: string;
|
|
83
|
+
description?: string;
|
|
84
|
+
fromMs: number;
|
|
85
|
+
durationMs: number;
|
|
86
|
+
}) => Promise<TimetrackWorklog>;
|