@leviyuan/lodestar 0.2.0 → 0.2.1
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/package.json +1 -1
- package/src/instructions.ts +9 -18
- package/src/session.ts +11 -8
package/package.json
CHANGED
package/src/instructions.ts
CHANGED
|
@@ -1,22 +1,13 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
2
|
+
* Daemon ↔ model I/O contracts. Appended to claude's system prompt on
|
|
3
|
+
* every headless launch via `--append-system-prompt`. Three rules:
|
|
4
|
+
* inbound file marker, multi-content boundary marker, outbound file
|
|
5
|
+
* marker. Anything beyond pure I/O semantics (environment description,
|
|
6
|
+
* UX conventions, identity binding) was stripped 2026-05-16 — the
|
|
7
|
+
* model handles conversational flow natively, doesn't need to be told.
|
|
7
8
|
*/
|
|
8
9
|
export const CHANNEL_INSTRUCTIONS = [
|
|
9
|
-
'
|
|
10
|
-
'
|
|
11
|
-
'',
|
|
12
|
-
'Conventions for every turn:',
|
|
13
|
-
'- Open with one short acknowledgement so the user sees you started.',
|
|
14
|
-
'- Stream your conclusion before the turn ends; never end on a silent tool call. The card is your voice.',
|
|
15
|
-
'- For long work, drop progress sentences between tool calls so the user is not staring at a loading dot.',
|
|
16
|
-
'',
|
|
17
|
-
'Inbound user messages may carry a [file: /abs/path] hint when the user sent an image or attachment in Feishu. Read those files when relevant.',
|
|
18
|
-
'',
|
|
19
|
-
'To send a local file or image back to the user in this Feishu group, write the marker `[[send: /abs/path]]` (absolute path) anywhere in your reply, preferably on its own line at the end. The daemon strips every marker from the displayed card and posts the file as a separate Feishu message. Emit the marker only when the user asked for a file or when delivering a generated artifact (screenshot, diagram, exported doc) — not for arbitrary paths.',
|
|
20
|
-
'',
|
|
21
|
-
'The group name equals the working directory under $HOME and equals the Lodestar session name. Treat that binding as load-bearing — do not rename or move the directory.',
|
|
10
|
+
'- Text prefixed with `[file: /abs/path]` means a file is attached at that path; read it when relevant.',
|
|
11
|
+
'- A content block wrapped in `<u>...</u>` is an independent message — treat each `<u>` element in a multi-content turn as a separate input, even when their texts concatenate visually (e.g. `<u>1</u><u>45</u>` is two messages, not the number `145`).',
|
|
12
|
+
'- Write `[[send: /abs/path]]` anywhere in your reply (preferably on its own line) to deliver that file as a separate message. The marker is stripped from the displayed text. Emit only when the user asked for a file or you are delivering a generated artifact.',
|
|
22
13
|
].join('\n')
|
package/src/session.ts
CHANGED
|
@@ -511,14 +511,17 @@ export class Session {
|
|
|
511
511
|
const wasBusy = this.currentTurn !== null || this.openingTurn
|
|
512
512
|
this.pendingUserMessageCount++
|
|
513
513
|
this.lastUserOpenId = userOpenId
|
|
514
|
-
// When
|
|
515
|
-
// user turn
|
|
516
|
-
//
|
|
517
|
-
//
|
|
518
|
-
//
|
|
519
|
-
//
|
|
520
|
-
//
|
|
521
|
-
|
|
514
|
+
// When the SDK will merge this msg with siblings into a multi-
|
|
515
|
+
// content user turn, wrap it in `<u>...</u>` so the model sees a
|
|
516
|
+
// structural boundary it actually attends to. Tried U+001E
|
|
517
|
+
// (ASCII Record Separator) first — invisible and theoretically
|
|
518
|
+
// perfect, but Anthropic's tokenizer effectively drops control
|
|
519
|
+
// chars and `<u>1</u><u>45</u>` became "145" to the model
|
|
520
|
+
// (2026-05-16 accumulator test). HTML-tag wrap is visible but
|
|
521
|
+
// models parse `<tag>` boundaries very reliably from training.
|
|
522
|
+
// Solo (eager-open) msgs don't get wrapped — no sibling, no
|
|
523
|
+
// merge, no need. Contract declared in CHANNEL_INSTRUCTIONS.
|
|
524
|
+
const wireText = wasBusy ? `<u>${text}</u>` : text
|
|
522
525
|
this.proc!.sendUserText(wireText, files)
|
|
523
526
|
if (wasBusy && msgId) {
|
|
524
527
|
// Hold the slot in the map even if the API call hasn't returned
|