daily-focus 2.0.0-dev.19 → 2.0.0-dev.21
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/SETUP.md
CHANGED
|
@@ -32,8 +32,8 @@ on your login shell's PATH, then where their installers put them, and checks tha
|
|
|
32
32
|
the one it finds is logged in. With one ready it doesn't ask: it uses Codex if
|
|
33
33
|
that is ready, otherwise Claude Code, and says so in a line you can **Change**.
|
|
34
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
|
|
36
|
-
to one it couldn't find.
|
|
35
|
+
(`codex login`, `claude auth login`), links to the installers with the plan each
|
|
36
|
+
needs, and takes the path to one it couldn't find.
|
|
37
37
|
|
|
38
38
|
Then it asks a few questions, one at a time, and each comes with the answer you
|
|
39
39
|
most likely want already ticked: confirm it or change it. A list can be left
|
|
@@ -67,11 +67,14 @@ card holds.
|
|
|
67
67
|
|
|
68
68
|
The sessions run on the newest flagship model at low effort (Opus for Claude Code,
|
|
69
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.
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
70
|
+
lighter models and, unlike them, told your calendars from other people's. When
|
|
71
|
+
your ChatGPT plan or workspace can't use Codex's first model, as an Enterprise or
|
|
72
|
+
Edu workspace can't until an admin turns GPT-6.1 Sol on, they run on GPT-6 Sol,
|
|
73
|
+
which answered the same; never on anything lighter. When Claude or Codex is busy,
|
|
74
|
+
the card says so and offers to try again. They only read, in an empty directory.
|
|
75
|
+
Claude Code is given read tools by name, and under Codex every connector write is
|
|
76
|
+
refused, drafts included; `gh` and `acli` are held to reading by their
|
|
77
|
+
instructions, as [the assistant's](#what-the-assistant-can-do) are.
|
|
75
78
|
|
|
76
79
|
Nothing is saved until the last step, **Write my first brief**. It saves the
|
|
77
80
|
settings, writes your source list from the answers (unless you already have one,
|
|
@@ -134,7 +137,9 @@ The dashboard runs the agent through a coding-agent CLI you already have. Instal
|
|
|
134
137
|
and log in to the [Codex CLI](https://developers.openai.com/codex/cli) or
|
|
135
138
|
[Claude Code](https://code.claude.com/docs), and choose it on the setup screen or
|
|
136
139
|
as **Write the brief with** under **Morning agent** in the settings
|
|
137
|
-
(`DAILY_FOCUS_AGENT`).
|
|
140
|
+
(`DAILY_FOCUS_AGENT`). Each needs a paid plan: ChatGPT Plus or higher for Codex,
|
|
141
|
+
whose Free and Go plans have it only in the desktop app, and any paid Claude plan
|
|
142
|
+
for Claude Code.
|
|
138
143
|
|
|
139
144
|
Each scheduled morning at 07:00 your time the dashboard starts the agent through
|
|
140
145
|
that CLI, headless, in the store, and the brief appears when it finishes. Set
|
|
@@ -431,13 +436,14 @@ Download `Daily-Focus.dmg` from the [latest release](https://github.com/watson/d
|
|
|
431
436
|
open it and drag the app to Applications, then open it from there.
|
|
432
437
|
It has no window and no Dock icon: look for it in the menu bar.
|
|
433
438
|
|
|
434
|
-
The app keeps itself up to date without a new disk image. **
|
|
435
|
-
shows two versions, the app's and the dashboard's, and which
|
|
436
|
-
**Stable Releases**, or **Development Builds**, a build of every
|
|
437
|
-
it is merged. A few times a day the app asks npm for the newest
|
|
438
|
-
it finds one, it posts a notification and the menu offers
|
|
439
|
-
Updating fetches only what the release changed. Most
|
|
440
|
-
dashboard, a few hundred kilobytes, and the dashboard
|
|
439
|
+
The app keeps itself up to date without a new disk image. **About Daily Focus** in
|
|
440
|
+
the menu shows two versions, the app's and the dashboard's, and **Updates** which
|
|
441
|
+
releases to take: **Stable Releases**, or **Development Builds**, a build of every
|
|
442
|
+
change as soon as it is merged. A few times a day the app asks npm for the newest
|
|
443
|
+
release, and when it finds one, it posts a notification and the menu offers
|
|
444
|
+
**Update Daily Focus**. Updating fetches only what the release changed. Most
|
|
445
|
+
releases change only the dashboard, a few hundred kilobytes, and the dashboard
|
|
446
|
+
restarts into it; if it
|
|
441
447
|
doesn't start, the app goes back to the one it had and says so. When a release
|
|
442
448
|
changes the app itself, the app downloads the new app, about 40 MB, puts it in its
|
|
443
449
|
own place and opens it again, and the new app carries the new dashboard. Either
|
|
@@ -264,6 +264,33 @@ function readSteps(value) {
|
|
|
264
264
|
}
|
|
265
265
|
return steps;
|
|
266
266
|
}
|
|
267
|
+
function explainFailure(cli, error) {
|
|
268
|
+
if (cli === "claude") {
|
|
269
|
+
if (/\b529\b|overloaded|experiencing high load/i.test(error)) return { cause: "busy", message: "Claude is busy right now" };
|
|
270
|
+
const model2 = /issue with the selected model \((.+?)\)/.exec(error)?.[1];
|
|
271
|
+
if (model2) return { cause: "model", message: `your Claude account can't use the model \u201C${model2}\u201D` };
|
|
272
|
+
return null;
|
|
273
|
+
}
|
|
274
|
+
const model = /The '(.+?)' model is not supported when using Codex/.exec(error)?.[1];
|
|
275
|
+
if (model) return { cause: "model", message: `your ChatGPT plan or workspace doesn't include the model \u201C${model}\u201D` };
|
|
276
|
+
if (/To use Codex with your ChatGPT plan/.test(error)) {
|
|
277
|
+
return { cause: "plan", message: "your ChatGPT plan doesn't include the Codex CLI, which needs Plus or higher" };
|
|
278
|
+
}
|
|
279
|
+
if (/at capacity|high demand|server_overloaded/i.test(error)) return { cause: "busy", message: "Codex is busy right now" };
|
|
280
|
+
return null;
|
|
281
|
+
}
|
|
282
|
+
function failed(cli, error) {
|
|
283
|
+
const explained = explainFailure(cli, error);
|
|
284
|
+
return explained ? { ok: false, error: explained.message, cause: explained.cause } : { ok: false, error };
|
|
285
|
+
}
|
|
286
|
+
function unwrapCodexError(message) {
|
|
287
|
+
try {
|
|
288
|
+
const inner = JSON.parse(message)?.error?.message;
|
|
289
|
+
return typeof inner === "string" && inner.trim() ? inner : message;
|
|
290
|
+
} catch {
|
|
291
|
+
return message;
|
|
292
|
+
}
|
|
293
|
+
}
|
|
267
294
|
function parseLine(line) {
|
|
268
295
|
const trimmed = line.trim();
|
|
269
296
|
if (!trimmed.startsWith("{")) return null;
|
|
@@ -321,7 +348,7 @@ var claudeAdapter = {
|
|
|
321
348
|
if (type === "result") {
|
|
322
349
|
const ok = event.is_error !== true && event.subtype === "success";
|
|
323
350
|
const reply = typeof event.result === "string" ? event.result : void 0;
|
|
324
|
-
const parsed = { done: ok ? { ok, reply } :
|
|
351
|
+
const parsed = { done: ok ? { ok, reply } : failed("claude", reply ?? String(event.subtype ?? "failed")) };
|
|
325
352
|
if (typeof event.session_id === "string") parsed.sessionId = event.session_id;
|
|
326
353
|
return parsed;
|
|
327
354
|
}
|
|
@@ -365,7 +392,7 @@ var codexAdapter = {
|
|
|
365
392
|
if (type === "turn.failed" || type === "error") {
|
|
366
393
|
const error = event.error;
|
|
367
394
|
const message = typeof event.message === "string" ? event.message : error?.message;
|
|
368
|
-
return { done:
|
|
395
|
+
return { done: failed("codex", message ? unwrapCodexError(message) : String(type)) };
|
|
369
396
|
}
|
|
370
397
|
return null;
|
|
371
398
|
}
|
|
@@ -409,8 +436,8 @@ function claudeStep(block) {
|
|
|
409
436
|
}
|
|
410
437
|
function codexStep(item, completed) {
|
|
411
438
|
if (typeof item.id !== "string") return null;
|
|
412
|
-
const
|
|
413
|
-
const state = completed ?
|
|
439
|
+
const failed2 = item.status === "failed" || item.error !== void 0 && item.error !== null;
|
|
440
|
+
const state = completed ? failed2 ? "failed" : "done" : "running";
|
|
414
441
|
if (item.type === "command_execution") {
|
|
415
442
|
const exited = typeof item.exit_code === "number" && item.exit_code !== 0;
|
|
416
443
|
return {
|
package/dist/cli.js
CHANGED
|
@@ -51,7 +51,7 @@ function shouldOpen(flag) {
|
|
|
51
51
|
return flag && process.stdout.isTTY === true && !process.env.CI;
|
|
52
52
|
}
|
|
53
53
|
async function demo(open, profile) {
|
|
54
|
-
const { DEMO_FIXED, demoEnv, demoIntegrations, demoProfile, writeDemoStore } = await import("./demo-
|
|
54
|
+
const { DEMO_FIXED, demoEnv, demoIntegrations, demoProfile, writeDemoStore } = await import("./demo-2F7M22LA.js");
|
|
55
55
|
const chosen = demoProfile(profile);
|
|
56
56
|
const store = await mkdtemp(join(tmpdir(), "daily-focus-demo-"));
|
|
57
57
|
process.on("exit", () => rmSync(store, { recursive: true, force: true }));
|
|
@@ -68,7 +68,7 @@ async function demo(open, profile) {
|
|
|
68
68
|
);
|
|
69
69
|
}
|
|
70
70
|
async function start(open, onStarted, options = {}) {
|
|
71
|
-
const { runServer } = await import("./server-
|
|
71
|
+
const { runServer } = await import("./server-VND7GAPL.js");
|
|
72
72
|
await runServer({
|
|
73
73
|
...options,
|
|
74
74
|
onStarted: (url) => {
|
|
@@ -15,7 +15,7 @@ import {
|
|
|
15
15
|
resolveBoard,
|
|
16
16
|
shorten,
|
|
17
17
|
unwrapShell
|
|
18
|
-
} from "./chunk-
|
|
18
|
+
} from "./chunk-YA2JMWCY.js";
|
|
19
19
|
import {
|
|
20
20
|
FOCUS_TEMPLATE,
|
|
21
21
|
SETTINGS,
|
|
@@ -3560,8 +3560,8 @@ import { createInterface as createInterface2 } from "node:readline";
|
|
|
3560
3560
|
|
|
3561
3561
|
// src/questions.ts
|
|
3562
3562
|
var INSTALL = {
|
|
3563
|
-
codex: { label: "Install Codex", url: "https://developers.openai.com/codex/cli" },
|
|
3564
|
-
claude: { label: "Install Claude Code", url: "https://code.claude.com/docs" }
|
|
3563
|
+
codex: { label: "Install Codex", url: "https://developers.openai.com/codex/cli", needs: "Codex needs ChatGPT Plus or higher" },
|
|
3564
|
+
claude: { label: "Install Claude Code", url: "https://code.claude.com/docs", needs: "Claude Code needs a paid Claude plan" }
|
|
3565
3565
|
};
|
|
3566
3566
|
function option(value, label, detail = null, group = null) {
|
|
3567
3567
|
return { value, label, detail, group };
|
|
@@ -3606,14 +3606,17 @@ var cli = {
|
|
|
3606
3606
|
const report = ctx.clis;
|
|
3607
3607
|
const ready = CLI_PREFERENCE.filter((name) => report[name].ready);
|
|
3608
3608
|
if (ready.length === 0) {
|
|
3609
|
-
const
|
|
3609
|
+
const labels = CLI_PREFERENCE.map((name) => CLI_LABEL[name]);
|
|
3610
|
+
const wrong = CLI_PREFERENCE.every((name) => !report[name].path) ? `Neither ${labels.join(" nor ")} is installed.` : CLI_PREFERENCE.every((name) => report[name].fix === LOGIN[name].fix) ? `${labels.join(" and ")} are installed, but neither is logged in.` : CLI_PREFERENCE.map((name) => `${report[name].problem ?? `${CLI_LABEL[name]} can't be used`}.`).join(" ");
|
|
3610
3611
|
const fix = CLI_PREFERENCE.map((name) => report[name].fix).find((command3) => command3) ?? null;
|
|
3612
|
+
const missing = CLI_PREFERENCE.filter((name) => !report[name].path);
|
|
3613
|
+
const needs = missing.length ? `${missing.map((name) => INSTALL[name].needs).join("; ")}. ` : "";
|
|
3611
3614
|
return card({
|
|
3612
3615
|
problem: {
|
|
3613
|
-
message: `${
|
|
3616
|
+
message: `${wrong} ${needs}${fix ? "Run this in a terminal, then check again." : "Install one, log in once in a terminal, then check again."}`,
|
|
3614
3617
|
command: fix,
|
|
3615
3618
|
blocking: true,
|
|
3616
|
-
links:
|
|
3619
|
+
links: missing.map((name) => ({ label: INSTALL[name].label, url: INSTALL[name].url }))
|
|
3617
3620
|
},
|
|
3618
3621
|
fields: [
|
|
3619
3622
|
field("path", "Installed somewhere setup didn\u2019t look? Its path", "", {
|
|
@@ -4088,6 +4091,7 @@ var SESSION_MODEL = {
|
|
|
4088
4091
|
claude: { model: "opus", effort: "low" },
|
|
4089
4092
|
codex: { model: null, effort: "low" }
|
|
4090
4093
|
};
|
|
4094
|
+
var CODEX_FALLBACK_MODEL = "gpt-6-sol";
|
|
4091
4095
|
var ONBOARDING_TOOLS = [
|
|
4092
4096
|
"Bash(gh *)",
|
|
4093
4097
|
"Bash(acli *)",
|
|
@@ -4184,6 +4188,7 @@ var Onboarding = class {
|
|
|
4184
4188
|
spawnFn;
|
|
4185
4189
|
gates = /* @__PURE__ */ new Map();
|
|
4186
4190
|
codexOff = null;
|
|
4191
|
+
/** The model Codex's sessions run on: the catalog's first until one fails for the account, then `CODEX_FALLBACK_MODEL`. */
|
|
4187
4192
|
codexModel = null;
|
|
4188
4193
|
/** What looking for the CLIs found, once the screen has asked. Not kept: what is installed changes. */
|
|
4189
4194
|
detected = null;
|
|
@@ -4606,6 +4611,11 @@ ${request}`, resume, said);
|
|
|
4606
4611
|
ok: false,
|
|
4607
4612
|
error: `${cli2} exited with code ${code}${stderr.length ? `: ${stderr.join("").trim().split("\n").slice(-3).join(" ")}` : ""}`
|
|
4608
4613
|
};
|
|
4614
|
+
if (cli2 === "codex" && outcome.cause === "model" && model !== CODEX_FALLBACK_MODEL && this.file?.proposals[question.id] === record) {
|
|
4615
|
+
this.codexModel = Promise.resolve(CODEX_FALLBACK_MODEL);
|
|
4616
|
+
void this.ask(question, ctx, prompt, resume, conversation).catch((err) => console.error(`[daily-focus] setup could not ask again: ${err.message}`)).finally(ended);
|
|
4617
|
+
return;
|
|
4618
|
+
}
|
|
4609
4619
|
void this.settle(question.id, record, outcome.ok ? { ok: true, reply: outcome.reply ?? said } : outcome).catch((err) => console.error(`[daily-focus] setup could not keep what it found: ${err.message}`)).finally(ended);
|
|
4610
4620
|
});
|
|
4611
4621
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "daily-focus",
|
|
3
|
-
"version": "2.0.0-dev.
|
|
3
|
+
"version": "2.0.0-dev.21",
|
|
4
4
|
"description": "An interactive dashboard of what you should focus on today at work",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"dashboard",
|
|
@@ -41,7 +41,7 @@
|
|
|
41
41
|
},
|
|
42
42
|
"daily-focus": {
|
|
43
43
|
"appInterface": 1,
|
|
44
|
-
"appSource": "
|
|
44
|
+
"appSource": "0df3059a46d460871b08ddea9dd9a793f20cf9f5"
|
|
45
45
|
},
|
|
46
46
|
"scripts": {
|
|
47
47
|
"start": "node src/server.ts",
|