@nmzpy/pi-ember-stack 0.1.6 → 0.2.2

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.
Files changed (36) hide show
  1. package/README.md +83 -83
  2. package/package.json +62 -48
  3. package/plugins/devin-auth/extensions/index.ts +68 -7
  4. package/plugins/devin-auth/src/cloud-direct/auth.ts +246 -246
  5. package/plugins/devin-auth/src/cloud-direct/catalog.ts +246 -246
  6. package/plugins/devin-auth/src/cloud-direct/chat.ts +1096 -1091
  7. package/plugins/devin-auth/src/cloud-direct/index.ts +41 -41
  8. package/plugins/devin-auth/src/cloud-direct/metadata.ts +78 -78
  9. package/plugins/devin-auth/src/cloud-direct/wire.ts +202 -202
  10. package/plugins/devin-auth/src/models.ts +42 -196
  11. package/plugins/devin-auth/src/oauth/register-user.ts +174 -174
  12. package/plugins/devin-auth/src/oauth/types.ts +71 -71
  13. package/plugins/devin-auth/src/stream.ts +1 -1
  14. package/plugins/index.ts +29 -6
  15. package/plugins/pi-compact-tools/index.ts +35 -192
  16. package/plugins/pi-compact-tools/renderer.ts +589 -0
  17. package/plugins/pi-custom-agents/index.ts +727 -373
  18. package/plugins/pi-custom-agents/questionnaire-tool.ts +14 -5
  19. package/plugins/pi-custom-agents/subagent/agents/coder.md +1 -0
  20. package/plugins/pi-custom-agents/subagent/agents/scout.md +16 -37
  21. package/plugins/pi-custom-agents/subagent/extensions/agents.ts +18 -1
  22. package/plugins/pi-custom-agents/subagent/extensions/index.ts +118 -226
  23. package/plugins/pi-custom-agents/subagent/extensions/model.ts +96 -96
  24. package/plugins/pi-custom-agents/subagent/extensions/render.ts +205 -1
  25. package/plugins/pi-custom-agents/subagent/extensions/runner.ts +260 -170
  26. package/plugins/pi-custom-agents/subagent/extensions/test/render.test.ts +145 -0
  27. package/plugins/pi-ember-fff/index.ts +975 -0
  28. package/plugins/pi-ember-fff/query.ts +247 -0
  29. package/plugins/pi-ember-fff/test/query.test.ts +222 -0
  30. package/plugins/pi-ember-fff/test/renderer.test.ts +727 -0
  31. package/plugins/pi-ember-tps/index.ts +144 -0
  32. package/plugins/pi-ember-ui/ember.json +99 -0
  33. package/plugins/pi-ember-ui/index.ts +805 -0
  34. package/plugins/pi-ember-ui/mode-colors.ts +196 -0
  35. package/tsconfig.json +2 -1
  36. package/plugins/pi-custom-agents/subagent/agents/architect.md +0 -56
