@damian87/omp 0.12.0 → 0.14.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/.github/skills/schedule/SKILL.md +27 -2
- package/.github/skills/verify-byok/SKILL.md +50 -0
- package/README.md +88 -4
- package/catalog/capabilities.json +23 -0
- package/catalog/skills-general.json +25 -0
- package/dist/src/cli.js +158 -5
- package/dist/src/cli.js.map +1 -1
- package/dist/src/commands/comms.d.ts +2 -0
- package/dist/src/commands/comms.js +110 -0
- package/dist/src/commands/comms.js.map +1 -0
- package/dist/src/commands/council.d.ts +2 -0
- package/dist/src/commands/council.js +77 -0
- package/dist/src/commands/council.js.map +1 -0
- package/dist/src/commands/env.d.ts +2 -0
- package/dist/src/commands/env.js +95 -0
- package/dist/src/commands/env.js.map +1 -0
- package/dist/src/commands/gateway.d.ts +3 -0
- package/dist/src/commands/gateway.js +129 -0
- package/dist/src/commands/gateway.js.map +1 -0
- package/dist/src/commands/memory.d.ts +7 -0
- package/dist/src/commands/memory.js +202 -0
- package/dist/src/commands/memory.js.map +1 -0
- package/dist/src/commands/mode.d.ts +4 -0
- package/dist/src/commands/mode.js +119 -0
- package/dist/src/commands/mode.js.map +1 -0
- package/dist/src/commands/schedule.d.ts +2 -0
- package/dist/src/commands/schedule.js +91 -0
- package/dist/src/commands/schedule.js.map +1 -0
- package/dist/src/commands/team.d.ts +2 -0
- package/dist/src/commands/team.js +146 -0
- package/dist/src/commands/team.js.map +1 -0
- package/dist/src/commands/utils.d.ts +13 -0
- package/dist/src/commands/utils.js +68 -0
- package/dist/src/commands/utils.js.map +1 -0
- package/dist/src/gateway/desktop-notify.d.ts +56 -0
- package/dist/src/gateway/desktop-notify.js +183 -0
- package/dist/src/gateway/desktop-notify.js.map +1 -0
- package/dist/src/goal.js +6 -8
- package/dist/src/goal.js.map +1 -1
- package/dist/src/instructions-memory.js +26 -3
- package/dist/src/instructions-memory.js.map +1 -1
- package/dist/src/memory-review/apply.d.ts +7 -0
- package/dist/src/memory-review/apply.js +75 -0
- package/dist/src/memory-review/apply.js.map +1 -0
- package/dist/src/memory-review/config.d.ts +22 -0
- package/dist/src/memory-review/config.js +54 -0
- package/dist/src/memory-review/config.js.map +1 -0
- package/dist/src/memory-review/guard.d.ts +5 -0
- package/dist/src/memory-review/guard.js +37 -0
- package/dist/src/memory-review/guard.js.map +1 -0
- package/dist/src/memory-review/index.d.ts +17 -0
- package/dist/src/memory-review/index.js +87 -0
- package/dist/src/memory-review/index.js.map +1 -0
- package/dist/src/memory-review/prompt.d.ts +18 -0
- package/dist/src/memory-review/prompt.js +89 -0
- package/dist/src/memory-review/prompt.js.map +1 -0
- package/dist/src/memory-review/spawn.d.ts +2 -0
- package/dist/src/memory-review/spawn.js +51 -0
- package/dist/src/memory-review/spawn.js.map +1 -0
- package/dist/src/memory-review/transcript.d.ts +24 -0
- package/dist/src/memory-review/transcript.js +212 -0
- package/dist/src/memory-review/transcript.js.map +1 -0
- package/dist/src/memory-review/trigger.d.ts +21 -0
- package/dist/src/memory-review/trigger.js +27 -0
- package/dist/src/memory-review/trigger.js.map +1 -0
- package/dist/src/project-memory.d.ts +9 -0
- package/dist/src/project-memory.js +72 -1
- package/dist/src/project-memory.js.map +1 -1
- package/dist/src/schedule/commands.d.ts +13 -0
- package/dist/src/schedule/commands.js +24 -1
- package/dist/src/schedule/commands.js.map +1 -1
- package/dist/src/schedule/deep-link.d.ts +18 -0
- package/dist/src/schedule/deep-link.js +41 -0
- package/dist/src/schedule/deep-link.js.map +1 -0
- package/dist/src/schedule/runner.d.ts +10 -0
- package/dist/src/schedule/runner.js +36 -0
- package/dist/src/schedule/runner.js.map +1 -1
- package/dist/src/schedule/types.d.ts +16 -0
- package/dist/src/state.js +25 -37
- package/dist/src/state.js.map +1 -1
- package/dist/src/utils/fs.d.ts +14 -0
- package/dist/src/utils/fs.js +32 -0
- package/dist/src/utils/fs.js.map +1 -0
- package/dist/src/utils/paths.d.ts +14 -0
- package/dist/src/utils/paths.js +21 -0
- package/dist/src/utils/paths.js.map +1 -0
- package/docs/memory-mode.md +94 -0
- package/docs/research/2026-06-22-schedule-desktop-notifications.md +193 -0
- package/package.json +4 -2
- package/plugin.json +1 -1
- package/scripts/lib/memory-review-trigger.mjs +59 -0
- package/scripts/lib/pending-directives.mjs +36 -0
- package/scripts/session-end.mjs +8 -0
- package/scripts/session-start.mjs +4 -0
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { flagValue, hasFlag, parsePositiveIntFlag } from "./utils.js";
|
|
2
|
+
export async function handleSchedule(argv) {
|
|
3
|
+
const [, command, value] = argv;
|
|
4
|
+
const json = hasFlag(argv, "--json");
|
|
5
|
+
const cwd = flagValue(argv, "--root") ?? process.cwd();
|
|
6
|
+
// The OS scheduler invokes `omp schedule run --id <id> --root <dir>`, so prefer
|
|
7
|
+
// the --id flag; fall back to the positional form for human-typed commands.
|
|
8
|
+
const targetId = flagValue(argv, "--id") ?? (value && !value.startsWith("--") ? value : undefined);
|
|
9
|
+
const mod = await import("../schedule/commands.js");
|
|
10
|
+
if (command === "add") {
|
|
11
|
+
const id = flagValue(argv, "--id");
|
|
12
|
+
const cron = flagValue(argv, "--cron");
|
|
13
|
+
const prompt = flagValue(argv, "--prompt");
|
|
14
|
+
if (!id || !cron || !prompt) {
|
|
15
|
+
return { ok: false, exitCode: 1, message: 'schedule add requires --id, --cron, and --prompt' };
|
|
16
|
+
}
|
|
17
|
+
let timeoutMs;
|
|
18
|
+
let maxRuns;
|
|
19
|
+
let ttlHours;
|
|
20
|
+
try {
|
|
21
|
+
timeoutMs = parsePositiveIntFlag(flagValue(argv, "--timeout"), "--timeout");
|
|
22
|
+
maxRuns = parsePositiveIntFlag(flagValue(argv, "--max-runs"), "--max-runs");
|
|
23
|
+
ttlHours = parsePositiveIntFlag(flagValue(argv, "--ttl-hours"), "--ttl-hours");
|
|
24
|
+
}
|
|
25
|
+
catch (err) {
|
|
26
|
+
return { ok: false, exitCode: 1, message: String(err instanceof Error ? err.message : err) };
|
|
27
|
+
}
|
|
28
|
+
const notifyTarget = flagValue(argv, "--notify-target");
|
|
29
|
+
if (notifyTarget) {
|
|
30
|
+
const { parseTarget } = await import("../gateway/target-parser.js");
|
|
31
|
+
const parsed = parseTarget(notifyTarget);
|
|
32
|
+
if (!parsed.ok) {
|
|
33
|
+
return { ok: false, exitCode: 1, message: `--notify-target: ${parsed.error}` };
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
const result = mod.addScheduleJob(cwd, {
|
|
37
|
+
id,
|
|
38
|
+
cron,
|
|
39
|
+
prompt,
|
|
40
|
+
bin: flagValue(argv, "--bin"),
|
|
41
|
+
model: flagValue(argv, "--model"),
|
|
42
|
+
cwd: flagValue(argv, "--cwd"),
|
|
43
|
+
timeoutMs,
|
|
44
|
+
maxRuns,
|
|
45
|
+
ttlHours,
|
|
46
|
+
allowAllTools: hasFlag(argv, "--allow-all-tools"),
|
|
47
|
+
dryRun: hasFlag(argv, "--dry-run"),
|
|
48
|
+
notifyTarget,
|
|
49
|
+
});
|
|
50
|
+
return json
|
|
51
|
+
? { ok: result.ok, exitCode: result.ok ? 0 : 1, output: result }
|
|
52
|
+
: { ok: result.ok, exitCode: result.ok ? 0 : 1, message: result.ok ? result.messages.join("\n") : (result.error ?? "schedule add failed") };
|
|
53
|
+
}
|
|
54
|
+
if (command === "list") {
|
|
55
|
+
const jobs = mod.listScheduleJobs(cwd);
|
|
56
|
+
return json
|
|
57
|
+
? { ok: true, output: jobs }
|
|
58
|
+
: {
|
|
59
|
+
ok: true,
|
|
60
|
+
message: jobs.length
|
|
61
|
+
? jobs.map((j) => `${j.id}\t${j.cron}\t${j.backend}\tinstalled=${j.osInstalled}\tlast=${j.lastStatus ?? "-"}`).join("\n")
|
|
62
|
+
: "(no scheduled jobs)",
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
if (command === "status" && targetId) {
|
|
66
|
+
const st = mod.getScheduleStatus(cwd, targetId);
|
|
67
|
+
if (!st.job)
|
|
68
|
+
return { ok: false, exitCode: 1, output: json ? st : undefined, message: `no schedule job "${targetId}"` };
|
|
69
|
+
return json
|
|
70
|
+
? { ok: true, output: st }
|
|
71
|
+
: { ok: true, message: `${st.job.id} cron=${st.job.cron} backend=${st.job.backend} installed=${st.osInstalled} runs=${st.job.runCount} last=${st.job.lastStatus ?? "-"}` };
|
|
72
|
+
}
|
|
73
|
+
if (command === "remove" && targetId) {
|
|
74
|
+
const result = mod.removeScheduleJob(cwd, targetId);
|
|
75
|
+
return json
|
|
76
|
+
? { ok: result.removed, exitCode: result.removed ? 0 : 1, output: result }
|
|
77
|
+
: { ok: result.removed, exitCode: result.removed ? 0 : 1, message: result.removed ? `removed "${targetId}"` : `no schedule job "${targetId}"` };
|
|
78
|
+
}
|
|
79
|
+
if ((command === "run" || command === "run-now") && targetId) {
|
|
80
|
+
const result = await mod.runScheduleById(cwd, targetId);
|
|
81
|
+
return json
|
|
82
|
+
? { ok: result.ok, exitCode: result.ok ? 0 : 1, output: result }
|
|
83
|
+
: { ok: result.ok, exitCode: result.ok ? 0 : 1, message: result.message };
|
|
84
|
+
}
|
|
85
|
+
return {
|
|
86
|
+
ok: false,
|
|
87
|
+
exitCode: 1,
|
|
88
|
+
message: 'Unknown schedule subcommand. Try: schedule add --id <id> --cron "<expr>" --prompt "<text>" | list | status <id> | remove <id> | run-now <id>',
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
//# sourceMappingURL=schedule.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schedule.js","sourceRoot":"","sources":["../../../src/commands/schedule.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
import { flagValue, hasFlag, parsePositiveIntFlag } from "./utils.js";
|
|
2
|
+
const TEAM_SPEC_RE = /^(\d+):([\w-]+)$/;
|
|
3
|
+
export async function handleTeam(argv) {
|
|
4
|
+
const [, command, value, extra] = argv;
|
|
5
|
+
const json = hasFlag(argv, "--json");
|
|
6
|
+
const cwd = flagValue(argv, "--root") ?? process.cwd();
|
|
7
|
+
if (command && TEAM_SPEC_RE.test(command)) {
|
|
8
|
+
const match = command.match(TEAM_SPEC_RE);
|
|
9
|
+
const workerCount = Number(match[1]);
|
|
10
|
+
const role = match[2];
|
|
11
|
+
if (!value) {
|
|
12
|
+
return { ok: false, exitCode: 1, message: "team <N:role> requires a task description" };
|
|
13
|
+
}
|
|
14
|
+
const name = flagValue(argv, "--name") ?? `${role}-${Date.now().toString(36)}`;
|
|
15
|
+
const { startTeam } = await import("../team/runtime.js");
|
|
16
|
+
try {
|
|
17
|
+
const result = await startTeam({ cwd, name, role, workerCount, task: value });
|
|
18
|
+
return json
|
|
19
|
+
? { ok: true, output: result }
|
|
20
|
+
: {
|
|
21
|
+
ok: true,
|
|
22
|
+
message: `started team ${name} session=${result.tmuxSession} workers=${result.config.workers
|
|
23
|
+
.map((w) => `${w.name}(${w.paneId ?? "?"})`)
|
|
24
|
+
.join(",")}`,
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
catch (error) {
|
|
28
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
29
|
+
return { ok: false, exitCode: 1, output: json ? { ok: false, error: message } : undefined, message };
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
if (command === "status" && value) {
|
|
33
|
+
const { statusTeam, formatStatus } = await import("../team/runtime.js");
|
|
34
|
+
const report = statusTeam({ cwd, name: value });
|
|
35
|
+
return json
|
|
36
|
+
? { ok: report.ok, output: report }
|
|
37
|
+
: { ok: report.ok, message: formatStatus(report) };
|
|
38
|
+
}
|
|
39
|
+
if (command === "shutdown" && value) {
|
|
40
|
+
const { shutdownTeam } = await import("../team/runtime.js");
|
|
41
|
+
const result = await shutdownTeam({ cwd, name: value });
|
|
42
|
+
return json
|
|
43
|
+
? { ok: result.ok, output: result }
|
|
44
|
+
: {
|
|
45
|
+
ok: result.ok,
|
|
46
|
+
message: `shutdown team ${value} killedPanes=${result.killedPanes} killedSession=${result.killedSession}`,
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
if (command === "monitor-panes") {
|
|
50
|
+
const leaderPaneId = flagValue(argv, "--leader-pane");
|
|
51
|
+
const workerPaneIds = argv
|
|
52
|
+
.flatMap((arg, index) => (arg === "--worker-pane" ? [argv[index + 1]] : []))
|
|
53
|
+
.filter((value) => Boolean(value));
|
|
54
|
+
if (!leaderPaneId || workerPaneIds.length === 0) {
|
|
55
|
+
return { ok: false, exitCode: 1, message: "team monitor-panes requires --leader-pane and at least one --worker-pane" };
|
|
56
|
+
}
|
|
57
|
+
let pollIntervalMs;
|
|
58
|
+
let readySamples;
|
|
59
|
+
let minObservationMs;
|
|
60
|
+
let timeoutMs;
|
|
61
|
+
let captureLines;
|
|
62
|
+
try {
|
|
63
|
+
pollIntervalMs = parsePositiveIntFlag(flagValue(argv, "--poll-interval-ms"), "--poll-interval-ms");
|
|
64
|
+
readySamples = parsePositiveIntFlag(flagValue(argv, "--ready-samples"), "--ready-samples");
|
|
65
|
+
minObservationMs = parsePositiveIntFlag(flagValue(argv, "--min-observation-ms"), "--min-observation-ms");
|
|
66
|
+
timeoutMs = parsePositiveIntFlag(flagValue(argv, "--timeout-ms"), "--timeout-ms");
|
|
67
|
+
captureLines = parsePositiveIntFlag(flagValue(argv, "--capture-lines"), "--capture-lines");
|
|
68
|
+
}
|
|
69
|
+
catch (err) {
|
|
70
|
+
return { ok: false, exitCode: 1, message: String(err instanceof Error ? err.message : err) };
|
|
71
|
+
}
|
|
72
|
+
const { monitorPanes } = await import("../team/pane-monitor.js");
|
|
73
|
+
const result = await monitorPanes({
|
|
74
|
+
leaderPaneId,
|
|
75
|
+
workerPaneIds,
|
|
76
|
+
sessionLabel: flagValue(argv, "--session-label"),
|
|
77
|
+
config: {
|
|
78
|
+
pollIntervalMs,
|
|
79
|
+
readySamples,
|
|
80
|
+
minObservationMs,
|
|
81
|
+
timeoutMs,
|
|
82
|
+
captureLines,
|
|
83
|
+
},
|
|
84
|
+
});
|
|
85
|
+
return json
|
|
86
|
+
? { ok: result.ok, exitCode: result.ok ? 0 : 1, output: result }
|
|
87
|
+
: { ok: result.ok, exitCode: result.ok ? 0 : 1, message: `team monitor-panes ${result.reason} events=${result.events.length}` };
|
|
88
|
+
}
|
|
89
|
+
if (command === "api") {
|
|
90
|
+
const sub = value;
|
|
91
|
+
const inputRaw = flagValue(argv, "--input");
|
|
92
|
+
if (!sub || !inputRaw) {
|
|
93
|
+
return { ok: false, exitCode: 1, message: "team api <sub> --input '<json>' required" };
|
|
94
|
+
}
|
|
95
|
+
let input;
|
|
96
|
+
try {
|
|
97
|
+
input = JSON.parse(inputRaw);
|
|
98
|
+
}
|
|
99
|
+
catch (error) {
|
|
100
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
101
|
+
return { ok: false, exitCode: 1, message: `invalid --input JSON: ${message}` };
|
|
102
|
+
}
|
|
103
|
+
const api = await import("../team/api.js");
|
|
104
|
+
if (sub === "claim-task") {
|
|
105
|
+
const result = api.apiClaimTask(input);
|
|
106
|
+
return json
|
|
107
|
+
? { ok: result.ok, exitCode: result.ok ? 0 : 1, output: result }
|
|
108
|
+
: { ok: result.ok, exitCode: result.ok ? 0 : 1, message: JSON.stringify(result) };
|
|
109
|
+
}
|
|
110
|
+
if (sub === "transition-task-status") {
|
|
111
|
+
const result = api.apiTransitionTaskStatus(input);
|
|
112
|
+
return json
|
|
113
|
+
? { ok: result.ok, exitCode: result.ok ? 0 : 1, output: result }
|
|
114
|
+
: { ok: result.ok, exitCode: result.ok ? 0 : 1, message: JSON.stringify(result) };
|
|
115
|
+
}
|
|
116
|
+
if (sub === "send-message") {
|
|
117
|
+
const result = await api.apiSendMessage(input);
|
|
118
|
+
return json
|
|
119
|
+
? { ok: result.ok, exitCode: result.ok ? 0 : 1, output: result }
|
|
120
|
+
: { ok: result.ok, exitCode: result.ok ? 0 : 1, message: JSON.stringify(result) };
|
|
121
|
+
}
|
|
122
|
+
if (sub === "broadcast") {
|
|
123
|
+
const result = await api.apiBroadcast(input);
|
|
124
|
+
return json
|
|
125
|
+
? { ok: result.ok, exitCode: result.ok ? 0 : 1, output: result }
|
|
126
|
+
: { ok: result.ok, exitCode: result.ok ? 0 : 1, message: JSON.stringify(result) };
|
|
127
|
+
}
|
|
128
|
+
if (sub === "mailbox-list") {
|
|
129
|
+
const result = api.apiMailboxList(input);
|
|
130
|
+
return json
|
|
131
|
+
? { ok: result.ok, exitCode: result.ok ? 0 : 1, output: result }
|
|
132
|
+
: { ok: result.ok, exitCode: result.ok ? 0 : 1, message: JSON.stringify(result) };
|
|
133
|
+
}
|
|
134
|
+
if (sub === "mailbox-mark-delivered") {
|
|
135
|
+
const result = api.apiMailboxMarkDelivered(input);
|
|
136
|
+
return json
|
|
137
|
+
? { ok: result.ok, exitCode: result.ok ? 0 : 1, output: result }
|
|
138
|
+
: { ok: result.ok, exitCode: result.ok ? 0 : 1, message: JSON.stringify(result) };
|
|
139
|
+
}
|
|
140
|
+
return { ok: false, exitCode: 1, message: `Unknown team api command: ${sub}` };
|
|
141
|
+
}
|
|
142
|
+
// tolerate trailing extras (e.g., '--json')
|
|
143
|
+
void extra;
|
|
144
|
+
return { ok: false, exitCode: 1, message: `Unknown team command. Try: omp team <N:role> "<task>" | status <name> | shutdown <name> | api <sub>` };
|
|
145
|
+
}
|
|
146
|
+
//# sourceMappingURL=team.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"team.js","sourceRoot":"","sources":["../../../src/commands/team.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AAEtE,MAAM,YAAY,GAAG,kBAAkB,CAAC;AAExC,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,IAAc;IAC7C,MAAM,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,CAAC,GAAG,IAAI,CAAC;IACvC,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;IACrC,MAAM,GAAG,GAAG,SAAS,CAAC,IAAI,EAAE,QAAQ,CAAC,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC;IAEvD,IAAI,OAAO,IAAI,YAAY,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;QAC1C,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,YAAY,CAAE,CAAC;QAC3C,MAAM,WAAW,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;QACrC,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAE,CAAC;QACvB,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,EAAE,OAAO,EAAE,2CAA2C,EAAE,CAAC;QAC1F,CAAC;QACD,MAAM,IAAI,GAAG,SAAS,CAAC,IAAI,EAAE,QAAQ,CAAC,IAAI,GAAG,IAAI,IAAI,IAAI,CAAC,GAAG,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,EAAE,CAAC;QAC/E,MAAM,EAAE,SAAS,EAAE,GAAG,MAAM,MAAM,CAAC,oBAAoB,CAAC,CAAC;QACzD,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,SAAS,CAAC,EAAE,GAAG,EAAE,IAAI,EAAE,IAAI,EAAE,WAAW,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;YAC9E,OAAO,IAAI;gBACT,CAAC,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE;gBAC9B,CAAC,CAAC;oBACE,EAAE,EAAE,IAAI;oBACR,OAAO,EAAE,gBAAgB,IAAI,YAAY,MAAM,CAAC,WAAW,YAAY,MAAM,CAAC,MAAM,CAAC,OAAO;yBACzF,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,MAAM,IAAI,GAAG,GAAG,CAAC;yBAC3C,IAAI,CAAC,GAAG,CAAC,EAAE;iBACf,CAAC;QACR,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YACvE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC,SAAS,EAAE,OAAO,EAAE,CAAC;QACvG,CAAC;IACH,CAAC;IAED,IAAI,OAAO,KAAK,QAAQ,IAAI,KAAK,EAAE,CAAC;QAClC,MAAM,EAAE,UAAU,EAAE,YAAY,EAAE,GAAG,MAAM,MAAM,CAAC,oBAAoB,CAAC,CAAC;QACxE,MAAM,MAAM,GAAG,UAAU,CAAC,EAAE,GAAG,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;QAChD,OAAO,IAAI;YACT,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE;YACnC,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,CAAC,EAAE,EAAE,OAAO,EAAE,YAAY,CAAC,MAAM,CAAC,EAAE,CAAC;IACvD,CAAC;IAED,IAAI,OAAO,KAAK,UAAU,IAAI,KAAK,EAAE,CAAC;QACpC,MAAM,EAAE,YAAY,EAAE,GAAG,MAAM,MAAM,CAAC,oBAAoB,CAAC,CAAC;QAC5D,MAAM,MAAM,GAAG,MAAM,YAAY,CAAC,EAAE,GAAG,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;QACxD,OAAO,IAAI;YACT,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE;YACnC,CAAC,CAAC;gBACE,EAAE,EAAE,MAAM,CAAC,EAAE;gBACb,OAAO,EAAE,iBAAiB,KAAK,gBAAgB,MAAM,CAAC,WAAW,kBAAkB,MAAM,CAAC,aAAa,EAAE;aAC1G,CAAC;IACR,CAAC;IAED,IAAI,OAAO,KAAK,eAAe,EAAE,CAAC;QAChC,MAAM,YAAY,GAAG,SAAS,CAAC,IAAI,EAAE,eAAe,CAAC,CAAC;QACtD,MAAM,aAAa,GAAG,IAAI;aACvB,OAAO,CAAC,CAAC,GAAG,EAAE,KAAK,EAAE,EAAE,CAAC,CAAC,GAAG,KAAK,eAAe,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;aAC3E,MAAM,CAAC,CAAC,KAAK,EAAmB,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC;QACtD,IAAI,CAAC,YAAY,IAAI,aAAa,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAChD,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,EAAE,OAAO,EAAE,0EAA0E,EAAE,CAAC;QACzH,CAAC;QACD,IAAI,cAAkC,CAAC;QACvC,IAAI,YAAgC,CAAC;QACrC,IAAI,gBAAoC,CAAC;QACzC,IAAI,SAA6B,CAAC;QAClC,IAAI,YAAgC,CAAC;QACrC,IAAI,CAAC;YACH,cAAc,GAAG,oBAAoB,CAAC,SAAS,CAAC,IAAI,EAAE,oBAAoB,CAAC,EAAE,oBAAoB,CAAC,CAAC;YACnG,YAAY,GAAG,oBAAoB,CAAC,SAAS,CAAC,IAAI,EAAE,iBAAiB,CAAC,EAAE,iBAAiB,CAAC,CAAC;YAC3F,gBAAgB,GAAG,oBAAoB,CAAC,SAAS,CAAC,IAAI,EAAE,sBAAsB,CAAC,EAAE,sBAAsB,CAAC,CAAC;YACzG,SAAS,GAAG,oBAAoB,CAAC,SAAS,CAAC,IAAI,EAAE,cAAc,CAAC,EAAE,cAAc,CAAC,CAAC;YAClF,YAAY,GAAG,oBAAoB,CAAC,SAAS,CAAC,IAAI,EAAE,iBAAiB,CAAC,EAAE,iBAAiB,CAAC,CAAC;QAC7F,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,EAAE,OAAO,EAAE,MAAM,CAAC,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC;QAC/F,CAAC;QACD,MAAM,EAAE,YAAY,EAAE,GAAG,MAAM,MAAM,CAAC,yBAAyB,CAAC,CAAC;QACjE,MAAM,MAAM,GAAG,MAAM,YAAY,CAAC;YAChC,YAAY;YACZ,aAAa;YACb,YAAY,EAAE,SAAS,CAAC,IAAI,EAAE,iBAAiB,CAAC;YAChD,MAAM,EAAE;gBACN,cAAc;gBACd,YAAY;gBACZ,gBAAgB;gBAChB,SAAS;gBACT,YAAY;aACb;SACF,CAAC,CAAC;QACH,OAAO,IAAI;YACT,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,CAAC,EAAE,EAAE,QAAQ,EAAE,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE;YAChE,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,CAAC,EAAE,EAAE,QAAQ,EAAE,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,sBAAsB,MAAM,CAAC,MAAM,WAAW,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,EAAE,CAAC;IACpI,CAAC;IAED,IAAI,OAAO,KAAK,KAAK,EAAE,CAAC;QACtB,MAAM,GAAG,GAAG,KAAK,CAAC;QAClB,MAAM,QAAQ,GAAG,SAAS,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC;QAC5C,IAAI,CAAC,GAAG,IAAI,CAAC,QAAQ,EAAE,CAAC;YACtB,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,EAAE,OAAO,EAAE,0CAA0C,EAAE,CAAC;QACzF,CAAC;QACD,IAAI,KAA8B,CAAC;QACnC,IAAI,CAAC;YACH,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,QAAQ,CAA4B,CAAC;QAC1D,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YACvE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,EAAE,OAAO,EAAE,yBAAyB,OAAO,EAAE,EAAE,CAAC;QACjF,CAAC;QACD,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,gBAAgB,CAAC,CAAC;QAC3C,IAAI,GAAG,KAAK,YAAY,EAAE,CAAC;YACzB,MAAM,MAAM,GAAG,GAAG,CAAC,YAAY,CAAC,KAAc,CAAC,CAAC;YAChD,OAAO,IAAI;gBACT,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,CAAC,EAAE,EAAE,QAAQ,EAAE,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE;gBAChE,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,CAAC,EAAE,EAAE,QAAQ,EAAE,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,EAAE,CAAC;QACtF,CAAC;QACD,IAAI,GAAG,KAAK,wBAAwB,EAAE,CAAC;YACrC,MAAM,MAAM,GAAG,GAAG,CAAC,uBAAuB,CAAC,KAAc,CAAC,CAAC;YAC3D,OAAO,IAAI;gBACT,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,CAAC,EAAE,EAAE,QAAQ,EAAE,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE;gBAChE,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,CAAC,EAAE,EAAE,QAAQ,EAAE,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,EAAE,CAAC;QACtF,CAAC;QACD,IAAI,GAAG,KAAK,cAAc,EAAE,CAAC;YAC3B,MAAM,MAAM,GAAG,MAAM,GAAG,CAAC,cAAc,CAAC,KAAc,CAAC,CAAC;YACxD,OAAO,IAAI;gBACT,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,CAAC,EAAE,EAAE,QAAQ,EAAE,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE;gBAChE,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,CAAC,EAAE,EAAE,QAAQ,EAAE,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,EAAE,CAAC;QACtF,CAAC;QACD,IAAI,GAAG,KAAK,WAAW,EAAE,CAAC;YACxB,MAAM,MAAM,GAAG,MAAM,GAAG,CAAC,YAAY,CAAC,KAAc,CAAC,CAAC;YACtD,OAAO,IAAI;gBACT,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,CAAC,EAAE,EAAE,QAAQ,EAAE,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE;gBAChE,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,CAAC,EAAE,EAAE,QAAQ,EAAE,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,EAAE,CAAC;QACtF,CAAC;QACD,IAAI,GAAG,KAAK,cAAc,EAAE,CAAC;YAC3B,MAAM,MAAM,GAAG,GAAG,CAAC,cAAc,CAAC,KAAc,CAAC,CAAC;YAClD,OAAO,IAAI;gBACT,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,CAAC,EAAE,EAAE,QAAQ,EAAE,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE;gBAChE,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,CAAC,EAAE,EAAE,QAAQ,EAAE,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,EAAE,CAAC;QACtF,CAAC;QACD,IAAI,GAAG,KAAK,wBAAwB,EAAE,CAAC;YACrC,MAAM,MAAM,GAAG,GAAG,CAAC,uBAAuB,CAAC,KAAc,CAAC,CAAC;YAC3D,OAAO,IAAI;gBACT,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,CAAC,EAAE,EAAE,QAAQ,EAAE,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE;gBAChE,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,CAAC,EAAE,EAAE,QAAQ,EAAE,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,EAAE,CAAC;QACtF,CAAC;QACD,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,EAAE,OAAO,EAAE,6BAA6B,GAAG,EAAE,EAAE,CAAC;IACjF,CAAC;IAED,4CAA4C;IAC5C,KAAK,KAAK,CAAC;IACX,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,EAAE,OAAO,EAAE,qGAAqG,EAAE,CAAC;AACpJ,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export declare function hasFlag(args: string[], flag: string): boolean;
|
|
2
|
+
export declare function flagValue(args: string[], flag: string): string | undefined;
|
|
3
|
+
export declare function resolveExistingInputPath(value: string): Promise<string>;
|
|
4
|
+
export declare const DEFAULT_COUNCIL_ROLES: string[];
|
|
5
|
+
/** Parse a --models value: comma-separated `model` or `model:role:weight` tokens. */
|
|
6
|
+
export declare function parseModelsFlag(value: string): {
|
|
7
|
+
model: string;
|
|
8
|
+
role: string;
|
|
9
|
+
weight: number;
|
|
10
|
+
}[];
|
|
11
|
+
/** Parse a numeric flag as a finite positive integer; throw on malformed input. */
|
|
12
|
+
export declare function parsePositiveIntFlag(value: string | undefined, flag: string): number | undefined;
|
|
13
|
+
export declare function readFlagOrFile(value: string | undefined): Promise<string | undefined>;
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
export function hasFlag(args, flag) {
|
|
2
|
+
return args.includes(flag);
|
|
3
|
+
}
|
|
4
|
+
export function flagValue(args, flag) {
|
|
5
|
+
const index = args.indexOf(flag);
|
|
6
|
+
if (index === -1)
|
|
7
|
+
return undefined;
|
|
8
|
+
return args[index + 1];
|
|
9
|
+
}
|
|
10
|
+
export async function resolveExistingInputPath(value) {
|
|
11
|
+
const { existsSync } = await import("node:fs");
|
|
12
|
+
const { isAbsolute, resolve } = await import("node:path");
|
|
13
|
+
const direct = isAbsolute(value) ? value : resolve(process.cwd(), value);
|
|
14
|
+
if (existsSync(direct))
|
|
15
|
+
return direct;
|
|
16
|
+
const parentRelative = isAbsolute(value) ? value : resolve(process.cwd(), "..", value);
|
|
17
|
+
if (existsSync(parentRelative))
|
|
18
|
+
return parentRelative;
|
|
19
|
+
return direct;
|
|
20
|
+
}
|
|
21
|
+
export const DEFAULT_COUNCIL_ROLES = ["critic", "architect", "pragmatist"];
|
|
22
|
+
/** Parse a --models value: comma-separated `model` or `model:role:weight` tokens. */
|
|
23
|
+
export function parseModelsFlag(value) {
|
|
24
|
+
const tokens = value
|
|
25
|
+
.split(",")
|
|
26
|
+
.map((t) => t.trim())
|
|
27
|
+
.filter((t) => t.length > 0);
|
|
28
|
+
if (tokens.length === 0) {
|
|
29
|
+
throw new Error("--models was empty");
|
|
30
|
+
}
|
|
31
|
+
return tokens.map((token, i) => {
|
|
32
|
+
const parts = token.split(":");
|
|
33
|
+
const model = parts[0].trim();
|
|
34
|
+
if (!model)
|
|
35
|
+
throw new Error(`--models token "${token}" has no model`);
|
|
36
|
+
const role = parts[1]?.trim() || DEFAULT_COUNCIL_ROLES[i % DEFAULT_COUNCIL_ROLES.length];
|
|
37
|
+
let weight = 1;
|
|
38
|
+
if (parts[2] !== undefined) {
|
|
39
|
+
const w = Number(parts[2]);
|
|
40
|
+
if (!Number.isFinite(w) || w <= 0) {
|
|
41
|
+
throw new Error(`--models token "${token}" has invalid weight`);
|
|
42
|
+
}
|
|
43
|
+
weight = w;
|
|
44
|
+
}
|
|
45
|
+
return { model, role, weight };
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
/** Parse a numeric flag as a finite positive integer; throw on malformed input. */
|
|
49
|
+
export function parsePositiveIntFlag(value, flag) {
|
|
50
|
+
if (value === undefined)
|
|
51
|
+
return undefined;
|
|
52
|
+
const n = Number(value);
|
|
53
|
+
if (!Number.isFinite(n) || n <= 0 || !Number.isInteger(n)) {
|
|
54
|
+
throw new Error(`Invalid ${flag}: expected a positive integer, got "${value}"`);
|
|
55
|
+
}
|
|
56
|
+
return n;
|
|
57
|
+
}
|
|
58
|
+
export async function readFlagOrFile(value) {
|
|
59
|
+
if (value === undefined)
|
|
60
|
+
return undefined;
|
|
61
|
+
if (value.startsWith("@")) {
|
|
62
|
+
const { readFileSync } = await import("node:fs");
|
|
63
|
+
const path = await resolveExistingInputPath(value.slice(1));
|
|
64
|
+
return readFileSync(path, "utf8");
|
|
65
|
+
}
|
|
66
|
+
return value;
|
|
67
|
+
}
|
|
68
|
+
//# sourceMappingURL=utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../../../src/commands/utils.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
export interface DesktopNotifyOptions {
|
|
2
|
+
title: string;
|
|
3
|
+
message: string;
|
|
4
|
+
/** URL or absolute file path to open when the notification is clicked (click-capable transports only). */
|
|
5
|
+
open?: string;
|
|
6
|
+
}
|
|
7
|
+
/** Resolved, non-empty payload handed to a transport. */
|
|
8
|
+
export interface ResolvedPayload {
|
|
9
|
+
title: string;
|
|
10
|
+
message: string;
|
|
11
|
+
open?: string;
|
|
12
|
+
}
|
|
13
|
+
/** Minimal slice of node-notifier we depend on (also a test seam). */
|
|
14
|
+
export interface Notifier {
|
|
15
|
+
notify(opts: Record<string, unknown>, cb?: (err: Error | null) => void): void;
|
|
16
|
+
}
|
|
17
|
+
/** Low-level command runner (test seam). Never throws; returns the structured result. */
|
|
18
|
+
export type ExecFn = (file: string, args: string[], timeoutMs: number) => Promise<DesktopNotifyResult>;
|
|
19
|
+
/** A delivery transport (test seam — bypasses platform selection entirely). */
|
|
20
|
+
export type Transport = (payload: ResolvedPayload, timeoutMs: number) => Promise<DesktopNotifyResult>;
|
|
21
|
+
export interface DesktopNotifyDeps {
|
|
22
|
+
/** Override env (tests). Defaults to process.env. */
|
|
23
|
+
env?: NodeJS.ProcessEnv;
|
|
24
|
+
/** Override platform (tests). Defaults to process.platform. */
|
|
25
|
+
platform?: NodeJS.Platform;
|
|
26
|
+
/** Max wait for delivery before giving up. Default 15s. */
|
|
27
|
+
timeoutMs?: number;
|
|
28
|
+
/** Inject the full transport (tests) — bypasses platform selection. */
|
|
29
|
+
transport?: Transport;
|
|
30
|
+
/** Inject the command runner (tests) for the macOS transports. */
|
|
31
|
+
exec?: ExecFn;
|
|
32
|
+
/** Inject system-terminal-notifier availability (tests). Defaults to a PATH lookup. */
|
|
33
|
+
hasSystemTerminalNotifier?: boolean;
|
|
34
|
+
/** Inject node-notifier (tests) for the non-macOS transport. */
|
|
35
|
+
notifier?: Notifier;
|
|
36
|
+
}
|
|
37
|
+
export type DesktopNotifyResult = {
|
|
38
|
+
ok: true;
|
|
39
|
+
skipped?: boolean;
|
|
40
|
+
} | {
|
|
41
|
+
ok: false;
|
|
42
|
+
reason: string;
|
|
43
|
+
};
|
|
44
|
+
/**
|
|
45
|
+
* Build the argv for `osascript`. The message/title are passed as `argv` items
|
|
46
|
+
* (via `on run argv`), never interpolated into the AppleScript source, so an
|
|
47
|
+
* arbitrary run summary cannot inject AppleScript.
|
|
48
|
+
*/
|
|
49
|
+
export declare function buildOsascriptArgs(title: string, message: string): string[];
|
|
50
|
+
/**
|
|
51
|
+
* Fire a desktop notification. Library entry point — never throws.
|
|
52
|
+
* Skips silently (ok:true, skipped) when disabled or on a headless host.
|
|
53
|
+
*/
|
|
54
|
+
export declare function notifyDesktop(opts: DesktopNotifyOptions, deps?: DesktopNotifyDeps): Promise<DesktopNotifyResult>;
|
|
55
|
+
/** True only when neither the PATH entry nor its real (symlink-resolved) target is under node_modules. */
|
|
56
|
+
export declare function isSystemNotifierPath(resolved: string, real: string): boolean;
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Native desktop notifier — Hermes-style sibling of gateway/notify.ts. No daemon.
|
|
3
|
+
* Each call is a one-shot, best-effort native OS notification.
|
|
4
|
+
*
|
|
5
|
+
* Platform transports (the bundled node-notifier terminal-notifier does NOT
|
|
6
|
+
* display on modern macOS — it is an unsigned app run from node_modules — so we
|
|
7
|
+
* do not use it there):
|
|
8
|
+
* - macOS: `osascript display notification` by default — the only path that
|
|
9
|
+
* reliably DISPLAYS on macOS Sequoia. It cannot carry a click action. A
|
|
10
|
+
* system `terminal-notifier` (which supports the click `-open` deep-link)
|
|
11
|
+
* is used only when OMP_NOTIFY_USE_TERMINAL_NOTIFIER is set, since it does
|
|
12
|
+
* not display on some Sequoia builds.
|
|
13
|
+
* - Linux/Windows: node-notifier (notify-send / SnoreToast).
|
|
14
|
+
*
|
|
15
|
+
* Contract (mirrors notify.ts): NEVER throws. Returns a structured result so the
|
|
16
|
+
* caller (the schedule runner) can log a dropped notification to stderr without
|
|
17
|
+
* the failure ever propagating into the job result. A bounded timeout means a
|
|
18
|
+
* wedged backend can never hang `omp schedule run`; the osascript/terminal-notifier
|
|
19
|
+
* children are our own and are killed on timeout.
|
|
20
|
+
*/
|
|
21
|
+
import { execFile, execFileSync } from "node:child_process";
|
|
22
|
+
import { realpathSync } from "node:fs";
|
|
23
|
+
/**
|
|
24
|
+
* Bound on how long we wait for delivery (a hung backend must not stall cron).
|
|
25
|
+
* Kept comfortably above node-notifier's own ~10s display timeout so a slow but
|
|
26
|
+
* successful delivery is not misclassified as a timeout.
|
|
27
|
+
*/
|
|
28
|
+
const DEFAULT_TIMEOUT_MS = 15_000;
|
|
29
|
+
/**
|
|
30
|
+
* Build the argv for `osascript`. The message/title are passed as `argv` items
|
|
31
|
+
* (via `on run argv`), never interpolated into the AppleScript source, so an
|
|
32
|
+
* arbitrary run summary cannot inject AppleScript.
|
|
33
|
+
*/
|
|
34
|
+
export function buildOsascriptArgs(title, message) {
|
|
35
|
+
return [
|
|
36
|
+
"-e",
|
|
37
|
+
"on run argv",
|
|
38
|
+
"-e",
|
|
39
|
+
"display notification (item 1 of argv) with title (item 2 of argv)",
|
|
40
|
+
"-e",
|
|
41
|
+
"end run",
|
|
42
|
+
"--",
|
|
43
|
+
message,
|
|
44
|
+
title,
|
|
45
|
+
];
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Fire a desktop notification. Library entry point — never throws.
|
|
49
|
+
* Skips silently (ok:true, skipped) when disabled or on a headless host.
|
|
50
|
+
*/
|
|
51
|
+
export async function notifyDesktop(opts, deps = {}) {
|
|
52
|
+
const env = deps.env ?? process.env;
|
|
53
|
+
const platform = deps.platform ?? process.platform;
|
|
54
|
+
// Skips win first — a disabled/headless host produces no artifact and no error.
|
|
55
|
+
if ((env.OMP_DISABLE_DESKTOP_NOTIFY ?? "").trim()) {
|
|
56
|
+
return { ok: true, skipped: true };
|
|
57
|
+
}
|
|
58
|
+
if (platform === "linux" && !env.DISPLAY && !env.WAYLAND_DISPLAY) {
|
|
59
|
+
return { ok: true, skipped: true };
|
|
60
|
+
}
|
|
61
|
+
const title = (opts.title ?? "").trim();
|
|
62
|
+
const message = (opts.message ?? "").trim();
|
|
63
|
+
if (!title && !message) {
|
|
64
|
+
return { ok: false, reason: "title and message are both empty" };
|
|
65
|
+
}
|
|
66
|
+
const payload = { title: title || message, message, open: opts.open };
|
|
67
|
+
const timeoutMs = deps.timeoutMs ?? DEFAULT_TIMEOUT_MS;
|
|
68
|
+
try {
|
|
69
|
+
const transport = deps.transport ?? selectTransport(platform, deps);
|
|
70
|
+
return await withTimeout(() => transport(payload, timeoutMs), timeoutMs);
|
|
71
|
+
}
|
|
72
|
+
catch (err) {
|
|
73
|
+
return { ok: false, reason: errMsg(err) };
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
/** Pick the delivery transport for this host. */
|
|
77
|
+
function selectTransport(platform, deps) {
|
|
78
|
+
const exec = deps.exec ?? realExec;
|
|
79
|
+
if (platform === "darwin") {
|
|
80
|
+
// Default to osascript: it is the one path that reliably displays on macOS
|
|
81
|
+
// Sequoia. A system terminal-notifier (which supports the click `-open`
|
|
82
|
+
// deep-link) is used ONLY when explicitly opted in, because it does not
|
|
83
|
+
// display on some Sequoia builds — preferring it would silently break
|
|
84
|
+
// notifications. See OMP_NOTIFY_USE_TERMINAL_NOTIFIER.
|
|
85
|
+
const env = deps.env ?? process.env;
|
|
86
|
+
const optIn = Boolean((env.OMP_NOTIFY_USE_TERMINAL_NOTIFIER ?? "").trim());
|
|
87
|
+
const tnCommand = optIn ? resolveTerminalNotifier(deps) : null;
|
|
88
|
+
return (payload, timeoutMs) => deliverMac(payload, exec, tnCommand, timeoutMs);
|
|
89
|
+
}
|
|
90
|
+
return (payload, timeoutMs) => deliverNodeNotifier(payload, deps, timeoutMs);
|
|
91
|
+
}
|
|
92
|
+
/** The terminal-notifier command to exec (validated absolute path), or null to use osascript. */
|
|
93
|
+
function resolveTerminalNotifier(deps) {
|
|
94
|
+
if (deps.hasSystemTerminalNotifier !== undefined) {
|
|
95
|
+
return deps.hasSystemTerminalNotifier ? "terminal-notifier" : null;
|
|
96
|
+
}
|
|
97
|
+
return detectSystemTerminalNotifier();
|
|
98
|
+
}
|
|
99
|
+
/** macOS: osascript displays reliably (no click); opt-in terminal-notifier adds the click `-open`. */
|
|
100
|
+
function deliverMac(p, exec, tnCommand, timeoutMs) {
|
|
101
|
+
if (tnCommand) {
|
|
102
|
+
const args = ["-title", p.title, "-message", p.message, ...(p.open ? ["-open", p.open] : [])];
|
|
103
|
+
return exec(tnCommand, args, timeoutMs);
|
|
104
|
+
}
|
|
105
|
+
return exec("osascript", buildOsascriptArgs(p.title, p.message), timeoutMs);
|
|
106
|
+
}
|
|
107
|
+
/** Non-macOS: node-notifier (notify-send / SnoreToast), bounded by the outer timeout. */
|
|
108
|
+
async function deliverNodeNotifier(p, deps, _timeoutMs) {
|
|
109
|
+
const notifier = deps.notifier ?? (await loadNotifier());
|
|
110
|
+
const opts = { title: p.title, message: p.message, sound: false };
|
|
111
|
+
if (p.open)
|
|
112
|
+
opts.open = p.open;
|
|
113
|
+
return new Promise((resolve) => {
|
|
114
|
+
try {
|
|
115
|
+
notifier.notify(opts, (err) => resolve(err ? { ok: false, reason: err.message } : { ok: true }));
|
|
116
|
+
}
|
|
117
|
+
catch (err) {
|
|
118
|
+
resolve({ ok: false, reason: errMsg(err) });
|
|
119
|
+
}
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
/** Race a delivery against a bounded timeout. The timer stays referenced so it fires. */
|
|
123
|
+
function withTimeout(fn, timeoutMs) {
|
|
124
|
+
return new Promise((resolve) => {
|
|
125
|
+
let settled = false;
|
|
126
|
+
const done = (r) => {
|
|
127
|
+
if (settled)
|
|
128
|
+
return;
|
|
129
|
+
settled = true;
|
|
130
|
+
clearTimeout(timer);
|
|
131
|
+
resolve(r);
|
|
132
|
+
};
|
|
133
|
+
const timer = setTimeout(() => done({ ok: false, reason: `desktop notify timed out after ${timeoutMs}ms` }), timeoutMs);
|
|
134
|
+
Promise.resolve()
|
|
135
|
+
.then(fn)
|
|
136
|
+
.then(done, (err) => done({ ok: false, reason: errMsg(err) }));
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
/** Real command runner: execFile with its own kill-on-timeout (our child, we own it). */
|
|
140
|
+
const realExec = (file, args, timeoutMs) => new Promise((resolve) => {
|
|
141
|
+
execFile(file, args, { timeout: Math.max(1_000, timeoutMs) }, (err) => {
|
|
142
|
+
resolve(err ? { ok: false, reason: (err.message || String(err)).slice(0, 200) } : { ok: true });
|
|
143
|
+
});
|
|
144
|
+
});
|
|
145
|
+
/** True only when neither the PATH entry nor its real (symlink-resolved) target is under node_modules. */
|
|
146
|
+
export function isSystemNotifierPath(resolved, real) {
|
|
147
|
+
if (!resolved)
|
|
148
|
+
return false;
|
|
149
|
+
const hasNodeModules = (p) => p.split(/[\\/]/).includes("node_modules");
|
|
150
|
+
return !hasNodeModules(resolved) && !hasNodeModules(real);
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* Resolve a SYSTEM terminal-notifier to its validated absolute path, or null.
|
|
154
|
+
* Resolves the symlink target too, so a PATH symlink pointing at node-notifier's
|
|
155
|
+
* bundled copy is rejected (it does not display on Sequoia and isn't "system").
|
|
156
|
+
*/
|
|
157
|
+
function detectSystemTerminalNotifier() {
|
|
158
|
+
try {
|
|
159
|
+
const resolved = execFileSync("which", ["terminal-notifier"], { encoding: "utf8" }).trim();
|
|
160
|
+
if (!resolved)
|
|
161
|
+
return null;
|
|
162
|
+
let real = resolved;
|
|
163
|
+
try {
|
|
164
|
+
real = realpathSync(resolved);
|
|
165
|
+
}
|
|
166
|
+
catch {
|
|
167
|
+
// keep `resolved` if the realpath lookup fails
|
|
168
|
+
}
|
|
169
|
+
return isSystemNotifierPath(resolved, real) ? real : null;
|
|
170
|
+
}
|
|
171
|
+
catch {
|
|
172
|
+
return null;
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
/** Lazy-load node-notifier so non-notifying CLI paths never pay for the dependency. */
|
|
176
|
+
async function loadNotifier() {
|
|
177
|
+
const mod = (await import("node-notifier"));
|
|
178
|
+
return mod.default ?? mod;
|
|
179
|
+
}
|
|
180
|
+
function errMsg(err) {
|
|
181
|
+
return err instanceof Error ? err.message : String(err);
|
|
182
|
+
}
|
|
183
|
+
//# sourceMappingURL=desktop-notify.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"desktop-notify.js","sourceRoot":"","sources":["../../../src/gateway/desktop-notify.ts"],"names":[],"mappings":"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"}
|
package/dist/src/goal.js
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import { existsSync,
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
1
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
2
|
+
import { atomicWrite, ensureDir } from "./utils/fs.js";
|
|
3
|
+
import { ompPath } from "./utils/paths.js";
|
|
4
4
|
// The repo's durable objective ("what we want to achieve in this repo"), stored
|
|
5
5
|
// once per project at .omp/goal.md — distinct from a daily log's per-day goal.
|
|
6
6
|
// Exposed through the `omp goal` CLI subcommands (NOT MCP), so the project dir
|
|
7
7
|
// is the CLI's cwd and never ambiguous.
|
|
8
8
|
function goalFile(cwd) {
|
|
9
|
-
return
|
|
9
|
+
return ompPath(cwd, "goal.md");
|
|
10
10
|
}
|
|
11
11
|
// Strip ONLY our own serialized `# Repo Goal` header (not any heading), so a
|
|
12
12
|
// hand-authored objective — even one that starts with `#` — is never lost.
|
|
@@ -35,10 +35,8 @@ export function writeRepoGoal(cwd, goal) {
|
|
|
35
35
|
.replace(/\s*\n\s*/g, " ")
|
|
36
36
|
.trim();
|
|
37
37
|
const p = goalFile(cwd);
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
writeFileSync(tmp, `# Repo Goal\n\n${clean}\n`, "utf8");
|
|
41
|
-
renameSync(tmp, p);
|
|
38
|
+
ensureDir(p);
|
|
39
|
+
atomicWrite(p, `# Repo Goal\n\n${clean}\n`);
|
|
42
40
|
return clean;
|
|
43
41
|
}
|
|
44
42
|
//# sourceMappingURL=goal.js.map
|