@agentdeck/shared 1.0.5 → 1.0.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/voice-reply-digest.d.ts +50 -0
- package/dist/voice-reply-digest.d.ts.map +1 -0
- package/dist/voice-reply-digest.js +198 -0
- package/dist/voice-reply-digest.js.map +1 -0
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -4,6 +4,7 @@ export * from './gateway-protocol.js';
|
|
|
4
4
|
export * from './command-builders.js';
|
|
5
5
|
export * from './adapter.js';
|
|
6
6
|
export * from './voice-paths.js';
|
|
7
|
+
export * from './voice-reply-digest.js';
|
|
7
8
|
export * from './net-utils.js';
|
|
8
9
|
export * from './timeline.js';
|
|
9
10
|
export * from './subagent-activity.js';
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,cAAc,eAAe,CAAC;AAC9B,cAAc,uBAAuB,CAAC;AACtC,cAAc,uBAAuB,CAAC;AACtC,cAAc,cAAc,CAAC;AAC7B,cAAc,kBAAkB,CAAC;AACjC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,eAAe,CAAC;AAC9B,cAAc,wBAAwB,CAAC;AACvC,cAAc,qBAAqB,CAAC;AACpC,cAAc,qBAAqB,CAAC;AACpC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,wBAAwB,CAAC;AACvC,cAAc,mBAAmB,CAAC;AAClC,cAAc,0BAA0B,CAAC;AACzC,cAAc,oBAAoB,CAAC;AACnC,cAAc,sBAAsB,CAAC;AACrC,cAAc,sBAAsB,CAAC;AACrC,cAAc,mBAAmB,CAAC;AAClC,cAAc,wBAAwB,CAAC;AACvC,cAAc,oBAAoB,CAAC;AACnC,cAAc,0BAA0B,CAAC;AACzC,cAAc,mBAAmB,CAAC;AAClC,cAAc,0BAA0B,CAAC;AACzC,cAAc,mBAAmB,CAAC;AAClC,cAAc,kBAAkB,CAAC;AACjC,cAAc,aAAa,CAAC;AAC5B,cAAc,cAAc,CAAC;AAC7B,cAAc,yBAAyB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,cAAc,eAAe,CAAC;AAC9B,cAAc,uBAAuB,CAAC;AACtC,cAAc,uBAAuB,CAAC;AACtC,cAAc,cAAc,CAAC;AAC7B,cAAc,kBAAkB,CAAC;AACjC,cAAc,yBAAyB,CAAC;AACxC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,eAAe,CAAC;AAC9B,cAAc,wBAAwB,CAAC;AACvC,cAAc,qBAAqB,CAAC;AACpC,cAAc,qBAAqB,CAAC;AACpC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,wBAAwB,CAAC;AACvC,cAAc,mBAAmB,CAAC;AAClC,cAAc,0BAA0B,CAAC;AACzC,cAAc,oBAAoB,CAAC;AACnC,cAAc,sBAAsB,CAAC;AACrC,cAAc,sBAAsB,CAAC;AACrC,cAAc,mBAAmB,CAAC;AAClC,cAAc,wBAAwB,CAAC;AACvC,cAAc,oBAAoB,CAAC;AACnC,cAAc,0BAA0B,CAAC;AACzC,cAAc,mBAAmB,CAAC;AAClC,cAAc,0BAA0B,CAAC;AACzC,cAAc,mBAAmB,CAAC;AAClC,cAAc,kBAAkB,CAAC;AACjC,cAAc,aAAa,CAAC;AAC5B,cAAc,cAAc,CAAC;AAC7B,cAAc,yBAAyB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -4,6 +4,7 @@ export * from './gateway-protocol.js';
|
|
|
4
4
|
export * from './command-builders.js';
|
|
5
5
|
export * from './adapter.js';
|
|
6
6
|
export * from './voice-paths.js';
|
|
7
|
+
export * from './voice-reply-digest.js';
|
|
7
8
|
export * from './net-utils.js';
|
|
8
9
|
export * from './timeline.js';
|
|
9
10
|
export * from './subagent-activity.js';
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,cAAc,eAAe,CAAC;AAC9B,cAAc,uBAAuB,CAAC;AACtC,cAAc,uBAAuB,CAAC;AACtC,cAAc,cAAc,CAAC;AAC7B,cAAc,kBAAkB,CAAC;AACjC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,eAAe,CAAC;AAC9B,cAAc,wBAAwB,CAAC;AACvC,cAAc,qBAAqB,CAAC;AACpC,cAAc,qBAAqB,CAAC;AACpC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,wBAAwB,CAAC;AACvC,cAAc,mBAAmB,CAAC;AAClC,cAAc,0BAA0B,CAAC;AACzC,cAAc,oBAAoB,CAAC;AACnC,cAAc,sBAAsB,CAAC;AACrC,cAAc,sBAAsB,CAAC;AACrC,cAAc,mBAAmB,CAAC;AAClC,cAAc,wBAAwB,CAAC;AACvC,cAAc,oBAAoB,CAAC;AACnC,cAAc,0BAA0B,CAAC;AACzC,cAAc,mBAAmB,CAAC;AAClC,cAAc,0BAA0B,CAAC;AACzC,cAAc,mBAAmB,CAAC;AAClC,cAAc,kBAAkB,CAAC;AACjC,cAAc,aAAa,CAAC;AAC5B,cAAc,cAAc,CAAC;AAC7B,cAAc,yBAAyB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,cAAc,eAAe,CAAC;AAC9B,cAAc,uBAAuB,CAAC;AACtC,cAAc,uBAAuB,CAAC;AACtC,cAAc,cAAc,CAAC;AAC7B,cAAc,kBAAkB,CAAC;AACjC,cAAc,yBAAyB,CAAC;AACxC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,eAAe,CAAC;AAC9B,cAAc,wBAAwB,CAAC;AACvC,cAAc,qBAAqB,CAAC;AACpC,cAAc,qBAAqB,CAAC;AACpC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,wBAAwB,CAAC;AACvC,cAAc,mBAAmB,CAAC;AAClC,cAAc,0BAA0B,CAAC;AACzC,cAAc,oBAAoB,CAAC;AACnC,cAAc,sBAAsB,CAAC;AACrC,cAAc,sBAAsB,CAAC;AACrC,cAAc,mBAAmB,CAAC;AAClC,cAAc,wBAAwB,CAAC;AACvC,cAAc,oBAAoB,CAAC;AACnC,cAAc,0BAA0B,CAAC;AACzC,cAAc,mBAAmB,CAAC;AAClC,cAAc,0BAA0B,CAAC;AACzC,cAAc,mBAAmB,CAAC;AAClC,cAAc,kBAAkB,CAAC;AACjC,cAAc,aAAa,CAAC;AAC5B,cAAc,cAAc,CAAC;AAC7B,cAAc,yBAAyB,CAAC"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What a spoken reply should actually say.
|
|
3
|
+
*
|
|
4
|
+
* SSOT for both daemons: the Node daemon imports these, and
|
|
5
|
+
* `DaemonServer.speakableReply` / `.spokenDigest` in the Swift daemon mirror
|
|
6
|
+
* them (parity cases in `SPOKEN_DIGEST_CASES` below are asserted on both sides).
|
|
7
|
+
*
|
|
8
|
+
* The distinction that matters: `speakableReply` decides *what is readable*
|
|
9
|
+
* (strip code fences, markdown scaffolding, URLs), while `spokenDigest` decides
|
|
10
|
+
* *how much to read*. A written answer and a spoken one are different artifacts
|
|
11
|
+
* — a 700-character reply is a fine thing to read on screen and a monologue
|
|
12
|
+
* through a speaker, and the listener cannot skim it. So speech gets the lead:
|
|
13
|
+
* an explicit summary line when the answer has one, otherwise its first
|
|
14
|
+
* sentence. The full text stays on the deck and in the terminal, where skimming
|
|
15
|
+
* works.
|
|
16
|
+
*/
|
|
17
|
+
/** A spoken reply past this is a monologue, not an answer. Truncated at a
|
|
18
|
+
* sentence boundary when one is near the cap. */
|
|
19
|
+
export declare const MAX_SPOKEN_CHARS = 700;
|
|
20
|
+
/** Ceiling for the digest. Reached only by a single very long sentence — the
|
|
21
|
+
* first-sentence rule normally lands far below it. */
|
|
22
|
+
export declare const SPOKEN_DIGEST_MAX_CHARS = 240;
|
|
23
|
+
/**
|
|
24
|
+
* Strip what makes no sense read aloud and cap at a sentence boundary.
|
|
25
|
+
* Kept separate from the digest so callers that genuinely want the whole answer
|
|
26
|
+
* (a board with a screen, a test) can still get it.
|
|
27
|
+
*/
|
|
28
|
+
export declare function speakableReply(raw: string, maxChars?: number): string;
|
|
29
|
+
/**
|
|
30
|
+
* The one thing worth reading aloud out of a full reply: an explicit summary
|
|
31
|
+
* line if the answer has one, otherwise its first sentence.
|
|
32
|
+
*
|
|
33
|
+
* `full: true` restores the whole readable answer for callers that opted out
|
|
34
|
+
* (daemon setting `voice.speakFullReply`).
|
|
35
|
+
*/
|
|
36
|
+
export declare function spokenDigest(raw: string, opts?: {
|
|
37
|
+
maxChars?: number;
|
|
38
|
+
full?: boolean;
|
|
39
|
+
}): string;
|
|
40
|
+
/**
|
|
41
|
+
* Cross-surface parity table. Asserted by vitest against `spokenDigest` and by
|
|
42
|
+
* XCTest against the Swift mirror, so the two daemons cannot drift into
|
|
43
|
+
* speaking different amounts of the same reply.
|
|
44
|
+
*/
|
|
45
|
+
export declare const SPOKEN_DIGEST_CASES: ReadonlyArray<{
|
|
46
|
+
name: string;
|
|
47
|
+
input: string;
|
|
48
|
+
expected: string;
|
|
49
|
+
}>;
|
|
50
|
+
//# sourceMappingURL=voice-reply-digest.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"voice-reply-digest.d.ts","sourceRoot":"","sources":["../src/voice-reply-digest.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH;kDACkD;AAClD,eAAO,MAAM,gBAAgB,MAAM,CAAC;AAEpC;uDACuD;AACvD,eAAO,MAAM,uBAAuB,MAAM,CAAC;AAc3C;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,SAAmB,GAAG,MAAM,CAwB/E;AAkDD;;;;;;GAMG;AACH,wBAAgB,YAAY,CAC1B,GAAG,EAAE,MAAM,EACX,IAAI,GAAE;IAAE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,OAAO,CAAA;CAAO,GAC/C,MAAM,CAiCR;AAED;;;;GAIG;AACH,eAAO,MAAM,mBAAmB,EAAE,aAAa,CAAC;IAC9C,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;CAC/C,CAoCA,CAAC"}
|
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What a spoken reply should actually say.
|
|
3
|
+
*
|
|
4
|
+
* SSOT for both daemons: the Node daemon imports these, and
|
|
5
|
+
* `DaemonServer.speakableReply` / `.spokenDigest` in the Swift daemon mirror
|
|
6
|
+
* them (parity cases in `SPOKEN_DIGEST_CASES` below are asserted on both sides).
|
|
7
|
+
*
|
|
8
|
+
* The distinction that matters: `speakableReply` decides *what is readable*
|
|
9
|
+
* (strip code fences, markdown scaffolding, URLs), while `spokenDigest` decides
|
|
10
|
+
* *how much to read*. A written answer and a spoken one are different artifacts
|
|
11
|
+
* — a 700-character reply is a fine thing to read on screen and a monologue
|
|
12
|
+
* through a speaker, and the listener cannot skim it. So speech gets the lead:
|
|
13
|
+
* an explicit summary line when the answer has one, otherwise its first
|
|
14
|
+
* sentence. The full text stays on the deck and in the terminal, where skimming
|
|
15
|
+
* works.
|
|
16
|
+
*/
|
|
17
|
+
/** A spoken reply past this is a monologue, not an answer. Truncated at a
|
|
18
|
+
* sentence boundary when one is near the cap. */
|
|
19
|
+
export const MAX_SPOKEN_CHARS = 700;
|
|
20
|
+
/** Ceiling for the digest. Reached only by a single very long sentence — the
|
|
21
|
+
* first-sentence rule normally lands far below it. */
|
|
22
|
+
export const SPOKEN_DIGEST_MAX_CHARS = 240;
|
|
23
|
+
/**
|
|
24
|
+
* Openers that mark an author-written summary. Matched at the start of a line,
|
|
25
|
+
* with or without a separator, in both languages the replies come in.
|
|
26
|
+
*/
|
|
27
|
+
const SUMMARY_LABELS = [
|
|
28
|
+
'요약', '한 줄 요약', '한줄 요약', '결론', '정리',
|
|
29
|
+
'TL;DR', 'TLDR', 'Summary', 'In short', 'In summary', 'Bottom line',
|
|
30
|
+
];
|
|
31
|
+
/** Sentence enders, including the CJK forms. */
|
|
32
|
+
const TERMINATORS = new Set(['.', '!', '?', '。', '!', '?', '…']);
|
|
33
|
+
/**
|
|
34
|
+
* Strip what makes no sense read aloud and cap at a sentence boundary.
|
|
35
|
+
* Kept separate from the digest so callers that genuinely want the whole answer
|
|
36
|
+
* (a board with a screen, a test) can still get it.
|
|
37
|
+
*/
|
|
38
|
+
export function speakableReply(raw, maxChars = MAX_SPOKEN_CHARS) {
|
|
39
|
+
if (!raw)
|
|
40
|
+
return '';
|
|
41
|
+
let text = raw
|
|
42
|
+
// Fenced blocks read as noise; say so once instead of reciting them.
|
|
43
|
+
.replace(/```[\s\S]*?```/g, ' (code) ')
|
|
44
|
+
.replace(/`([^`]+)`/g, '$1')
|
|
45
|
+
.replace(/!?\[([^\]]*)\]\([^)]*\)/g, '$1')
|
|
46
|
+
.replace(/https?:\/\/\S+/g, ' link ')
|
|
47
|
+
.replace(/^\s*(?:#{1,6}|>|[*\-+])\s+/gm, '')
|
|
48
|
+
.replace(/\*\*|__|~~/g, '')
|
|
49
|
+
.replace(/[ \t]+/g, ' ')
|
|
50
|
+
.replace(/\n{2,}/g, '\n')
|
|
51
|
+
.trim();
|
|
52
|
+
if (!text)
|
|
53
|
+
return '';
|
|
54
|
+
if (text.length > maxChars) {
|
|
55
|
+
const head = text.slice(0, maxChars);
|
|
56
|
+
// Prefer ending on a sentence so the cut doesn't sound like a dropout.
|
|
57
|
+
const lastStop = Math.max(head.lastIndexOf('. '), head.lastIndexOf('。'), head.lastIndexOf('! '), head.lastIndexOf('? '), head.lastIndexOf('다.'));
|
|
58
|
+
text = lastStop > maxChars * 0.5 ? head.slice(0, lastStop + 1) : head;
|
|
59
|
+
}
|
|
60
|
+
return text.trim();
|
|
61
|
+
}
|
|
62
|
+
/** True when a line ends a sentence — the cheap test for "prose, not a heading". */
|
|
63
|
+
function hasTerminator(line) {
|
|
64
|
+
for (const ch of line)
|
|
65
|
+
if (TERMINATORS.has(ch))
|
|
66
|
+
return true;
|
|
67
|
+
return false;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* The summary a line declares, or null. `요약: 고쳤습니다` yields the remainder;
|
|
71
|
+
* a bare `요약` line yields '' so the caller can take the line after it.
|
|
72
|
+
*/
|
|
73
|
+
function summaryOnLine(line) {
|
|
74
|
+
for (const label of SUMMARY_LABELS) {
|
|
75
|
+
if (!line.toLowerCase().startsWith(label.toLowerCase()))
|
|
76
|
+
continue;
|
|
77
|
+
const afterLabel = line.slice(label.length);
|
|
78
|
+
const rest = afterLabel.replace(/^\s*[::\-—–.]\s*/, '').trim();
|
|
79
|
+
// "Summarywise …" and "요약 대신 …" are prose, not labels; require a
|
|
80
|
+
// separator (or end of line) before treating the remainder as the summary.
|
|
81
|
+
if (rest === afterLabel.trim() && rest !== '' && /^[\p{L}\p{N}_]/u.test(rest)) {
|
|
82
|
+
continue;
|
|
83
|
+
}
|
|
84
|
+
return rest;
|
|
85
|
+
}
|
|
86
|
+
return null;
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* The first sentence of `text`, or all of it when it has no terminator.
|
|
90
|
+
* Returns the substring rather than an index so the Swift mirror (which counts
|
|
91
|
+
* Characters, not UTF-16 units) cannot cut a surrogate pair differently.
|
|
92
|
+
*/
|
|
93
|
+
function firstSentence(text) {
|
|
94
|
+
const chars = Array.from(text);
|
|
95
|
+
for (let i = 0; i < chars.length; i += 1) {
|
|
96
|
+
if (!TERMINATORS.has(chars[i]))
|
|
97
|
+
continue;
|
|
98
|
+
const next = chars[i + 1];
|
|
99
|
+
// "1.0" and "v1.2.3" are not sentence ends; a terminator only counts when
|
|
100
|
+
// what follows is nothing, whitespace, or a closing mark.
|
|
101
|
+
if (chars[i] === '.' && /\d/.test(chars[i - 1] ?? '') && /\d/.test(next ?? ''))
|
|
102
|
+
continue;
|
|
103
|
+
if (next === undefined || /[\s"'”’)\]]/.test(next)) {
|
|
104
|
+
// Run out any repeated terminators ("!?", "...") so they stay together.
|
|
105
|
+
let end = i + 1;
|
|
106
|
+
while (end < chars.length && TERMINATORS.has(chars[end]))
|
|
107
|
+
end += 1;
|
|
108
|
+
return chars.slice(0, end).join('');
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
return text;
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* The one thing worth reading aloud out of a full reply: an explicit summary
|
|
115
|
+
* line if the answer has one, otherwise its first sentence.
|
|
116
|
+
*
|
|
117
|
+
* `full: true` restores the whole readable answer for callers that opted out
|
|
118
|
+
* (daemon setting `voice.speakFullReply`).
|
|
119
|
+
*/
|
|
120
|
+
export function spokenDigest(raw, opts = {}) {
|
|
121
|
+
const readable = speakableReply(raw, opts.full ? MAX_SPOKEN_CHARS : Number.MAX_SAFE_INTEGER);
|
|
122
|
+
if (!readable)
|
|
123
|
+
return '';
|
|
124
|
+
if (opts.full)
|
|
125
|
+
return readable;
|
|
126
|
+
const cap = opts.maxChars ?? SPOKEN_DIGEST_MAX_CHARS;
|
|
127
|
+
const lines = readable.split('\n').map((l) => l.trim()).filter((l) => l.length > 0);
|
|
128
|
+
let unit = '';
|
|
129
|
+
for (let i = 0; i < lines.length; i += 1) {
|
|
130
|
+
const summary = summaryOnLine(lines[i]);
|
|
131
|
+
if (summary === null)
|
|
132
|
+
continue;
|
|
133
|
+
unit = summary || lines[i + 1] || '';
|
|
134
|
+
if (unit)
|
|
135
|
+
break;
|
|
136
|
+
}
|
|
137
|
+
if (!unit) {
|
|
138
|
+
// Skip a leading section label ("원인", "Result") when prose follows it:
|
|
139
|
+
// reading a heading alone tells the listener nothing.
|
|
140
|
+
let start = 0;
|
|
141
|
+
while (start < lines.length - 1 && !hasTerminator(lines[start]) && lines[start].length <= 24) {
|
|
142
|
+
start += 1;
|
|
143
|
+
}
|
|
144
|
+
unit = firstSentence(lines[start] ?? '');
|
|
145
|
+
}
|
|
146
|
+
unit = unit.trim();
|
|
147
|
+
if (!unit)
|
|
148
|
+
return '';
|
|
149
|
+
if (unit.length <= cap)
|
|
150
|
+
return unit;
|
|
151
|
+
// A single sentence over the cap: cut on a word boundary, not mid-word.
|
|
152
|
+
const head = unit.slice(0, cap);
|
|
153
|
+
const lastSpace = head.lastIndexOf(' ');
|
|
154
|
+
return (lastSpace > cap * 0.6 ? head.slice(0, lastSpace) : head).trim();
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* Cross-surface parity table. Asserted by vitest against `spokenDigest` and by
|
|
158
|
+
* XCTest against the Swift mirror, so the two daemons cannot drift into
|
|
159
|
+
* speaking different amounts of the same reply.
|
|
160
|
+
*/
|
|
161
|
+
export const SPOKEN_DIGEST_CASES = [
|
|
162
|
+
{
|
|
163
|
+
name: 'first sentence only, not the whole paragraph',
|
|
164
|
+
input: '원인을 찾았습니다. 헬퍼 바이너리에 Info.plist가 없었습니다. 지금은 고쳤습니다.',
|
|
165
|
+
expected: '원인을 찾았습니다.',
|
|
166
|
+
},
|
|
167
|
+
{
|
|
168
|
+
name: 'explicit summary label wins over the opening sentence',
|
|
169
|
+
input: 'VOICE 키가 죽어 있었습니다. 원인은 TCC입니다.\n요약: 헬퍼를 재빌드하면 동작합니다.',
|
|
170
|
+
expected: '헬퍼를 재빌드하면 동작합니다.',
|
|
171
|
+
},
|
|
172
|
+
{
|
|
173
|
+
name: 'bare summary label takes the line after it',
|
|
174
|
+
input: 'TL;DR\nThe helper needed a usage description.\nDetails follow.',
|
|
175
|
+
expected: 'The helper needed a usage description.',
|
|
176
|
+
},
|
|
177
|
+
{
|
|
178
|
+
name: 'a heading-only first line is skipped for the prose under it',
|
|
179
|
+
input: '## 원인\n번들 헬퍼에 Info.plist가 없었습니다. 그래서 TCC가 죽였습니다.',
|
|
180
|
+
expected: '번들 헬퍼에 Info.plist가 없었습니다.',
|
|
181
|
+
},
|
|
182
|
+
{
|
|
183
|
+
name: 'code fences never get recited',
|
|
184
|
+
input: 'Fixed it.\n\n```ts\nconst x = 1;\n```\n',
|
|
185
|
+
expected: 'Fixed it.',
|
|
186
|
+
},
|
|
187
|
+
{
|
|
188
|
+
name: 'a version number does not end the sentence',
|
|
189
|
+
input: 'Bumped it to 1.0.2 for the release. Nothing else changed.',
|
|
190
|
+
expected: 'Bumped it to 1.0.2 for the release.',
|
|
191
|
+
},
|
|
192
|
+
{
|
|
193
|
+
name: 'nothing speakable stays empty',
|
|
194
|
+
input: '```\ndiff --git a b\n```',
|
|
195
|
+
expected: '(code)',
|
|
196
|
+
},
|
|
197
|
+
];
|
|
198
|
+
//# sourceMappingURL=voice-reply-digest.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"voice-reply-digest.js","sourceRoot":"","sources":["../src/voice-reply-digest.ts"],"names":[],"mappings":"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"}
|