Skip to content

Commit 76f4478

Browse files
committed
v0.37.18: fix --deliver delivery (2 bugs)
1. Flag parser: 'for i < len(args)-1' skipped the last arg, so --deliver at end of command was never parsed. Changed loop to 'i < len(args)' with bounds checks, plus post-loop scan for standalone flags after the task text. 2. Config loader: resolveTelegram() didn't copy DefaultChatID from file config, so deliverToTelegram always got chatID=0. 3. Removed ParseModeMarkdownV2 from deliverToTelegram — LLM output has unescaped special chars that Telegram rejects in MarkdownV2.
1 parent ebf5e3e commit 76f4478

3 files changed

Lines changed: 99 additions & 7 deletions

File tree

cmd/odek/main.go

Lines changed: 92 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -327,28 +327,46 @@ func parseRunFlags(args []string) (runFlags, error) {
327327
var f runFlags
328328

329329
i := 0
330-
for i < len(args)-1 {
330+
for i < len(args) {
331331
switch args[i] {
332332
case "--model":
333+
if i+1 >= len(args) {
334+
return f, fmt.Errorf("--model requires a value")
335+
}
333336
f.Model = args[i+1]
334337
i += 2
335338
case "--base-url":
339+
if i+1 >= len(args) {
340+
return f, fmt.Errorf("--base-url requires a value")
341+
}
336342
f.BaseURL = args[i+1]
337343
i += 2
338344
case "--max-iter":
345+
if i+1 >= len(args) {
346+
return f, fmt.Errorf("--max-iter requires a value")
347+
}
339348
var n int
340349
fmt.Sscanf(args[i+1], "%d", &n)
341350
if n > 0 {
342351
f.MaxIter = n
343352
}
344353
i += 2
345354
case "--system":
355+
if i+1 >= len(args) {
356+
return f, fmt.Errorf("--system requires a value")
357+
}
346358
f.System = args[i+1]
347359
i += 2
348360
case "--thinking":
361+
if i+1 >= len(args) {
362+
return f, fmt.Errorf("--thinking requires a value")
363+
}
349364
f.Thinking = args[i+1]
350365
i += 2
351366
case "--temperature":
367+
if i+1 >= len(args) {
368+
return f, fmt.Errorf("--temperature requires a value")
369+
}
352370
var t float64
353371
fmt.Sscanf(args[i+1], "%f", &t)
354372
f.Temp = t
@@ -375,42 +393,110 @@ func parseRunFlags(args []string) (runFlags, error) {
375393
f.Session = boolPtr(true)
376394
i++
377395
case "--sandbox-image":
396+
if i+1 >= len(args) {
397+
return f, fmt.Errorf("--sandbox-image requires a value")
398+
}
378399
f.SandboxImage = args[i+1]
379400
i += 2
380401
case "--sandbox-network":
402+
if i+1 >= len(args) {
403+
return f, fmt.Errorf("--sandbox-network requires a value")
404+
}
381405
f.SandboxNetwork = args[i+1]
382406
i += 2
383407
case "--sandbox-readonly":
384408
f.SandboxReadonly = boolPtr(true)
385409
i++
386410
case "--sandbox-memory":
411+
if i+1 >= len(args) {
412+
return f, fmt.Errorf("--sandbox-memory requires a value")
413+
}
387414
f.SandboxMemory = args[i+1]
388415
i += 2
389416
case "--sandbox-cpus":
417+
if i+1 >= len(args) {
418+
return f, fmt.Errorf("--sandbox-cpus requires a value")
419+
}
390420
f.SandboxCPUs = args[i+1]
391421
i += 2
392422
case "--sandbox-user":
423+
if i+1 >= len(args) {
424+
return f, fmt.Errorf("--sandbox-user requires a value")
425+
}
393426
f.SandboxUser = args[i+1]
394427
i += 2
395428
case "--github-repo-dir":
429+
if i+1 >= len(args) {
430+
return f, fmt.Errorf("--github-repo-dir requires a value")
431+
}
396432
f.GithubRepoDirectory = args[i+1]
397433
i += 2
398434
case "--github-repo-url":
435+
if i+1 >= len(args) {
436+
return f, fmt.Errorf("--github-repo-url requires a value")
437+
}
399438
f.GithubRepoUrl = args[i+1]
400439
i += 2
401440
case "--ctx", "-c":
441+
if i+1 >= len(args) {
442+
return f, fmt.Errorf("--ctx requires a value")
443+
}
402444
f.Ctx = strings.Split(args[i+1], ",")
403445
i += 2
404-
case "--deliver":
405-
f.Deliver = boolPtr(true)
406-
i++
446+
case "--deliver":
447+
f.Deliver = boolPtr(true)
448+
i++
407449
default:
408450
// Not a flag — treat remaining as the task
409451
goto done
410452
}
411453
}
412454
done:
413-
f.Task = strings.Join(args[i:], " ")
455+
// Scan remaining args for standalone flags that may appear after the
456+
// task phrase (e.g. "odek run 'hello' --deliver"). This allows flags
457+
// without values to be placed anywhere on the command line.
458+
taskArgs := args[i:]
459+
for j := 0; j < len(taskArgs); j++ {
460+
switch taskArgs[j] {
461+
case "--deliver":
462+
f.Deliver = boolPtr(true)
463+
taskArgs = append(taskArgs[:j], taskArgs[j+1:]...)
464+
j--
465+
case "--sandbox":
466+
f.Sandbox = boolPtr(true)
467+
taskArgs = append(taskArgs[:j], taskArgs[j+1:]...)
468+
j--
469+
case "--session":
470+
f.Session = boolPtr(true)
471+
taskArgs = append(taskArgs[:j], taskArgs[j+1:]...)
472+
j--
473+
case "--no-color":
474+
f.NoColor = boolPtr(true)
475+
taskArgs = append(taskArgs[:j], taskArgs[j+1:]...)
476+
j--
477+
case "--no-agents":
478+
f.NoAgents = boolPtr(true)
479+
taskArgs = append(taskArgs[:j], taskArgs[j+1:]...)
480+
j--
481+
case "--no-learn":
482+
f.Learn = boolPtr(false)
483+
taskArgs = append(taskArgs[:j], taskArgs[j+1:]...)
484+
j--
485+
case "--learn":
486+
f.Learn = boolPtr(true)
487+
taskArgs = append(taskArgs[:j], taskArgs[j+1:]...)
488+
j--
489+
case "--prompt-caching":
490+
f.PromptCaching = boolPtr(true)
491+
taskArgs = append(taskArgs[:j], taskArgs[j+1:]...)
492+
j--
493+
case "--sandbox-readonly":
494+
f.SandboxReadonly = boolPtr(true)
495+
taskArgs = append(taskArgs[:j], taskArgs[j+1:]...)
496+
j--
497+
}
498+
}
499+
f.Task = strings.Join(taskArgs, " ")
414500
if f.Task == "" {
415501
return f, fmt.Errorf("no task provided")
416502
}
@@ -1102,7 +1188,7 @@ func deliverToTelegram(text string, resolved config.ResolvedConfig) error {
11021188
return fmt.Errorf("telegram default_chat_id not configured")
11031189
}
11041190
bot := telegram.NewBot(resolved.Telegram.Token)
1105-
_, err := bot.SendMessage(chatID, text, &telegram.SendOpts{ParseMode: telegram.ParseModeMarkdownV2})
1191+
_, err := bot.SendMessage(chatID, text, nil)
11061192
if err != nil {
11071193
return fmt.Errorf("send telegram message: %w", err)
11081194
}

cmd/odek/main_test.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -563,9 +563,12 @@ func TestParseRunFlags_EdgeCases(t *testing.T) {
563563
name: "flags after task",
564564
args: []string{"my task", "--sandbox"},
565565
check: func(t *testing.T, f runFlags) {
566-
if f.Task != "my task --sandbox" {
566+
if f.Task != "my task" {
567567
t.Errorf("task = %q", f.Task)
568568
}
569+
if f.Sandbox == nil || !*f.Sandbox {
570+
t.Error("Sandbox should be true (parsed from post-task flag)")
571+
}
569572
},
570573
},
571574
{

internal/config/loader.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -788,6 +788,9 @@ func resolveTelegram(cfg *telegram.TelegramConfig) telegram.TelegramConfig {
788788
if cfg.LogFile != "" {
789789
base.LogFile = cfg.LogFile
790790
}
791+
if cfg.DefaultChatID != 0 {
792+
base.DefaultChatID = cfg.DefaultChatID
793+
}
791794
return base
792795
}
793796

0 commit comments

Comments
 (0)