loopengine 0.1.57 → 0.1.58

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,25 @@
1
+ ---
2
+ name: composio-large-outputs
3
+ description: How to retrieve a gateway tool's real output when its result says storedInFile is true instead of returning the data inline.
4
+ ---
5
+
6
+ # Gateway tools with a large result
7
+
8
+ Some gateway tools (Composio-sourced ones in particular) return a small
9
+ pointer object instead of their real output when the actual result is
10
+ too large to return inline:
11
+
12
+ ```
13
+ {
14
+ "successful": true,
15
+ "storedInFile": true,
16
+ "tokenCount": 10234,
17
+ "outputFilePath": "/tmp/.../SOME_TOOL_OUTPUT_xxxxx.json"
18
+ }
19
+ ```
20
+
21
+ When you see `storedInFile: true` in a tool result, the real data is
22
+ **not** in that object — it's in the file at `outputFilePath`. Call
23
+ `system_read_file` with that exact path to retrieve the actual content
24
+ before answering. Don't guess at an answer, summarize from the pointer
25
+ alone, or claim you don't have the data — read the file first.
package/dist/index.d.ts CHANGED
@@ -55,7 +55,7 @@ export { globalConfigPageHtml } from './web/global-config-page.js';
55
55
  export { playgroundHtml } from './web/playground.js';
56
56
  export { readSkill, writeSkill, deleteSkill, SkillInvalidIdError, SkillNotFoundError } from './web/skills-admin.js';
57
57
  export type { SkillContent } from './web/skills-admin.js';
58
- export { listDeclaredEnvVars, setEnvVar, EnvVarNameError } from './web/env-admin.js';
58
+ export { listDeclaredEnvVars, setEnvVar, unsetEnvVar, EnvVarNameError } from './web/env-admin.js';
59
59
  export type { DeclaredEnvVar } from './web/env-admin.js';
60
60
  export { readActauthConfig, addActauthRule, updateActauthRule, removeActauthRule, setDefaultDecision, ActauthRuleExistsError, ActauthRuleNotFoundError, } from './web/actauth-admin.js';
61
61
  export type { ActauthRuleInput, ActauthConfigView } from './web/actauth-admin.js';
package/dist/index.js CHANGED
@@ -50,7 +50,7 @@ export { agentsListPageHtml } from './web/agents-list-page.js';
50
50
  export { globalConfigPageHtml } from './web/global-config-page.js';
51
51
  export { playgroundHtml } from './web/playground.js';
52
52
  export { readSkill, writeSkill, deleteSkill, SkillInvalidIdError, SkillNotFoundError } from './web/skills-admin.js';
53
- export { listDeclaredEnvVars, setEnvVar, EnvVarNameError } from './web/env-admin.js';
53
+ export { listDeclaredEnvVars, setEnvVar, unsetEnvVar, EnvVarNameError } from './web/env-admin.js';
54
54
  export { readActauthConfig, addActauthRule, updateActauthRule, removeActauthRule, setDefaultDecision, ActauthRuleExistsError, ActauthRuleNotFoundError, } from './web/actauth-admin.js';
55
55
  export { installAbility, upgradeAbility, listInstalledAbilities, backfillDependencies, AbilityManifestError, AbilityVersionError, AbilityCollisionError, AbilityAlreadyInstalledError, AbilityNotInstalledError, } from './bin/ability-manager.js';
56
56
  export { searchPublicAbilities, fetchLatestAbilityVersion } from './web/abilities-admin.js';
@@ -1202,6 +1202,14 @@ export const agentsConfigPageHtml = `<!doctype html>
1202
1202
  : v.multiline
1203
1203
  ? '<textarea name="value" rows="8" placeholder="' + (v.set ? 'unchanged unless you paste a new value' : 'paste the full value') + '" required></textarea>'
1204
1204
  : '<input type="' + (v.secret ? 'password' : 'text') + '" name="value" placeholder="' + (v.set ? 'unchanged unless you type a new value' : 'value') + '" required>';
1205
+ // Only offered once something is actually set — removing what's
1206
+ // already absent has nothing to do, and the button would just be
1207
+ // clutter for every var an operator hasn't touched yet (most of
1208
+ // them, on a freshly installed ability — see renderEnvConfigHtml's
1209
+ // own comment on why "not set" isn't itself treated as a problem).
1210
+ var removeHtml = v.set
1211
+ ? ' <button type="button" class="env-var-remove" data-name="' + escapeHtml(v.name) + '">Remove</button>'
1212
+ : '';
1205
1213
  return '<tr>' +
1206
1214
  '<td><code>' + escapeHtml(v.name) + '</code>' + sharedNote + '</td>' +
1207
1215
  '<td style="max-width:320px">' + escapeHtml(v.description || '') + '</td>' +
@@ -1209,7 +1217,7 @@ export const agentsConfigPageHtml = `<!doctype html>
1209
1217
  '<td><form class="add-source env-var-form" data-name="' + escapeHtml(v.name) + '">' +
1210
1218
  fieldHtml +
1211
1219
  '<button type="submit">Save</button>' +
