grix-connector 2.0.2 → 2.0.4

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.
@@ -1 +1 @@
1
- function a(t){const o=new Set([`http://127.0.0.1:${t.serverPort}`,`http://localhost:${t.serverPort}`,...t.allowedOrigins]),e=new Set([`127.0.0.1:${t.serverPort}`,`localhost:${t.serverPort}`,...t.allowedHosts]);return{validateRequest(s){const r=i(s,o);if(!r.ok)return r;const n=l(s,e);return n.ok?{ok:!0}:n}}}function i(t,o){const e=t.headers.origin;return e?o.has(e)?{ok:!0}:{ok:!1,statusCode:403,message:`Origin not allowed: ${e}`}:{ok:!0}}function l(t,o){const e=t.headers.host;return e?o.has(e)?{ok:!0}:{ok:!1,statusCode:403,message:`Host not allowed: ${e}`}:{ok:!1,statusCode:403,message:"Missing Host header"}}export{a as createSecurityPolicy};
1
+ function a(o){const e=new Set([`http://127.0.0.1:${o.serverPort}`,`http://localhost:${o.serverPort}`,...o.allowedOrigins]),t=new Set([`127.0.0.1:${o.serverPort}`,`localhost:${o.serverPort}`,...o.allowedHosts]);return{validateRequest(s){const r=i(s,e);if(!r.ok)return r;const n=l(s,t);return n.ok?{ok:!0}:n}}}function i(o,e){const t=o.headers.origin;return t?e.has(t)?{ok:!0}:{ok:!1,statusCode:403,message:`Origin not allowed: ${t}`}:{ok:!0}}function l(o,e){const t=o.headers.host;return t?e.has(t)?{ok:!0}:{ok:!1,statusCode:403,message:`Host not allowed: ${t}`}:{ok:!1,statusCode:403,message:"Missing Host header"}}export{a as createSecurityPolicy};
@@ -9081,7 +9081,7 @@ var TOOLS = [
9081
9081
  },
