runline 0.15.0 → 0.15.1
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/dist/core/engine.d.ts +8 -0
- package/dist/core/engine.js +20 -1
- package/dist/plugin/api.js +27 -2
- package/package.json +1 -1
package/dist/core/engine.d.ts
CHANGED
|
@@ -37,5 +37,13 @@ export declare class ExecutionEngine {
|
|
|
37
37
|
constructor(registry: PluginRegistry, config: RunlineConfig);
|
|
38
38
|
execute(code: string, options?: EngineOptions): Promise<ExecuteResult>;
|
|
39
39
|
private invokeAction;
|
|
40
|
+
/**
|
|
41
|
+
* A miss on "salesforce.status" is often a plugin that registered
|
|
42
|
+
* its action name with the plugin prefix ("salesforce.status" inside
|
|
43
|
+
* plugin "salesforce"), making the real path
|
|
44
|
+
* "salesforce.salesforce.status". Detect exactly that shape and
|
|
45
|
+
* teach the caller — agents read error messages and self-correct.
|
|
46
|
+
*/
|
|
47
|
+
private selfPrefixHint;
|
|
40
48
|
private resolveConnection;
|
|
41
49
|
}
|
package/dist/core/engine.js
CHANGED
|
@@ -158,7 +158,7 @@ export class ExecutionEngine {
|
|
|
158
158
|
async invokeAction(path, args) {
|
|
159
159
|
const resolved = this.registry.resolveAction(path);
|
|
160
160
|
if (!resolved) {
|
|
161
|
-
throw new Error(`Unknown action: ${path}`);
|
|
161
|
+
throw new Error(`Unknown action: ${path}${this.selfPrefixHint(path)}`);
|
|
162
162
|
}
|
|
163
163
|
const { plugin, action } = resolved;
|
|
164
164
|
const connection = this.resolveConnection(plugin);
|
|
@@ -184,6 +184,25 @@ export class ExecutionEngine {
|
|
|
184
184
|
}
|
|
185
185
|
return action.execute(args, ctx);
|
|
186
186
|
}
|
|
187
|
+
/**
|
|
188
|
+
* A miss on "salesforce.status" is often a plugin that registered
|
|
189
|
+
* its action name with the plugin prefix ("salesforce.status" inside
|
|
190
|
+
* plugin "salesforce"), making the real path
|
|
191
|
+
* "salesforce.salesforce.status". Detect exactly that shape and
|
|
192
|
+
* teach the caller — agents read error messages and self-correct.
|
|
193
|
+
*/
|
|
194
|
+
selfPrefixHint(path) {
|
|
195
|
+
// A dot-less miss can still be the exact-name case: plugin "ping"
|
|
196
|
+
// registering action "ping" makes the callable path "ping.ping".
|
|
197
|
+
const dot = path.indexOf(".");
|
|
198
|
+
const pluginName = dot < 0 ? path : path.slice(0, dot);
|
|
199
|
+
const doubled = `${pluginName}.${path}`;
|
|
200
|
+
if (!this.registry.resolveAction(doubled))
|
|
201
|
+
return "";
|
|
202
|
+
return (`. Did you mean "${doubled}"? Plugin "${pluginName}" registered its ` +
|
|
203
|
+
`action name with the plugin prefix ("${path}"), so the full callable ` +
|
|
204
|
+
`path is "${doubled}".`);
|
|
205
|
+
}
|
|
187
206
|
resolveConnection(plugin) {
|
|
188
207
|
const conn = this.config.connections.find((c) => c.plugin === plugin.name);
|
|
189
208
|
const base = conn ?? {
|
package/dist/plugin/api.js
CHANGED
|
@@ -59,14 +59,39 @@ export function createPluginAPI(pluginId) {
|
|
|
59
59
|
export function isPluginFunction(val) {
|
|
60
60
|
return typeof val === "function";
|
|
61
61
|
}
|
|
62
|
+
/**
|
|
63
|
+
* Action names are plugin-relative: plugin "salesforce" registering
|
|
64
|
+
* "salesforce.status" is callable as "salesforce.salesforce.status",
|
|
65
|
+
* which is almost never what the author meant. Warn at resolve time —
|
|
66
|
+
* the earliest point where both the final plugin name and the full
|
|
67
|
+
* action list are known (setName may be called after registerAction,
|
|
68
|
+
* and object exports never go through createPluginAPI).
|
|
69
|
+
*/
|
|
70
|
+
function warnSelfPrefixedActions(plugin) {
|
|
71
|
+
for (const action of plugin.actions) {
|
|
72
|
+
const prefixed = action.name.startsWith(`${plugin.name}.`);
|
|
73
|
+
if (!prefixed && action.name !== plugin.name)
|
|
74
|
+
continue;
|
|
75
|
+
const advice = prefixed
|
|
76
|
+
? `Rename the action to "${action.name.slice(plugin.name.length + 1)}".`
|
|
77
|
+
: "Choose an action name that does not repeat the plugin name.";
|
|
78
|
+
console.warn(`[runline] Plugin "${plugin.name}" registered action "${action.name}", which repeats the plugin name. ` +
|
|
79
|
+
`Action names are plugin-relative, so this action is callable as "${plugin.name}.${action.name}" — ` +
|
|
80
|
+
`not "${action.name}". ${advice}`);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
62
83
|
export function resolvePluginExport(exported, pluginId) {
|
|
63
84
|
if (isPluginFunction(exported)) {
|
|
64
85
|
const { api, resolve } = createPluginAPI(pluginId);
|
|
65
86
|
exported(api);
|
|
66
|
-
|
|
87
|
+
const plugin = resolve();
|
|
88
|
+
warnSelfPrefixedActions(plugin);
|
|
89
|
+
return plugin;
|
|
67
90
|
}
|
|
68
91
|
if (exported && typeof exported === "object" && "actions" in exported) {
|
|
69
|
-
|
|
92
|
+
const plugin = exported;
|
|
93
|
+
warnSelfPrefixedActions(plugin);
|
|
94
|
+
return plugin;
|
|
70
95
|
}
|
|
71
96
|
throw new Error(`Invalid plugin export from "${pluginId}": expected a function or { name, actions } object`);
|
|
72
97
|
}
|