@@ -254,15 +254,15 @@ type runFlags struct {
254254 NoAgents * bool // nil = not set
255255 PromptCaching * bool // nil = not set; true = enable prompt caching
256256 Session * bool // nil = not set; true = save session after run
257- Learn * bool // nil = not set; true = enable skills learning mode
258- Task string
257+ Learn * bool // nil = not set; true = enable skills learning mode
258+ Task string
259259
260260 // ToolsEnabled and ToolsDisabled control which tools are exposed to the LLM.
261261 // Repeated --tool/--no-tool flags accumulate. They are the highest priority
262262 // layer after file config and env vars.
263263 ToolsEnabled []string
264264 ToolsDisabled []string
265- Ctx []string // --ctx files to attach
265+ Ctx []string // --ctx files to attach
266266
267267 // Sandbox-specific CLI flags
268268 SandboxImage string // Docker image (e.g. "node:20-alpine")
@@ -273,10 +273,18 @@ type runFlags struct {
273273 SandboxReadonly * bool // nil = not set; true = read-only mount
274274
275275 // Extended memory subsystem CLI overrides.
276- MemoryExtendedEnabled * bool // nil = not set
277- MemoryExtendedMaxSizeMB int // 0 = not set
278- MemoryExtendedAtomMaxChars int // 0 = not set
279- MemoryExtendedMemoryBudgetChars int // 0 = not set
276+ MemoryExtendedEnabled * bool // nil = not set
277+ MemoryExtendedMaxSizeMB int // 0 = not set
278+ MemoryExtendedAtomMaxChars int // 0 = not set
279+ MemoryExtendedMemoryBudgetChars int // 0 = not set
280+ MemoryExtendedUserStateTurnInterval int // 0 = not set
281+ MemoryExtendedUserStateMaxPending int // 0 = not set
282+ MemoryExtendedAssociationsEnabled * bool // nil = not set
283+ MemoryExtendedAssociationSemanticTopK int // 0 = not set
284+ MemoryExtendedProactiveReturnAfterBreak * bool // nil = not set
285+ MemoryExtendedStyleMirroringEnabled * bool // nil = not set
286+ MemoryExtendedAnaphoraResolutionEnabled * bool // nil = not set
287+ MemoryExtendedFollowUpAnticipationEnabled * bool // nil = not set
280288
281289 Deliver * bool // nil = not set; true = deliver result to default channel
282290}
@@ -430,6 +438,54 @@ func parseRunFlags(args []string) (runFlags, error) {
430438 }
431439 fmt .Sscanf (args [i + 1 ], "%d" , & f .MemoryExtendedMemoryBudgetChars )
432440 i += 2
441+ case "--memory-extended-user-state-turn-interval" :
442+ if i + 1 >= len (args ) {
443+ return f , fmt .Errorf ("--memory-extended-user-state-turn-interval requires a value" )
444+ }
445+ fmt .Sscanf (args [i + 1 ], "%d" , & f .MemoryExtendedUserStateTurnInterval )
446+ i += 2
447+ case "--memory-extended-user-state-max-pending" :
448+ if i + 1 >= len (args ) {
449+ return f , fmt .Errorf ("--memory-extended-user-state-max-pending requires a value" )
450+ }
451+ fmt .Sscanf (args [i + 1 ], "%d" , & f .MemoryExtendedUserStateMaxPending )
452+ i += 2
453+ case "--memory-extended-associations-enabled" :
454+ f .MemoryExtendedAssociationsEnabled = boolPtr (true )
455+ i ++
456+ case "--memory-extended-associations-disabled" :
457+ f .MemoryExtendedAssociationsEnabled = boolPtr (false )
458+ i ++
459+ case "--memory-extended-association-semantic-top-k" :
460+ if i + 1 >= len (args ) {
461+ return f , fmt .Errorf ("--memory-extended-association-semantic-top-k requires a value" )
462+ }
463+ fmt .Sscanf (args [i + 1 ], "%d" , & f .MemoryExtendedAssociationSemanticTopK )
464+ i += 2
465+ case "--memory-extended-proactive-return-after-break" :
466+ f .MemoryExtendedProactiveReturnAfterBreak = boolPtr (true )
467+ i ++
468+ case "--memory-extended-no-proactive-return-after-break" :
469+ f .MemoryExtendedProactiveReturnAfterBreak = boolPtr (false )
470+ i ++
471+ case "--memory-extended-style-mirroring-enabled" :
472+ f .MemoryExtendedStyleMirroringEnabled = boolPtr (true )
473+ i ++
474+ case "--memory-extended-style-mirroring-disabled" :
475+ f .MemoryExtendedStyleMirroringEnabled = boolPtr (false )
476+ i ++
477+ case "--memory-extended-anaphora-resolution-enabled" :
478+ f .MemoryExtendedAnaphoraResolutionEnabled = boolPtr (true )
479+ i ++
480+ case "--memory-extended-anaphora-resolution-disabled" :
481+ f .MemoryExtendedAnaphoraResolutionEnabled = boolPtr (false )
482+ i ++
483+ case "--memory-extended-follow-up-anticipation-enabled" :
484+ f .MemoryExtendedFollowUpAnticipationEnabled = boolPtr (true )
485+ i ++
486+ case "--memory-extended-follow-up-anticipation-disabled" :
487+ f .MemoryExtendedFollowUpAnticipationEnabled = boolPtr (false )
488+ i ++
433489 case "--deliver" :
434490 f .Deliver = boolPtr (true )
435491 i ++
@@ -678,10 +734,23 @@ Sandbox flags:
678734 --sandbox-user <s> Run as user (uid:gid or name)
679735
680736Extended memory flags:
681- --memory-extended-enabled Enable Extended Memory (opt-in)
682- --memory-extended-max-size-mb <n> Max on-disk size in MiB (default: 100)
683- --memory-extended-atom-max-chars <n> Max chars per atom (default: 300)
684- --memory-extended-memory-budget-chars <n> Max chars injected into prompt (default: 2000)
737+ --memory-extended-enabled Enable Extended Memory (opt-in)
738+ --memory-extended-max-size-mb <n> Max on-disk size in MiB (default: 100)
739+ --memory-extended-atom-max-chars <n> Max chars per atom (default: 300)
740+ --memory-extended-memory-budget-chars <n> Max chars injected into prompt (default: 2000)
741+ --memory-extended-user-state-turn-interval <n> Turns between user-state inferences (default: 5)
742+ --memory-extended-user-state-max-pending <n> Max pending user-state inferences (default: 20)
743+ --memory-extended-associations-enabled Enable atom associations (default: true)
744+ --memory-extended-associations-disabled Disable atom associations
745+ --memory-extended-association-semantic-top-k <n> Semantic neighbours per atom (default: 3)
746+ --memory-extended-proactive-return-after-break Resume summary on continue (default: true)
747+ --memory-extended-no-proactive-return-after-break Disable resume summary
748+ --memory-extended-style-mirroring-enabled Mirror inferred user style (default: true)
749+ --memory-extended-style-mirroring-disabled Disable style mirroring
750+ --memory-extended-anaphora-resolution-enabled Resolve pronouns against atoms (default: true)
751+ --memory-extended-anaphora-resolution-disabled Disable anaphora resolution
752+ --memory-extended-follow-up-anticipation-enabled Pre-load follow-up context (default: true)
753+ --memory-extended-follow-up-anticipation-disabled Disable follow-up anticipation
685754
686755Config sources (lowest to highest priority):
687756 ~/.odek/config.json Global defaults (shared across projects)
@@ -710,7 +779,15 @@ Environment variables:
710779 ODEK_MEMORY_EXTENDED_ENABLED true/false — enable Extended Memory
711780 ODEK_MEMORY_EXTENDED_MAX_SIZE_MB Max on-disk size in MiB
712781 ODEK_MEMORY_EXTENDED_ATOM_MAX_CHARS Max chars per atom
713- ODEK_MEMORY_EXTENDED_MEMORY_BUDGET_CHARS Max chars injected into prompt` )
782+ ODEK_MEMORY_EXTENDED_MEMORY_BUDGET_CHARS Max chars injected into prompt
783+ ODEK_MEMORY_EXTENDED_USER_STATE_TURN_INTERVAL Turns between user-state inferences
784+ ODEK_MEMORY_EXTENDED_USER_STATE_MAX_PENDING Max pending user-state inferences
785+ ODEK_MEMORY_EXTENDED_ASSOCIATIONS_ENABLED true/false — enable atom associations
786+ ODEK_MEMORY_EXTENDED_ASSOCIATION_SEMANTIC_TOP_K Semantic neighbours per atom
787+ ODEK_MEMORY_EXTENDED_PROACTIVE_RETURN_AFTER_BREAK true/false — resume summary on continue
788+ ODEK_MEMORY_EXTENDED_STYLE_MIRRORING_ENABLED true/false — mirror inferred user style
789+ ODEK_MEMORY_EXTENDED_ANAPHORA_RESOLUTION_ENABLED true/false — resolve pronouns against atoms
790+ ODEK_MEMORY_EXTENDED_FOLLOW_UP_ANTICIPATION_ENABLED true/false — pre-load follow-up context` )
714791}
715792
716793// ── Init ──────────────────────────────────────────────────────────────
@@ -909,10 +986,18 @@ func run(args []string) error {
909986 SandboxCPUs : f .SandboxCPUs ,
910987 SandboxUser : f .SandboxUser ,
911988
912- MemoryExtendedEnabled : f .MemoryExtendedEnabled ,
913- MemoryExtendedMaxSizeMB : f .MemoryExtendedMaxSizeMB ,
914- MemoryExtendedAtomMaxChars : f .MemoryExtendedAtomMaxChars ,
915- MemoryExtendedMemoryBudgetChars : f .MemoryExtendedMemoryBudgetChars ,
989+ MemoryExtendedEnabled : f .MemoryExtendedEnabled ,
990+ MemoryExtendedMaxSizeMB : f .MemoryExtendedMaxSizeMB ,
991+ MemoryExtendedAtomMaxChars : f .MemoryExtendedAtomMaxChars ,
992+ MemoryExtendedMemoryBudgetChars : f .MemoryExtendedMemoryBudgetChars ,
993+ MemoryExtendedUserStateTurnInterval : f .MemoryExtendedUserStateTurnInterval ,
994+ MemoryExtendedUserStateMaxPending : f .MemoryExtendedUserStateMaxPending ,
995+ MemoryExtendedAssociationsEnabled : f .MemoryExtendedAssociationsEnabled ,
996+ MemoryExtendedAssociationSemanticTopK : f .MemoryExtendedAssociationSemanticTopK ,
997+ MemoryExtendedProactiveReturnAfterBreak : f .MemoryExtendedProactiveReturnAfterBreak ,
998+ MemoryExtendedStyleMirroringEnabled : f .MemoryExtendedStyleMirroringEnabled ,
999+ MemoryExtendedAnaphoraResolutionEnabled : f .MemoryExtendedAnaphoraResolutionEnabled ,
1000+ MemoryExtendedFollowUpAnticipationEnabled : f .MemoryExtendedFollowUpAnticipationEnabled ,
9161001 })
9171002
9181003 // Resolve @references and --ctx file attachments in the task
@@ -1022,18 +1107,18 @@ func run(args []string) error {
10221107 SystemMessage : systemMessage ,
10231108 UntrustedWrapper : func (source , content string ) string { return wrapUntrusted (context .Background (), source , content ) },
10241109 NoProjectFile : resolved .NoAgents ,
1025- Thinking : resolved .Thinking ,
1026- ThinkingBudget : f .ThinkingBudget ,
1027- Temperature : 0 , // deterministic by default; override with --temperature
1028- Tools : tools ,
1029- ToolFilter : odek.ToolFilterConfig {Enabled : resolved .Tools .Enabled , Disabled : resolved .Tools .Disabled },
1030- SandboxCleanup : sandboxCleanup ,
1031- Renderer : rend ,
1032- Skills : skillsCfg ,
1033- SkillManager : sm ,
1034- PromptCaching : resolved .PromptCaching ,
1035- MemoryDir : expandHome ("~/.odek/memory" ),
1036- MemoryConfig : resolved .Memory ,
1110+ Thinking : resolved .Thinking ,
1111+ ThinkingBudget : f .ThinkingBudget ,
1112+ Temperature : 0 , // deterministic by default; override with --temperature
1113+ Tools : tools ,
1114+ ToolFilter : odek.ToolFilterConfig {Enabled : resolved .Tools .Enabled , Disabled : resolved .Tools .Disabled },
1115+ SandboxCleanup : sandboxCleanup ,
1116+ Renderer : rend ,
1117+ Skills : skillsCfg ,
1118+ SkillManager : sm ,
1119+ PromptCaching : resolved .PromptCaching ,
1120+ MemoryDir : expandHome ("~/.odek/memory" ),
1121+ MemoryConfig : resolved .Memory ,
10371122 })
10381123 if err != nil {
10391124 return err
@@ -1994,27 +2079,27 @@ func continueCmd(args []string) error {
19942079 skillsCfg = & resolved .Skills
19952080 }
19962081
1997- agent , err := odek .New (odek.Config {
1998- Model : resolved .Model ,
1999- BaseURL : resolved .BaseURL ,
2000- APIKey : resolved .APIKey ,
2001- MaxIterations : resolved .MaxIter ,
2002- MaxToolParallel : resolved .MaxToolParallel ,
2003- SystemMessage : systemMessage ,
2004- UntrustedWrapper : func (source , content string ) string { return wrapUntrusted (context .Background (), source , content ) },
2005- NoProjectFile : resolved .NoAgents ,
2006- Thinking : resolved .Thinking ,
2007- Temperature : 0 , // deterministic by default; override with --temperature
2008- Tools : tools ,
2009- ToolFilter : odek.ToolFilterConfig {Enabled : resolved .Tools .Enabled , Disabled : resolved .Tools .Disabled },
2010- SandboxCleanup : sandboxCleanup ,
2011- Renderer : rend ,
2012- Skills : skillsCfg ,
2013- SkillManager : sm ,
2014- PromptCaching : resolved .PromptCaching ,
2015- MemoryDir : expandHome ("~/.odek/memory" ),
2016- MemoryConfig : resolved .Memory ,
2017- })
2082+ agent , err := odek .New (odek.Config {
2083+ Model : resolved .Model ,
2084+ BaseURL : resolved .BaseURL ,
2085+ APIKey : resolved .APIKey ,
2086+ MaxIterations : resolved .MaxIter ,
2087+ MaxToolParallel : resolved .MaxToolParallel ,
2088+ SystemMessage : systemMessage ,
2089+ UntrustedWrapper : func (source , content string ) string { return wrapUntrusted (context .Background (), source , content ) },
2090+ NoProjectFile : resolved .NoAgents ,
2091+ Thinking : resolved .Thinking ,
2092+ Temperature : 0 , // deterministic by default; override with --temperature
2093+ Tools : tools ,
2094+ ToolFilter : odek.ToolFilterConfig {Enabled : resolved .Tools .Enabled , Disabled : resolved .Tools .Disabled },
2095+ SandboxCleanup : sandboxCleanup ,
2096+ Renderer : rend ,
2097+ Skills : skillsCfg ,
2098+ SkillManager : sm ,
2099+ PromptCaching : resolved .PromptCaching ,
2100+ MemoryDir : expandHome ("~/.odek/memory" ),
2101+ MemoryConfig : resolved .Memory ,
2102+ })
20182103 if err != nil {
20192104 return err
20202105 }
@@ -2035,6 +2120,29 @@ func continueCmd(args []string) error {
20352120 // Build message history: session messages + new user message
20362121 // The system message is already in the session
20372122 messages := sess .GetMessages ()
2123+
2124+ // Return-after-break: on session resume, load a concise summary of where
2125+ // the user left off and the next likely step.
2126+ if mm := agent .Memory (); mm != nil {
2127+ rbCtx , rbCancel := context .WithTimeout (context .Background (), 5 * time .Second )
2128+ if rb := mm .FormatReturnAfterBreak (rbCtx ); rb != "" {
2129+ insertIdx := - 1
2130+ for i := len (messages ) - 1 ; i >= 0 ; i -- {
2131+ if messages [i ].Role == "system" {
2132+ insertIdx = i
2133+ break
2134+ }
2135+ }
2136+ rbMsg := llm.Message {Role : "system" , Content : rb }
2137+ if insertIdx >= 0 {
2138+ messages = append (messages [:insertIdx + 1 ], append ([]llm.Message {rbMsg }, messages [insertIdx + 1 :]... )... )
2139+ } else {
2140+ messages = append ([]llm.Message {rbMsg }, messages ... )
2141+ }
2142+ }
2143+ rbCancel ()
2144+ }
2145+
20382146 messages = append (messages , llm.Message {Role : "user" , Content : task })
20392147
20402148 // Append user input to buffer (AppendBuffer summarizes raw text).
0 commit comments