typeclaw 0.37.3 → 0.37.5
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/README.md +69 -46
- package/package.json +1 -1
- package/src/agent/compaction.ts +24 -15
- package/src/agent/doctor.ts +6 -1
- package/src/agent/session-origin.ts +101 -173
- package/src/agent/subagents.ts +146 -14
- package/src/agent/system-prompt.ts +46 -48
- package/src/agent/todo/scope.ts +4 -2
- package/src/agent/tools/channel-reply.ts +7 -9
- package/src/bundled-plugins/memory/index.ts +33 -33
- package/src/bundled-plugins/memory/load-memory.ts +92 -35
- package/src/bundled-plugins/memory/slug.ts +19 -0
- package/src/bundled-plugins/memory/turn-dedup.ts +32 -29
- package/src/bundled-plugins/security/policies/private-surface-read.ts +4 -1
- package/src/bundled-plugins/tool-result-cap/README.md +7 -7
- package/src/bundled-plugins/tool-result-cap/index.ts +1 -1
- package/src/channels/adapters/discord-bot.ts +11 -4
- package/src/channels/adapters/github/inbound.ts +68 -43
- package/src/channels/adapters/github/index.ts +57 -9
- package/src/channels/adapters/github/recover-failed-deliveries.ts +270 -0
- package/src/channels/adapters/kakaotalk.ts +5 -1
- package/src/channels/adapters/mention-hints.ts +75 -0
- package/src/channels/adapters/slack-bot.ts +8 -2
- package/src/channels/continuation-willingness.ts +216 -68
- package/src/channels/router.ts +149 -15
- package/src/cli/dreams.ts +2 -2
- package/src/cli/init.ts +41 -7
- package/src/cli/inspect.ts +2 -2
- package/src/cli/logs.ts +2 -2
- package/src/cli/qr.ts +4 -3
- package/src/cli/require-agent-dir.ts +31 -0
- package/src/cli/shell.ts +2 -2
- package/src/cli/stop.ts +2 -2
- package/src/cli/tui.ts +20 -6
- package/src/cli/ui.ts +8 -4
- package/src/container/shared.ts +18 -0
- package/src/container/start.ts +1 -1
- package/src/doctor/checks.ts +145 -2
- package/src/hostd/client.ts +48 -52
- package/src/hostd/daemon.ts +82 -39
- package/src/hostd/paths.ts +22 -2
- package/src/hostd/spawn.ts +7 -0
- package/src/hostd/tailscale.ts +12 -1
- package/src/init/index.ts +35 -8
- package/src/init/kakaotalk-auth.ts +2 -2
- package/src/init/packagejson.ts +2 -2
- package/src/init/run-bun-install.ts +71 -37
- package/src/inspect/transcript-view.ts +15 -2
- package/src/plugin/loader.ts +7 -4
- package/src/portbroker/hostd-client.ts +32 -6
- package/src/sandbox/session-tmp.ts +6 -1
- package/src/secrets/export-claude-credentials-file.ts +2 -2
- package/src/shared/index.ts +4 -0
- package/src/shared/platform.ts +11 -0
- package/src/shared/wsl.ts +139 -0
- package/src/tui/index.ts +26 -8
- package/src/tui/terminal-guard.ts +139 -0
- package/typeclaw.schema.json +2 -2
|
@@ -13,6 +13,14 @@
|
|
|
13
13
|
// descriptive ("I checked and it's fine") or other-directed ("you can continue")
|
|
14
14
|
// usage. This is a HINT, not a control-flow authority: the abort still fires
|
|
15
15
|
// regardless; only the optional nudge is gated on it.
|
|
16
|
+
//
|
|
17
|
+
// Detection is two-pass: a phrase-substring pass (ALL_PHRASES) for analytic
|
|
18
|
+
// languages where future intent is a separate word ("I'll", "voy a", "我会"),
|
|
19
|
+
// plus a morpheme pass (MORPHEME_PATTERNS + the Japanese check) for languages
|
|
20
|
+
// where it is a verb inflection/affix. The morpheme pass matches the marker
|
|
21
|
+
// itself, so it generalizes across EVERY action verb (update/configure/fix/…)
|
|
22
|
+
// instead of enumerating each — what the per-verb KO/TR/HI/JA lists used to do
|
|
23
|
+
// by hand.
|
|
16
24
|
|
|
17
25
|
// Strip markdown emphasis/code fences before matching so an inline `gh` span
|
|
18
26
|
// inside "바로 `gh`로 확인할게요" does not split the phrase.
|
|
@@ -62,70 +70,80 @@ const EN_PHRASES: readonly string[] = [
|
|
|
62
70
|
'lemme check',
|
|
63
71
|
'lemme look',
|
|
64
72
|
'lemme take a look',
|
|
73
|
+
// Action/config verb family. The retrieval verbs above ("check/look/look up")
|
|
74
|
+
// miss the much larger class of "I'll DO X" promises — update/configure/set up/
|
|
75
|
+
// schedule/fix/apply/create — which is exactly the class that silently truncates
|
|
76
|
+
// when the model forgets `continue: true` (the cron-update production miss).
|
|
77
|
+
"i'll update",
|
|
78
|
+
"i'll set up",
|
|
79
|
+
"i'll set it up",
|
|
80
|
+
"i'll configure",
|
|
81
|
+
"i'll schedule",
|
|
82
|
+
"i'll fix",
|
|
83
|
+
"i'll apply",
|
|
84
|
+
"i'll add",
|
|
85
|
+
"i'll create",
|
|
86
|
+
"i'll handle",
|
|
87
|
+
'let me update',
|
|
88
|
+
'let me fix',
|
|
89
|
+
'let me set up',
|
|
90
|
+
'let me configure',
|
|
91
|
+
'let me add',
|
|
92
|
+
'let me create',
|
|
93
|
+
'let me handle',
|
|
65
94
|
]
|
|
66
95
|
|
|
67
|
-
// Korean:
|
|
68
|
-
//
|
|
69
|
-
//
|
|
70
|
-
//
|
|
71
|
-
//
|
|
96
|
+
// Korean: the -겠습니다/-겠어요 and -ㄹ게요 verb endings are first-person
|
|
97
|
+
// volitional — they cannot address the listener, so they are safe self-direction
|
|
98
|
+
// anchors. The -겠습니다/-겠어요 form is matched by MORPHEME_PATTERNS below (it
|
|
99
|
+
// generalizes across all action verbs), so only the -게요/-게여 forms and stall
|
|
100
|
+
// idioms are enumerated here. Bare adverb+noun fragments ("바로 확인", "계속 확인",
|
|
101
|
+
// "곧 알려") are deliberately NOT listed: without the volitional ending they match
|
|
102
|
+
// other-directed requests ("바로 확인 부탁드려요" = "please check") and descriptive
|
|
103
|
+
// progressives ("계속 확인 중입니다" = "I'm still checking") — the exact false
|
|
104
|
+
// positives the design forbids. Their volitional forms are caught by the morpheme
|
|
105
|
+
// regex regardless.
|
|
72
106
|
const KO_PHRASES: readonly string[] = [
|
|
73
107
|
'확인해볼게요',
|
|
74
108
|
'확인해 볼게요',
|
|
75
109
|
'확인할게요',
|
|
76
|
-
'
|
|
77
|
-
'확인해보겠습니다',
|
|
78
|
-
'확인해 보겠습니다',
|
|
79
|
-
'다시 확인하겠습니다',
|
|
80
|
-
'다시 확인해보겠습니다',
|
|
81
|
-
'이어서 확인',
|
|
82
|
-
'계속 확인',
|
|
110
|
+
'확인할게여',
|
|
83
111
|
'계속 진행할게요',
|
|
84
|
-
'계속 진행하겠습니다',
|
|
85
|
-
'계속하겠습니다',
|
|
86
112
|
'계속할게요',
|
|
87
|
-
'바로 확인',
|
|
88
113
|
'바로 볼게요',
|
|
89
|
-
'바로 진행',
|
|
90
114
|
'살펴볼게요',
|
|
91
|
-
'살펴보겠습니다',
|
|
92
|
-
'진행하겠습니다',
|
|
93
|
-
'잠시만요',
|
|
94
|
-
'잠깐만요',
|
|
95
|
-
'곧 알려',
|
|
96
|
-
// Bare first-person-volitional verb endings: the -ㄹ게요/-겠습니다 ending is
|
|
97
|
-
// self-directed regardless of the preceding adverb, so the "바로 …" prefix in
|
|
98
|
-
// the entries above is not load-bearing. "볼게요" alone (and "먼저/한번/지금 볼게요"
|
|
99
|
-
// by substring) is the exact production miss — the ack "…먼저 볼게요" did not
|
|
100
|
-
// match because only the "바로 볼게요" compound was listed. Common work verbs
|
|
101
|
-
// (검토/조회/찾아/알아/처리) in the same volitional form join here for parity with
|
|
102
|
-
// "확인/살펴" above; "볼게여" is the casual -여 variant seen in chat.
|
|
103
115
|
'볼게요',
|
|
104
116
|
'볼게여',
|
|
105
|
-
'확인할게여',
|
|
106
117
|
'검토할게요',
|
|
107
118
|
'검토해볼게요',
|
|
108
|
-
'검토하겠습니다',
|
|
109
119
|
'조회해볼게요',
|
|
110
|
-
'조회하겠습니다',
|
|
111
120
|
'찾아볼게요',
|
|
112
|
-
'찾아보겠습니다',
|
|
113
121
|
'알아볼게요',
|
|
114
|
-
'알아보겠습니다',
|
|
115
122
|
'처리할게요',
|
|
116
|
-
'
|
|
123
|
+
'알려드릴게요',
|
|
124
|
+
// Action/config verb -게요 forms (the -겠습니다 siblings are covered by the
|
|
125
|
+
// morpheme regex; these are the casual-polite variants chat models also emit).
|
|
126
|
+
'업데이트할게요',
|
|
127
|
+
'수정할게요',
|
|
128
|
+
'설정할게요',
|
|
129
|
+
'반영할게요',
|
|
130
|
+
'적용할게요',
|
|
131
|
+
'추가할게요',
|
|
132
|
+
'생성할게요',
|
|
133
|
+
'잠시만요',
|
|
134
|
+
'잠깐만요',
|
|
117
135
|
]
|
|
118
136
|
|
|
119
137
|
// The remaining languages mirror the precision-first selection above: every
|
|
120
138
|
// entry pairs a FIRST-PERSON future/volitional anchor with a work verb
|
|
121
|
-
// (check/look/continue/proceed/verify) or is an
|
|
122
|
-
// now"). The same false-negative bias holds — bare
|
|
123
|
-
// ("ok", "sí", "好"), second-person imperatives ("you
|
|
124
|
-
// descriptive past forms ("I checked") are deliberately excluded
|
|
125
|
-
// substring match on those would mis-fire. Latin/Cyrillic/Arabic/Indic
|
|
126
|
-
// are inflected first-person-future forms (or multi-word) so they cannot
|
|
127
|
-
// collide with a bare common word; CJK entries are full 4+ character
|
|
128
|
-
//
|
|
139
|
+
// (check/look/continue/proceed/verify or update/configure/fix/create) or is an
|
|
140
|
+
// immediate-work idiom ("on it now"). The same false-negative bias holds — bare
|
|
141
|
+
// verbs, bare acknowledgments ("ok", "sí", "好"), second-person imperatives ("you
|
|
142
|
+
// continue"), and descriptive past forms ("I checked") are deliberately excluded
|
|
143
|
+
// because a substring match on those would mis-fire. Latin/Cyrillic/Arabic/Indic
|
|
144
|
+
// entries are inflected first-person-future forms (or multi-word) so they cannot
|
|
145
|
+
// collide with a bare common word; CJK entries are full 4+ character intent
|
|
146
|
+
// phrases, never a lone noun.
|
|
129
147
|
|
|
130
148
|
// Spanish: "voy a" / "déjame" + work verb; "enseguida" (right away) idioms.
|
|
131
149
|
const ES_PHRASES: readonly string[] = [
|
|
@@ -152,6 +170,17 @@ const ES_PHRASES: readonly string[] = [
|
|
|
152
170
|
'un momento',
|
|
153
171
|
'dame un momento',
|
|
154
172
|
'dame un segundo',
|
|
173
|
+
// Action/config verb family.
|
|
174
|
+
'voy a actualizar',
|
|
175
|
+
'voy a configurar',
|
|
176
|
+
'voy a corregir',
|
|
177
|
+
'voy a arreglar',
|
|
178
|
+
'voy a crear',
|
|
179
|
+
'voy a añadir',
|
|
180
|
+
'voy a programar',
|
|
181
|
+
'voy a aplicar',
|
|
182
|
+
'déjame actualizar',
|
|
183
|
+
'déjame corregir',
|
|
155
184
|
]
|
|
156
185
|
|
|
157
186
|
// French: "je vais" + work verb; "laisse-moi" idioms.
|
|
@@ -174,6 +203,16 @@ const FR_PHRASES: readonly string[] = [
|
|
|
174
203
|
'un instant',
|
|
175
204
|
'donne-moi un instant',
|
|
176
205
|
'donne-moi une seconde',
|
|
206
|
+
// Action/config verb family.
|
|
207
|
+
'je vais mettre à jour',
|
|
208
|
+
'je vais configurer',
|
|
209
|
+
'je vais corriger',
|
|
210
|
+
'je vais créer',
|
|
211
|
+
'je vais ajouter',
|
|
212
|
+
'je vais programmer',
|
|
213
|
+
'je vais appliquer',
|
|
214
|
+
'laisse-moi corriger',
|
|
215
|
+
'laisse-moi mettre à jour',
|
|
177
216
|
]
|
|
178
217
|
|
|
179
218
|
// Italian: "vado a" / "fammi" + work verb; "controllo subito" idioms.
|
|
@@ -194,6 +233,15 @@ const IT_PHRASES: readonly string[] = [
|
|
|
194
233
|
'un momento',
|
|
195
234
|
'dammi un momento',
|
|
196
235
|
'dammi un secondo',
|
|
236
|
+
// Action/config verb family.
|
|
237
|
+
'vado ad aggiornare',
|
|
238
|
+
'vado a configurare',
|
|
239
|
+
'vado a correggere',
|
|
240
|
+
'vado a creare',
|
|
241
|
+
'vado ad aggiungere',
|
|
242
|
+
'vado ad applicare',
|
|
243
|
+
'fammi aggiornare',
|
|
244
|
+
'fammi correggere',
|
|
197
245
|
]
|
|
198
246
|
|
|
199
247
|
// Portuguese: "vou" + work verb; "deixa eu" idioms.
|
|
@@ -214,6 +262,16 @@ const PT_PHRASES: readonly string[] = [
|
|
|
214
262
|
'um momento',
|
|
215
263
|
'me dê um momento',
|
|
216
264
|
'me dá um segundo',
|
|
265
|
+
// Action/config verb family.
|
|
266
|
+
'vou atualizar',
|
|
267
|
+
'vou configurar',
|
|
268
|
+
'vou corrigir',
|
|
269
|
+
'vou criar',
|
|
270
|
+
'vou adicionar',
|
|
271
|
+
'vou agendar',
|
|
272
|
+
'vou aplicar',
|
|
273
|
+
'deixa eu atualizar',
|
|
274
|
+
'deixa eu corrigir',
|
|
217
275
|
]
|
|
218
276
|
|
|
219
277
|
// German: "ich werde" / "lass mich" + work verb; "ich schaue gleich" idioms.
|
|
@@ -238,10 +296,22 @@ const DE_PHRASES: readonly string[] = [
|
|
|
238
296
|
'einen moment',
|
|
239
297
|
'einen augenblick',
|
|
240
298
|
'gib mir eine sekunde',
|
|
299
|
+
// Action/config verb family.
|
|
300
|
+
'ich werde aktualisieren',
|
|
301
|
+
'ich werde konfigurieren',
|
|
302
|
+
'ich werde korrigieren',
|
|
303
|
+
'ich werde einrichten',
|
|
304
|
+
'ich werde erstellen',
|
|
305
|
+
'ich werde hinzufügen',
|
|
306
|
+
'ich werde anwenden',
|
|
307
|
+
'lass mich aktualisieren',
|
|
308
|
+
'lass mich korrigieren',
|
|
241
309
|
]
|
|
242
310
|
|
|
243
311
|
// Russian: first-person-future verbs (проверю/посмотрю/продолжу) — the -ю/-у
|
|
244
|
-
// inflection is unambiguously "I will", so it is a safe self-anchor.
|
|
312
|
+
// inflection is unambiguously "I will", so it is a safe self-anchor. (Note: the
|
|
313
|
+
// bare -ю ending is shared with present-imperfective "я делаю" = "I do", so this
|
|
314
|
+
// stays an enumerated list rather than a morpheme regex.)
|
|
245
315
|
const RU_PHRASES: readonly string[] = [
|
|
246
316
|
'сейчас проверю',
|
|
247
317
|
'я проверю',
|
|
@@ -254,6 +324,15 @@ const RU_PHRASES: readonly string[] = [
|
|
|
254
324
|
'дайте мне минуту',
|
|
255
325
|
'одну секунду',
|
|
256
326
|
'минутку',
|
|
327
|
+
// Action/config verb family (perfective first-person futures).
|
|
328
|
+
'я обновлю',
|
|
329
|
+
'я настрою',
|
|
330
|
+
'я исправлю',
|
|
331
|
+
'я создам',
|
|
332
|
+
'я добавлю',
|
|
333
|
+
'я применю',
|
|
334
|
+
'сейчас обновлю',
|
|
335
|
+
'сейчас исправлю',
|
|
257
336
|
]
|
|
258
337
|
|
|
259
338
|
// Chinese: 我会/我来/我再 + work verb. Full multi-character intent phrases only;
|
|
@@ -277,26 +356,39 @@ const ZH_PHRASES: readonly string[] = [
|
|
|
277
356
|
'让我检查一下',
|
|
278
357
|
'稍等一下',
|
|
279
358
|
'我看一下',
|
|
359
|
+
// Action/config verb family.
|
|
360
|
+
'我来更新',
|
|
361
|
+
'我会更新',
|
|
362
|
+
'我来配置',
|
|
363
|
+
'我来设置',
|
|
364
|
+
'我会设置',
|
|
365
|
+
'我来修改',
|
|
366
|
+
'我会修改',
|
|
367
|
+
'我来修复',
|
|
368
|
+
'我来创建',
|
|
369
|
+
'我来添加',
|
|
370
|
+
'我马上更新',
|
|
371
|
+
'让我更新',
|
|
372
|
+
'让我改一下',
|
|
280
373
|
]
|
|
281
374
|
|
|
282
|
-
// Japanese:
|
|
283
|
-
//
|
|
375
|
+
// Japanese: handled by the JA_VOLITIONAL morpheme check below (-します/-いたします/
|
|
376
|
+
// -してみます generalizes across all する action verbs). Only the regular-verb
|
|
377
|
+
// ます forms (調べます/見てみます/続けます — bare ます is too broad to regex) and
|
|
378
|
+
// stall idioms are enumerated here.
|
|
284
379
|
const JA_PHRASES: readonly string[] = [
|
|
285
|
-
'確認します',
|
|
286
|
-
'確認してみます',
|
|
287
|
-
'確認いたします',
|
|
288
380
|
'調べてみます',
|
|
289
381
|
'調べます',
|
|
290
382
|
'見てみます',
|
|
291
383
|
'続けます',
|
|
292
|
-
'引き続き確認します',
|
|
293
|
-
'すぐ確認します',
|
|
294
384
|
'少々お待ちください',
|
|
295
385
|
'ちょっと待ってください',
|
|
296
386
|
]
|
|
297
387
|
|
|
298
388
|
// Arabic: future particle سـ prefixed first-person verb (سأتحقق = "I will
|
|
299
|
-
// verify"). The سأ prefix is
|
|
389
|
+
// verify"). The سأ prefix is first-person-future, but as a bare substring it
|
|
390
|
+
// collides with the root س-أ-ل ("ask": سألت "I asked", المسألة "the matter"), so
|
|
391
|
+
// this stays an enumerated list of full verbs rather than a سأ-prefix regex.
|
|
300
392
|
const AR_PHRASES: readonly string[] = [
|
|
301
393
|
'سأتحقق',
|
|
302
394
|
'سأتأكد',
|
|
@@ -307,30 +399,31 @@ const AR_PHRASES: readonly string[] = [
|
|
|
307
399
|
'دعني أتحقق',
|
|
308
400
|
'دعني أراجع',
|
|
309
401
|
'لحظة من فضلك',
|
|
402
|
+
// Action/config verb family.
|
|
403
|
+
'سأحدث',
|
|
404
|
+
'سأحدّث',
|
|
405
|
+
'سأعدل',
|
|
406
|
+
'سأعدّل',
|
|
407
|
+
'سأضبط',
|
|
408
|
+
'سأصلح',
|
|
409
|
+
'سأنشئ',
|
|
410
|
+
'سأضيف',
|
|
310
411
|
]
|
|
311
412
|
|
|
312
|
-
// Hindi: first-person-future
|
|
313
|
-
//
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
'जांच करूंगा',
|
|
317
|
-
'देख लूँगा',
|
|
318
|
-
'देख लूंगा',
|
|
319
|
-
'जारी रखूँगा',
|
|
320
|
-
'जारी रखूंगा',
|
|
321
|
-
'एक मिनट रुकिए',
|
|
322
|
-
]
|
|
413
|
+
// Hindi: first-person-future is the -ūṅgā/-ūṅgī suffix, matched by
|
|
414
|
+
// MORPHEME_PATTERNS below (it covers all X-करना compounds). Only the stall idiom
|
|
415
|
+
// is enumerated here.
|
|
416
|
+
const HI_PHRASES: readonly string[] = ['एक मिनट रुकिए']
|
|
323
417
|
|
|
324
|
-
// Turkish: first-person-future "-eceğim/-acağım"
|
|
418
|
+
// Turkish: first-person-future "-eceğim/-acağım" is matched by MORPHEME_PATTERNS
|
|
419
|
+
// below. The present-progressive ("ediyorum" = "I'm checking now"), optative
|
|
420
|
+
// ("bir bakayım" = "let me look"), and stall idioms stay enumerated — the
|
|
421
|
+
// progressive -ıyorum ending is too polysemous to regex ("biliyorum" = "I know").
|
|
325
422
|
const TR_PHRASES: readonly string[] = [
|
|
326
|
-
'kontrol edeceğim',
|
|
327
423
|
'kontrol ediyorum',
|
|
328
|
-
'bakacağım',
|
|
329
424
|
'bir bakayım',
|
|
330
425
|
'bir kontrol edeyim',
|
|
331
426
|
'kontrol edeyim',
|
|
332
|
-
'inceleyeceğim',
|
|
333
|
-
'devam edeceğim',
|
|
334
427
|
'hemen kontrol ediyorum',
|
|
335
428
|
'hemen bakıyorum',
|
|
336
429
|
'bir saniye',
|
|
@@ -348,6 +441,14 @@ const VI_PHRASES: readonly string[] = [
|
|
|
348
441
|
'tôi xem ngay',
|
|
349
442
|
'chờ một chút',
|
|
350
443
|
'đợi một chút',
|
|
444
|
+
// Action/config verb family.
|
|
445
|
+
'tôi sẽ cập nhật',
|
|
446
|
+
'tôi sẽ cấu hình',
|
|
447
|
+
'tôi sẽ sửa',
|
|
448
|
+
'tôi sẽ tạo',
|
|
449
|
+
'tôi sẽ thêm',
|
|
450
|
+
'để tôi cập nhật',
|
|
451
|
+
'để tôi sửa',
|
|
351
452
|
]
|
|
352
453
|
|
|
353
454
|
// Indonesian: "saya akan" / "biar saya" (I will / let me) + work verb.
|
|
@@ -362,6 +463,16 @@ const ID_PHRASES: readonly string[] = [
|
|
|
362
463
|
'saya periksa dulu',
|
|
363
464
|
'tunggu sebentar',
|
|
364
465
|
'sebentar ya',
|
|
466
|
+
// Action/config verb family.
|
|
467
|
+
'saya akan perbarui',
|
|
468
|
+
'saya akan memperbarui',
|
|
469
|
+
'saya akan atur',
|
|
470
|
+
'saya akan konfigurasi',
|
|
471
|
+
'saya akan perbaiki',
|
|
472
|
+
'saya akan buat',
|
|
473
|
+
'saya akan tambah',
|
|
474
|
+
'biar saya perbaiki',
|
|
475
|
+
'biar saya perbarui',
|
|
365
476
|
]
|
|
366
477
|
|
|
367
478
|
const ALL_PHRASES: readonly string[] = [
|
|
@@ -382,6 +493,41 @@ const ALL_PHRASES: readonly string[] = [
|
|
|
382
493
|
...ID_PHRASES,
|
|
383
494
|
]
|
|
384
495
|
|
|
496
|
+
// First-person future/volitional realized as a verb inflection or affix (not a
|
|
497
|
+
// separate word), so matching the marker generalizes across ALL action verbs.
|
|
498
|
+
const MORPHEME_PATTERNS: readonly RegExp[] = [
|
|
499
|
+
// Korean first-person volitional: a verb stem + -겠습니다/-겠어요. The stem must
|
|
500
|
+
// be one of the action/auxiliary verbs 하 (the 하다 light verb behind every
|
|
501
|
+
// X하다 — 업데이트하겠습니다/반영하겠어요), 보 (살펴보겠습니다), 두 (반영해두겠습니다), or
|
|
502
|
+
// 놓 (해놓겠습니다). Anchoring on the verb stem is what keeps this self-directed:
|
|
503
|
+
// bare 겠 also matches adjective-stem CONJECTURE (좋겠어요 "that'd be nice",
|
|
504
|
+
// 괜찮겠어요 "must be fine") and the idioms 알겠/모르겠, none of which promise work.
|
|
505
|
+
// Listener-directed conjecture takes the honorific 시 (피곤하시겠어요 → 시겠, not
|
|
506
|
+
// 하겠), so it is excluded too.
|
|
507
|
+
/(?:하|보|두|놓)겠(?:습니다|어요)/,
|
|
508
|
+
// Turkish first-person-singular future "-acağım/-eceğim" ("I will VERB").
|
|
509
|
+
// Vowel harmony yields exactly these two suffixes; the y-buffer
|
|
510
|
+
// ("bekleyeceğim") leaves the suffix intact.
|
|
511
|
+
/acağım|eceğim/,
|
|
512
|
+
// Hindi first-person future "-ūṅgā/-ūṅgī" on any verb, covering all X-करना
|
|
513
|
+
// compounds ("अपडेट करूँगा"). Both nasal spellings (ँ U+0901 / ं U+0902) and
|
|
514
|
+
// both genders (ा/ी) are included.
|
|
515
|
+
/ू[ँं]ग[ाी]/,
|
|
516
|
+
]
|
|
517
|
+
|
|
518
|
+
// Japanese する-verb volitional します/いたします/してみます — covers the action class
|
|
519
|
+
// (更新します/設定します/対応します). Bare ます is the universal polite verb ending and
|
|
520
|
+
// far too broad to match, so this keys on します specifically. Two request/greeting
|
|
521
|
+
// idioms end in します without being work intent — お願い(いた)します ("please") and
|
|
522
|
+
// 失礼します ("excuse me") — and are stripped before the test so they don't fire.
|
|
523
|
+
// The (?![か??]) lookahead drops question forms — both the か question particle
|
|
524
|
+
// (どうしますか "what should I do?") and a trailing question mark, fullwidth ? or
|
|
525
|
+
// ASCII ? (どうします?, 更新します? "shall I update?"). A question awaits the user;
|
|
526
|
+
// it is not a commitment to act this turn. A statement keeps its 。/, so
|
|
527
|
+
// 更新します。 still matches.
|
|
528
|
+
const JA_VOLITIONAL_IDIOMS = /お願い(?:いた)?します|失礼します/g
|
|
529
|
+
const JA_VOLITIONAL = /します(?![か??])|してみます(?![か??])/
|
|
530
|
+
|
|
385
531
|
// Reply texts shorter than this are almost always a complete final answer
|
|
386
532
|
// ("네", "ok", "done") where a partial match would be noise. The shortest
|
|
387
533
|
// legitimate intent phrases ("on it now", "확인할게요") clear this floor.
|
|
@@ -391,5 +537,7 @@ export function detectContinuationWillingness(text: string): boolean {
|
|
|
391
537
|
if (text.length < MIN_LENGTH) return false
|
|
392
538
|
const normalized = normalize(text)
|
|
393
539
|
if (normalized.length < MIN_LENGTH) return false
|
|
394
|
-
|
|
540
|
+
if (ALL_PHRASES.some((phrase) => normalized.includes(phrase))) return true
|
|
541
|
+
if (MORPHEME_PATTERNS.some((pattern) => pattern.test(normalized))) return true
|
|
542
|
+
return JA_VOLITIONAL.test(normalized.replace(JA_VOLITIONAL_IDIOMS, ''))
|
|
395
543
|
}
|