ommlds 0.0.0.dev474__py3-none-any.whl → 0.0.0.dev476__py3-none-any.whl
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.
- ommlds/.omlish-manifests.json +131 -1
- ommlds/__about__.py +1 -1
- ommlds/backends/groq/_marshal.py +23 -0
- ommlds/backends/groq/protocol.py +184 -0
- ommlds/backends/tinygrad/models/llama3/__init__.py +22 -14
- ommlds/cli/asyncs.py +30 -0
- ommlds/cli/{sessions/chat/backends → backends}/catalog.py +35 -3
- ommlds/cli/backends/configs.py +9 -0
- ommlds/cli/backends/inject.py +31 -36
- ommlds/cli/{sessions/chat/backends → backends}/injection.py +1 -1
- ommlds/cli/{sessions/chat/backends → backends}/types.py +11 -1
- ommlds/cli/{sessions/chat/content → content}/messages.py +1 -1
- ommlds/cli/{sessions/chat/content → content}/strings.py +1 -1
- ommlds/cli/inject.py +7 -6
- ommlds/cli/inputs/asyncs.py +32 -0
- ommlds/cli/inputs/sync.py +75 -0
- ommlds/cli/main.py +266 -124
- ommlds/cli/rendering/__init__.py +0 -0
- ommlds/cli/rendering/configs.py +9 -0
- ommlds/cli/{sessions/chat/rendering → rendering}/inject.py +4 -5
- ommlds/cli/{sessions/chat/rendering → rendering}/markdown.py +1 -1
- ommlds/cli/{sessions/chat/rendering → rendering}/raw.py +1 -1
- ommlds/cli/{sessions/chat/rendering → rendering}/types.py +1 -1
- ommlds/cli/secrets.py +21 -0
- ommlds/cli/sessions/base.py +1 -1
- ommlds/cli/sessions/chat/chat/ai/configs.py +11 -0
- ommlds/cli/sessions/chat/chat/ai/inject.py +7 -11
- ommlds/cli/sessions/chat/chat/ai/rendering.py +4 -4
- ommlds/cli/sessions/chat/chat/ai/services.py +2 -2
- ommlds/cli/sessions/chat/chat/state/configs.py +11 -0
- ommlds/cli/sessions/chat/chat/state/inject.py +6 -10
- ommlds/cli/sessions/chat/chat/state/inmemory.py +1 -2
- ommlds/cli/sessions/chat/chat/state/storage.py +1 -2
- ommlds/cli/sessions/chat/chat/state/types.py +1 -1
- ommlds/cli/sessions/chat/chat/user/configs.py +17 -0
- ommlds/cli/sessions/chat/chat/user/inject.py +16 -15
- ommlds/cli/sessions/chat/chat/user/interactive.py +7 -5
- ommlds/cli/sessions/chat/configs.py +15 -24
- ommlds/cli/sessions/chat/inject.py +18 -34
- ommlds/cli/sessions/chat/session.py +1 -1
- ommlds/cli/sessions/chat/tools/configs.py +13 -0
- ommlds/cli/sessions/chat/tools/inject.py +6 -10
- ommlds/cli/sessions/chat/tools/injection.py +1 -0
- ommlds/cli/sessions/chat/tools/rendering.py +1 -1
- ommlds/cli/sessions/completion/configs.py +2 -2
- ommlds/cli/sessions/completion/inject.py +14 -0
- ommlds/cli/sessions/completion/session.py +7 -11
- ommlds/cli/sessions/embedding/configs.py +2 -2
- ommlds/cli/sessions/embedding/inject.py +14 -0
- ommlds/cli/sessions/embedding/session.py +7 -11
- ommlds/cli/state/storage.py +1 -1
- ommlds/minichain/backends/catalogs/strings.py +1 -1
- ommlds/minichain/backends/impls/dummy/__init__.py +0 -0
- ommlds/minichain/backends/impls/dummy/chat.py +69 -0
- ommlds/minichain/backends/impls/groq/__init__.py +0 -0
- ommlds/minichain/backends/impls/groq/chat.py +69 -0
- ommlds/minichain/backends/impls/groq/names.py +35 -0
- ommlds/minichain/backends/impls/groq/protocol.py +46 -0
- ommlds/minichain/backends/impls/groq/stream.py +121 -0
- ommlds/minichain/backends/impls/openai/chat.py +3 -3
- ommlds/minichain/backends/impls/openai/names.py +27 -3
- ommlds/minichain/backends/impls/openai/stream.py +2 -2
- ommlds/wiki/analyze.py +2 -2
- ommlds/wiki/utils/xml.py +5 -5
- {ommlds-0.0.0.dev474.dist-info → ommlds-0.0.0.dev476.dist-info}/METADATA +5 -5
- {ommlds-0.0.0.dev474.dist-info → ommlds-0.0.0.dev476.dist-info}/RECORD +73 -55
- ommlds/cli/backends/standard.py +0 -20
- ommlds/cli/sessions/chat/backends/inject.py +0 -53
- /ommlds/{cli/sessions/chat/backends → backends/groq}/__init__.py +0 -0
- /ommlds/cli/{sessions/chat/content → content}/__init__.py +0 -0
- /ommlds/cli/{sessions/chat/rendering → inputs}/__init__.py +0 -0
- {ommlds-0.0.0.dev474.dist-info → ommlds-0.0.0.dev476.dist-info}/WHEEL +0 -0
- {ommlds-0.0.0.dev474.dist-info → ommlds-0.0.0.dev476.dist-info}/entry_points.txt +0 -0
- {ommlds-0.0.0.dev474.dist-info → ommlds-0.0.0.dev476.dist-info}/licenses/LICENSE +0 -0
- {ommlds-0.0.0.dev474.dist-info → ommlds-0.0.0.dev476.dist-info}/top_level.txt +0 -0
ommlds/cli/inject.py
CHANGED
|
@@ -5,7 +5,7 @@ from omlish import lang
|
|
|
5
5
|
|
|
6
6
|
|
|
7
7
|
with lang.auto_proxy_import(globals()):
|
|
8
|
-
from .
|
|
8
|
+
from . import asyncs
|
|
9
9
|
from .sessions import inject as _sessions
|
|
10
10
|
from .state import inject as _state
|
|
11
11
|
|
|
@@ -16,17 +16,12 @@ with lang.auto_proxy_import(globals()):
|
|
|
16
16
|
def bind_main(
|
|
17
17
|
*,
|
|
18
18
|
session_cfg: ta.Any,
|
|
19
|
-
enable_backend_strings: bool = False,
|
|
20
19
|
) -> inj.Elements:
|
|
21
20
|
els: list[inj.Elemental] = []
|
|
22
21
|
|
|
23
22
|
#
|
|
24
23
|
|
|
25
24
|
els.extend([
|
|
26
|
-
_backends.bind_backends(
|
|
27
|
-
enable_backend_strings=enable_backend_strings,
|
|
28
|
-
),
|
|
29
|
-
|
|
30
25
|
_sessions.bind_sessions(session_cfg),
|
|
31
26
|
|
|
32
27
|
_state.bind_state(),
|
|
@@ -34,4 +29,10 @@ def bind_main(
|
|
|
34
29
|
|
|
35
30
|
#
|
|
36
31
|
|
|
32
|
+
els.extend([
|
|
33
|
+
inj.bind(asyncs.AsyncThreadRunner, to_ctor=asyncs.AnyioAsyncThreadRunner),
|
|
34
|
+
])
|
|
35
|
+
|
|
36
|
+
#
|
|
37
|
+
|
|
37
38
|
return inj.as_elements(*els)
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import typing as ta
|
|
2
|
+
|
|
3
|
+
from .. import asyncs
|
|
4
|
+
from .sync import SyncStringInput
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
##
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class AsyncStringInput(ta.Protocol):
|
|
11
|
+
def __call__(self) -> ta.Awaitable[str]: ...
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class ThreadAsyncStringInput:
|
|
15
|
+
def __init__(self, child: SyncStringInput, runner: asyncs.AsyncThreadRunner) -> None:
|
|
16
|
+
super().__init__()
|
|
17
|
+
|
|
18
|
+
self._child = child
|
|
19
|
+
self._runner = runner
|
|
20
|
+
|
|
21
|
+
async def __call__(self) -> str:
|
|
22
|
+
return await self._runner.run_in_thread(self._child)
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class SyncAsyncStringInput:
|
|
26
|
+
def __init__(self, child: SyncStringInput) -> None:
|
|
27
|
+
super().__init__()
|
|
28
|
+
|
|
29
|
+
self._child = child
|
|
30
|
+
|
|
31
|
+
async def __call__(self) -> str:
|
|
32
|
+
return self._child()
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import sys
|
|
2
|
+
import typing as ta
|
|
3
|
+
|
|
4
|
+
from omlish import check
|
|
5
|
+
from omlish import lang
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
with lang.auto_proxy_import(globals()):
|
|
9
|
+
from omlish.subprocesses import editor
|
|
10
|
+
from omlish.subprocesses import sync as sync_subprocesses
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
##
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class SyncStringInput(ta.Protocol):
|
|
17
|
+
def __call__(self) -> str: ...
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class InputSyncStringInput:
|
|
21
|
+
DEFAULT_PROMPT: ta.ClassVar[str] = '> '
|
|
22
|
+
|
|
23
|
+
def __init__(
|
|
24
|
+
self,
|
|
25
|
+
prompt: str | None = None,
|
|
26
|
+
*,
|
|
27
|
+
use_readline: bool | ta.Literal['auto'] = False,
|
|
28
|
+
) -> None:
|
|
29
|
+
super().__init__()
|
|
30
|
+
|
|
31
|
+
if prompt is None:
|
|
32
|
+
prompt = self.DEFAULT_PROMPT
|
|
33
|
+
self._prompt = prompt
|
|
34
|
+
self._use_readline = use_readline
|
|
35
|
+
|
|
36
|
+
self._handled_readline = False
|
|
37
|
+
|
|
38
|
+
def _handle_readline(self) -> None:
|
|
39
|
+
if self._handled_readline:
|
|
40
|
+
return
|
|
41
|
+
self._handled_readline = True
|
|
42
|
+
|
|
43
|
+
if not self._use_readline:
|
|
44
|
+
return
|
|
45
|
+
|
|
46
|
+
if self._use_readline == 'auto':
|
|
47
|
+
if not sys.stdin.isatty():
|
|
48
|
+
return
|
|
49
|
+
|
|
50
|
+
try:
|
|
51
|
+
import readline # noqa
|
|
52
|
+
except ImportError:
|
|
53
|
+
pass
|
|
54
|
+
|
|
55
|
+
def __call__(self) -> str:
|
|
56
|
+
self._handle_readline()
|
|
57
|
+
return input(self._prompt)
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
class FileSyncStringInput(InputSyncStringInput):
|
|
61
|
+
def __init__(self, path: str) -> None:
|
|
62
|
+
super().__init__()
|
|
63
|
+
|
|
64
|
+
self._path = check.non_empty_str(path)
|
|
65
|
+
|
|
66
|
+
def __call__(self) -> str:
|
|
67
|
+
with open(self._path) as f:
|
|
68
|
+
return f.read()
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
class UserEditorSyncStringInput(InputSyncStringInput):
|
|
72
|
+
def __call__(self) -> str:
|
|
73
|
+
if (ec := editor.edit_text_with_user_editor('', sync_subprocesses.subprocesses)) is None:
|
|
74
|
+
raise EOFError
|
|
75
|
+
return ec
|
ommlds/cli/main.py
CHANGED
|
@@ -1,188 +1,331 @@
|
|
|
1
1
|
"""
|
|
2
|
-
|
|
3
|
-
-
|
|
4
|
-
- https://github.com/TheR1D/shell_gpt
|
|
5
|
-
- https://github.com/paul-gauthier/aider
|
|
2
|
+
TODO:
|
|
3
|
+
- bootstrap lol
|
|
6
4
|
"""
|
|
7
|
-
import
|
|
5
|
+
import abc
|
|
8
6
|
import functools
|
|
9
|
-
import os.path
|
|
10
|
-
import sys
|
|
11
7
|
import typing as ta
|
|
12
8
|
|
|
13
9
|
import anyio
|
|
14
10
|
|
|
15
|
-
from omdev.home.secrets import load_secrets
|
|
16
11
|
from omlish import check
|
|
12
|
+
from omlish import dataclasses as dc
|
|
17
13
|
from omlish import inject as inj
|
|
18
14
|
from omlish import lang
|
|
19
|
-
from omlish.
|
|
15
|
+
from omlish.argparse import all as ap
|
|
20
16
|
from omlish.logs import all as logs
|
|
21
|
-
from omlish.subprocesses.editor import edit_text_with_user_editor
|
|
22
|
-
from omlish.subprocesses.sync import subprocesses
|
|
23
17
|
|
|
24
|
-
from .. import minichain as mc
|
|
25
18
|
from .inject import bind_main
|
|
19
|
+
from .secrets import install_secrets
|
|
26
20
|
from .sessions.base import Session
|
|
27
21
|
from .sessions.chat.configs import ChatConfig
|
|
28
22
|
from .sessions.completion.configs import CompletionConfig
|
|
29
23
|
from .sessions.embedding.configs import EmbeddingConfig
|
|
30
24
|
|
|
31
25
|
|
|
32
|
-
if ta.TYPE_CHECKING:
|
|
33
|
-
import PIL.Image as pimg # noqa
|
|
34
|
-
else:
|
|
35
|
-
pimg = lang.proxy_import('PIL.Image')
|
|
36
|
-
|
|
37
|
-
|
|
38
26
|
##
|
|
39
27
|
|
|
40
28
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
29
|
+
MAIN_EXTRA_ARGS: ta.Sequence[ap.Arg] = [
|
|
30
|
+
ap.arg('-v', '--verbose', action='store_true'),
|
|
31
|
+
]
|
|
44
32
|
|
|
45
|
-
parser.add_argument('-b', '--backend', default='openai')
|
|
46
33
|
|
|
47
|
-
|
|
34
|
+
def _process_main_extra_args(args: ap.Namespace) -> None:
|
|
35
|
+
if args.verbose:
|
|
36
|
+
logs.configure_standard_logging('DEBUG')
|
|
37
|
+
else:
|
|
38
|
+
logs.configure_standard_logging('INFO')
|
|
39
|
+
logs.silence_noisy_loggers()
|
|
48
40
|
|
|
49
|
-
parser.add_argument('-C', '--completion', action='store_true')
|
|
50
41
|
|
|
51
|
-
|
|
52
|
-
parser.add_argument('--ephemeral', action='store_true')
|
|
42
|
+
##
|
|
53
43
|
|
|
54
|
-
parser.add_argument('-e', '--editor', action='store_true')
|
|
55
|
-
parser.add_argument('-i', '--interactive', action='store_true')
|
|
56
|
-
parser.add_argument('-c', '--code', action='store_true')
|
|
57
|
-
parser.add_argument('-s', '--stream', action='store_true')
|
|
58
|
-
parser.add_argument('-M', '--markdown', action='store_true')
|
|
59
44
|
|
|
60
|
-
|
|
61
|
-
|
|
45
|
+
class Profile(lang.Abstract):
|
|
46
|
+
@abc.abstractmethod
|
|
47
|
+
def run(self, argv: ta.Sequence[str]) -> ta.Awaitable[None]:
|
|
48
|
+
raise NotImplementedError
|
|
62
49
|
|
|
63
|
-
parser.add_argument('-v', '--verbose', action='store_true')
|
|
64
50
|
|
|
65
|
-
|
|
66
|
-
parser.add_argument('--enable-todo-tools', action='store_true')
|
|
67
|
-
parser.add_argument('--enable-unsafe-tools-do-not-use-lol', action='store_true')
|
|
68
|
-
parser.add_argument('--enable-test-weather-tool', action='store_true')
|
|
69
|
-
parser.add_argument('--dangerous-no-tool-confirmation', action='store_true')
|
|
51
|
+
##
|
|
70
52
|
|
|
71
|
-
args = parser.parse_args(args)
|
|
72
53
|
|
|
73
|
-
|
|
54
|
+
# class ChatAspect(lang.Abstract):
|
|
55
|
+
# def get_parser_args(self) -> ta.Sequence[ap.Arg]: ...
|
|
56
|
+
# def set_args(self, args: ap.Namespace) -> None: ...
|
|
57
|
+
# def configure(self, cfg: ChatConfig) -> ChatConfig: ...
|
|
74
58
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
logs.configure_standard_logging('INFO')
|
|
79
|
-
logs.silence_noisy_loggers()
|
|
59
|
+
|
|
60
|
+
class ChatProfile(Profile):
|
|
61
|
+
_args: ap.Namespace
|
|
80
62
|
|
|
81
63
|
#
|
|
82
64
|
|
|
83
|
-
|
|
65
|
+
BACKEND_ARGS: ta.ClassVar[ta.Sequence[ap.Arg]] = [
|
|
66
|
+
ap.arg('-b', '--backend', group='backend'),
|
|
67
|
+
]
|
|
84
68
|
|
|
85
|
-
|
|
86
|
-
|
|
69
|
+
def configure_backend(self, cfg: ChatConfig) -> ChatConfig:
|
|
70
|
+
return dc.replace(
|
|
71
|
+
cfg,
|
|
72
|
+
backend=dc.replace(
|
|
73
|
+
cfg.backend,
|
|
74
|
+
backend=self._args.backend,
|
|
75
|
+
),
|
|
76
|
+
)
|
|
87
77
|
|
|
88
|
-
|
|
89
|
-
check.arg(not args.prompt)
|
|
90
|
-
if (ec := edit_text_with_user_editor('', subprocesses)) is None:
|
|
91
|
-
return
|
|
92
|
-
content = ec
|
|
78
|
+
#
|
|
93
79
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
80
|
+
INPUT_ARGS: ta.ClassVar[ta.Sequence[ap.Arg]] = [
|
|
81
|
+
ap.arg('message', nargs='*', group='input'),
|
|
82
|
+
ap.arg('-i', '--interactive', action='store_true', group='input'),
|
|
83
|
+
ap.arg('-e', '--editor', action='store_true', group='input'),
|
|
84
|
+
]
|
|
85
|
+
|
|
86
|
+
def configure_input(self, cfg: ChatConfig) -> ChatConfig:
|
|
87
|
+
if self._args.editor:
|
|
88
|
+
check.arg(not self._args.interactive)
|
|
89
|
+
check.arg(not self._args.message)
|
|
90
|
+
raise NotImplementedError
|
|
91
|
+
|
|
92
|
+
elif self._args.interactive:
|
|
93
|
+
check.arg(not self._args.message)
|
|
94
|
+
return dc.replace(
|
|
95
|
+
cfg,
|
|
96
|
+
user=dc.replace(
|
|
97
|
+
cfg.user,
|
|
98
|
+
interactive=True,
|
|
99
|
+
),
|
|
100
|
+
)
|
|
101
|
+
|
|
102
|
+
elif self._args.message:
|
|
103
|
+
# TODO: '-' -> stdin
|
|
104
|
+
return dc.replace(
|
|
105
|
+
cfg,
|
|
106
|
+
user=dc.replace(
|
|
107
|
+
cfg.user,
|
|
108
|
+
initial_user_content=' '.join(self._args.message),
|
|
109
|
+
),
|
|
110
|
+
)
|
|
98
111
|
|
|
99
|
-
elif args.code:
|
|
100
|
-
if args.prompt:
|
|
101
|
-
content = ' '.join(args.prompt)
|
|
102
112
|
else:
|
|
103
|
-
|
|
113
|
+
raise ValueError('Must specify input')
|
|
104
114
|
|
|
105
|
-
|
|
106
|
-
raise ValueError('Must provide prompt')
|
|
115
|
+
#
|
|
107
116
|
|
|
108
|
-
|
|
109
|
-
|
|
117
|
+
STATE_ARGS: ta.ClassVar[ta.Sequence[ap.Arg]] = [
|
|
118
|
+
ap.arg('-n', '--new', action='store_true', group='state'),
|
|
119
|
+
ap.arg('--ephemeral', action='store_true', group='state'),
|
|
120
|
+
]
|
|
121
|
+
|
|
122
|
+
def configure_state(self, cfg: ChatConfig) -> ChatConfig:
|
|
123
|
+
return dc.replace(
|
|
124
|
+
cfg,
|
|
125
|
+
state=dc.replace(
|
|
126
|
+
cfg.state,
|
|
127
|
+
state='ephemeral' if self._args.ephemeral else 'new' if self._args.new else 'continue',
|
|
128
|
+
),
|
|
129
|
+
)
|
|
110
130
|
|
|
111
|
-
|
|
112
|
-
if not sys.stdin.isatty() and not pycharm.is_pycharm_hosted():
|
|
113
|
-
stdin_data = sys.stdin.read()
|
|
114
|
-
prompt = '\n'.join([prompt, stdin_data])
|
|
131
|
+
#
|
|
115
132
|
|
|
116
|
-
|
|
133
|
+
OUTPUT_ARGS: ta.ClassVar[ta.Sequence[ap.Arg]] = [
|
|
134
|
+
ap.arg('-s', '--stream', action='store_true', group='output'),
|
|
135
|
+
ap.arg('-M', '--markdown', action='store_true', group='output'),
|
|
136
|
+
]
|
|
137
|
+
|
|
138
|
+
def configure_output(self, cfg: ChatConfig) -> ChatConfig:
|
|
139
|
+
return dc.replace(
|
|
140
|
+
cfg,
|
|
141
|
+
ai=dc.replace(
|
|
142
|
+
cfg.ai,
|
|
143
|
+
stream=bool(self._args.stream),
|
|
144
|
+
),
|
|
145
|
+
rendering=dc.replace(
|
|
146
|
+
cfg.rendering,
|
|
147
|
+
markdown=bool(self._args.markdown),
|
|
148
|
+
),
|
|
149
|
+
)
|
|
117
150
|
|
|
118
151
|
#
|
|
119
152
|
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
'
|
|
123
|
-
'
|
|
124
|
-
'
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
153
|
+
TOOLS_ARGS: ta.ClassVar[ta.Sequence[ap.Arg]] = [
|
|
154
|
+
ap.arg('--enable-fs-tools', action='store_true', group='tools'),
|
|
155
|
+
ap.arg('--enable-todo-tools', action='store_true', group='tools'),
|
|
156
|
+
# ap.arg('--enable-unsafe-tools-do-not-use-lol', action='store_true', group='tools'),
|
|
157
|
+
ap.arg('--enable-test-weather-tool', action='store_true', group='tools'),
|
|
158
|
+
]
|
|
159
|
+
|
|
160
|
+
def configure_tools(self, cfg: ChatConfig) -> ChatConfig:
|
|
161
|
+
return dc.replace(
|
|
162
|
+
cfg,
|
|
163
|
+
ai=dc.replace(
|
|
164
|
+
cfg.ai,
|
|
165
|
+
enable_tools=(
|
|
166
|
+
self._args.enable_fs_tools or
|
|
167
|
+
self._args.enable_todo_tools or
|
|
168
|
+
# self._args.enable_unsafe_tools_do_not_use_lol or
|
|
169
|
+
self._args.enable_test_weather_tool or
|
|
170
|
+
self._args.code
|
|
171
|
+
),
|
|
172
|
+
),
|
|
173
|
+
tools=dc.replace(
|
|
174
|
+
cfg.tools,
|
|
175
|
+
enabled_tools={ # noqa
|
|
176
|
+
*(cfg.tools.enabled_tools or []),
|
|
177
|
+
*(['fs'] if self._args.enable_fs_tools else []),
|
|
178
|
+
*(['todo'] if self._args.enable_todo_tools else []),
|
|
179
|
+
*(['weather'] if self._args.enable_test_weather_tool else []),
|
|
180
|
+
},
|
|
181
|
+
),
|
|
182
|
+
)
|
|
131
183
|
|
|
132
184
|
#
|
|
133
185
|
|
|
134
|
-
|
|
186
|
+
CODE_CONFIG: ta.ClassVar[ta.Sequence[ap.Arg]] = [
|
|
187
|
+
ap.arg('-c', '--code', action='store_true', group='code'),
|
|
188
|
+
]
|
|
135
189
|
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
backend=args.backend,
|
|
140
|
-
)
|
|
190
|
+
def configure_code(self, cfg: ChatConfig) -> ChatConfig:
|
|
191
|
+
if not self._args.code:
|
|
192
|
+
return cfg
|
|
141
193
|
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
194
|
+
cfg = dc.replace(
|
|
195
|
+
cfg,
|
|
196
|
+
ai=dc.replace(
|
|
197
|
+
cfg.ai,
|
|
198
|
+
enable_tools=True,
|
|
199
|
+
),
|
|
146
200
|
)
|
|
147
201
|
|
|
148
|
-
|
|
149
|
-
system_content: mc.Content | None = None
|
|
150
|
-
if (args.new or args.ephemeral) and args.code:
|
|
202
|
+
if self._args.new or self._args.ephemeral:
|
|
151
203
|
from ..minichain.lib.code.prompts import CODE_AGENT_SYSTEM_PROMPT
|
|
152
204
|
system_content = CODE_AGENT_SYSTEM_PROMPT
|
|
153
205
|
|
|
154
|
-
|
|
206
|
+
cfg = dc.replace(
|
|
207
|
+
cfg,
|
|
208
|
+
user=dc.replace(
|
|
209
|
+
cfg.user,
|
|
210
|
+
initial_system_content=system_content,
|
|
211
|
+
),
|
|
212
|
+
)
|
|
213
|
+
|
|
214
|
+
return cfg
|
|
215
|
+
|
|
216
|
+
#
|
|
217
|
+
|
|
218
|
+
async def run(self, argv: ta.Sequence[str]) -> None:
|
|
219
|
+
parser = ap.ArgumentParser()
|
|
220
|
+
|
|
221
|
+
for grp_name, grp_args in [
|
|
222
|
+
('backend', self.BACKEND_ARGS),
|
|
223
|
+
('input', self.INPUT_ARGS),
|
|
224
|
+
('state', self.STATE_ARGS),
|
|
225
|
+
('output', self.OUTPUT_ARGS),
|
|
226
|
+
('tools', self.TOOLS_ARGS),
|
|
227
|
+
('code', self.CODE_CONFIG),
|
|
228
|
+
]:
|
|
229
|
+
grp = parser.add_argument_group(grp_name)
|
|
230
|
+
for a in grp_args:
|
|
231
|
+
grp.add_argument(*a.args, **a.kwargs)
|
|
232
|
+
|
|
233
|
+
self._args = parser.parse_args(argv)
|
|
234
|
+
|
|
235
|
+
cfg = ChatConfig()
|
|
236
|
+
cfg = self.configure_backend(cfg)
|
|
237
|
+
cfg = self.configure_input(cfg)
|
|
238
|
+
cfg = self.configure_state(cfg)
|
|
239
|
+
cfg = self.configure_output(cfg)
|
|
240
|
+
cfg = self.configure_tools(cfg)
|
|
241
|
+
cfg = self.configure_code(cfg)
|
|
242
|
+
|
|
243
|
+
with inj.create_managed_injector(bind_main(
|
|
244
|
+
session_cfg=cfg,
|
|
245
|
+
)) as injector:
|
|
246
|
+
await injector[Session].run()
|
|
247
|
+
|
|
248
|
+
|
|
249
|
+
##
|
|
250
|
+
|
|
251
|
+
|
|
252
|
+
class CompletionProfile(Profile):
|
|
253
|
+
async def run(self, argv: ta.Sequence[str]) -> None:
|
|
254
|
+
parser = ap.ArgumentParser()
|
|
255
|
+
parser.add_argument('prompt', nargs='*')
|
|
256
|
+
parser.add_argument('-b', '--backend', default='openai')
|
|
257
|
+
args = parser.parse_args(argv)
|
|
258
|
+
|
|
259
|
+
content = ' '.join(args.prompt)
|
|
260
|
+
|
|
261
|
+
cfg = CompletionConfig(
|
|
262
|
+
check.non_empty_str(content),
|
|
155
263
|
backend=args.backend,
|
|
156
|
-
model_name=args.model_name,
|
|
157
|
-
state='ephemeral' if args.ephemeral else 'new' if args.new else 'continue',
|
|
158
|
-
initial_system_content=system_content,
|
|
159
|
-
initial_user_content=content, # noqa
|
|
160
|
-
interactive=bool(args.interactive),
|
|
161
|
-
markdown=bool(args.markdown),
|
|
162
|
-
stream=bool(args.stream),
|
|
163
|
-
enable_tools=(
|
|
164
|
-
args.enable_fs_tools or
|
|
165
|
-
args.enable_todo_tools or
|
|
166
|
-
args.enable_unsafe_tools_do_not_use_lol or
|
|
167
|
-
args.enable_test_weather_tool or
|
|
168
|
-
args.code
|
|
169
|
-
),
|
|
170
|
-
enabled_tools={ # noqa
|
|
171
|
-
*(['fs'] if args.enable_fs_tools else []),
|
|
172
|
-
*(['todo'] if args.enable_todo_tools else []),
|
|
173
|
-
*(['weather'] if args.enable_test_weather_tool else []),
|
|
174
|
-
# FIXME: enable_unsafe_tools_do_not_use_lol
|
|
175
|
-
},
|
|
176
|
-
dangerous_no_tool_confirmation=bool(args.dangerous_no_tool_confirmation),
|
|
177
264
|
)
|
|
178
265
|
|
|
179
|
-
|
|
266
|
+
with inj.create_managed_injector(bind_main(
|
|
267
|
+
session_cfg=cfg,
|
|
268
|
+
)) as injector:
|
|
269
|
+
await injector[Session].run()
|
|
270
|
+
|
|
271
|
+
|
|
272
|
+
##
|
|
273
|
+
|
|
274
|
+
|
|
275
|
+
class EmbedProfile(Profile):
|
|
276
|
+
async def run(self, argv: ta.Sequence[str]) -> None:
|
|
277
|
+
parser = ap.ArgumentParser()
|
|
278
|
+
parser.add_argument('prompt', nargs='*')
|
|
279
|
+
parser.add_argument('-b', '--backend', default='openai')
|
|
280
|
+
args = parser.parse_args(argv)
|
|
281
|
+
|
|
282
|
+
content = ' '.join(args.prompt)
|
|
283
|
+
|
|
284
|
+
cfg = EmbeddingConfig(
|
|
285
|
+
check.non_empty_str(content),
|
|
286
|
+
backend=args.backend,
|
|
287
|
+
)
|
|
288
|
+
|
|
289
|
+
with inj.create_managed_injector(bind_main(
|
|
290
|
+
session_cfg=cfg,
|
|
291
|
+
)) as injector:
|
|
292
|
+
await injector[Session].run()
|
|
293
|
+
|
|
294
|
+
|
|
295
|
+
##
|
|
296
|
+
|
|
297
|
+
|
|
298
|
+
PROFILE_TYPES: ta.Mapping[str, type[Profile]] = {
|
|
299
|
+
'chat': ChatProfile,
|
|
300
|
+
'complete': CompletionProfile,
|
|
301
|
+
'embed': EmbedProfile,
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
|
|
305
|
+
##
|
|
306
|
+
|
|
307
|
+
|
|
308
|
+
MAIN_PROFILE_ARGS: ta.Sequence[ap.Arg] = [
|
|
309
|
+
ap.arg('-p', '--profile', default='chat'),
|
|
310
|
+
ap.arg('args', nargs=ap.REMAINDER),
|
|
311
|
+
]
|
|
312
|
+
|
|
313
|
+
|
|
314
|
+
async def _a_main(argv: ta.Any = None) -> None:
|
|
315
|
+
parser = ap.ArgumentParser()
|
|
316
|
+
|
|
317
|
+
for a in [*MAIN_PROFILE_ARGS, *MAIN_EXTRA_ARGS]:
|
|
318
|
+
parser.add_argument(*a.args, **a.kwargs)
|
|
319
|
+
|
|
320
|
+
args, unk_args = parser.parse_known_args(argv)
|
|
321
|
+
|
|
322
|
+
_process_main_extra_args(args)
|
|
323
|
+
|
|
324
|
+
install_secrets()
|
|
180
325
|
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
)) as injector:
|
|
185
|
-
await injector[Session].run()
|
|
326
|
+
profile_cls = PROFILE_TYPES[args.profile]
|
|
327
|
+
profile = profile_cls()
|
|
328
|
+
await profile.run([*unk_args, *args.args])
|
|
186
329
|
|
|
187
330
|
|
|
188
331
|
def _main(args: ta.Any = None) -> None:
|
|
@@ -191,7 +334,6 @@ def _main(args: ta.Any = None) -> None:
|
|
|
191
334
|
_a_main,
|
|
192
335
|
args,
|
|
193
336
|
),
|
|
194
|
-
# backend='trio',
|
|
195
337
|
) # noqa
|
|
196
338
|
|
|
197
339
|
|
|
File without changes
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
from omlish import inject as inj
|
|
2
2
|
from omlish import lang
|
|
3
3
|
|
|
4
|
+
from .configs import RenderingConfig
|
|
5
|
+
|
|
4
6
|
|
|
5
7
|
with lang.auto_proxy_import(globals()):
|
|
6
8
|
from . import markdown as _markdown
|
|
@@ -11,13 +13,10 @@ with lang.auto_proxy_import(globals()):
|
|
|
11
13
|
##
|
|
12
14
|
|
|
13
15
|
|
|
14
|
-
def bind_rendering(
|
|
15
|
-
*,
|
|
16
|
-
markdown: bool = False,
|
|
17
|
-
) -> inj.Elements:
|
|
16
|
+
def bind_rendering(cfg: RenderingConfig = RenderingConfig()) -> inj.Elements:
|
|
18
17
|
els: list[inj.Elemental] = []
|
|
19
18
|
|
|
20
|
-
if markdown:
|
|
19
|
+
if cfg.markdown:
|
|
21
20
|
els.extend([
|
|
22
21
|
inj.bind(_types.ContentRendering, to_ctor=_markdown.MarkdownContentRendering, singleton=True),
|
|
23
22
|
inj.bind(_types.StreamContentRendering, to_ctor=_markdown.MarkdownStreamContentRendering, singleton=True),
|
|
@@ -3,7 +3,7 @@ import typing as ta
|
|
|
3
3
|
from omdev.tui import rich
|
|
4
4
|
from omlish import lang
|
|
5
5
|
|
|
6
|
-
from
|
|
6
|
+
from ... import minichain as mc
|
|
7
7
|
from ..content.strings import ContentStringifier
|
|
8
8
|
from ..content.strings import HasContentStringifier
|
|
9
9
|
from .types import ContentRendering
|