@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.
@@ -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
- import("../dist/cli.js").catch((error) => {
4
- console.error(error);
5
- process.exitCode = 1;
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
+ }
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  runRawSyncOnce
3
- } from "./chunk-JPHN4VKM.js";
3
+ } from "./chunk-PTDADW47.js";
4
4
  import {
5
5
  resolvePackageRoot
6
6
  } from "./chunk-F57IFY3K.js";