@fml-inc/fml 0.8.9 → 0.8.10
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/.claude-plugin/plugin.json +1 -1
- package/README.md +114 -3
- package/agent-assets/mini-swe-agent/FML_WORKFLOW.md +62 -0
- package/agent-assets/mini-swe-agent/fml_mini_agent.py +483 -0
- package/agent-assets/mini-swe-agent/fml_mini_bootstrap.py +141 -0
- package/bin/fml +18 -4
- package/dist/{chunk-2DGHAVVR.js → chunk-OUXFHL3I.js} +1 -1
- package/dist/{chunk-JPHN4VKM.js → chunk-PTDADW47.js} +197 -94
- package/dist/{chunk-TWJ62CZX.js → chunk-U4BM27VN.js} +1 -1
- package/dist/{chunk-H5LWJ5PH.js → chunk-XB7EIDWY.js} +123 -67
- package/dist/cli.js +4608 -3883
- package/dist/hook-handler.js +39 -11
- package/dist/mcp/server.js +5 -5
- package/dist/observer-server.js +51 -11
- package/dist/pi/extension.js +17 -4
- package/dist/sync-cycle.js +2 -2
- package/package.json +2 -2
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
# <!-- fml-managed-agent-surface:v1 -->
|
|
2
|
+
"""Interpreter-local, fail-open activation for the native mini CLI only.
|
|
3
|
+
|
|
4
|
+
Imported by the owned .pth on Python startup. Ordinary Python invocations do
|
|
5
|
+
not import mini, read its configuration, or install an import hook. Native mini
|
|
6
|
+
still resolves all configuration itself on every invocation.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
import sys
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def _explicit_override(arguments):
|
|
13
|
+
values = {"--model", "--model-class", "--environment-class",
|
|
14
|
+
"--task", "--cost-limit", "--output"}
|
|
15
|
+
skip = False
|
|
16
|
+
for argument in arguments:
|
|
17
|
+
if skip:
|
|
18
|
+
skip = False
|
|
19
|
+
continue
|
|
20
|
+
if argument == "--":
|
|
21
|
+
break
|
|
22
|
+
if (argument in ("--config", "--agent-class")
|
|
23
|
+
or argument.startswith(("--config=", "--agent-class="))):
|
|
24
|
+
return True
|
|
25
|
+
skip = argument in values
|
|
26
|
+
if argument.startswith("-") and not argument.startswith("--"):
|
|
27
|
+
# Native mini has one short flag (-y); -c/-m/-t/-l/-o take values.
|
|
28
|
+
# Click consumes the rest of a cluster, or the next argv, as a value.
|
|
29
|
+
for index, option in enumerate(argument[1:], 2):
|
|
30
|
+
if option == "c":
|
|
31
|
+
return True
|
|
32
|
+
if option in "mtlo":
|
|
33
|
+
skip = index == len(argument)
|
|
34
|
+
break
|
|
35
|
+
if option != "y":
|
|
36
|
+
break # Unknown short options stop native parsing too.
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def _native_cli():
|
|
40
|
+
original = getattr(sys, "orig_argv", ())
|
|
41
|
+
if sys.argv and sys.argv[0] == "-m" and "-m" in original:
|
|
42
|
+
index = original.index("-m")
|
|
43
|
+
return index + 1 < len(original) and original[index + 1] in (
|
|
44
|
+
"minisweagent", "minisweagent.__main__", "minisweagent.run.mini",
|
|
45
|
+
)
|
|
46
|
+
# Console scripts have their real script path in argv at site startup.
|
|
47
|
+
# Check the entrypoint rather than activating arbitrary programs named mini.
|
|
48
|
+
filename = sys.argv[0] if sys.argv else ""
|
|
49
|
+
if filename.replace("\\", "/").rsplit("/", 1)[-1] not in (
|
|
50
|
+
"mini", "mini.exe", "mini-script.py",
|
|
51
|
+
"mini-swe-agent", "mini-swe-agent.exe", "mini-swe-agent-script.py",
|
|
52
|
+
):
|
|
53
|
+
return False
|
|
54
|
+
try:
|
|
55
|
+
if filename.lower().endswith(".exe"):
|
|
56
|
+
# Windows pip launchers append a ZIP containing the same entrypoint.
|
|
57
|
+
import zipfile
|
|
58
|
+
with zipfile.ZipFile(filename) as script:
|
|
59
|
+
return b"from minisweagent.run.mini import app" in script.read("__main__.py")
|
|
60
|
+
with open(filename, "rb") as script:
|
|
61
|
+
return b"from minisweagent.run.mini import app" in script.read(8192)
|
|
62
|
+
except Exception:
|
|
63
|
+
return False
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
def _patch_agents(module):
|
|
67
|
+
native = module.get_agent
|
|
68
|
+
|
|
69
|
+
def get_agent(model, env, config, *, default_type=""):
|
|
70
|
+
adapted = config
|
|
71
|
+
try:
|
|
72
|
+
from minisweagent.agents.default import DefaultAgent
|
|
73
|
+
from minisweagent.agents.interactive import InteractiveAgent
|
|
74
|
+
from minisweagent.environments.local import LocalEnvironment
|
|
75
|
+
# Class identity, not inheritance: custom agents/environments remain native.
|
|
76
|
+
if type(env) is LocalEnvironment:
|
|
77
|
+
selected = module.get_agent_class(config.get("agent_class", default_type))
|
|
78
|
+
if selected is DefaultAgent or selected is InteractiveAgent:
|
|
79
|
+
from fml_mini_agent import FmlDefaultAgent, FmlInteractiveAgent
|
|
80
|
+
adapted = dict(config)
|
|
81
|
+
adapted["agent_class"] = (
|
|
82
|
+
"fml_mini_agent.FmlDefaultAgent" if selected is DefaultAgent
|
|
83
|
+
else "fml_mini_agent.FmlInteractiveAgent"
|
|
84
|
+
)
|
|
85
|
+
except Exception:
|
|
86
|
+
# An incompatible/missing adapter must not disable the native CLI.
|
|
87
|
+
adapted = config
|
|
88
|
+
return native(model, env, adapted, default_type=default_type)
|
|
89
|
+
|
|
90
|
+
module.get_agent = get_agent
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
def _activate(expected_prefix):
|
|
94
|
+
if not _native_cli() or _explicit_override(sys.argv[1:]):
|
|
95
|
+
return
|
|
96
|
+
# Other interpreters can inherit this .pth via system site-packages. Their
|
|
97
|
+
# executables may resolve to the same binary, but their prefixes are distinct.
|
|
98
|
+
import os
|
|
99
|
+
actual_prefix = os.path.normcase(os.path.realpath(sys.prefix))
|
|
100
|
+
selected_prefix = os.path.normcase(os.path.realpath(expected_prefix))
|
|
101
|
+
if actual_prefix != selected_prefix:
|
|
102
|
+
return
|
|
103
|
+
# All mini/config imports remain lazy; ordinary Python never reaches here.
|
|
104
|
+
from importlib.machinery import PathFinder
|
|
105
|
+
|
|
106
|
+
class Loader:
|
|
107
|
+
def __init__(self, native):
|
|
108
|
+
self.native = native
|
|
109
|
+
|
|
110
|
+
def __getattr__(self, name):
|
|
111
|
+
return getattr(self.native, name)
|
|
112
|
+
|
|
113
|
+
def create_module(self, spec):
|
|
114
|
+
return self.native.create_module(spec)
|
|
115
|
+
|
|
116
|
+
def exec_module(self, module):
|
|
117
|
+
self.native.exec_module(module)
|
|
118
|
+
try:
|
|
119
|
+
_patch_agents(module)
|
|
120
|
+
except Exception:
|
|
121
|
+
pass
|
|
122
|
+
|
|
123
|
+
class Finder:
|
|
124
|
+
def find_spec(self, fullname, path=None, target=None):
|
|
125
|
+
if fullname != "minisweagent.agents":
|
|
126
|
+
return None
|
|
127
|
+
spec = PathFinder.find_spec(fullname, path, target)
|
|
128
|
+
if spec is not None and spec.loader is not None:
|
|
129
|
+
spec.loader = Loader(spec.loader)
|
|
130
|
+
sys.meta_path.remove(self)
|
|
131
|
+
return spec
|
|
132
|
+
|
|
133
|
+
sys.meta_path.insert(0, Finder())
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
def activate(expected_prefix):
|
|
137
|
+
try:
|
|
138
|
+
_activate(expected_prefix)
|
|
139
|
+
except Exception:
|
|
140
|
+
# .pth startup must remain usable even after a partial upgrade/uninstall.
|
|
141
|
+
pass
|
package/bin/fml
CHANGED
|
@@ -1,6 +1,20 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
3
|
+
if (process.argv[2] === "hook") {
|
|
4
|
+
if (process.argv.includes("--help") || process.argv.includes("-h")) {
|
|
5
|
+
process.stdout.write(
|
|
6
|
+
"Usage: fml hook --target <target>\n\nCapture an agent callback from JSON stdin and return optional context JSON.\n",
|
|
7
|
+
);
|
|
8
|
+
} else {
|
|
9
|
+
import("../dist/hook-handler.js").catch(() => {
|
|
10
|
+
// Agent callbacks remain fail-open even when the integration is unavailable.
|
|
11
|
+
process.exitCode = 0;
|
|
12
|
+
process.stdout.write("{}");
|
|
13
|
+
});
|
|
14
|
+
}
|
|
15
|
+
} else {
|
|
16
|
+
import("../dist/cli.js").catch((error) => {
|
|
17
|
+
console.error(error);
|
|
18
|
+
process.exitCode = 1;
|
|
19
|
+
});
|
|
20
|
+
}
|