@deepseekharness-mobile/companion 0.0.0-stage → 0.1.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 (131) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +25 -2
  3. package/cordis.patch.yml +20 -0
  4. package/dist/core/devices.d.ts +35 -0
  5. package/dist/core/devices.d.ts.map +1 -0
  6. package/dist/core/devices.js +90 -0
  7. package/dist/core/devices.js.map +1 -0
  8. package/dist/core/pairing.d.ts +21 -0
  9. package/dist/core/pairing.d.ts.map +1 -0
  10. package/dist/core/pairing.js +74 -0
  11. package/dist/core/pairing.js.map +1 -0
  12. package/dist/dsh/errors.d.ts +3 -0
  13. package/dist/dsh/errors.d.ts.map +1 -0
  14. package/dist/dsh/errors.js +15 -0
  15. package/dist/dsh/errors.js.map +1 -0
  16. package/dist/dsh/lifecycle.d.ts +37 -0
  17. package/dist/dsh/lifecycle.d.ts.map +1 -0
  18. package/dist/dsh/lifecycle.js +95 -0
  19. package/dist/dsh/lifecycle.js.map +1 -0
  20. package/dist/dsh/models.d.ts +39 -0
  21. package/dist/dsh/models.d.ts.map +1 -0
  22. package/dist/dsh/models.js +171 -0
  23. package/dist/dsh/models.js.map +1 -0
  24. package/dist/dsh/prompt.d.ts +8 -0
  25. package/dist/dsh/prompt.d.ts.map +1 -0
  26. package/dist/dsh/prompt.js +25 -0
  27. package/dist/dsh/prompt.js.map +1 -0
  28. package/dist/dsh/providers.d.ts +25 -0
  29. package/dist/dsh/providers.d.ts.map +1 -0
  30. package/dist/dsh/providers.js +315 -0
  31. package/dist/dsh/providers.js.map +1 -0
  32. package/dist/dsh/question-bridge.d.ts +25 -0
  33. package/dist/dsh/question-bridge.d.ts.map +1 -0
  34. package/dist/dsh/question-bridge.js +140 -0
  35. package/dist/dsh/question-bridge.js.map +1 -0
  36. package/dist/dsh/questions.d.ts +15 -0
  37. package/dist/dsh/questions.d.ts.map +1 -0
  38. package/dist/dsh/questions.js +126 -0
  39. package/dist/dsh/questions.js.map +1 -0
  40. package/dist/dsh/session-activity.d.ts +5 -0
  41. package/dist/dsh/session-activity.d.ts.map +1 -0
  42. package/dist/dsh/session-activity.js +100 -0
  43. package/dist/dsh/session-activity.js.map +1 -0
  44. package/dist/dsh/session-source.d.ts +19 -0
  45. package/dist/dsh/session-source.d.ts.map +1 -0
  46. package/dist/dsh/session-source.js +104 -0
  47. package/dist/dsh/session-source.js.map +1 -0
  48. package/dist/dsh/sessions.d.ts +10 -0
  49. package/dist/dsh/sessions.d.ts.map +1 -0
  50. package/dist/dsh/sessions.js +51 -0
  51. package/dist/dsh/sessions.js.map +1 -0
  52. package/dist/dsh/slash-commands.d.ts +15 -0
  53. package/dist/dsh/slash-commands.d.ts.map +1 -0
  54. package/dist/dsh/slash-commands.js +60 -0
  55. package/dist/dsh/slash-commands.js.map +1 -0
  56. package/dist/dsh/transcript.d.ts +28 -0
  57. package/dist/dsh/transcript.d.ts.map +1 -0
  58. package/dist/dsh/transcript.js +211 -0
  59. package/dist/dsh/transcript.js.map +1 -0
  60. package/dist/dsh/workspaces.d.ts +20 -0
  61. package/dist/dsh/workspaces.d.ts.map +1 -0
  62. package/dist/dsh/workspaces.js +123 -0
  63. package/dist/dsh/workspaces.js.map +1 -0
  64. package/dist/host-api.d.ts +148 -0
  65. package/dist/host-api.d.ts.map +1 -0
  66. package/dist/host-api.js +54 -0
  67. package/dist/host-api.js.map +1 -0
  68. package/dist/index.d.ts +5 -0
  69. package/dist/index.d.ts.map +1 -0
  70. package/dist/index.js +268 -0
  71. package/dist/index.js.map +1 -0
  72. package/dist/log.d.ts +5 -0
  73. package/dist/log.d.ts.map +1 -0
  74. package/dist/log.js +40 -0
  75. package/dist/log.js.map +1 -0
  76. package/dist/open-browser.d.ts +3 -0
  77. package/dist/open-browser.d.ts.map +1 -0
  78. package/dist/open-browser.js +46 -0
  79. package/dist/open-browser.js.map +1 -0
  80. package/dist/pairing-message.d.ts +16 -0
  81. package/dist/pairing-message.d.ts.map +1 -0
  82. package/dist/pairing-message.js +38 -0
  83. package/dist/pairing-message.js.map +1 -0
  84. package/dist/persist/devices-file.d.ts +8 -0
  85. package/dist/persist/devices-file.d.ts.map +1 -0
  86. package/dist/persist/devices-file.js +47 -0
  87. package/dist/persist/devices-file.js.map +1 -0
  88. package/dist/probe.d.ts +25 -0
  89. package/dist/probe.d.ts.map +1 -0
  90. package/dist/probe.js +143 -0
  91. package/dist/probe.js.map +1 -0
  92. package/dist/public-origin.d.ts +11 -0
  93. package/dist/public-origin.d.ts.map +1 -0
  94. package/dist/public-origin.js +79 -0
  95. package/dist/public-origin.js.map +1 -0
  96. package/dist/qr-text.d.ts +2 -0
  97. package/dist/qr-text.d.ts.map +1 -0
  98. package/dist/qr-text.js +31 -0
  99. package/dist/qr-text.js.map +1 -0
  100. package/dist/routes/origin.d.ts +17 -0
  101. package/dist/routes/origin.d.ts.map +1 -0
  102. package/dist/routes/origin.js +85 -0
  103. package/dist/routes/origin.js.map +1 -0
  104. package/dist/routes/static.d.ts +9 -0
  105. package/dist/routes/static.d.ts.map +1 -0
  106. package/dist/routes/static.js +129 -0
  107. package/dist/routes/static.js.map +1 -0
  108. package/dist/routes/web-root.d.ts +2 -0
  109. package/dist/routes/web-root.d.ts.map +1 -0
  110. package/dist/routes/web-root.js +21 -0
  111. package/dist/routes/web-root.js.map +1 -0
  112. package/dist/server.d.ts +140 -0
  113. package/dist/server.d.ts.map +1 -0
  114. package/dist/server.js +829 -0
  115. package/dist/server.js.map +1 -0
  116. package/dist/web/apple-touch-icon-precomposed.png +0 -0
  117. package/dist/web/apple-touch-icon.png +0 -0
  118. package/dist/web/assets/index-NOGXMIsS.js +65 -0
  119. package/dist/web/assets/index-NOGXMIsS.js.map +1 -0
  120. package/dist/web/assets/index-s7zoNGmx.css +1 -0
  121. package/dist/web/fonts/Montserrat-OFL.txt +93 -0
  122. package/dist/web/fonts/montserrat-medium.woff2 +0 -0
  123. package/dist/web/fonts/montserrat-regular.woff2 +0 -0
  124. package/dist/web/icon-192.png +0 -0
  125. package/dist/web/icon-512.png +0 -0
  126. package/dist/web/icon-maskable-512.png +0 -0
  127. package/dist/web/icon-maskable.svg +15 -0
  128. package/dist/web/icon.svg +6 -0
  129. package/dist/web/index.html +25 -0
  130. package/dist/web/manifest.webmanifest +37 -0
  131. package/package.json +60 -3