1212
- '</form></td>' +
1220
+ '</form>' + removeHtml + '</td>' +
1213
1221
  '</tr>';
1214
1222
  }
1215
1223
 
@@ -1291,6 +1299,29 @@ export const agentsConfigPageHtml = `<!doctype html>
1291
1299
  });
1292
1300
  });
1293
1301
  }
1302
+ var removeButtons = content.querySelectorAll('.env-var-remove');
1303
+ for (var j = 0; j < removeButtons.length; j++) {
1304
+ removeButtons[j].addEventListener('click', function (ev) {
1305
+ var btn = ev.currentTarget;
1306
+ var varName = btn.getAttribute('data-name');
1307
+ // A destructive action (clearing a configured value, possibly a
1308
+ // secret nothing else has a copy of) gets the one confirm() this
1309
+ // whole tab uses — every other action here is a plain upsert,
1310
+ // nothing else to lose by clicking it again.
1311
+ if (!confirm('Remove ' + varName + '? Any tool/ability relying on it falls back to its own default (if it has one) or starts failing until it\'s set again.')) return;
1312
+ btn.disabled = true;
1313
+ fetch('/agents/' + encodeURIComponent(name) + '/env/' + encodeURIComponent(varName), { method: 'DELETE' })
1314
+ .then(function (r) { return r.json().then(function (j) { return { ok: r.ok, body: j }; }); })
1315
+ .then(function (result) {
1316
+ if (!result.ok) throw new Error(result.body.error || 'request failed');
1317
+ loadEnvTab(name);
1318
+ })
1319
+ .catch(function (err) {
1320
+ alert('Could not remove value: ' + err.message);
1321
+ btn.disabled = false;
1322
+ });
1323
+ });
1324
+ }
1294
1325
  }
1295
1326
 
1296
1327
  function applyEnvConfig(name, vars) {
@@ -57,3 +57,15 @@ export declare function listDeclaredEnvVars(agentName: string): DeclaredEnvVar[]
57
57
  * call this at all when `LOOPENGINE_ADMIN_AUTH` isn't set — this
58
58
  * function itself has no notion of HTTP auth, it just writes. */
59
59
  export declare function setEnvVar(name: string, value: string): void;
60
+ /** Removes NAME= entirely from the project's .env file (not just
61
+ * blanking its value — an empty string is itself a real, distinct
62
+ * value some vars would treat differently from "unset," e.g. falling
63
+ * through to a default only when truly absent) and clears it from
64
+ * *this* running process's own process.env immediately, the same
65
+ * "no restart needed" promise setEnvVar already makes. A no-op,
66
+ * not an error, when the var was never set in .env to begin with —
67
+ * same reasoning the DELETE route calling this treats a missing name
68
+ * as success rather than a 404: the end state ("not set") is identical
69
+ * either way, and the caller has no way to distinguish "I removed it"
70
+ * from "it was already gone" that would actually matter to them. */
71
+ export declare function unsetEnvVar(name: string): void;
@@ -134,3 +134,31 @@ export function setEnvVar(name, value) {
134
134
  writeFileSync(path, lines.join('\n') + '\n');
135
135
  process.env[name] = value;
136
136
  }
137
+ /** Removes NAME= entirely from the project's .env file (not just
138
+ * blanking its value — an empty string is itself a real, distinct
139
+ * value some vars would treat differently from "unset," e.g. falling
140
+ * through to a default only when truly absent) and clears it from
141
+ * *this* running process's own process.env immediately, the same
142
+ * "no restart needed" promise setEnvVar already makes. A no-op,
143
+ * not an error, when the var was never set in .env to begin with —
144
+ * same reasoning the DELETE route calling this treats a missing name
145
+ * as success rather than a 404: the end state ("not set") is identical
146
+ * either way, and the caller has no way to distinguish "I removed it"
147
+ * from "it was already gone" that would actually matter to them. */
148
+ export function unsetEnvVar(name) {
149
+ if (!ENV_VAR_NAME_PATTERN.test(name)) {
150
+ throw new EnvVarNameError(`"${name}" isn't a valid env var name (uppercase letters, digits, underscore, not starting with a digit).`);
151
+ }
152
+ const path = envFilePath();
153
+ if (existsSync(path)) {
154
+ const lines = readFileSync(path, 'utf8').split('\n');
155
+ const filtered = lines.filter((line) => !line.startsWith(`${name}=`));
156
+ // Only rewrites the file when something actually changed — a
157
+ // no-op removal shouldn't still touch the file's own mtime/trailing-
158
+ // newline shape for no reason. Matches setEnvVar's own exactly-one-
159
+ // trailing-newline convention when it does.
160
+ if (filtered.length !== lines.length)
161
+ writeFileSync(path, filtered.join('\n').replace(/\n*$/, '\n'));
162
+ }
163
+ delete process.env[name];
164
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "loopengine",
3
- "version": "0.1.57",
3
+ "version": "0.1.58",
4
4
  "type": "module",
5
5
  "description": "Runtime for tool-using AI agents with a transparent ReAct loop.",
6
6
  "license": "MIT",