@jinion/cli 0.0.0-stage → 0.3.491

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 (171) hide show
  1. package/bin/jinion.js +4 -0
  2. package/dist/app/activity.js +50 -0
  3. package/dist/app/activity.js.map +1 -0
  4. package/dist/app/announcements.js +21 -0
  5. package/dist/app/announcements.js.map +1 -0
  6. package/dist/app/api.js +26 -0
  7. package/dist/app/api.js.map +1 -0
  8. package/dist/app/app.js +91 -0
  9. package/dist/app/app.js.map +1 -0
  10. package/dist/app/aside.js +52 -0
  11. package/dist/app/aside.js.map +1 -0
  12. package/dist/app/dialogs.js +43 -0
  13. package/dist/app/dialogs.js.map +1 -0
  14. package/dist/app/keys.js +79 -0
  15. package/dist/app/keys.js.map +1 -0
  16. package/dist/app/prompt-area.js +56 -0
  17. package/dist/app/prompt-area.js.map +1 -0
  18. package/dist/app/shortcuts.js +31 -0
  19. package/dist/app/shortcuts.js.map +1 -0
  20. package/dist/app/sidebar.js +50 -0
  21. package/dist/app/sidebar.js.map +1 -0
  22. package/dist/app/status-line.js +23 -0
  23. package/dist/app/status-line.js.map +1 -0
  24. package/dist/app/task-line.js +19 -0
  25. package/dist/app/task-line.js.map +1 -0
  26. package/dist/app/use-screen.js +24 -0
  27. package/dist/app/use-screen.js.map +1 -0
  28. package/dist/app/views.js +62 -0
  29. package/dist/app/views.js.map +1 -0
  30. package/dist/main.js +122 -0
  31. package/dist/main.js.map +1 -0
  32. package/dist/panels/account/account-picker.js +118 -0
  33. package/dist/panels/account/account-picker.js.map +1 -0
  34. package/dist/panels/account/describe.js +14 -0
  35. package/dist/panels/account/describe.js.map +1 -0
  36. package/dist/panels/account/sign-in-view.js +8 -0
  37. package/dist/panels/account/sign-in-view.js.map +1 -0
  38. package/dist/panels/account/use-sign-in.js +46 -0
  39. package/dist/panels/account/use-sign-in.js.map +1 -0
  40. package/dist/panels/context.js +55 -0
  41. package/dist/panels/context.js.map +1 -0
  42. package/dist/panels/diff/change-list.js +48 -0
  43. package/dist/panels/diff/change-list.js.map +1 -0
  44. package/dist/panels/diff/current-view.js +47 -0
  45. package/dist/panels/diff/current-view.js.map +1 -0
  46. package/dist/panels/diff/diff-panel.js +22 -0
  47. package/dist/panels/diff/diff-panel.js.map +1 -0
  48. package/dist/panels/diff/file-diff.js +19 -0
  49. package/dist/panels/diff/file-diff.js.map +1 -0
  50. package/dist/panels/diff/views.js +29 -0
  51. package/dist/panels/diff/views.js.map +1 -0
  52. package/dist/panels/feedback.js +67 -0
  53. package/dist/panels/feedback.js.map +1 -0
  54. package/dist/panels/help.js +79 -0
  55. package/dist/panels/help.js.map +1 -0
  56. package/dist/panels/mcp.js +129 -0
  57. package/dist/panels/mcp.js.map +1 -0
  58. package/dist/panels/memory.js +55 -0
  59. package/dist/panels/memory.js.map +1 -0
  60. package/dist/panels/mode.js +36 -0
  61. package/dist/panels/mode.js.map +1 -0
  62. package/dist/panels/model.js +20 -0
  63. package/dist/panels/model.js.map +1 -0
  64. package/dist/panels/onboarding/onboarding-panel.js +56 -0
  65. package/dist/panels/onboarding/onboarding-panel.js.map +1 -0
  66. package/dist/panels/onboarding/use-onboarding.js +65 -0
  67. package/dist/panels/onboarding/use-onboarding.js.map +1 -0
  68. package/dist/panels/profile.js +31 -0
  69. package/dist/panels/profile.js.map +1 -0
  70. package/dist/panels/resume.js +52 -0
  71. package/dist/panels/resume.js.map +1 -0
  72. package/dist/panels/rewind/changes.js +20 -0
  73. package/dist/panels/rewind/changes.js.map +1 -0
  74. package/dist/panels/rewind/rewind-panel.js +93 -0
  75. package/dist/panels/rewind/rewind-panel.js.map +1 -0
  76. package/dist/panels/sign-in/sign-in-panel.js +56 -0
  77. package/dist/panels/sign-in/sign-in-panel.js.map +1 -0
  78. package/dist/panels/sign-in/use-jinion-sign-in.js +69 -0
  79. package/dist/panels/sign-in/use-jinion-sign-in.js.map +1 -0
  80. package/dist/panels/statusline.js +94 -0
  81. package/dist/panels/statusline.js.map +1 -0
  82. package/dist/panels/tasks/output.js +23 -0
  83. package/dist/panels/tasks/output.js.map +1 -0
  84. package/dist/panels/tasks/task-output.js +29 -0
  85. package/dist/panels/tasks/task-output.js.map +1 -0
  86. package/dist/panels/tasks/tasks-panel.js +75 -0
  87. package/dist/panels/tasks/tasks-panel.js.map +1 -0
  88. package/dist/panels/terminal-setup.js +41 -0
  89. package/dist/panels/terminal-setup.js.map +1 -0
  90. package/dist/panels/usage/section.js +16 -0
  91. package/dist/panels/usage/section.js.map +1 -0
  92. package/dist/panels/usage/stats-view.js +52 -0
  93. package/dist/panels/usage/stats-view.js.map +1 -0
  94. package/dist/panels/usage/usage-panel.js +68 -0
  95. package/dist/panels/usage/usage-panel.js.map +1 -0
  96. package/dist/panels/usage/usage-view.js +51 -0
  97. package/dist/panels/usage/usage-view.js.map +1 -0
  98. package/dist/prompt/attachments.js +91 -0
  99. package/dist/prompt/attachments.js.map +1 -0
  100. package/dist/prompt/draft.js +24 -0
  101. package/dist/prompt/draft.js.map +1 -0
  102. package/dist/prompt/images.js +84 -0
  103. package/dist/prompt/images.js.map +1 -0
  104. package/dist/prompt/pasted-path.js +19 -0
  105. package/dist/prompt/pasted-path.js.map +1 -0
  106. package/dist/prompt/use-prompt.js +62 -0
  107. package/dist/prompt/use-prompt.js.map +1 -0
  108. package/dist/serve.js +38 -0
  109. package/dist/serve.js.map +1 -0
  110. package/dist/state/session.js +91 -0
  111. package/dist/state/session.js.map +1 -0
  112. package/dist/status/data.js +39 -0
  113. package/dist/status/data.js.map +1 -0
  114. package/dist/status/git.js +18 -0
  115. package/dist/status/git.js.map +1 -0
  116. package/dist/status/items.js +8 -0
  117. package/dist/status/items.js.map +1 -0
  118. package/dist/status/line.js +25 -0
  119. package/dist/status/line.js.map +1 -0
  120. package/dist/status/saved.js +8 -0
  121. package/dist/status/saved.js.map +1 -0
  122. package/dist/status/segment.js +2 -0
  123. package/dist/status/segment.js.map +1 -0
  124. package/dist/status/segments/conversation.js +71 -0
  125. package/dist/status/segments/conversation.js.map +1 -0
  126. package/dist/status/segments/git.js +33 -0
  127. package/dist/status/segments/git.js.map +1 -0
  128. package/dist/status/segments/identity.js +71 -0
  129. package/dist/status/segments/identity.js.map +1 -0
  130. package/dist/status/segments/index.js +27 -0
  131. package/dist/status/segments/index.js.map +1 -0
  132. package/dist/status/segments/usage.js +61 -0
  133. package/dist/status/segments/usage.js.map +1 -0
  134. package/dist/terminal/apple-terminal.js +68 -0
  135. package/dist/terminal/apple-terminal.js.map +1 -0
  136. package/dist/ui/banner.js +24 -0
  137. package/dist/ui/banner.js.map +1 -0
  138. package/dist/ui/entries/changes-card.js +27 -0
  139. package/dist/ui/entries/changes-card.js.map +1 -0
  140. package/dist/ui/entries/entry-view.js +82 -0
  141. package/dist/ui/entries/entry-view.js.map +1 -0
  142. package/dist/ui/entries/status-entries.js +33 -0
  143. package/dist/ui/entries/status-entries.js.map +1 -0
  144. package/dist/ui/entries/tools/agent-view.js +39 -0
  145. package/dist/ui/entries/tools/agent-view.js.map +1 -0
  146. package/dist/ui/entries/tools/mcp-view.js +10 -0
  147. package/dist/ui/entries/tools/mcp-view.js.map +1 -0
  148. package/dist/ui/entries/tools/result-preview.js +19 -0
  149. package/dist/ui/entries/tools/result-preview.js.map +1 -0
  150. package/dist/ui/entries/tools/search.js +42 -0
  151. package/dist/ui/entries/tools/search.js.map +1 -0
  152. package/dist/ui/entries/tools/shell-footer.js +36 -0
  153. package/dist/ui/entries/tools/shell-footer.js.map +1 -0
  154. package/dist/ui/entries/tools/tool-view.js +47 -0
  155. package/dist/ui/entries/tools/tool-view.js.map +1 -0
  156. package/dist/ui/entries/tools/web.js +41 -0
  157. package/dist/ui/entries/tools/web.js.map +1 -0
  158. package/dist/ui/modes.js +13 -0
  159. package/dist/ui/modes.js.map +1 -0
  160. package/dist/ui/task-marks.js +7 -0
  161. package/dist/ui/task-marks.js.map +1 -0
  162. package/dist/ui/use-async.js +17 -0
  163. package/dist/ui/use-async.js.map +1 -0
  164. package/dist/ui/use-pager.js +25 -0
  165. package/dist/ui/use-pager.js.map +1 -0
  166. package/dist/ui/use-project-files.js +18 -0
  167. package/dist/ui/use-project-files.js.map +1 -0
  168. package/dist/ui/use-workdir.js +9 -0
  169. package/dist/ui/use-workdir.js.map +1 -0
  170. package/package.json +34 -3
  171. package/README.md +0 -3
