@pi-harness/pi-harness 0.1.59 → 0.1.61
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/apps/web/dist/assets/de-cpvds4yE.js +1 -0
- package/apps/web/dist/assets/en-YSPpVylg.js +1 -0
- package/apps/web/dist/assets/es-Cf919-L8.js +1 -0
- package/apps/web/dist/assets/fr-DIVXpddQ.js +1 -0
- package/apps/web/dist/assets/{index-B9ioDJfx.js → index-CNdMhPss.js} +14 -14
- package/apps/web/dist/assets/index-DaXMEkln.css +2 -0
- package/apps/web/dist/assets/ja-CnGd6_Oa.js +1 -0
- package/apps/web/dist/assets/ko-BixyEcS-.js +1 -0
- package/apps/web/dist/assets/pt-BR-D4LgrQuy.js +1 -0
- package/apps/web/dist/assets/ru-DWAoJHV_.js +1 -0
- package/apps/web/dist/assets/zh-TW-DQwXVbfm.js +1 -0
- package/apps/web/dist/index.html +2 -2
- package/apps/web/package.json +1 -1
- package/apps/web/src/style.css +86 -3
- package/node_modules/@pi-harness/api-gateway/dist/index.d.ts.map +1 -1
- package/node_modules/@pi-harness/api-gateway/dist/index.js +39 -2
- package/node_modules/@pi-harness/api-gateway/dist/index.js.map +1 -1
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/session-compare.json +1 -1
- package/node_modules/@pi-harness/api-gateway/package.json +1 -1
- package/node_modules/@pi-harness/cli/package.json +1 -1
- package/node_modules/@pi-harness/host-webserver/package.json +1 -1
- package/node_modules/@pi-harness/web-app/package.json +1 -1
- package/package.json +6 -6
- package/packages/api-gateway/dist/index.d.ts.map +1 -1
- package/packages/api-gateway/dist/index.js +39 -2
- package/packages/api-gateway/dist/index.js.map +1 -1
- package/packages/api-gateway/dist/marketplace-entries/official/session-compare.json +1 -1
- package/packages/api-gateway/package.json +1 -1
- package/packages/api-gateway/src/index.ts +42 -2
- package/packages/api-gateway/src/marketplace-entries/official/session-compare.json +1 -1
- package/packages/api-gateway/test/index.test.ts +46 -0
- package/packages/bundle-web-app/package.json +1 -1
- package/packages/cli/package.json +1 -1
- package/packages/host-webserver/package.json +1 -1
- package/apps/web/dist/assets/de-Bdfs0IHV.js +0 -1
- package/apps/web/dist/assets/en-_S-AnZAH.js +0 -1
- package/apps/web/dist/assets/es-Dz5gTQCT.js +0 -1
- package/apps/web/dist/assets/fr-BZe_-4z8.js +0 -1
- package/apps/web/dist/assets/index-5PWQdE1Y.css +0 -2
- package/apps/web/dist/assets/ja-DE9YOJc4.js +0 -1
- package/apps/web/dist/assets/ko-DCMv2Wcb.js +0 -1
- package/apps/web/dist/assets/pt-BR-Bvv7IpuC.js +0 -1
- package/apps/web/dist/assets/ru-DEcoObf8.js +0 -1
- package/apps/web/dist/assets/zh-TW-Cb083xOu.js +0 -1
package/apps/web/src/style.css
CHANGED
|
@@ -496,7 +496,7 @@ button:disabled {
|
|
|
496
496
|
@apply [flex:1];
|
|
497
497
|
}
|
|
498
498
|
.run-indicator {
|
|
499
|
-
@apply [display:flex] [align-items:center] [gap:6px] [flex:none] [color:var(--color-muted)] [font:10.5px_var(--font-mono)];
|
|
499
|
+
@apply [display:flex] [min-width:0] [max-width:min(52vw,_560px)] [align-items:center] [gap:6px] [flex:none] [padding:4px_5px_4px_8px] [border:1px_solid_rgba(53,_101,_197,_0.18)] [border-radius:8px] [background:var(--color-blue-soft)] [color:var(--color-muted)] [font:10.5px_var(--font-mono)];
|
|
500
500
|
}
|
|
501
501
|
.run-indicator .run-dot {
|
|
502
502
|
@apply [width:6px] [height:6px] [border-radius:50%] [background:var(--color-green)] [animation:var(--animate-pulse-soft)];
|
|
@@ -505,11 +505,53 @@ button:disabled {
|
|
|
505
505
|
@apply [white-space:nowrap];
|
|
506
506
|
}
|
|
507
507
|
.run-indicator button {
|
|
508
|
-
@apply [padding:2px_8px] [border:1px_solid_rgba(236,_19,_19,_0.24)] [border-radius:6px] [color:var(--color-red)] [font-size:11px];
|
|
508
|
+
@apply [flex:none] [padding:2px_8px] [border:1px_solid_rgba(236,_19,_19,_0.24)] [border-radius:6px] [background:var(--color-surface)] [color:var(--color-red)] [font-size:11px];
|
|
509
509
|
}
|
|
510
510
|
.run-indicator.running .run-dot {
|
|
511
511
|
@apply [background:var(--color-blue)];
|
|
512
512
|
}
|
|
513
|
+
.run-indicator .run-phase {
|
|
514
|
+
@apply [color:var(--color-ink)] [font-weight:600];
|
|
515
|
+
}
|
|
516
|
+
.run-indicator .run-clock {
|
|
517
|
+
@apply [padding:1px_5px] [border-radius:4px] [background:rgba(255,_255,_255,_0.72)] [color:var(--color-blue)] [font-variant-numeric:tabular-nums];
|
|
518
|
+
}
|
|
519
|
+
.run-indicator .run-activity {
|
|
520
|
+
@apply [min-width:0] [overflow:hidden] [color:var(--color-muted)] [text-overflow:ellipsis];
|
|
521
|
+
}
|
|
522
|
+
.run-indicator.quiet,
|
|
523
|
+
.run-indicator.connecting,
|
|
524
|
+
.run-indicator.reconnecting {
|
|
525
|
+
@apply [border-color:rgba(180,_83,_9,_0.22)] [background:var(--color-amber-soft)];
|
|
526
|
+
}
|
|
527
|
+
.run-indicator.quiet .run-dot,
|
|
528
|
+
.run-indicator.connecting .run-dot,
|
|
529
|
+
.run-indicator.reconnecting .run-dot {
|
|
530
|
+
@apply [background:var(--color-amber)];
|
|
531
|
+
}
|
|
532
|
+
.run-indicator.quiet .run-clock,
|
|
533
|
+
.run-indicator.connecting .run-clock,
|
|
534
|
+
.run-indicator.reconnecting .run-clock {
|
|
535
|
+
@apply [color:var(--color-amber)];
|
|
536
|
+
}
|
|
537
|
+
.run-indicator.disconnected,
|
|
538
|
+
.run-indicator.offline {
|
|
539
|
+
@apply [border-color:rgba(236,_19,_19,_0.22)] [background:var(--color-red-soft)];
|
|
540
|
+
}
|
|
541
|
+
.run-indicator.disconnected .run-dot,
|
|
542
|
+
.run-indicator.offline .run-dot {
|
|
543
|
+
@apply [background:var(--color-red)] [animation:none];
|
|
544
|
+
}
|
|
545
|
+
.run-indicator.disconnected .run-clock,
|
|
546
|
+
.run-indicator.offline .run-clock {
|
|
547
|
+
@apply [color:var(--color-red)];
|
|
548
|
+
}
|
|
549
|
+
.run-indicator button:hover {
|
|
550
|
+
@apply [background:var(--color-red)] [color:var(--color-inverse)];
|
|
551
|
+
}
|
|
552
|
+
.run-indicator button:focus-visible {
|
|
553
|
+
@apply [outline:2px_solid_var(--color-red)] [outline-offset:2px];
|
|
554
|
+
}
|
|
513
555
|
.view-tabs {
|
|
514
556
|
@apply [display:flex] [gap:2px] [padding:2px] [border-radius:8px] [background:var(--color-soft)];
|
|
515
557
|
}
|
|
@@ -664,6 +706,27 @@ button:disabled {
|
|
|
664
706
|
.streaming-placeholder {
|
|
665
707
|
@apply [display:flex] [align-items:center] [gap:8px] [color:var(--color-muted)] [font-size:12px];
|
|
666
708
|
}
|
|
709
|
+
.streaming-turn.quiet,
|
|
710
|
+
.streaming-turn.connecting,
|
|
711
|
+
.streaming-turn.reconnecting {
|
|
712
|
+
@apply [padding-left:12px] [border-left:2px_solid_var(--color-amber)];
|
|
713
|
+
}
|
|
714
|
+
.streaming-turn.disconnected,
|
|
715
|
+
.streaming-turn.offline {
|
|
716
|
+
@apply [padding-left:12px] [border-left:2px_solid_var(--color-red)];
|
|
717
|
+
}
|
|
718
|
+
.streaming-activity {
|
|
719
|
+
@apply [width:fit-content] [margin-top:8px] [padding:3px_7px] [border-radius:5px] [background:var(--color-soft)] [color:var(--color-muted)] [font:10.5px_var(--font-mono)];
|
|
720
|
+
}
|
|
721
|
+
.streaming-activity.quiet,
|
|
722
|
+
.streaming-activity.connecting,
|
|
723
|
+
.streaming-activity.reconnecting {
|
|
724
|
+
@apply [background:var(--color-amber-soft)] [color:var(--color-amber)];
|
|
725
|
+
}
|
|
726
|
+
.streaming-activity.disconnected,
|
|
727
|
+
.streaming-activity.offline {
|
|
728
|
+
@apply [background:var(--color-red-soft)] [color:var(--color-red)];
|
|
729
|
+
}
|
|
667
730
|
@keyframes spin-smooth {
|
|
668
731
|
to {
|
|
669
732
|
transform: rotate(360deg);
|
|
@@ -1751,6 +1814,18 @@ button:disabled {
|
|
|
1751
1814
|
.main-header {
|
|
1752
1815
|
@apply [gap:7px] [padding:0_10px];
|
|
1753
1816
|
}
|
|
1817
|
+
.main-header:has(.run-indicator) .active-heading,
|
|
1818
|
+
.main-header:has(.run-indicator) .header-spacer,
|
|
1819
|
+
.main-header:has(.run-indicator) .header-divider,
|
|
1820
|
+
.main-header:has(.run-indicator) .details-toggle {
|
|
1821
|
+
@apply [display:none];
|
|
1822
|
+
}
|
|
1823
|
+
.main-header:has(.run-indicator) .run-indicator {
|
|
1824
|
+
@apply [max-width:none] [flex-wrap:nowrap] [margin-right:auto];
|
|
1825
|
+
}
|
|
1826
|
+
.main-header:has(.run-indicator) .run-activity {
|
|
1827
|
+
@apply [display:none];
|
|
1828
|
+
}
|
|
1754
1829
|
.active-heading small {
|
|
1755
1830
|
@apply [max-width:180px];
|
|
1756
1831
|
}
|
|
@@ -1761,6 +1836,12 @@ button:disabled {
|
|
|
1761
1836
|
.view-tabs {
|
|
1762
1837
|
@apply [margin-left:auto];
|
|
1763
1838
|
}
|
|
1839
|
+
.run-indicator {
|
|
1840
|
+
@apply [max-width:46vw] [flex-wrap:wrap] [gap-x:5px] [gap-y:1px];
|
|
1841
|
+
}
|
|
1842
|
+
.run-indicator .run-activity {
|
|
1843
|
+
@apply [order:3] [basis:100%] [padding-left:12px] [font-size:9.5px];
|
|
1844
|
+
}
|
|
1764
1845
|
.composer-hint {
|
|
1765
1846
|
@apply [display:none];
|
|
1766
1847
|
}
|
|
@@ -1853,7 +1934,9 @@ button:disabled {
|
|
|
1853
1934
|
@media (prefers-reduced-motion: reduce) {
|
|
1854
1935
|
.session-dot.running,
|
|
1855
1936
|
.run-indicator .run-dot,
|
|
1856
|
-
.initial-loading > span
|
|
1937
|
+
.initial-loading > span,
|
|
1938
|
+
.streaming-spinner,
|
|
1939
|
+
.reasoning-head::after {
|
|
1857
1940
|
@apply [animation:none];
|
|
1858
1941
|
}
|
|
1859
1942
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;;;;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;;;;mBAmzBlC,OAAO;;AAHxB,wBAo9CE"}
|
|
@@ -78,9 +78,16 @@ function jsonSafe(value, seen = new WeakSet()) {
|
|
|
78
78
|
}
|
|
79
79
|
// A plugin that contributes tools only joins on the next start, so the console remembers what it installed until then. That memory is about one particular process, and the console cannot tell a restart from a reconnect on its own, so the identity of this process rides along with the status it already polls.
|
|
80
80
|
const PROCESS_STARTED_AT = new Date(Date.now() - Math.round(process.uptime() * 1000)).toISOString();
|
|
81
|
-
function createStatus(services, events) {
|
|
81
|
+
function createStatus(services, events, runActivity) {
|
|
82
82
|
const activeModel = services.runtime.session.model ?? services.models.model;
|
|
83
83
|
const cwd = activeCwd(services);
|
|
84
|
+
const currentRun = services.runtime.session.isStreaming && runActivity?.sessionId === services.runtime.session.sessionId
|
|
85
|
+
? {
|
|
86
|
+
startedAt: new Date(runActivity.startedAt).toISOString(),
|
|
87
|
+
lastActivityAt: new Date(runActivity.lastActivityAt).toISOString(),
|
|
88
|
+
phase: runActivity.phase,
|
|
89
|
+
}
|
|
90
|
+
: undefined;
|
|
84
91
|
return {
|
|
85
92
|
processStartedAt: PROCESS_STARTED_AT,
|
|
86
93
|
status: services.runtime.session.isStreaming ? "running" : "ready",
|
|
@@ -92,6 +99,7 @@ function createStatus(services, events) {
|
|
|
92
99
|
cwd,
|
|
93
100
|
agentDir: services.launch.agentDir,
|
|
94
101
|
plugins: services.loader ? [...services.loader.entries()].filter((entry) => !entry.disabled).map((entry) => entry.options.name) : [],
|
|
102
|
+
...(currentRun === undefined ? {} : { run: currentRun }),
|
|
95
103
|
};
|
|
96
104
|
}
|
|
97
105
|
function activeCwd(services) {
|
|
@@ -725,6 +733,15 @@ export default {
|
|
|
725
733
|
let busy = false;
|
|
726
734
|
const events = [];
|
|
727
735
|
const eventClients = new Set();
|
|
736
|
+
const initialRunAt = Date.now();
|
|
737
|
+
let runActivity = services.runtime.session.isStreaming
|
|
738
|
+
? {
|
|
739
|
+
sessionId: services.runtime.session.sessionId,
|
|
740
|
+
startedAt: initialRunAt,
|
|
741
|
+
lastActivityAt: initialRunAt,
|
|
742
|
+
phase: "starting",
|
|
743
|
+
}
|
|
744
|
+
: undefined;
|
|
728
745
|
// Pi puts a wall-clock on a message payload and nowhere else, so a tool call has no time of its own and nothing downstream can recover when the harness saw it. The gateway is the one place that sees every event as it happens, so it stamps each one on arrival, and pairs a tool call's two events to record how long the call took.
|
|
729
746
|
// The stamp is written onto the event rather than onto a copy: a copy would give every event a new identity, and the serializer's cycle detection reads identity, so a self-referential event would serialize one level deeper on every hop.
|
|
730
747
|
const toolCallStartedAt = new Map();
|
|
@@ -750,6 +767,26 @@ export default {
|
|
|
750
767
|
};
|
|
751
768
|
const handleEvent = (rawEvent) => {
|
|
752
769
|
const event = stampEvent(rawEvent);
|
|
770
|
+
const sessionId = services.runtime.session.sessionId;
|
|
771
|
+
if (event.type === "agent_settled") {
|
|
772
|
+
runActivity = undefined;
|
|
773
|
+
}
|
|
774
|
+
else if (event.type === "agent_start") {
|
|
775
|
+
runActivity = { sessionId, startedAt: event.receivedAt, lastActivityAt: event.receivedAt, phase: "starting" };
|
|
776
|
+
}
|
|
777
|
+
else if (runActivity?.sessionId === sessionId || services.runtime.session.isStreaming) {
|
|
778
|
+
const startedAt = runActivity?.sessionId === sessionId ? runActivity.startedAt : event.receivedAt;
|
|
779
|
+
let phase = runActivity?.sessionId === sessionId ? runActivity.phase : "starting";
|
|
780
|
+
if (event.type === "message_update") {
|
|
781
|
+
if (event.assistantMessageEvent.type === "thinking_delta")
|
|
782
|
+
phase = "thinking";
|
|
783
|
+
if (event.assistantMessageEvent.type === "text_delta")
|
|
784
|
+
phase = "responding";
|
|
785
|
+
}
|
|
786
|
+
if (event.type === "tool_execution_start" || event.type === "tool_execution_update" || event.type === "tool_execution_end")
|
|
787
|
+
phase = "tool";
|
|
788
|
+
runActivity = { sessionId, startedAt, lastActivityAt: event.receivedAt, phase };
|
|
789
|
+
}
|
|
753
790
|
// Streaming deltas reach clients live over SSE and each one carries the whole partial message, so only durable events are retained for snapshots.
|
|
754
791
|
if (event.type !== "message_update") {
|
|
755
792
|
events.push(event);
|
|
@@ -770,7 +807,7 @@ export default {
|
|
|
770
807
|
const disposeStatus = services.webServer.register({
|
|
771
808
|
path: "/api/status",
|
|
772
809
|
handler(_request, response) {
|
|
773
|
-
sendJson(response, 200, createStatus(services, events));
|
|
810
|
+
sendJson(response, 200, createStatus(services, events, runActivity));
|
|
774
811
|
},
|
|
775
812
|
});
|
|
776
813
|
const disposeConfig = services.webServer.register({
|