@@ -0,0 +1,140 @@
1
+ import { PROTOCOL_VERSION, newMessageId, } from '@deepseekharness-mobile/protocol';
2
+ import { toQuestionItem } from './questions.js';
3
+ function recordOf(value) {
4
+ return typeof value === 'object' && value !== null
5
+ ? value
6
+ : undefined;
7
+ }
8
+ function sessionIdOf(request) {
9
+ const agent = recordOf(request['agent']);
10
+ const session = recordOf(agent?.['session']);
11
+ const id = session?.['id'];
12
+ return typeof id === 'string' && id.length > 0 ? id : undefined;
13
+ }
14
+ function itemsOf(request) {
15
+ const questions = request['questions'];
16
+ if (!Array.isArray(questions))
17
+ return [];
18
+ return questions.map(toQuestionItem).filter((item) => item !== undefined);
19
+ }
20
+ function pendingFrame(batch) {
21
+ return {
22
+ v: PROTOCOL_VERSION,
23
+ id: newMessageId(),
24
+ at: Date.now(),
25
+ type: 'question.pending',
26
+ question: batch,
27
+ };
28
+ }
29
+ function settledFrame(callId, sessionId) {
30
+ return {
31
+ v: PROTOCOL_VERSION,
32
+ id: newMessageId(),
33
+ at: Date.now(),
34
+ type: 'question.settled',
35
+ callId,
36
+ sessionId,
37
+ };
38
+ }
39
+ function completeAnswer(items, answers) {
40
+ const expected = new Set(items.map((item) => item.id));
41
+ const ids = answers.map((answer) => answer.id);
42
+ return (ids.length === expected.size &&
43
+ new Set(ids).size === ids.length &&
44
+ ids.every((id) => expected.has(id)));
45
+ }
46
+ export function createQuestionBridge(ctx, deps) {
47
+ const pending = new Map();
48
+ let off;
49
+ const handle = async (request, next) => {
50
+ const raw = recordOf(request);
51
+ if (!raw || deps.clients() === 0 || recordOf(raw['wait']))
52
+ return next();
53
+ const sessionId = sessionIdOf(raw);
54
+ const items = itemsOf(raw);
55
+ if (!sessionId || items.length === 0)
56
+ return next();
57
+ const session = sessionId;
58
+ const callId = `mobile-${newMessageId()}`;
59
+ const batch = {
60
+ callId,
61
+ sessionId: session,
62
+ state: 'open',
63
+ items,
64
+ createdAt: Date.now(),
65
+ };
66
+ const signal = raw['signal'];
67
+ return new Promise((resolve, reject) => {
68
+ let finished = false;
69
+ function onAbort() {
70
+ finish(undefined, new Error('The question was cancelled before the phone answered.'));
71
+ }
72
+ function finish(answer, error) {
73
+ if (finished)
74
+ return;
75
+ finished = true;
76
+ pending.delete(callId);
77
+ signal?.removeEventListener('abort', onAbort);
78
+ deps.push(settledFrame(callId, session));
79
+ if (answer)
80
+ resolve(answer);
81
+ else
82
+ reject(error ?? new Error('The question was cancelled before an answer arrived.'));
83
+ }
84
+ pending.set(callId, {
85
+ batch,
86
+ items,
87
+ resolve: (answer) => finish(answer),
88
+ abort: (error) => finish(undefined, error),
89
+ });
90
+ deps.push(pendingFrame(batch));
91
+ if (signal?.aborted) {
92
+ onAbort();
93
+ return;
94
+ }
95
+ signal?.addEventListener('abort', onAbort);
96
+ void next().then((answer) => finish(answer), () => undefined);
97
+ });
98
+ };
99
+ const answer = (input) => {
100
+ const entry = pending.get(input.callId);
101
+ if (!entry)
102
+ return undefined;
103
+ if (!completeAnswer(entry.items, input.answers)) {
104
+ return {
105
+ ok: false,
106
+ code: 'bad-request',
107
+ message: 'The answer batch must name each question exactly once.',
108
+ };
109
+ }
110
+ pending.delete(input.callId);
111
+ entry.resolve({ answers: input.answers });
112
+ return { ok: true };
113
+ };
114
+ const on = ctx.on;
115
+ if (on) {
116
+ off = on.call(ctx, 'user-questions/request', handle, { prepend: true, global: true });
117
+ }
118
+ return {
119
+ answer,
120
+ pendingBatches() {
121
+ return [...pending.values()].map((entry) => entry.batch);
122
+ },
123
+ counts() {
124
+ const counts = new Map();
125
+ for (const entry of pending.values()) {
126
+ counts.set(entry.batch.sessionId, (counts.get(entry.batch.sessionId) ?? 0) + 1);
127
+ }
128
+ return counts;
129
+ },
130
+ dispose() {
131
+ off?.();
132
+ off = undefined;
133
+ for (const entry of [...pending.values()]) {
134
+ entry.abort(new Error('The question bridge was disposed.'));
135
+ }
136
+ pending.clear();
137
+ },
138
+ };
139
+ }
140
+ //# sourceMappingURL=question-bridge.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"question-bridge.js","sourceRoot":"","sources":["../../src/dsh/question-bridge.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ import type { QuestionAnswerItem, QuestionBatch, QuestionItem } from '@deepseekharness-mobile/protocol';
2
+ import { type HostContext } from '../host-api.js';
3
+ export declare function toQuestionItem(raw: unknown): QuestionItem | undefined;
4
+ export declare function listPendingQuestions(ctx: HostContext): QuestionBatch[];
5
+ export interface AnswerOutcome {
6
+ ok: boolean;
7
+ code?: 'not-found' | 'bad-request' | 'internal';
8
+ message?: string;
9
+ }
10
+ export declare function answerQuestion(ctx: HostContext, input: {
11
+ callId: string;
12
+ sessionId: string;
13
+ answers: QuestionAnswerItem[];
14
+ }): AnswerOutcome;
15
+ //# sourceMappingURL=questions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"questions.d.ts","sourceRoot":"","sources":["../../src/dsh/questions.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,kBAAkB,EAClB,aAAa,EACb,YAAY,EAEb,MAAM,kCAAkC,CAAC;AAC1C,OAAO,EAEL,KAAK,WAAW,EAGjB,MAAM,gBAAgB,CAAC;AA8BxB,wBAAgB,cAAc,CAAC,GAAG,EAAE,OAAO,GAAG,YAAY,GAAG,SAAS,CAgCrE;AAkDD,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,WAAW,GAAG,aAAa,EAAE,CAatE;AAED,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,OAAO,CAAC;IACZ,IAAI,CAAC,EAAE,WAAW,GAAG,aAAa,GAAG,UAAU,CAAC;IAChD,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,wBAAgB,cAAc,CAC5B,GAAG,EAAE,WAAW,EAChB,KAAK,EAAE;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,kBAAkB,EAAE,CAAA;CAAE,GAC1E,aAAa,CAiCf"}
@@ -0,0 +1,126 @@
1
+ import { service, } from '../host-api.js';
2
+ function asString(value, fallback = '') {
3
+ return typeof value === 'string' ? value : fallback;
4
+ }
5
+ export function toQuestionItem(raw) {
6
+ if (typeof raw !== 'object' || raw === null)
7
+ return undefined;
8
+ const item = raw;
9
+ const id = asString(item.id);
10
+ const text = asString(item.question);
11
+ if (!id)
12
+ return undefined;
13
+ const options = Array.isArray(item.options)
14
+ ? item.options
15
+ .map((option) => {
16
+ if (typeof option !== 'object' || option === null)
17
+ return undefined;
18
+ const record = option;
19
+ const label = asString(record.label);
20
+ if (!label)
21
+ return undefined;
22
+ const description = asString(record.description);
23
+ return { label, ...(description ? { description } : {}) };
24
+ })
25
+ .filter((option) => option !== undefined)
26
+ : [];
27
+ const intent = asString(item.intent);
28
+ return {
29
+ id,
30
+ text,
31
+ ...(asString(item.detail) ? { detail: asString(item.detail) } : {}),
32
+ ...(asString(item.header) ? { header: asString(item.header) } : {}),
33
+ options,
34
+ multiSelect: item.multiSelect === true,
35
+ allowCustom: intent !== 'approval',
36
+ };
37
+ }
38
+ function toBatch(raw, sessionId) {
39
+ if (typeof raw !== 'object' || raw === null)
40
+ return undefined;
41
+ const pending = raw;
42
+ const callId = asString(pending.callId);
43
+ if (!callId)
44
+ return undefined;
45
+ const items = Array.isArray(pending.questions)
46
+ ? pending.questions
47
+ .map(toQuestionItem)
48
+ .filter((item) => item !== undefined)
49
+ : [];
50
+ if (items.length === 0)
51
+ return undefined;
52
+ const state = pending.state === 'continued' ? 'continued' : 'open';
53
+ return {
54
+ callId,
55
+ sessionId,
56
+ state,
57
+ items,
58
+ createdAt: 0,
59
+ };
60
+ }
61
+ function pendingOf(ctx, sessionId, projections) {
62
+ const sessions = service(ctx, 'sessions');
63
+ const session = sessions?.get(sessionId);
64
+ if (!session)
65
+ return [];
66
+ try {
67
+ const view = projections.snapshot(session).values['userQuestions'];
68
+ const active = view?.active;
69
+ if (!Array.isArray(active))
70
+ return [];
71
+ return active
72
+ .map((raw) => toBatch(raw, sessionId))
73
+ .filter((batch) => batch !== undefined);
74
+ }
75
+ catch {
76
+ return [];
77
+ }
78
+ }
79
+ export function listPendingQuestions(ctx) {
80
+ const projections = service(ctx, 'sessionProjections');
81
+ const sessions = service(ctx, 'sessions');
82
+ if (!projections || !sessions)
83
+ return [];
84
+ let ids;
85
+ try {
86
+ ids = sessions.list().map((session) => session.id);
87
+ }
88
+ catch {
89
+ return [];
90
+ }
91
+ return ids.flatMap((id) => pendingOf(ctx, id, projections));
92
+ }
93
+ export function answerQuestion(ctx, input) {
94
+ const userQuestions = service(ctx, 'userQuestions');
95
+ if (!userQuestions) {
96
+ return {
97
+ ok: false,
98
+ code: 'internal',
99
+ message: 'The host does not expose the questions service.',
100
+ };
101
+ }
102
+ const agents = service(ctx, 'agents');
103
+ const agent = agents?.get(input.sessionId);
104
+ if (!agent) {
105
+ return {
106
+ ok: false,
107
+ code: 'not-found',
108
+ message: 'The session is not loaded on the host. Open it on the desktop and try again.',
109
+ };
110
+ }
111
+ try {
112
+ const accepted = userQuestions.answer(agent, input.callId, { answers: input.answers });
113
+ if (!accepted) {
114
+ return {
115
+ ok: false,
116
+ code: 'bad-request',
117
+ message: 'That question no longer accepts an answer: the desktop may have answered it.',
118
+ };
119
+ }
120
+ return { ok: true };
121
+ }
122
+ catch (error) {
123
+ return { ok: false, code: 'bad-request', message: String(error) };
124
+ }
125
+ }
126
+ //# sourceMappingURL=questions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"questions.js","sourceRoot":"","sources":["../../src/dsh/questions.ts"],"names":[],"mappings":"AAMA,OAAO,EACL,OAAO,GAIR,MAAM,gBAAgB,CAAC;AA0BxB,SAAS,QAAQ,CAAC,KAAc,EAAE,QAAQ,GAAG,EAAE;IAC7C,OAAO,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,QAAQ,CAAC;AACtD,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,GAAY;IACzC,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,GAAG,KAAK,IAAI;QAAE,OAAO,SAAS,CAAC;IAC9D,MAAM,IAAI,GAAG,GAAsB,CAAC;IAEpC,MAAM,EAAE,GAAG,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAC7B,MAAM,IAAI,GAAG,QAAQ,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IACrC,IAAI,CAAC,EAAE;QAAE,OAAO,SAAS,CAAC;IAE1B,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC;QACzC,CAAC,CAAC,IAAI,CAAC,OAAO;aACT,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE;YACd,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,MAAM,KAAK,IAAI;gBAAE,OAAO,SAAS,CAAC;YACpE,MAAM,MAAM,GAAG,MAAoD,CAAC;YACpE,MAAM,KAAK,GAAG,QAAQ,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YACrC,IAAI,CAAC,KAAK;gBAAE,OAAO,SAAS,CAAC;YAC7B,MAAM,WAAW,GAAG,QAAQ,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;YACjD,OAAO,EAAE,KAAK,EAAE,GAAG,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC;QAC5D,CAAC,CAAC;aACD,MAAM,CAAC,CAAC,MAAM,EAAqD,EAAE,CAAC,MAAM,KAAK,SAAS,CAAC;QAChG,CAAC,CAAC,EAAE,CAAC;IAEP,MAAM,MAAM,GAAG,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAErC,OAAO;QACL,EAAE;QACF,IAAI;QACJ,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACnE,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACnE,OAAO;QACP,WAAW,EAAE,IAAI,CAAC,WAAW,KAAK,IAAI;QACtC,WAAW,EAAE,MAAM,KAAK,UAAU;KACnC,CAAC;AACJ,CAAC;AAED,SAAS,OAAO,CAAC,GAAY,EAAE,SAAiB;IAC9C,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,GAAG,KAAK,IAAI;QAAE,OAAO,SAAS,CAAC;IAC9D,MAAM,OAAO,GAAG,GAAiB,CAAC;IAElC,MAAM,MAAM,GAAG,QAAQ,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;IACxC,IAAI,CAAC,MAAM;QAAE,OAAO,SAAS,CAAC;IAE9B,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,SAAS,CAAC;QAC5C,CAAC,CAAC,OAAO,CAAC,SAAS;aACd,GAAG,CAAC,cAAc,CAAC;aACnB,MAAM,CAAC,CAAC,IAAI,EAAwB,EAAE,CAAC,IAAI,KAAK,SAAS,CAAC;QAC/D,CAAC,CAAC,EAAE,CAAC;IACP,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,SAAS,CAAC;IAEzC,MAAM,KAAK,GAAkB,OAAO,CAAC,KAAK,KAAK,WAAW,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,MAAM,CAAC;IAElF,OAAO;QACL,MAAM;QACN,SAAS;QACT,KAAK;QACL,KAAK;QACL,SAAS,EAAE,CAAC;KACb,CAAC;AACJ,CAAC;AAED,SAAS,SAAS,CAChB,GAAgB,EAChB,SAAiB,EACjB,WAA+B;IAE/B,MAAM,QAAQ,GAAG,OAAO,CAAkB,GAAG,EAAE,UAAU,CAAC,CAAC;IAC3D,MAAM,OAAO,GAAG,QAAQ,EAAE,GAAG,CAAC,SAAS,CAAC,CAAC;IACzC,IAAI,CAAC,OAAO;QAAE,OAAO,EAAE,CAAC;IAExB,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,WAAW,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,eAAe,CAC/B,CAAC;QACnC,MAAM,MAAM,GAAG,IAAI,EAAE,MAAM,CAAC;QAC5B,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC;YAAE,OAAO,EAAE,CAAC;QAEtC,OAAO,MAAM;aACV,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC;aACrC,MAAM,CAAC,CAAC,KAAK,EAA0B,EAAE,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC;IACpE,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC;AAED,MAAM,UAAU,oBAAoB,CAAC,GAAgB;IACnD,MAAM,WAAW,GAAG,OAAO,CAAqB,GAAG,EAAE,oBAAoB,CAAC,CAAC;IAC3E,MAAM,QAAQ,GAAG,OAAO,CAAkB,GAAG,EAAE,UAAU,CAAC,CAAC;IAC3D,IAAI,CAAC,WAAW,IAAI,CAAC,QAAQ;QAAE,OAAO,EAAE,CAAC;IAEzC,IAAI,GAAa,CAAC;IAClB,IAAI,CAAC;QACH,GAAG,GAAG,QAAQ,CAAC,IAAI,EAAE,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IACrD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,OAAO,GAAG,CAAC,OAAO,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,EAAE,WAAW,CAAC,CAAC,CAAC;AAC9D,CAAC;AAQD,MAAM,UAAU,cAAc,CAC5B,GAAgB,EAChB,KAA2E;IAE3E,MAAM,aAAa,GAAG,OAAO,CAAuB,GAAG,EAAE,eAAe,CAAC,CAAC;IAC1E,IAAI,CAAC,aAAa,EAAE,CAAC;QACnB,OAAO;YACL,EAAE,EAAE,KAAK;YACT,IAAI,EAAE,UAAU;YAChB,OAAO,EAAE,iDAAiD;SAC3D,CAAC;IACJ,CAAC;IAED,MAAM,MAAM,GAAG,OAAO,CAAgB,GAAG,EAAE,QAAQ,CAAC,CAAC;IACrD,MAAM,KAAK,GAAG,MAAM,EAAE,GAAG,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;IAC3C,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,OAAO;YACL,EAAE,EAAE,KAAK;YACT,IAAI,EAAE,WAAW;YACjB,OAAO,EAAE,8EAA8E;SACxF,CAAC;IACJ,CAAC;IAED,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,aAAa,CAAC,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC,MAAM,EAAE,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;QACvF,IAAI,CAAC,QAAQ,EAAE,CAAC;YACd,OAAO;gBACL,EAAE,EAAE,KAAK;gBACT,IAAI,EAAE,aAAa;gBACnB,OAAO,EAAE,8EAA8E;aACxF,CAAC;QACJ,CAAC;QACD,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC;IACtB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,aAAa,EAAE,OAAO,EAAE,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC;IACpE,CAAC;AACH,CAAC"}
@@ -0,0 +1,5 @@
1
+ import type { SessionActivity } from '@deepseekharness-mobile/protocol';
2
+ import { type HostContext } from '../host-api.js';
3
+ export declare function activityAvailable(ctx: HostContext): boolean;
4
+ export declare function readSessionActivity(ctx: HostContext, sessionId: string): Promise<SessionActivity>;
5
+ //# sourceMappingURL=session-activity.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session-activity.d.ts","sourceRoot":"","sources":["../../src/dsh/session-activity.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAIV,eAAe,EAChB,MAAM,kCAAkC,CAAC;AAC1C,OAAO,EAEL,KAAK,WAAW,EAKjB,MAAM,gBAAgB,CAAC;AAKxB,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,WAAW,GAAG,OAAO,CAK3D;AAuFD,wBAAsB,mBAAmB,CACvC,GAAG,EAAE,WAAW,EAChB,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,eAAe,CAAC,CAiB1B"}
@@ -0,0 +1,100 @@
1
+ import { service, } from '../host-api.js';
2
+ const MAX_SUBAGENTS = 20;
3
+ const MAX_TODOS = 8;
4
+ export function activityAvailable(ctx) {
5
+ return (Boolean(service(ctx, 'sessionProjections')) &&
6
+ Boolean(service(ctx, 'sessions')));
7
+ }
8
+ function isRecord(value) {
9
+ return typeof value === 'object' && value !== null;
10
+ }
11
+ function goalOf(value) {
12
+ if (!isRecord(value))
13
+ return undefined;
14
+ const goal = isRecord(value['goal']) ? value['goal'] : value;
15
+ const objective = typeof goal['objective'] === 'string' ? goal['objective'] : undefined;
16
+ const phase = typeof goal['phase'] === 'string' ? goal['phase'] : undefined;
17
+ if (!objective || !phase)
18
+ return undefined;
19
+ const roundsStarted = typeof value['roundsStarted'] === 'number' && value['roundsStarted'] >= 0
20
+ ? value['roundsStarted']
21
+ : 0;
22
+ const maxRounds = typeof goal['maxGoalRounds'] === 'number' && goal['maxGoalRounds'] > 0
23
+ ? goal['maxGoalRounds']
24
+ : undefined;
25
+ return { objective, phase, roundsStarted, ...(maxRounds ? { maxRounds } : {}) };
26
+ }
27
+ function todosOf(value) {
28
+ if (!Array.isArray(value) || value.length === 0)
29
+ return undefined;
30
+ const items = [];
31
+ for (const raw of value) {
32
+ if (!isRecord(raw) || typeof raw['content'] !== 'string')
33
+ continue;
34
+ const status = raw['status'];
35
+ if (status !== 'pending' && status !== 'in_progress' && status !== 'completed')
36
+ continue;
37
+ items.push({ content: raw['content'], status });
38
+ }
39
+ if (items.length === 0)
40
+ return undefined;
41
+ return {
42
+ open: items.filter((item) => item.status !== 'completed').length,
43
+ total: items.length,
44
+ items: items.slice(0, MAX_TODOS),
45
+ };
46
+ }
47
+ function planActiveOf(value) {
48
+ return isRecord(value) && value['active'] === true;
49
+ }
50
+ async function subagentsOf(ctx, sessionId) {
51
+ const subagents = service(ctx, 'subagents');
52
+ if (!subagents || typeof subagents.listDescendants !== 'function')
53
+ return [];
54
+ try {
55
+ const entries = await subagents.listDescendants(sessionId, new AbortController().signal);
56
+ const rows = entries
57
+ .filter((entry) => entry.kind === 'child')
58
+ .map((entry) => ({
59
+ id: entry.id,
60
+ ...(typeof entry.label === 'string' && entry.label ? { label: entry.label } : {}),
61
+ activity: entry.activity === 'running' ? 'running' : 'inactive',
62
+ depth: typeof entry.depth === 'number' && entry.depth > 0 ? entry.depth : 1,
63
+ ...(entry.hasChildren !== undefined ? { hasChildren: entry.hasChildren } : {}),
64
+ }));
65
+ rows.sort((left, right) => {
66
+ if (left.activity !== right.activity)
67
+ return left.activity === 'running' ? -1 : 1;
68
+ return left.depth - right.depth;
69
+ });
70
+ return rows.slice(0, MAX_SUBAGENTS);
71
+ }
72
+ catch {
73
+ return [];
74
+ }
75
+ }
76
+ function snapshotOf(projections, session) {
77
+ try {
78
+ return projections.snapshot(session).values;
79
+ }
80
+ catch {
81
+ return undefined;
82
+ }
83
+ }
84
+ export async function readSessionActivity(ctx, sessionId) {
85
+ const projections = service(ctx, 'sessionProjections');
86
+ const sessions = service(ctx, 'sessions');
87
+ const session = sessions?.get(sessionId);
88
+ const values = session && projections ? snapshotOf(projections, session) : undefined;
89
+ const goal = goalOf(values?.['goal']);
90
+ const todos = todosOf(values?.['todos']);
91
+ const planActive = planActiveOf(values?.['plan']);
92
+ const subagents = await subagentsOf(ctx, sessionId);
93
+ return {
94
+ ...(goal ? { goal } : {}),
95
+ subagents,
96
+ ...(todos ? { todos } : {}),
97
+ ...(planActive ? { planActive } : {}),
98
+ };
99
+ }
100
+ //# sourceMappingURL=session-activity.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session-activity.js","sourceRoot":"","sources":["../../src/dsh/session-activity.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ import type { ModelSelection, SessionSummary as WireSession } from '@deepseekharness-mobile/protocol';
2
+ import { type HostContext } from '../host-api.js';
3
+ export interface SessionRecord {
4
+ id: string;
5
+ title: string;
6
+ updatedAt: number;
7
+ seq: number;
8
+ agentAvailable: boolean;
9
+ running: boolean;
10
+ pendingQuestions: number;
11
+ workspaceId?: string;
12
+ model?: ModelSelection;
13
+ archived?: boolean;
14
+ }
15
+ export declare function listSessions(ctx: HostContext, options?: {
16
+ includeArchived?: boolean;
17
+ }): Promise<SessionRecord[]>;
18
+ export declare function toWireSession(record: SessionRecord): WireSession;
19
+ //# sourceMappingURL=session-source.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session-source.d.ts","sourceRoot":"","sources":["../../src/dsh/session-source.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,cAAc,EAEd,cAAc,IAAI,WAAW,EAC9B,MAAM,kCAAkC,CAAC;AAC1C,OAAO,EAEL,KAAK,WAAW,EAGjB,MAAM,gBAAgB,CAAC;AAIxB,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,GAAG,EAAE,MAAM,CAAC;IACZ,cAAc,EAAE,OAAO,CAAC;IACxB,OAAO,EAAE,OAAO,CAAC;IACjB,gBAAgB,EAAE,MAAM,CAAC;IACzB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE,cAAc,CAAC;IACvB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AA4DD,wBAAsB,YAAY,CAChC,GAAG,EAAE,WAAW,EAChB,OAAO,GAAE;IAAE,eAAe,CAAC,EAAE,OAAO,CAAA;CAAO,GAC1C,OAAO,CAAC,aAAa,EAAE,CAAC,CAuD1B;AAED,wBAAgB,aAAa,CAAC,MAAM,EAAE,aAAa,GAAG,WAAW,CAYhE"}
@@ -0,0 +1,104 @@
1
+ import { service, } from '../host-api.js';
2
+ import { listArchivedSessions, listWorkspaces } from './workspaces.js';
3
+ import { selectionOf } from './models.js';
4
+ const MAX_SESSIONS = 200;
5
+ function countPending(snapshot) {
6
+ if (typeof snapshot !== 'object' || snapshot === null)
7
+ return 0;
8
+ const active = snapshot.active;
9
+ return Array.isArray(active) ? active.length : 0;
10
+ }
11
+ function pendingFor(ctx, sessionId, projections) {
12
+ if (!projections)
13
+ return 0;
14
+ const sessions = service(ctx, 'sessions');
15
+ const session = sessions?.get(sessionId);
16
+ if (!session)
17
+ return 0;
18
+ try {
19
+ return countPending(projections.snapshot(session).values['userQuestions']);
20
+ }
21
+ catch {
22
+ return 0;
23
+ }
24
+ }
25
+ function modelFor(item) {
26
+ const snapshot = item.projections?.values?.['modelSelection'];
27
+ if (typeof snapshot !== 'object' || snapshot === null)
28
+ return undefined;
29
+ const record = snapshot;
30
+ return selectionOf(record['next']) ?? selectionOf(record['lastUsed']) ?? selectionOf(record);
31
+ }
32
+ function wireState(record) {
33
+ if (record.pendingQuestions > 0)
34
+ return 'waiting';
35
+ if (record.running)
36
+ return 'working';
37
+ return 'idle';
38
+ }
39
+ export async function listSessions(ctx, options = {}) {
40
+ const controller = service(ctx, 'sessionController');
41
+ if (!controller || typeof controller.list !== 'function')
42
+ return [];
43
+ const projections = service(ctx, 'sessionProjections');
44
+ let items;
45
+ try {
46
+ const result = await controller.list({}, new AbortController().signal);
47
+ items = result?.items ?? [];
48
+ }
49
+ catch {
50
+ return [];
51
+ }
52
+ const records = items
53
+ .slice(0, MAX_SESSIONS)
54
+ .map((item) => {
55
+ const id = typeof item.sessionId === 'string' ? item.sessionId : '';
56
+ const titleValue = item.projections?.values?.['title'];
57
+ const pendingQuestions = id ? pendingFor(ctx, id, projections) : 0;
58
+ const model = id ? modelFor(item) : undefined;
59
+ return {
60
+ id,
61
+ title: typeof titleValue === 'string' && titleValue.trim() ? titleValue.trim() : 'Untitled',
62
+ updatedAt: typeof item.updatedAt === 'number' ? item.updatedAt : 0,
63
+ seq: typeof item.projections?.asOfSeq === 'number' ? item.projections.asOfSeq : 0,
64
+ agentAvailable: item.agentAvailable === true,
65
+ running: item.running === true,
66
+ pendingQuestions,
67
+ ...(model ? { model } : {}),
68
+ };
69
+ })
70
+ .filter((record) => record.id !== '');
71
+ try {
72
+ const workspaces = await listWorkspaces(ctx);
73
+ const folderOf = new Map();
74
+ for (const workspace of workspaces) {
75
+ for (const sessionId of workspace.sessionIds)
76
+ folderOf.set(sessionId, workspace.id);
77
+ }
78
+ for (const record of records) {
79
+ const folder = folderOf.get(record.id);
80
+ if (folder)
81
+ record.workspaceId = folder;
82
+ }
83
+ }
84
+ catch { }
85
+ const archived = await listArchivedSessions(ctx).catch(() => new Set());
86
+ const visible = options.includeArchived === true
87
+ ? records.map((record) => (archived.has(record.id) ? { ...record, archived: true } : record))
88
+ : records.filter((record) => !archived.has(record.id));
89
+ return visible.sort((a, b) => b.updatedAt - a.updatedAt);
90
+ }
91
+ export function toWireSession(record) {
92
+ return {
93
+ id: record.id,
94
+ title: record.title,
95
+ state: wireState(record),
96
+ updatedAt: record.updatedAt,
97
+ seq: record.seq,
98
+ pendingQuestions: record.pendingQuestions,
99
+ ...(record.workspaceId ? { workspaceId: record.workspaceId } : {}),
100
+ ...(record.model ? { model: record.model } : {}),
101
+ ...(record.archived ? { archived: true } : {}),
102
+ };
103
+ }
104
+ //# sourceMappingURL=session-source.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session-source.js","sourceRoot":"","sources":["../../src/dsh/session-source.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ import { type HostContext } from '../host-api.js';
2
+ export type SessionResolution = {
3
+ ok: true;
4
+ id: string;
5
+ } | {
6
+ ok: false;
7
+ error: string;
8
+ };
9
+ export declare function resolveSessionId(ctx: HostContext, raw: string): SessionResolution;
10
+ //# sourceMappingURL=sessions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sessions.d.ts","sourceRoot":"","sources":["../../src/dsh/sessions.ts"],"names":[],"mappings":"AAAA,OAAO,EAAW,KAAK,WAAW,EAAwB,MAAM,gBAAgB,CAAC;AAEjF,MAAM,MAAM,iBAAiB,GAAG;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,EAAE,EAAE,MAAM,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AASxF,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,WAAW,EAAE,GAAG,EAAE,MAAM,GAAG,iBAAiB,CA0CjF"}
@@ -0,0 +1,51 @@
1
+ import { service } from '../host-api.js';
2
+ function clean(raw) {
3
+ return raw
4
+ .replace(/[<>"'`]/g, '')
5
+ .replace(/\s+/g, '')
6
+ .trim();
7
+ }
8
+ export function resolveSessionId(ctx, raw) {
9
+ const wanted = clean(raw);
10
+ if (!wanted)
11
+ return { ok: false, error: 'Missing the session identifier.' };
12
+ const sessions = service(ctx, 'sessions');
13
+ if (!sessions)
14
+ return { ok: false, error: 'The sessions service is not available.' };
15
+ let ids;
16
+ try {
17
+ ids = sessions.list().map((session) => session.id);
18
+ }
19
+ catch (error) {
20
+ return { ok: false, error: `Could not list the sessions: ${String(error)}` };
21
+ }
22
+ if (/^\d+$/.test(wanted)) {
23
+ const index = Number(wanted) - 1;
24
+ const chosen = ids[index];
25
+ if (chosen)
26
+ return { ok: true, id: chosen };
27
+ return {
28
+ ok: false,
29
+ error: `No session number ${wanted}. There are ${ids.length}:\n${ids.map((id, i) => `${i + 1}) ${id}`).join('\n')}`,
30
+ };
31
+ }
32
+ if (ids.includes(wanted))
33
+ return { ok: true, id: wanted };
34
+ const prefixed = wanted.startsWith('session-') ? wanted : `session-${wanted}`;
35
+ if (ids.includes(prefixed))
36
+ return { ok: true, id: prefixed };
37
+ const matches = ids.filter((id) => id.includes(wanted));
38
+ if (matches.length === 1)
39
+ return { ok: true, id: matches[0] };
40
+ if (matches.length > 1) {
41
+ return {
42
+ ok: false,
43
+ error: `"${wanted}" is ambiguous and matches ${matches.length} sessions:\n${matches.join('\n')}`,
44
+ };
45
+ }
46
+ return {
47
+ ok: false,
48
+ error: `No session matches "${wanted}".\nLive sessions:\n${ids.join('\n') || '(none)'}`,
49
+ };
50
+ }
51
+ //# sourceMappingURL=sessions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sessions.js","sourceRoot":"","sources":["../../src/dsh/sessions.ts"],"names":[],"mappings":"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"}