Remove deprecated console_new package
				
					
				
			Deleted the `console_new` package, including its agent, container, execution, and utility files. Updated dependencies and replaced references to align with the maintained code structure.
This commit is contained in:
		
							
								
								
									
										14
									
								
								go.mod
									
									
									
									
									
								
							
							
						
						
									
										14
									
								
								go.mod
									
									
									
									
									
								
							| @@ -7,7 +7,7 @@ replace github.com/rocketlaunchr/google-search => github.com/chrisjoyce911/googl | |||||||
| //replace gitea.stevedudenhoeffer.com/steve/go-llm => ../go-llm | //replace gitea.stevedudenhoeffer.com/steve/go-llm => ../go-llm | ||||||
|  |  | ||||||
| require ( | require ( | ||||||
| 	gitea.stevedudenhoeffer.com/steve/go-extractor v0.0.0-20250318064250-39453288ce2a | 	gitea.stevedudenhoeffer.com/steve/go-extractor v0.0.0-20251028042419-868acfae40b8 | ||||||
| 	gitea.stevedudenhoeffer.com/steve/go-llm v0.0.0-20250502021123-e9baf7910e00 | 	gitea.stevedudenhoeffer.com/steve/go-llm v0.0.0-20250502021123-e9baf7910e00 | ||||||
| 	github.com/Edw590/go-wolfram v0.0.0-20241010091529-fb9031908c5d | 	github.com/Edw590/go-wolfram v0.0.0-20241010091529-fb9031908c5d | ||||||
| 	github.com/advancedlogic/GoOse v0.0.0-20231203033844-ae6b36caf275 | 	github.com/advancedlogic/GoOse v0.0.0-20231203033844-ae6b36caf275 | ||||||
| @@ -17,7 +17,7 @@ require ( | |||||||
| 	github.com/joho/godotenv v1.5.1 | 	github.com/joho/godotenv v1.5.1 | ||||||
| 	github.com/lrstanley/go-ytdlp v0.0.0-20250501010938-80d02fe36936 | 	github.com/lrstanley/go-ytdlp v0.0.0-20250501010938-80d02fe36936 | ||||||
| 	github.com/opencontainers/image-spec v1.1.1 | 	github.com/opencontainers/image-spec v1.1.1 | ||||||
| 	github.com/playwright-community/playwright-go v0.5101.0 | 	github.com/playwright-community/playwright-go v0.5200.1 | ||||||
| 	github.com/rocketlaunchr/google-search v1.1.6 | 	github.com/rocketlaunchr/google-search v1.1.6 | ||||||
| 	github.com/urfave/cli v1.22.16 | 	github.com/urfave/cli v1.22.16 | ||||||
| 	go.starlark.net v0.0.0-20250318223901-d9371fef63fe | 	go.starlark.net v0.0.0-20250318223901-d9371fef63fe | ||||||
| @@ -95,12 +95,12 @@ require ( | |||||||
| 	go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.35.0 // indirect | 	go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.35.0 // indirect | ||||||
| 	go.opentelemetry.io/otel/metric v1.35.0 // indirect | 	go.opentelemetry.io/otel/metric v1.35.0 // indirect | ||||||
| 	go.opentelemetry.io/otel/trace v1.35.0 // indirect | 	go.opentelemetry.io/otel/trace v1.35.0 // indirect | ||||||
| 	golang.org/x/crypto v0.37.0 // indirect | 	golang.org/x/crypto v0.43.0 // indirect | ||||||
| 	golang.org/x/net v0.39.0 // indirect | 	golang.org/x/net v0.46.0 // indirect | ||||||
| 	golang.org/x/oauth2 v0.29.0 // indirect | 	golang.org/x/oauth2 v0.29.0 // indirect | ||||||
| 	golang.org/x/sync v0.13.0 // indirect | 	golang.org/x/sync v0.17.0 // indirect | ||||||
| 	golang.org/x/sys v0.32.0 // indirect | 	golang.org/x/sys v0.37.0 // indirect | ||||||
| 	golang.org/x/text v0.24.0 // indirect | 	golang.org/x/text v0.30.0 // indirect | ||||||
| 	golang.org/x/time v0.11.0 // indirect | 	golang.org/x/time v0.11.0 // indirect | ||||||
| 	google.golang.org/api v0.231.0 // indirect | 	google.golang.org/api v0.231.0 // indirect | ||||||
| 	google.golang.org/appengine v1.6.8 // indirect | 	google.golang.org/appengine v1.6.8 // indirect | ||||||
|   | |||||||
							
								
								
									
										28
									
								
								go.sum
									
									
									
									
									
								
							
							
						
						
									
										28
									
								
								go.sum
									
									
									
									
									
								
							| @@ -11,8 +11,8 @@ cloud.google.com/go/compute/metadata v0.6.0 h1:A6hENjEsCDtC1k8byVsgwvVcioamEHvZ4 | |||||||
| cloud.google.com/go/compute/metadata v0.6.0/go.mod h1:FjyFAW1MW0C203CEOMDTu3Dk1FlqW3Rga40jzHL4hfg= | cloud.google.com/go/compute/metadata v0.6.0/go.mod h1:FjyFAW1MW0C203CEOMDTu3Dk1FlqW3Rga40jzHL4hfg= | ||||||
| cloud.google.com/go/longrunning v0.6.7 h1:IGtfDWHhQCgCjwQjV9iiLnUta9LBCo8R9QmAFsS/PrE= | cloud.google.com/go/longrunning v0.6.7 h1:IGtfDWHhQCgCjwQjV9iiLnUta9LBCo8R9QmAFsS/PrE= | ||||||
| cloud.google.com/go/longrunning v0.6.7/go.mod h1:EAFV3IZAKmM56TyiE6VAP3VoTzhZzySwI/YI1s/nRsY= | cloud.google.com/go/longrunning v0.6.7/go.mod h1:EAFV3IZAKmM56TyiE6VAP3VoTzhZzySwI/YI1s/nRsY= | ||||||
| gitea.stevedudenhoeffer.com/steve/go-extractor v0.0.0-20250318064250-39453288ce2a h1:LZriHuPVjdus7Haz+qEFYgr+g/eOdmeAvlbgk67DDHA= | gitea.stevedudenhoeffer.com/steve/go-extractor v0.0.0-20251028042419-868acfae40b8 h1:AaoLRGM7EFKtyx8+2vBuLoRmGxXdpkHpVF5XBtbWrXI= | ||||||
| gitea.stevedudenhoeffer.com/steve/go-extractor v0.0.0-20250318064250-39453288ce2a/go.mod h1:fzvvUfN8ej2u1ruCsABG+D+2dAPfOklInS4b1pvog1M= | gitea.stevedudenhoeffer.com/steve/go-extractor v0.0.0-20251028042419-868acfae40b8/go.mod h1:RjdXeJjOcnilhFf1O8cKOUaeGpuAazlQ2ectwgpjzbs= | ||||||
| gitea.stevedudenhoeffer.com/steve/go-llm v0.0.0-20250502021123-e9baf7910e00 h1:yPVQZG4xdENkWZi/9OLQcFSQb603ftWUTRct51Q64xc= | gitea.stevedudenhoeffer.com/steve/go-llm v0.0.0-20250502021123-e9baf7910e00 h1:yPVQZG4xdENkWZi/9OLQcFSQb603ftWUTRct51Q64xc= | ||||||
| gitea.stevedudenhoeffer.com/steve/go-llm v0.0.0-20250502021123-e9baf7910e00/go.mod h1:RPbuI2VSwQJArwr4tdqmu+fEKlhpro5Cqtq6aC4Cp1w= | gitea.stevedudenhoeffer.com/steve/go-llm v0.0.0-20250502021123-e9baf7910e00/go.mod h1:RPbuI2VSwQJArwr4tdqmu+fEKlhpro5Cqtq6aC4Cp1w= | ||||||
| github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c h1:udKWzYgxTojEKWjV8V+WSxDXJ4NFATAsZjh8iIbsQIg= | github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c h1:udKWzYgxTojEKWjV8V+WSxDXJ4NFATAsZjh8iIbsQIg= | ||||||
| @@ -206,8 +206,8 @@ github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE | |||||||
| github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= | github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= | ||||||
| github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= | github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= | ||||||
| github.com/pkg/profile v1.4.0/go.mod h1:NWz/XGvpEW1FyYQ7fCx4dqYBLlfTcE+A9FLAkNKqjFE= | github.com/pkg/profile v1.4.0/go.mod h1:NWz/XGvpEW1FyYQ7fCx4dqYBLlfTcE+A9FLAkNKqjFE= | ||||||
| github.com/playwright-community/playwright-go v0.5101.0 h1:gVCMZThDO76LJ/aCI27lpB8hEAWhZszeS0YB+oTxJp0= | github.com/playwright-community/playwright-go v0.5200.1 h1:Sm2oOuhqt0M5Y4kUi/Qh9w4cyyi3ZIWTBeGKImc2UVo= | ||||||
| github.com/playwright-community/playwright-go v0.5101.0/go.mod h1:kBNWs/w2aJ2ZUp1wEOOFLXgOqvppFngM5OS+qyhl+ZM= | github.com/playwright-community/playwright-go v0.5200.1/go.mod h1:UnnyQZaqUOO5ywAZu60+N4EiWReUqX1MQBBA3Oofvf8= | ||||||
| github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= | github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= | ||||||
| github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= | ||||||
| github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= | github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= | ||||||
| @@ -294,8 +294,8 @@ golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf | |||||||
| golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= | golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= | ||||||
| golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8= | golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8= | ||||||
| golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk= | golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk= | ||||||
| golang.org/x/crypto v0.37.0 h1:kJNSjF/Xp7kU0iB2Z+9viTPMW4EqqsrywMXLJOOsXSE= | golang.org/x/crypto v0.43.0 h1:dduJYIi3A3KOfdGOHX8AVZ/jGiyPa3IbBozJ5kNuE04= | ||||||
| golang.org/x/crypto v0.37.0/go.mod h1:vg+k43peMZ0pUMhYmVAWysMK35e6ioLh3wB8ZCAfbVc= | golang.org/x/crypto v0.43.0/go.mod h1:BFbav4mRNlXJL4wNeejLpWxB7wMbc79PdRGhWKncxR0= | ||||||
| golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= | golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= | ||||||
| golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= | golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= | ||||||
| golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= | golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= | ||||||
| @@ -335,8 +335,8 @@ golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= | |||||||
| golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= | golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= | ||||||
| golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM= | golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM= | ||||||
| golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4= | golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4= | ||||||
| golang.org/x/net v0.39.0 h1:ZCu7HMWDxpXpaiKdhzIfaltL9Lp31x/3fCP11bc6/fY= | golang.org/x/net v0.46.0 h1:giFlY12I07fugqwPuWJi68oOnpfqFnJIJzaIIm2JVV4= | ||||||
| golang.org/x/net v0.39.0/go.mod h1:X7NRbYVEA+ewNkCNyJ513WmMdQ3BineSwVtN2zD/d+E= | golang.org/x/net v0.46.0/go.mod h1:Q9BGdFy1y4nkUwiLvT5qtyhAnEHgnQ/zd8PfU6nc210= | ||||||
| golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= | golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= | ||||||
| golang.org/x/oauth2 v0.29.0 h1:WdYw2tdTK1S8olAzWHdgeqfy+Mtm9XNhv/xJsY65d98= | golang.org/x/oauth2 v0.29.0 h1:WdYw2tdTK1S8olAzWHdgeqfy+Mtm9XNhv/xJsY65d98= | ||||||
| golang.org/x/oauth2 v0.29.0/go.mod h1:onh5ek6nERTohokkhCD/y2cV4Do3fxFHFuAejCkRWT8= | golang.org/x/oauth2 v0.29.0/go.mod h1:onh5ek6nERTohokkhCD/y2cV4Do3fxFHFuAejCkRWT8= | ||||||
| @@ -351,8 +351,8 @@ golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= | |||||||
| golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= | golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= | ||||||
| golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= | golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= | ||||||
| golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= | golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= | ||||||
| golang.org/x/sync v0.13.0 h1:AauUjRAJ9OSnvULf/ARrrVywoJDy0YS2AwQ98I37610= | golang.org/x/sync v0.17.0 h1:l60nONMj9l5drqw6jlhIELNv9I0A4OFgRsG9k2oT9Ug= | ||||||
| golang.org/x/sync v0.13.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= | golang.org/x/sync v0.17.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI= | ||||||
| golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= | golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= | ||||||
| golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= | ||||||
| golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||||||
| @@ -372,8 +372,8 @@ golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= | |||||||
| golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= | golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= | ||||||
| golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= | golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= | ||||||
| golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= | golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= | ||||||
| golang.org/x/sys v0.32.0 h1:s77OFDvIQeibCmezSnk/q6iAfkdiQaJi4VzroCFrN20= | golang.org/x/sys v0.37.0 h1:fdNQudmxPjkdUTPnLn5mdQv7Zwvbvpaxqs831goi9kQ= | ||||||
| golang.org/x/sys v0.32.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= | golang.org/x/sys v0.37.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= | ||||||
| golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2/go.mod h1:TeRTkGYfJXctD9OcfyVLyj2J3IxLnKwHJR8f4D8a3YE= | golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2/go.mod h1:TeRTkGYfJXctD9OcfyVLyj2J3IxLnKwHJR8f4D8a3YE= | ||||||
| golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= | golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= | ||||||
| golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= | golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= | ||||||
| @@ -399,8 +399,8 @@ golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= | |||||||
| golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= | golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= | ||||||
| golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= | golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= | ||||||
| golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ= | golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ= | ||||||
| golang.org/x/text v0.24.0 h1:dd5Bzh4yt5KYA8f9CJHCP4FB4D51c2c6JvN37xJJkJ0= | golang.org/x/text v0.30.0 h1:yznKA/E9zq54KzlzBEAWn1NXSQ8DIp/NYMy88xJjl4k= | ||||||
| golang.org/x/text v0.24.0/go.mod h1:L8rBsPeo2pSS+xqN0d5u2ikmjtmoJbDBT1b7nHvFCdU= | golang.org/x/text v0.30.0/go.mod h1:yDdHFIX9t+tORqspjENWgzaCVXgk0yYnYuSZ8UzzBVM= | ||||||
| golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= | golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= | ||||||
| golang.org/x/time v0.11.0 h1:/bpjEDfN9tkoN/ryeYHnv5hcMlc8ncjMcM4XBk5NWV0= | golang.org/x/time v0.11.0 h1:/bpjEDfN9tkoN/ryeYHnv5hcMlc8ncjMcM4XBk5NWV0= | ||||||
| golang.org/x/time v0.11.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg= | golang.org/x/time v0.11.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg= | ||||||
|   | |||||||
| @@ -7,6 +7,7 @@ import ( | |||||||
| 	"sync/atomic" | 	"sync/atomic" | ||||||
|  |  | ||||||
| 	gollm "gitea.stevedudenhoeffer.com/steve/go-llm" | 	gollm "gitea.stevedudenhoeffer.com/steve/go-llm" | ||||||
|  | 	"github.com/davecgh/go-spew/spew" | ||||||
| ) | ) | ||||||
|  |  | ||||||
| // Agent is essentially the bones of a chat agent.  It has a model and a toolbox, and can be used to call the model | // Agent is essentially the bones of a chat agent.  It has a model and a toolbox, and can be used to call the model | ||||||
| @@ -184,6 +185,8 @@ func (a Agent) _callAndExecuteParallel(ctx context.Context, parallel bool, msgs | |||||||
|  |  | ||||||
| 	req, err := a.ToRequest(msgs...) | 	req, err := a.ToRequest(msgs...) | ||||||
|  |  | ||||||
|  | 	spew.Dump(req) | ||||||
|  |  | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return CallAndExecuteResults{}, fmt.Errorf("failed to create request: %w", err) | 		return CallAndExecuteResults{}, fmt.Errorf("failed to create request: %w", err) | ||||||
| 	} | 	} | ||||||
|   | |||||||
| @@ -1,397 +0,0 @@ | |||||||
| package console_new |  | ||||||
|  |  | ||||||
| import ( |  | ||||||
| 	"context" |  | ||||||
| 	"fmt" |  | ||||||
| 	"log/slog" |  | ||||||
| 	"os" |  | ||||||
| 	"path/filepath" |  | ||||||
| 	"strings" |  | ||||||
|  |  | ||||||
| 	"github.com/docker/docker/api/types/container" |  | ||||||
| 	"github.com/docker/docker/api/types/mount" |  | ||||||
| 	"github.com/docker/docker/client" |  | ||||||
|  |  | ||||||
| 	gollm "gitea.stevedudenhoeffer.com/steve/go-llm" |  | ||||||
|  |  | ||||||
| 	"gitea.stevedudenhoeffer.com/steve/answer/pkg/agents" |  | ||||||
| 	"gitea.stevedudenhoeffer.com/steve/answer/pkg/agents/shared" |  | ||||||
| ) |  | ||||||
|  |  | ||||||
| type Agent struct { |  | ||||||
| 	agents.Agent |  | ||||||
| 	// Model is the chat completion model to use |  | ||||||
| 	Model gollm.ChatCompletion |  | ||||||
|  |  | ||||||
| 	OnLoopComplete func(ctx context.Context, knowledge shared.Knowledge) error |  | ||||||
|  |  | ||||||
| 	OnCommandStart func(ctx context.Context, command string) error |  | ||||||
| 	OnCommandDone  func(ctx context.Context, command string, output string, err error) error |  | ||||||
|  |  | ||||||
| 	OnDone func(ctx context.Context, knowledge shared.Knowledge) error |  | ||||||
|  |  | ||||||
| 	ContextualInformation []string |  | ||||||
|  |  | ||||||
| 	MaxCommands int |  | ||||||
| } |  | ||||||
|  |  | ||||||
| type Response struct { |  | ||||||
| 	Knowledge shared.Knowledge |  | ||||||
| 	DataDir   string |  | ||||||
| 	OutputDir string |  | ||||||
| } |  | ||||||
|  |  | ||||||
| // Answer will give the model access to an ubuntu console with python and pip installed, and then ask the model to |  | ||||||
| // do what is necessary to answer the question. |  | ||||||
| func (a Agent) Answer(ctx context.Context, questions []string) (Response, error) { |  | ||||||
| 	var res Response |  | ||||||
|  |  | ||||||
| 	a.Agent = agents.NewAgent(a.Model, gollm.NewToolBox()).WithMaxCalls(200) |  | ||||||
|  |  | ||||||
| 	if a.MaxCommands <= 0 { |  | ||||||
| 		a.MaxCommands = 20 // Default to 20 commands as per requirements |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	res.Knowledge = shared.Knowledge{ |  | ||||||
| 		OriginalQuestions:  questions, |  | ||||||
| 		RemainingQuestions: questions, |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	// create temporary directories for data and output |  | ||||||
| 	dataDir, err := os.MkdirTemp("", "console-data-") |  | ||||||
| 	if err != nil { |  | ||||||
| 		return res, err |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	outputDir, err := os.MkdirTemp("", "console-output-") |  | ||||||
| 	if err != nil { |  | ||||||
| 		os.RemoveAll(dataDir) |  | ||||||
| 		return res, err |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	res.DataDir = dataDir |  | ||||||
| 	res.OutputDir = outputDir |  | ||||||
|  |  | ||||||
| 	cl, err := client.NewClientWithOpts(client.FromEnv) |  | ||||||
| 	if err != nil { |  | ||||||
| 		os.RemoveAll(dataDir) |  | ||||||
| 		os.RemoveAll(outputDir) |  | ||||||
| 		return res, err |  | ||||||
| 	} |  | ||||||
| 	defer cl.Close() |  | ||||||
|  |  | ||||||
| 	mounts := []mount.Mount{ |  | ||||||
| 		{ |  | ||||||
| 			Type:   mount.TypeBind, |  | ||||||
| 			Source: dataDir, |  | ||||||
| 			Target: "/data", |  | ||||||
| 		}, |  | ||||||
| 		{ |  | ||||||
| 			Type:   mount.TypeBind, |  | ||||||
| 			Source: outputDir, |  | ||||||
| 			Target: "/output", |  | ||||||
| 		}, |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	c, err := CreateContainer(ctx, cl, ContainerConfig{ |  | ||||||
| 		Config: &container.Config{ |  | ||||||
| 			Image:      "ubuntu:latest", |  | ||||||
| 			Cmd:        []string{"tail", "-f", "/dev/null"}, |  | ||||||
| 			Tty:        true, |  | ||||||
| 			WorkingDir: "/data", |  | ||||||
| 		}, |  | ||||||
| 		HostConfig: &container.HostConfig{ |  | ||||||
| 			AutoRemove: true, |  | ||||||
| 			Mounts:     mounts, |  | ||||||
| 		}, |  | ||||||
| 		Name: filepath.Base(dataDir), |  | ||||||
| 	}) |  | ||||||
|  |  | ||||||
| 	if err != nil { |  | ||||||
| 		os.RemoveAll(dataDir) |  | ||||||
| 		os.RemoveAll(outputDir) |  | ||||||
| 		return res, fmt.Errorf("failed to create container: %w", err) |  | ||||||
| 	} |  | ||||||
| 	defer func() { |  | ||||||
| 		_ = c.Close(ctx) |  | ||||||
| 	}() |  | ||||||
|  |  | ||||||
| 	slog.Info("starting container", "dataDir", dataDir, "outputDir", outputDir, "container", fmt.Sprintf("%+v", c)) |  | ||||||
| 	err = c.Start(ctx) |  | ||||||
| 	if err != nil { |  | ||||||
| 		os.RemoveAll(dataDir) |  | ||||||
| 		os.RemoveAll(outputDir) |  | ||||||
| 		return res, fmt.Errorf("failed to start container: %w", err) |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	// Run the model |  | ||||||
|  |  | ||||||
| 	var history executions |  | ||||||
| 	var keepGoing = true |  | ||||||
|  |  | ||||||
| 	// Initial setup - install basic tools |  | ||||||
| 	setupCmd, setupErr := c.Sudo(ctx, "apt-get update && apt-get install -y curl wget git python3 python3-pip") |  | ||||||
| 	if setupErr == nil { |  | ||||||
| 		history = append(history, execution{ |  | ||||||
| 			Command:      "sudo apt-get update && apt-get install -y curl wget git python3 python3-pip", |  | ||||||
| 			Output:       setupCmd, |  | ||||||
| 			WhatILearned: []string{"Basic tools installed: curl, wget, git, python3, pip"}, |  | ||||||
| 		}) |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	tools := map[string]gollm.Function{ |  | ||||||
| 		"exit": gollm.NewFunction( |  | ||||||
| 			"exit", |  | ||||||
| 			"exit the container", |  | ||||||
| 			func(ctx *gollm.Context, args struct { |  | ||||||
| 				RemainingQuestions []string `description:"any remaining questions that remain unanswered"` |  | ||||||
| 			}) (any, error) { |  | ||||||
| 				keepGoing = false |  | ||||||
| 				return "exiting", nil |  | ||||||
| 			}), |  | ||||||
|  |  | ||||||
| 		"write_data": gollm.NewFunction( |  | ||||||
| 			"write_data", |  | ||||||
| 			"write a file in the /data directory", |  | ||||||
| 			func(ctx *gollm.Context, args struct { |  | ||||||
| 				Filename string `description:"The name of the file to write"` |  | ||||||
| 				Content  string `description:"The content of the file to write"` |  | ||||||
| 			}) (any, error) { |  | ||||||
| 				target, err := SafeJoinPath(dataDir, args.Filename) |  | ||||||
| 				if err != nil { |  | ||||||
| 					return "", err |  | ||||||
| 				} |  | ||||||
|  |  | ||||||
| 				// Ensure directory exists |  | ||||||
| 				dir := filepath.Dir(target) |  | ||||||
| 				if err := os.MkdirAll(dir, 0755); err != nil { |  | ||||||
| 					return "", err |  | ||||||
| 				} |  | ||||||
|  |  | ||||||
| 				f, err := os.Create(target) |  | ||||||
| 				if err != nil { |  | ||||||
| 					return "", err |  | ||||||
| 				} |  | ||||||
| 				defer f.Close() |  | ||||||
|  |  | ||||||
| 				_, err = f.WriteString(args.Content) |  | ||||||
| 				if err != nil { |  | ||||||
| 					return "", err |  | ||||||
| 				} |  | ||||||
|  |  | ||||||
| 				return "wrote file to /data/" + args.Filename, nil |  | ||||||
| 			}), |  | ||||||
|  |  | ||||||
| 		"write_output": gollm.NewFunction( |  | ||||||
| 			"write_output", |  | ||||||
| 			"write a file in the /output directory (files here will be available after the agent completes)", |  | ||||||
| 			func(ctx *gollm.Context, args struct { |  | ||||||
| 				Filename string `description:"The name of the file to write"` |  | ||||||
| 				Content  string `description:"The content of the file to write"` |  | ||||||
| 			}) (any, error) { |  | ||||||
| 				target, err := SafeJoinPath(outputDir, args.Filename) |  | ||||||
| 				if err != nil { |  | ||||||
| 					return "", err |  | ||||||
| 				} |  | ||||||
|  |  | ||||||
| 				// Ensure directory exists |  | ||||||
| 				dir := filepath.Dir(target) |  | ||||||
| 				if err := os.MkdirAll(dir, 0755); err != nil { |  | ||||||
| 					return "", err |  | ||||||
| 				} |  | ||||||
|  |  | ||||||
| 				f, err := os.Create(target) |  | ||||||
| 				if err != nil { |  | ||||||
| 					return "", err |  | ||||||
| 				} |  | ||||||
| 				defer f.Close() |  | ||||||
|  |  | ||||||
| 				_, err = f.WriteString(args.Content) |  | ||||||
| 				if err != nil { |  | ||||||
| 					return "", err |  | ||||||
| 				} |  | ||||||
|  |  | ||||||
| 				return "wrote file to /output/" + args.Filename, nil |  | ||||||
| 			}), |  | ||||||
|  |  | ||||||
| 		"read_data": gollm.NewFunction( |  | ||||||
| 			"read_data", |  | ||||||
| 			"read a file from the /data directory", |  | ||||||
| 			func(ctx *gollm.Context, args struct { |  | ||||||
| 				Filename string `description:"The name of the file to read"` |  | ||||||
| 			}) (any, error) { |  | ||||||
| 				target, err := SafeJoinPath(dataDir, args.Filename) |  | ||||||
| 				if err != nil { |  | ||||||
| 					return "", err |  | ||||||
| 				} |  | ||||||
|  |  | ||||||
| 				b, err := os.ReadFile(target) |  | ||||||
| 				if err != nil { |  | ||||||
| 					return "", err |  | ||||||
| 				} |  | ||||||
|  |  | ||||||
| 				return string(b), nil |  | ||||||
| 			}), |  | ||||||
|  |  | ||||||
| 		"read_output": gollm.NewFunction( |  | ||||||
| 			"read_output", |  | ||||||
| 			"read a file from the /output directory", |  | ||||||
| 			func(ctx *gollm.Context, args struct { |  | ||||||
| 				Filename string `description:"The name of the file to read"` |  | ||||||
| 			}) (any, error) { |  | ||||||
| 				target, err := SafeJoinPath(outputDir, args.Filename) |  | ||||||
| 				if err != nil { |  | ||||||
| 					return "", err |  | ||||||
| 				} |  | ||||||
|  |  | ||||||
| 				b, err := os.ReadFile(target) |  | ||||||
| 				if err != nil { |  | ||||||
| 					return "", err |  | ||||||
| 				} |  | ||||||
|  |  | ||||||
| 				return string(b), nil |  | ||||||
| 			}), |  | ||||||
|  |  | ||||||
| 		"execute": gollm.NewFunction( |  | ||||||
| 			"execute", |  | ||||||
| 			"execute a command in the container", |  | ||||||
| 			func(ctx *gollm.Context, args struct { |  | ||||||
| 				Command string   `description:"The command to execute"` |  | ||||||
| 				Learn   []string `description:"What you learned from this command (optional)"` |  | ||||||
| 				ToLearn []string `description:"What you still need to learn (optional)"` |  | ||||||
| 			}) (any, error) { |  | ||||||
| 				if len(history) >= a.MaxCommands { |  | ||||||
| 					return "Command limit reached. You've used all " + fmt.Sprintf("%d", a.MaxCommands) + " allowed commands.", nil |  | ||||||
| 				} |  | ||||||
|  |  | ||||||
| 				if a.OnCommandStart != nil { |  | ||||||
| 					err := a.OnCommandStart(ctx, args.Command) |  | ||||||
| 					if err != nil { |  | ||||||
| 						return "", err |  | ||||||
| 					} |  | ||||||
| 				} |  | ||||||
|  |  | ||||||
| 				var res string |  | ||||||
| 				// if the command starts with sudo then we need to use the sudo function |  | ||||||
| 				if strings.HasPrefix(args.Command, "sudo ") { |  | ||||||
| 					res, err = c.Sudo(ctx, args.Command[5:]) |  | ||||||
| 				} else { |  | ||||||
| 					res, err = c.Execute(ctx, args.Command) |  | ||||||
| 				} |  | ||||||
|  |  | ||||||
| 				if a.OnCommandDone != nil { |  | ||||||
| 					err = a.OnCommandDone(ctx, args.Command, res, nil) |  | ||||||
| 					if err != nil { |  | ||||||
| 						return "", err |  | ||||||
| 					} |  | ||||||
| 				} |  | ||||||
|  |  | ||||||
| 				history = append(history, execution{ |  | ||||||
| 					Command:               args.Command, |  | ||||||
| 					Output:                res, |  | ||||||
| 					WhatILearned:          args.Learn, |  | ||||||
| 					WhatIStillNeedToLearn: args.ToLearn, |  | ||||||
| 				}) |  | ||||||
|  |  | ||||||
| 				return res, nil |  | ||||||
| 			}), |  | ||||||
|  |  | ||||||
| 		"summarize_knowledge": gollm.NewFunction( |  | ||||||
| 			"summarize_knowledge", |  | ||||||
| 			"summarize what you've learned so far", |  | ||||||
| 			func(ctx *gollm.Context, args struct{}) (any, error) { |  | ||||||
| 				var learned []string |  | ||||||
| 				var toLearn []string |  | ||||||
|  |  | ||||||
| 				for _, exec := range history { |  | ||||||
| 					learned = append(learned, exec.WhatILearned...) |  | ||||||
| 					toLearn = append(toLearn, exec.WhatIStillNeedToLearn...) |  | ||||||
| 				} |  | ||||||
|  |  | ||||||
| 				summary := "Knowledge Summary:\n" |  | ||||||
| 				if len(learned) > 0 { |  | ||||||
| 					summary += "What I've learned:\n- " + strings.Join(learned, "\n- ") + "\n\n" |  | ||||||
| 				} else { |  | ||||||
| 					summary += "I haven't learned anything specific yet.\n\n" |  | ||||||
| 				} |  | ||||||
|  |  | ||||||
| 				if len(toLearn) > 0 { |  | ||||||
| 					summary += "What I still need to learn:\n- " + strings.Join(toLearn, "\n- ") |  | ||||||
| 				} else { |  | ||||||
| 					summary += "I don't have any specific learning goals at the moment." |  | ||||||
| 				} |  | ||||||
|  |  | ||||||
| 				return summary, nil |  | ||||||
| 			}), |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	for i := 0; i < a.MaxCommands && len(history) < a.MaxCommands && keepGoing; i++ { |  | ||||||
|  |  | ||||||
| 		systemPrompt := `You are now in a shell in a container of the ubuntu:latest image to answer a question asked by the user.  |  | ||||||
| You have full control over a bash shell inside this Docker container. |  | ||||||
|  |  | ||||||
| Important directories: |  | ||||||
| - /data: A temporary directory with the lifespan of your processing. Use this for working files. |  | ||||||
| - /output: Files placed here will be returned to the caller after you're done. Use this for final results. |  | ||||||
|  |  | ||||||
| You can execute up to ` + fmt.Sprintf("%d", a.MaxCommands) + ` commands total. You're currently on command ` + fmt.Sprintf("%d", len(history)+1) + ` of ` + fmt.Sprintf("%d", a.MaxCommands) + `. |  | ||||||
|  |  | ||||||
| For each command, you should: |  | ||||||
| 1. Think about what you need to learn |  | ||||||
| 2. Execute the command using the "execute" function |  | ||||||
| 3. Analyze the output and record what you learned |  | ||||||
| 4. Plan your next command based on this knowledge |  | ||||||
|  |  | ||||||
| You can write files directly to /data or /output using the write_data and write_output functions. |  | ||||||
| When you are done, use "exit" to exit the container.` |  | ||||||
|  |  | ||||||
| 		var toolbox []gollm.Function |  | ||||||
|  |  | ||||||
| 		// Add all tools |  | ||||||
| 		toolbox = append(toolbox, |  | ||||||
| 			tools["exit"], |  | ||||||
| 			tools["write_data"], |  | ||||||
| 			tools["write_output"], |  | ||||||
| 			tools["read_data"], |  | ||||||
| 			tools["read_output"], |  | ||||||
| 			tools["summarize_knowledge"], |  | ||||||
| 		) |  | ||||||
|  |  | ||||||
| 		// Only add execute if we haven't reached the command limit |  | ||||||
| 		if len(history) < a.MaxCommands { |  | ||||||
| 			toolbox = append(toolbox, tools["execute"]) |  | ||||||
| 		} |  | ||||||
|  |  | ||||||
| 		kw := shared.KnowledgeWorker{ |  | ||||||
| 			Model:                 a.Model, |  | ||||||
| 			ToolBox:               gollm.NewToolBox(toolbox...), |  | ||||||
| 			ContextualInformation: a.ContextualInformation, |  | ||||||
| 			OnNewFunction: func(ctx context.Context, funcName string, args string) (any, error) { |  | ||||||
| 				slog.Info("new function called", "function name", funcName, "args", args) |  | ||||||
| 				return nil, nil |  | ||||||
| 			}, |  | ||||||
| 		} |  | ||||||
|  |  | ||||||
| 		slog.Info("answering question", "question", questions[0]) |  | ||||||
| 		r, err := kw.Answer(ctx, &res.Knowledge, systemPrompt, "", "", history.ToGeneralButLastMessageHistory(), func(res gollm.ToolCallResponse) { |  | ||||||
| 		}) |  | ||||||
|  |  | ||||||
| 		if err != nil { |  | ||||||
| 			return res, fmt.Errorf("error answering question: %w", err) |  | ||||||
| 		} |  | ||||||
|  |  | ||||||
| 		if len(r.Knowledge) > 0 { |  | ||||||
| 			slog.Info("answered question and learned", "knowledge", r.Knowledge) |  | ||||||
| 		} else { |  | ||||||
| 			slog.Info("answered question and learned nothing") |  | ||||||
| 		} |  | ||||||
|  |  | ||||||
| 		res.Knowledge, err = a.KnowledgeIntegrate(ctx, res.Knowledge, r) |  | ||||||
| 		if err != nil { |  | ||||||
| 			return res, fmt.Errorf("error integrating knowledge: %w", err) |  | ||||||
| 		} |  | ||||||
|  |  | ||||||
| 		slog.Info("knowledge integrated", "question", questions[0], "knowledge", res.Knowledge) |  | ||||||
| 	} |  | ||||||
| 	return res, nil |  | ||||||
| } |  | ||||||
| @@ -1,115 +0,0 @@ | |||||||
| package console_new |  | ||||||
|  |  | ||||||
| import ( |  | ||||||
| 	"context" |  | ||||||
| 	"fmt" |  | ||||||
| 	"io" |  | ||||||
| 	"log/slog" |  | ||||||
|  |  | ||||||
| 	"github.com/docker/docker/api/types/container" |  | ||||||
| 	"github.com/docker/docker/api/types/network" |  | ||||||
| 	"github.com/docker/docker/client" |  | ||||||
| 	v1 "github.com/opencontainers/image-spec/specs-go/v1" |  | ||||||
| ) |  | ||||||
|  |  | ||||||
| type Container struct { |  | ||||||
| 	client *client.Client |  | ||||||
| 	id     string |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func (c Container) Start(ctx context.Context) error { |  | ||||||
| 	return c.client.ContainerStart(ctx, c.id, container.StartOptions{}) |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func (c Container) Close(ctx context.Context) error { |  | ||||||
| 	timeout := 10 |  | ||||||
| 	if err := c.client.ContainerStop(ctx, c.id, container.StopOptions{ |  | ||||||
| 		Timeout: &timeout, |  | ||||||
| 	}); err != nil { |  | ||||||
| 		// If stop fails, force kill |  | ||||||
| 		if err := c.client.ContainerKill(ctx, c.id, "SIGKILL"); err != nil { |  | ||||||
| 			return err |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	// Remove container and volumes |  | ||||||
| 	removeOptions := container.RemoveOptions{ |  | ||||||
| 		RemoveVolumes: true, |  | ||||||
| 		Force:         true, |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	return c.client.ContainerRemove(ctx, c.id, removeOptions) |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func (c Container) execUserCmd(ctx context.Context, user string, cmd string) (string, error) { |  | ||||||
| 	slog.Info("executing command", "user", user, "cmd", cmd) |  | ||||||
| 	var cmdStr = []string{"/bin/bash", "-c"} |  | ||||||
|  |  | ||||||
| 	cmdStr = append(cmdStr, cmd) |  | ||||||
|  |  | ||||||
| 	slog.Info("executing command", "user", user, "cmd", fmt.Sprintf("%#v", cmdStr)) |  | ||||||
| 	exec, err := c.client.ContainerExecCreate(ctx, c.id, container.ExecOptions{ |  | ||||||
| 		Cmd:          cmdStr, |  | ||||||
| 		User:         user, |  | ||||||
| 		AttachStdout: true, |  | ||||||
| 		AttachStderr: true, |  | ||||||
| 	}) |  | ||||||
| 	if err != nil { |  | ||||||
| 		return "", err |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	resp, err := c.client.ContainerExecAttach(ctx, exec.ID, container.ExecAttachOptions{}) |  | ||||||
| 	if err != nil { |  | ||||||
| 		return "", err |  | ||||||
| 	} |  | ||||||
| 	defer resp.Close() |  | ||||||
|  |  | ||||||
| 	output, err := io.ReadAll(resp.Reader) |  | ||||||
| 	if err != nil { |  | ||||||
| 		return "", err |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	// Wait for command to finish and get exit code |  | ||||||
| 	inspectResp, err := c.client.ContainerExecInspect(ctx, exec.ID) |  | ||||||
| 	if err != nil { |  | ||||||
| 		return "", err |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	slog.Info("command finished", "output", string(output), "err", err, "resp", inspectResp) |  | ||||||
|  |  | ||||||
| 	if inspectResp.ExitCode != 0 { |  | ||||||
| 		return string(output), fmt.Errorf("command exited with code %d", inspectResp.ExitCode) |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	return string(output), nil |  | ||||||
| } |  | ||||||
| func (c Container) Execute(ctx context.Context, cmd string) (string, error) { |  | ||||||
| 	return c.execUserCmd(ctx, "", cmd) |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func (c Container) ExecuteAs(ctx context.Context, user string, cmd string) (string, error) { |  | ||||||
| 	return c.execUserCmd(ctx, user, cmd) |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func (c Container) Sudo(ctx context.Context, cmd string) (string, error) { |  | ||||||
| 	return c.execUserCmd(ctx, "root", cmd) |  | ||||||
| } |  | ||||||
|  |  | ||||||
| type ContainerConfig struct { |  | ||||||
| 	Config     *container.Config |  | ||||||
| 	HostConfig *container.HostConfig |  | ||||||
| 	NetConfig  *network.NetworkingConfig |  | ||||||
| 	Platform   *v1.Platform |  | ||||||
| 	Name       string |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func CreateContainer(ctx context.Context, cl *client.Client, cfg ContainerConfig) (*Container, error) { |  | ||||||
| 	resp, err := cl.ContainerCreate(ctx, cfg.Config, cfg.HostConfig, cfg.NetConfig, cfg.Platform, cfg.Name) |  | ||||||
|  |  | ||||||
| 	slog.Info("creating container", "resp", resp, "err", err) |  | ||||||
| 	if err != nil { |  | ||||||
| 		return nil, err |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	return &Container{client: cl, id: resp.ID}, nil |  | ||||||
| } |  | ||||||
| @@ -1,97 +0,0 @@ | |||||||
| package console_new |  | ||||||
|  |  | ||||||
| import ( |  | ||||||
| 	"strings" |  | ||||||
|  |  | ||||||
| 	gollm "gitea.stevedudenhoeffer.com/steve/go-llm" |  | ||||||
| ) |  | ||||||
|  |  | ||||||
| type execution struct { |  | ||||||
| 	Command               string |  | ||||||
| 	Output                string |  | ||||||
| 	WhatILearned          []string |  | ||||||
| 	WhatIStillNeedToLearn []string |  | ||||||
| } |  | ||||||
|  |  | ||||||
| const kMaxLenCommandSummary = 200 |  | ||||||
| const kMaxLenCommandOutputSummary = 200 |  | ||||||
|  |  | ||||||
| func (e execution) ToGeneralMessageHistory() gollm.Message { |  | ||||||
| 	if len(e.Command) > kMaxLenCommandSummary { |  | ||||||
| 		e.Command = e.Command[:kMaxLenCommandSummary] + "... (truncated)" |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	if len(e.Output) > kMaxLenCommandOutputSummary { |  | ||||||
| 		e.Output = e.Output[:kMaxLenCommandOutputSummary] + "... (truncated)" |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	text := "# " + e.Command + "\n" + e.Output |  | ||||||
|  |  | ||||||
| 	return gollm.Message{ |  | ||||||
| 		Role: gollm.RoleUser, |  | ||||||
| 		Text: text, |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func (e execution) ToDetailedMessageHistory() gollm.Message { |  | ||||||
| 	prompt := "$ " |  | ||||||
| 	if strings.HasPrefix(e.Command, "sudo ") { |  | ||||||
| 		prompt = "# " |  | ||||||
| 		e.Command = e.Command[5:] |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	text := prompt + strings.TrimSpace(e.Command) + "\n" + e.Output |  | ||||||
|  |  | ||||||
| 	if len(e.WhatILearned) > 0 { |  | ||||||
| 		text += "\n\nWhat I learned:\n" + strings.Join(e.WhatILearned, "\n") |  | ||||||
| 	} else { |  | ||||||
| 		text += "\n\nI didn't learn anything new." |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	if len(e.WhatIStillNeedToLearn) > 0 { |  | ||||||
| 		text += "\n\nWhat I still need to learn:\n" + strings.Join(e.WhatIStillNeedToLearn, "\n") |  | ||||||
| 	} else { |  | ||||||
| 		text += "\n\nI don't need to learn anything else." |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	return gollm.Message{ |  | ||||||
| 		Role: gollm.RoleUser, |  | ||||||
| 		Text: text, |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
|  |  | ||||||
| type executions []execution |  | ||||||
|  |  | ||||||
| func (e executions) ToGeneralMessageHistory() []gollm.Message { |  | ||||||
| 	var messages []gollm.Message |  | ||||||
|  |  | ||||||
| 	for _, v := range e { |  | ||||||
| 		messages = append(messages, v.ToGeneralMessageHistory()) |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	return messages |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func (e executions) ToGeneralButLastMessageHistory() []gollm.Message { |  | ||||||
| 	var messages []gollm.Message |  | ||||||
|  |  | ||||||
| 	for i, v := range e { |  | ||||||
| 		if i == len(e)-1 { |  | ||||||
| 			messages = append(messages, v.ToDetailedMessageHistory()) |  | ||||||
| 			break |  | ||||||
| 		} |  | ||||||
|  |  | ||||||
| 		messages = append(messages, v.ToGeneralMessageHistory()) |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	return messages |  | ||||||
| } |  | ||||||
| func (e executions) ToDetailedMessageHistory() []gollm.Message { |  | ||||||
| 	var messages []gollm.Message |  | ||||||
|  |  | ||||||
| 	for _, v := range e { |  | ||||||
| 		messages = append(messages, v.ToDetailedMessageHistory()) |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	return messages |  | ||||||
| } |  | ||||||
| @@ -1,23 +0,0 @@ | |||||||
| package console_new |  | ||||||
|  |  | ||||||
| import ( |  | ||||||
| 	"fmt" |  | ||||||
| 	"path/filepath" |  | ||||||
| 	"strings" |  | ||||||
| ) |  | ||||||
|  |  | ||||||
| func SafeJoinPath(tempDir, fileName string) (string, error) { |  | ||||||
| 	// Clean both paths |  | ||||||
| 	tempDir = filepath.Clean(tempDir) |  | ||||||
| 	fileName = filepath.Clean(fileName) |  | ||||||
|  |  | ||||||
| 	// Join paths and clean result |  | ||||||
| 	fullPath := filepath.Clean(filepath.Join(tempDir, fileName)) |  | ||||||
|  |  | ||||||
| 	// Verify the path is still within tempDir |  | ||||||
| 	if !strings.HasPrefix(fullPath, tempDir+string(filepath.Separator)) { |  | ||||||
| 		return "", fmt.Errorf("invalid path") |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	return fullPath, nil |  | ||||||
| } |  | ||||||
| @@ -51,7 +51,7 @@ func (a Agent) SearchAndUseTools(ctx context.Context, searchQuery string, questi | |||||||
|  |  | ||||||
| 	browser, ok := ctx.Value("browser").(extractor.Browser) | 	browser, ok := ctx.Value("browser").(extractor.Browser) | ||||||
| 	if !ok { | 	if !ok { | ||||||
| 		b, err := extractor.NewPlayWrightBrowser(extractor.PlayWrightBrowserOptions{}) | 		b, err := extractor.NewPlayWrightBrowser(ctx, extractor.PlayWrightBrowserOptions{}) | ||||||
| 		if err != nil { | 		if err != nil { | ||||||
| 			return knowledge, err | 			return knowledge, err | ||||||
| 		} | 		} | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user