@loopstack/filesystem-examples 0.1.1 → 0.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +37 -1
- package/dist/workflows/local-file-explorer/local-file-explorer-example.workflow.d.ts +1 -5
- package/dist/workflows/local-file-explorer/local-file-explorer-example.workflow.d.ts.map +1 -1
- package/dist/workflows/local-file-explorer/local-file-explorer-example.workflow.js +2 -2
- package/dist/workflows/local-file-explorer/local-file-explorer-example.workflow.js.map +1 -1
- package/dist/workflows/remote-client/remote-client-example.workflow.d.ts +1 -1
- package/dist/workflows/remote-client/remote-client-example.workflow.d.ts.map +1 -1
- package/dist/workflows/remote-client/remote-client-example.workflow.js +4 -4
- package/dist/workflows/remote-client/remote-client-example.workflow.js.map +1 -1
- package/dist/workflows/remote-file-explorer/remote-file-explorer-example.workflow.d.ts +1 -1
- package/dist/workflows/remote-file-explorer/remote-file-explorer-example.workflow.d.ts.map +1 -1
- package/dist/workflows/remote-file-explorer/remote-file-explorer-example.workflow.js +2 -2
- package/dist/workflows/remote-file-explorer/remote-file-explorer-example.workflow.js.map +1 -1
- package/package.json +2 -2
- package/src/workflows/local-file-explorer/local-file-explorer-example.workflow.ts +1 -5
- package/src/workflows/remote-client/remote-client-example.workflow.ts +3 -3
- package/src/workflows/remote-file-explorer/__tests__/remote-file-explorer-example.spec.ts +53 -0
- package/src/workflows/remote-file-explorer/remote-file-explorer-example.workflow.ts +1 -1
package/README.md
CHANGED
|
@@ -38,9 +38,45 @@ npm install @loopstack/filesystem-examples
|
|
|
38
38
|
import { FilesystemExamplesModule } from '@loopstack/filesystem-examples';
|
|
39
39
|
```
|
|
40
40
|
|
|
41
|
+
## Required app-module configuration
|
|
42
|
+
|
|
43
|
+
The Remote File Explorer and Remote Client examples connect to a remote agent. `FilesystemExamplesModule` declares the slot via `RemoteClientModule.forFeature({ slots: [{ type: 'sandbox' }] })`, but the consumer must register at least one matching environment in their root module via `RemoteClientModule.forRoot(...)`:
|
|
44
|
+
|
|
45
|
+
```typescript
|
|
46
|
+
import { Module } from '@nestjs/common';
|
|
47
|
+
import { FilesystemExamplesModule } from '@loopstack/filesystem-examples';
|
|
48
|
+
import { LoopstackModule } from '@loopstack/loopstack-module';
|
|
49
|
+
import { RemoteClientModule } from '@loopstack/remote-client';
|
|
50
|
+
|
|
51
|
+
@Module({
|
|
52
|
+
imports: [
|
|
53
|
+
LoopstackModule.forRoot(),
|
|
54
|
+
RemoteClientModule.forRoot({
|
|
55
|
+
environments: {
|
|
56
|
+
available: [
|
|
57
|
+
{
|
|
58
|
+
type: 'sandbox',
|
|
59
|
+
name: 'Local Remote Server',
|
|
60
|
+
connectionUrl: process.env.SANDBOX_URL ?? 'http://localhost:3080',
|
|
61
|
+
agentUrl: process.env.SANDBOX_AGENT_URL ?? 'http://localhost:3001',
|
|
62
|
+
local: true,
|
|
63
|
+
},
|
|
64
|
+
],
|
|
65
|
+
},
|
|
66
|
+
}),
|
|
67
|
+
FilesystemExamplesModule,
|
|
68
|
+
],
|
|
69
|
+
})
|
|
70
|
+
export class AppModule {}
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
The `type: 'sandbox'` must match the slot type declared by `FilesystemExamplesModule`. Workspaces created in Studio auto-select the environment from the matching type.
|
|
74
|
+
|
|
75
|
+
The Sandbox and Local File Explorer examples don't depend on the remote server and work without this config.
|
|
76
|
+
|
|
41
77
|
## Environment
|
|
42
78
|
|
|
43
|
-
The
|
|
79
|
+
The Sandbox example requires Docker. The Remote File Explorer and Remote Client examples require a running remote agent (the simplest option is `@loopstack/remote-server` on `localhost:3001`).
|
|
44
80
|
|
|
45
81
|
## Examples
|
|
46
82
|
|
|
@@ -1,12 +1,8 @@
|
|
|
1
1
|
import { BaseWorkflow } from '@loopstack/common';
|
|
2
2
|
import { FileSystemService } from '@loopstack/local-file-explorer-module';
|
|
3
|
-
interface LocalFileExplorerState {
|
|
4
|
-
fileCount?: number;
|
|
5
|
-
}
|
|
6
3
|
export declare class LocalFileExplorerExampleWorkflow extends BaseWorkflow {
|
|
7
4
|
private readonly fileSystem;
|
|
8
5
|
constructor(fileSystem: FileSystemService);
|
|
9
|
-
listTree(
|
|
6
|
+
listTree(): Promise<void>;
|
|
10
7
|
}
|
|
11
|
-
export {};
|
|
12
8
|
//# sourceMappingURL=local-file-explorer-example.workflow.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"local-file-explorer-example.workflow.d.ts","sourceRoot":"","sources":["../../../src/workflows/local-file-explorer/local-file-explorer-example.workflow.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAA0C,MAAM,mBAAmB,CAAC;AACzF,OAAO,EAAE,iBAAiB,EAAE,MAAM,uCAAuC,CAAC;AAE1E,
|
|
1
|
+
{"version":3,"file":"local-file-explorer-example.workflow.d.ts","sourceRoot":"","sources":["../../../src/workflows/local-file-explorer/local-file-explorer-example.workflow.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAA0C,MAAM,mBAAmB,CAAC;AACzF,OAAO,EAAE,iBAAiB,EAAE,MAAM,uCAAuC,CAAC;AAE1E,qBAKa,gCAAiC,SAAQ,YAAY;IACpD,OAAO,CAAC,QAAQ,CAAC,UAAU;gBAAV,UAAU,EAAE,iBAAiB;IAKpD,QAAQ;CAef"}
|
|
@@ -18,7 +18,7 @@ let LocalFileExplorerExampleWorkflow = class LocalFileExplorerExampleWorkflow ex
|
|
|
18
18
|
super();
|
|
19
19
|
this.fileSystem = fileSystem;
|
|
20
20
|
}
|
|
21
|
-
async listTree(
|
|
21
|
+
async listTree() {
|
|
22
22
|
const tree = await this.fileSystem.buildFileTree(process.cwd());
|
|
23
23
|
const lines = tree.slice(0, 50).map((node) => `- ${node.path} (${node.type})`);
|
|
24
24
|
await this.documentStore.save(common_1.MarkdownDocument, {
|
|
@@ -37,7 +37,7 @@ exports.LocalFileExplorerExampleWorkflow = LocalFileExplorerExampleWorkflow;
|
|
|
37
37
|
__decorate([
|
|
38
38
|
(0, common_1.Transition)({ to: 'end' }),
|
|
39
39
|
__metadata("design:type", Function),
|
|
40
|
-
__metadata("design:paramtypes", [
|
|
40
|
+
__metadata("design:paramtypes", []),
|
|
41
41
|
__metadata("design:returntype", Promise)
|
|
42
42
|
], LocalFileExplorerExampleWorkflow.prototype, "listTree", null);
|
|
43
43
|
exports.LocalFileExplorerExampleWorkflow = LocalFileExplorerExampleWorkflow = __decorate([
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"local-file-explorer-example.workflow.js","sourceRoot":"","sources":["../../../src/workflows/local-file-explorer/local-file-explorer-example.workflow.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,8CAAyF;AACzF,sFAA0E;
|
|
1
|
+
{"version":3,"file":"local-file-explorer-example.workflow.js","sourceRoot":"","sources":["../../../src/workflows/local-file-explorer/local-file-explorer-example.workflow.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,8CAAyF;AACzF,sFAA0E;AAOnE,IAAM,gCAAgC,GAAtC,MAAM,gCAAiC,SAAQ,qBAAY;IACnC;IAA7B,YAA6B,UAA6B;QACxD,KAAK,EAAE,CAAC;QADmB,eAAU,GAAV,UAAU,CAAmB;IAE1D,CAAC;IAGK,AAAN,KAAK,CAAC,QAAQ;QACZ,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,aAAa,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC;QAChE,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,KAAK,IAAI,CAAC,IAAI,KAAK,IAAI,CAAC,IAAI,GAAG,CAAC,CAAC;QAE/E,MAAM,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,yBAAgB,EAAE;YAC9C,QAAQ,EAAE;gBACR,uBAAuB;gBACvB,EAAE;gBACF,SAAS,IAAI,CAAC,MAAM,2BAA2B,OAAO,CAAC,GAAG,EAAE,KAAK;gBACjE,EAAE;gBACF,GAAG,KAAK;gBACR,IAAI,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC,CAAC,OAAO,IAAI,CAAC,MAAM,GAAG,EAAE,yBAAyB,CAAC,CAAC,CAAC,EAAE;aACzE,CAAC,IAAI,CAAC,IAAI,CAAC;SACb,CAAC,CAAC;IACL,CAAC;CACF,CAAA;AArBY,4EAAgC;AAMrC;IADL,IAAA,mBAAU,EAAC,EAAE,EAAE,EAAE,KAAK,EAAE,CAAC;;;;gEAezB;2CApBU,gCAAgC;IAL5C,IAAA,iBAAQ,EAAC;QACR,KAAK,EAAE,0CAA0C;QACjD,WAAW,EACT,iNAAiN;KACpN,CAAC;qCAEyC,8CAAiB;GAD/C,gCAAgC,CAqB5C"}
|
|
@@ -8,7 +8,7 @@ export declare class RemoteClientExampleWorkflow extends BaseWorkflow {
|
|
|
8
8
|
private readonly read;
|
|
9
9
|
private readonly write;
|
|
10
10
|
constructor(bash: BashTool, read: ReadTool, write: WriteTool);
|
|
11
|
-
writeFile(
|
|
11
|
+
writeFile(): Promise<void>;
|
|
12
12
|
runCommand(state: RemoteClientState): Promise<void>;
|
|
13
13
|
readBack(state: RemoteClientState): Promise<void>;
|
|
14
14
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"remote-client-example.workflow.d.ts","sourceRoot":"","sources":["../../../src/workflows/remote-client/remote-client-example.workflow.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAyC,MAAM,mBAAmB,CAAC;AACxF,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAC;AAEzE,UAAU,iBAAiB;IACzB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,qBAKa,2BAA4B,SAAQ,YAAY;IAEzD,OAAO,CAAC,QAAQ,CAAC,IAAI;IACrB,OAAO,CAAC,QAAQ,CAAC,IAAI;IACrB,OAAO,CAAC,QAAQ,CAAC,KAAK;gBAFL,IAAI,EAAE,QAAQ,EACd,IAAI,EAAE,QAAQ,EACd,KAAK,EAAE,SAAS;IAM7B,SAAS
|
|
1
|
+
{"version":3,"file":"remote-client-example.workflow.d.ts","sourceRoot":"","sources":["../../../src/workflows/remote-client/remote-client-example.workflow.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAyC,MAAM,mBAAmB,CAAC;AACxF,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAC;AAEzE,UAAU,iBAAiB;IACzB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,qBAKa,2BAA4B,SAAQ,YAAY;IAEzD,OAAO,CAAC,QAAQ,CAAC,IAAI;IACrB,OAAO,CAAC,QAAQ,CAAC,IAAI;IACrB,OAAO,CAAC,QAAQ,CAAC,KAAK;gBAFL,IAAI,EAAE,QAAQ,EACd,IAAI,EAAE,QAAQ,EACd,KAAK,EAAE,SAAS;IAM7B,SAAS;IAcT,UAAU,CAAC,KAAK,EAAE,iBAAiB;IAYnC,QAAQ,CAAC,KAAK,EAAE,iBAAiB;CAQxC"}
|
|
@@ -22,7 +22,7 @@ let RemoteClientExampleWorkflow = class RemoteClientExampleWorkflow extends comm
|
|
|
22
22
|
this.read = read;
|
|
23
23
|
this.write = write;
|
|
24
24
|
}
|
|
25
|
-
async writeFile(
|
|
25
|
+
async writeFile() {
|
|
26
26
|
const filePath = '/tmp/remote-client-example.txt';
|
|
27
27
|
await this.write.call({
|
|
28
28
|
file_path: filePath,
|
|
@@ -38,10 +38,10 @@ let RemoteClientExampleWorkflow = class RemoteClientExampleWorkflow extends comm
|
|
|
38
38
|
const result = await this.bash.call({
|
|
39
39
|
command: `wc -l ${state.filePath} && date`,
|
|
40
40
|
});
|
|
41
|
-
const
|
|
41
|
+
const output = result.data?.output ?? '';
|
|
42
42
|
await this.documentStore.save(common_1.MessageDocument, {
|
|
43
43
|
role: 'assistant',
|
|
44
|
-
text: `Command output:\n\`\`\`\n${
|
|
44
|
+
text: `Command output:\n\`\`\`\n${output}\n\`\`\``,
|
|
45
45
|
});
|
|
46
46
|
}
|
|
47
47
|
async readBack(state) {
|
|
@@ -57,7 +57,7 @@ exports.RemoteClientExampleWorkflow = RemoteClientExampleWorkflow;
|
|
|
57
57
|
__decorate([
|
|
58
58
|
(0, common_1.Transition)({ to: 'file_written' }),
|
|
59
59
|
__metadata("design:type", Function),
|
|
60
|
-
__metadata("design:paramtypes", [
|
|
60
|
+
__metadata("design:paramtypes", []),
|
|
61
61
|
__metadata("design:returntype", Promise)
|
|
62
62
|
], RemoteClientExampleWorkflow.prototype, "writeFile", null);
|
|
63
63
|
__decorate([
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"remote-client-example.workflow.js","sourceRoot":"","sources":["../../../src/workflows/remote-client/remote-client-example.workflow.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,8CAAwF;AACxF,4DAAyE;AAWlE,IAAM,2BAA2B,GAAjC,MAAM,2BAA4B,SAAQ,qBAAY;IAExC;IACA;IACA;IAHnB,YACmB,IAAc,EACd,IAAc,EACd,KAAgB;QAEjC,KAAK,EAAE,CAAC;QAJS,SAAI,GAAJ,IAAI,CAAU;QACd,SAAI,GAAJ,IAAI,CAAU;QACd,UAAK,GAAL,KAAK,CAAW;IAGnC,CAAC;IAGK,AAAN,KAAK,CAAC,SAAS
|
|
1
|
+
{"version":3,"file":"remote-client-example.workflow.js","sourceRoot":"","sources":["../../../src/workflows/remote-client/remote-client-example.workflow.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,8CAAwF;AACxF,4DAAyE;AAWlE,IAAM,2BAA2B,GAAjC,MAAM,2BAA4B,SAAQ,qBAAY;IAExC;IACA;IACA;IAHnB,YACmB,IAAc,EACd,IAAc,EACd,KAAgB;QAEjC,KAAK,EAAE,CAAC;QAJS,SAAI,GAAJ,IAAI,CAAU;QACd,SAAI,GAAJ,IAAI,CAAU;QACd,UAAK,GAAL,KAAK,CAAW;IAGnC,CAAC;IAGK,AAAN,KAAK,CAAC,SAAS;QACb,MAAM,QAAQ,GAAG,gCAAgC,CAAC;QAClD,MAAM,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC;YACpB,SAAS,EAAE,QAAQ;YACnB,OAAO,EAAE,2CAA2C;SACrD,CAAC,CAAC;QACH,MAAM,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,wBAAe,EAAE;YAC7C,IAAI,EAAE,WAAW;YACjB,IAAI,EAAE,cAAc,QAAQ,GAAG;SAChC,CAAC,CAAC;QACH,IAAI,CAAC,WAAW,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC;IACjC,CAAC;IAGK,AAAN,KAAK,CAAC,UAAU,CAAC,KAAwB;QACvC,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC;YAClC,OAAO,EAAE,SAAS,KAAK,CAAC,QAAQ,UAAU;SAC3C,CAAC,CAAC;QACH,MAAM,MAAM,GAAI,MAAM,CAAC,IAA4B,EAAE,MAAM,IAAI,EAAE,CAAC;QAClE,MAAM,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,wBAAe,EAAE;YAC7C,IAAI,EAAE,WAAW;YACjB,IAAI,EAAE,4BAA4B,MAAM,UAAU;SACnD,CAAC,CAAC;IACL,CAAC;IAGK,AAAN,KAAK,CAAC,QAAQ,CAAC,KAAwB;QACrC,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,SAAS,EAAE,KAAK,CAAC,QAAS,EAAE,CAAC,CAAC;QACpE,MAAM,OAAO,GAAI,MAAM,CAAC,IAA6B,EAAE,OAAO,IAAI,EAAE,CAAC;QACrE,MAAM,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,wBAAe,EAAE;YAC7C,IAAI,EAAE,WAAW;YACjB,IAAI,EAAE,gCAAgC,OAAO,UAAU;SACxD,CAAC,CAAC;IACL,CAAC;CACF,CAAA;AA5CY,kEAA2B;AAUhC;IADL,IAAA,mBAAU,EAAC,EAAE,EAAE,EAAE,cAAc,EAAE,CAAC;;;;4DAYlC;AAGK;IADL,IAAA,mBAAU,EAAC,EAAE,IAAI,EAAE,cAAc,EAAE,EAAE,EAAE,kBAAkB,EAAE,CAAC;;;;6DAU5D;AAGK;IADL,IAAA,mBAAU,EAAC,EAAE,IAAI,EAAE,kBAAkB,EAAE,EAAE,EAAE,KAAK,EAAE,CAAC;;;;2DAQnD;sCA3CU,2BAA2B;IALvC,IAAA,iBAAQ,EAAC;QACR,KAAK,EAAE,oCAAoC;QAC3C,WAAW,EACT,6NAA6N;KAChO,CAAC;qCAGyB,wBAAQ;QACR,wBAAQ;QACP,yBAAS;GAJxB,2BAA2B,CA4CvC"}
|
|
@@ -7,7 +7,7 @@ export declare class RemoteFileExplorerExampleWorkflow extends BaseWorkflow {
|
|
|
7
7
|
private readonly glob;
|
|
8
8
|
private readonly read;
|
|
9
9
|
constructor(glob: GlobTool, read: ReadTool);
|
|
10
|
-
listFiles(
|
|
10
|
+
listFiles(): Promise<void>;
|
|
11
11
|
readFirst(state: RemoteFileExplorerState): Promise<void>;
|
|
12
12
|
}
|
|
13
13
|
export {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"remote-file-explorer-example.workflow.d.ts","sourceRoot":"","sources":["../../../src/workflows/remote-file-explorer/remote-file-explorer-example.workflow.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAyC,MAAM,mBAAmB,CAAC;AACxF,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AAE9D,UAAU,uBAAuB;IAC/B,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,qBAKa,iCAAkC,SAAQ,YAAY;IAE/D,OAAO,CAAC,QAAQ,CAAC,IAAI;IACrB,OAAO,CAAC,QAAQ,CAAC,IAAI;gBADJ,IAAI,EAAE,QAAQ,EACd,IAAI,EAAE,QAAQ;IAM3B,SAAS
|
|
1
|
+
{"version":3,"file":"remote-file-explorer-example.workflow.d.ts","sourceRoot":"","sources":["../../../src/workflows/remote-file-explorer/remote-file-explorer-example.workflow.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAyC,MAAM,mBAAmB,CAAC;AACxF,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AAE9D,UAAU,uBAAuB;IAC/B,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,qBAKa,iCAAkC,SAAQ,YAAY;IAE/D,OAAO,CAAC,QAAQ,CAAC,IAAI;IACrB,OAAO,CAAC,QAAQ,CAAC,IAAI;gBADJ,IAAI,EAAE,QAAQ,EACd,IAAI,EAAE,QAAQ;IAM3B,SAAS;IAeT,SAAS,CAAC,KAAK,EAAE,uBAAuB;CAiB/C"}
|
|
@@ -20,7 +20,7 @@ let RemoteFileExplorerExampleWorkflow = class RemoteFileExplorerExampleWorkflow
|
|
|
20
20
|
this.glob = glob;
|
|
21
21
|
this.read = read;
|
|
22
22
|
}
|
|
23
|
-
async listFiles(
|
|
23
|
+
async listFiles() {
|
|
24
24
|
const result = await this.glob.call({ pattern: '**/*.md' });
|
|
25
25
|
const files = result.data?.files ?? [];
|
|
26
26
|
await this.documentStore.save(common_1.MessageDocument, {
|
|
@@ -52,7 +52,7 @@ exports.RemoteFileExplorerExampleWorkflow = RemoteFileExplorerExampleWorkflow;
|
|
|
52
52
|
__decorate([
|
|
53
53
|
(0, common_1.Transition)({ to: 'listed' }),
|
|
54
54
|
__metadata("design:type", Function),
|
|
55
|
-
__metadata("design:paramtypes", [
|
|
55
|
+
__metadata("design:paramtypes", []),
|
|
56
56
|
__metadata("design:returntype", Promise)
|
|
57
57
|
], RemoteFileExplorerExampleWorkflow.prototype, "listFiles", null);
|
|
58
58
|
__decorate([
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"remote-file-explorer-example.workflow.js","sourceRoot":"","sources":["../../../src/workflows/remote-file-explorer/remote-file-explorer-example.workflow.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,8CAAwF;AACxF,4DAA8D;AAWvD,IAAM,iCAAiC,GAAvC,MAAM,iCAAkC,SAAQ,qBAAY;IAE9C;IACA;IAFnB,YACmB,IAAc,EACd,IAAc;QAE/B,KAAK,EAAE,CAAC;QAHS,SAAI,GAAJ,IAAI,CAAU;QACd,SAAI,GAAJ,IAAI,CAAU;IAGjC,CAAC;IAGK,AAAN,KAAK,CAAC,SAAS
|
|
1
|
+
{"version":3,"file":"remote-file-explorer-example.workflow.js","sourceRoot":"","sources":["../../../src/workflows/remote-file-explorer/remote-file-explorer-example.workflow.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,8CAAwF;AACxF,4DAA8D;AAWvD,IAAM,iCAAiC,GAAvC,MAAM,iCAAkC,SAAQ,qBAAY;IAE9C;IACA;IAFnB,YACmB,IAAc,EACd,IAAc;QAE/B,KAAK,EAAE,CAAC;QAHS,SAAI,GAAJ,IAAI,CAAU;QACd,SAAI,GAAJ,IAAI,CAAU;IAGjC,CAAC;IAGK,AAAN,KAAK,CAAC,SAAS;QACb,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,SAAS,EAAE,CAAC,CAAC;QAC5D,MAAM,KAAK,GAAI,MAAM,CAAC,IAA6B,EAAE,KAAK,IAAI,EAAE,CAAC;QAEjE,MAAM,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,wBAAe,EAAE;YAC7C,IAAI,EAAE,WAAW;YACjB,IAAI,EAAE,SAAS,KAAK,CAAC,MAAM,qBAAqB,KAAK;iBAClD,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC;iBACZ,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC;iBACpB,IAAI,CAAC,IAAI,CAAC,EAAE;SAChB,CAAC,CAAC;QACH,IAAI,CAAC,WAAW,CAAC,EAAE,UAAU,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;IAC7C,CAAC;IAGK,AAAN,KAAK,CAAC,SAAS,CAAC,KAA8B;QAC5C,IAAI,CAAC,KAAK,CAAC,UAAU,EAAE,CAAC;YACtB,MAAM,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,wBAAe,EAAE;gBAC7C,IAAI,EAAE,WAAW;gBACjB,IAAI,EAAE,4BAA4B;aACnC,CAAC,CAAC;YACH,OAAO;QACT,CAAC;QAED,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,SAAS,EAAE,KAAK,CAAC,UAAU,EAAE,CAAC,CAAC;QACrE,MAAM,OAAO,GAAI,MAAM,CAAC,IAA6B,EAAE,OAAO,IAAI,EAAE,CAAC;QAErE,MAAM,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,wBAAe,EAAE;YAC7C,IAAI,EAAE,WAAW;YACjB,IAAI,EAAE,KAAK,KAAK,CAAC,UAAU,OAAO,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE;SAC1D,CAAC,CAAC;IACL,CAAC;CACF,CAAA;AAzCY,8EAAiC;AAStC;IADL,IAAA,mBAAU,EAAC,EAAE,EAAE,EAAE,QAAQ,EAAE,CAAC;;;;kEAa5B;AAGK;IADL,IAAA,mBAAU,EAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,EAAE,KAAK,EAAE,CAAC;;;;kEAiBzC;4CAxCU,iCAAiC;IAL7C,IAAA,iBAAQ,EAAC;QACR,KAAK,EAAE,2CAA2C;QAClD,WAAW,EACT,4HAA4H;KAC/H,CAAC;qCAGyB,wBAAQ;QACR,wBAAQ;GAHtB,iCAAiC,CAyC7C"}
|
package/package.json
CHANGED
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
"remote",
|
|
11
11
|
"workflow"
|
|
12
12
|
],
|
|
13
|
-
"version": "0.1.
|
|
13
|
+
"version": "0.1.3",
|
|
14
14
|
"license": "MIT",
|
|
15
15
|
"author": {
|
|
16
16
|
"name": "Jakob Klippel",
|
|
@@ -37,7 +37,7 @@
|
|
|
37
37
|
"@loopstack/remote-file-explorer-module": "*",
|
|
38
38
|
"@loopstack/sandbox-filesystem": "*",
|
|
39
39
|
"@loopstack/sandbox-tool": "*",
|
|
40
|
-
"@nestjs/common": "^
|
|
40
|
+
"@nestjs/common": "^12.0.1",
|
|
41
41
|
"zod": "^4.3.6"
|
|
42
42
|
},
|
|
43
43
|
"files": [
|
|
@@ -1,10 +1,6 @@
|
|
|
1
1
|
import { BaseWorkflow, MarkdownDocument, Transition, Workflow } from '@loopstack/common';
|
|
2
2
|
import { FileSystemService } from '@loopstack/local-file-explorer-module';
|
|
3
3
|
|
|
4
|
-
interface LocalFileExplorerState {
|
|
5
|
-
fileCount?: number;
|
|
6
|
-
}
|
|
7
|
-
|
|
8
4
|
@Workflow({
|
|
9
5
|
title: 'Filesystem - Local File Explorer Example',
|
|
10
6
|
description:
|
|
@@ -16,7 +12,7 @@ export class LocalFileExplorerExampleWorkflow extends BaseWorkflow {
|
|
|
16
12
|
}
|
|
17
13
|
|
|
18
14
|
@Transition({ to: 'end' })
|
|
19
|
-
async listTree(
|
|
15
|
+
async listTree() {
|
|
20
16
|
const tree = await this.fileSystem.buildFileTree(process.cwd());
|
|
21
17
|
const lines = tree.slice(0, 50).map((node) => `- ${node.path} (${node.type})`);
|
|
22
18
|
|
|
@@ -20,7 +20,7 @@ export class RemoteClientExampleWorkflow extends BaseWorkflow {
|
|
|
20
20
|
}
|
|
21
21
|
|
|
22
22
|
@Transition({ to: 'file_written' })
|
|
23
|
-
async writeFile(
|
|
23
|
+
async writeFile() {
|
|
24
24
|
const filePath = '/tmp/remote-client-example.txt';
|
|
25
25
|
await this.write.call({
|
|
26
26
|
file_path: filePath,
|
|
@@ -38,10 +38,10 @@ export class RemoteClientExampleWorkflow extends BaseWorkflow {
|
|
|
38
38
|
const result = await this.bash.call({
|
|
39
39
|
command: `wc -l ${state.filePath} && date`,
|
|
40
40
|
});
|
|
41
|
-
const
|
|
41
|
+
const output = (result.data as { output?: string })?.output ?? '';
|
|
42
42
|
await this.documentStore.save(MessageDocument, {
|
|
43
43
|
role: 'assistant',
|
|
44
|
-
text: `Command output:\n\`\`\`\n${
|
|
44
|
+
text: `Command output:\n\`\`\`\n${output}\n\`\`\``,
|
|
45
45
|
});
|
|
46
46
|
}
|
|
47
47
|
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest';
|
|
2
|
+
import { RemoteClientModule } from '@loopstack/remote-client';
|
|
3
|
+
import { type TestRun, coverage, replay, runWorkflow } from '@loopstack/testing';
|
|
4
|
+
import { FilesystemExamplesModule } from '../../../filesystem-examples.module';
|
|
5
|
+
import { RemoteFileExplorerExampleWorkflow } from '../remote-file-explorer-example.workflow';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Infra-free testing of an infra-heavy workflow: the glob/read tools talk to a remote
|
|
9
|
+
* workspace, but replaying their envelopes makes the whole flow hermetic — no server needed.
|
|
10
|
+
* Two scripted results exercise both branches (matches found vs. none), showing how the tool
|
|
11
|
+
* boundary drives branch coverage.
|
|
12
|
+
*/
|
|
13
|
+
describe('RemoteFileExplorerExampleWorkflow', () => {
|
|
14
|
+
const runs: TestRun[] = [];
|
|
15
|
+
const imports = [RemoteClientModule.forRoot(), FilesystemExamplesModule];
|
|
16
|
+
|
|
17
|
+
it('reads the first match when markdown files exist', async () => {
|
|
18
|
+
const run = await runWorkflow(RemoteFileExplorerExampleWorkflow, undefined, {
|
|
19
|
+
imports,
|
|
20
|
+
replay: replay({
|
|
21
|
+
version: 3,
|
|
22
|
+
recordings: [
|
|
23
|
+
{ tool: 'glob', envelope: { data: { files: ['docs/intro.md', 'docs/guide.md'] } } },
|
|
24
|
+
{ tool: 'read', envelope: { data: { content: '# Intro\n\nWelcome.', path: 'docs/intro.md' } } },
|
|
25
|
+
],
|
|
26
|
+
}),
|
|
27
|
+
});
|
|
28
|
+
runs.push(run);
|
|
29
|
+
|
|
30
|
+
expect(run.error).toBeUndefined();
|
|
31
|
+
expect(run.status).toBe('completed');
|
|
32
|
+
const texts = run.documents.map((d) => (d.content as { text?: string }).text ?? '');
|
|
33
|
+
expect(texts.some((t) => t.includes('Found 2 markdown files'))).toBe(true);
|
|
34
|
+
expect(texts.some((t) => t.includes('# docs/intro.md'))).toBe(true);
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
it('takes the empty branch when no markdown files are found', async () => {
|
|
38
|
+
const run = await runWorkflow(RemoteFileExplorerExampleWorkflow, undefined, {
|
|
39
|
+
imports,
|
|
40
|
+
replay: replay({ version: 3, recordings: [{ tool: 'glob', envelope: { data: { files: [] } } }] }),
|
|
41
|
+
});
|
|
42
|
+
runs.push(run);
|
|
43
|
+
|
|
44
|
+
expect(run.status).toBe('completed');
|
|
45
|
+
const texts = run.documents.map((d) => (d.content as { text?: string }).text ?? '');
|
|
46
|
+
expect(texts).toContain('No markdown files to read.');
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
it('covers every transition (coverage gate)', () => {
|
|
50
|
+
const cov = coverage(runs, RemoteFileExplorerExampleWorkflow);
|
|
51
|
+
expect(cov.missingTransitions).toEqual([]);
|
|
52
|
+
});
|
|
53
|
+
});
|
|
@@ -19,7 +19,7 @@ export class RemoteFileExplorerExampleWorkflow extends BaseWorkflow {
|
|
|
19
19
|
}
|
|
20
20
|
|
|
21
21
|
@Transition({ to: 'listed' })
|
|
22
|
-
async listFiles(
|
|
22
|
+
async listFiles() {
|
|
23
23
|
const result = await this.glob.call({ pattern: '**/*.md' });
|
|
24
24
|
const files = (result.data as { files?: string[] })?.files ?? [];
|
|
25
25
|
|