@marimo-team/frontend 0.20.5-dev19 → 0.20.5-dev20
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/assets/{add-cell-with-ai-BK9zCuNy.js → add-cell-with-ai-n1W-BSLf.js} +28 -26
- package/dist/assets/{agent-panel-DHwIjihK.js → agent-panel-C4ReXyY-.js} +1 -1
- package/dist/assets/{cell-editor-B2FqB6tW.js → cell-editor-DQFDo_RG.js} +1 -1
- package/dist/assets/{chat-display-BcoYsiMy.js → chat-display-UjJ3dstS.js} +1 -1
- package/dist/assets/{chat-panel-CMpcjtJu.js → chat-panel-vsvgmMju.js} +1 -1
- package/dist/assets/{edit-page-CX2XiE7U.js → edit-page-DP78KheM.js} +3 -3
- package/dist/assets/{index-6M2A6jg9.js → index-CKAAJr4G.js} +3 -3
- package/dist/assets/{scratchpad-panel-Ba9QTbWc.js → scratchpad-panel-qV3cJDWg.js} +1 -1
- package/dist/index.html +3 -3
- package/package.json +1 -1
- package/src/core/ai/tools/__tests__/run-cells-tool.test.ts +79 -0
- package/src/core/ai/tools/run-cells-tool.ts +63 -17
|
@@ -1 +1 @@
|
|
|
1
|
-
import{s as oe}from"./chunk-LvLJmgfZ.js";import{d as ye,l as be,n as T,p as ae,u as we}from"./useEvent-WUlsM6MC.js";import{t as Ne}from"./react-Bj1aDYRI.js";import{P as ke,T as ze,kn as Ce,ui as Se,vi as Ae,yi as n,__tla as Oe}from"./cells-BLS3X4Af.js";import"./react-dom-CSu739Rf.js";import{t as se}from"./compiler-runtime-B3qBwwSJ.js";import"./tooltip-Mz5m-WBI.js";import{h as ie}from"./useEventListener-CTPW4ELK.js";import{y as Ie}from"./utils-D6N4h71e.js";import{t as Pe}from"./constants-CdR60lKM.js";import{t as Le}from"./jsx-runtime-CP2fAiZX.js";import{t as z}from"./button-B_BBklax.js";import{t as le}from"./cn-d_A4rA-x.js";import"./dist-Dr9qtoId.js";import{n as Me,__tla as Ee}from"./JsonOutput-CHgq3R6J.js";import"./cjs-CVt8hZ5L.js";import"./main-Cmx6WhDY.js";import"./useNonce-BY4jV7Yb.js";import{r as Re}from"./requests-DZy_SQ_v.js";import{t as me}from"./createLucideIcon-BvP5LBIs.js";import{d as De,__tla as He}from"./layout-bJhK1MU7.js";import{n as Te,t as Ve,__tla as qe}from"./LazyAnyLanguageCodeMirror-B11pcXh7.js";import"./download-dbepOsRi.js";import"./markdown-renderer-rEsmEgLk.js";import{u as Ge}from"./toDate-DDAiY7kz.js";import{t as Ue,__tla as Be}from"./cell-editor-
|
|
1
|
+
import{s as oe}from"./chunk-LvLJmgfZ.js";import{d as ye,l as be,n as T,p as ae,u as we}from"./useEvent-WUlsM6MC.js";import{t as Ne}from"./react-Bj1aDYRI.js";import{P as ke,T as ze,kn as Ce,ui as Se,vi as Ae,yi as n,__tla as Oe}from"./cells-BLS3X4Af.js";import"./react-dom-CSu739Rf.js";import{t as se}from"./compiler-runtime-B3qBwwSJ.js";import"./tooltip-Mz5m-WBI.js";import{h as ie}from"./useEventListener-CTPW4ELK.js";import{y as Ie}from"./utils-D6N4h71e.js";import{t as Pe}from"./constants-CdR60lKM.js";import{t as Le}from"./jsx-runtime-CP2fAiZX.js";import{t as z}from"./button-B_BBklax.js";import{t as le}from"./cn-d_A4rA-x.js";import"./dist-Dr9qtoId.js";import{n as Me,__tla as Ee}from"./JsonOutput-CHgq3R6J.js";import"./cjs-CVt8hZ5L.js";import"./main-Cmx6WhDY.js";import"./useNonce-BY4jV7Yb.js";import{r as Re}from"./requests-DZy_SQ_v.js";import{t as me}from"./createLucideIcon-BvP5LBIs.js";import{d as De,__tla as He}from"./layout-bJhK1MU7.js";import{n as Te,t as Ve,__tla as qe}from"./LazyAnyLanguageCodeMirror-B11pcXh7.js";import"./download-dbepOsRi.js";import"./markdown-renderer-rEsmEgLk.js";import{u as Ge}from"./toDate-DDAiY7kz.js";import{t as Ue,__tla as Be}from"./cell-editor-DQFDo_RG.js";import{t as Fe}from"./spinner-Dt4SmUsI.js";import{t as Je}from"./play-CkqWG85-.js";import"./dist-Jp_4M-Ei.js";import"./dist-Cf47zp7b.js";import"./dist-Bagw3W9X.js";import"./dist-t1vdhOX_.js";import"./dist-D3OoaVQX.js";import"./session--x-9D3HE.js";import{r as Ke}from"./useTheme-DKICbfFh.js";import"./Combination-CvuTtFZA.js";import{t as C}from"./tooltip-CSN_sVIP.js";import"./purify.es-BBn8CPhf.js";import"./dates-DbMtViXe.js";import"./popover-BoqMUhMK.js";import"./vega-loader.browser-BJ9oKrvH.js";import"./defaultLocale-CuYNS33t.js";import"./defaultLocale-CGfP-Ye3.js";import{__tla as Qe}from"./chunk-5FQGJX7Z-Cyze_Wbx.js";import"./katex-FSdXOW5Y.js";import"./html-to-image-Fz0aHtSN.js";import{o as We}from"./focus-YYacdzxP.js";import{a as Xe}from"./renderShortcut-D-zdqWZr.js";import"./esm-Hlfcqnf0.js";import{n as Ye,r as Ze,t as ne}from"./react-resizable-panels.browser.esm-RgA6v8U3.js";import"./name-cell-input-CDeuhMiw.js";import{n as $e,r as et}from"./panel-context-ICWm_stq.js";import{__tla as tt}from"./loro_wasm_bg-Bj93RhA2.js";import"./ws-D2eS61zr.js";import"./Inputs-DWdIc0Ie.js";import"./dist-DKPpxz2S.js";import"./dist-D_4TSZPK.js";import"./dist-CsQrBXB1.js";import"./dist-ykiUNgjx.js";import"./dist-CrFxmtyb.js";import"./dist-C1g0ZQqM.js";import"./dist-0PMxXIr6.js";import"./dist-wBVaU_K6.js";import"./dist-BIYYQefO.js";import"./esm-MvMf2P5n.js";import{t as rt}from"./kiosk-mode-owaVEljR.js";let ce,ot=Promise.all([(()=>{try{return Oe}catch{}})(),(()=>{try{return Ee}catch{}})(),(()=>{try{return He}catch{}})(),(()=>{try{return qe}catch{}})(),(()=>{try{return Be}catch{}})(),(()=>{try{return Qe}catch{}})(),(()=>{try{return tt}catch{}})()]).then(async()=>{var de=me("eraser",[["path",{d:"M21 21H8a2 2 0 0 1-1.42-.587l-3.994-3.999a2 2 0 0 1 0-2.828l10-10a2 2 0 0 1 2.829 0l5.999 6a2 2 0 0 1 0 2.828L12.834 21",key:"g5wo59"}],["path",{d:"m5.082 11.09 8.828 8.828",key:"1wx5vj"}]]),pe=me("history",[["path",{d:"M3 12a9 9 0 1 0 9-9 9.75 9.75 0 0 0-6.74 2.74L3 8",key:"1357e3"}],["path",{d:"M3 3v5h5",key:"1xhq8a"}],["path",{d:"M12 7v5l4 2",key:"1fdv2h"}]]),he=se(),V=oe(Ne(),1),ue=15;const q=Se("marimo:scratchpadHistory:v1",[],Ce),fe=ae(!1),xe=ae(null,(e,s,i)=>{if(i=i.trim(),!i)return;let m=e(q);s(q,[i,...m.filter(c=>c!==i)].slice(0,ue))});var t=oe(Le(),1),_e={hide_code:!1,disabled:!1};const ve=()=>{var re;let e=(0,he.c)(60),s=ke(),[i]=Ie(),{theme:m}=Ke(),c=(0,V.useRef)(null),G=We(),{createNewCell:U,updateCellCode:d}=ze(),{sendRunScratchpad:p}=Re(),S=$e(),B=et(),l=s.cellRuntime[n],F=l==null?void 0:l.output,A=l==null?void 0:l.status,J=l==null?void 0:l.consoleOutputs,r=((re=s.cellData.__scratch__)==null?void 0:re.code)??"",K=ye(xe),[a,h]=be(fe),u=we(q),O;e[0]!==K||e[1]!==r||e[2]!==p?(O=()=>{p({code:r}),K(r)},e[0]=K,e[1]=r,e[2]=p,e[3]=O):O=e[3];let f=T(O),I;e[4]!==r||e[5]!==U||e[6]!==G?(I=()=>{r.trim()&&U({code:r,before:!1,cellId:G??"__end__"})},e[4]=r,e[5]=U,e[6]=G,e[7]=I):I=e[7];let Q=T(I),P;e[8]!==p||e[9]!==d?(P=()=>{d({cellId:n,code:"",formattingChange:!1}),p({code:""});let o=c.current;o&&o.dispatch({changes:{from:0,to:o.state.doc.length,insert:""}})},e[8]=p,e[9]=d,e[10]=P):P=e[10];let W=T(P),L;e[11]!==h||e[12]!==d?(L=o=>{h(!1),d({cellId:n,code:o,formattingChange:!1});let k=c.current;k&&k.dispatch({changes:{from:0,to:k.state.doc.length,insert:o}})},e[11]=h,e[12]=d,e[13]=L):L=e[13];let X=T(L),[Y,ge]=(0,V.useState)(),M;e[14]!==X||e[15]!==u||e[16]!==a||e[17]!==m?(M=()=>a?(0,t.jsx)("div",{className:"absolute inset-0 z-100 bg-background p-3 border-none overflow-auto",children:(0,t.jsx)("div",{className:"overflow-auto flex flex-col gap-3",children:u.map((o,k)=>(0,t.jsx)("div",{className:"border rounded-md hover:shadow-sm cursor-pointer hover:border-input overflow-hidden",onClick:()=>X(o),children:(0,t.jsx)(V.Suspense,{children:(0,t.jsx)(Ve,{language:"python",theme:m,basicSetup:{highlightActiveLine:!1,highlightActiveLineGutter:!1},value:o.trim(),editable:!1,readOnly:!0})})},k))})}):null,e[14]=X,e[15]=u,e[16]=a,e[17]=m,e[18]=M):M=e[18];let Z=M,E;e[19]!==W||e[20]!==Q||e[21]!==f||e[22]!==u.length||e[23]!==a||e[24]!==h||e[25]!==A?(E=()=>(0,t.jsxs)("div",{className:"flex items-center shrink-0 border-b",children:[(0,t.jsx)(C,{content:Xe("cell.run"),children:(0,t.jsx)(z,{"data-testid":"scratchpad-run-button",onClick:f,disabled:a,variant:"text",size:"xs",children:(0,t.jsx)(Je,{color:"var(--grass-11)",size:16})})}),(0,t.jsx)(C,{content:"Clear code and outputs",children:(0,t.jsx)(z,{disabled:a,size:"xs",variant:"text",onClick:W,children:(0,t.jsx)(de,{size:16})})}),(0,t.jsx)(rt,{children:(0,t.jsx)(C,{content:"Insert code",children:(0,t.jsx)(z,{disabled:a,size:"xs",variant:"text",onClick:Q,children:(0,t.jsx)(Te,{size:16})})})}),(A==="running"||A==="queued")&&(0,t.jsx)(Fe,{className:"inline",size:"small"}),(0,t.jsx)("div",{className:"flex-1"}),(0,t.jsx)(C,{content:"Toggle history",children:(0,t.jsx)(z,{size:"xs",variant:"text",className:le(a&&"bg-(--sky-3) rounded-none"),onClick:()=>h(!a),disabled:u.length===0,children:(0,t.jsx)(pe,{size:16})})}),(0,t.jsx)(C,{content:(0,t.jsx)("span",{className:"block max-w-prose",children:"Use this scratchpad to experiment with code without restrictions on variable names. Variables defined here aren't saved to notebook memory, and the code is not saved in the notebook file."}),children:(0,t.jsx)(z,{size:"xs",variant:"text",children:(0,t.jsx)(Ge,{size:16})})})]}),e[19]=W,e[20]=Q,e[21]=f,e[22]=u.length,e[23]=a,e[24]=h,e[25]=A,e[26]=E):E=e[26];let $=E,je=S==="vertical",R;e[27]===Symbol.for("react.memo_cache_sentinel")?(R=Ae.create(n),e[27]=R):R=e[27];let x;e[28]===$?x=e[29]:(x=$(),e[28]=$,e[29]=x);let D;e[30]===Symbol.for("react.memo_cache_sentinel")?(D=o=>{c.current=o},e[30]=D):D=e[30];let _;e[31]!==r||e[32]!==f||e[33]!==Y||e[34]!==m||e[35]!==i?(_=(0,t.jsx)("div",{className:"flex-1 overflow-auto",children:(0,t.jsx)(Ue,{theme:m,showPlaceholder:!1,id:n,code:r,config:_e,status:"idle",serializedEditorState:null,runCell:f,userConfig:i,editorViewRef:c,setEditorView:D,hidden:!1,showHiddenCode:ie.NOOP,languageAdapter:Y,setLanguageAdapter:ge})}),e[31]=r,e[32]=f,e[33]=Y,e[34]=m,e[35]=i,e[36]=_):_=e[36];let v;e[37]===Z?v=e[38]:(v=Z(),e[37]=Z,e[38]=v);let g;e[39]!==v||e[40]!==x||e[41]!==_?(g=(0,t.jsx)(ne,{defaultSize:40,minSize:20,maxSize:70,children:(0,t.jsxs)("div",{className:"h-full flex flex-col overflow-hidden relative",children:[x,_,v]})}),e[39]=v,e[40]=x,e[41]=_,e[42]=g):g=e[42];let ee=je?"h-1":"w-1",j;e[43]===ee?j=e[44]:(j=le("bg-border hover:bg-primary/50 transition-colors",ee),e[43]=ee,e[44]=j);let y;e[45]===j?y=e[46]:(y=(0,t.jsx)(Ze,{className:j}),e[45]=j,e[46]=y);let b;e[47]===F?b=e[48]:(b=(0,t.jsx)("div",{className:"flex-1 overflow-auto",children:(0,t.jsx)(Me,{allowExpand:!1,output:F,className:Pe.outputArea,cellId:n,stale:!1,loading:!1})}),e[47]=F,e[48]=b);let w;e[49]===J?w=e[50]:(w=(0,t.jsx)("div",{className:"overflow-auto shrink-0 max-h-[50%]",children:(0,t.jsx)(De,{consoleOutputs:J,className:"overflow-auto",stale:!1,cellName:"_",onSubmitDebugger:ie.NOOP,cellId:n,debuggerActive:!1})}),e[49]=J,e[50]=w);let N;e[51]!==b||e[52]!==w?(N=(0,t.jsx)(ne,{defaultSize:60,minSize:20,children:(0,t.jsxs)("div",{className:"h-full flex flex-col divide-y overflow-hidden",children:[b,w]})}),e[51]=b,e[52]=w,e[53]=N):N=e[53];let H;return e[54]!==S||e[55]!==B||e[56]!==g||e[57]!==y||e[58]!==N?(H=(0,t.jsx)("div",{className:"flex flex-col h-full overflow-hidden",id:R,children:(0,t.jsxs)(Ye,{direction:S,className:"h-full",children:[g,y,N]},B)}),e[54]=S,e[55]=B,e[56]=g,e[57]=y,e[58]=N,e[59]=H):H=e[59],H};let te;te=se(),ce=()=>{let e=(0,te.c)(1),s;return e[0]===Symbol.for("react.memo_cache_sentinel")?(s=(0,t.jsx)(ve,{}),e[0]=s):s=e[0],s}});export{ot as __tla,ce as default};
|
package/dist/index.html
CHANGED
|
@@ -66,7 +66,7 @@
|
|
|
66
66
|
<marimo-server-token data-token="{{ server_token }}" hidden></marimo-server-token>
|
|
67
67
|
<!-- /TODO -->
|
|
68
68
|
<title>{{ title }}</title>
|
|
69
|
-
<script type="module" crossorigin src="./assets/index-
|
|
69
|
+
<script type="module" crossorigin src="./assets/index-CKAAJr4G.js"></script>
|
|
70
70
|
<link rel="modulepreload" crossorigin href="./assets/preload-helper-BW0IMuFq.js">
|
|
71
71
|
<link rel="modulepreload" crossorigin href="./assets/clsx-A78R3nYl.js">
|
|
72
72
|
<link rel="modulepreload" crossorigin href="./assets/cn-d_A4rA-x.js">
|
|
@@ -216,10 +216,10 @@
|
|
|
216
216
|
<link rel="modulepreload" crossorigin href="./assets/file-DVwc11C3.js">
|
|
217
217
|
<link rel="modulepreload" crossorigin href="./assets/image-CBwHq93J.js">
|
|
218
218
|
<link rel="modulepreload" crossorigin href="./assets/play-CkqWG85-.js">
|
|
219
|
-
<link rel="modulepreload" crossorigin href="./assets/add-cell-with-ai-
|
|
219
|
+
<link rel="modulepreload" crossorigin href="./assets/add-cell-with-ai-n1W-BSLf.js">
|
|
220
220
|
<link rel="modulepreload" crossorigin href="./assets/isEmpty-9KlyX4nB.js">
|
|
221
221
|
<link rel="modulepreload" crossorigin href="./assets/bot-message-square-BzawfL5p.js">
|
|
222
|
-
<link rel="modulepreload" crossorigin href="./assets/chat-display-
|
|
222
|
+
<link rel="modulepreload" crossorigin href="./assets/chat-display-UjJ3dstS.js">
|
|
223
223
|
<link rel="modulepreload" crossorigin href="./assets/chart-no-axes-column-F2DZENgf.js">
|
|
224
224
|
<link rel="modulepreload" crossorigin href="./assets/square-function-DEp1ozoA.js">
|
|
225
225
|
<link rel="modulepreload" crossorigin href="./assets/spec-koLy2UDc.js">
|
package/package.json
CHANGED
|
@@ -411,6 +411,85 @@ describe("RunStaleCellsTool", () => {
|
|
|
411
411
|
});
|
|
412
412
|
});
|
|
413
413
|
|
|
414
|
+
describe("output truncation", () => {
|
|
415
|
+
it("should summarize text/html output instead of dumping raw content", async () => {
|
|
416
|
+
const notebook = MockNotebook.notebookState({
|
|
417
|
+
cellData: {
|
|
418
|
+
[cellId1]: { code: "fig.show()", edited: true },
|
|
419
|
+
},
|
|
420
|
+
});
|
|
421
|
+
store.set(notebookAtom, notebook);
|
|
422
|
+
|
|
423
|
+
vi.mocked(runCells).mockImplementation(async () => {
|
|
424
|
+
const updatedNotebook = store.get(notebookAtom);
|
|
425
|
+
updatedNotebook.cellRuntime[cellId1] = {
|
|
426
|
+
...updatedNotebook.cellRuntime[cellId1],
|
|
427
|
+
status: "idle",
|
|
428
|
+
};
|
|
429
|
+
store.set(notebookAtom, updatedNotebook);
|
|
430
|
+
});
|
|
431
|
+
|
|
432
|
+
const largeHtml = `<div>${"x".repeat(2_000_000)}</div>`;
|
|
433
|
+
vi.mocked(getCellContextData).mockReturnValue({
|
|
434
|
+
cellOutput: {
|
|
435
|
+
outputType: "text",
|
|
436
|
+
processedContent: null,
|
|
437
|
+
imageUrl: null,
|
|
438
|
+
output: { mimetype: "text/html", data: largeHtml },
|
|
439
|
+
},
|
|
440
|
+
consoleOutputs: null,
|
|
441
|
+
cellName: "cell1",
|
|
442
|
+
} as never);
|
|
443
|
+
|
|
444
|
+
const result = await tool.handler({}, toolContext as never);
|
|
445
|
+
|
|
446
|
+
expect(result.status).toBe("success");
|
|
447
|
+
const output = result.cellsToOutput?.[cellId1]?.cellOutput ?? "";
|
|
448
|
+
expect(output).toContain("HTML Output:");
|
|
449
|
+
expect(output).toContain("text/html");
|
|
450
|
+
expect(output.length).toBeLessThan(200);
|
|
451
|
+
expect(output).not.toContain(largeHtml);
|
|
452
|
+
});
|
|
453
|
+
|
|
454
|
+
it("should truncate large text output to MAX_TEXT_OUTPUT_CHARS", async () => {
|
|
455
|
+
const notebook = MockNotebook.notebookState({
|
|
456
|
+
cellData: {
|
|
457
|
+
[cellId1]: { code: "print(big_string)", edited: true },
|
|
458
|
+
},
|
|
459
|
+
});
|
|
460
|
+
store.set(notebookAtom, notebook);
|
|
461
|
+
|
|
462
|
+
vi.mocked(runCells).mockImplementation(async () => {
|
|
463
|
+
const updatedNotebook = store.get(notebookAtom);
|
|
464
|
+
updatedNotebook.cellRuntime[cellId1] = {
|
|
465
|
+
...updatedNotebook.cellRuntime[cellId1],
|
|
466
|
+
status: "idle",
|
|
467
|
+
};
|
|
468
|
+
store.set(notebookAtom, updatedNotebook);
|
|
469
|
+
});
|
|
470
|
+
|
|
471
|
+
const largeText = "a".repeat(10_000);
|
|
472
|
+
vi.mocked(getCellContextData).mockReturnValue({
|
|
473
|
+
cellOutput: {
|
|
474
|
+
outputType: "text",
|
|
475
|
+
processedContent: largeText,
|
|
476
|
+
imageUrl: null,
|
|
477
|
+
output: { mimetype: "text/plain", data: largeText },
|
|
478
|
+
},
|
|
479
|
+
consoleOutputs: null,
|
|
480
|
+
cellName: "cell1",
|
|
481
|
+
} as never);
|
|
482
|
+
|
|
483
|
+
const result = await tool.handler({}, toolContext as never);
|
|
484
|
+
|
|
485
|
+
const output = result.cellsToOutput?.[cellId1]?.cellOutput ?? "";
|
|
486
|
+
expect(output).toContain("[TRUNCATED:");
|
|
487
|
+
expect(output).toContain("Full output visible in the notebook UI.");
|
|
488
|
+
// Output should be capped (2000 chars content + "Output:\n" prefix + truncation message)
|
|
489
|
+
expect(output.length).toBeLessThan(2200);
|
|
490
|
+
});
|
|
491
|
+
});
|
|
492
|
+
|
|
414
493
|
describe("cell execution completion", () => {
|
|
415
494
|
it("should complete immediately if cells are already idle", async () => {
|
|
416
495
|
const notebook = MockNotebook.notebookState({
|
|
@@ -24,6 +24,11 @@ import type { CopilotMode } from "./registry";
|
|
|
24
24
|
const POST_EXECUTION_DELAY = 200;
|
|
25
25
|
const WAIT_FOR_CELLS_TIMEOUT = 30_000;
|
|
26
26
|
|
|
27
|
+
// Output size limits to prevent exceeding LLM token limits.
|
|
28
|
+
const MAX_TEXT_OUTPUT_CHARS = 2000;
|
|
29
|
+
const MAX_ERROR_OUTPUT_CHARS = 3000;
|
|
30
|
+
const MAX_TOOL_OUTPUT_CHARS = 40_000;
|
|
31
|
+
|
|
27
32
|
interface CellOutput {
|
|
28
33
|
consoleOutput?: string;
|
|
29
34
|
cellOutput?: string;
|
|
@@ -118,42 +123,60 @@ export class RunStaleCellsTool
|
|
|
118
123
|
const cellsToOutput = new Map<CellId, CellOutput | null>();
|
|
119
124
|
let resultMessage = "";
|
|
120
125
|
let outputHasErrors = false;
|
|
126
|
+
let totalOutputChars = 0;
|
|
121
127
|
|
|
122
128
|
for (const cellId of staleCells) {
|
|
123
129
|
const cellContextData = getCellContextData(cellId, updatedNotebook, {
|
|
124
130
|
includeConsoleOutput: true,
|
|
125
131
|
});
|
|
126
132
|
|
|
127
|
-
let cellOutputString: string | undefined;
|
|
128
|
-
let consoleOutputString: string | undefined;
|
|
129
|
-
|
|
130
133
|
const cellOutput = cellContextData.cellOutput;
|
|
131
134
|
const consoleOutputs = cellContextData.consoleOutputs;
|
|
132
135
|
const hasConsoleOutput = consoleOutputs && consoleOutputs.length > 0;
|
|
133
136
|
|
|
137
|
+
// Track errors regardless of budget
|
|
138
|
+
if (cellOutput && this.outputHasErrors(cellOutput)) {
|
|
139
|
+
outputHasErrors = true;
|
|
140
|
+
}
|
|
141
|
+
if (
|
|
142
|
+
hasConsoleOutput &&
|
|
143
|
+
consoleOutputs.some((output) => this.outputHasErrors(output))
|
|
144
|
+
) {
|
|
145
|
+
outputHasErrors = true;
|
|
146
|
+
}
|
|
147
|
+
|
|
134
148
|
if (!cellOutput && !hasConsoleOutput) {
|
|
135
|
-
// Set null to show no output
|
|
136
149
|
cellsToOutput.set(cellId, null);
|
|
137
150
|
continue;
|
|
138
151
|
}
|
|
139
152
|
|
|
153
|
+
// If total budget exceeded, summarize remaining cells
|
|
154
|
+
if (totalOutputChars >= MAX_TOOL_OUTPUT_CHARS) {
|
|
155
|
+
cellsToOutput.set(cellId, {
|
|
156
|
+
cellOutput: "Cell executed (output omitted due to context limits).",
|
|
157
|
+
});
|
|
158
|
+
continue;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
let cellOutputString: string | undefined;
|
|
162
|
+
let consoleOutputString: string | undefined;
|
|
163
|
+
|
|
140
164
|
if (cellOutput) {
|
|
141
165
|
cellOutputString = this.formatOutputString(cellOutput);
|
|
142
|
-
|
|
143
|
-
outputHasErrors = true;
|
|
144
|
-
}
|
|
166
|
+
totalOutputChars += cellOutputString.length;
|
|
145
167
|
}
|
|
146
168
|
|
|
147
169
|
if (hasConsoleOutput) {
|
|
148
170
|
consoleOutputString = consoleOutputs
|
|
149
171
|
.map((output) => this.formatOutputString(output))
|
|
150
172
|
.join("\n");
|
|
173
|
+
consoleOutputString = this.truncateString(
|
|
174
|
+
consoleOutputString,
|
|
175
|
+
MAX_TEXT_OUTPUT_CHARS,
|
|
176
|
+
);
|
|
177
|
+
totalOutputChars += consoleOutputString.length;
|
|
151
178
|
resultMessage +=
|
|
152
179
|
"Console output represents the stdout or stderr of the cell (eg. print statements).";
|
|
153
|
-
|
|
154
|
-
if (consoleOutputs.some((output) => this.outputHasErrors(output))) {
|
|
155
|
-
outputHasErrors = true;
|
|
156
|
-
}
|
|
157
180
|
}
|
|
158
181
|
|
|
159
182
|
cellsToOutput.set(cellId, {
|
|
@@ -199,13 +222,29 @@ export class RunStaleCellsTool
|
|
|
199
222
|
let outputString = "";
|
|
200
223
|
const { outputType, processedContent, imageUrl, output } = cellOutput;
|
|
201
224
|
if (outputType === "text") {
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
225
|
+
if (output.mimetype === "text/html") {
|
|
226
|
+
// text/html (e.g. plotly figures, rich dataframes) can be millions of
|
|
227
|
+
// chars and is not interpretable by LLMs — summarize instead
|
|
228
|
+
const dataLength =
|
|
229
|
+
typeof output.data === "string"
|
|
230
|
+
? output.data.length
|
|
231
|
+
: JSON.stringify(output.data).length;
|
|
232
|
+
outputString += `HTML Output: text/html content (${dataLength.toLocaleString()} chars). Full output visible in notebook UI.`;
|
|
207
233
|
} else {
|
|
208
|
-
|
|
234
|
+
const isError = this.outputHasErrors(cellOutput);
|
|
235
|
+
const maxChars = isError
|
|
236
|
+
? MAX_ERROR_OUTPUT_CHARS
|
|
237
|
+
: MAX_TEXT_OUTPUT_CHARS;
|
|
238
|
+
outputString += "Output:\n";
|
|
239
|
+
let content: string;
|
|
240
|
+
if (processedContent) {
|
|
241
|
+
content = processedContent;
|
|
242
|
+
} else if (typeof output.data === "string") {
|
|
243
|
+
content = output.data;
|
|
244
|
+
} else {
|
|
245
|
+
content = JSON.stringify(output.data);
|
|
246
|
+
}
|
|
247
|
+
outputString += this.truncateString(content, maxChars);
|
|
209
248
|
}
|
|
210
249
|
} else if (outputType === "media") {
|
|
211
250
|
outputString += `Media Output: Contains ${output.mimetype} content`;
|
|
@@ -216,6 +255,13 @@ export class RunStaleCellsTool
|
|
|
216
255
|
return outputString;
|
|
217
256
|
}
|
|
218
257
|
|
|
258
|
+
private truncateString(str: string, maxLength: number): string {
|
|
259
|
+
if (str.length <= maxLength) {
|
|
260
|
+
return str;
|
|
261
|
+
}
|
|
262
|
+
return `${str.slice(0, maxLength)}\n\n[TRUNCATED: ${str.length.toLocaleString()} → ${maxLength.toLocaleString()} chars. Full output visible in the notebook UI.]`;
|
|
263
|
+
}
|
|
264
|
+
|
|
219
265
|
/**
|
|
220
266
|
* Wait for cells to finish executing (status becomes "idle")
|
|
221
267
|
* Returns true if all cells finished executing, false if the timeout was reached
|