@@ -183,7 +183,7 @@ describe("the mutating-tool table", () => {
183183 "removeClip" ,
184184 "removeModifier" ,
185185 "removeTrim" ,
186- "removeFillerWords " ,
186+ "removeWords " ,
187187 "replaceTimeline" ,
188188 "setAnnotation" ,
189189 "setAudio" ,
@@ -2385,7 +2385,7 @@ describe("getTranscriptWords", () => {
23852385 } ) ;
23862386} ) ;
23872387
2388- describe ( "removeFillerWords " , ( ) => {
2388+ describe ( "removeWords " , ( ) => {
23892389 function repeatedWordDocument ( ) : AxcutDocument {
23902390 const base = fixtureDocument ( ) ;
23912391 return {
@@ -2409,7 +2409,7 @@ describe("removeFillerWords", () => {
24092409 "filler" ,
24102410 "meaningful" ,
24112411 ] ) ;
2412- const result = run ( before , "removeFillerWords " , { wordIds : [ "filler" ] } ) ;
2412+ const result = run ( before , "removeWords " , { wordIds : [ "filler" ] } ) ;
24132413 expect ( result . ok ) . toBe ( true ) ;
24142414 const next = result . document as AxcutDocument ;
24152415 const trim = next . timeline . trimRanges . at ( - 1 ) ;
@@ -2438,6 +2438,52 @@ describe("removeFillerWords", () => {
24382438 expect ( next . timeline . trimRanges ) . toHaveLength ( before . timeline . trimRanges . length + 1 ) ;
24392439 } ) ;
24402440
2441+ it ( "cuts consecutive words as one span, gaps included, and the others apart" , ( ) => {
2442+ const base = fixtureDocument ( ) ;
2443+ const before : AxcutDocument = {
2444+ ...base ,
2445+ transcripts : [
2446+ {
2447+ ...base . transcripts [ 0 ] ,
2448+ words : [
2449+ { id : "word_1" , segmentId : "seg_1" , startSec : 1 , endSec : 1.2 , text : "so" } ,
2450+ { id : "word_2" , segmentId : "seg_1" , startSec : 1.4 , endSec : 1.5 , text : "I" } ,
2451+ { id : "word_3" , segmentId : "seg_1" , startSec : 1.6 , endSec : 1.9 , text : "mean" } ,
2452+ { id : "word_4" , segmentId : "seg_1" , startSec : 2.2 , endSec : 2.4 , text : "the" } ,
2453+ { id : "word_5" , segmentId : "seg_1" , startSec : 3 , endSec : 3.2 , text : "um" } ,
2454+ ] ,
2455+ } ,
2456+ ] ,
2457+ } ;
2458+ const result = run ( before , "removeWords" , { wordIds : [ "word_3" , "word_5" , "word_2" ] } ) ;
2459+ expect ( result . ok ) . toBe ( true ) ;
2460+ const added = result . document ?. timeline . trimRanges . slice ( before . timeline . trimRanges . length ) ;
2461+ expect ( added ?. map ( ( { startSec, endSec } ) => [ startSec , endSec ] ) ) . toEqual ( [
2462+ [ 1.4 , 1.9 ] ,
2463+ [ 3 , 3.2 ] ,
2464+ ] ) ;
2465+ const removed = JSON . parse ( result . resultJson ) . removed ;
2466+ expect ( removed . map ( ( word : { wordId : string } ) => word . wordId ) ) . toEqual ( [
2467+ "word_2" ,
2468+ "word_3" ,
2469+ "word_5" ,
2470+ ] ) ;
2471+ expect ( removed [ 1 ] . trimRangeId ) . toBe ( removed [ 0 ] . trimRangeId ) ;
2472+ expect ( removed [ 2 ] . trimRangeId ) . not . toBe ( removed [ 0 ] . trimRangeId ) ;
2473+ } ) ;
2474+
2475+ it ( "refuses a duplicated or already-cut word without cutting anything" , ( ) => {
2476+ const before = repeatedWordDocument ( ) ;
2477+ const duplicated = run ( before , "removeWords" , { wordIds : [ "filler" , "filler" ] } ) ;
2478+ expect ( duplicated . ok ) . toBe ( false ) ;
2479+ expect ( duplicated . document ) . toBeUndefined ( ) ;
2480+ const cut = run ( before , "removeWords" , { wordIds : [ "filler" ] } ) . document as AxcutDocument ;
2481+ const again = run ( cut , "removeWords" , { wordIds : [ "meaningful" , "filler" ] } ) ;
2482+ expect ( again . ok ) . toBe ( false ) ;
2483+ expect ( again . document ) . toBeUndefined ( ) ;
2484+ expect ( again . resultJson ) . toContain ( "already cut" ) ;
2485+ } ) ;
2486+
24412487 it ( "preserves addTrim warnings when removing a filler cuts a zoom transition" , ( ) => {
24422488 const before = repeatedWordDocument ( ) ;
24432489 before . timeline . trimRanges = [ ] ;
@@ -2452,14 +2498,14 @@ describe("removeFillerWords", () => {
24522498 } ) ;
24532499 const expected = JSON . parse ( directTrim . resultJson ) . cutTransitions ;
24542500 expect ( expected . length ) . toBeGreaterThan ( 0 ) ;
2455- const removed = run ( zoomed , "removeFillerWords " , { assetId : "asset_1" , wordIds : [ "filler" ] } ) ;
2501+ const removed = run ( zoomed , "removeWords " , { assetId : "asset_1" , wordIds : [ "filler" ] } ) ;
24562502 expect ( removed . ok ) . toBe ( true ) ;
24572503 expect ( JSON . parse ( removed . resultJson ) . cutTransitions ) . toEqual ( expected ) ;
24582504 } ) ;
24592505
24602506 it ( "refuses an invalid ID atomically, including when another ID is valid" , ( ) => {
24612507 const before = repeatedWordDocument ( ) ;
2462- const result = run ( before , "removeFillerWords " , { wordIds : [ "filler" , "missing" ] } ) ;
2508+ const result = run ( before , "removeWords " , { wordIds : [ "filler" , "missing" ] } ) ;
24632509 expect ( result . ok ) . toBe ( false ) ;
24642510 expect ( result . document ) . toBeUndefined ( ) ;
24652511 expect ( result . resultJson ) . toContain ( "Unknown transcript word ID: missing" ) ;
@@ -2479,7 +2525,7 @@ describe("removeFillerWords", () => {
24792525 assetId : "asset_2" ,
24802526 words : [ { id : "other_filler" , segmentId : "seg_1" , startSec : 4 , endSec : 4.2 , text : "um" } ] ,
24812527 } ) ;
2482- const result = run ( before , "removeFillerWords " , { wordIds : [ "other_filler" ] } ) ;
2528+ const result = run ( before , "removeWords " , { wordIds : [ "other_filler" ] } ) ;
24832529 expect ( result . ok ) . toBe ( true ) ;
24842530 expect ( result . document ?. timeline . trimRanges . at ( - 1 ) ) . toMatchObject ( {
24852531 assetId : "asset_2" ,
@@ -2503,7 +2549,7 @@ describe("removeFillerWords", () => {
25032549 } ) ;
25042550 const read = JSON . parse ( run ( before , "getTranscriptWords" , { assetId : "asset_2" } ) . resultJson ) ;
25052551 expect ( read . words [ 0 ] . id ) . toBe ( "word_1" ) ;
2506- const result = run ( before , "removeFillerWords " , {
2552+ const result = run ( before , "removeWords " , {
25072553 assetId : "asset_2" ,
25082554 wordIds : [ read . words [ 0 ] . id ] ,
25092555 } ) ;
@@ -2516,10 +2562,10 @@ describe("removeFillerWords", () => {
25162562 result . document ?. timeline . trimRanges . filter ( ( trim ) => trim . assetId === "asset_1" ) ,
25172563 ) . toEqual ( before . timeline . trimRanges ) ;
25182564 expect ( result . document ?. transcripts ) . toEqual ( before . transcripts ) ;
2519- const ambiguous = run ( before , "removeFillerWords " , { wordIds : [ "word_1" ] } ) ;
2565+ const ambiguous = run ( before , "removeWords " , { wordIds : [ "word_1" ] } ) ;
25202566 expect ( ambiguous . ok ) . toBe ( false ) ;
25212567 expect ( ambiguous . document ) . toBeUndefined ( ) ;
2522- const unknownAsset = run ( before , "removeFillerWords " , {
2568+ const unknownAsset = run ( before , "removeWords " , {
25232569 assetId : "missing_asset" ,
25242570 wordIds : [ "word_1" ] ,
25252571 } ) ;
@@ -2530,7 +2576,7 @@ describe("removeFillerWords", () => {
25302576 it ( "refuses invalid timestamps without guessing a span" , ( ) => {
25312577 const before = repeatedWordDocument ( ) ;
25322578 before . transcripts [ 0 ] . words [ 0 ] . endSec = Number . NaN ;
2533- const result = run ( before , "removeFillerWords " , { wordIds : [ "filler" ] } ) ;
2579+ const result = run ( before , "removeWords " , { wordIds : [ "filler" ] } ) ;
25342580 expect ( result . ok ) . toBe ( false ) ;
25352581 expect ( result . document ) . toBeUndefined ( ) ;
25362582 expect ( result . resultJson ) . toContain ( "invalid source timestamps" ) ;
@@ -2542,7 +2588,7 @@ describe("removeFillerWords", () => {
25422588 ...before . timeline . clips [ 0 ] ,
25432589 id : "duplicate_clip" ,
25442590 } ) ;
2545- const result = run ( before , "removeFillerWords " , { wordIds : [ "filler" ] } ) ;
2591+ const result = run ( before , "removeWords " , { wordIds : [ "filler" ] } ) ;
25462592 expect ( result . ok ) . toBe ( false ) ;
25472593 expect ( result . document ) . toBeUndefined ( ) ;
25482594 expect ( result . resultJson ) . toContain ( "exactly one clip; found 2" ) ;
@@ -2551,7 +2597,7 @@ describe("removeFillerWords", () => {
25512597 it ( "honours project edit consent" , ( ) => {
25522598 const result = executeAgentTool (
25532599 repeatedWordDocument ( ) ,
2554- "removeFillerWords " ,
2600+ "removeWords " ,
25552601 JSON . stringify ( { wordIds : [ "filler" ] } ) ,
25562602 { editsAllowed : false } ,
25572603 ) ;
0 commit comments