daily-focus 1.2.0-dev.10 → 1.2.0-dev.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -3
- package/SETUP.md +60 -18
- package/dist/{audit-7ZCLKF46.js → audit-F26VGPOO.js} +3 -3
- package/dist/{chunk-J7ZYVUG6.js → chunk-4DZEBUPU.js} +5 -1
- package/dist/{chunk-RZNQJ6UG.js → chunk-CPJ6LOVC.js} +1 -1
- package/dist/{chunk-ODJGQCM3.js → chunk-EV44BC2F.js} +22 -5
- package/dist/{chunk-Z4SFMMRQ.js → chunk-GVLNDQVQ.js} +2 -2
- package/dist/{chunk-64XB7UDN.js → chunk-HVCCIZGA.js} +1 -1
- package/dist/cli.js +6 -6
- package/dist/{demo-BYLLMKSQ.js → demo-UMGG3VKY.js} +4 -4
- package/dist/{init-EMZDG2I7.js → init-MFPXASX3.js} +1 -1
- package/dist/{seed-JU4LQ33D.js → seed-S32JX5MW.js} +3 -3
- package/dist/{server-WQYUOKB3.js → server-EDPYEZCP.js} +1701 -209
- package/dist/{service-PUJ3YDH5.js → service-XPFMYIHR.js} +1 -1
- package/package.json +1 -1
- package/prompts/README.md +6 -4
- package/prompts/onboarding.md +41 -0
- package/public/app.js +611 -273
- package/public/style.css +573 -75
package/README.md
CHANGED
|
@@ -35,9 +35,11 @@ To use your own data:
|
|
|
35
35
|
npx daily-focus
|
|
36
36
|
```
|
|
37
37
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
Codex),
|
|
38
|
+
A new store opens on the setup screen: a few questions, one at a time, each with
|
|
39
|
+
the likely answer already ticked. Once you've chosen the coding-agent CLI that writes
|
|
40
|
+
the brief (Claude Code or Codex), it looks into the rest for you, such as which of
|
|
41
|
+
your calendars are work ones, so most answers are a click. Everything stays on the
|
|
42
|
+
settings page afterwards.
|
|
41
43
|
To keep it running in the background on macOS, install it and run it as a service:
|
|
42
44
|
|
|
43
45
|
```sh
|
package/SETUP.md
CHANGED
|
@@ -27,18 +27,56 @@ and `npm start` runs it in the terminal. Each `daily-focus <command>` below is
|
|
|
27
27
|
`npm run <command>` in a checkout, with two differences: `build-calendar` is
|
|
28
28
|
`build:calendar`, and flags go after `--`, as in `npm run audit -- --against <file>`.
|
|
29
29
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
30
|
+
A new store opens on the setup screen. It first looks for Codex and Claude Code:
|
|
31
|
+
on your login shell's PATH, then where their installers put them, and checks that
|
|
32
|
+
the one it finds is logged in. With one ready it doesn't ask: it uses Codex if
|
|
33
|
+
that is ready, otherwise Claude Code, and says so in a line you can **Change**.
|
|
34
|
+
With neither ready, it says what is wrong with each and the command that fixes it
|
|
35
|
+
(`codex login`, `claude auth login`), links to the installers, and takes the path
|
|
36
|
+
to one it couldn't find.
|
|
37
|
+
|
|
38
|
+
Then it asks a few questions, one at a time, and each comes with the answer you
|
|
39
|
+
most likely want already ticked: confirm it or change it. A list can be left
|
|
40
|
+
unticked and a field empty. Two questions can be left, by a button that says what
|
|
41
|
+
that does: **Decide later** for the agent, and **Leave this out** for who you are.
|
|
42
|
+
**Change** reopens an earlier answer.
|
|
43
|
+
|
|
44
|
+
1. **Who writes the brief**, only when it couldn't pick for you.
|
|
45
|
+
2. **What it briefs**: your work, or your personal life. See
|
|
33
46
|
[A personal instance](#a-personal-instance) for running both.
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
47
|
+
3. **When it runs**, and on which days.
|
|
48
|
+
4. **Who you are**: your name as meeting notes write it, your email, and each
|
|
49
|
+
GitHub account `gh` is logged in to, with what it's for.
|
|
50
|
+
5. **What else to show**: the pull request board and the Jira board, each with
|
|
51
|
+
its status.
|
|
52
|
+
6. **Which calendars** the brief reads, which the live agenda follows too.
|
|
53
|
+
7. **Your objective**, which the agent ranks the day against, and what's in the
|
|
54
|
+
way. It suggests a few from what you've been doing, when something stands
|
|
55
|
+
out, and writes one up from whatever you tell it, however rough.
|
|
56
|
+
|
|
57
|
+
The [assistant](#ask-the-assistant) isn't asked about: it comes on with the CLI
|
|
58
|
+
that writes the brief, unless you've set it already.
|
|
59
|
+
|
|
60
|
+
Once you've said what it briefs, the CLI looks into the others in the background,
|
|
61
|
+
one short session each, so the slow ones are ready when you get to them. It reads
|
|
62
|
+
`gh`, your mail and your calendars to tell work from personal, and says in a
|
|
63
|
+
sentence why it ticked what it did. Reply under that sentence with what to change,
|
|
64
|
+
such as "also the on-call rota", and it tries again, answering in the same place.
|
|
65
|
+
Continue before it has finished and it asks first, then stops and keeps what the
|
|
66
|
+
card holds.
|
|
67
|
+
|
|
68
|
+
The sessions run on the newest flagship model at low effort (Opus for Claude Code,
|
|
69
|
+
the first model in Codex's own list for Codex), which measured as fast as the
|
|
70
|
+
lighter models and, unlike them, told your calendars from other people's. They
|
|
71
|
+
only read, in an empty directory. Claude Code is given read tools by name, and
|
|
72
|
+
under Codex every connector write is refused, drafts included; `gh` and `acli` are
|
|
73
|
+
held to reading by their instructions, as
|
|
74
|
+
[the assistant's](#what-the-assistant-can-do) are.
|
|
75
|
+
|
|
76
|
+
Nothing is saved until the last step, **Write my first brief**. It saves the
|
|
77
|
+
settings, writes your source list from the answers (unless you already have one,
|
|
78
|
+
which it leaves alone) and your objective, restarts the dashboard to apply them,
|
|
79
|
+
and runs the agent once while you watch.
|
|
42
80
|
|
|
43
81
|
Everything in it stays on the settings page afterwards: the gear in the header, or
|
|
44
82
|
<kbd>,</kbd>. The dashboard keeps its files in `~/.daily-focus/`, and links the
|
|
@@ -52,6 +90,8 @@ terminal open while you use the dashboard. `daily-focus --help` lists the rest.
|
|
|
52
90
|
|
|
53
91
|
If you'd rather write the files by hand, `daily-focus init` creates the store with
|
|
54
92
|
templates for both. It preserves existing files, so you can safely run it again.
|
|
93
|
+
A setting given in the environment, such as `DAILY_FOCUS_PROFILE`, is shown on the
|
|
94
|
+
setup screen as answered and isn't asked.
|
|
55
95
|
|
|
56
96
|
## Set your objective and sources
|
|
57
97
|
|
|
@@ -91,7 +131,7 @@ Keep real names, account handles, and work details in this private store, outsid
|
|
|
91
131
|
|
|
92
132
|
The dashboard runs the agent through a coding-agent CLI you already have. Install
|
|
93
133
|
and log in to the [Codex CLI](https://developers.openai.com/codex/cli) or
|
|
94
|
-
[Claude Code](https://code.claude.com/docs), and choose it
|
|
134
|
+
[Claude Code](https://code.claude.com/docs), and choose it on the setup screen or
|
|
95
135
|
under **Morning agent** in the settings. In `.env` or the environment that is:
|
|
96
136
|
|
|
97
137
|
```dotenv
|
|
@@ -108,7 +148,8 @@ half minute. The days are Monday to Friday unless `DAILY_FOCUS_AGENT_DAYS` says
|
|
|
108
148
|
otherwise; see [Match your working week](#match-your-working-week).
|
|
109
149
|
`DAILY_FOCUS_AGENT_AT=off` means the dashboard never starts a run on its own; the
|
|
110
150
|
refresh icon still does. A new store's first brief always comes from the setup
|
|
111
|
-
|
|
151
|
+
screen's last button, so the clock never runs the agent before you've told it where
|
|
152
|
+
to look.
|
|
112
153
|
|
|
113
154
|
"Your time" is the time zone of the browser you last looked at the dashboard
|
|
114
155
|
in. The page tells the dashboard when it loads, reconnects or comes back into view,
|
|
@@ -470,8 +511,8 @@ daily-focus service --remove
|
|
|
470
511
|
|
|
471
512
|
Daily Focus can brief your personal life as well as your work: email, family
|
|
472
513
|
calendars, Apple Reminders, Apple Messages, e-Boks and your own GitHub projects. Run it as a second instance
|
|
473
|
-
with its own store, server and morning agent, and choose **Personal life**
|
|
474
|
-
setup
|
|
514
|
+
with its own store, server and morning agent, and choose **Personal life** on its
|
|
515
|
+
setup screen, or set:
|
|
475
516
|
|
|
476
517
|
```dotenv
|
|
477
518
|
DAILY_FOCUS_PROFILE=personal
|
|
@@ -580,9 +621,10 @@ matters when `DAILY_FOCUS_FREE_WINDOWS` is off.
|
|
|
580
621
|
which it ends with. Run `daily-focus service` to keep it running. If the
|
|
581
622
|
service is installed and the page still doesn't load, read
|
|
582
623
|
`~/Library/Logs/local.daily-focus.log`.
|
|
583
|
-
-
|
|
584
|
-
|
|
585
|
-
|
|
624
|
+
- After setup and before the first brief, the Today tab says where the first brief
|
|
625
|
+
is, and offers to run it again if it didn't finish. Once a brief has existed, an
|
|
626
|
+
empty Today tab means the agent hasn't written a new `items.json`: start a run
|
|
627
|
+
from the refresh icon beside the brief's age.
|
|
586
628
|
- A stale brief needs an agent run. Refreshing a board doesn't regenerate the brief;
|
|
587
629
|
the icon beside the brief's age does. Click "updated … ago" to see what the last
|
|
588
630
|
run said, or whether there was one: the dashboard has to be running at
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
readSystemZone,
|
|
3
3
|
startingZone
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-GVLNDQVQ.js";
|
|
5
5
|
import {
|
|
6
6
|
linkState
|
|
7
7
|
} from "./chunk-QKT2FAB5.js";
|
|
@@ -13,7 +13,7 @@ import {
|
|
|
13
13
|
resolveItems,
|
|
14
14
|
runContractChecks,
|
|
15
15
|
setsStatus
|
|
16
|
-
} from "./chunk-
|
|
16
|
+
} from "./chunk-CPJ6LOVC.js";
|
|
17
17
|
import {
|
|
18
18
|
BRIEF_REFRESH_GRACE_HOURS,
|
|
19
19
|
describeSchedule,
|
|
@@ -23,7 +23,7 @@ import {
|
|
|
23
23
|
resolveSchedule,
|
|
24
24
|
runsOn,
|
|
25
25
|
workingMsBetween
|
|
26
|
-
} from "./chunk-
|
|
26
|
+
} from "./chunk-4DZEBUPU.js";
|
|
27
27
|
import {
|
|
28
28
|
command
|
|
29
29
|
} from "./chunk-BC2W7NND.js";
|
|
@@ -462,12 +462,16 @@ function loadConfig(env = loadEnv()) {
|
|
|
462
462
|
assistantPromptFile: resolve2(dataDir, "assistant.md"),
|
|
463
463
|
assistantPromptSource: resolve2(import.meta.dirname, "..", "prompts", "assistant.md"),
|
|
464
464
|
agent: envAgent(env),
|
|
465
|
-
agentLogFile: resolve2(dataDir, "agent.jsonl")
|
|
465
|
+
agentLogFile: resolve2(dataDir, "agent.jsonl"),
|
|
466
|
+
onboardingFile: resolve2(dataDir, "onboarding.json"),
|
|
467
|
+
onboardingDir: resolve2(dataDir, "onboarding"),
|
|
468
|
+
onboardingPromptSource: resolve2(import.meta.dirname, "..", "prompts", "onboarding.md")
|
|
466
469
|
};
|
|
467
470
|
}
|
|
468
471
|
|
|
469
472
|
export {
|
|
470
473
|
LAUNCH_SETTINGS,
|
|
474
|
+
expandHome,
|
|
471
475
|
readDotEnv,
|
|
472
476
|
envSources,
|
|
473
477
|
layerEnv,
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import {
|
|
2
2
|
canonicalId,
|
|
3
3
|
foldActionLog
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-CPJ6LOVC.js";
|
|
5
5
|
import {
|
|
6
6
|
laterISO,
|
|
7
7
|
localDateKey,
|
|
8
8
|
parseISO
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-4DZEBUPU.js";
|
|
10
10
|
|
|
11
11
|
// src/codex.ts
|
|
12
12
|
import { execFile } from "node:child_process";
|
|
@@ -109,6 +109,18 @@ async function codexVersionWarning(bin, run = defaultExec) {
|
|
|
109
109
|
const consequence = olderThan(version, CODEX_CONNECTOR_POLICY) ? `Before ${CODEX_CONNECTOR_POLICY} Codex ignores the dashboard's refusal of connector writes without saying so, so the dashboard won't start the agent or the assistant on it.` : `Before ${CODEX_MINIMUM} Codex can't switch computer use off, so the assistant won't answer while computer use is off in its settings.`;
|
|
110
110
|
return `Codex ${version} is older than ${CODEX_MINIMUM}, the oldest the dashboard's limits on Codex work with. ${consequence} Update Codex.`;
|
|
111
111
|
}
|
|
112
|
+
async function codexLatestModel(bin, run = defaultExec) {
|
|
113
|
+
try {
|
|
114
|
+
const catalog = JSON.parse(await run(bin, ["debug", "models"], { timeout: LIST_TIMEOUT_MS }));
|
|
115
|
+
const listed = (Array.isArray(catalog.models) ? catalog.models : []).filter(
|
|
116
|
+
(model) => typeof model === "object" && model !== null && typeof model.slug === "string" && typeof model.priority === "number" && model.visibility === "list"
|
|
117
|
+
);
|
|
118
|
+
listed.sort((a, b) => a.priority - b.priority);
|
|
119
|
+
return listed[0]?.slug ?? null;
|
|
120
|
+
} catch {
|
|
121
|
+
return null;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
112
124
|
|
|
113
125
|
// src/assistant.ts
|
|
114
126
|
import { spawn } from "node:child_process";
|
|
@@ -263,7 +275,7 @@ function parseLine(line) {
|
|
|
263
275
|
}
|
|
264
276
|
}
|
|
265
277
|
var claudeAdapter = {
|
|
266
|
-
args({ prompt, sessionId, model, effort, tools, denyEdits }) {
|
|
278
|
+
args({ prompt, sessionId, model, effort, tools, denyEdits, schema }) {
|
|
267
279
|
const args = [
|
|
268
280
|
"-p",
|
|
269
281
|
"--output-format",
|
|
@@ -278,6 +290,7 @@ var claudeAdapter = {
|
|
|
278
290
|
if (tools.length > 0) args.push("--allowedTools", ...tools);
|
|
279
291
|
if (model) args.push("--model", model);
|
|
280
292
|
if (effort) args.push("--effort", effort);
|
|
293
|
+
if (schema) args.push("--json-schema", schema.json);
|
|
281
294
|
if (sessionId) args.push("--resume", sessionId);
|
|
282
295
|
args.push("--", prompt);
|
|
283
296
|
return args;
|
|
@@ -310,10 +323,11 @@ var claudeAdapter = {
|
|
|
310
323
|
}
|
|
311
324
|
};
|
|
312
325
|
var codexAdapter = {
|
|
313
|
-
args({ prompt, sessionId, model, effort, drafts, codexConfig }) {
|
|
326
|
+
args({ prompt, sessionId, model, effort, drafts, codexConfig, schema }) {
|
|
314
327
|
const args = ["exec"];
|
|
315
328
|
if (sessionId) args.push("resume");
|
|
316
329
|
args.push("--json", "--skip-git-repo-check");
|
|
330
|
+
if (schema) args.push("--output-schema", schema.file);
|
|
317
331
|
const config = [
|
|
318
332
|
'sandbox_mode="workspace-write"',
|
|
319
333
|
"sandbox_workspace_write.network_access=true",
|
|
@@ -354,7 +368,7 @@ var ADAPTERS = {
|
|
|
354
368
|
claude: claudeAdapter,
|
|
355
369
|
codex: codexAdapter
|
|
356
370
|
};
|
|
357
|
-
var CLAUDE_QUIET_TOOLS = /* @__PURE__ */ new Set(["ToolSearch", "TodoWrite"]);
|
|
371
|
+
var CLAUDE_QUIET_TOOLS = /* @__PURE__ */ new Set(["ToolSearch", "TodoWrite", "StructuredOutput"]);
|
|
358
372
|
function claudeStep(block) {
|
|
359
373
|
if (block.type === "tool_result" && typeof block.tool_use_id === "string") {
|
|
360
374
|
return { id: block.tool_use_id, state: block.is_error === true ? "failed" : "done" };
|
|
@@ -989,8 +1003,11 @@ function countBoard(rows) {
|
|
|
989
1003
|
}
|
|
990
1004
|
|
|
991
1005
|
export {
|
|
1006
|
+
computerUseOff,
|
|
1007
|
+
refusalFor,
|
|
992
1008
|
CodexGate,
|
|
993
1009
|
codexVersionWarning,
|
|
1010
|
+
codexLatestModel,
|
|
994
1011
|
QUICK_ACTIONS,
|
|
995
1012
|
ADAPTERS,
|
|
996
1013
|
Assistant,
|
package/dist/cli.js
CHANGED
|
@@ -49,7 +49,7 @@ function shouldOpen(flag) {
|
|
|
49
49
|
return flag && process.stdout.isTTY === true && !process.env.CI;
|
|
50
50
|
}
|
|
51
51
|
async function demo(open, profile) {
|
|
52
|
-
const { demoEnv, demoIntegrations, demoProfile, writeDemoStore } = await import("./demo-
|
|
52
|
+
const { demoEnv, demoIntegrations, demoProfile, writeDemoStore } = await import("./demo-UMGG3VKY.js");
|
|
53
53
|
const chosen = demoProfile(profile);
|
|
54
54
|
const store = await mkdtemp(join(tmpdir(), "daily-focus-demo-"));
|
|
55
55
|
process.on("exit", () => rmSync(store, { recursive: true, force: true }));
|
|
@@ -66,7 +66,7 @@ async function demo(open, profile) {
|
|
|
66
66
|
);
|
|
67
67
|
}
|
|
68
68
|
async function start(open, onStarted, options = {}) {
|
|
69
|
-
const { runServer } = await import("./server-
|
|
69
|
+
const { runServer } = await import("./server-EDPYEZCP.js");
|
|
70
70
|
await runServer({
|
|
71
71
|
...options,
|
|
72
72
|
onStarted: (url) => {
|
|
@@ -163,20 +163,20 @@ async function main(argv) {
|
|
|
163
163
|
}
|
|
164
164
|
return start(open);
|
|
165
165
|
case "service": {
|
|
166
|
-
const { main: service } = await import("./service-
|
|
166
|
+
const { main: service } = await import("./service-XPFMYIHR.js");
|
|
167
167
|
process.exitCode = await service(values.remove ? ["--remove"] : []);
|
|
168
168
|
return;
|
|
169
169
|
}
|
|
170
170
|
// These three are scripts that do their work as they load, and read their
|
|
171
171
|
// own flags from the command line.
|
|
172
172
|
case "init":
|
|
173
|
-
await import("./init-
|
|
173
|
+
await import("./init-MFPXASX3.js");
|
|
174
174
|
return;
|
|
175
175
|
case "audit":
|
|
176
|
-
await import("./audit-
|
|
176
|
+
await import("./audit-F26VGPOO.js");
|
|
177
177
|
return;
|
|
178
178
|
case "seed":
|
|
179
|
-
await import("./seed-
|
|
179
|
+
await import("./seed-S32JX5MW.js");
|
|
180
180
|
return;
|
|
181
181
|
case "build-calendar":
|
|
182
182
|
return buildCalendar();
|
|
@@ -3,17 +3,17 @@ import {
|
|
|
3
3
|
actionOf,
|
|
4
4
|
autoKeys,
|
|
5
5
|
judge
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-EV44BC2F.js";
|
|
7
7
|
import {
|
|
8
8
|
dateFromNow,
|
|
9
9
|
sampleBrief,
|
|
10
10
|
sampleGeneratedAt
|
|
11
|
-
} from "./chunk-
|
|
12
|
-
import "./chunk-
|
|
11
|
+
} from "./chunk-HVCCIZGA.js";
|
|
12
|
+
import "./chunk-CPJ6LOVC.js";
|
|
13
13
|
import {
|
|
14
14
|
PROFILES,
|
|
15
15
|
localDateKey
|
|
16
|
-
} from "./chunk-
|
|
16
|
+
} from "./chunk-4DZEBUPU.js";
|
|
17
17
|
import "./chunk-BC2W7NND.js";
|
|
18
18
|
|
|
19
19
|
// src/demo.ts
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import {
|
|
2
2
|
sampleBrief
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-HVCCIZGA.js";
|
|
4
4
|
import {
|
|
5
5
|
Store
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-CPJ6LOVC.js";
|
|
7
7
|
import {
|
|
8
8
|
loadConfig
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-4DZEBUPU.js";
|
|
10
10
|
import {
|
|
11
11
|
command
|
|
12
12
|
} from "./chunk-BC2W7NND.js";
|