@@ -0,0 +1,144 @@
1
+ /**
2
+ * Ember TPS Meter — minimal tokens-per-second tracker
3
+ *
4
+ * Tracks output plus thinking token rate during streaming and exposes the live
5
+ * value via getLiveTps() for the custom footer to render.
6
+ */
7
+
8
+ import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
9
+
10
+ const STREAM_INTERVAL_MS = 500;
11
+
12
+ let streamStartMs = 0;
13
+ let firstTokenMs = 0;
14
+ let streamChars = 0;
15
+ let streamThinkingChars = 0;
16
+ let streamTokens = 0;
17
+ let tickTimer: ReturnType<typeof setInterval> | null = null;
18
+ let streaming = false;
19
+ let liveTps = 0;
20
+ let renderTrigger: (() => void) | undefined;
21
+
22
+ function now(): number {
23
+ return performance.now();
24
+ }
25
+
26
+ function tokEst(ch: number): number {
27
+ return (ch >>> 2) + ((ch & 3) > 0 ? 1 : 0);
28
+ }
29
+
30
+ function computeTps(): number {
31
+ const ref = firstTokenMs > 0 ? firstTokenMs : streamStartMs;
32
+ const elapsed = (now() - ref) / 1000;
33
+ return elapsed > 0.3 ? streamTokens / elapsed : 0;
34
+ }
35
+
36
+ function startTick(): void {
37
+ if (tickTimer) return;
38
+ tickTimer = setInterval(() => {
39
+ if (!streaming) {
40
+ stopTick();
41
+ return;
42
+ }
43
+ liveTps = computeTps();
44
+ renderTrigger?.();
45
+ }, STREAM_INTERVAL_MS);
46
+ }
47
+
48
+ function stopTick(): void {
49
+ if (tickTimer) {
50
+ clearInterval(tickTimer);
51
+ tickTimer = null;
52
+ }
53
+ }
54
+
55
+ export function getLiveTps(): number {
56
+ return liveTps;
57
+ }
58
+
59
+ export default function piEmberTps(pi: ExtensionAPI): void {
60
+ pi.on("message_start", async (event, ctx) => {
61
+ if (event.message.role !== "assistant") return;
62
+ streamStartMs = now();
63
+ firstTokenMs = 0;
64
+ streamChars = 0;
65
+ streamThinkingChars = 0;
66
+ streamTokens = 0;
67
+ liveTps = 0;
68
+ streaming = true;
69
+ if (ctx.mode === "tui") {
70
+ renderTrigger = () => ctx.ui.setStatus("tps", undefined);
71
+ }
72
+ startTick();
73
+ });
74
+
75
+ pi.on("message_update", async (event) => {
76
+ if (event.message.role !== "assistant") return;
77
+ if (!event.assistantMessageEvent) return;
78
+ const evt = event.assistantMessageEvent;
79
+ if (evt.type === "text_delta" || evt.type === "thinking_delta") {
80
+ const d = evt.delta as string;
81
+ if (!d) return;
82
+ if (firstTokenMs === 0) firstTokenMs = now();
83
+ streamChars += d.length;
84
+ if (evt.type === "thinking_delta") streamThinkingChars += d.length;
85
+ streamTokens = tokEst(streamChars);
86
+ }
87
+ });
88
+
89
+ pi.on("message_end", async (event) => {
90
+ if (event.message.role !== "assistant") return;
91
+ streaming = false;
92
+ stopTick();
93
+
94
+ const usage = event.message?.usage;
95
+ const realOut = usage?.output;
96
+ // Some providers report output tokens without their thinking tokens.
97
+ // Keep the streamed combined estimate in that case; providers that
98
+ // expose `reasoning` already include it in `usage.output`.
99
+ const tokens = typeof realOut === "number" && realOut > 0
100
+ ? streamThinkingChars > 0 && usage?.reasoning === undefined
101
+ ? Math.max(realOut, streamTokens)
102
+ : realOut
103
+ : streamTokens;
104
+
105
+ const ref = firstTokenMs > 0 ? firstTokenMs : streamStartMs;
106
+ const elapsed = (now() - ref) / 1000;
107
+ if (elapsed < 0.1 || tokens === 0) {
108
+ liveTps = 0;
109
+ return;
110
+ }
111
+
112
+ liveTps = tokens / elapsed;
113
+ renderTrigger?.();
114
+ });
115
+
116
+ pi.on("agent_end", async () => {
117
+ streaming = false;
118
+ stopTick();
119
+ });
120
+
121
+ pi.on("session_start", async (_event, ctx) => {
122
+ streaming = false;
123
+ stopTick();
124
+ streamStartMs = 0;
125
+ firstTokenMs = 0;
126
+ streamChars = 0;
127
+ streamThinkingChars = 0;
128
+ streamTokens = 0;
129
+ liveTps = 0;
130
+ renderTrigger = undefined;
131
+ ctx.ui.setStatus("tps", undefined);
132
+ });
133
+
134
+ // Clear the tick interval and stale render trigger on shutdown so a
135
+ // subsequent /resume does not keep a setInterval alive against the dead
136
+ // session's ctx.ui. Without this, the 500ms tick keeps firing and
137
+ // calls the old renderTrigger long after the session is gone.
138
+ pi.on("session_shutdown", async () => {
139
+ streaming = false;
140
+ stopTick();
141
+ renderTrigger = undefined;
142
+ liveTps = 0;
143
+ });
144
+ }
@@ -0,0 +1,99 @@
1
+ {
2
+ "$schema": "https://raw.githubusercontent.com/earendil-works/pi/main/packages/coding-agent/src/modes/interactive/theme/theme-schema.json",
3
+ "name": "ember",
4
+ "vars": {
5
+ "emberAccent": "#EB6E00",
6
+ "emberAccent90": "#EB6E00",
7
+ "emberAccent75": "#D9640F",
8
+ "emberAccent60": "#C25A17",
9
+ "emberAccent45": "#A8501F",
10
+ "emberAccent30": "#8F4627",
11
+ "emberAccent15": "#783C2F",
12
+ "emberAccent25": "#4D2E17",
13
+ "emberGray": "#808080",
14
+ "emberDarkGray": "#505050",
15
+ "cyan": "#00d7ff",
16
+ "blue": "#5f87ff",
17
+ "green": "#b5bd68",
18
+ "red": "#cc6666",
19
+ "yellow": "#ffff00",
20
+ "text": "#d4d4d4",
21
+ "gray": "#808080",
22
+ "dimGray": "#666666",
23
+ "darkGray": "#505050",
24
+ "accent": "#EB6E00",
25
+ "selectedBg": "#3a3a4a",
26
+ "userMsgBg": "#343541",
27
+ "subagentBg": "#32333f",
28
+ "toolPendingBg": "#282832",
29
+ "toolSuccessBg": "#283228",
30
+ "toolErrorBg": "#3c2828",
31
+ "customMsgBg": "#2d2838"
32
+ },
33
+ "colors": {
34
+ "accent": "emberAccent",
35
+ "border": "emberAccent",
36
+ "borderAccent": "emberAccent",
37
+ "borderMuted": "emberDarkGray",
38
+ "success": "green",
39
+ "error": "red",
40
+ "warning": "yellow",
41
+ "muted": "gray",
42
+ "dim": "dimGray",
43
+ "text": "text",
44
+ "thinkingText": "gray",
45
+
46
+ "selectedBg": "selectedBg",
47
+ "userMessageBg": "userMsgBg",
48
+ "subagentBg": "subagentBg",
49
+ "userMessageText": "text",
50
+ "customMessageBg": "customMsgBg",
51
+ "customMessageText": "text",
52
+ "customMessageLabel": "#9575cd",
53
+ "toolPendingBg": "toolPendingBg",
54
+ "toolSuccessBg": "toolSuccessBg",
55
+ "toolErrorBg": "toolErrorBg",
56
+ "toolTitle": "text",
57
+ "toolOutput": "gray",
58
+
59
+ "mdHeading": "#f0c674",
60
+ "mdLink": "#81a2be",
61
+ "mdLinkUrl": "dimGray",
62
+ "mdCode": "text",
63
+ "mdCodeBlock": "green",
64
+ "mdCodeBlockBorder": "gray",
65
+ "mdQuote": "gray",
66
+ "mdQuoteBorder": "gray",
67
+ "mdHr": "gray",
68
+ "mdListBullet": "emberAccent",
69
+
70
+ "toolDiffAdded": "green",
71
+ "toolDiffRemoved": "red",
72
+ "toolDiffContext": "gray",
73
+
74
+ "syntaxComment": "#6A9955",
75
+ "syntaxKeyword": "#569CD6",
76
+ "syntaxFunction": "#DCDCAA",
77
+ "syntaxVariable": "#9CDCFE",
78
+ "syntaxString": "#CE9178",
79
+ "syntaxNumber": "#B5CEA8",
80
+ "syntaxType": "#4EC9B0",
81
+ "syntaxOperator": "#D4D4D4",
82
+ "syntaxPunctuation": "#D4D4D4",
83
+
84
+ "thinkingOff": "emberDarkGray",
85
+ "thinkingMinimal": "emberAccent15",
86
+ "thinkingLow": "emberAccent30",
87
+ "thinkingMedium": "emberAccent45",
88
+ "thinkingHigh": "emberAccent60",
89
+ "thinkingXhigh": "emberAccent75",
90
+ "thinkingMax": "emberAccent90",
91
+
92
+ "bashMode": "green"
93
+ },
94
+ "export": {
95
+ "pageBg": "#18181e",
96
+ "cardBg": "#1e1e24",
97
+ "infoBg": "#3c3728"
98
+ }
99
+ }