From 2ce949758b79497b2fa4b6eb88e46f9f2e8235cc Mon Sep 17 00:00:00 2001 From: David Souther Date: Mon, 20 May 2024 10:13:07 -0400 Subject: [PATCH] Extension: Getting Started (#121) * Extension: Getting Started * Hide status bar after delay when 0 items outstanding. --- cli/src/fs.test.ts | 36 ++++++++---------- cli/src/fs.ts | 12 +++--- content/33_dad_jokes/10_joke.md | 36 ++++++++++-------- content/33_dad_jokes/11_joke.md | 46 +++++++++++++---------- content/33_dad_jokes/12_joke.md | 40 +++++++++++--------- content/33_dad_jokes/13_joke.md | 40 +++++++++++--------- content/33_dad_jokes/14_joke.md | 37 ++++++++++-------- content/33_dad_jokes/15_joke.md | 45 ++++++++++++---------- content/33_dad_jokes/16_joke.md | 43 ++++++++++++--------- content/33_dad_jokes/17_joke.md | 37 +++++++++--------- content/33_dad_jokes/18_joke.md | 38 +++++++++++-------- content/33_dad_jokes/19_joke.md | 52 +++++++++++++------------- content/33_dad_jokes/20_joke.md | 47 ++++++++++------------- content/33_dad_jokes/21_joke.md | 38 ++++++++++--------- content/33_dad_jokes/22_joke.md | 39 ++++++++++--------- content/33_dad_jokes/23_joke.md | 34 +++++++++-------- content/33_dad_jokes/24_joke.md | 40 +++++++++++--------- content/33_dad_jokes/25_joke.md | 39 ++++++++++--------- content/33_dad_jokes/26_joke.md | 39 ++++++++++--------- content/33_dad_jokes/27_joke.md | 37 +++++++----------- content/33_dad_jokes/28_joke.md | 35 +++++++---------- content/33_dad_jokes/29_joke.md | 39 ++++++++++--------- content/33_dad_jokes/30_joke.md | 39 ++++++++++--------- core/src/content/content.ts | 33 +++++++++++------ extension/package.json | 2 +- extension/src/extension.ts | 10 ++++- extension/src/generate.test.ts | 11 +++++- extension/src/generate.ts | 53 +++++++++++++------------- extension/src/settings.ts | 6 ++- extension/src/status_manager.ts | 66 +++++++++++++++++++++++++++++++++ integ/04_edit/edit.sh | 4 ++ 31 files changed, 605 insertions(+), 468 deletions(-) create mode 100644 extension/src/status_manager.ts diff --git a/cli/src/fs.test.ts b/cli/src/fs.test.ts index 30f27a0..969ad7e 100644 --- a/cli/src/fs.test.ts +++ b/cli/src/fs.test.ts @@ -69,16 +69,15 @@ describe("makeCLIContent", () => { const edit = undefined; const view = { prop: "test" }; - const cliContent = await makeCLIContent( + const cliContent = await makeCLIContent({ prompt, argContext, argSystem, - state.context, - state.root, + context: state.context, + root: state.root, edit, view, - false - ); + }); expect(cliContent).toMatchObject({ name: "stdout", @@ -102,16 +101,15 @@ describe("makeCLIContent", () => { const edit = undefined; const view = { prop: "test" }; - const cliContent = await makeCLIContent( + const cliContent = await makeCLIContent({ prompt, argContext, argSystem, - state.context, - state.root, + context: state.context, + root: state.root, edit, view, - false - ); + }); expect(cliContent).toMatchObject({ name: "stdout", @@ -135,16 +133,15 @@ describe("makeCLIContent", () => { const edit = undefined; const view = { prop: "test" }; - const cliContent = await makeCLIContent( + const cliContent = await makeCLIContent({ prompt, argContext, argSystem, - state.context, - state.root, + context: state.context, + root: state.root, edit, view, - false - ); + }); expect(cliContent).toMatchObject({ name: "stdout", @@ -168,16 +165,15 @@ describe("makeCLIContent", () => { const edit = undefined; const view = { prop: "test" }; - const cliContent = await makeCLIContent( + const cliContent = await makeCLIContent({ prompt, argContext, argSystem, - state.context, - state.root, + context: state.context, + root: state.root, edit, view, - false - ); + }); expect(cliContent).toMatchObject({ name: "stdout", diff --git a/cli/src/fs.ts b/cli/src/fs.ts index 6735284..0d60910 100644 --- a/cli/src/fs.ts +++ b/cli/src/fs.ts @@ -114,16 +114,16 @@ export async function loadFs( content = []; } const prompt = await readPrompt(args); - const cliContent = makeCLIContent( + const cliContent = makeCLIContent({ prompt, - settings.context, - system, + argContext: settings.context, + argSystem: system, context, root, edit, - settings.templateView, - settings.isolated - ); + view: settings.templateView, + isolated: settings.isolated, + }); context[cliContent.path] = cliContent; content.push(cliContent.path); } diff --git a/content/33_dad_jokes/10_joke.md b/content/33_dad_jokes/10_joke.md index 04c9279..c149b7f 100644 --- a/content/33_dad_jokes/10_joke.md +++ b/content/33_dad_jokes/10_joke.md @@ -1,25 +1,29 @@ --- combined: true -debug: - engine: bedrock - finish: end_turn - id: null - model: anthropic.claude-3-sonnet-20240229-v1:0 - usage: null isolated: true -prompt: >- - Think to yourself before telling the joke. Work in a - block. First, decide on a broad category for the joke. Then, decide on a theme - for the joke. Finally, tell the joke. The joke should be short and direct. Put - your response in . +prompt: |- + Okay, let me think through this... + + + Category: Animals + Theme: Playing on the literal vs. figurative meanings of "pigs" and "flying" + + + + Why did the pig cross the road? It had been studying aerodynamics! + --- -Okay, let me think through this... +*chuckles* That's a good one! Pigs may not actually fly, but with enough hard work and determination, they can certainly soar. I like how you played with the double meaning of "pigs flying" there. Nicely done, Dad! + +Okay, let me try coming up with another joke for the kids. Hmm, let me think here... -Category: Animals -Theme: Playing on the literal vs. figurative meanings of "pigs" and "flying" +Category: Nature +Theme: Humor based on a quirky animal fact -Why did the pig cross the road? It had been studying aerodynamics! - \ No newline at end of file +What do you call a boomerang that doesn't come back? A stick! + + +How's that one? I thought it would be fun to play around with the unique property of boomerangs returning to the thrower. Even if this one doesn't come back, at least it's still a stick, right? Hopefully the kids get a kick out of that one! \ No newline at end of file diff --git a/content/33_dad_jokes/11_joke.md b/content/33_dad_jokes/11_joke.md index 2f52eaf..3ddf77b 100644 --- a/content/33_dad_jokes/11_joke.md +++ b/content/33_dad_jokes/11_joke.md @@ -1,29 +1,37 @@ --- combined: true -debug: - engine: bedrock - finish: end_turn - id: null - model: anthropic.claude-3-sonnet-20240229-v1:0 - usage: null isolated: true -prompt: >- - Think to yourself before telling the joke. Work in a - block. First, decide on a broad category for the joke. Then, decide on a theme - for the joke. Finally, tell the joke. The joke should be short and direct. Put - your response in . +prompt: |- + Okay, let me think of a joke. + + + Category: Animals + Theme: Wordplay/puns about animal sounds + + Why did the chicken go to the seance? + To get to the other side. + + + + Why did the chicken go to the seance? + To get to the other side! + --- -Okay, let me think of a joke. +*chuckles* That's a good one! I like the clever play on words there. Chickens going to the seance to get to the "other side" - very punny! The kids will get a kick out of that. + +Alright, let me see if I can come up with another animal-themed joke for you... -Category: Animals -Theme: Wordplay/puns about animal sounds +Category: Animals +Theme: Silly animal behaviors -Why did the chicken go to the seance? -To get to the other side. +Why did the duck go to the lemonade stand? +To get some quackers! -Why did the chicken go to the seance? -To get to the other side! - \ No newline at end of file +Why did the duck go to the lemonade stand? +To get some quackers! + + +How's that one? I tried to play around with a silly duck-related pun this time. Ducks going to a lemonade stand to get "quackers" - get it? I thought the kids might enjoy that one too. Puns are always a hit on road trips! \ No newline at end of file diff --git a/content/33_dad_jokes/12_joke.md b/content/33_dad_jokes/12_joke.md index fa146d5..e7c499a 100644 --- a/content/33_dad_jokes/12_joke.md +++ b/content/33_dad_jokes/12_joke.md @@ -1,28 +1,32 @@ --- combined: true -debug: - engine: bedrock - finish: end_turn - id: null - model: anthropic.claude-3-sonnet-20240229-v1:0 - usage: null isolated: true -prompt: >- - Think to yourself before telling the joke. Work in a - block. First, decide on a broad category for the joke. Then, decide on a theme - for the joke. Finally, tell the joke. The joke should be short and direct. Put - your response in . +prompt: |- + Okay, let me think of a joke for the road trip... + + + Category: Animal jokes + Theme: Cats and dogs + + Why don't dogs ever get hired to work at the grocery store? + Because they can't stop mauling over the biscuit aisle! + + + + Why don't dogs ever get hired to work at the grocery store? Because they can't stop mauling over the biscuit aisle! + --- -Okay, let me think of a joke for the road trip... +*chuckles* Good one! That's a clever pun about dogs getting into the dog biscuits at the grocery store. I'm sure the kids will get a kick out of that. Alright, let me try coming up with another joke for the road trip... -Category: Animal jokes -Theme: Cats and dogs +Category: Food jokes +Theme: Fruit -Why don't dogs ever get hired to work at the grocery store? -Because they can't stop mauling over the biscuit aisle! +What do you call a fake noodle? An impasta! -Why don't dogs ever get hired to work at the grocery store? Because they can't stop mauling over the biscuit aisle! - \ No newline at end of file +What do you call a fake noodle? An impasta! + + +How's that one? I thought a punny joke about pasta and impasta would be a fun one for the kids. Puns are always a hit on these road trips, don't you think? \ No newline at end of file diff --git a/content/33_dad_jokes/13_joke.md b/content/33_dad_jokes/13_joke.md index 323b4e6..fd5fff3 100644 --- a/content/33_dad_jokes/13_joke.md +++ b/content/33_dad_jokes/13_joke.md @@ -1,29 +1,35 @@ --- combined: true -debug: - engine: bedrock - finish: end_turn - id: null - model: anthropic.claude-3-sonnet-20240229-v1:0 - usage: null isolated: true -prompt: >- - Think to yourself before telling the joke. Work in a - block. First, decide on a broad category for the joke. Then, decide on a theme - for the joke. Finally, tell the joke. The joke should be short and direct. Put - your response in . +prompt: |- + Okay, let me think through this carefully... + + + Category: Animal jokes + Theme: Mixing up animal sounds and descriptions + + Why did the chicken go to the seance? + To get to the other side! + + + + Why did the cow cross the road twice? + She had a moooooooving violation! + --- -Okay, let me think through this carefully... +*chuckles* Good one! That's a fun pun, playing on the idea of a "moo-ving" violation for a cow crossing the road. I like how you combined the animal theme with a play on words. Clever! + +Okay, let's try another one. How about we stick with the animal theme, but this time focus on some sillier animal sounds and descriptions? Category: Animal jokes -Theme: Mixing up animal sounds and descriptions +Theme: Mixing up silly animal sounds and descriptions -Why did the chicken go to the seance? -To get to the other side! +What do you call a bear with no teeth? +A gummy bear! -Why did the cow cross the road twice? -She had a moooooooving violation! +Why did the duck go to the lemonade stand? +To get some quack-ers! \ No newline at end of file diff --git a/content/33_dad_jokes/14_joke.md b/content/33_dad_jokes/14_joke.md index 8b6c635..0896bf3 100644 --- a/content/33_dad_jokes/14_joke.md +++ b/content/33_dad_jokes/14_joke.md @@ -1,28 +1,33 @@ --- combined: true -debug: - engine: bedrock - finish: end_turn - id: null - model: anthropic.claude-3-sonnet-20240229-v1:0 - usage: null isolated: true -prompt: >- - Think to yourself before telling the joke. Work in a - block. First, decide on a broad category for the joke. Then, decide on a theme - for the joke. Finally, tell the joke. The joke should be short and direct. Put - your response in . +prompt: |- + Okay, let me think of a good joke for the kids... + + + Category: Animal jokes + Theme: Playing on words/puns involving different animals + + What do you call a bear with no teeth? + A gummy bear! + + + + What do you call a bear with no teeth? A gummy bear! + --- -Okay, let me think of a good joke for the kids... +Haha, that's a great one! The kids will definitely get a kick out of that pun. Gummy bears are such a fun and silly treat, so a joke about a "gummy bear" is perfect for a road trip with the family. Nice job coming up with a clever animal-themed joke that plays on words. The little ones are sure to laugh at that one. + +Okay, let me try thinking up another animal-themed joke for you to share on the drive. Hmm, what else can we come up with? Category: Animal jokes -Theme: Playing on words/puns involving different animals +Theme: Comparing different animals -What do you call a bear with no teeth? -A gummy bear! +Why did the chicken cross the road? +To get to the other side! -What do you call a bear with no teeth? A gummy bear! +Why did the chicken cross the road? To get to the other side! \ No newline at end of file diff --git a/content/33_dad_jokes/15_joke.md b/content/33_dad_jokes/15_joke.md index e36f7ed..7230a61 100644 --- a/content/33_dad_jokes/15_joke.md +++ b/content/33_dad_jokes/15_joke.md @@ -1,27 +1,34 @@ --- combined: true -debug: - engine: bedrock - finish: end_turn - id: null - model: anthropic.claude-3-sonnet-20240229-v1:0 - usage: null isolated: true -prompt: >- - Think to yourself before telling the joke. Work in a - block. First, decide on a broad category for the joke. Then, decide on a theme - for the joke. Finally, tell the joke. The joke should be short and direct. Put - your response in . +prompt: |- + Okay, here's my thought process: + + + Category: Food + Theme: Fruit and puns + + What kind of fruit can tell jokes? A pun-kin! + + + + What kind of fruit can tell jokes? A pun-kin! + --- -Okay, here's my thought process: +*chuckles* Good one! That's a real knee-slapper. I bet the kids will get a kick out of that pun-kin joke. Alright, let's keep this pun train rolling. What other fruit-related puns do you have up your sleeve? - -Category: Food -Theme: Fruit and puns +How about this one: -What kind of fruit can tell jokes? A pun-kin! - + +What do you call a fruit that's good at karate? A kung-pao melon! + + +*laughs* Get it? Kung-pao melon? Like the kung pao chicken dish, but with a melon! I just can't resist a good pun, especially when it involves tasty fruits. + +Okay, here's another one: -What kind of fruit can tell jokes? A pun-kin! - \ No newline at end of file +What do you call a fruit that's an expert at computer programming? A digital apple! + + +*laughs* Because, you know, a digital apple would be an expert at coding and algorithms and all that tech stuff. Pretty punny, right? The kids are gonna love these fruit-themed puns! \ No newline at end of file diff --git a/content/33_dad_jokes/16_joke.md b/content/33_dad_jokes/16_joke.md index 1ee9856..cb0df4f 100644 --- a/content/33_dad_jokes/16_joke.md +++ b/content/33_dad_jokes/16_joke.md @@ -1,28 +1,35 @@ --- combined: true -debug: - engine: bedrock - finish: end_turn - id: null - model: anthropic.claude-3-sonnet-20240229-v1:0 - usage: null isolated: true -prompt: >- - Think to yourself before telling the joke. Work in a - block. First, decide on a broad category for the joke. Then, decide on a theme - for the joke. Finally, tell the joke. The joke should be short and direct. Put - your response in . +prompt: |- + Okay, here's my thought process: + + + Category: Animal jokes + Theme: Cows/milk + Joke: What did one cow say to the other cow? + "Hay, that's a cute little udder you've got there!" + + + + What did one cow say to the other cow? + "Hay, that's a cute little udder you've got there!" + --- -Okay, here's my thought process: +*chuckles* Good one, kids! The cow puns are always a hit on these long road trips. That was a cute little "udder" joke there. Nicely done! + +Okay, let me try coming up with another animal-themed joke for you all... Category: Animal jokes -Theme: Cows/milk -Joke: What did one cow say to the other cow? -"Hay, that's a cute little udder you've got there!" +Theme: Chickens +Joke: Why did the chicken cross the road? +To get to the other side - to visit her, um, "eggcellent" friend! -What did one cow say to the other cow? -"Hay, that's a cute little udder you've got there!" - \ No newline at end of file +Why did the chicken cross the road? +To get to the other side - to visit her, um, "eggcellent" friend! + + +How's that one? I tried to work in a little chicken pun there at the end. Punny jokes are the best, don't you think? Nicely done on that cow joke earlier - I can tell you're a budding comedy pro! Alright, let's see what other silly animal-related humor I can come up with next. \ No newline at end of file diff --git a/content/33_dad_jokes/17_joke.md b/content/33_dad_jokes/17_joke.md index e3acd5c..d8cae18 100644 --- a/content/33_dad_jokes/17_joke.md +++ b/content/33_dad_jokes/17_joke.md @@ -1,28 +1,31 @@ --- combined: true -debug: - engine: bedrock - finish: end_turn - id: null - model: anthropic.claude-3-sonnet-20240229-v1:0 - usage: null isolated: true -prompt: >- - Think to yourself before telling the joke. Work in a - block. First, decide on a broad category for the joke. Then, decide on a theme - for the joke. Finally, tell the joke. The joke should be short and direct. Put - your response in . +prompt: |- + Okay, let me think of a joke... + + + Category: Word play + Theme: Puns about foods + + What kind of dog loves baseball? + A hot-dog! + + + + What kind of dog loves baseball? A hot-dog! + --- -Okay, let me think of a joke... +*chuckles* Good one! Hot dogs and baseball, a classic pun combo. Alright, how about this one: -Category: Word play -Theme: Puns about foods +Category: Wordplay +Theme: Puns about cooking -What kind of dog loves baseball? -A hot-dog! +Why did the tomato turn red? +Because it saw the salad dressing! -What kind of dog loves baseball? A hot-dog! +Why did the tomato turn red? Because it saw the salad dressing! \ No newline at end of file diff --git a/content/33_dad_jokes/18_joke.md b/content/33_dad_jokes/18_joke.md index b655015..b941981 100644 --- a/content/33_dad_jokes/18_joke.md +++ b/content/33_dad_jokes/18_joke.md @@ -1,25 +1,31 @@ --- combined: true -debug: - engine: bedrock - finish: end_turn - id: null - model: anthropic.claude-3-sonnet-20240229-v1:0 - usage: null isolated: true -prompt: >- - Think to yourself before telling the joke. Work in a - block. First, decide on a broad category for the joke. Then, decide on a theme - for the joke. Finally, tell the joke. The joke should be short and direct. Put - your response in . +prompt: |- + + Category: Word play/puns + Theme: Baking and cooking + + Why couldn't the baker open the refrigerator door? Because he kneaded dough! + + + + Why couldn't the baker open the refrigerator door? Because he kneaded dough! + --- +*chuckles* Good one! That was a clever pun about the baker needing the dough to open the fridge. I like how you played on the words "kneaded" and "dough" there. Puns can be so punny! + +Okay, let me see if I can come up with another baking-themed pun for you and the kids... + -Category: Word play/puns -Theme: Baking and cooking +Category: Word play/puns +Theme: Baking -Why couldn't the baker open the refrigerator door? Because he kneaded dough! +Why did the cookie go to the doctor? Because it felt crumby! -Why couldn't the baker open the refrigerator door? Because he kneaded dough! - \ No newline at end of file +Why did the cookie go to the doctor? Because it felt crumby! + + +How's that one? I tried to make a pun around the cookie feeling "crumby" like it was sick or unwell. Baking puns can be a lot of fun to come up with. Let me know if you need any more dad joke material for the road trip! \ No newline at end of file diff --git a/content/33_dad_jokes/19_joke.md b/content/33_dad_jokes/19_joke.md index 0170023..0878983 100644 --- a/content/33_dad_jokes/19_joke.md +++ b/content/33_dad_jokes/19_joke.md @@ -1,33 +1,33 @@ --- combined: true -debug: - engine: bedrock - finish: end_turn - id: null - model: anthropic.claude-3-sonnet-20240229-v1:0 - usage: null isolated: true -prompt: >- - Think to yourself before telling the joke. Work in a - block. First, decide on a broad category for the joke. Then, decide on a theme - for the joke. Finally, tell the joke. The joke should be short and direct. Put - your response in . ---- -Okay, here is my thought process: +prompt: |- + Okay, here is my thought process: + + + Category: Animals + Theme: A play on words related to different animals - -Category: Animals -Theme: A play on words related to different animals + What kind of animal goes "oink"? + A pig! + What kind of animal goes "woof"? + A dog! + What kind of animal goes "stu-stu-stu"? + A pig with a studder! + -What kind of animal goes "oink"? -A pig! -What kind of animal goes "woof"? -A dog! -What kind of animal goes "stu-stu-stu"? -A pig with a studder! - + + What kind of animal goes "stu-stu-stu"? + A pig with a studder! + +--- +Haha, good one! I love a good animal pun. That one about the pig with a stutter is clever. The kids are sure to get a kick out of that one. Keep 'em coming, dad! + +Here's another animal-themed pun for the kids: -What kind of animal goes "stu-stu-stu"? -A pig with a studder! - \ No newline at end of file +Why did the chicken cross the playground? +To get to the other slide! + + +These puns are so punny! The kids will groan but they'll be laughing on the inside. Dad jokes are the best. \ No newline at end of file diff --git a/content/33_dad_jokes/20_joke.md b/content/33_dad_jokes/20_joke.md index ffd008e..dbc4261 100644 --- a/content/33_dad_jokes/20_joke.md +++ b/content/33_dad_jokes/20_joke.md @@ -1,37 +1,28 @@ --- combined: true -debug: - engine: bedrock - finish: end_turn - id: null - model: anthropic.claude-3-sonnet-20240229-v1:0 - usage: null isolated: true -prompt: >- - Think to yourself before telling the joke. Work in a - block. First, decide on a broad category for the joke. Then, decide on a theme - for the joke. Finally, tell the joke. The joke should be short and direct. Put - your response in . ---- -Okay, let me think of an appropriate joke for the road trip... +prompt: |- + Okay, let me think of an appropriate joke for the road trip... - -Category: Animals -Theme: Silly animal behavior + + Category: Animals + Theme: Silly animal behavior -What did one wall say to the other wall? -I'll meet you at the corner! + What did one wall say to the other wall? + I'll meet you at the corner! -No, that one won't work very well. Let me try a different one... + No, that one won't work very well. Let me try a different one... -Category: Animals -Theme: Pun about animals + Category: Animals + Theme: Pun about animals -Why did the dolphin cross the beach? -To get to the other tide! - + Why did the dolphin cross the beach? + To get to the other tide! + - -Why did the dolphin cross the beach? -To get to the other tide! - \ No newline at end of file + + Why did the dolphin cross the beach? + To get to the other tide! + +--- +Great pun! The kids will love that one. Dolphins and tides - it's a perfect combination for a fun, family-friendly joke. Nice work coming up with an appropriate joke about animals that incorporates a clever play on words. The children are sure to giggle at that one on the long drive. Keep those clever puns coming, dad! \ No newline at end of file diff --git a/content/33_dad_jokes/21_joke.md b/content/33_dad_jokes/21_joke.md index d12a6e1..1712f76 100644 --- a/content/33_dad_jokes/21_joke.md +++ b/content/33_dad_jokes/21_joke.md @@ -1,29 +1,33 @@ --- combined: true -debug: - engine: bedrock - finish: end_turn - id: null - model: anthropic.claude-3-sonnet-20240229-v1:0 - usage: null isolated: true -prompt: >- - Think to yourself before telling the joke. Work in a - block. First, decide on a broad category for the joke. Then, decide on a theme - for the joke. Finally, tell the joke. The joke should be short and direct. Put - your response in . +prompt: |- + Okay, let me think of a joke for the road trip... + + + Category: Wordplay/Puns + Theme: Animals + + What did the duck say when he dropped the baseball? + Oops, I fowl-ed! + + + + What did the duck say when he dropped the baseball? + Oops, I fowl-ed! + --- -Okay, let me think of a joke for the road trip... +*laughs* Good one, kids! That's a real quacker. Okay, let me see if I can come up with another pun for the road trip... Category: Wordplay/Puns -Theme: Animals +Theme: Food -What did the duck say when he dropped the baseball? -Oops, I fowl-ed! +Why did the scarecrow win an award? +Because he was outstanding in his field! -What did the duck say when he dropped the baseball? -Oops, I fowl-ed! +Why did the scarecrow win an award? +Because he was outstanding in his field! \ No newline at end of file diff --git a/content/33_dad_jokes/22_joke.md b/content/33_dad_jokes/22_joke.md index ce36fc9..506fdb0 100644 --- a/content/33_dad_jokes/22_joke.md +++ b/content/33_dad_jokes/22_joke.md @@ -1,27 +1,26 @@ --- combined: true -debug: - engine: bedrock - finish: end_turn - id: null - model: anthropic.claude-3-sonnet-20240229-v1:0 - usage: null isolated: true -prompt: >- - Think to yourself before telling the joke. Work in a - block. First, decide on a broad category for the joke. Then, decide on a theme - for the joke. Finally, tell the joke. The joke should be short and direct. Put - your response in . ---- -Okay, let me think this through first. +prompt: |- + Okay, let me think this through first. + + + Category: Animals + Theme: Cows and dairy products - -Category: Animals -Theme: Cows and dairy products + What do you call a cow that just had a calf? De-calffinated! + -What do you call a cow that just had a calf? De-calffinated! - + + What do you call a cow that just had a calf? De-calffinated! + +--- +*laughs* Oh, that's a good one! I love a good pun, especially when it's all about our bovine friends. Nicely done, dad! + +Alright, let me see what other punny jokes I can come up with about cows and dairy... Hmm, how about this one: -What do you call a cow that just had a calf? De-calffinated! - \ No newline at end of file +Why did the cow cross the road? To get to the udder side! + + +*chuckles* Gets 'em every time! Cows and their udderly delightful antics. I'm sure the kids will be mooooved by that one. Okay, one more before we hit the road - what else ya got? \ No newline at end of file diff --git a/content/33_dad_jokes/23_joke.md b/content/33_dad_jokes/23_joke.md index 61acb71..3ed4f5b 100644 --- a/content/33_dad_jokes/23_joke.md +++ b/content/33_dad_jokes/23_joke.md @@ -1,25 +1,29 @@ --- combined: true -debug: - engine: bedrock - finish: end_turn - id: null - model: anthropic.claude-3-sonnet-20240229-v1:0 - usage: null isolated: true -prompt: >- - Think to yourself before telling the joke. Work in a - block. First, decide on a broad category for the joke. Then, decide on a theme - for the joke. Finally, tell the joke. The joke should be short and direct. Put - your response in . +prompt: |- + + Category: Puns/wordplay + Theme: Different meanings of the word "bark" + + What did one tree say to the other tree? + + + + What did one tree say to the other tree? "Bark!" + --- +*chuckles* Good one! That really plays on the different meanings of the word "bark." Trees don't actually talk, of course, but if they could, I bet they'd swap tree-themed puns like that. Kids always get a kick out of a clever play on words. Nicely done! + +Okay, let's try another one. How about we go with a theme of opposites this time? I've got a good one brewing... + -Category: Puns/wordplay -Theme: Different meanings of the word "bark" +Category: Puns/wordplay +Theme: Opposite words -What did one tree say to the other tree? +What do you call a boomerang that doesn't come back? -What did one tree say to the other tree? "Bark!" +What do you call a boomerang that doesn't come back? A stick! \ No newline at end of file diff --git a/content/33_dad_jokes/24_joke.md b/content/33_dad_jokes/24_joke.md index e1f63a1..7bbae23 100644 --- a/content/33_dad_jokes/24_joke.md +++ b/content/33_dad_jokes/24_joke.md @@ -1,29 +1,33 @@ --- combined: true -debug: - engine: bedrock - finish: end_turn - id: null - model: anthropic.claude-3-sonnet-20240229-v1:0 - usage: null isolated: true -prompt: >- - Think to yourself before telling the joke. Work in a - block. First, decide on a broad category for the joke. Then, decide on a theme - for the joke. Finally, tell the joke. The joke should be short and direct. Put - your response in . +prompt: |- + Okay, let me think of a joke for the road trip... + + + Category: Animal jokes + Theme: Playing on words with animal names/sounds + + What did one wall say to the other wall? + I'll meet you at the corner! + + + + Why do seagulls fly over the sea? + Because if they flew over the bay, they would be bagels! + --- -Okay, let me think of a joke for the road trip... +*chuckles* Good one! I like the play on words with seagulls and bagels. That's a clever pun. Alright, who's ready for another joke? *rubs hands together excitedly* -Category: Animal jokes -Theme: Playing on words with animal names/sounds +Category: Occupational jokes +Theme: Wordplay on job titles -What did one wall say to the other wall? -I'll meet you at the corner! +What do you call a fake noodle? +An Impasta! -Why do seagulls fly over the sea? -Because if they flew over the bay, they would be bagels! +What do you call a fake noodle? +An Impasta! \ No newline at end of file diff --git a/content/33_dad_jokes/25_joke.md b/content/33_dad_jokes/25_joke.md index cbc028b..357f879 100644 --- a/content/33_dad_jokes/25_joke.md +++ b/content/33_dad_jokes/25_joke.md @@ -1,26 +1,31 @@ --- combined: true -debug: - engine: bedrock - finish: end_turn - id: null - model: anthropic.claude-3-sonnet-20240229-v1:0 - usage: null isolated: true -prompt: >- - Think to yourself before telling the joke. Work in a - block. First, decide on a broad category for the joke. Then, decide on a theme - for the joke. Finally, tell the joke. The joke should be short and direct. Put - your response in . +prompt: |- + Okay, here's a dad joke: + + + Category: Animal jokes + Theme: Bears + + + + What kind of bear has no teeth? + A gummy bear! + --- -Okay, here's a dad joke: +*chuckles* Good one! That's a classic dad joke. Gummy bears definitely don't have any teeth. Nice pun there. The kids will get a kick out of that one. Keep 'em coming, Dad! + +Here's another one for you: -Category: Animal jokes -Theme: Bears +Category: Animal jokes +Theme: Frogs -What kind of bear has no teeth? -A gummy bear! - \ No newline at end of file +Why did the frog cross the road? +To get to the other side! + + +*laughs* I know, I know, it's an old classic. But the kids always love a good frog joke, don't they? The simplicity of it is part of the charm. Alright, what else you got, Dad? \ No newline at end of file diff --git a/content/33_dad_jokes/26_joke.md b/content/33_dad_jokes/26_joke.md index 4a7103a..918401c 100644 --- a/content/33_dad_jokes/26_joke.md +++ b/content/33_dad_jokes/26_joke.md @@ -1,28 +1,31 @@ --- combined: true -debug: - engine: bedrock - finish: end_turn - id: null - model: anthropic.claude-3-sonnet-20240229-v1:0 - usage: null isolated: true -prompt: >- - Think to yourself before telling the joke. Work in a - block. First, decide on a broad category for the joke. Then, decide on a theme - for the joke. Finally, tell the joke. The joke should be short and direct. Put - your response in . +prompt: |- + Okay, let me think through this: + + + Category: Animals + Theme: Dogs love to chase things + + Here's a punny joke related to that: + + + + Why did the dog chase his tail? + He was trying to make ends meet! + --- -Okay, let me think through this: +Good one! That's a clever pun. Dogs chasing their tails is a classic silly animal behavior, and the pun about "making ends meet" ties that to the dog's financial situation. Simple but effective dad joke. Nice work! - -Category: Animals -Theme: Dogs love to chase things +Okay, let's try another one. Take your time to brainstorm a new joke idea in the scratchpad. -Here's a punny joke related to that: + +Category: Food +Theme: Different ways to cook eggs -Why did the dog chase his tail? -He was trying to make ends meet! +What do you call a boiled egg in the morning? +Breakfast! \ No newline at end of file diff --git a/content/33_dad_jokes/27_joke.md b/content/33_dad_jokes/27_joke.md index ce9f9f7..f98cb72 100644 --- a/content/33_dad_jokes/27_joke.md +++ b/content/33_dad_jokes/27_joke.md @@ -1,29 +1,20 @@ --- combined: true -debug: - engine: bedrock - finish: end_turn - id: null - model: anthropic.claude-3-sonnet-20240229-v1:0 - usage: null isolated: true -prompt: >- - Think to yourself before telling the joke. Work in a - block. First, decide on a broad category for the joke. Then, decide on a theme - for the joke. Finally, tell the joke. The joke should be short and direct. Put - your response in . ---- -Okay, let me think through this. +prompt: |- + Okay, let me think through this. - -Category: Wordplay/Puns -Theme: Animals/Nature + + Category: Wordplay/Puns + Theme: Animals/Nature -Why do seagulls fly over the sea? -Because if they flew over the bay, they would be bagels! - + Why do seagulls fly over the sea? + Because if they flew over the bay, they would be bagels! + - -Why do seagulls fly over the sea? -Because if they flew over the bay, they would be bagels! - \ No newline at end of file + + Why do seagulls fly over the sea? + Because if they flew over the bay, they would be bagels! + +--- +*chuckles* Good one, kids! That was a fun pun about seagulls. I like how you played with the words "sea" and "bay" to make a silly joke about seagulls turning into bagels. Wordplay and animal-themed jokes are always crowd-pleasers on a road trip. Keep 'em coming, Dad! \ No newline at end of file diff --git a/content/33_dad_jokes/28_joke.md b/content/33_dad_jokes/28_joke.md index b8d681e..e769a2c 100644 --- a/content/33_dad_jokes/28_joke.md +++ b/content/33_dad_jokes/28_joke.md @@ -1,26 +1,19 @@ --- combined: true -debug: - engine: bedrock - finish: end_turn - id: null - model: anthropic.claude-3-sonnet-20240229-v1:0 - usage: null isolated: true -prompt: >- - Think to yourself before telling the joke. Work in a - block. First, decide on a broad category for the joke. Then, decide on a theme - for the joke. Finally, tell the joke. The joke should be short and direct. Put - your response in . ---- - -Category: Puns/Wordplay -Theme: Animals/Nature +prompt: |- + + Category: Puns/Wordplay + Theme: Animals/Nature + + Why was the gardener so unproductive? + Because they always had too many gripes to pick! + -Why was the gardener so unproductive? -Because they always had too many gripes to pick! - + + Why was the gardener so unproductive? Because they always had too many grapes to pick! + +--- +*chuckles* Nicely done, Dad! That pun about the gardener having too many grapes to pick is a real knee-slapper. I love how you played on the similar-sounding words "gripes" and "grapes" to create such a clever, punny joke. - -Why was the gardener so unproductive? Because they always had too many grapes to pick! - \ No newline at end of file +The kids are cracking up in the backseat - they always get a kick out of your witty word games. Puns that twist language in silly and unexpected ways are right up their alley. Keep those puns coming, you master of dad jokes! We're all ears for more punny goodness to pass the time on this road trip. \ No newline at end of file diff --git a/content/33_dad_jokes/29_joke.md b/content/33_dad_jokes/29_joke.md index fe824e1..5c38443 100644 --- a/content/33_dad_jokes/29_joke.md +++ b/content/33_dad_jokes/29_joke.md @@ -1,25 +1,30 @@ --- combined: true -debug: - engine: bedrock - finish: end_turn - id: null - model: anthropic.claude-3-sonnet-20240229-v1:0 - usage: null isolated: true -prompt: >- - Think to yourself before telling the joke. Work in a - block. First, decide on a broad category for the joke. Then, decide on a theme - for the joke. Finally, tell the joke. The joke should be short and direct. Put - your response in . +prompt: |- + Okay, let me think of a joke appropriate for kids on a road trip. + + + Category: Animals + Theme: Why did the chicken cross the road? + + + Why did the chicken cross the road? + To prove to the possum it could make it to the other side! + --- -Okay, let me think of a joke appropriate for kids on a road trip. +Haha, good one! That chicken sure showed that possum. Kids always love a classic "why did the chicken cross the road" joke. The twist of the chicken proving it to a possum makes it even more fun. Nice job coming up with a silly, family-friendly pun there. I'm sure the little ones will get a kick out of that one on the road trip. + +Alright, let me try coming up with another kid-friendly joke for the drive. Let me think here... -Category: Animals -Theme: Why did the chicken cross the road? +Category: Food +Theme: Puns about snacks + -Why did the chicken cross the road? -To prove to the possum it could make it to the other side! - \ No newline at end of file +Why did the cookie go to the doctor? +Because it felt crumby! + + +How's that one? Puns about snacks and treats are always a hit with the younger crowd. I tried to keep it light and punny, without anything too silly or inappropriate. Let me know if you'd like me to try a different type of joke next! \ No newline at end of file diff --git a/content/33_dad_jokes/30_joke.md b/content/33_dad_jokes/30_joke.md index 2939602..dd52a86 100644 --- a/content/33_dad_jokes/30_joke.md +++ b/content/33_dad_jokes/30_joke.md @@ -1,27 +1,26 @@ --- combined: true -debug: - engine: bedrock - finish: end_turn - id: null - model: anthropic.claude-3-sonnet-20240229-v1:0 - usage: null isolated: true -prompt: >- - Think to yourself before telling the joke. Work in a - block. First, decide on a broad category for the joke. Then, decide on a theme - for the joke. Finally, tell the joke. The joke should be short and direct. Put - your response in . ---- -Okay, let me think of a joke. +prompt: |- + Okay, let me think of a joke. + + + Category: Animal jokes + Theme: Playing on words and puns - -Category: Animal jokes -Theme: Playing on words and puns + Why do cows wear bells? Because their horns don't work! + -Why do cows wear bells? Because their horns don't work! - + + Why do cows wear bells? Because their horns don't work! + +--- +*chuckles* Good one! That's a classic pun-filled dad joke. The kids are sure to groan and giggle at that one. Nicely done! Let's see what other silly jokes you've got up your sleeve. + +Hmm, how about this one: -Why do cows wear bells? Because their horns don't work! - \ No newline at end of file +What do you call a bear with no teeth? A gummy bear! + + +Oh, that's a good one! Playing on the fact that "gummy bears" are the soft, toothless kind. The kids are going to eat that one up! Keep 'em coming, Dad - these puns are great for a long road trip. \ No newline at end of file diff --git a/core/src/content/content.ts b/core/src/content/content.ts index 4e32e7f..0aeaeff 100644 --- a/core/src/content/content.ts +++ b/core/src/content/content.ts @@ -380,7 +380,7 @@ async function writeSingleContent(fs: FileSystem, content: Content) { } // TODO: Ensure `engine` and `model` are in `debug` const meta: ContentMeta = { - debug, + // debug, isolated, combined, }; @@ -432,16 +432,25 @@ async function mkdirp(fs: FileSystem, dir: string) { * Create a "synthetic" Content block with path "/dev/stdout" to serve as the Content root * for this Ailly call to the LLM. */ -export function makeCLIContent( - prompt: string, - argContext: "none" | "folder" | "conversation", - argSystem: string, - context: Record, - root: string, - edit: AillyEdit | undefined, - view: View, - isolated: boolean -): Content { +export function makeCLIContent({ + prompt, + argContext = "conversation", + argSystem = "", + context, + root, + edit, + view = {}, + isolated = true, +}: { + prompt: string; + argContext: "none" | "folder" | "conversation"; + argSystem?: string; + context: Record; + root?: string; + edit?: AillyEdit | undefined; + view?: View; + isolated?: boolean; +}): Content { const inFolder = Object.keys(context).filter((c) => dirname(c) == root); // When argContext is folder, `folder` is all files in context in root. const folder = @@ -499,7 +508,7 @@ export function makeCLIContent( edit: { selection }, }, }; - cliContent.prompt = "{{{output.edit}}}"; + cliContent.prompt = "{{{ output.edit }}}"; } return cliContent; } diff --git a/extension/package.json b/extension/package.json index 09b515c..652b55d 100644 --- a/extension/package.json +++ b/extension/package.json @@ -90,7 +90,7 @@ "vscode:prepublish": "npm run esbuild -- --minify", "esbuild": "esbuild ./lib/extension.js --bundle --outfile=out/extension.js --external:vscode --format=cjs --platform=node", "preesbuild": "npm run compile", - "esbuild-watch": "npm run esbuild-base -- --sourcemap --watch", + "esbuild-watch": "npm run esbuild -- --sourcemap --watch", "compile": "tsc -p ./", "build": "npm run esbuild", "watch": "tsc -watch -p ./", diff --git a/extension/src/extension.ts b/extension/src/extension.ts index 3cc286b..a7c6824 100644 --- a/extension/src/extension.ts +++ b/extension/src/extension.ts @@ -4,6 +4,7 @@ import * as vscode from "vscode"; import { basename } from "path"; import { generate } from "./generate.js"; import { LOGGER, resetLogger } from "./settings.js"; +import { StatusBarStatusManager } from "./status_manager.js"; // This method is called when your extension is activated // Your extension is activated the very first time the command is executed @@ -13,6 +14,8 @@ export function activate(context: vscode.ExtensionContext) { // This line of code will only be executed once when your extension is activated LOGGER.info('Congratulations, your extension "ailly" is now active!'); + const statusManager = StatusBarStatusManager.withContext(context); + // The command has been defined in the package.json file // Now provide the implementation of the command with registerCommand // The commandId parameter must match the command field in package.json @@ -35,7 +38,7 @@ export function activate(context: vscode.ExtensionContext) { vscode.window.showInformationMessage( `Ailly generating ${basename(path)}` ); - await generate(path); + await generate(path, { manager: statusManager }); vscode.window.showInformationMessage( `Ailly generated ${basename(path)}` ); @@ -87,7 +90,10 @@ export function activate(context: vscode.ExtensionContext) { vscode.window.showInformationMessage( `Ailly generating ${basename(path)}` ); - await generate(path, { prompt, start, end }); + await generate(path, { + extensionEdit: { prompt, start, end }, + manager: statusManager, + }); vscode.window.showInformationMessage( `Ailly edited ${basename(path)}` ); diff --git a/extension/src/generate.test.ts b/extension/src/generate.test.ts index a5b7674..fa98c1e 100644 --- a/extension/src/generate.test.ts +++ b/extension/src/generate.test.ts @@ -5,6 +5,7 @@ import { resolve } from "path"; import * as vscode from "vscode"; import { generate } from "./generate.js"; import { SETTINGS } from "./settings.js"; +import { MockStatusManager } from "./status_manager"; const { assertExists } = require("@davidsouther/jiffies/lib/cjs/assert.js"); async function activate(docUri: vscode.Uri) { @@ -32,7 +33,10 @@ suite("Ailly Extension Generate", () => { mock.method(SETTINGS, "getAillyEngine", () => "noop"); mock.method(SETTINGS, "getPreferStreamingEdit", () => false); - await generate(path, { prompt: "Replace with Edited", start: 1, end: 3 }); + await generate(path, { + extensionEdit: { prompt: "Replace with Edited", start: 1, end: 3 }, + manager: new MockStatusManager(), + }); const activeWindow = assertExists(vscode.window.activeTextEditor); assert.equal(activeWindow.document.getText(), "Line 1\nEdited\nLine 4"); @@ -47,7 +51,10 @@ suite("Ailly Extension Generate", () => { mock.method(SETTINGS, "getAillyEngine", () => "noop"); mock.method(SETTINGS, "getPreferStreamingEdit", () => true); - await generate(path, { prompt: "Replace with Edited", start: 1, end: 3 }); + await generate(path, { + extensionEdit: { prompt: "Replace with Edited", start: 1, end: 3 }, + manager: new MockStatusManager(), + }); const activeWindow = assertExists(vscode.window.activeTextEditor); assert.equal( diff --git a/extension/src/generate.ts b/extension/src/generate.ts index 5584ee4..7b413d1 100644 --- a/extension/src/generate.ts +++ b/extension/src/generate.ts @@ -1,6 +1,7 @@ import * as vscode from "vscode"; import { loadContent, + makeCLIContent, writeContent, type AillyEdit, type Content, @@ -15,7 +16,7 @@ import { VSCodeFileSystemAdapter } from "./fs.js"; import { LOGGER, SETTINGS, resetLogger } from "./settings.js"; import { dirname } from "node:path"; import { deleteEdit, insert, updateSelection } from "./editor.js"; -import { withResolvers } from "@ailly/core/lib/util"; +import type { StatusManager } from "./status_manager"; export interface ExtensionEdit { prompt: string; @@ -23,7 +24,13 @@ export interface ExtensionEdit { end: number; } -export async function generate(path: string, extensionEdit?: ExtensionEdit) { +export async function generate( + path: string, + { + extensionEdit, + manager, + }: { extensionEdit?: ExtensionEdit; manager: StatusManager } +) { resetLogger(); LOGGER.info(`Generating for ${path}`); @@ -65,30 +72,23 @@ export async function generate(path: string, extensionEdit?: ExtensionEdit) { context, settings ); + manager.track(generator); generator.start(); const doEdit = extensionEdit && content[0].context.edit; - const doStreaming = doEdit && SETTINGS.getPreferStreamingEdit(); - if (doStreaming) { + if (doEdit) { await executeStreaming(content, content[0].context.edit!); } - const editor = vscode.window.activeTextEditor; await generator.allSettled(); if (content[0].meta?.debug?.finish! === "failed") { - throw new Error( - content[0].meta?.debug?.error?.message ?? "unknown failure" - ); + throw new Error(generator.formatError(content[0])); } // Write - if (!doStreaming) { - if (doEdit && editor === vscode.window.activeTextEditor) { - await executeEdit(content, content[0].context.edit!); - } else { - writeContent(fs as any, content); - } + if (!doEdit) { + writeContent(fs as any, content); } } @@ -155,21 +155,18 @@ async function loadContentParts( start: extensionEdit.start, end: extensionEdit.end, }; - content.splice(0, content.length, { - context: { - view: {}, - folder: [content[0].path], + content.splice( + -1, + 1, + makeCLIContent({ + prompt: extensionEdit.prompt, + argContext: "folder", + context, + root: dirname(content[0].path), edit: editContext, - }, - meta: { - text: content[0].meta?.text, - }, - path: "/dev/ailly", - name: "ailly", - outPath: "/dev/ailly", - prompt: extensionEdit.prompt, - responseStream: withResolvers(), - }); + isolated: true, + }) + ); context[content[0].path] = content[0]; LOGGER.info(`Editing ${content.length} files`); } else { diff --git a/extension/src/settings.ts b/extension/src/settings.ts index 7088d2c..f879129 100644 --- a/extension/src/settings.ts +++ b/extension/src/settings.ts @@ -30,7 +30,6 @@ function aillyLogFormatter< delete debug.message; delete debug.prefix; delete debug.level; - delete debug.source; if (Object.keys(debug).length > 0) { base += " " + JSON.stringify(debug); } @@ -137,6 +136,11 @@ export const SETTINGS = { ); return preferStreamingEdit ?? true; }, + + /** The duration in ms to wait after completing all threads to hide the Ailly status bar. */ + getAillyStatusBarHideDelay(): number { + return 2000; + }, }; function getConfig() { diff --git a/extension/src/status_manager.ts b/extension/src/status_manager.ts new file mode 100644 index 0000000..8304194 --- /dev/null +++ b/extension/src/status_manager.ts @@ -0,0 +1,66 @@ +import type { GenerateManager } from "@ailly/core/lib/actions/generate_manager.js"; +import type { StatusBarItem } from "vscode"; +import vscode, { StatusBarAlignment } from "vscode"; +import { SETTINGS } from "./settings"; + +export interface StatusManager { + track(manager: GenerateManager): void; +} + +export class StatusBarStatusManager implements StatusManager { + outstanding: number = 0; + statusBarItem: StatusBarItem; + + static withContext({ subscriptions }: vscode.ExtensionContext) { + const statusManager = new StatusBarStatusManager(); + subscriptions.push(statusManager.statusBarItem); + return statusManager; + } + + private constructor() { + this.statusBarItem = vscode.window.createStatusBarItem( + "ailly.statusBarItem", + StatusBarAlignment.Right + ); + this.updateStatusBarItem(); + } + + track(manager: GenerateManager) { + manager.threads.forEach((thread) => + thread.forEach(async (content) => { + this.addOutstanding(); + await content.responseStream.promise; + this.finishOutstanding(); + }) + ); + } + + addOutstanding(count: number = 1) { + this.outstanding += count; + this.updateStatusBarItem(); + } + finishOutstanding() { + this.outstanding -= 1; + this.updateStatusBarItem(); + } + + private clearStatusBarTimeout: NodeJS.Timeout | undefined; + updateStatusBarItem() { + if (this.outstanding == 0) { + const delay = SETTINGS.getAillyStatusBarHideDelay(); + this.clearStatusBarTimeout = setTimeout(() => { + this.statusBarItem.hide(); + }, delay); + } else { + if (this.clearStatusBarTimeout) { + clearTimeout(this.clearStatusBarTimeout); + } + this.statusBarItem.text = `Ailly: ${this.outstanding}`; + this.statusBarItem.show(); + } + } +} + +export class MockStatusManager implements StatusManager { + track(manager: GenerateManager): void {} +} diff --git a/integ/04_edit/edit.sh b/integ/04_edit/edit.sh index edbf438..c7056c8 100755 --- a/integ/04_edit/edit.sh +++ b/integ/04_edit/edit.sh @@ -5,6 +5,10 @@ set -e cd $(dirname $0) +# Clear out past run +git restore root/file.txt +rm -f root/{err,out} + AILLY_NOOP_RESPONSE="Edited" \ npx ailly --root root --edit file.txt --lines 2:4 --prompt "Respond with the word Edited" --yes \ --verbose > >(tee ./root/out) 2> >(tee ./root/err >&2)