9082
9082
  {
9083
9083
  name: "grix_session_send",
9084
- description: "Send a message into a session as the owner (not as yourself). Use this to speak on the owner's behalf in a session the owner is a member of. The owner must be a member of the target session.",
9084
+ description: "Send a message into a session AS THE OWNER \u2014 it appears as if the owner sent it, NOT as you (the agent). Use ONLY to relay on the owner's behalf into one of the owner's OTHER sessions that you are not part of (e.g. you were dispatched to work and need to drop a note to the owner elsewhere). NEVER use this to send your own reply in a session you are conversing in \u2014 that would make your words show up as the owner's message. To answer in your current conversation, reply normally (or use grix_message_send to send as yourself). The owner must be a member of the target session, and you (the agent) must NOT be a member of it \u2014 sending into a session you belong to is rejected.",
9085
9085
  inputSchema: {
9086
9086
  type: "object",
9087
9087
  properties: {
@@ -9114,7 +9114,7 @@ var TOOLS = [
9114
9114
  var EVENT_TOOLS = [
9115
9115
  {
9116
9116
  name: "grix_reply",
9117
- description: "Send a reply message to the specified session. Supports streaming in chunks; the frontend will automatically aggregate them into one complete message.",
9117
+ description: "Send a reply message to the specified session. Supports streaming in chunks; the frontend will automatically aggregate them into one complete message. Any content meant for the user \u2014 including your final conclusion at the end of a turn \u2014 MUST be sent through this tool; text written outside this tool is not delivered to the user.",
9118
9118
  inputSchema: {
9119
9119
  type: "object",
9120
9120
  properties: {
@@ -11699,6 +11699,32 @@ var IMAGE_MIME = {
11699
11699
  function imageMimeType(fileName) {
11700
11700
  return IMAGE_MIME[path5.extname(fileName).toLowerCase()];
11701
11701
  }
11702
+ var VIDEO_MIME = {
11703
+ ".mp4": "video/mp4",
11704
+ ".m4v": "video/mp4",
11705
+ ".mov": "video/quicktime",
11706
+ ".webm": "video/webm",
11707
+ ".ogv": "video/ogg",
11708
+ ".mkv": "video/x-matroska",
11709
+ ".avi": "video/x-msvideo",
11710
+ ".3gp": "video/3gpp",
11711
+ ".ts": "video/mp2t"
11712
+ };
11713
+ var AUDIO_MIME = {
11714
+ ".mp3": "audio/mpeg",
11715
+ ".m4a": "audio/mp4",
11716
+ ".aac": "audio/aac",
11717
+ ".wav": "audio/wav",
11718
+ ".ogg": "audio/ogg",
11719
+ ".oga": "audio/ogg",
11720
+ ".opus": "audio/opus",
11721
+ ".flac": "audio/flac",
11722
+ ".weba": "audio/webm"
11723
+ };
11724
+ function inlineMimeType(fileName) {
11725
+ const ext = path5.extname(fileName).toLowerCase();
11726
+ return IMAGE_MIME[ext] ?? VIDEO_MIME[ext] ?? AUDIO_MIME[ext];
11727
+ }
11702
11728
  var DEFAULT_TTL_MS = 10 * 60 * 1e3;
11703
11729
  var entries = /* @__PURE__ */ new Map();
11704
11730
  var server = null;
@@ -11723,15 +11749,49 @@ async function startServer(host) {
11723
11749
  res.end("not found");
11724
11750
  return;
11725
11751
  }
11726
- res.statusCode = 200;
11727
- const mime = imageMimeType(entry.fileName);
11752
+ const mime = inlineMimeType(entry.fileName);
11728
11753
  res.setHeader("Content-Type", mime ?? "application/octet-stream");
11729
- res.setHeader("Content-Length", String(entry.size));
11730
11754
  res.setHeader(
11731
11755
  "Content-Disposition",
11732
- mime ? `inline; filename*=UTF-8''${encodeURIComponent(entry.fileName)}` : `attachment; filename*=UTF-8''${encodeURIComponent(entry.fileName)}`
11756
+ `${mime ? "inline" : "attachment"}; filename*=UTF-8''${encodeURIComponent(entry.fileName)}`
11733
11757
  );
11734
- const stream = fs.createReadStream(entry.filePath);
11758
+ res.setHeader("Accept-Ranges", "bytes");
11759
+ const total = entry.size;
11760
+ let start = 0;
11761
+ let end = total - 1;
11762
+ const rangeHeader = req.headers.range;
11763
+ if (rangeHeader) {
11764
+ const m = /^bytes=(\d*)-(\d*)$/.exec(String(rangeHeader).trim());
11765
+ if (!m || m[1] === "" && m[2] === "") {
11766
+ res.statusCode = 416;
11767
+ res.setHeader("Content-Range", `bytes */${total}`);
11768
+ res.end();
11769
+ return;
11770
+ }
11771
+ if (m[1] === "") {
11772
+ const suffix = Number(m[2]);
11773
+ start = suffix >= total ? 0 : total - suffix;
11774
+ } else {
11775
+ start = Number(m[1]);
11776
+ end = m[2] === "" ? total - 1 : Math.min(Number(m[2]), total - 1);
11777
+ }
11778
+ if (start > end || start >= total) {
11779
+ res.statusCode = 416;
11780
+ res.setHeader("Content-Range", `bytes */${total}`);
11781
+ res.end();
11782
+ return;
11783
+ }
11784
+ res.statusCode = 206;
11785
+ res.setHeader("Content-Range", `bytes ${start}-${end}/${total}`);
11786
+ } else {
11787
+ res.statusCode = 200;
11788
+ }
11789
+ res.setHeader("Content-Length", String(end - start + 1));
11790
+ if (req.method === "HEAD") {
11791
+ res.end();
11792
+ return;
11793
+ }
11794
+ const stream = fs.createReadStream(entry.filePath, { start, end });
11735
11795
  stream.on("error", () => {
11736
11796
  if (!res.headersSent) res.statusCode = 500;
11737
11797
  res.end();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "grix-connector",
3
- "version": "2.0.2",
3
+ "version": "2.0.4",
4
4
  "description": "Connect local AI coding agents (Claude, Codex, Gemini, Qwen, DeepSeek, Cursor, OpenCode, Pi, OpenHuman, Reasonix) to the Grix scheduling platform. Also serves as an OpenClaw plugin for Grix channel transport.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",