daily-focus 1.2.0-dev.7 → 1.2.0-dev.9
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 +7 -12
- package/SETUP.md +3 -5
- package/dist/{audit-7YAJYHZF.js → audit-DNTFZOHH.js} +3 -3
- package/dist/{chunk-4DCBCR4D.js → chunk-6SMUSPZG.js} +2 -2
- package/dist/{chunk-JQGYCWRX.js → chunk-GQ3NCWRT.js} +7 -175
- package/dist/{chunk-SX5FPS3A.js → chunk-KL6RU4XT.js} +141 -15
- package/dist/{chunk-RNE27FQY.js → chunk-KZNY45XW.js} +0 -5
- package/dist/{chunk-UY6HQLGE.js → chunk-P3E2B2SD.js} +1 -1
- package/dist/cli.js +6 -6
- package/dist/{demo-5I4BNHW2.js → demo-TIIXODJG.js} +38 -25
- package/dist/{init-57WHZZNG.js → init-XDMAXU2S.js} +1 -9
- package/dist/{seed-BLFBCHIA.js → seed-TWT7EDXJ.js} +3 -3
- package/dist/{server-UI6WYRTL.js → server-WT4CQ3VX.js} +88 -218
- package/dist/{service-NAAAV67B.js → service-ZUHI3VKH.js} +1 -1
- package/package.json +1 -1
- package/prompts/README.md +2 -3
- package/prompts/assistant.md +7 -2
- package/prompts/morning-brief-personal.md +0 -25
- package/prompts/morning-brief-work.md +0 -28
- package/public/app.js +361 -427
- package/public/style.css +141 -180
package/public/app.js
CHANGED
|
@@ -69,9 +69,9 @@ function H() {
|
|
|
69
69
|
}
|
|
70
70
|
}
|
|
71
71
|
function L(n3, l5, u4, t4, i4, r4, o4, e4, f4, c4, a4) {
|
|
72
|
-
var s4, h5, p5, v4,
|
|
73
|
-
for (f4 = T(u4, l5, g4, f4, m4), s4 = 0; s4 < m4; s4++) null != (p5 = u4.__k[s4]) && (h5 = -1 != p5.__i && g4[p5.__i] || d, p5.__i = s4, _5 = q(n3, p5, h5, i4, r4, o4, e4, f4, c4, a4), v4 = p5.__e, p5.ref && h5.ref != p5.ref && (h5.ref && J(h5.ref, null, p5), a4.push(p5.ref, p5.__c || v4, p5)), null ==
|
|
74
|
-
return u4.__e =
|
|
72
|
+
var s4, h5, p5, v4, y5, _5, g4 = t4 && t4.__k || w, m4 = l5.length;
|
|
73
|
+
for (f4 = T(u4, l5, g4, f4, m4), s4 = 0; s4 < m4; s4++) null != (p5 = u4.__k[s4]) && (h5 = -1 != p5.__i && g4[p5.__i] || d, p5.__i = s4, _5 = q(n3, p5, h5, i4, r4, o4, e4, f4, c4, a4), v4 = p5.__e, p5.ref && h5.ref != p5.ref && (h5.ref && J(h5.ref, null, p5), a4.push(p5.ref, p5.__c || v4, p5)), null == y5 && null != v4 && (y5 = v4), 4 & p5.__u ? (f4 = j(p5, f4, n3), h5.__e && (h5.__e = null)) : "function" == typeof p5.type && void 0 !== _5 ? f4 = _5 : v4 && (f4 = v4.nextSibling), p5.__u &= -7);
|
|
74
|
+
return u4.__e = y5, f4;
|
|
75
75
|
}
|
|
76
76
|
function T(n3, l5, u4, t4, i4) {
|
|
77
77
|
var r4, o4, e4, f4, c4, a4 = u4.length, s4 = a4, h5 = 0;
|
|
@@ -131,29 +131,29 @@ function V(n3) {
|
|
|
131
131
|
};
|
|
132
132
|
}
|
|
133
133
|
function q(n3, u4, t4, i4, r4, o4, e4, f4, c4, a4) {
|
|
134
|
-
var s4, h5, p5, v4,
|
|
134
|
+
var s4, h5, p5, v4, y5, d5, _5, k3, x4, M, I2, P2, A3, H2, T4, j4, F2 = u4.type;
|
|
135
135
|
if (void 0 !== u4.constructor) return null;
|
|
136
136
|
128 & t4.__u && (c4 = !!(32 & t4.__u), o4 = [f4 = u4.__e = t4.__e]), (s4 = l.__b) && s4(u4);
|
|
137
137
|
n: if ("function" == typeof F2) {
|
|
138
138
|
h5 = e4.length;
|
|
139
139
|
try {
|
|
140
|
-
if (x4 = u4.props, M = F2.prototype && F2.prototype.render, I2 = (s4 = F2.contextType) && i4[s4.__c], P2 = s4 ? I2 ? I2.props.value : s4.__ : i4, t4.__c ? k3 = (p5 = u4.__c = t4.__c).__ = p5.__E : (M ? u4.__c = p5 = new F2(x4, P2) : (u4.__c = p5 = new C(x4, P2), p5.constructor = F2, p5.render = Q), I2 && I2.sub(p5), p5.state || (p5.state = {}), p5.__n = i4, v4 = p5.__d = true, p5.__h = [], p5._sb = []), M && null == p5.__s && (p5.__s = p5.state), M && null != F2.getDerivedStateFromProps && (p5.__s == p5.state && (p5.__s = m({}, p5.__s)), m(p5.__s, F2.getDerivedStateFromProps(x4, p5.__s))),
|
|
140
|
+
if (x4 = u4.props, M = F2.prototype && F2.prototype.render, I2 = (s4 = F2.contextType) && i4[s4.__c], P2 = s4 ? I2 ? I2.props.value : s4.__ : i4, t4.__c ? k3 = (p5 = u4.__c = t4.__c).__ = p5.__E : (M ? u4.__c = p5 = new F2(x4, P2) : (u4.__c = p5 = new C(x4, P2), p5.constructor = F2, p5.render = Q), I2 && I2.sub(p5), p5.state || (p5.state = {}), p5.__n = i4, v4 = p5.__d = true, p5.__h = [], p5._sb = []), M && null == p5.__s && (p5.__s = p5.state), M && null != F2.getDerivedStateFromProps && (p5.__s == p5.state && (p5.__s = m({}, p5.__s)), m(p5.__s, F2.getDerivedStateFromProps(x4, p5.__s))), y5 = p5.props, d5 = p5.state, p5.__v = u4, v4) M && null == F2.getDerivedStateFromProps && null != p5.componentWillMount && p5.componentWillMount(), M && null != p5.componentDidMount && p5.__h.push(p5.componentDidMount);
|
|
141
141
|
else {
|
|
142
|
-
if (M && null == F2.getDerivedStateFromProps && x4 !==
|
|
142
|
+
if (M && null == F2.getDerivedStateFromProps && x4 !== y5 && null != p5.componentWillReceiveProps && p5.componentWillReceiveProps(x4, P2), u4.__v == t4.__v || !p5.__e && null != p5.shouldComponentUpdate && false === p5.shouldComponentUpdate(x4, p5.__s, P2)) {
|
|
143
143
|
u4.__v != t4.__v && (p5.props = x4, p5.state = p5.__s, p5.__d = false), u4.__e = t4.__e, u4.__k = t4.__k, u4.__k.some(function(n4) {
|
|
144
144
|
n4 && (n4.__ = u4);
|
|
145
145
|
}), w.push.apply(p5.__h, p5._sb), p5._sb = [], p5.__h.length && e4.push(p5), f4 = $(t4);
|
|
146
146
|
break n;
|
|
147
147
|
}
|
|
148
148
|
null != p5.componentWillUpdate && p5.componentWillUpdate(x4, p5.__s, P2), M && null != p5.componentDidUpdate && p5.__h.push(function() {
|
|
149
|
-
p5.componentDidUpdate(
|
|
149
|
+
p5.componentDidUpdate(y5, d5, _5);
|
|
150
150
|
});
|
|
151
151
|
}
|
|
152
152
|
if (p5.context = P2, p5.props = x4, p5.__P = n3, p5.__e = false, A3 = l.__r, H2 = 0, M) p5.state = p5.__s, p5.__d = false, A3 && A3(u4), s4 = p5.render(p5.props, p5.state, p5.context), w.push.apply(p5.__h, p5._sb), p5._sb = [];
|
|
153
153
|
else do {
|
|
154
154
|
p5.__d = false, A3 && A3(u4), s4 = p5.render(p5.props, p5.state, p5.context), p5.state = p5.__s;
|
|
155
155
|
} while (p5.__d && ++H2 < 25);
|
|
156
|
-
p5.state = p5.__s, null != p5.getChildContext && (i4 = m(m({}, i4), p5.getChildContext())), M && !v4 && null != p5.getSnapshotBeforeUpdate && (_5 = p5.getSnapshotBeforeUpdate(
|
|
156
|
+
p5.state = p5.__s, null != p5.getChildContext && (i4 = m(m({}, i4), p5.getChildContext())), M && !v4 && null != p5.getSnapshotBeforeUpdate && (_5 = p5.getSnapshotBeforeUpdate(y5, d5)), T4 = null != s4 && s4.type === S && null == s4.key ? E(s4.props.children) : s4, f4 = L(n3, g(T4) ? T4 : [T4], u4, t4, i4, r4, o4, e4, f4, c4, a4), p5.base = u4.__e, u4.__u &= -161, p5.__h.length && e4.push(p5), k3 && (p5.__E = p5.__ = null);
|
|
157
157
|
} catch (n4) {
|
|
158
158
|
if (e4.length = h5, u4.__v = null, c4 || null != o4) {
|
|
159
159
|
if (n4.then) {
|
|
@@ -185,10 +185,10 @@ function E(n3) {
|
|
|
185
185
|
return "object" != typeof n3 || null == n3 || n3.__b > 0 ? n3 : g(n3) ? n3.map(E) : void 0 !== n3.constructor ? null : m({}, n3);
|
|
186
186
|
}
|
|
187
187
|
function G(u4, t4, i4, r4, o4, e4, f4, c4, a4) {
|
|
188
|
-
var s4, h5, p5, v4,
|
|
188
|
+
var s4, h5, p5, v4, y5, w5, _5, m4 = i4.props || d, k3 = t4.props, x4 = t4.type;
|
|
189
189
|
if ("svg" == x4 ? o4 = "http://www.w3.org/2000/svg" : "math" == x4 ? o4 = "http://www.w3.org/1998/Math/MathML" : o4 || (o4 = "http://www.w3.org/1999/xhtml"), null != e4) {
|
|
190
|
-
for (s4 = 0; s4 < e4.length; s4++) if ((
|
|
191
|
-
u4 =
|
|
190
|
+
for (s4 = 0; s4 < e4.length; s4++) if ((y5 = e4[s4]) && "setAttribute" in y5 == !!x4 && (x4 ? y5.localName == x4 : 3 == y5.nodeType)) {
|
|
191
|
+
u4 = y5, e4[s4] = null;
|
|
192
192
|
break;
|
|
193
193
|
}
|
|
194
194
|
}
|
|
@@ -198,9 +198,9 @@ function G(u4, t4, i4, r4, o4, e4, f4, c4, a4) {
|
|
|
198
198
|
}
|
|
199
199
|
if (null == x4) m4 === k3 || c4 && u4.data == k3 || (u4.data = k3);
|
|
200
200
|
else {
|
|
201
|
-
if (e4 = "textarea" == x4 && null != k3.defaultValue ? null : e4 && n.call(u4.childNodes), !c4 && null != e4) for (m4 = {}, s4 = 0; s4 < u4.attributes.length; s4++) m4[(
|
|
202
|
-
for (s4 in m4)
|
|
203
|
-
for (s4 in k3)
|
|
201
|
+
if (e4 = "textarea" == x4 && null != k3.defaultValue ? null : e4 && n.call(u4.childNodes), !c4 && null != e4) for (m4 = {}, s4 = 0; s4 < u4.attributes.length; s4++) m4[(y5 = u4.attributes[s4]).name] = y5.value;
|
|
202
|
+
for (s4 in m4) y5 = m4[s4], "dangerouslySetInnerHTML" == s4 ? p5 = y5 : "children" == s4 || s4 in k3 || "value" == s4 && "defaultValue" in k3 || "checked" == s4 && "defaultChecked" in k3 || N(u4, s4, null, y5, o4);
|
|
203
|
+
for (s4 in k3) y5 = k3[s4], "children" == s4 ? v4 = y5 : "dangerouslySetInnerHTML" == s4 ? h5 = y5 : "value" == s4 ? w5 = y5 : "checked" == s4 ? _5 = y5 : c4 && "function" != typeof y5 || m4[s4] === y5 || N(u4, s4, y5, m4[s4], o4);
|
|
204
204
|
if (h5) c4 || p5 && (h5.__html == p5.__html || h5.__html == u4.innerHTML) || (u4.innerHTML = h5.__html), t4.__k = [];
|
|
205
205
|
else if (p5 && (u4.innerHTML = ""), L("template" == t4.type ? u4.content : u4, g(v4) ? v4 : [v4], t4, i4, r4, "foreignObject" == x4 ? "http://www.w3.org/1999/xhtml" : o4, e4, f4, e4 ? e4[0] : i4.__k && $(i4, 0), c4, a4), null != e4) for (s4 = e4.length; s4--; ) b(e4[s4]);
|
|
206
206
|
c4 && "textarea" != x4 || (s4 = "value", "progress" == x4 && null == w5 ? u4.removeAttribute("value") : null != w5 && (w5 !== u4[s4] || "progress" == x4 && !w5 || "option" == x4 && w5 != m4[s4]) && N(u4, s4, w5, m4[s4], o4), s4 = "checked", null != _5 && _5 != u4[s4] && N(u4, s4, _5, m4[s4], o4));
|
|
@@ -274,6 +274,42 @@ function s2(n3, t4) {
|
|
|
274
274
|
var u4 = r2.__H || (r2.__H = { __: [], __h: [] });
|
|
275
275
|
return n3 >= u4.__.length && u4.__.push({}), u4.__[n3];
|
|
276
276
|
}
|
|
277
|
+
function d2(n3) {
|
|
278
|
+
return o2 = 1, y2(D2, n3);
|
|
279
|
+
}
|
|
280
|
+
function y2(n3, u4, i4) {
|
|
281
|
+
var o4 = s2(t2++, 2);
|
|
282
|
+
if (o4.t = n3, !o4.__c && (o4.__ = [i4 ? i4(u4) : D2(void 0, u4), function(n4) {
|
|
283
|
+
var t4 = o4.__N ? o4.__N[0] : o4.__[0], r4 = o4.t(t4, n4);
|
|
284
|
+
t4 !== r4 && (o4.__N = [r4, o4.__[1]], o4.__c.setState({}));
|
|
285
|
+
}], o4.__c = r2, !r2.__f)) {
|
|
286
|
+
var f4 = function(n4, t4, r4) {
|
|
287
|
+
if (!o4.__c.__H) return true;
|
|
288
|
+
var u5 = false, i5 = o4.__c.props !== n4;
|
|
289
|
+
if (o4.__c.__H.__.some(function(n5) {
|
|
290
|
+
if (n5.__N) {
|
|
291
|
+
u5 = true;
|
|
292
|
+
var t5 = n5.__[0];
|
|
293
|
+
n5.__ = n5.__N, n5.__N = void 0, t5 !== n5.__[0] && (i5 = true);
|
|
294
|
+
}
|
|
295
|
+
}), c4) {
|
|
296
|
+
var f5 = c4.call(this, n4, t4, r4);
|
|
297
|
+
return u5 ? f5 || i5 : f5;
|
|
298
|
+
}
|
|
299
|
+
return !u5 || i5;
|
|
300
|
+
};
|
|
301
|
+
r2.__f = true;
|
|
302
|
+
var c4 = r2.shouldComponentUpdate, e4 = r2.componentWillUpdate;
|
|
303
|
+
r2.componentWillUpdate = function(n4, t4, r4) {
|
|
304
|
+
if (this.__e) {
|
|
305
|
+
var u5 = c4;
|
|
306
|
+
c4 = void 0, f4(n4, t4, r4), c4 = u5;
|
|
307
|
+
}
|
|
308
|
+
e4 && e4.call(this, n4, t4, r4);
|
|
309
|
+
}, r2.shouldComponentUpdate = f4;
|
|
310
|
+
}
|
|
311
|
+
return o4.__N || o4.__;
|
|
312
|
+
}
|
|
277
313
|
function h2(n3, u4) {
|
|
278
314
|
var i4 = s2(t2++, 3);
|
|
279
315
|
!c2.__s && C2(i4.__H, u4) && (i4.__ = n3, i4.u = u4, r2.__H.__h.push(i4));
|
|
@@ -360,6 +396,9 @@ function C2(n3, t4) {
|
|
|
360
396
|
return t5 !== n3[r4];
|
|
361
397
|
});
|
|
362
398
|
}
|
|
399
|
+
function D2(n3, t4) {
|
|
400
|
+
return "function" == typeof t4 ? t4(n3) : t4;
|
|
401
|
+
}
|
|
363
402
|
|
|
364
403
|
// node_modules/@preact/signals-core/dist/signals-core.module.js
|
|
365
404
|
var i3 = /* @__PURE__ */ Symbol.for("preact-signals");
|
|
@@ -430,7 +469,7 @@ var s3 = 0;
|
|
|
430
469
|
var u3 = 0;
|
|
431
470
|
var e3 = 0;
|
|
432
471
|
var c3 = void 0;
|
|
433
|
-
var
|
|
472
|
+
var d3 = 0;
|
|
434
473
|
function a3(i4) {
|
|
435
474
|
if (void 0 !== o3) {
|
|
436
475
|
var t4 = i4.n;
|
|
@@ -543,7 +582,7 @@ Object.defineProperty(l3.prototype, "value", { get: function() {
|
|
|
543
582
|
})(this);
|
|
544
583
|
this.v = i4;
|
|
545
584
|
this.i++;
|
|
546
|
-
|
|
585
|
+
d3++;
|
|
547
586
|
v3++;
|
|
548
587
|
try {
|
|
549
588
|
for (var n3 = this.t; void 0 !== n3; n3 = n3.x) n3.t.N();
|
|
@@ -552,7 +591,7 @@ Object.defineProperty(l3.prototype, "value", { get: function() {
|
|
|
552
591
|
}
|
|
553
592
|
}
|
|
554
593
|
} });
|
|
555
|
-
function
|
|
594
|
+
function y3(i4, t4) {
|
|
556
595
|
return new l3(i4, t4);
|
|
557
596
|
}
|
|
558
597
|
function w3(i4) {
|
|
@@ -590,7 +629,7 @@ function p3(i4, t4) {
|
|
|
590
629
|
l3.call(this, void 0, t4);
|
|
591
630
|
this.x = i4;
|
|
592
631
|
this.s = void 0;
|
|
593
|
-
this.g =
|
|
632
|
+
this.g = d3 - 1;
|
|
594
633
|
this.f = 4;
|
|
595
634
|
}
|
|
596
635
|
p3.prototype = new l3();
|
|
@@ -599,8 +638,8 @@ p3.prototype.h = function() {
|
|
|
599
638
|
if (1 & this.f) return false;
|
|
600
639
|
if (32 == (36 & this.f)) return true;
|
|
601
640
|
this.f &= -5;
|
|
602
|
-
if (this.g ===
|
|
603
|
-
this.g =
|
|
641
|
+
if (this.g === d3) return true;
|
|
642
|
+
this.g = d3;
|
|
604
643
|
this.f |= 1;
|
|
605
644
|
if (this.i > 0 && !w3(this)) {
|
|
606
645
|
this.f &= -2;
|
|
@@ -754,7 +793,7 @@ function j3(i4, t4) {
|
|
|
754
793
|
// node_modules/@preact/signals/dist/signals.module.js
|
|
755
794
|
var l4;
|
|
756
795
|
var h4;
|
|
757
|
-
var
|
|
796
|
+
var d4;
|
|
758
797
|
var p4 = "undefined" != typeof window && !!window.__PREACT_SIGNALS_DEVTOOLS__;
|
|
759
798
|
var _4 = [];
|
|
760
799
|
j3(function() {
|
|
@@ -765,14 +804,14 @@ function g3(i4, r4) {
|
|
|
765
804
|
});
|
|
766
805
|
}
|
|
767
806
|
function b3(i4) {
|
|
768
|
-
if (
|
|
769
|
-
var n3 =
|
|
770
|
-
|
|
807
|
+
if (d4) {
|
|
808
|
+
var n3 = d4;
|
|
809
|
+
d4 = void 0;
|
|
771
810
|
n3();
|
|
772
811
|
}
|
|
773
|
-
|
|
812
|
+
d4 = i4 && i4.S();
|
|
774
813
|
}
|
|
775
|
-
function
|
|
814
|
+
function y4(i4) {
|
|
776
815
|
var n3 = this, t4 = i4.data, f4 = useSignal(t4);
|
|
777
816
|
f4.name = "ReactiveDom";
|
|
778
817
|
f4.value = t4;
|
|
@@ -802,8 +841,8 @@ function y3(i4) {
|
|
|
802
841
|
}, []), a4 = e4[0], v4 = e4[1];
|
|
803
842
|
return a4.value ? v4.peek() : v4.value;
|
|
804
843
|
}
|
|
805
|
-
|
|
806
|
-
Object.defineProperties(l3.prototype, { constructor: { configurable: true, value: void 0 }, type: { configurable: true, value:
|
|
844
|
+
y4.displayName = "ReactiveTextNode";
|
|
845
|
+
Object.defineProperties(l3.prototype, { constructor: { configurable: true, value: void 0 }, type: { configurable: true, value: y4 }, props: { configurable: true, get: function() {
|
|
807
846
|
var i4 = this;
|
|
808
847
|
return { data: { get value() {
|
|
809
848
|
return i4.value;
|
|
@@ -887,7 +926,7 @@ g3("diffed", function(i4, n3) {
|
|
|
887
926
|
i4(n3);
|
|
888
927
|
});
|
|
889
928
|
function w4(i4, n3, r4, t4) {
|
|
890
|
-
var o4 = n3 in i4 && void 0 === i4.ownerSVGElement, f4 =
|
|
929
|
+
var o4 = n3 in i4 && void 0 === i4.ownerSVGElement, f4 = y3(r4);
|
|
891
930
|
return { o: function(i5, n4) {
|
|
892
931
|
f4.value = i5;
|
|
893
932
|
t4 = n4;
|
|
@@ -955,7 +994,7 @@ C.prototype.shouldComponentUpdate = function(i4, n3) {
|
|
|
955
994
|
};
|
|
956
995
|
function useSignal(i4, n3) {
|
|
957
996
|
return T2(function() {
|
|
958
|
-
return
|
|
997
|
+
return y3(i4, n3);
|
|
959
998
|
}, []);
|
|
960
999
|
}
|
|
961
1000
|
var q2 = function(i4) {
|
|
@@ -1013,9 +1052,6 @@ function subscribe(onState, onError) {
|
|
|
1013
1052
|
function postTimeZone(timeZone) {
|
|
1014
1053
|
return post("/api/timezone", { timeZone });
|
|
1015
1054
|
}
|
|
1016
|
-
function postSession(body) {
|
|
1017
|
-
return post("/api/session", body);
|
|
1018
|
-
}
|
|
1019
1055
|
function postBoardRefresh() {
|
|
1020
1056
|
return post("/api/board/refresh");
|
|
1021
1057
|
}
|
|
@@ -1080,40 +1116,35 @@ var VIEWS = ["today", "board", "tickets", "settings"];
|
|
|
1080
1116
|
var RUN_PREFIX = "run:";
|
|
1081
1117
|
var PANEL_PREFIX = "panel:";
|
|
1082
1118
|
var VIEW_KEY = "daily-focus:view";
|
|
1083
|
-
var UNATTENDED_SEEN_KEY = "daily-focus:unattended-seen";
|
|
1084
1119
|
var AGENT_RUN_SEEN_KEY = "daily-focus:agent-run-seen";
|
|
1085
|
-
var FOCUS_MODE_KEY = "daily-focus:focus-mode";
|
|
1086
1120
|
var DETAIL_KEY = "daily-focus:detail-for";
|
|
1087
|
-
var state =
|
|
1121
|
+
var state = y3(null);
|
|
1088
1122
|
function createUi(initial = {}) {
|
|
1089
1123
|
return {
|
|
1090
|
-
selectedId:
|
|
1091
|
-
clickedId:
|
|
1092
|
-
pending:
|
|
1093
|
-
menuFor:
|
|
1094
|
-
statusFor:
|
|
1095
|
-
detailFor:
|
|
1096
|
-
noteDraft:
|
|
1097
|
-
assistantDraft:
|
|
1098
|
-
focusField:
|
|
1099
|
-
openDrawers:
|
|
1100
|
-
ticketMode:
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
settingsSaving: y2(initial.settingsSaving ?? false),
|
|
1115
|
-
texts: y2(initial.texts ?? {}),
|
|
1116
|
-
calendars: y2(initial.calendars ?? null)
|
|
1124
|
+
selectedId: y3(initial.selectedId ?? null),
|
|
1125
|
+
clickedId: y3(initial.clickedId ?? null),
|
|
1126
|
+
pending: y3(initial.pending ?? /* @__PURE__ */ new Set()),
|
|
1127
|
+
menuFor: y3(initial.menuFor ?? null),
|
|
1128
|
+
statusFor: y3(initial.statusFor ?? null),
|
|
1129
|
+
detailFor: y3(initial.detailFor ?? null),
|
|
1130
|
+
noteDraft: y3(initial.noteDraft ?? ""),
|
|
1131
|
+
assistantDraft: y3(initial.assistantDraft ?? ""),
|
|
1132
|
+
focusField: y3(initial.focusField ?? null),
|
|
1133
|
+
openDrawers: y3(initial.openDrawers ?? /* @__PURE__ */ new Set()),
|
|
1134
|
+
ticketMode: y3(initial.ticketMode ?? "sync"),
|
|
1135
|
+
agentReportSeen: y3(initial.agentReportSeen ?? null),
|
|
1136
|
+
messageOpen: y3(initial.messageOpen ?? /* @__PURE__ */ new Map()),
|
|
1137
|
+
view: y3(initial.view ?? "today"),
|
|
1138
|
+
theme: y3(initial.theme ?? "system"),
|
|
1139
|
+
toast: y3(initial.toast ?? null),
|
|
1140
|
+
connectionError: y3(initial.connectionError ?? null),
|
|
1141
|
+
settingsReturn: y3(initial.settingsReturn ?? "today"),
|
|
1142
|
+
settings: y3(initial.settings ?? null),
|
|
1143
|
+
settingsDraft: y3(initial.settingsDraft ?? /* @__PURE__ */ new Map()),
|
|
1144
|
+
settingsError: y3(initial.settingsError ?? null),
|
|
1145
|
+
settingsSaving: y3(initial.settingsSaving ?? false),
|
|
1146
|
+
texts: y3(initial.texts ?? {}),
|
|
1147
|
+
calendars: y3(initial.calendars ?? null)
|
|
1117
1148
|
};
|
|
1118
1149
|
}
|
|
1119
1150
|
function isView(value) {
|
|
@@ -1125,9 +1156,7 @@ function remembered() {
|
|
|
1125
1156
|
return {
|
|
1126
1157
|
// Settings is a page to visit, so a reload returns to the view underneath.
|
|
1127
1158
|
view: isView(view) && view !== "settings" ? view : "today",
|
|
1128
|
-
unattendedSeen: localStorage.getItem(UNATTENDED_SEEN_KEY),
|
|
1129
1159
|
agentReportSeen: localStorage.getItem(AGENT_RUN_SEEN_KEY),
|
|
1130
|
-
focusMode: localStorage.getItem(FOCUS_MODE_KEY) === "1",
|
|
1131
1160
|
detailFor: sessionStorage.getItem(DETAIL_KEY)
|
|
1132
1161
|
};
|
|
1133
1162
|
} catch {
|
|
@@ -1295,208 +1324,6 @@ function ThemeToggle({ ui: ui2, handlers: handlers2 }) {
|
|
|
1295
1324
|
);
|
|
1296
1325
|
}
|
|
1297
1326
|
|
|
1298
|
-
// client/format.ts
|
|
1299
|
-
var DAY_FORMAT = {
|
|
1300
|
-
weekday: "long",
|
|
1301
|
-
day: "numeric",
|
|
1302
|
-
month: "long"
|
|
1303
|
-
};
|
|
1304
|
-
function formatters(timeZone) {
|
|
1305
|
-
return {
|
|
1306
|
-
time: new Intl.DateTimeFormat(void 0, { timeZone, hour: "2-digit", minute: "2-digit" }),
|
|
1307
|
-
day: new Intl.DateTimeFormat(void 0, { timeZone, ...DAY_FORMAT }),
|
|
1308
|
-
shortDay: new Intl.DateTimeFormat(void 0, { timeZone, day: "numeric", month: "short" }),
|
|
1309
|
-
shortDayYear: new Intl.DateTimeFormat(void 0, { timeZone, day: "numeric", month: "short", year: "numeric" }),
|
|
1310
|
-
weekday: new Intl.DateTimeFormat(void 0, { timeZone, weekday: "long" })
|
|
1311
|
-
};
|
|
1312
|
-
}
|
|
1313
|
-
var clockFormats = formatters();
|
|
1314
|
-
var dateFormats = formatters("UTC");
|
|
1315
|
-
var DATE_ONLY = /^\d{4}-\d{2}-\d{2}$/;
|
|
1316
|
-
function formatted(value, kind) {
|
|
1317
|
-
const bare = typeof value === "string" && DATE_ONLY.test(value);
|
|
1318
|
-
const d4 = bare ? /* @__PURE__ */ new Date(`${value}T00:00:00Z`) : parseDate(value);
|
|
1319
|
-
return d4 && !Number.isNaN(d4.getTime()) ? (bare ? dateFormats : clockFormats)[kind].format(d4) : "";
|
|
1320
|
-
}
|
|
1321
|
-
function parseDate(value) {
|
|
1322
|
-
if (typeof value !== "string" || value === "") return null;
|
|
1323
|
-
const dateOnly = /^(\d{4})-(\d{2})-(\d{2})$/.exec(value);
|
|
1324
|
-
if (dateOnly) return new Date(+dateOnly[1], +dateOnly[2] - 1, +dateOnly[3]);
|
|
1325
|
-
const d4 = new Date(value);
|
|
1326
|
-
return Number.isNaN(d4.getTime()) ? null : d4;
|
|
1327
|
-
}
|
|
1328
|
-
function formatTime(value) {
|
|
1329
|
-
return formatted(value, "time");
|
|
1330
|
-
}
|
|
1331
|
-
function formatDay(value) {
|
|
1332
|
-
return formatted(value, "day");
|
|
1333
|
-
}
|
|
1334
|
-
function formatShortDay(value) {
|
|
1335
|
-
return formatted(value, "shortDay");
|
|
1336
|
-
}
|
|
1337
|
-
function formatWeekday(value) {
|
|
1338
|
-
return formatted(value, "weekday");
|
|
1339
|
-
}
|
|
1340
|
-
var dayKeyFmt = null;
|
|
1341
|
-
var calendarZone;
|
|
1342
|
-
function setCalendarZone(timeZone) {
|
|
1343
|
-
if (timeZone === calendarZone) return;
|
|
1344
|
-
calendarZone = timeZone;
|
|
1345
|
-
try {
|
|
1346
|
-
clockFormats = formatters(timeZone);
|
|
1347
|
-
dayKeyFmt = timeZone ? new Intl.DateTimeFormat("en-US", { timeZone, year: "numeric", month: "2-digit", day: "2-digit" }) : null;
|
|
1348
|
-
} catch {
|
|
1349
|
-
dayKeyFmt = null;
|
|
1350
|
-
clockFormats = formatters();
|
|
1351
|
-
}
|
|
1352
|
-
}
|
|
1353
|
-
function dayKey(d4) {
|
|
1354
|
-
if (dayKeyFmt) {
|
|
1355
|
-
const parts = dayKeyFmt.formatToParts(d4);
|
|
1356
|
-
const part = (type) => parts.find((p5) => p5.type === type)?.value ?? "";
|
|
1357
|
-
return `${part("year")}-${part("month")}-${part("day")}`;
|
|
1358
|
-
}
|
|
1359
|
-
const m4 = String(d4.getMonth() + 1).padStart(2, "0");
|
|
1360
|
-
const day = String(d4.getDate()).padStart(2, "0");
|
|
1361
|
-
return `${d4.getFullYear()}-${m4}-${day}`;
|
|
1362
|
-
}
|
|
1363
|
-
function splitKey(key) {
|
|
1364
|
-
const [y4, m4, d4] = key.split("-").map(Number);
|
|
1365
|
-
return [y4, m4 - 1, d4];
|
|
1366
|
-
}
|
|
1367
|
-
function keyAt(ms) {
|
|
1368
|
-
return new Date(ms).toISOString().slice(0, 10);
|
|
1369
|
-
}
|
|
1370
|
-
function addDays(key, days) {
|
|
1371
|
-
const [y4, m4, d4] = splitKey(key);
|
|
1372
|
-
return keyAt(Date.UTC(y4, m4, d4 + days));
|
|
1373
|
-
}
|
|
1374
|
-
function addMonths(key, months) {
|
|
1375
|
-
const [y4, m4, d4] = splitKey(key);
|
|
1376
|
-
const lastDay = new Date(Date.UTC(y4, m4 + months + 1, 0)).getUTCDate();
|
|
1377
|
-
return keyAt(Date.UTC(y4, m4 + months, Math.min(d4, lastDay)));
|
|
1378
|
-
}
|
|
1379
|
-
function daysFromToday(value, now = /* @__PURE__ */ new Date()) {
|
|
1380
|
-
if (typeof value === "string" && /^\d{4}-\d{2}-\d{2}$/.test(value)) {
|
|
1381
|
-
const [y4, m4, d4] = splitKey(value);
|
|
1382
|
-
const [ty, tm, td] = splitKey(dayKey(now));
|
|
1383
|
-
return Math.round((Date.UTC(y4, m4, d4) - Date.UTC(ty, tm, td)) / 864e5);
|
|
1384
|
-
}
|
|
1385
|
-
const target = parseDate(value);
|
|
1386
|
-
if (!target) return null;
|
|
1387
|
-
const a4 = Date.UTC(...splitKey(dayKey(now)));
|
|
1388
|
-
const b4 = Date.UTC(...splitKey(dayKey(target)));
|
|
1389
|
-
return Math.round((b4 - a4) / 864e5);
|
|
1390
|
-
}
|
|
1391
|
-
function relativeDay(value, now = /* @__PURE__ */ new Date()) {
|
|
1392
|
-
const diff = daysFromToday(value, now);
|
|
1393
|
-
if (diff === null) return "";
|
|
1394
|
-
if (diff === 0) return "today";
|
|
1395
|
-
if (diff === 1) return "tomorrow";
|
|
1396
|
-
if (diff === -1) return "yesterday";
|
|
1397
|
-
if (diff > 1 && diff <= 7) return `in ${diff} days`;
|
|
1398
|
-
if (diff < -1 && diff >= -7) return `${Math.abs(diff)} days ago`;
|
|
1399
|
-
return formatShortDay(value);
|
|
1400
|
-
}
|
|
1401
|
-
function formatDuration(minutes) {
|
|
1402
|
-
const h5 = Math.floor(minutes / 60);
|
|
1403
|
-
const m4 = minutes % 60;
|
|
1404
|
-
if (h5 === 0) return `${m4} min`;
|
|
1405
|
-
if (m4 === 0) return `${h5} h`;
|
|
1406
|
-
return `${h5} h ${m4} min`;
|
|
1407
|
-
}
|
|
1408
|
-
function relativeTime(value, now = /* @__PURE__ */ new Date()) {
|
|
1409
|
-
const d4 = parseDate(value);
|
|
1410
|
-
if (!d4) return "";
|
|
1411
|
-
const seconds = Math.round((now.getTime() - d4.getTime()) / 1e3);
|
|
1412
|
-
if (seconds < 60) return "just now";
|
|
1413
|
-
const minutes = Math.round(seconds / 60);
|
|
1414
|
-
if (minutes < 60) return `${minutes} min ago`;
|
|
1415
|
-
const hours = Math.round(minutes / 60);
|
|
1416
|
-
if (hours < 48) return `${hours} h ago`;
|
|
1417
|
-
const days = Math.round(hours / 24);
|
|
1418
|
-
if (days <= 30) return `${days} days ago`;
|
|
1419
|
-
return dayKey(d4).slice(0, 4) === dayKey(now).slice(0, 4) ? formatShortDay(value) : formatted(value, "shortDayYear");
|
|
1420
|
-
}
|
|
1421
|
-
function firstLine(text) {
|
|
1422
|
-
const line = String(text).split("\n").find((l5) => l5.trim() !== "") ?? "";
|
|
1423
|
-
return line.replace(/^[#>*\-\s]+/, "").replace(/[*_`]/g, "").trim();
|
|
1424
|
-
}
|
|
1425
|
-
|
|
1426
|
-
// client/timer.ts
|
|
1427
|
-
function clock(seconds) {
|
|
1428
|
-
const total = Math.abs(seconds);
|
|
1429
|
-
const mm = Math.floor(total / 60);
|
|
1430
|
-
const ss = Math.floor(total % 60);
|
|
1431
|
-
return `${seconds < 0 ? "+" : ""}${mm}:${String(ss).padStart(2, "0")}`;
|
|
1432
|
-
}
|
|
1433
|
-
function remainingSeconds(active, nowMs) {
|
|
1434
|
-
return Math.round((new Date(active.endsAt).getTime() - nowMs) / 1e3);
|
|
1435
|
-
}
|
|
1436
|
-
function unattendedNotice(closed, handlers2) {
|
|
1437
|
-
const stoppedAt = formatTime(closed.endedAt);
|
|
1438
|
-
const headline = closed.reason === "away" ? `Timer stopped at ${stoppedAt} \u2014 nothing had touched the machine since.` : `Timer stopped at ${stoppedAt} \u2014 it had been left running.`;
|
|
1439
|
-
return el(
|
|
1440
|
-
"div",
|
|
1441
|
-
{ class: "timer__away", role: "status" },
|
|
1442
|
-
el(
|
|
1443
|
-
"span",
|
|
1444
|
-
{ class: "timer__away-body" },
|
|
1445
|
-
el("span", { class: "timer__away-text" }, headline),
|
|
1446
|
-
el(
|
|
1447
|
-
"span",
|
|
1448
|
-
{ class: "timer__away-detail" },
|
|
1449
|
-
`${formatDuration(closed.actualMinutes)} logged on \u201C${closed.title}\u201D. `,
|
|
1450
|
-
closed.reason === "away" ? "The time you were away is not in the record." : "Treat that as an upper bound, not a measurement."
|
|
1451
|
-
)
|
|
1452
|
-
),
|
|
1453
|
-
el("button", { type: "button", class: "button", onClick: () => handlers2.startSession(closed.id) }, "Pick it back up"),
|
|
1454
|
-
el(
|
|
1455
|
-
"button",
|
|
1456
|
-
{
|
|
1457
|
-
type: "button",
|
|
1458
|
-
class: "icon-button",
|
|
1459
|
-
"aria-label": "Dismiss",
|
|
1460
|
-
onClick: () => handlers2.dismissUnattended(closed.endedAt)
|
|
1461
|
-
},
|
|
1462
|
-
"\u2715"
|
|
1463
|
-
)
|
|
1464
|
-
);
|
|
1465
|
-
}
|
|
1466
|
-
function Timer({ state: state2, ui: ui2, handlers: handlers2 }) {
|
|
1467
|
-
const { active, completedToday, minutesToday, unattendedClose } = state2.session;
|
|
1468
|
-
const closed = unattendedClose && ui2.unattendedSeen.value !== unattendedClose.endedAt ? unattendedClose : null;
|
|
1469
|
-
if (!active && completedToday === 0 && !closed) {
|
|
1470
|
-
return el("div", { class: "timer", id: "timer", hidden: true });
|
|
1471
|
-
}
|
|
1472
|
-
const tally = completedToday > 0 ? `${completedToday} session${completedToday === 1 ? "" : "s"} today \xB7 ${formatDuration(minutesToday)}` : null;
|
|
1473
|
-
if (!active) {
|
|
1474
|
-
return el(
|
|
1475
|
-
"div",
|
|
1476
|
-
{ class: "timer", id: "timer", hidden: false, "data-state": closed ? "stopped" : "idle" },
|
|
1477
|
-
closed ? unattendedNotice(closed, handlers2) : null,
|
|
1478
|
-
tally ? el("span", { class: "timer__tally" }, tally) : null
|
|
1479
|
-
);
|
|
1480
|
-
}
|
|
1481
|
-
const remaining = remainingSeconds(active, ui2.clock.value);
|
|
1482
|
-
const overrun = remaining < 0;
|
|
1483
|
-
return el(
|
|
1484
|
-
"div",
|
|
1485
|
-
{ class: "timer", id: "timer", hidden: false, "data-state": overrun ? "overrun" : "running" },
|
|
1486
|
-
el("span", { class: "timer__clock" }, clock(remaining)),
|
|
1487
|
-
el(
|
|
1488
|
-
"span",
|
|
1489
|
-
{ class: "timer__title" },
|
|
1490
|
-
active.title,
|
|
1491
|
-
overrun ? el("span", { class: "timer__note" }, ` \xB7 ${active.minutes} min in, still counting`) : null,
|
|
1492
|
-
// The one thing a kitchen timer can't tell you.
|
|
1493
|
-
active.collidesWithNextEvent && !overrun ? el("span", { class: "timer__note timer__note--warn" }, ` \xB7 runs into ${formatTime(active.nextEventAt)}`) : null
|
|
1494
|
-
),
|
|
1495
|
-
tally ? el("span", { class: "timer__tally" }, tally) : null,
|
|
1496
|
-
el("button", { type: "button", class: "button", onClick: () => handlers2.stopSession() }, "Stop")
|
|
1497
|
-
);
|
|
1498
|
-
}
|
|
1499
|
-
|
|
1500
1327
|
// client/actions.ts
|
|
1501
1328
|
function afterRender(fn) {
|
|
1502
1329
|
if (typeof requestAnimationFrame === "function") requestAnimationFrame(fn);
|
|
@@ -1550,7 +1377,6 @@ function adoptState(next) {
|
|
|
1550
1377
|
state.value = next;
|
|
1551
1378
|
ui.connectionError.value = null;
|
|
1552
1379
|
});
|
|
1553
|
-
startLocalTick();
|
|
1554
1380
|
checkStore(next.storeId);
|
|
1555
1381
|
checkAssetVersion(next.assetVersion);
|
|
1556
1382
|
}
|
|
@@ -1714,6 +1540,27 @@ async function stopAssistant(id) {
|
|
|
1714
1540
|
showToast(`Could not stop: ${err.message}`);
|
|
1715
1541
|
}
|
|
1716
1542
|
}
|
|
1543
|
+
async function copy(text) {
|
|
1544
|
+
try {
|
|
1545
|
+
if (navigator.clipboard && window.isSecureContext) {
|
|
1546
|
+
await navigator.clipboard.writeText(text);
|
|
1547
|
+
} else {
|
|
1548
|
+
const field = document.createElement("textarea");
|
|
1549
|
+
field.value = text;
|
|
1550
|
+
field.setAttribute("readonly", "");
|
|
1551
|
+
field.style.position = "fixed";
|
|
1552
|
+
field.style.opacity = "0";
|
|
1553
|
+
document.body.append(field);
|
|
1554
|
+
field.select();
|
|
1555
|
+
const copied = document.execCommand("copy");
|
|
1556
|
+
field.remove();
|
|
1557
|
+
if (!copied) throw new Error("the browser would not copy");
|
|
1558
|
+
}
|
|
1559
|
+
showToast("Copied");
|
|
1560
|
+
} catch (err) {
|
|
1561
|
+
showToast(`Could not copy: ${err.message}`);
|
|
1562
|
+
}
|
|
1563
|
+
}
|
|
1717
1564
|
async function runAgent() {
|
|
1718
1565
|
if (!state.value?.agentRun?.enabled || state.value.agentRun.last?.status === "running") return;
|
|
1719
1566
|
const ok = window.confirm(
|
|
@@ -1742,53 +1589,6 @@ async function askAgent(run, text) {
|
|
|
1742
1589
|
showToast(`Could not ask the morning agent: ${err.message}`);
|
|
1743
1590
|
}
|
|
1744
1591
|
}
|
|
1745
|
-
async function changeSession(body) {
|
|
1746
|
-
if (body.action === "start" && "Notification" in window && Notification.permission === "default") {
|
|
1747
|
-
void Notification.requestPermission();
|
|
1748
|
-
}
|
|
1749
|
-
try {
|
|
1750
|
-
state.value = await postSession(body);
|
|
1751
|
-
startLocalTick();
|
|
1752
|
-
} catch (err) {
|
|
1753
|
-
showToast(`Could not change the timer: ${err.message}`);
|
|
1754
|
-
}
|
|
1755
|
-
}
|
|
1756
|
-
var tickTimer = null;
|
|
1757
|
-
var announcedOverrunFor = null;
|
|
1758
|
-
function startLocalTick() {
|
|
1759
|
-
if (tickTimer) clearInterval(tickTimer);
|
|
1760
|
-
tickTimer = setInterval(tick, 1e3);
|
|
1761
|
-
tick();
|
|
1762
|
-
}
|
|
1763
|
-
function tick() {
|
|
1764
|
-
const active = state.value?.session.active;
|
|
1765
|
-
if (!active) {
|
|
1766
|
-
document.title = "Daily Focus";
|
|
1767
|
-
if (tickTimer) clearInterval(tickTimer);
|
|
1768
|
-
tickTimer = null;
|
|
1769
|
-
return;
|
|
1770
|
-
}
|
|
1771
|
-
const nowMs = Date.now();
|
|
1772
|
-
ui.clock.value = nowMs;
|
|
1773
|
-
const remaining = remainingSeconds(active, nowMs);
|
|
1774
|
-
const mm = Math.floor(Math.abs(remaining) / 60);
|
|
1775
|
-
const ss = String(Math.floor(Math.abs(remaining) % 60)).padStart(2, "0");
|
|
1776
|
-
document.title = `${remaining < 0 ? "+" : ""}${mm}:${ss} \xB7 ${active.title}`;
|
|
1777
|
-
if (remaining <= 0 && announcedOverrunFor !== active.startedAt) {
|
|
1778
|
-
announcedOverrunFor = active.startedAt;
|
|
1779
|
-
announceSessionEnd(active);
|
|
1780
|
-
}
|
|
1781
|
-
}
|
|
1782
|
-
function announceSessionEnd(active) {
|
|
1783
|
-
const label = active.minutes === 1 ? "1 minute" : `${active.minutes} minutes`;
|
|
1784
|
-
showToast(`${label} in \u2014 still on "${active.title}"?`, null);
|
|
1785
|
-
if ("Notification" in window && Notification.permission === "granted") {
|
|
1786
|
-
new Notification("Still on this?", {
|
|
1787
|
-
body: `${label} in on ${active.title}. Keep going, or stop and log it.`,
|
|
1788
|
-
tag: "daily-focus-session"
|
|
1789
|
-
});
|
|
1790
|
-
}
|
|
1791
|
-
}
|
|
1792
1592
|
function showView(view) {
|
|
1793
1593
|
if (ui.view.value === view) return;
|
|
1794
1594
|
if (state.value && !availableViews(state.value).includes(view)) return;
|
|
@@ -1837,10 +1637,6 @@ function setTicketMode(mode) {
|
|
|
1837
1637
|
closeMenus();
|
|
1838
1638
|
});
|
|
1839
1639
|
}
|
|
1840
|
-
function setFocusMode(on) {
|
|
1841
|
-
ui.focusMode.value = on;
|
|
1842
|
-
remember(FOCUS_MODE_KEY, on ? "1" : null);
|
|
1843
|
-
}
|
|
1844
1640
|
function restartToast(page) {
|
|
1845
1641
|
if (page.restart === "manual") showToast("Saved. Restart the dashboard to apply it.");
|
|
1846
1642
|
else if (page.restart === "waiting" && state.value?.agentRun?.last?.status === "running") {
|
|
@@ -2063,12 +1859,6 @@ var handlers = {
|
|
|
2063
1859
|
() => document.querySelector('#tickets .item[data-selected="true"]')?.scrollIntoView({ block: "center", behavior: "smooth" })
|
|
2064
1860
|
);
|
|
2065
1861
|
},
|
|
2066
|
-
startSession: (id) => void changeSession({ action: "start", id }),
|
|
2067
|
-
stopSession: () => void changeSession({ action: "stop" }),
|
|
2068
|
-
dismissUnattended: (endedAt) => {
|
|
2069
|
-
ui.unattendedSeen.value = endedAt;
|
|
2070
|
-
remember(UNATTENDED_SEEN_KEY, endedAt);
|
|
2071
|
-
},
|
|
2072
1862
|
// A nudge on Slack is invisible to GitHub, so it's recorded: the board's nudge
|
|
2073
1863
|
// timer starts over from it, and the agent reads that the user asked.
|
|
2074
1864
|
nudge: (id) => void applyAction(id, "nudge"),
|
|
@@ -2078,6 +1868,7 @@ var handlers = {
|
|
|
2078
1868
|
refreshCalendar: () => void refreshCalendar(),
|
|
2079
1869
|
ask: (id, body) => void ask(id, body),
|
|
2080
1870
|
stopAssistant: (id) => void stopAssistant(id),
|
|
1871
|
+
copy: (text) => void copy(text),
|
|
2081
1872
|
runAgent: () => void runAgent(),
|
|
2082
1873
|
stopAgent: () => void stopAgent(),
|
|
2083
1874
|
askAgent: (run, text) => void askAgent(run, text),
|
|
@@ -2096,7 +1887,6 @@ var handlers = {
|
|
|
2096
1887
|
applyTheme(mode);
|
|
2097
1888
|
ui.theme.value = mode;
|
|
2098
1889
|
},
|
|
2099
|
-
setFocusMode,
|
|
2100
1890
|
openHelp: () => document.getElementById("help")?.showModal(),
|
|
2101
1891
|
hideToast,
|
|
2102
1892
|
openSettings,
|
|
@@ -2117,6 +1907,145 @@ var handlers = {
|
|
|
2117
1907
|
listCalendars: () => void listCalendars()
|
|
2118
1908
|
};
|
|
2119
1909
|
|
|
1910
|
+
// client/format.ts
|
|
1911
|
+
var DAY_FORMAT = {
|
|
1912
|
+
weekday: "long",
|
|
1913
|
+
day: "numeric",
|
|
1914
|
+
month: "long"
|
|
1915
|
+
};
|
|
1916
|
+
function formatters(timeZone) {
|
|
1917
|
+
return {
|
|
1918
|
+
time: new Intl.DateTimeFormat(void 0, { timeZone, hour: "2-digit", minute: "2-digit" }),
|
|
1919
|
+
day: new Intl.DateTimeFormat(void 0, { timeZone, ...DAY_FORMAT }),
|
|
1920
|
+
shortDay: new Intl.DateTimeFormat(void 0, { timeZone, day: "numeric", month: "short" }),
|
|
1921
|
+
shortDayYear: new Intl.DateTimeFormat(void 0, { timeZone, day: "numeric", month: "short", year: "numeric" }),
|
|
1922
|
+
weekday: new Intl.DateTimeFormat(void 0, { timeZone, weekday: "long" })
|
|
1923
|
+
};
|
|
1924
|
+
}
|
|
1925
|
+
var clockFormats = formatters();
|
|
1926
|
+
var dateFormats = formatters("UTC");
|
|
1927
|
+
var DATE_ONLY = /^\d{4}-\d{2}-\d{2}$/;
|
|
1928
|
+
function formatted(value, kind) {
|
|
1929
|
+
const bare = typeof value === "string" && DATE_ONLY.test(value);
|
|
1930
|
+
const d5 = bare ? /* @__PURE__ */ new Date(`${value}T00:00:00Z`) : parseDate(value);
|
|
1931
|
+
return d5 && !Number.isNaN(d5.getTime()) ? (bare ? dateFormats : clockFormats)[kind].format(d5) : "";
|
|
1932
|
+
}
|
|
1933
|
+
function parseDate(value) {
|
|
1934
|
+
if (typeof value !== "string" || value === "") return null;
|
|
1935
|
+
const dateOnly = /^(\d{4})-(\d{2})-(\d{2})$/.exec(value);
|
|
1936
|
+
if (dateOnly) return new Date(+dateOnly[1], +dateOnly[2] - 1, +dateOnly[3]);
|
|
1937
|
+
const d5 = new Date(value);
|
|
1938
|
+
return Number.isNaN(d5.getTime()) ? null : d5;
|
|
1939
|
+
}
|
|
1940
|
+
function formatTime(value) {
|
|
1941
|
+
return formatted(value, "time");
|
|
1942
|
+
}
|
|
1943
|
+
function formatDay(value) {
|
|
1944
|
+
return formatted(value, "day");
|
|
1945
|
+
}
|
|
1946
|
+
function formatShortDay(value) {
|
|
1947
|
+
return formatted(value, "shortDay");
|
|
1948
|
+
}
|
|
1949
|
+
function formatWeekday(value) {
|
|
1950
|
+
return formatted(value, "weekday");
|
|
1951
|
+
}
|
|
1952
|
+
var dayKeyFmt = null;
|
|
1953
|
+
var calendarZone;
|
|
1954
|
+
function setCalendarZone(timeZone) {
|
|
1955
|
+
if (timeZone === calendarZone) return;
|
|
1956
|
+
calendarZone = timeZone;
|
|
1957
|
+
try {
|
|
1958
|
+
clockFormats = formatters(timeZone);
|
|
1959
|
+
dayKeyFmt = timeZone ? new Intl.DateTimeFormat("en-US", { timeZone, year: "numeric", month: "2-digit", day: "2-digit" }) : null;
|
|
1960
|
+
} catch {
|
|
1961
|
+
dayKeyFmt = null;
|
|
1962
|
+
clockFormats = formatters();
|
|
1963
|
+
}
|
|
1964
|
+
}
|
|
1965
|
+
function dayKey(d5) {
|
|
1966
|
+
if (dayKeyFmt) {
|
|
1967
|
+
const parts = dayKeyFmt.formatToParts(d5);
|
|
1968
|
+
const part = (type) => parts.find((p5) => p5.type === type)?.value ?? "";
|
|
1969
|
+
return `${part("year")}-${part("month")}-${part("day")}`;
|
|
1970
|
+
}
|
|
1971
|
+
const m4 = String(d5.getMonth() + 1).padStart(2, "0");
|
|
1972
|
+
const day = String(d5.getDate()).padStart(2, "0");
|
|
1973
|
+
return `${d5.getFullYear()}-${m4}-${day}`;
|
|
1974
|
+
}
|
|
1975
|
+
function splitKey(key) {
|
|
1976
|
+
const [y5, m4, d5] = key.split("-").map(Number);
|
|
1977
|
+
return [y5, m4 - 1, d5];
|
|
1978
|
+
}
|
|
1979
|
+
function keyAt(ms) {
|
|
1980
|
+
return new Date(ms).toISOString().slice(0, 10);
|
|
1981
|
+
}
|
|
1982
|
+
function addDays(key, days) {
|
|
1983
|
+
const [y5, m4, d5] = splitKey(key);
|
|
1984
|
+
return keyAt(Date.UTC(y5, m4, d5 + days));
|
|
1985
|
+
}
|
|
1986
|
+
function addMonths(key, months) {
|
|
1987
|
+
const [y5, m4, d5] = splitKey(key);
|
|
1988
|
+
const lastDay = new Date(Date.UTC(y5, m4 + months + 1, 0)).getUTCDate();
|
|
1989
|
+
return keyAt(Date.UTC(y5, m4 + months, Math.min(d5, lastDay)));
|
|
1990
|
+
}
|
|
1991
|
+
function daysFromToday(value, now = /* @__PURE__ */ new Date()) {
|
|
1992
|
+
if (typeof value === "string" && /^\d{4}-\d{2}-\d{2}$/.test(value)) {
|
|
1993
|
+
const [y5, m4, d5] = splitKey(value);
|
|
1994
|
+
const [ty, tm, td] = splitKey(dayKey(now));
|
|
1995
|
+
return Math.round((Date.UTC(y5, m4, d5) - Date.UTC(ty, tm, td)) / 864e5);
|
|
1996
|
+
}
|
|
1997
|
+
const target = parseDate(value);
|
|
1998
|
+
if (!target) return null;
|
|
1999
|
+
const a4 = Date.UTC(...splitKey(dayKey(now)));
|
|
2000
|
+
const b4 = Date.UTC(...splitKey(dayKey(target)));
|
|
2001
|
+
return Math.round((b4 - a4) / 864e5);
|
|
2002
|
+
}
|
|
2003
|
+
function relativeDay(value, now = /* @__PURE__ */ new Date()) {
|
|
2004
|
+
const diff = daysFromToday(value, now);
|
|
2005
|
+
if (diff === null) return "";
|
|
2006
|
+
if (diff === 0) return "today";
|
|
2007
|
+
if (diff === 1) return "tomorrow";
|
|
2008
|
+
if (diff === -1) return "yesterday";
|
|
2009
|
+
if (diff > 1 && diff <= 7) return `in ${diff} days`;
|
|
2010
|
+
if (diff < -1 && diff >= -7) return `${Math.abs(diff)} days ago`;
|
|
2011
|
+
return formatShortDay(value);
|
|
2012
|
+
}
|
|
2013
|
+
function formatDuration(minutes) {
|
|
2014
|
+
const h5 = Math.floor(minutes / 60);
|
|
2015
|
+
const m4 = minutes % 60;
|
|
2016
|
+
if (h5 === 0) return `${m4} min`;
|
|
2017
|
+
if (m4 === 0) return `${h5} h`;
|
|
2018
|
+
return `${h5} h ${m4} min`;
|
|
2019
|
+
}
|
|
2020
|
+
function relativeTime(value, now = /* @__PURE__ */ new Date()) {
|
|
2021
|
+
const d5 = parseDate(value);
|
|
2022
|
+
if (!d5) return "";
|
|
2023
|
+
const seconds = Math.round((now.getTime() - d5.getTime()) / 1e3);
|
|
2024
|
+
if (seconds < 60) return "just now";
|
|
2025
|
+
const minutes = Math.round(seconds / 60);
|
|
2026
|
+
if (minutes < 60) return `${minutes} min ago`;
|
|
2027
|
+
const hours = Math.round(minutes / 60);
|
|
2028
|
+
if (hours < 48) return `${hours} h ago`;
|
|
2029
|
+
const days = Math.round(hours / 24);
|
|
2030
|
+
if (days <= 30) return `${days} days ago`;
|
|
2031
|
+
return dayKey(d5).slice(0, 4) === dayKey(now).slice(0, 4) ? formatShortDay(value) : formatted(value, "shortDayYear");
|
|
2032
|
+
}
|
|
2033
|
+
function durationBetween(start, end) {
|
|
2034
|
+
const from = parseDate(start);
|
|
2035
|
+
const to = parseDate(end);
|
|
2036
|
+
if (!from || !to || to < from) return "";
|
|
2037
|
+
const seconds = Math.round((to.getTime() - from.getTime()) / 1e3);
|
|
2038
|
+
return seconds < 60 ? `${seconds} s` : formatDuration(Math.round(seconds / 60));
|
|
2039
|
+
}
|
|
2040
|
+
function formatClock(seconds) {
|
|
2041
|
+
const whole = Math.max(0, Math.floor(seconds));
|
|
2042
|
+
return `${Math.floor(whole / 60)}:${String(whole % 60).padStart(2, "0")}`;
|
|
2043
|
+
}
|
|
2044
|
+
function firstLine(text) {
|
|
2045
|
+
const line = String(text).split("\n").find((l5) => l5.trim() !== "") ?? "";
|
|
2046
|
+
return line.replace(/^[#>*\-\s]+/, "").replace(/[*_`]/g, "").trim();
|
|
2047
|
+
}
|
|
2048
|
+
|
|
2120
2049
|
// client/failure.ts
|
|
2121
2050
|
function failureNotice(failure, { fold, className, icon, lastGood, now, onRetry }, ui2, handlers2) {
|
|
2122
2051
|
return el(
|
|
@@ -2310,7 +2239,7 @@ function renderMarkdown(value) {
|
|
|
2310
2239
|
function anchor(href, label) {
|
|
2311
2240
|
return el("a", { href: /^https?:\/\//i.test(href) ? href : "#", target: "_blank", rel: "noopener noreferrer" }, label);
|
|
2312
2241
|
}
|
|
2313
|
-
function renderMarkdownBlocks(value) {
|
|
2242
|
+
function renderMarkdownBlocks(value, options = {}) {
|
|
2314
2243
|
const out = [];
|
|
2315
2244
|
const lines = String(value).replace(/\r\n/g, "\n").split("\n");
|
|
2316
2245
|
let i4 = 0;
|
|
@@ -2321,7 +2250,16 @@ function renderMarkdownBlocks(value) {
|
|
|
2321
2250
|
i4++;
|
|
2322
2251
|
while (i4 < lines.length && !/^\s*```/.test(lines[i4])) code.push(lines[i4++]);
|
|
2323
2252
|
i4++;
|
|
2324
|
-
|
|
2253
|
+
const text = code.join("\n");
|
|
2254
|
+
const { onCopy } = options;
|
|
2255
|
+
out.push(
|
|
2256
|
+
onCopy ? el(
|
|
2257
|
+
"div",
|
|
2258
|
+
{ class: "code-block" },
|
|
2259
|
+
el("pre", null, text),
|
|
2260
|
+
el("button", { type: "button", class: "code-block__copy", title: "Copy to the clipboard", onClick: () => onCopy(text) }, "Copy")
|
|
2261
|
+
) : el("pre", null, text)
|
|
2262
|
+
);
|
|
2325
2263
|
continue;
|
|
2326
2264
|
}
|
|
2327
2265
|
if (line.trim() === "") {
|
|
@@ -2331,7 +2269,7 @@ function renderMarkdownBlocks(value) {
|
|
|
2331
2269
|
if (/^\s*>/.test(line)) {
|
|
2332
2270
|
const quoted = [];
|
|
2333
2271
|
while (i4 < lines.length && /^\s*>/.test(lines[i4])) quoted.push(lines[i4++].replace(/^\s*>\s?/, ""));
|
|
2334
|
-
out.push(el("blockquote", null, renderMarkdownBlocks(quoted.join("\n"))));
|
|
2272
|
+
out.push(el("blockquote", null, renderMarkdownBlocks(quoted.join("\n"), options)));
|
|
2335
2273
|
continue;
|
|
2336
2274
|
}
|
|
2337
2275
|
if (/^\s*(?:-{3,}|\*{3,}|_{3,})\s*$/.test(line)) {
|
|
@@ -2575,9 +2513,6 @@ function renderItem(item, state2, ui2, handlers2) {
|
|
|
2575
2513
|
function ItemRow({ item, state: state2, ui: ui2, handlers: handlers2 }) {
|
|
2576
2514
|
const now = new Date(state2.now);
|
|
2577
2515
|
const selected = ui2.selectedId.value === item.id;
|
|
2578
|
-
const active = state2.session?.active ?? null;
|
|
2579
|
-
const running = active !== null && active.id === item.id;
|
|
2580
|
-
const overrun = running && remainingSeconds(active, ui2.clock.value) < 0;
|
|
2581
2516
|
const repo = githubRepo(item);
|
|
2582
2517
|
const title = item.url ? el(
|
|
2583
2518
|
"a",
|
|
@@ -2595,8 +2530,6 @@ function ItemRow({ item, state: state2, ui: ui2, handlers: handlers2 }) {
|
|
|
2595
2530
|
"data-selected": String(selected),
|
|
2596
2531
|
"data-priority": String(item.priority !== void 0 && item.status === "open"),
|
|
2597
2532
|
"data-pending": String(ui2.pending.value.has(item.id)),
|
|
2598
|
-
"data-running": String(running),
|
|
2599
|
-
"data-overrun": String(overrun),
|
|
2600
2533
|
"data-detail": String(ui2.detailFor.value === item.id),
|
|
2601
2534
|
// A click on the card opens the panel on it: one way in, and the whole card is it.
|
|
2602
2535
|
onClick: (event) => {
|
|
@@ -2616,31 +2549,20 @@ function ItemRow({ item, state: state2, ui: ui2, handlers: handlers2 }) {
|
|
|
2616
2549
|
"div",
|
|
2617
2550
|
{ class: "item__body" },
|
|
2618
2551
|
el("p", { class: "item__title" }, title),
|
|
2619
|
-
renderMeta(item, state2,
|
|
2552
|
+
renderMeta(item, state2, now),
|
|
2620
2553
|
item.detail ? el("p", { class: "item__detail" }, renderMarkdown(item.detail)) : null
|
|
2621
2554
|
),
|
|
2622
|
-
renderActions(item,
|
|
2555
|
+
renderActions(item, ui2, handlers2),
|
|
2623
2556
|
ui2.menuFor.value === item.id ? renderSnoozeMenu(item, now, handlers2) : null
|
|
2624
2557
|
);
|
|
2625
2558
|
}
|
|
2626
|
-
function renderMeta(item, state2,
|
|
2559
|
+
function renderMeta(item, state2, now) {
|
|
2627
2560
|
const pills = [];
|
|
2628
2561
|
const said = /* @__PURE__ */ new Set();
|
|
2629
2562
|
const pill = (cls, text) => {
|
|
2630
2563
|
pills.push(el("span", { class: cls }, text));
|
|
2631
2564
|
said.add(text.trim().toLowerCase());
|
|
2632
2565
|
};
|
|
2633
|
-
const active = state2.session?.active ?? null;
|
|
2634
|
-
if (active && active.id === item.id) {
|
|
2635
|
-
pills.push(
|
|
2636
|
-
el(
|
|
2637
|
-
"span",
|
|
2638
|
-
{ class: "pill pill--running" },
|
|
2639
|
-
el("span", { class: "item__running-clock" }, clock(remainingSeconds(active, ui2.clock.value))),
|
|
2640
|
-
" focusing"
|
|
2641
|
-
)
|
|
2642
|
-
);
|
|
2643
|
-
}
|
|
2644
2566
|
if (item.priority !== void 0 && item.status === "open") {
|
|
2645
2567
|
pill("pill pill--priority", `#${item.priority}`);
|
|
2646
2568
|
}
|
|
@@ -2692,24 +2614,11 @@ function rowPillTexts(row, state2) {
|
|
|
2692
2614
|
function rowPills(row, state2) {
|
|
2693
2615
|
return rowPillTexts(row, state2).map(([cls, text]) => el("span", { class: cls }, text));
|
|
2694
2616
|
}
|
|
2695
|
-
function renderActions(item,
|
|
2617
|
+
function renderActions(item, ui2, handlers2) {
|
|
2696
2618
|
const buttons = [];
|
|
2697
2619
|
const act = (id, action) => () => handlers2.onAction(id, action);
|
|
2698
|
-
const running = state2.session?.active?.id === item.id;
|
|
2699
2620
|
if (item.status === "open") {
|
|
2700
2621
|
if (item.kind === "task") {
|
|
2701
|
-
buttons.push(
|
|
2702
|
-
el(
|
|
2703
|
-
"button",
|
|
2704
|
-
{
|
|
2705
|
-
type: "button",
|
|
2706
|
-
class: running ? "button button--primary" : "button",
|
|
2707
|
-
title: running ? "Stop the focus session" : "Start a focus session on this",
|
|
2708
|
-
onClick: () => running ? handlers2.stopSession() : handlers2.startSession(item.id)
|
|
2709
|
-
},
|
|
2710
|
-
running ? "Stop" : "Focus"
|
|
2711
|
-
)
|
|
2712
|
-
);
|
|
2713
2622
|
buttons.push(el("button", { type: "button", class: "button", onClick: act(item.id, "done") }, "Done"));
|
|
2714
2623
|
buttons.push(
|
|
2715
2624
|
el(
|
|
@@ -3776,8 +3685,6 @@ var SHORTCUTS = [
|
|
|
3776
3685
|
[["Esc"], "Close the menu, then the panel"],
|
|
3777
3686
|
[["o"], "Open the source link"],
|
|
3778
3687
|
[["u"], "Undo the last action"],
|
|
3779
|
-
[["f"], "Focus mode \u2014 hide all but the top item"],
|
|
3780
|
-
[["p"], "Start a focus session on the selected item"],
|
|
3781
3688
|
[["r"], "Refresh whichever board you are on"],
|
|
3782
3689
|
[["w"], "Jira tickets: switch between out of sync and working on"],
|
|
3783
3690
|
[[","], "Settings: your objective, where the agent looks, and the rest"],
|
|
@@ -3971,11 +3878,7 @@ function runStatus(run, now, handlers2) {
|
|
|
3971
3878
|
);
|
|
3972
3879
|
}
|
|
3973
3880
|
function runDuration(run) {
|
|
3974
|
-
|
|
3975
|
-
const to = parseDate(run.endedAt);
|
|
3976
|
-
if (!from || !to || to < from) return "";
|
|
3977
|
-
const seconds = Math.round((to.getTime() - from.getTime()) / 1e3);
|
|
3978
|
-
return seconds < 60 ? `${seconds} s` : formatDuration(Math.round(seconds / 60));
|
|
3881
|
+
return durationBetween(run.startedAt, run.endedAt);
|
|
3979
3882
|
}
|
|
3980
3883
|
function runConversation(run, busy, answering, enabled, ui2, handlers2, inputRef) {
|
|
3981
3884
|
const turns = run.turns.length ? el(
|
|
@@ -4131,8 +4034,9 @@ function RowPanel({ row, state: state2, ui: ui2, handlers: handlers2 }) {
|
|
|
4131
4034
|
) : el("p", { class: "flyout__empty" }, "Nothing noted yet. A note goes to the morning agent as free text."),
|
|
4132
4035
|
k(NoteForm, { row, title: facts.title, ui: ui2, handlers: handlers2, inputRef: noteInput })
|
|
4133
4036
|
),
|
|
4134
|
-
|
|
4135
|
-
)
|
|
4037
|
+
entry.turns.length ? renderAssistantSection(state2, entry, enabled, handlers2) : null
|
|
4038
|
+
),
|
|
4039
|
+
enabled ? renderAssistantFooter(facts, state2, entry, ui2, handlers2, askInput, row) : null
|
|
4136
4040
|
];
|
|
4137
4041
|
}
|
|
4138
4042
|
function describeRow(row) {
|
|
@@ -4233,21 +4137,27 @@ function NoteForm({
|
|
|
4233
4137
|
el("button", { type: "submit", class: "button button--primary flyout__submit" }, "Save")
|
|
4234
4138
|
);
|
|
4235
4139
|
}
|
|
4236
|
-
function renderAssistantSection(
|
|
4237
|
-
const source = "source" in row ? row.source : "github";
|
|
4238
|
-
const actions = (state2.assistant?.quickActions ?? []).filter(
|
|
4239
|
-
(action) => action.sources === null || action.sources.includes(source)
|
|
4240
|
-
);
|
|
4140
|
+
function renderAssistantSection(state2, entry, enabled, handlers2) {
|
|
4241
4141
|
const label = new Map((state2.assistant?.quickActions ?? []).map((action) => [action.id, action]));
|
|
4242
4142
|
return el(
|
|
4243
4143
|
"section",
|
|
4244
4144
|
{ class: "flyout__section assistant", "data-running": String(entry.running) },
|
|
4245
4145
|
el("h3", { class: "flyout__label" }, "Assistant"),
|
|
4246
|
-
|
|
4146
|
+
el(
|
|
4247
4147
|
"div",
|
|
4248
4148
|
{ class: "assistant__turns" },
|
|
4249
|
-
entry.turns.map((turn) => renderAssistantTurn(turn, label))
|
|
4250
|
-
)
|
|
4149
|
+
entry.turns.map((turn) => renderAssistantTurn(turn, label, handlers2))
|
|
4150
|
+
),
|
|
4151
|
+
enabled ? null : el("p", { class: "flyout__empty" }, "The assistant is switched off (DAILY_FOCUS_ASSISTANT), so nothing more can be asked here.")
|
|
4152
|
+
);
|
|
4153
|
+
}
|
|
4154
|
+
function renderAssistantFooter(facts, state2, entry, ui2, handlers2, inputRef, row) {
|
|
4155
|
+
const actions = (state2.assistant?.quickActions ?? []).filter(
|
|
4156
|
+
(action) => action.sources === null || action.sources.includes(facts.source)
|
|
4157
|
+
);
|
|
4158
|
+
return el(
|
|
4159
|
+
"div",
|
|
4160
|
+
{ class: "flyout__footer" },
|
|
4251
4161
|
entry.running ? null : el(
|
|
4252
4162
|
"div",
|
|
4253
4163
|
{ class: "assistant__quick" },
|
|
@@ -4267,20 +4177,6 @@ function renderAssistantSection(row, facts, state2, entry, ui2, handlers2, input
|
|
|
4267
4177
|
k(AssistantComposer, { row, title: facts.title, entry, ui: ui2, handlers: handlers2, inputRef })
|
|
4268
4178
|
);
|
|
4269
4179
|
}
|
|
4270
|
-
function renderAssistantHistory(state2, entry) {
|
|
4271
|
-
const label = new Map((state2.assistant?.quickActions ?? []).map((action) => [action.id, action]));
|
|
4272
|
-
return el(
|
|
4273
|
-
"section",
|
|
4274
|
-
{ class: "flyout__section assistant", "data-running": "false" },
|
|
4275
|
-
el("h3", { class: "flyout__label" }, "Assistant"),
|
|
4276
|
-
el(
|
|
4277
|
-
"div",
|
|
4278
|
-
{ class: "assistant__turns" },
|
|
4279
|
-
entry.turns.map((turn) => renderAssistantTurn(turn, label))
|
|
4280
|
-
),
|
|
4281
|
-
el("p", { class: "flyout__empty" }, "The assistant is switched off (DAILY_FOCUS_ASSISTANT), so nothing more can be asked here.")
|
|
4282
|
-
);
|
|
4283
|
-
}
|
|
4284
4180
|
function AssistantComposer({
|
|
4285
4181
|
row,
|
|
4286
4182
|
title,
|
|
@@ -4309,7 +4205,7 @@ function AssistantComposer({
|
|
|
4309
4205
|
rows: 2,
|
|
4310
4206
|
ref: inputRef,
|
|
4311
4207
|
value: ui2.assistantDraft.value,
|
|
4312
|
-
placeholder: entry.turns.length ? "Follow up\u2026" : "
|
|
4208
|
+
placeholder: entry.turns.length ? "Follow up\u2026" : "Ask the assistant about this\u2026",
|
|
4313
4209
|
"aria-label": `Ask the assistant about ${title}`,
|
|
4314
4210
|
disabled: entry.running,
|
|
4315
4211
|
onInput: (event) => {
|
|
@@ -4325,19 +4221,83 @@ function AssistantComposer({
|
|
|
4325
4221
|
entry.running ? el("button", { type: "button", class: "button flyout__submit", onClick: () => handlers2.stopAssistant(row.id) }, "Stop") : el("button", { type: "submit", class: "button button--primary flyout__submit" }, "Send")
|
|
4326
4222
|
);
|
|
4327
4223
|
}
|
|
4328
|
-
function renderAssistantTurn(turn, label) {
|
|
4224
|
+
function renderAssistantTurn(turn, label, handlers2) {
|
|
4329
4225
|
const action = turn.action ? label.get(turn.action) : null;
|
|
4330
4226
|
const extra = action && turn.request.startsWith(action.request) ? turn.request.slice(action.request.length).trim() : null;
|
|
4331
4227
|
const asked = action ? [el("strong", null, action.label), extra ? ` \u2014 ${extra}` : ""] : [turn.request];
|
|
4332
|
-
const
|
|
4228
|
+
const { body, created } = turn.status === "done" ? splitCreated(turn.reply) : { body: turn.reply, created: [] };
|
|
4229
|
+
const status = turn.status === "failed" ? el("p", { class: "assistant__status assistant__status--bad" }, `Failed: ${turn.error}`) : turn.status === "aborted" ? el("p", { class: "assistant__status" }, `Stopped: ${turn.error}`) : null;
|
|
4333
4230
|
return el(
|
|
4334
4231
|
"div",
|
|
4335
|
-
{ class: "assistant__turn", "data-status": turn.status },
|
|
4232
|
+
{ key: turn.id, class: "assistant__turn", "data-status": turn.status },
|
|
4336
4233
|
el("p", { class: "assistant__request" }, asked),
|
|
4337
|
-
|
|
4338
|
-
|
|
4234
|
+
renderWork(turn),
|
|
4235
|
+
body ? el("div", { class: "assistant__reply" }, renderMarkdownBlocks(body, { onCopy: (text) => handlers2.copy(text) })) : null,
|
|
4236
|
+
status,
|
|
4237
|
+
turn.status === "done" && (body || created.length) ? el(
|
|
4238
|
+
"div",
|
|
4239
|
+
{ class: "assistant__after" },
|
|
4240
|
+
created.map(
|
|
4241
|
+
(link) => el("a", { class: "button", href: link.url, target: "_blank", rel: "noopener noreferrer", title: link.url }, `${link.label} \u2197`)
|
|
4242
|
+
),
|
|
4243
|
+
body ? el("button", { type: "button", class: "button", onClick: () => handlers2.copy(body) }, "Copy reply") : null
|
|
4244
|
+
) : null
|
|
4245
|
+
);
|
|
4246
|
+
}
|
|
4247
|
+
function renderWork(turn) {
|
|
4248
|
+
const steps = turn.steps ?? [];
|
|
4249
|
+
if (turn.status === "running") {
|
|
4250
|
+
return el(
|
|
4251
|
+
"div",
|
|
4252
|
+
{ class: "assistant__work" },
|
|
4253
|
+
el("p", { class: "assistant__status assistant__status--working" }, "Working \xB7 ", k(Elapsed, { since: turn.startedAt })),
|
|
4254
|
+
steps.length ? renderSteps(steps) : null
|
|
4255
|
+
);
|
|
4256
|
+
}
|
|
4257
|
+
const took = durationBetween(turn.startedAt, turn.endedAt);
|
|
4258
|
+
if (!steps.length) return took ? el("p", { class: "assistant__took" }, `Answered in ${took}`) : null;
|
|
4259
|
+
const failed = steps.filter((step2) => step2.state === "failed").length;
|
|
4260
|
+
const summary = [
|
|
4261
|
+
took ? `${turn.status === "done" ? "Worked" : "Ran"} for ${took}` : null,
|
|
4262
|
+
`${steps.length} ${steps.length === 1 ? "step" : "steps"}`,
|
|
4263
|
+
failed ? `${failed} failed` : null
|
|
4264
|
+
].filter(Boolean).join(" \xB7 ");
|
|
4265
|
+
return el("details", { class: "assistant__work", open: turn.status === "failed" }, el("summary", null, summary), renderSteps(steps));
|
|
4266
|
+
}
|
|
4267
|
+
function renderSteps(steps) {
|
|
4268
|
+
return el(
|
|
4269
|
+
"ol",
|
|
4270
|
+
{ class: "assistant__steps" },
|
|
4271
|
+
steps.map(
|
|
4272
|
+
(step2, index) => step2.kind === "message" ? el("li", { key: index, class: "assistant__step assistant__step--message" }, renderMarkdown(step2.text.trim())) : el(
|
|
4273
|
+
"li",
|
|
4274
|
+
{ key: index, class: "assistant__step", "data-state": step2.state },
|
|
4275
|
+
el("span", { class: "assistant__step-text" }, step2.text),
|
|
4276
|
+
step2.detail ? el("code", { class: "assistant__step-detail", title: step2.detail }, step2.detail) : null
|
|
4277
|
+
)
|
|
4278
|
+
)
|
|
4339
4279
|
);
|
|
4340
4280
|
}
|
|
4281
|
+
function Elapsed({ since }) {
|
|
4282
|
+
const [now, setNow] = d2(() => Date.now());
|
|
4283
|
+
h2(() => {
|
|
4284
|
+
const timer = setInterval(() => setNow(Date.now()), 1e3);
|
|
4285
|
+
return () => clearInterval(timer);
|
|
4286
|
+
}, []);
|
|
4287
|
+
const start = parseDate(since)?.getTime() ?? now;
|
|
4288
|
+
return el("span", { class: "assistant__clock" }, formatClock((now - start) / 1e3));
|
|
4289
|
+
}
|
|
4290
|
+
var CREATED = /^\s*(?:[-*]\s+)?Created:\s*\[([^\]]+)\]\((https?:\/\/[^\s)]+)\)\s*\.?\s*$/i;
|
|
4291
|
+
function splitCreated(reply) {
|
|
4292
|
+
const created = [];
|
|
4293
|
+
const kept = [];
|
|
4294
|
+
for (const line of reply.split("\n")) {
|
|
4295
|
+
const match = CREATED.exec(line);
|
|
4296
|
+
if (match) created.push({ label: match[1].trim(), url: match[2] });
|
|
4297
|
+
else kept.push(line);
|
|
4298
|
+
}
|
|
4299
|
+
return { body: created.length ? kept.join("\n").trim() : reply, created };
|
|
4300
|
+
}
|
|
4341
4301
|
|
|
4342
4302
|
// client/settings.ts
|
|
4343
4303
|
var VIEW_NAME = {
|
|
@@ -4873,14 +4833,8 @@ function boardRow(name, health, text, action) {
|
|
|
4873
4833
|
|
|
4874
4834
|
// client/today.ts
|
|
4875
4835
|
function TodayView({ state: state2, ui: ui2, handlers: handlers2 }) {
|
|
4876
|
-
|
|
4877
|
-
|
|
4878
|
-
{ class: "focus-bar", id: "focus-bar", hidden: !ui2.focusMode.value },
|
|
4879
|
-
"Focus mode \u2014 everything but the top item is hidden. ",
|
|
4880
|
-
el("button", { type: "button", class: "button", id: "focus-exit", onClick: () => handlers2.setFocusMode(false) }, "Show everything")
|
|
4881
|
-
);
|
|
4882
|
-
if (state2.setup?.needed) return [focusBar, k(SetupCard, { state: state2, ui: ui2, handlers: handlers2 })];
|
|
4883
|
-
return [focusBar, renderObjective(state2, handlers2), renderStats(state2), renderHeadline(state2), renderSections(state2, ui2, handlers2)];
|
|
4836
|
+
if (state2.setup?.needed) return [k(SetupCard, { state: state2, ui: ui2, handlers: handlers2 })];
|
|
4837
|
+
return [renderObjective(state2, handlers2), renderStats(state2), renderHeadline(state2), renderSections(state2, ui2, handlers2)];
|
|
4884
4838
|
}
|
|
4885
4839
|
function renderObjective(state2, handlers2 = null) {
|
|
4886
4840
|
const focus = state2.focus;
|
|
@@ -5003,7 +4957,6 @@ function App({ ui: ui2, handlers: handlers2 }) {
|
|
|
5003
4957
|
el("a", { class: "skip-link", href: "#main" }, "Skip to content"),
|
|
5004
4958
|
k(Header, { state: current, ui: ui2, handlers: handlers2 }),
|
|
5005
4959
|
k(Tabs, { state: current, ui: ui2, handlers: handlers2 }),
|
|
5006
|
-
current ? k(Timer, { state: current, ui: ui2, handlers: handlers2 }) : el("div", { class: "timer", id: "timer", hidden: true }),
|
|
5007
4960
|
el("div", { id: "banners", class: "banners" }, current ? renderBanners(current, ui2, handlers2) : null),
|
|
5008
4961
|
el(
|
|
5009
4962
|
"main",
|
|
@@ -5121,11 +5074,6 @@ function installKeyboard(handlers2) {
|
|
|
5121
5074
|
event.preventDefault();
|
|
5122
5075
|
moveSelection(-1);
|
|
5123
5076
|
return;
|
|
5124
|
-
case "f":
|
|
5125
|
-
if (ui.view.value !== "today") return;
|
|
5126
|
-
event.preventDefault();
|
|
5127
|
-
handlers2.setFocusMode(!ui.focusMode.value);
|
|
5128
|
-
return;
|
|
5129
5077
|
case "1":
|
|
5130
5078
|
event.preventDefault();
|
|
5131
5079
|
handlers2.setView("today");
|
|
@@ -5170,7 +5118,6 @@ function installKeyboard(handlers2) {
|
|
|
5170
5118
|
if (!item) return;
|
|
5171
5119
|
const boardRow2 = ui.view.value !== "today";
|
|
5172
5120
|
const status = "status" in item ? item.status : null;
|
|
5173
|
-
const kind = "kind" in item ? item.kind : null;
|
|
5174
5121
|
switch (event.key) {
|
|
5175
5122
|
case "e":
|
|
5176
5123
|
event.preventDefault();
|
|
@@ -5193,12 +5140,6 @@ function installKeyboard(handlers2) {
|
|
|
5193
5140
|
event.preventDefault();
|
|
5194
5141
|
handlers2.openDetail(item.id, "assistant");
|
|
5195
5142
|
break;
|
|
5196
|
-
case "p":
|
|
5197
|
-
event.preventDefault();
|
|
5198
|
-
if (boardRow2) break;
|
|
5199
|
-
if (state.value?.session.active?.id === item.id) handlers2.stopSession();
|
|
5200
|
-
else if (status === "open" && kind === "task") handlers2.startSession(item.id);
|
|
5201
|
-
break;
|
|
5202
5143
|
case "o":
|
|
5203
5144
|
if (item.url) {
|
|
5204
5145
|
event.preventDefault();
|
|
@@ -5218,15 +5159,9 @@ R(k(App, { ui, handlers }), root);
|
|
|
5218
5159
|
j3(() => {
|
|
5219
5160
|
document.body.dataset.view = ui.view.value;
|
|
5220
5161
|
});
|
|
5221
|
-
j3(() => {
|
|
5222
|
-
document.body.dataset.focusMode = String(ui.focusMode.value);
|
|
5223
|
-
});
|
|
5224
5162
|
j3(() => {
|
|
5225
5163
|
document.body.dataset.offline = String(ui.connectionError.value !== null);
|
|
5226
5164
|
});
|
|
5227
|
-
j3(() => {
|
|
5228
|
-
document.body.dataset.sessionActive = String(state.value?.session.active != null);
|
|
5229
|
-
});
|
|
5230
5165
|
j3(() => {
|
|
5231
5166
|
const current = state.value;
|
|
5232
5167
|
const open = current !== null && (detailRun(current, ui) !== null || detailRow(current, ui) !== null);
|
|
@@ -5253,7 +5188,6 @@ j3(() => {
|
|
|
5253
5188
|
});
|
|
5254
5189
|
installKeyboard(handlers);
|
|
5255
5190
|
await refresh();
|
|
5256
|
-
startLocalTick();
|
|
5257
5191
|
var zone = watchZone({
|
|
5258
5192
|
browserZone,
|
|
5259
5193
|
dashboardZone: () => state.value?.timeZone,
|