@sumicom/quicksave 0.5.1 → 0.6.0

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 (50) hide show
  1. package/dist/ai/asyncQueue.d.ts +16 -0
  2. package/dist/ai/asyncQueue.d.ts.map +1 -0
  3. package/dist/ai/asyncQueue.js +39 -0
  4. package/dist/ai/asyncQueue.js.map +1 -0
  5. package/dist/ai/asyncQueue.test.d.ts +2 -0
  6. package/dist/ai/asyncQueue.test.d.ts.map +1 -0
  7. package/dist/ai/asyncQueue.test.js +56 -0
  8. package/dist/ai/asyncQueue.test.js.map +1 -0
  9. package/dist/ai/cardBuilder.d.ts +64 -0
  10. package/dist/ai/cardBuilder.d.ts.map +1 -0
  11. package/dist/ai/cardBuilder.js +503 -0
  12. package/dist/ai/cardBuilder.js.map +1 -0
  13. package/dist/ai/claudeCodeService.d.ts +65 -32
  14. package/dist/ai/claudeCodeService.d.ts.map +1 -1
  15. package/dist/ai/claudeCodeService.js +534 -267
  16. package/dist/ai/claudeCodeService.js.map +1 -1
  17. package/dist/connection/connection.d.ts +24 -1
  18. package/dist/connection/connection.d.ts.map +1 -1
  19. package/dist/connection/connection.js +92 -6
  20. package/dist/connection/connection.js.map +1 -1
  21. package/dist/connection/pubsub.d.ts +41 -0
  22. package/dist/connection/pubsub.d.ts.map +1 -0
  23. package/dist/connection/pubsub.js +101 -0
  24. package/dist/connection/pubsub.js.map +1 -0
  25. package/dist/connection/pubsub.test.d.ts +2 -0
  26. package/dist/connection/pubsub.test.d.ts.map +1 -0
  27. package/dist/connection/pubsub.test.js +96 -0
  28. package/dist/connection/pubsub.test.js.map +1 -0
  29. package/dist/connection/relay.d.ts +4 -0
  30. package/dist/connection/relay.d.ts.map +1 -1
  31. package/dist/connection/relay.js +30 -0
  32. package/dist/connection/relay.js.map +1 -1
  33. package/dist/handlers/messageHandler.d.ts +22 -2
  34. package/dist/handlers/messageHandler.d.ts.map +1 -1
  35. package/dist/handlers/messageHandler.js +207 -16
  36. package/dist/handlers/messageHandler.js.map +1 -1
  37. package/dist/handlers/messageHandler.test.js +1 -1
  38. package/dist/index.js +192 -4
  39. package/dist/index.js.map +1 -1
  40. package/dist/service/ipc.test.js +6 -6
  41. package/dist/service/ipcClient.js +1 -1
  42. package/dist/service/run.d.ts.map +1 -1
  43. package/dist/service/run.js +125 -13
  44. package/dist/service/run.js.map +1 -1
  45. package/dist/service/singleton.test.js +1 -1
  46. package/dist/service/types.d.ts +29 -0
  47. package/dist/service/types.d.ts.map +1 -1
  48. package/dist/service/types.js +11 -0
  49. package/dist/service/types.js.map +1 -1
  50. package/package.json +2 -2
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Push-based async iterable.
3
+ * Consumers `for await` over it; producers call `push()` to enqueue values
4
+ * and `end()` to signal completion.
5
+ */
6
+ export declare class AsyncQueue<T> implements AsyncIterable<T> {
7
+ private queue;
8
+ private resolve;
9
+ private done;
10
+ /** Enqueue a value. No-op if end() was already called. */
11
+ push(value: T): void;
12
+ /** Signal that no more values will be pushed. */
13
+ end(): void;
14
+ [Symbol.asyncIterator](): AsyncGenerator<T, void>;
15
+ }
16
+ //# sourceMappingURL=asyncQueue.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"asyncQueue.d.ts","sourceRoot":"","sources":["../../src/ai/asyncQueue.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,qBAAa,UAAU,CAAC,CAAC,CAAE,YAAW,aAAa,CAAC,CAAC,CAAC;IACpD,OAAO,CAAC,KAAK,CAAW;IACxB,OAAO,CAAC,OAAO,CAA6B;IAC5C,OAAO,CAAC,IAAI,CAAS;IAErB,0DAA0D;IAC1D,IAAI,CAAC,KAAK,EAAE,CAAC,GAAG,IAAI;IASpB,iDAAiD;IACjD,GAAG,IAAI,IAAI;IAQJ,CAAC,MAAM,CAAC,aAAa,CAAC,IAAI,cAAc,CAAC,CAAC,EAAE,IAAI,CAAC;CASzD"}
@@ -0,0 +1,39 @@
1
+ /**
2
+ * Push-based async iterable.
3
+ * Consumers `for await` over it; producers call `push()` to enqueue values
4
+ * and `end()` to signal completion.
5
+ */
6
+ export class AsyncQueue {
7
+ queue = [];
8
+ resolve = null;
9
+ done = false;
10
+ /** Enqueue a value. No-op if end() was already called. */
11
+ push(value) {
12
+ if (this.done)
13
+ return;
14
+ this.queue.push(value);
15
+ if (this.resolve) {
16
+ this.resolve();
17
+ this.resolve = null;
18
+ }
19
+ }
20
+ /** Signal that no more values will be pushed. */
21
+ end() {
22
+ this.done = true;
23
+ if (this.resolve) {
24
+ this.resolve();
25
+ this.resolve = null;
26
+ }
27
+ }
28
+ async *[Symbol.asyncIterator]() {
29
+ while (true) {
30
+ while (this.queue.length > 0) {
31
+ yield this.queue.shift();
32
+ }
33
+ if (this.done)
34
+ return;
35
+ await new Promise((r) => { this.resolve = r; });
36
+ }
37
+ }
38
+ }
39
+ //# sourceMappingURL=asyncQueue.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"asyncQueue.js","sourceRoot":"","sources":["../../src/ai/asyncQueue.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,MAAM,OAAO,UAAU;IACb,KAAK,GAAQ,EAAE,CAAC;IAChB,OAAO,GAAwB,IAAI,CAAC;IACpC,IAAI,GAAG,KAAK,CAAC;IAErB,0DAA0D;IAC1D,IAAI,CAAC,KAAQ;QACX,IAAI,IAAI,CAAC,IAAI;YAAE,OAAO;QACtB,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACvB,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YACjB,IAAI,CAAC,OAAO,EAAE,CAAC;YACf,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC;QACtB,CAAC;IACH,CAAC;IAED,iDAAiD;IACjD,GAAG;QACD,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YACjB,IAAI,CAAC,OAAO,EAAE,CAAC;YACf,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC;QACtB,CAAC;IACH,CAAC;IAED,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,aAAa,CAAC;QAC3B,OAAO,IAAI,EAAE,CAAC;YACZ,OAAO,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBAC7B,MAAM,IAAI,CAAC,KAAK,CAAC,KAAK,EAAG,CAAC;YAC5B,CAAC;YACD,IAAI,IAAI,CAAC,IAAI;gBAAE,OAAO;YACtB,MAAM,IAAI,OAAO,CAAO,CAAC,CAAC,EAAE,EAAE,GAAG,IAAI,CAAC,OAAO,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QACxD,CAAC;IACH,CAAC;CACF"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=asyncQueue.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"asyncQueue.test.d.ts","sourceRoot":"","sources":["../../src/ai/asyncQueue.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,56 @@
1
+ import { describe, it, expect } from 'vitest';
2
+ import { AsyncQueue } from './asyncQueue.js';
3
+ describe('AsyncQueue', () => {
4
+ it('yields pushed values in order', async () => {
5
+ const q = new AsyncQueue();
6
+ q.push(1);
7
+ q.push(2);
8
+ q.push(3);
9
+ q.end();
10
+ const results = [];
11
+ for await (const v of q) {
12
+ results.push(v);
13
+ }
14
+ expect(results).toEqual([1, 2, 3]);
15
+ });
16
+ it('waits for values when consumed before pushed', async () => {
17
+ const q = new AsyncQueue();
18
+ const results = [];
19
+ const consumer = (async () => {
20
+ for await (const v of q) {
21
+ results.push(v);
22
+ }
23
+ })();
24
+ // Push after consumer starts waiting
25
+ q.push('a');
26
+ q.push('b');
27
+ q.end();
28
+ await consumer;
29
+ expect(results).toEqual(['a', 'b']);
30
+ });
31
+ it('stops iterating after end() is called', async () => {
32
+ const q = new AsyncQueue();
33
+ q.push(1);
34
+ q.end();
35
+ q.push(2); // should be ignored after end
36
+ const results = [];
37
+ for await (const v of q) {
38
+ results.push(v);
39
+ }
40
+ expect(results).toEqual([1]);
41
+ });
42
+ it('supports multiple sequential consumers via Symbol.asyncIterator', async () => {
43
+ const q = new AsyncQueue();
44
+ q.push(1);
45
+ q.push(2);
46
+ const iter = q[Symbol.asyncIterator]();
47
+ const first = await iter.next();
48
+ expect(first).toEqual({ value: 1, done: false });
49
+ const second = await iter.next();
50
+ expect(second).toEqual({ value: 2, done: false });
51
+ q.end();
52
+ const third = await iter.next();
53
+ expect(third).toEqual({ value: undefined, done: true });
54
+ });
55
+ });
56
+ //# sourceMappingURL=asyncQueue.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"asyncQueue.test.js","sourceRoot":"","sources":["../../src/ai/asyncQueue.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,64 @@
1
+ import type { Card, CardId, CardEvent, CardHistoryResponse, PendingInputAttachment } from '@sumicom/quicksave-shared';
2
+ export declare class StreamCardBuilder {
3
+ private sessionId;
4
+ private streamId;
5
+ private seq;
6
+ private cards;
7
+ /** tool_use_id → CardId, for pairing tool_result to ToolCallCard */
8
+ private toolUseIdToCardId;
9
+ /** agentId (task_id) → CardId, for matching subagent updates */
10
+ private agentIdToCardId;
11
+ /** Cards created for subagent permissions — removed after resolution. */
12
+ private ephemeralCards;
13
+ /** Current streaming assistant_text card (for append_text events) */
14
+ private currentTextCardId;
15
+ constructor(sessionId: string, streamId: string);
16
+ updateSessionId(sessionId: string): void;
17
+ /** Start a new turn: update streamId and reset per-turn state, keep accumulated cards. */
18
+ startNewTurn(streamId: string): void;
19
+ private nextId;
20
+ private addEvent;
21
+ private updateEvent;
22
+ private appendTextEvent;
23
+ private removeEvent;
24
+ userMessage(text: string): CardEvent;
25
+ thinkingBlock(text: string): CardEvent;
26
+ /**
27
+ * Append text to current assistant_text card, or create a new one.
28
+ * Returns append_text event (hot path) or add event (new card).
29
+ */
30
+ assistantText(text: string): CardEvent;
31
+ /** Mark the current assistant_text card as done streaming. */
32
+ finalizeAssistantText(): CardEvent | null;
33
+ /**
34
+ * Handle tool_use block from SDK stream.
35
+ * If the card was already pre-created via `toolCallFromPermission()`, confirm it.
36
+ * Otherwise create a new ToolCallCard.
37
+ */
38
+ toolUse(toolName: string, toolInput: Record<string, unknown>, toolUseId: string): CardEvent;
39
+ /**
40
+ * Pre-create a ToolCallCard from canUseTool (fires before tool_use stream event).
41
+ * This eliminates the synthetic message hack.
42
+ */
43
+ toolCallFromPermission(toolName: string, toolInput: Record<string, unknown>, toolUseId: string, pendingInput: PendingInputAttachment,
44
+ /** Ephemeral cards are removed after permission is resolved (subagent permissions). */
45
+ ephemeral?: boolean): CardEvent;
46
+ /** Attach a pending input to a subagent card (subagent permission). */
47
+ attachPendingToSubagent(agentId: string, pendingInput: PendingInputAttachment): CardEvent | null;
48
+ /** Clear pending input from a card. Ephemeral cards are removed entirely. */
49
+ clearPendingInput(requestId: string): CardEvent | null;
50
+ /** Find the card ID for a given requestId. */
51
+ findCardByRequestId(requestId: string): CardId | undefined;
52
+ /** Check if a tool card already exists for the given tool_use_id. */
53
+ hasToolCard(toolUseId: string): boolean;
54
+ /** Return all live cards (insertion order). Cards carry pendingInput if set. */
55
+ getCards(): Card[];
56
+ toolResult(toolUseId: string, content: string, isError: boolean): CardEvent | null;
57
+ subagentStart(description: string, agentId: string, toolUseId?: string): CardEvent;
58
+ subagentProgress(agentId: string, toolUseId: string | undefined, toolUseCount?: number, lastToolName?: string): CardEvent | null;
59
+ subagentEnd(agentId: string, toolUseId: string | undefined, status: 'completed' | 'failed' | 'stopped', summary?: string): CardEvent | null;
60
+ systemMessage(text: string, subtype?: 'compacted' | 'cost' | 'error' | 'info' | 'warning'): CardEvent;
61
+ errorMessage(text: string): CardEvent;
62
+ }
63
+ export declare function buildCardsFromHistory(sessionId: string, cwd: string, offset?: number, limit?: number): Promise<CardHistoryResponse>;
64
+ //# sourceMappingURL=cardBuilder.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cardBuilder.d.ts","sourceRoot":"","sources":["../../src/ai/cardBuilder.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,IAAI,EACJ,MAAM,EACN,SAAS,EAKT,mBAAmB,EAGnB,sBAAsB,EACvB,MAAM,2BAA2B,CAAC;AA0BnC,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,GAAG,CAAK;IAChB,OAAO,CAAC,KAAK,CAA2B;IACxC,oEAAoE;IACpE,OAAO,CAAC,iBAAiB,CAA6B;IACtD,gEAAgE;IAChE,OAAO,CAAC,eAAe,CAA6B;IACpD,yEAAyE;IACzE,OAAO,CAAC,cAAc,CAAqB;IAC3C,qEAAqE;IACrE,OAAO,CAAC,iBAAiB,CAAuB;gBAEpC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM;IAK/C,eAAe,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI;IAIxC,0FAA0F;IAC1F,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI;IAKpC,OAAO,CAAC,MAAM;IAId,OAAO,CAAC,QAAQ;IAKhB,OAAO,CAAC,WAAW;IAQnB,OAAO,CAAC,eAAe;IAQvB,OAAO,CAAC,WAAW;IAOnB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS;IAMpC,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS;IAMtC;;;OAGG;IACH,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS;IAUtC,8DAA8D;IAC9D,qBAAqB,IAAI,SAAS,GAAG,IAAI;IAOzC;;;;OAIG;IACH,OAAO,CAAC,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,SAAS,EAAE,MAAM,GAAG,SAAS;IAmB3F;;;OAGG;IACH,sBAAsB,CACpB,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAClC,SAAS,EAAE,MAAM,EACjB,YAAY,EAAE,sBAAsB;IACpC,uFAAuF;IACvF,SAAS,UAAQ,GAChB,SAAS;IAqBZ,uEAAuE;IACvE,uBAAuB,CAAC,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,sBAAsB,GAAG,SAAS,GAAG,IAAI;IAMhG,6EAA6E;IAC7E,iBAAiB,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI;IAatD,8CAA8C;IAC9C,mBAAmB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IAO1D,qEAAqE;IACrE,WAAW,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO;IAIvC,gFAAgF;IAChF,QAAQ,IAAI,IAAI,EAAE;IAIlB,UAAU,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,GAAG,SAAS,GAAG,IAAI;IAYlF,aAAa,CAAC,WAAW,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS;IAiBlF,gBAAgB,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,SAAS,EAAE,YAAY,CAAC,EAAE,MAAM,EAAE,YAAY,CAAC,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI;IAUhI,WAAW,CACT,OAAO,EAAE,MAAM,EACf,SAAS,EAAE,MAAM,GAAG,SAAS,EAC7B,MAAM,EAAE,WAAW,GAAG,QAAQ,GAAG,SAAS,EAC1C,OAAO,CAAC,EAAE,MAAM,GACf,SAAS,GAAG,IAAI;IAOnB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,WAAW,GAAG,MAAM,GAAG,OAAO,GAAG,MAAM,GAAG,SAAS,GAAG,SAAS;IAKrG,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS;CAGtC;AAMD,wBAAsB,qBAAqB,CACzC,SAAS,EAAE,MAAM,EACjB,GAAG,EAAE,MAAM,EACX,MAAM,SAAI,EACV,KAAK,SAAK,GACT,OAAO,CAAC,mBAAmB,CAAC,CAmR9B"}