@oratis/lisa 0.7.0 → 0.8.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/autostart/install.d.ts +28 -0
- package/dist/autostart/install.d.ts.map +1 -0
- package/dist/autostart/install.js +180 -0
- package/dist/autostart/install.js.map +1 -0
- package/dist/cli.js +49 -1
- package/dist/cli.js.map +1 -1
- package/dist/heartbeat/install.d.ts.map +1 -1
- package/dist/heartbeat/install.js +1 -43
- package/dist/heartbeat/install.js.map +1 -1
- package/dist/heartbeat/runner.d.ts.map +1 -1
- package/dist/heartbeat/runner.js +11 -0
- package/dist/heartbeat/runner.js.map +1 -1
- package/dist/integrations/aider/observer.d.ts +48 -0
- package/dist/integrations/aider/observer.d.ts.map +1 -0
- package/dist/integrations/aider/observer.js +196 -0
- package/dist/integrations/aider/observer.js.map +1 -0
- package/dist/integrations/comparisons.d.ts +23 -0
- package/dist/integrations/comparisons.d.ts.map +1 -0
- package/dist/integrations/comparisons.js +47 -0
- package/dist/integrations/comparisons.js.map +1 -0
- package/dist/integrations/github-pr/observer.d.ts +85 -0
- package/dist/integrations/github-pr/observer.d.ts.map +1 -0
- package/dist/integrations/github-pr/observer.js +261 -0
- package/dist/integrations/github-pr/observer.js.map +1 -0
- package/dist/integrations/hub.d.ts.map +1 -1
- package/dist/integrations/hub.js +10 -0
- package/dist/integrations/hub.js.map +1 -1
- package/dist/integrations/opencode/observer.d.ts +74 -0
- package/dist/integrations/opencode/observer.d.ts.map +1 -0
- package/dist/integrations/opencode/observer.js +207 -0
- package/dist/integrations/opencode/observer.js.map +1 -0
- package/dist/integrations/registry.d.ts.map +1 -1
- package/dist/integrations/registry.js +3 -1
- package/dist/integrations/registry.js.map +1 -1
- package/dist/integrations/scheduled-dispatch.d.ts +42 -0
- package/dist/integrations/scheduled-dispatch.d.ts.map +1 -0
- package/dist/integrations/scheduled-dispatch.js +140 -0
- package/dist/integrations/scheduled-dispatch.js.map +1 -0
- package/dist/launchd.d.ts +18 -0
- package/dist/launchd.d.ts.map +1 -0
- package/dist/launchd.js +60 -0
- package/dist/launchd.js.map +1 -0
- package/dist/orchestrator/journal.d.ts +46 -0
- package/dist/orchestrator/journal.d.ts.map +1 -0
- package/dist/orchestrator/journal.js +82 -0
- package/dist/orchestrator/journal.js.map +1 -0
- package/dist/orchestrator/recap.d.ts +38 -0
- package/dist/orchestrator/recap.d.ts.map +1 -0
- package/dist/orchestrator/recap.js +134 -0
- package/dist/orchestrator/recap.js.map +1 -0
- package/dist/screen_advisor/engine.d.ts +79 -0
- package/dist/screen_advisor/engine.d.ts.map +1 -0
- package/dist/screen_advisor/engine.js +128 -0
- package/dist/screen_advisor/engine.js.map +1 -0
- package/dist/soul/lock.d.ts +7 -4
- package/dist/soul/lock.d.ts.map +1 -1
- package/dist/soul/lock.js +33 -9
- package/dist/soul/lock.js.map +1 -1
- package/dist/tools/agent_recap.d.ts +21 -0
- package/dist/tools/agent_recap.d.ts.map +1 -0
- package/dist/tools/agent_recap.js +43 -0
- package/dist/tools/agent_recap.js.map +1 -0
- package/dist/tools/compare_agents.d.ts +16 -0
- package/dist/tools/compare_agents.d.ts.map +1 -0
- package/dist/tools/compare_agents.js +145 -0
- package/dist/tools/compare_agents.js.map +1 -0
- package/dist/tools/dispatch_agent.d.ts +13 -0
- package/dist/tools/dispatch_agent.d.ts.map +1 -1
- package/dist/tools/dispatch_agent.js +46 -46
- package/dist/tools/dispatch_agent.js.map +1 -1
- package/dist/tools/exec-util.d.ts +18 -0
- package/dist/tools/exec-util.d.ts.map +1 -0
- package/dist/tools/exec-util.js +72 -0
- package/dist/tools/exec-util.js.map +1 -0
- package/dist/tools/inspect_agent.d.ts +21 -0
- package/dist/tools/inspect_agent.d.ts.map +1 -0
- package/dist/tools/inspect_agent.js +87 -0
- package/dist/tools/inspect_agent.js.map +1 -0
- package/dist/tools/list_agents.d.ts +21 -0
- package/dist/tools/list_agents.d.ts.map +1 -0
- package/dist/tools/list_agents.js +88 -0
- package/dist/tools/list_agents.js.map +1 -0
- package/dist/tools/pr_status.d.ts +31 -0
- package/dist/tools/pr_status.d.ts.map +1 -0
- package/dist/tools/pr_status.js +90 -0
- package/dist/tools/pr_status.js.map +1 -0
- package/dist/tools/registry.d.ts.map +1 -1
- package/dist/tools/registry.js +19 -0
- package/dist/tools/registry.js.map +1 -1
- package/dist/tools/repo_digest.d.ts +33 -0
- package/dist/tools/repo_digest.d.ts.map +1 -0
- package/dist/tools/repo_digest.js +113 -0
- package/dist/tools/repo_digest.js.map +1 -0
- package/dist/tools/review_diff.d.ts +28 -0
- package/dist/tools/review_diff.d.ts.map +1 -0
- package/dist/tools/review_diff.js +68 -0
- package/dist/tools/review_diff.js.map +1 -0
- package/dist/tools/run_checks.d.ts +15 -0
- package/dist/tools/run_checks.d.ts.map +1 -0
- package/dist/tools/run_checks.js +117 -0
- package/dist/tools/run_checks.js.map +1 -0
- package/dist/tools/scheduled_dispatch.d.ts +27 -0
- package/dist/tools/scheduled_dispatch.d.ts.map +1 -0
- package/dist/tools/scheduled_dispatch.js +57 -0
- package/dist/tools/scheduled_dispatch.js.map +1 -0
- package/dist/web/island.d.ts +1 -1
- package/dist/web/island.d.ts.map +1 -1
- package/dist/web/island.js +67 -4
- package/dist/web/island.js.map +1 -1
- package/dist/web/lisa-html.d.ts +1 -1
- package/dist/web/lisa-html.d.ts.map +1 -1
- package/dist/web/lisa-html.js +23 -2
- package/dist/web/lisa-html.js.map +1 -1
- package/dist/web/server.d.ts.map +1 -1
- package/dist/web/server.js +136 -0
- package/dist/web/server.js.map +1 -1
- package/package.json +1 -1
package/dist/tools/registry.js
CHANGED
|
@@ -1,8 +1,17 @@
|
|
|
1
1
|
import { memoryTool } from "../memory/tool.js";
|
|
2
2
|
import { memorySearchTool } from "../memory/search_tool.js";
|
|
3
3
|
import { adviseNowTool } from "./advise_now.js";
|
|
4
|
+
import { listAgentsTool } from "./list_agents.js";
|
|
5
|
+
import { inspectAgentTool } from "./inspect_agent.js";
|
|
6
|
+
import { repoDigestTool } from "./repo_digest.js";
|
|
7
|
+
import { reviewDiffTool } from "./review_diff.js";
|
|
8
|
+
import { runChecksTool } from "./run_checks.js";
|
|
9
|
+
import { prStatusTool } from "./pr_status.js";
|
|
4
10
|
import { dispatchAgentTool } from "./dispatch_agent.js";
|
|
11
|
+
import { scheduledDispatchTool } from "./scheduled_dispatch.js";
|
|
12
|
+
import { compareAgentsTool } from "./compare_agents.js";
|
|
5
13
|
import { signalAgentTool } from "./signal_agent.js";
|
|
14
|
+
import { agentRecapTool } from "./agent_recap.js";
|
|
6
15
|
import { skillManageTool } from "../skills/tool.js";
|
|
7
16
|
import { desireCloseTool, desireProgressTool, soulDiffTool, soulFeelTool, soulHistoryTool, soulJournalTool, soulObjectTool, soulPatchTool, soulReadTool, } from "../soul/tools.js";
|
|
8
17
|
import { speakTool, transcribeTool } from "../voice/tool.js";
|
|
@@ -43,9 +52,18 @@ export function buildToolRegistry(opts = {}) {
|
|
|
43
52
|
webSearchTool,
|
|
44
53
|
redeployTool,
|
|
45
54
|
// Orchestration (docs/ORCHESTRATOR_PLAN.md): observe → advise → dispatch → control.
|
|
55
|
+
listAgentsTool,
|
|
56
|
+
inspectAgentTool,
|
|
57
|
+
repoDigestTool,
|
|
58
|
+
reviewDiffTool,
|
|
59
|
+
runChecksTool,
|
|
60
|
+
prStatusTool,
|
|
46
61
|
adviseNowTool,
|
|
47
62
|
dispatchAgentTool,
|
|
63
|
+
scheduledDispatchTool,
|
|
64
|
+
compareAgentsTool,
|
|
48
65
|
signalAgentTool,
|
|
66
|
+
agentRecapTool,
|
|
49
67
|
];
|
|
50
68
|
if (opts.includeVoice) {
|
|
51
69
|
tools.push(speakTool, transcribeTool);
|
|
@@ -71,6 +89,7 @@ export const READ_ONLY_TOOL_NAMES = new Set([
|
|
|
71
89
|
"soul_diff",
|
|
72
90
|
"web_fetch",
|
|
73
91
|
"web_search",
|
|
92
|
+
"agent_recap",
|
|
74
93
|
]);
|
|
75
94
|
export function readOnlySubset(tools) {
|
|
76
95
|
return tools.filter((t) => READ_ONLY_TOOL_NAMES.has(t.name));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"registry.js","sourceRoot":"","sources":["../../src/tools/registry.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAC5D,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,EACL,eAAe,EACf,kBAAkB,EAClB,YAAY,EACZ,YAAY,EACZ,eAAe,EACf,eAAe,EACf,cAAc,EACd,aAAa,EACb,YAAY,GACb,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,SAAS,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAC7D,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AACrC,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AACrC,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AACrC,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AACjC,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AACrC,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAC7C,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAavC,MAAM,UAAU,iBAAiB,CAAC,OAA4B,EAAE;IAC9D,MAAM,KAAK,GAAqB;QAC9B,QAA0B;QAC1B,SAA2B;QAC3B,QAA0B;QAC1B,cAAgC;QAChC,QAA0B;QAC1B,QAA0B;QAC1B,MAAwB;QACxB,eAAiC;QACjC,UAA4B;QAC5B,gBAAkC;QAClC,WAA6B;QAC7B,aAA+B;QAC/B,eAAiC;QACjC,YAA8B;QAC9B,YAA8B;QAC9B,eAAiC;QACjC,YAA8B;QAC9B,cAAgC;QAChC,kBAAoC;QACpC,eAAiC;QACjC,YAA8B;QAC9B,aAA+B;QAC/B,YAA8B;QAC9B,oFAAoF;QACpF,aAA+B;QAC/B,iBAAmC;QACnC,eAAiC;
|
|
1
|
+
{"version":3,"file":"registry.js","sourceRoot":"","sources":["../../src/tools/registry.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* repo_digest (vibe-coding) — "what actually changed?" across the repos your
|
|
3
|
+
* agents are working in. The orchestrator only sees structural activity (tool
|
|
4
|
+
* names, file paths); git is the source of truth for *what was produced*. This
|
|
5
|
+
* wraps git so LISA can answer "what did Claude Code do today" with real
|
|
6
|
+
* commits + working-tree state, per repo.
|
|
7
|
+
*
|
|
8
|
+
* Reads the user's own git repos (content they've asked LISA to look at) — this
|
|
9
|
+
* is separate from the orchestrator's no-conversation-content privacy rule.
|
|
10
|
+
*/
|
|
11
|
+
import type { ToolDefinition } from "../types.js";
|
|
12
|
+
interface RepoDigestInput {
|
|
13
|
+
/** Repo path. Omit to digest every repo with an observed agent session. */
|
|
14
|
+
cwd?: string;
|
|
15
|
+
/** git --since value. Default "1 day ago". */
|
|
16
|
+
since?: string;
|
|
17
|
+
}
|
|
18
|
+
export interface RepoDigest {
|
|
19
|
+
root: string;
|
|
20
|
+
branch: string;
|
|
21
|
+
commits: string[];
|
|
22
|
+
dirtyFiles: number;
|
|
23
|
+
diffStat: string;
|
|
24
|
+
ahead: number;
|
|
25
|
+
behind: number;
|
|
26
|
+
since: string;
|
|
27
|
+
error?: string;
|
|
28
|
+
}
|
|
29
|
+
/** Pure: render one repo's digest. Exported for tests. */
|
|
30
|
+
export declare function formatDigest(d: RepoDigest): string;
|
|
31
|
+
export declare const repoDigestTool: ToolDefinition<RepoDigestInput, string>;
|
|
32
|
+
export {};
|
|
33
|
+
//# sourceMappingURL=repo_digest.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"repo_digest.d.ts","sourceRoot":"","sources":["../../src/tools/repo_digest.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAIlD,UAAU,eAAe;IACvB,2EAA2E;IAC3E,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,8CAA8C;IAC9C,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,0DAA0D;AAC1D,wBAAgB,YAAY,CAAC,CAAC,EAAE,UAAU,GAAG,MAAM,CAqBlD;AAoDD,eAAO,MAAM,cAAc,EAAE,cAAc,CAAC,eAAe,EAAE,MAAM,CAkClE,CAAC"}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import { getCurrentHub } from "../integrations/current-hub.js";
|
|
2
|
+
import { runIn, isDir, gitRoot } from "./exec-util.js";
|
|
3
|
+
/** Pure: render one repo's digest. Exported for tests. */
|
|
4
|
+
export function formatDigest(d) {
|
|
5
|
+
const name = d.root.split("/").pop() || d.root;
|
|
6
|
+
if (d.error)
|
|
7
|
+
return `▸ ${name} — ${d.error}`;
|
|
8
|
+
const lines = [];
|
|
9
|
+
const sync = d.ahead || d.behind
|
|
10
|
+
? ` (${d.ahead ? "↑" + d.ahead : ""}${d.behind ? "↓" + d.behind : ""} vs upstream)`
|
|
11
|
+
: "";
|
|
12
|
+
lines.push(`▸ ${name} @ ${d.branch}${sync}`);
|
|
13
|
+
if (d.commits.length) {
|
|
14
|
+
lines.push(` commits since ${d.since}:`);
|
|
15
|
+
for (const c of d.commits)
|
|
16
|
+
lines.push(` ${c}`);
|
|
17
|
+
}
|
|
18
|
+
else {
|
|
19
|
+
lines.push(` no commits since ${d.since}`);
|
|
20
|
+
}
|
|
21
|
+
if (d.dirtyFiles > 0) {
|
|
22
|
+
lines.push(` uncommitted: ${d.dirtyFiles} file(s)${d.diffStat ? " · " + d.diffStat : ""}`);
|
|
23
|
+
}
|
|
24
|
+
else {
|
|
25
|
+
lines.push(` working tree clean`);
|
|
26
|
+
}
|
|
27
|
+
return lines.join("\n");
|
|
28
|
+
}
|
|
29
|
+
async function digestRepo(cwd, since, signal) {
|
|
30
|
+
const root = await gitRoot(cwd, signal);
|
|
31
|
+
const base = { root: root ?? cwd, branch: "?", commits: [], dirtyFiles: 0, diffStat: "", ahead: 0, behind: 0, since };
|
|
32
|
+
if (!root)
|
|
33
|
+
return { ...base, error: "not a git repo" };
|
|
34
|
+
const git = (args) => runIn(root, "git", ["-C", root, ...args], { timeoutMs: 8000, signal });
|
|
35
|
+
const branch = await git(["rev-parse", "--abbrev-ref", "HEAD"]);
|
|
36
|
+
base.branch = branch.code === 0 ? branch.stdout.trim() || "?" : "?";
|
|
37
|
+
// Commits across all refs in the window (covers agent worktrees/branches).
|
|
38
|
+
const log = await git(["log", "--all", "--oneline", "--no-decorate", `--since=${since}`, "-n", "25"]);
|
|
39
|
+
if (log.code === 0) {
|
|
40
|
+
base.commits = log.stdout.split("\n").map((l) => l.trim()).filter(Boolean);
|
|
41
|
+
}
|
|
42
|
+
const status = await git(["status", "--porcelain"]);
|
|
43
|
+
if (status.code === 0) {
|
|
44
|
+
base.dirtyFiles = status.stdout.split("\n").filter((l) => l.trim()).length;
|
|
45
|
+
}
|
|
46
|
+
if (base.dirtyFiles > 0) {
|
|
47
|
+
const ds = await git(["diff", "--shortstat"]);
|
|
48
|
+
if (ds.code === 0)
|
|
49
|
+
base.diffStat = ds.stdout.trim();
|
|
50
|
+
}
|
|
51
|
+
const ab = await git(["rev-list", "--left-right", "--count", "@{upstream}...HEAD"]);
|
|
52
|
+
if (ab.code === 0) {
|
|
53
|
+
const m = ab.stdout.trim().split(/\s+/);
|
|
54
|
+
base.behind = parseInt(m[0] ?? "0", 10) || 0;
|
|
55
|
+
base.ahead = parseInt(m[1] ?? "0", 10) || 0;
|
|
56
|
+
}
|
|
57
|
+
return base;
|
|
58
|
+
}
|
|
59
|
+
/** Collect distinct git roots from the observed agent sessions' cwds. */
|
|
60
|
+
async function observedRepoRoots(signal) {
|
|
61
|
+
const hub = getCurrentHub();
|
|
62
|
+
if (!hub)
|
|
63
|
+
return [];
|
|
64
|
+
const cwds = Array.from(new Set(hub.list().map((s) => s.cwd).filter((c) => !!c && c.startsWith("/"))));
|
|
65
|
+
const roots = new Set();
|
|
66
|
+
for (const c of cwds) {
|
|
67
|
+
const r = await gitRoot(c, signal);
|
|
68
|
+
if (r)
|
|
69
|
+
roots.add(r);
|
|
70
|
+
if (roots.size >= 8)
|
|
71
|
+
break;
|
|
72
|
+
}
|
|
73
|
+
return Array.from(roots);
|
|
74
|
+
}
|
|
75
|
+
export const repoDigestTool = {
|
|
76
|
+
name: "repo_digest",
|
|
77
|
+
description: "Summarise what actually changed in a git repo (or, with no cwd, every repo your agents are " +
|
|
78
|
+
"working in): recent commits in a time window, current branch, uncommitted file count + diff " +
|
|
79
|
+
"stat, and ahead/behind vs upstream. Use to answer 'what did <agent> / I do today', 'what's the " +
|
|
80
|
+
"state of <repo>', or before reviewing/merging. Reads git only (no writes). Pair with review_diff " +
|
|
81
|
+
"to see the actual changes and run_checks to verify them.",
|
|
82
|
+
inputSchema: {
|
|
83
|
+
type: "object",
|
|
84
|
+
properties: {
|
|
85
|
+
cwd: { type: "string", description: "Absolute path inside the repo. Omit to digest all repos with an active agent session." },
|
|
86
|
+
since: { type: "string", description: 'git --since window, e.g. "1 day ago", "today", "3 hours ago". Default "1 day ago".' },
|
|
87
|
+
},
|
|
88
|
+
additionalProperties: false,
|
|
89
|
+
},
|
|
90
|
+
async execute(input, ctx) {
|
|
91
|
+
const since = input.since?.trim() || "1 day ago";
|
|
92
|
+
let roots;
|
|
93
|
+
if (input.cwd) {
|
|
94
|
+
if (!(await isDir(input.cwd)))
|
|
95
|
+
return `(not a directory: ${input.cwd})`;
|
|
96
|
+
roots = [input.cwd];
|
|
97
|
+
}
|
|
98
|
+
else {
|
|
99
|
+
roots = await observedRepoRoots(ctx.signal);
|
|
100
|
+
if (roots.length === 0) {
|
|
101
|
+
// Fall back to the current working directory's repo.
|
|
102
|
+
const r = await gitRoot(ctx.cwd, ctx.signal);
|
|
103
|
+
if (r)
|
|
104
|
+
roots = [r];
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
if (roots.length === 0)
|
|
108
|
+
return "(no git repos to digest — no active agent sessions and cwd isn't a repo)";
|
|
109
|
+
const digests = await Promise.all(roots.map((r) => digestRepo(r, since, ctx.signal)));
|
|
110
|
+
return digests.map(formatDigest).join("\n\n");
|
|
111
|
+
},
|
|
112
|
+
};
|
|
113
|
+
//# sourceMappingURL=repo_digest.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"repo_digest.js","sourceRoot":"","sources":["../../src/tools/repo_digest.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* review_diff (vibe-coding) — show the actual code changes in a repo (or a PR)
|
|
3
|
+
* so LISA can review an agent's work: spot bugs, risky edits, leftover debug
|
|
4
|
+
* code, missing tests. The natural follow-up to repo_digest ("something
|
|
5
|
+
* changed") and the natural lead-in to run_checks ("does it pass?").
|
|
6
|
+
*
|
|
7
|
+
* Read-only. Diff output is capped so a huge change doesn't blow the context.
|
|
8
|
+
*/
|
|
9
|
+
import type { ToolDefinition } from "../types.js";
|
|
10
|
+
interface ReviewDiffInput {
|
|
11
|
+
/** Repo path. Defaults to the current working directory. */
|
|
12
|
+
cwd?: string;
|
|
13
|
+
/**
|
|
14
|
+
* What to diff: "head" (all uncommitted vs HEAD, default), "working"
|
|
15
|
+
* (unstaged only), "staged" (staged only), or any git ref/range
|
|
16
|
+
* (e.g. "main...HEAD", "HEAD~3").
|
|
17
|
+
*/
|
|
18
|
+
target?: string;
|
|
19
|
+
/** Review a GitHub PR's diff instead (needs the `gh` CLI). */
|
|
20
|
+
pr?: number;
|
|
21
|
+
/** Max diff lines to return. Default 600. */
|
|
22
|
+
max_lines?: number;
|
|
23
|
+
}
|
|
24
|
+
/** Pure: assemble the stat header + (capped) diff body. Exported for tests. */
|
|
25
|
+
export declare function assembleReview(stat: string, diff: string, maxLines: number): string;
|
|
26
|
+
export declare const reviewDiffTool: ToolDefinition<ReviewDiffInput, string>;
|
|
27
|
+
export {};
|
|
28
|
+
//# sourceMappingURL=review_diff.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"review_diff.d.ts","sourceRoot":"","sources":["../../src/tools/review_diff.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAGlD,UAAU,eAAe;IACvB,4DAA4D;IAC5D,GAAG,CAAC,EAAE,MAAM,CAAC;IACb;;;;OAIG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,8DAA8D;IAC9D,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,6CAA6C;IAC7C,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAgBD,+EAA+E;AAC/E,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAOnF;AAED,eAAO,MAAM,cAAc,EAAE,cAAc,CAAC,eAAe,EAAE,MAAM,CAuClE,CAAC"}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { runIn, isDir, gitRoot } from "./exec-util.js";
|
|
2
|
+
function gitDiffArgs(target) {
|
|
3
|
+
switch (target) {
|
|
4
|
+
case "working":
|
|
5
|
+
return ["diff"];
|
|
6
|
+
case "staged":
|
|
7
|
+
return ["diff", "--cached"];
|
|
8
|
+
case "head":
|
|
9
|
+
case "":
|
|
10
|
+
return ["diff", "HEAD"];
|
|
11
|
+
default:
|
|
12
|
+
return ["diff", target];
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
/** Pure: assemble the stat header + (capped) diff body. Exported for tests. */
|
|
16
|
+
export function assembleReview(stat, diff, maxLines) {
|
|
17
|
+
const header = stat.trim() ? stat.trim() : "(no changes)";
|
|
18
|
+
if (!diff.trim())
|
|
19
|
+
return header;
|
|
20
|
+
const lines = diff.split("\n");
|
|
21
|
+
if (lines.length <= maxLines)
|
|
22
|
+
return `${header}\n\n${diff.trimEnd()}`;
|
|
23
|
+
const shown = lines.slice(0, maxLines).join("\n");
|
|
24
|
+
return `${header}\n\n${shown}\n… [diff truncated — ${maxLines} of ${lines.length} lines shown; narrow with target or review per-file]`;
|
|
25
|
+
}
|
|
26
|
+
export const reviewDiffTool = {
|
|
27
|
+
name: "review_diff",
|
|
28
|
+
description: "Show the actual code diff in a repo so you can review it — uncommitted changes vs HEAD by " +
|
|
29
|
+
"default, or working/staged only, or any git ref/range, or a GitHub PR (pr:<n>, needs `gh`). " +
|
|
30
|
+
"Use to review what an agent wrote before committing/merging: bugs, risky edits, debug leftovers, " +
|
|
31
|
+
"missing tests. Read-only; output is capped. Pair with repo_digest (what changed) and run_checks " +
|
|
32
|
+
"(does it pass).",
|
|
33
|
+
inputSchema: {
|
|
34
|
+
type: "object",
|
|
35
|
+
properties: {
|
|
36
|
+
cwd: { type: "string", description: "Absolute path inside the repo. Defaults to the current directory." },
|
|
37
|
+
target: { type: "string", description: '"head" (default, all uncommitted), "working", "staged", or a git ref/range like "main...HEAD".' },
|
|
38
|
+
pr: { type: "integer", description: "Review this GitHub PR's diff instead (needs `gh`)." },
|
|
39
|
+
max_lines: { type: "integer", minimum: 50, maximum: 4000, description: "Max diff lines (default 600)." },
|
|
40
|
+
},
|
|
41
|
+
additionalProperties: false,
|
|
42
|
+
},
|
|
43
|
+
async execute(input, ctx) {
|
|
44
|
+
const cwd = input.cwd && input.cwd.startsWith("/") ? input.cwd : ctx.cwd;
|
|
45
|
+
if (!(await isDir(cwd)))
|
|
46
|
+
return `(not a directory: ${cwd})`;
|
|
47
|
+
const root = await gitRoot(cwd, ctx.signal);
|
|
48
|
+
if (!root)
|
|
49
|
+
return `(not a git repo: ${cwd})`;
|
|
50
|
+
const maxLines = input.max_lines ?? 600;
|
|
51
|
+
if (typeof input.pr === "number") {
|
|
52
|
+
const r = await runIn(root, "gh", ["pr", "diff", String(input.pr)], { timeoutMs: 20000, signal: ctx.signal, maxBytes: 200_000 });
|
|
53
|
+
if (r.spawnError)
|
|
54
|
+
return "(the `gh` CLI isn't installed — needed to fetch PR diffs)";
|
|
55
|
+
if (r.code !== 0)
|
|
56
|
+
return `(gh pr diff ${input.pr} failed: ${r.stderr.trim().slice(0, 200) || "unknown error"})`;
|
|
57
|
+
return assembleReview(`PR #${input.pr} diff`, r.stdout, maxLines);
|
|
58
|
+
}
|
|
59
|
+
const target = (input.target ?? "head").trim();
|
|
60
|
+
const args = gitDiffArgs(target);
|
|
61
|
+
const stat = await runIn(root, "git", ["-C", root, ...args, "--stat"], { timeoutMs: 10000, signal: ctx.signal });
|
|
62
|
+
const diff = await runIn(root, "git", ["-C", root, ...args], { timeoutMs: 15000, signal: ctx.signal, maxBytes: 200_000 });
|
|
63
|
+
if (diff.code !== 0)
|
|
64
|
+
return `(git diff failed: ${diff.stderr.trim().slice(0, 200) || "bad target?"})`;
|
|
65
|
+
return assembleReview(stat.stdout, diff.stdout, maxLines);
|
|
66
|
+
},
|
|
67
|
+
};
|
|
68
|
+
//# sourceMappingURL=review_diff.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"review_diff.js","sourceRoot":"","sources":["../../src/tools/review_diff.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { ToolDefinition } from "../types.js";
|
|
2
|
+
interface RunChecksInput {
|
|
3
|
+
cwd?: string;
|
|
4
|
+
/** Subset to run, e.g. ["test","typecheck"]. Omit = all detected. */
|
|
5
|
+
only?: string[];
|
|
6
|
+
}
|
|
7
|
+
export interface DetectedCheck {
|
|
8
|
+
name: string;
|
|
9
|
+
script: string;
|
|
10
|
+
}
|
|
11
|
+
/** Pure: pick which checks to run from a scripts map. Exported for tests. */
|
|
12
|
+
export declare function detectChecks(scripts: Record<string, string>, only?: string[]): DetectedCheck[];
|
|
13
|
+
export declare const runChecksTool: ToolDefinition<RunChecksInput, string>;
|
|
14
|
+
export {};
|
|
15
|
+
//# sourceMappingURL=run_checks.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"run_checks.d.ts","sourceRoot":"","sources":["../../src/tools/run_checks.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAGlD,UAAU,cAAc;IACtB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,qEAAqE;IACrE,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;CACjB;AAiBD,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,6EAA6E;AAC7E,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,IAAI,CAAC,EAAE,MAAM,EAAE,GAAG,aAAa,EAAE,CAe9F;AAOD,eAAO,MAAM,aAAa,EAAE,cAAc,CAAC,cAAc,EAAE,MAAM,CA8DhE,CAAC"}
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* run_checks (vibe-coding) — the quality gate. Auto-detects the repo's own
|
|
3
|
+
* checks (typecheck / lint / test / build from package.json scripts) and runs
|
|
4
|
+
* them, reporting pass/fail + the tail of any failure. "Lisa, does the agent's
|
|
5
|
+
* work pass?" before you commit or merge.
|
|
6
|
+
*
|
|
7
|
+
* Runs the project's OWN scripts (npm/pnpm/yarn run <script>) — same trust as
|
|
8
|
+
* running them yourself; capped per-check by a timeout.
|
|
9
|
+
*/
|
|
10
|
+
import { readFile } from "node:fs/promises";
|
|
11
|
+
import path from "node:path";
|
|
12
|
+
import { runIn, isDir, gitRoot } from "./exec-util.js";
|
|
13
|
+
/** Preferred order — fast/cheap signals first, slow build last. */
|
|
14
|
+
const CHECK_PRIORITY = ["typecheck", "lint", "test", "build"];
|
|
15
|
+
/** Script-name aliases mapped onto a canonical check. */
|
|
16
|
+
const ALIASES = {
|
|
17
|
+
typecheck: "typecheck",
|
|
18
|
+
tsc: "typecheck",
|
|
19
|
+
"type-check": "typecheck",
|
|
20
|
+
lint: "lint",
|
|
21
|
+
eslint: "lint",
|
|
22
|
+
test: "test",
|
|
23
|
+
tests: "test",
|
|
24
|
+
build: "build",
|
|
25
|
+
check: "lint",
|
|
26
|
+
};
|
|
27
|
+
/** Pure: pick which checks to run from a scripts map. Exported for tests. */
|
|
28
|
+
export function detectChecks(scripts, only) {
|
|
29
|
+
const onlySet = only && only.length ? new Set(only.map((s) => s.toLowerCase())) : null;
|
|
30
|
+
const byCanon = new Map(); // canonical → script key (first wins)
|
|
31
|
+
for (const key of Object.keys(scripts)) {
|
|
32
|
+
const canon = ALIASES[key.toLowerCase()];
|
|
33
|
+
if (!canon)
|
|
34
|
+
continue;
|
|
35
|
+
if (!byCanon.has(canon))
|
|
36
|
+
byCanon.set(canon, key);
|
|
37
|
+
}
|
|
38
|
+
const out = [];
|
|
39
|
+
for (const canon of CHECK_PRIORITY) {
|
|
40
|
+
if (!byCanon.has(canon))
|
|
41
|
+
continue;
|
|
42
|
+
if (onlySet && !onlySet.has(canon))
|
|
43
|
+
continue;
|
|
44
|
+
out.push({ name: canon, script: byCanon.get(canon) });
|
|
45
|
+
}
|
|
46
|
+
return out;
|
|
47
|
+
}
|
|
48
|
+
function tail(s, n) {
|
|
49
|
+
const lines = s.split("\n").filter((l) => l.length);
|
|
50
|
+
return lines.slice(-n).join("\n");
|
|
51
|
+
}
|
|
52
|
+
export const runChecksTool = {
|
|
53
|
+
name: "run_checks",
|
|
54
|
+
description: "Run a repo's own quality checks (typecheck, lint, test, build — auto-detected from package.json " +
|
|
55
|
+
"scripts) and report pass/fail with the tail of any failure. Use to verify an agent's work before " +
|
|
56
|
+
"committing/merging, or when the user asks 'does it pass / are tests green'. Runs the project's own " +
|
|
57
|
+
"npm/pnpm/yarn scripts (capped by a per-check timeout). Narrow with only:['test'] etc.",
|
|
58
|
+
inputSchema: {
|
|
59
|
+
type: "object",
|
|
60
|
+
properties: {
|
|
61
|
+
cwd: { type: "string", description: "Absolute path inside the repo. Defaults to the current directory." },
|
|
62
|
+
only: { type: "array", items: { type: "string" }, description: "Subset: any of typecheck/lint/test/build. Omit to run all detected." },
|
|
63
|
+
},
|
|
64
|
+
additionalProperties: false,
|
|
65
|
+
},
|
|
66
|
+
async execute(input, ctx) {
|
|
67
|
+
const cwd = input.cwd && input.cwd.startsWith("/") ? input.cwd : ctx.cwd;
|
|
68
|
+
if (!(await isDir(cwd)))
|
|
69
|
+
return `(not a directory: ${cwd})`;
|
|
70
|
+
const root = (await gitRoot(cwd, ctx.signal)) ?? cwd;
|
|
71
|
+
let scripts = {};
|
|
72
|
+
try {
|
|
73
|
+
const pkg = JSON.parse(await readFile(path.join(root, "package.json"), "utf8"));
|
|
74
|
+
scripts = pkg.scripts ?? {};
|
|
75
|
+
}
|
|
76
|
+
catch {
|
|
77
|
+
return "(no package.json with scripts found — run_checks currently supports Node/npm projects)";
|
|
78
|
+
}
|
|
79
|
+
const checks = detectChecks(scripts, input.only);
|
|
80
|
+
if (checks.length === 0) {
|
|
81
|
+
return `(no recognised check scripts in package.json; available: ${Object.keys(scripts).join(", ") || "none"})`;
|
|
82
|
+
}
|
|
83
|
+
// Pick the package manager from the lockfile.
|
|
84
|
+
const has = async (f) => isDir(root).then(() => readFile(path.join(root, f)).then(() => true).catch(() => false));
|
|
85
|
+
let pm = "npm";
|
|
86
|
+
if (await has("pnpm-lock.yaml"))
|
|
87
|
+
pm = "pnpm";
|
|
88
|
+
else if (await has("yarn.lock"))
|
|
89
|
+
pm = "yarn";
|
|
90
|
+
else if (await has("bun.lockb"))
|
|
91
|
+
pm = "bun";
|
|
92
|
+
const results = [];
|
|
93
|
+
const failures = [];
|
|
94
|
+
for (const c of checks) {
|
|
95
|
+
const r = await runIn(root, pm, ["run", c.script], { timeoutMs: 240_000, signal: ctx.signal, maxBytes: 200_000 });
|
|
96
|
+
if (r.spawnError) {
|
|
97
|
+
results.push(`✗ ${c.name} (couldn't run ${pm})`);
|
|
98
|
+
continue;
|
|
99
|
+
}
|
|
100
|
+
if (r.timedOut) {
|
|
101
|
+
results.push(`⏱ ${c.name} (timed out at 240s)`);
|
|
102
|
+
continue;
|
|
103
|
+
}
|
|
104
|
+
if (r.code === 0) {
|
|
105
|
+
results.push(`✓ ${c.name}`);
|
|
106
|
+
}
|
|
107
|
+
else {
|
|
108
|
+
results.push(`✗ ${c.name} (exit ${r.code})`);
|
|
109
|
+
const out = tail(r.stdout + "\n" + r.stderr, 20);
|
|
110
|
+
failures.push(`── ${c.name} (${pm} run ${c.script}) ──\n${out}`);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
const head = `${root.split("/").pop()}: ${results.join(" ")}`;
|
|
114
|
+
return failures.length ? `${head}\n\n${failures.join("\n\n")}` : head;
|
|
115
|
+
},
|
|
116
|
+
};
|
|
117
|
+
//# sourceMappingURL=run_checks.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"run_checks.js","sourceRoot":"","sources":["../../src/tools/run_checks.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* scheduled_dispatch (vibe-coding) — schedule an agent to run a task on a
|
|
3
|
+
* recurring basis: "every night triage the issue backlog", "every 2h sync the
|
|
4
|
+
* docs". Entries are stored and fired by the heartbeat at its cadence.
|
|
5
|
+
*
|
|
6
|
+
* SAFETY: this auto-launches an autonomous agent unattended (no approval at
|
|
7
|
+
* fire time, like any heartbeat action). Each entry has a maxRuns cap (default
|
|
8
|
+
* 30) so a forgotten schedule can't run forever. Needs the heartbeat installed
|
|
9
|
+
* (`lisa heartbeat install`) to actually fire.
|
|
10
|
+
*/
|
|
11
|
+
import type { ToolDefinition } from "../types.js";
|
|
12
|
+
import { type ScheduledAgent } from "../integrations/scheduled-dispatch.js";
|
|
13
|
+
interface ScheduledDispatchInput {
|
|
14
|
+
action: "add" | "list" | "remove";
|
|
15
|
+
agent?: ScheduledAgent;
|
|
16
|
+
task?: string;
|
|
17
|
+
cwd?: string;
|
|
18
|
+
/** "every:30m" | "every:2h" | "every:1d" | "daily:09:00" */
|
|
19
|
+
schedule?: string;
|
|
20
|
+
/** Max times to fire before going inert. Default 30. */
|
|
21
|
+
max_runs?: number;
|
|
22
|
+
/** For remove: the entry id (or prefix). */
|
|
23
|
+
id?: string;
|
|
24
|
+
}
|
|
25
|
+
export declare const scheduledDispatchTool: ToolDefinition<ScheduledDispatchInput, string>;
|
|
26
|
+
export {};
|
|
27
|
+
//# sourceMappingURL=scheduled_dispatch.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scheduled_dispatch.d.ts","sourceRoot":"","sources":["../../src/tools/scheduled_dispatch.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAClD,OAAO,EAOL,KAAK,cAAc,EACpB,MAAM,uCAAuC,CAAC;AAE/C,UAAU,sBAAsB;IAC9B,MAAM,EAAE,KAAK,GAAG,MAAM,GAAG,QAAQ,CAAC;IAClC,KAAK,CAAC,EAAE,cAAc,CAAC;IACvB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,4DAA4D;IAC5D,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,wDAAwD;IACxD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,4CAA4C;IAC5C,EAAE,CAAC,EAAE,MAAM,CAAC;CACb;AAED,eAAO,MAAM,qBAAqB,EAAE,cAAc,CAAC,sBAAsB,EAAE,MAAM,CA0DhF,CAAC"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { loadScheduled, addScheduled, removeScheduled, isValidSchedule, describeScheduled, DEFAULT_MAX_RUNS, } from "../integrations/scheduled-dispatch.js";
|
|
2
|
+
export const scheduledDispatchTool = {
|
|
3
|
+
name: "scheduled_dispatch",
|
|
4
|
+
description: "Schedule a CLI agent to run a task recurringly (fired by the heartbeat). action:'add' needs " +
|
|
5
|
+
"agent + task + cwd + schedule ('every:30m'/'every:2h'/'every:1d'/'daily:09:00'); 'list' shows " +
|
|
6
|
+
"scheduled dispatches; 'remove' (needs id) deletes one. Use for standing autonomous work like " +
|
|
7
|
+
"nightly issue triage or periodic doc sync. It auto-launches an agent unattended, so it has a " +
|
|
8
|
+
"maxRuns cap (default 30) and needs `lisa heartbeat install` to fire.",
|
|
9
|
+
inputSchema: {
|
|
10
|
+
type: "object",
|
|
11
|
+
properties: {
|
|
12
|
+
action: { type: "string", enum: ["add", "list", "remove"] },
|
|
13
|
+
agent: { type: "string", enum: ["claude", "codex", "opencode", "aider"], description: "Which agent to launch (for add)." },
|
|
14
|
+
task: { type: "string", description: "Task/prompt for the agent (for add).", minLength: 1 },
|
|
15
|
+
cwd: { type: "string", description: "Absolute working directory (for add). Defaults to the current directory." },
|
|
16
|
+
schedule: { type: "string", description: "every:30m | every:2h | every:1d | daily:HH:MM (for add)." },
|
|
17
|
+
max_runs: { type: "integer", minimum: 1, maximum: 1000, description: `Max fires before inert (default ${DEFAULT_MAX_RUNS}).` },
|
|
18
|
+
id: { type: "string", description: "Entry id or prefix (for remove)." },
|
|
19
|
+
},
|
|
20
|
+
required: ["action"],
|
|
21
|
+
additionalProperties: false,
|
|
22
|
+
},
|
|
23
|
+
async execute(input, ctx) {
|
|
24
|
+
if (input.action === "list") {
|
|
25
|
+
const entries = await loadScheduled();
|
|
26
|
+
if (entries.length === 0)
|
|
27
|
+
return "(no scheduled dispatches)";
|
|
28
|
+
return `${entries.length} scheduled dispatch(es):\n` + entries.map(describeScheduled).join("\n");
|
|
29
|
+
}
|
|
30
|
+
if (input.action === "remove") {
|
|
31
|
+
if (!input.id)
|
|
32
|
+
return "(remove needs an id — from scheduled_dispatch action:'list')";
|
|
33
|
+
const ok = await removeScheduled(input.id);
|
|
34
|
+
return ok ? `Removed scheduled dispatch ${input.id}.` : `(no scheduled dispatch matches "${input.id}")`;
|
|
35
|
+
}
|
|
36
|
+
// add
|
|
37
|
+
if (!input.agent || !input.task || !input.schedule) {
|
|
38
|
+
return "(add needs agent, task and schedule)";
|
|
39
|
+
}
|
|
40
|
+
if (!isValidSchedule(input.schedule)) {
|
|
41
|
+
return `(bad schedule "${input.schedule}" — use every:30m / every:2h / every:1d / daily:09:00)`;
|
|
42
|
+
}
|
|
43
|
+
const cwd = input.cwd && input.cwd.startsWith("/") ? input.cwd : ctx.cwd;
|
|
44
|
+
const entry = await addScheduled({
|
|
45
|
+
agent: input.agent,
|
|
46
|
+
task: input.task,
|
|
47
|
+
cwd,
|
|
48
|
+
schedule: input.schedule,
|
|
49
|
+
maxRuns: input.max_runs ?? DEFAULT_MAX_RUNS,
|
|
50
|
+
});
|
|
51
|
+
const heartbeatNote = "\n(Fires via the heartbeat — if you haven't, run `lisa heartbeat install` so it actually ticks.)";
|
|
52
|
+
return (`Scheduled ${entry.agent} ${entry.schedule} in ${cwd} (id ${entry.id}, max ${entry.maxRuns} runs):\n` +
|
|
53
|
+
` "${input.task.slice(0, 100)}"` +
|
|
54
|
+
heartbeatNote);
|
|
55
|
+
},
|
|
56
|
+
};
|
|
57
|
+
//# sourceMappingURL=scheduled_dispatch.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scheduled_dispatch.js","sourceRoot":"","sources":["../../src/tools/scheduled_dispatch.ts"],"names":[],"mappings":"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"}
|