@@ -0,0 +1,84 @@
1
+ import { execFile, execFileSync } from 'node:child_process';
2
+ import { existsSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from 'node:fs';
3
+ import { tmpdir } from 'node:os';
4
+ import { extname, join } from 'node:path';
5
+ import { pastedFile } from './pasted-path.js';
6
+ const MEDIA_TYPES = {
7
+ '.png': 'image/png',
8
+ '.jpg': 'image/jpeg',
9
+ '.jpeg': 'image/jpeg',
10
+ '.gif': 'image/gif',
11
+ '.webp': 'image/webp',
12
+ };
13
+ /** Claude takes images up to 5 MB once encoded, and base64 makes them a third bigger. */
14
+ const MAX_BYTES = 3_750_000;
15
+ const SHRINK_TO = 2048;
16
+ /** The image a pasted path names, read to go in the prompt; nothing for a file of another kind. */
17
+ export function imageFromPaste(text) {
18
+ const path = pastedFile(text);
19
+ const mediaType = path && MEDIA_TYPES[extname(path).toLowerCase()];
20
+ if (!path || !mediaType)
21
+ return undefined;
22
+ return fitting(readFileSync(path), mediaType);
23
+ }
24
+ export async function clipboardImage() {
25
+ const png = await clipboardPng();
26
+ return png && png.length > 0 ? fitting(png, 'image/png') : undefined;
27
+ }
28
+ function clipboardPng() {
29
+ if (process.platform === 'darwin') {
30
+ const folder = mkdtempSync(join(tmpdir(), 'jinion-clipboard-'));
31
+ const file = join(folder, 'clipboard.png');
32
+ // AppleScript writes the clipboard's PNG data to a file, and fails when the clipboard holds no image.
33
+ const script = [
34
+ 'set png to (the clipboard as «class PNGf»)',
35
+ `set out to open for access POSIX file "${file}" with write permission`,
36
+ 'set eof out to 0',
37
+ 'write png to out',
38
+ 'close access out',
39
+ ];
40
+ return new Promise((resolve) => {
41
+ execFile('osascript', script.flatMap((line) => ['-e', line]), (error) => {
42
+ resolve(error || !existsSync(file) ? undefined : readFileSync(file));
43
+ rmSync(folder, { recursive: true, force: true });
44
+ });
45
+ });
46
+ }
47
+ if (process.platform === 'linux') {
48
+ const read = (command, args) => new Promise((resolve) => {
49
+ execFile(command, args, { encoding: 'buffer', maxBuffer: 64 * 1024 * 1024 }, (error, stdout) => resolve(error ? undefined : stdout));
50
+ });
51
+ return read('wl-paste', ['--type', 'image/png']).then((png) => png ?? read('xclip', ['-selection', 'clipboard', '-t', 'image/png', '-o']));
52
+ }
53
+ return Promise.resolve(undefined);
54
+ }
55
+ function fitting(bytes, mediaType) {
56
+ if (bytes.length <= MAX_BYTES)
57
+ return { mediaType, data: bytes.toString('base64') };
58
+ const smaller = shrink(bytes);
59
+ if (!smaller || smaller.length > MAX_BYTES) {
60
+ throw new Error(`The image is ${(bytes.length / 1_000_000).toFixed(1)} MB; Claude takes images up to 3.7 MB.`);
61
+ }
62
+ return { mediaType: 'image/jpeg', data: smaller.toString('base64') };
63
+ }
64
+ function shrink(bytes) {
65
+ if (process.platform !== 'darwin')
66
+ return undefined;
67
+ const folder = mkdtempSync(join(tmpdir(), 'jinion-image-'));
68
+ try {
69
+ const source = join(folder, 'source');
70
+ const target = join(folder, 'target.jpg');
71
+ writeFileSync(source, bytes);
72
+ execFileSync('sips', ['-Z', String(SHRINK_TO), '-s', 'format', 'jpeg', '-s', 'formatOptions', '80', source, '--out', target], {
73
+ stdio: 'ignore',
74
+ });
75
+ return readFileSync(target);
76
+ }
77
+ catch {
78
+ return undefined;
79
+ }
80
+ finally {
81
+ rmSync(folder, { recursive: true, force: true });
82
+ }
83
+ }
84
+ //# sourceMappingURL=images.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"images.js","sourceRoot":"","sources":["../../src/prompt/images.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ import { existsSync, statSync } from 'node:fs';
2
+ import { homedir } from 'node:os';
3
+ import { isAbsolute, join } from 'node:path';
4
+ /**
5
+ * The file whose path a paste is, when it is one and nothing else: terminals paste a dragged file's path quoted, with
6
+ * backslashes before spaces, or as a `file://` URL.
7
+ */
8
+ export function pastedFile(text) {
9
+ let path = text.trim();
10
+ if (!path || path.includes('\n'))
11
+ return undefined;
12
+ if (path.startsWith('file://'))
13
+ path = decodeURIComponent(path.slice('file://'.length));
14
+ path = path.replace(/^(['"])(.*)\1$/, '$2').replace(/\\(.)/g, '$1');
15
+ if (path.startsWith('~/'))
16
+ path = join(homedir(), path.slice(2));
17
+ return isAbsolute(path) && existsSync(path) && statSync(path).isFile() ? path : undefined;
18
+ }
19
+ //# sourceMappingURL=pasted-path.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pasted-path.js","sourceRoot":"","sources":["../../src/prompt/pasted-path.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAC/C,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAE7C;;;GAGG;AACH,MAAM,UAAU,UAAU,CAAC,IAAY;IACrC,IAAI,IAAI,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;IACvB,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC;QAAE,OAAO,SAAS,CAAC;IAEnD,IAAI,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC;QAAE,IAAI,GAAG,kBAAkB,CAAC,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC;IACxF,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,gBAAgB,EAAE,IAAI,CAAC,CAAC,OAAO,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;IACpE,IAAI,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC;QAAE,IAAI,GAAG,IAAI,CAAC,OAAO,EAAE,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;IAEjE,OAAO,UAAU,CAAC,IAAI,CAAC,IAAI,UAAU,CAAC,IAAI,CAAC,IAAI,QAAQ,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC;AAC5F,CAAC"}
@@ -0,0 +1,62 @@
1
+ import { useStore } from 'jotai';
2
+ import { queueAtom, shownAtom, steeringAtom } from '../state/session.js';
3
+ import { useApi } from '../app/api.js';
4
+ import { useAttachments } from './attachments.js';
5
+ import { draftAtom, draftsAtom, fillDraft, historyAtom, requeueAtom, requeuesAtom } from './draft.js';
6
+ /** Sends the draft of the session the user looks at; what is sent goes to the history and leaves the prompt. */
7
+ export function usePrompt() {
8
+ const api = useApi();
9
+ const attachments = useAttachments();
10
+ const store = useStore();
11
+ const take = (value = store.get(draftAtom)) => {
12
+ const text = value.trim();
13
+ if (!text)
14
+ return undefined;
15
+ store.set(historyAtom, (history) => [...history, text]);
16
+ store.set(draftAtom, '');
17
+ return text;
18
+ };
19
+ const queue = (value) => {
20
+ const text = take(value);
21
+ if (text)
22
+ api.act(attachments.submission(text).then((submission) => api.inSession('session/queue', submission)));
23
+ };
24
+ return {
25
+ /** Queued messages taken back to edit go back in the queue, and are sent as any message once the turn has ended. */
26
+ submit(value) {
27
+ if (store.get(requeueAtom))
28
+ return queue(value);
29
+ const text = take(value);
30
+ if (text)
31
+ api.act(attachments.submission(text).then((submission) => api.inSession('session/submit', submission)));
32
+ },
33
+ queue,
34
+ /** Kept in the history, so `up` brings it back. */
35
+ clear() {
36
+ take();
37
+ },
38
+ /**
39
+ * Takes back into the prompt, as one, the steered messages the agent hasn't read yet and then the queued ones. Sent
40
+ * again, they steer the turn when any of them did, and go back in the queue when all were queued.
41
+ */
42
+ takeBack() {
43
+ const session = store.get(shownAtom).id;
44
+ const queued = store.get(queueAtom);
45
+ const steering = store.get(steeringAtom).length > 0;
46
+ api.act(Promise.all([
47
+ steering ? api.inSession('session/unsteer', {}) : [],
48
+ Promise.all(queued.map(({ text }) => api.inSession('session/unqueue', { text }))),
49
+ ]).then(([steered, unqueued]) => {
50
+ // The agent may have read them, or the turn ended and sent them, meanwhile.
51
+ const texts = [...steered, ...unqueued.flatMap((submission) => (submission ? [submission.text] : []))];
52
+ if (texts.length === 0)
53
+ return;
54
+ // Before anything typed since, as the core puts them back when a turn stops.
55
+ store.set(draftsAtom, (drafts) => fillDraft(drafts, session, texts.join('\n'), 'prepend'));
56
+ if (steered.length === 0)
57
+ store.set(requeuesAtom, (all) => ({ ...all, [session]: true }));
58
+ }));
59
+ },
60
+ };
61
+ }
62
+ //# sourceMappingURL=use-prompt.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-prompt.js","sourceRoot":"","sources":["../../src/prompt/use-prompt.ts"],"names":[],"mappings":"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"}
package/dist/serve.js ADDED
@@ -0,0 +1,38 @@
1
+ import { newToken, removeServerFile, writeServerFile } from '@jinion/core/api/server-file';
2
+ import { streamTransport } from '@jinion/core/api/stream-transport';
3
+ import { listenWebSocket } from '@jinion/core/api/websocket';
4
+ import { tildify } from '@jinion/core/lib/paths';
5
+ /**
6
+ * `jinion serve`: the core without a screen, for clients to drive. Resolves once it has stopped, on ctrl+c or when the
7
+ * stdio client goes; what it says goes to stderr, since stdout may carry the API.
8
+ */
9
+ export async function serve(server, options) {
10
+ const { cwd, version, stdio } = options;
11
+ if (stdio) {
12
+ const transport = streamTransport(process.stdin, process.stdout);
13
+ const connection = server.connect(transport);
14
+ await new Promise((resolve) => {
15
+ connection.peer.onClose(resolve);
16
+ stopOnSignal(() => transport.close());
17
+ });
18
+ return server.app.quit();
19
+ }
20
+ const token = newToken();
21
+ const listening = await listenWebSocket({ port: options.port, token, origins: options.origins }, (transport) => server.connect(transport));
22
+ const file = writeServerFile({ url: listening.url, token, cwd, pid: process.pid, version });
23
+ console.error(`jinion serves ${tildify(cwd)} at ${listening.url}`);
24
+ console.error(`Clients find its token in ${tildify(file)}, which only you can read. jinion --attach shows it here; ctrl+c stops it.`);
25
+ await new Promise((resolve) => stopOnSignal(resolve));
26
+ try {
27
+ await server.app.quit();
28
+ await listening.close();
29
+ }
30
+ finally {
31
+ removeServerFile(file);
32
+ }
33
+ }
34
+ function stopOnSignal(stop) {
35
+ process.once('SIGINT', stop);
36
+ process.once('SIGTERM', stop);
37
+ }
38
+ //# sourceMappingURL=serve.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"serve.js","sourceRoot":"","sources":["../src/serve.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AAE3F,OAAO,EAAE,eAAe,EAAE,MAAM,mCAAmC,CAAC;AACpE,OAAO,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAC7D,OAAO,EAAE,OAAO,EAAE,MAAM,wBAAwB,CAAC;AAYjD;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,KAAK,CAAC,MAAoB,EAAE,OAAqB;IACrE,MAAM,EAAE,GAAG,EAAE,OAAO,EAAE,KAAK,EAAE,GAAG,OAAO,CAAC;IAExC,IAAI,KAAK,EAAE,CAAC;QACV,MAAM,SAAS,GAAG,eAAe,CAAC,OAAO,CAAC,KAAK,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;QACjE,MAAM,UAAU,GAAG,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;QAE7C,MAAM,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,EAAE;YAClC,UAAU,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;YACjC,YAAY,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,KAAK,EAAE,CAAC,CAAC;QACxC,CAAC,CAAC,CAAC;QAEH,OAAO,MAAM,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC;IAC3B,CAAC;IAED,MAAM,KAAK,GAAG,QAAQ,EAAE,CAAC;IACzB,MAAM,SAAS,GAAG,MAAM,eAAe,CAAC,EAAE,IAAI,EAAE,OAAO,CAAC,IAAI,EAAE,KAAK,EAAE,OAAO,EAAE,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC,SAAS,EAAE,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC;IAC3I,MAAM,IAAI,GAAG,eAAe,CAAC,EAAE,GAAG,EAAE,SAAS,CAAC,GAAG,EAAE,KAAK,EAAE,GAAG,EAAE,GAAG,EAAE,OAAO,CAAC,GAAG,EAAE,OAAO,EAAE,CAAC,CAAC;IAE5F,OAAO,CAAC,KAAK,CAAC,iBAAiB,OAAO,CAAC,GAAG,CAAC,OAAO,SAAS,CAAC,GAAG,EAAE,CAAC,CAAC;IACnE,OAAO,CAAC,KAAK,CAAC,6BAA6B,OAAO,CAAC,IAAI,CAAC,4EAA4E,CAAC,CAAC;IAEtI,MAAM,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,EAAE,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC,CAAC;IAE5D,IAAI,CAAC;QACH,MAAM,MAAM,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC;QACxB,MAAM,SAAS,CAAC,KAAK,EAAE,CAAC;IAC1B,CAAC;YAAS,CAAC;QACT,gBAAgB,CAAC,IAAI,CAAC,CAAC;IACzB,CAAC;AACH,CAAC;AAED,SAAS,YAAY,CAAC,IAAgB;IACpC,OAAO,CAAC,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;IAC7B,OAAO,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;AAChC,CAAC"}
@@ -0,0 +1,91 @@
1
+ import { atom } from 'jotai';
2
+ import { modelLabel, modelName } from '@jinion/core/agent/models';
3
+ import { editTurns } from '@jinion/core/conversation/edits';
4
+ import { skillMention } from '@jinion/core/prompt/skills';
5
+ /** Set once as the app starts; everything below reads the client's store through it. */
6
+ export const clientAtom = atom(undefined);
7
+ function client(get) {
8
+ const found = get(clientAtom);
9
+ if (!found)
10
+ throw new Error('The app has no client yet.');
11
+ return found;
12
+ }
13
+ /** The session the app shows: the active one, once the client holds it. */
14
+ export const shownAtom = atom((get) => {
15
+ const following = client(get);
16
+ const id = get(following.shownAtom);
17
+ const snapshot = id === undefined ? undefined : get(following.session(id));
18
+ if (id === undefined || !snapshot)
19
+ throw new Error('No session is shown yet.');
20
+ return { id, ...snapshot };
21
+ });
22
+ export const sessionAtom = atom((get) => get(shownAtom).state);
23
+ /** Every open session, in the order they opened; the client follows them all. */
24
+ export const tabsAtom = atom((get) => {
25
+ const following = client(get);
26
+ const shown = get(following.shownAtom);
27
+ return get(following.sessionsAtom).sessions.map(({ id, title, working }) => ({
28
+ id,
29
+ title,
30
+ working,
31
+ waiting: get(following.session(id))?.fields.dialog !== undefined,
32
+ shown: id === shown,
33
+ }));
34
+ });
35
+ export const entriesAtom = atom((get) => get(sessionAtom).entries);
36
+ export const todosAtom = atom((get) => get(sessionAtom).todos);
37
+ export const worktreeAtom = atom((get) => get(sessionAtom).worktree);
38
+ export const busySinceAtom = atom((get) => get(sessionAtom).busySince);
39
+ export const busyAtom = atom((get) => get(busySinceAtom) !== undefined);
40
+ export const editTurnsAtom = atom((get) => editTurns(get(entriesAtom)));
41
+ const fields = (get) => get(shownAtom).fields;
42
+ /** From the moment a turn starts until it ends, also before its first event. */
43
+ export const workingAtom = atom((get) => fields(get).working);
44
+ export const queueAtom = atom((get) => fields(get).queue);
45
+ /** Steered into the running turn; each joins the conversation once the agent reads it. */
46
+ export const steeringAtom = atom((get) => fields(get).steering ?? []);
47
+ /** The files put with the session's messages that the core is still reading, each with what is being done to it. */
48
+ export const readingAtom = atom((get) => (fields(get).attachments ?? []).filter((file) => file.reading !== undefined));
49
+ export const selectionAtom = atom((get) => fields(get).selection);
50
+ export const modeAtom = atom((get) => fields(get).mode);
51
+ /** Includes the command or subagent the turn waits for, as `foreground`. */
52
+ export const tasksAtom = atom((get) => fields(get).tasks);
53
+ export const backgroundTasksAtom = atom((get) => get(tasksAtom).filter((task) => !task.foreground));
54
+ export const waitsOnForegroundTaskAtom = atom((get) => get(tasksAtom).some((task) => task.foreground && task.status === 'running'));
55
+ export const dialogAtom = atom((get) => fields(get).dialog);
56
+ function app(get) {
57
+ const found = get(client(get).appAtom);
58
+ if (!found)
59
+ throw new Error('The client is not initialized yet.');
60
+ return found;
61
+ }
62
+ /** The backend the shown session runs on, with what it and the session on it can do. */
63
+ export const agentAtom = atom((get) => {
64
+ const { agent: name, features } = fields(get);
65
+ const info = app(get).agents.find((candidate) => candidate.name === name);
66
+ if (!info)
67
+ throw new Error(`The server didn't describe ${name}.`);
68
+ return { ...info, features: { ...info.features, ...features } };
69
+ });
70
+ /** Whether `up` in an empty prompt has messages to take back: queued ones, or steered ones the agent can give back. */
71
+ export const takeBackAtom = atom((get) => get(queueAtom).length > 0 || (get(steeringAtom).length > 0 && get(agentAtom).features.unsteer === true));
72
+ export const agentsAtom = atom((get) => app(get).agents);
73
+ /** Every backend's models, by backend; one is missing until it has listed them. */
74
+ export const allModelsAtom = atom((get) => app(get).models);
75
+ export const modelsAtom = atom((get) => app(get).models[get(agentAtom).name]);
76
+ export const accountAtom = atom((get) => app(get).accounts[get(agentAtom).name]);
77
+ export const identityAtom = atom((get) => app(get).identities[get(agentAtom).name]);
78
+ const noSkills = [];
79
+ export const skillsAtom = atom((get) => app(get).skills[get(agentAtom).name] ?? noSkills);
80
+ export const seenLimitsAtom = atom((get) => app(get).seenLimits);
81
+ /** Who is signed in to Jinion's own account; null until someone is, and the app shows only its sign-in until then. */
82
+ export const jinionUserAtom = atom((get) => app(get).jinionUser ?? null);
83
+ const noAnnouncements = [];
84
+ /** What the Jinion team says now that this user hasn't put away. */
85
+ export const announcementsAtom = atom((get) => app(get).announcements ?? noAnnouncements);
86
+ /** The default for new sessions, which `ctrl+g` turns on and off. */
87
+ export const worktreesAtom = atom((get) => app(get).worktrees);
88
+ export const mentionAtom = atom((get) => skillMention(get(skillsAtom)));
89
+ export const modelNameAtom = atom((get) => modelName(get(selectionAtom), get(modelsAtom)));
90
+ export const modelLabelAtom = atom((get) => modelLabel(get(selectionAtom), get(modelsAtom)));
91
+ //# sourceMappingURL=session.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session.js","sourceRoot":"","sources":["../../src/state/session.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,39 @@
1
+ import { useEffect, useState } from 'react';
2
+ import { useTheme } from '@jinion/tui';
3
+ import { atom, useAtomValue } from 'jotai';
4
+ import { limitsKey } from '@jinion/core/agent/usage';
5
+ import { useApi } from '../app/api.js';
6
+ import { accountAtom, agentAtom, identityAtom, modeAtom, modelNameAtom, seenLimitsAtom, selectionAtom, sessionAtom } from '../state/session.js';
7
+ /** Set by the status line, which runs `git status` only while a shown segment needs it. */
8
+ export const gitStatusAtom = atom(undefined);
9
+ export function useStatusData(now = Date.now()) {
10
+ const { info } = useApi().initialized;
11
+ const agent = useAtomValue(agentAtom);
12
+ const account = useAtomValue(accountAtom);
13
+ const seen = useAtomValue(seenLimitsAtom);
14
+ return {
15
+ version: info.version,
16
+ cwd: info.cwd,
17
+ agent: agent.name,
18
+ model: { name: useAtomValue(modelNameAtom), selection: useAtomValue(selectionAtom) },
19
+ mode: useAtomValue(modeAtom),
20
+ account: useAtomValue(identityAtom),
21
+ session: useAtomValue(sessionAtom),
22
+ git: useAtomValue(gitStatusAtom),
23
+ limits: seen[limitsKey(agent.name, account)]?.windows,
24
+ now,
25
+ theme: useTheme(),
26
+ };
27
+ }
28
+ export function useNow(active, interval = 15_000) {
29
+ const [now, setNow] = useState(Date.now);
30
+ useEffect(() => {
31
+ if (!active)
32
+ return;
33
+ setNow(Date.now());
34
+ const timer = setInterval(() => setNow(Date.now()), interval);
35
+ return () => clearInterval(timer);
36
+ }, [active, interval]);
37
+ return now;
38
+ }
39
+ //# sourceMappingURL=data.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"data.js","sourceRoot":"","sources":["../../src/status/data.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAC5C,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AACvC,OAAO,EAAE,IAAI,EAAE,YAAY,EAAE,MAAM,OAAO,CAAC;AAE3C,OAAO,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAC;AACrD,OAAO,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AACvC,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,YAAY,EAAE,QAAQ,EAAE,aAAa,EAAE,cAAc,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAGhJ,2FAA2F;AAC3F,MAAM,CAAC,MAAM,aAAa,GAAG,IAAI,CAAwB,SAAS,CAAC,CAAC;AAEpE,MAAM,UAAU,aAAa,CAAC,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE;IAC5C,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,EAAE,CAAC,WAAW,CAAC;IACtC,MAAM,KAAK,GAAG,YAAY,CAAC,SAAS,CAAC,CAAC;IACtC,MAAM,OAAO,GAAG,YAAY,CAAC,WAAW,CAAC,CAAC;IAC1C,MAAM,IAAI,GAAG,YAAY,CAAC,cAAc,CAAC,CAAC;IAE1C,OAAO;QACL,OAAO,EAAE,IAAI,CAAC,OAAO;QACrB,GAAG,EAAE,IAAI,CAAC,GAAG;QACb,KAAK,EAAE,KAAK,CAAC,IAAI;QACjB,KAAK,EAAE,EAAE,IAAI,EAAE,YAAY,CAAC,aAAa,CAAC,EAAE,SAAS,EAAE,YAAY,CAAC,aAAa,CAAC,EAAE;QACpF,IAAI,EAAE,YAAY,CAAC,QAAQ,CAAC;QAC5B,OAAO,EAAE,YAAY,CAAC,YAAY,CAAC;QACnC,OAAO,EAAE,YAAY,CAAC,WAAW,CAAC;QAClC,GAAG,EAAE,YAAY,CAAC,aAAa,CAAC;QAChC,MAAM,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,EAAE,OAAO;QACrD,GAAG;QACH,KAAK,EAAE,QAAQ,EAAE;KAClB,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,MAAM,CAAC,MAAe,EAAE,QAAQ,GAAG,MAAM;IACvD,MAAM,CAAC,GAAG,EAAE,MAAM,CAAC,GAAG,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAEzC,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,CAAC,MAAM;YAAE,OAAO;QAEpB,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC;QAEnB,MAAM,KAAK,GAAG,WAAW,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,EAAE,QAAQ,CAAC,CAAC;QAE9D,OAAO,GAAG,EAAE,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;IACpC,CAAC,EAAE,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC,CAAC;IAEvB,OAAO,GAAG,CAAC;AACb,CAAC"}
@@ -0,0 +1,18 @@
1
+ import { useEffect, useState } from 'react';
2
+ import { useApi } from '../app/api.js';
3
+ /** Of the folder the shown session works in, read again as `folder` or `refresh` changes; the last one stays shown meanwhile. */
4
+ export function useGitStatus(folder, enabled, refresh) {
5
+ const api = useApi();
6
+ const [status, setStatus] = useState();
7
+ useEffect(() => {
8
+ if (!enabled)
9
+ return;
10
+ let current = true;
11
+ api.inSession('git/status', {}).then((found) => current && setStatus(found ?? undefined), () => { });
12
+ return () => {
13
+ current = false;
14
+ };
15
+ }, [folder, enabled, refresh]);
16
+ return enabled ? status : undefined;
17
+ }
18
+ //# sourceMappingURL=git.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"git.js","sourceRoot":"","sources":["../../src/status/git.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAE5C,OAAO,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AAEvC,iIAAiI;AACjI,MAAM,UAAU,YAAY,CAAC,MAAc,EAAE,OAAgB,EAAE,OAAgB;IAC7E,MAAM,GAAG,GAAG,MAAM,EAAE,CAAC;IAErB,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,GAAG,QAAQ,EAAa,CAAC;IAElD,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,CAAC,OAAO;YAAE,OAAO;QAErB,IAAI,OAAO,GAAG,IAAI,CAAC;QAEnB,GAAG,CAAC,SAAS,CAAC,YAAY,EAAE,EAAE,CAAC,CAAC,IAAI,CAClC,CAAC,KAAK,EAAE,EAAE,CAAC,OAAO,IAAI,SAAS,CAAC,KAAK,IAAI,SAAS,CAAC,EACnD,GAAG,EAAE,GAAE,CAAC,CACT,CAAC;QAEF,OAAO,GAAG,EAAE;YACV,OAAO,GAAG,KAAK,CAAC;QAClB,CAAC,CAAC;IACJ,CAAC,EAAE,CAAC,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC;IAE/B,OAAO,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC;AACtC,CAAC"}
@@ -0,0 +1,8 @@
1
+ import { atom } from 'jotai';
2
+ import { persistedAtom } from '@jinion/core/lib/persisted';
3
+ import { DEFAULT_STATUS_LINE, knownItems } from './line.js';
4
+ import { loadStatusLine, saveStatusLine } from './saved.js';
5
+ export const statusItemsAtom = persistedAtom(() => knownItems(loadStatusLine() ?? DEFAULT_STATUS_LINE), saveStatusLine);
6
+ export const statusPreviewAtom = atom(undefined);
7
+ export const shownStatusItemsAtom = atom((get) => get(statusPreviewAtom) ?? get(statusItemsAtom));
8
+ //# sourceMappingURL=items.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"items.js","sourceRoot":"","sources":["../../src/status/items.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,OAAO,CAAC;AAC7B,OAAO,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAC3D,OAAO,EAAE,mBAAmB,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAC5D,OAAO,EAAE,cAAc,EAAE,cAAc,EAAmB,MAAM,YAAY,CAAC;AAE7E,MAAM,CAAC,MAAM,eAAe,GAAG,aAAa,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,cAAc,EAAE,IAAI,mBAAmB,CAAC,EAAE,cAAc,CAAC,CAAC;AAExH,MAAM,CAAC,MAAM,iBAAiB,GAAG,IAAI,CAA2B,SAAS,CAAC,CAAC;AAE3E,MAAM,CAAC,MAAM,oBAAoB,GAAG,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,iBAAiB,CAAC,IAAI,GAAG,CAAC,eAAe,CAAC,CAAC,CAAC"}
@@ -0,0 +1,25 @@
1
+ import { findSegment } from './segments/index.js';
2
+ export const DEFAULT_STATUS_LINE = [
3
+ { id: 'brand', side: 'left' },
4
+ { id: 'model', side: 'left' },
5
+ { id: 'directory', side: 'left' },
6
+ { id: 'worktree', side: 'left' },
7
+ { id: 'context', side: 'left' },
8
+ { id: 'cost', side: 'left' },
9
+ { id: 'title', side: 'right' },
10
+ ];
11
+ export function renderStatusLine(items, data) {
12
+ const left = [];
13
+ const right = [];
14
+ for (const item of items) {
15
+ const node = findSegment(item.id)?.render(data, styleOf(item));
16
+ if (node === undefined || node === null || node === false || node === '')
17
+ continue;
18
+ (item.side === 'right' ? right : left).push(node);
19
+ }
20
+ return { left, right };
21
+ }
22
+ export const styleOf = (item) => item.style ?? findSegment(item.id)?.styles?.[0]?.id ?? '';
23
+ /** Settings can name segments a later version dropped. */
24
+ export const knownItems = (items) => items.filter((item) => findSegment(item.id));
25
+ //# sourceMappingURL=line.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"line.js","sourceRoot":"","sources":["../../src/status/line.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAElD,MAAM,CAAC,MAAM,mBAAmB,GAAiB;IAC/C,EAAE,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE;IAC7B,EAAE,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE;IAC7B,EAAE,EAAE,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,EAAE;IACjC,EAAE,EAAE,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,EAAE;IAChC,EAAE,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,EAAE;IAC/B,EAAE,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE;IAC5B,EAAE,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE;CAC/B,CAAC;AAEF,MAAM,UAAU,gBAAgB,CAAC,KAAmB,EAAE,IAAgB;IACpE,MAAM,IAAI,GAAgB,EAAE,CAAC;IAC7B,MAAM,KAAK,GAAgB,EAAE,CAAC;IAE9B,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,IAAI,GAAG,WAAW,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;QAC/D,IAAI,IAAI,KAAK,SAAS,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,EAAE;YAAE,SAAS;QAEnF,CAAC,IAAI,CAAC,IAAI,KAAK,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACpD,CAAC;IAED,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC;AACzB,CAAC;AAED,MAAM,CAAC,MAAM,OAAO,GAAG,CAAC,IAAgB,EAAE,EAAE,CAAC,IAAI,CAAC,KAAK,IAAI,WAAW,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,IAAI,EAAE,CAAC;AAEvG,0DAA0D;AAC1D,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,KAAmB,EAAE,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,WAAW,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC"}
@@ -0,0 +1,8 @@
1
+ import { join } from 'node:path';
2
+ import { readJson, updateJson } from '@jinion/core/lib/json-file';
3
+ import { jinionHome } from '@jinion/core/lib/paths';
4
+ /** The layout is this app's own, kept in the user's settings file beside what the core keeps there. */
5
+ const file = () => join(jinionHome(), 'settings.json');
6
+ export const loadStatusLine = () => readJson(file(), {}).statusLine;
7
+ export const saveStatusLine = (statusLine) => updateJson(file(), {}, (current) => ({ ...current, statusLine }));
8
+ //# sourceMappingURL=saved.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"saved.js","sourceRoot":"","sources":["../../src/status/saved.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAC;AAClE,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AAWpD,uGAAuG;AACvG,MAAM,IAAI,GAAG,GAAG,EAAE,CAAC,IAAI,CAAC,UAAU,EAAE,EAAE,eAAe,CAAC,CAAC;AAEvD,MAAM,CAAC,MAAM,cAAc,GAAG,GAAG,EAAE,CAAC,QAAQ,CAAgC,IAAI,EAAE,EAAE,EAAE,CAAC,CAAC,UAAU,CAAC;AAEnG,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,UAAwB,EAAE,EAAE,CAAC,UAAU,CAAS,IAAI,EAAE,EAAE,EAAE,EAAE,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,EAAE,GAAG,OAAO,EAAE,UAAU,EAAE,CAAC,CAAC,CAAC"}
@@ -0,0 +1,2 @@
1
+ export const levelColor = (theme, used) => (used >= 0.8 ? theme.error : used >= 0.5 ? theme.warning : theme.success);
2
+ //# sourceMappingURL=segment.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"segment.js","sourceRoot":"","sources":["../../src/status/segment.ts"],"names":[],"mappings":"AAsCA,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,KAAY,EAAE,IAAY,EAAE,EAAE,CAAC,CAAC,IAAI,IAAI,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,IAAI,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC"}
@@ -0,0 +1,71 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { countChanges, parsePatch, Text } from '@jinion/tui';
3
+ import { clockTime, minutes, plural } from '@jinion/core/lib/format';
4
+ export const changes = {
5
+ id: 'changes',
6
+ name: 'Changes',
7
+ description: 'Lines added and removed in this conversation',
8
+ render: ({ session, theme }) => {
9
+ const { added, removed } = sessionChanges(session.entries);
10
+ if (added === 0 && removed === 0)
11
+ return undefined;
12
+ return (_jsxs(Text, { children: [_jsxs(Text, { color: theme.success, children: ["+", added] }), " ", _jsxs(Text, { color: theme.error, children: ["-", removed] })] }));
13
+ },
14
+ };
15
+ export const tasks = {
16
+ id: 'tasks',
17
+ name: 'Tasks',
18
+ description: "Progress on the agent's task list",
19
+ render: ({ session, theme }) => {
20
+ const items = session.todos.flatMap((group) => group.items);
21
+ if (items.length === 0)
22
+ return undefined;
23
+ const done = items.filter((item) => item.status === 'done').length;
24
+ return (_jsxs(Text, { children: [_jsx(Text, { color: theme.muted, children: "tasks " }), done, "/", items.length] }));
25
+ },
26
+ };
27
+ export const title = {
28
+ id: 'title',
29
+ name: 'Title',
30
+ description: 'What the conversation is about',
31
+ render: ({ session, theme }) => session.title && _jsx(Text, { color: theme.muted, children: session.title }),
32
+ };
33
+ export const duration = {
34
+ id: 'duration',
35
+ name: 'Duration',
36
+ description: 'How long ago the conversation started',
37
+ ticks: true,
38
+ render: ({ session, now, theme }) => _jsx(Text, { color: theme.muted, children: minutes(now - session.createdAt) }),
39
+ };
40
+ export const turns = {
41
+ id: 'turns',
42
+ name: 'Turns',
43
+ description: 'Prompts sent in this conversation',
44
+ render: ({ session, theme }) => (_jsx(Text, { color: theme.muted, children: plural(session.entries.filter((entry) => entry.kind === 'user').length, 'turn') })),
45
+ };
46
+ export const time = {
47
+ id: 'time',
48
+ name: 'Clock',
49
+ description: 'The time of day',
50
+ ticks: true,
51
+ render: ({ now, theme }) => _jsx(Text, { color: theme.muted, children: clockTime(new Date(now)) }),
52
+ };
53
+ const changesByEntry = new WeakMap();
54
+ /** Entries never change once they are done, so each patch is parsed once. */
55
+ function sessionChanges(entries) {
56
+ let added = 0;
57
+ let removed = 0;
58
+ for (const entry of entries) {
59
+ if (entry.kind !== 'tool' || entry.run.name !== 'edit' || entry.status !== 'done')
60
+ continue;
61
+ let counts = changesByEntry.get(entry);
62
+ if (!counts) {
63
+ counts = countChanges(parsePatch(entry.run.result?.patch ?? entry.run.input.patch));
64
+ changesByEntry.set(entry, counts);
65
+ }
66
+ added += counts.added;
67
+ removed += counts.removed;
68
+ }
69
+ return { added, removed };
70
+ }
71
+ //# sourceMappingURL=conversation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"conversation.js","sourceRoot":"","sources":["../../../src/status/segments/conversation.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,33 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Text } from '@jinion/tui';
3
+ import { Tag } from '@jinion/tui/chat';
4
+ export const git = {
5
+ id: 'git',
6
+ name: 'Git',
7
+ description: 'The branch, with uncommitted files and commits ahead or behind; for several repositories, how many',
8
+ styles: [
9
+ { id: 'changes', name: 'with changes' },
10
+ { id: 'branch', name: 'branch only' },
11
+ ],
12
+ git: true,
13
+ render: ({ git, theme }, style) => {
14
+ if (!git)
15
+ return undefined;
16
+ // A folder of several repositories sums them up; `/diff` tells them apart. A single one in a folder below is named.
17
+ const [only] = git.repos;
18
+ const where = git.repos.length > 1 || !only ? `${git.repos.length} repos` : only.repo.path ? `${only.repo.label} ${only.branch}` : only.branch;
19
+ const sum = (key) => git.repos.reduce((total, repo) => total + repo[key], 0);
20
+ const details = style === 'changes'
21
+ ? [sum('changed') > 0 && `*${sum('changed')}`, sum('ahead') > 0 && `↑${sum('ahead')}`, sum('behind') > 0 && `↓${sum('behind')}`]
22
+ : [];
23
+ const extra = details.filter(Boolean).join(' ');
24
+ return (_jsx(Tag, { name: "G", value: _jsxs(Text, { children: [where, extra && _jsxs(Text, { color: theme.warning, children: [" ", extra] })] }), color: theme.code }));
25
+ },
26
+ };
27
+ export const worktree = {
28
+ id: 'worktree',
29
+ name: 'Worktree',
30
+ description: 'The git worktree the conversation works in, when it has one (ctrl+g)',
31
+ render: ({ session, theme }) => session.worktree && _jsx(Tag, { name: "W", value: session.worktree.name, color: theme.code }),
32
+ };
33
+ //# sourceMappingURL=git.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"git.js","sourceRoot":"","sources":["../../../src/status/segments/git.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC;AACnC,OAAO,EAAE,GAAG,EAAE,MAAM,kBAAkB,CAAC;AAGvC,MAAM,CAAC,MAAM,GAAG,GAAY;IAC1B,EAAE,EAAE,KAAK;IACT,IAAI,EAAE,KAAK;IACX,WAAW,EAAE,oGAAoG;IACjH,MAAM,EAAE;QACN,EAAE,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,cAAc,EAAE;QACvC,EAAE,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,aAAa,EAAE;KACtC;IACD,GAAG,EAAE,IAAI;IACT,MAAM,EAAE,CAAC,EAAE,GAAG,EAAE,KAAK,EAAE,EAAE,KAAK,EAAE,EAAE;QAChC,IAAI,CAAC,GAAG;YAAE,OAAO,SAAS,CAAC;QAE3B,oHAAoH;QACpH,MAAM,CAAC,IAAI,CAAC,GAAG,GAAG,CAAC,KAAK,CAAC;QACzB,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,KAAK,CAAC,MAAM,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC;QAC/I,MAAM,GAAG,GAAG,CAAC,GAAmC,EAAE,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE,CAAC,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC;QAE7G,MAAM,OAAO,GACX,KAAK,KAAK,SAAS;YACjB,CAAC,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,IAAI,GAAG,CAAC,SAAS,CAAC,EAAE,EAAE,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,IAAI,GAAG,CAAC,OAAO,CAAC,EAAE,EAAE,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,IAAI,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC;YAChI,CAAC,CAAC,EAAE,CAAC;QAET,MAAM,KAAK,GAAG,OAAO,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAEhD,OAAO,CACL,KAAC,GAAG,IACF,IAAI,EAAC,GAAG,EACR,KAAK,EACH,MAAC,IAAI,eACF,KAAK,EACL,KAAK,IAAI,MAAC,IAAI,IAAC,KAAK,EAAE,KAAK,CAAC,OAAO,kBAAI,KAAK,IAAQ,IAChD,EAET,KAAK,EAAE,KAAK,CAAC,IAAI,GACjB,CACH,CAAC;IACJ,CAAC;CACF,CAAC;AAEF,MAAM,CAAC,MAAM,QAAQ,GAAY;IAC/B,EAAE,EAAE,UAAU;IACd,IAAI,EAAE,UAAU;IAChB,WAAW,EAAE,sEAAsE;IACnF,MAAM,EAAE,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,OAAO,CAAC,QAAQ,IAAI,KAAC,GAAG,IAAC,IAAI,EAAC,GAAG,EAAC,KAAK,EAAE,OAAO,CAAC,QAAQ,CAAC,IAAI,EAAE,KAAK,EAAE,KAAK,CAAC,IAAI,GAAI;CACtH,CAAC"}